Skip to content

Commit 740c32c

Browse files
committed
Fix expected type of SqlContext.Credential.
1 parent 73d2c4c commit 740c32c

7 files changed

Lines changed: 93 additions & 31 deletions

File tree

Coverlet.runsettings

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,18 @@
55
-->
66
<!--
77
Documentation:
8+
https://learn.microsoft.com/en-us/visualstudio/test/configure-unit-tests-by-using-a-dot-runsettings-file
89
https://github.com/tonerdo/coverlet/blob/master/Documentation/VSTestIntegration.md
910
-->
1011
<RunSettings>
12+
<RunConfiguration>
13+
<!-- To test with SQL authentication -->
14+
<!--
15+
<EnvironmentVariables>
16+
<MSSQL_SA_PASSWORD>...</MSSQL_SA_PASSWORD>
17+
</EnvironmentVariables>
18+
-->
19+
</RunConfiguration>
1120
<DataCollectionRunSettings>
1221
<DataCollectors>
1322
<DataCollector friendlyName="XPlat Code Coverage">

PSql.Deploy.Tests/Data/SqlTargetDatabaseTests.cs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public SqlTargetDatabaseTests(bool wrapped)
2828
[Test]
2929
public void Construct_WithValues()
3030
{
31-
var credential = new NetworkCredential("sa", "secret");
31+
var credential = MakePSCredential("sa", "secret");
3232

3333
var target = new SqlTargetDatabase(
3434
"Server = localhost; Database = Test",
@@ -77,7 +77,7 @@ public void Construct_FromSameType()
7777
{
7878
var source = new SqlTargetDatabase(
7979
"Server = localhost; Database = Test",
80-
new NetworkCredential("sa", "secret"),
80+
MakePSCredential("sa", "secret"),
8181
"My Server",
8282
"My Database"
8383
);
@@ -106,7 +106,7 @@ public void Construct_FromSqlContext()
106106
var source = new TestSqlContext
107107
{
108108
ConnectionString = "Server = localhost; Database = Test",
109-
Credential = new("sa", "secret"),
109+
Credential = MakePSCredential("sa", "secret"),
110110
};
111111

112112
var actual = MakeSqlTargetDatabase(source);
@@ -140,7 +140,7 @@ public void Construct_FromAzureSqlContext()
140140
{
141141
ServerResourceName = "example",
142142
ConnectionString = "Server = example.database.windows.net; Database = Test",
143-
Credential = new("sa", "secret"),
143+
Credential = MakePSCredential("sa", "secret"),
144144
};
145145

146146
var actual = MakeSqlTargetDatabase(source);
@@ -157,7 +157,7 @@ public void Construct_FromAzureSqlContext_ServerResourceNameIsNull()
157157
var source = new TestAzureSqlContext
158158
{
159159
ConnectionString = "Server = example.database.windows.net; Database = Test",
160-
Credential = new("sa", "secret"),
160+
Credential = MakePSCredential("sa", "secret"),
161161
};
162162

163163
var actual = MakeSqlTargetDatabase(source);
@@ -223,7 +223,7 @@ public void Construct_FromSqlContext_GetConnectionStringReturnsNull()
223223
new TestSqlContext
224224
{
225225
ConnectionString = null,
226-
Credential = new("sa", "secret"),
226+
Credential = MakePSCredential("sa", "secret"),
227227
}
228228
);
229229
}
@@ -285,4 +285,14 @@ private void ShouldThrowDueToNonConformingApi(object obj)
285285

286286
private SqlTargetDatabase MakeSqlTargetDatabase(object obj)
287287
=> new SqlTargetDatabase(_wrap(obj));
288+
289+
private PSCredential MakePSCredential(string userName, string password)
290+
{
291+
var networkCredential = new NetworkCredential(userName, password);
292+
293+
return new(
294+
networkCredential.UserName,
295+
networkCredential.SecurePassword
296+
);
297+
}
288298
}

PSql.Deploy.Tests/Integration/IntegrationTestsSetup.cs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright Subatomix Research Inc.
22
// SPDX-License-Identifier: MIT
33

4+
using System.Management.Automation.Runspaces;
45
using System.Net;
56
using System.Net.Sockets;
67
using Microsoft.Data.SqlClient;
@@ -30,7 +31,10 @@ public static NetworkCredential? Credential
3031
[OneTimeSetUp]
3132
public static async Task SetUp()
3233
{
33-
var connectionString = "Server = .";
34+
var connectionString
35+
= "Server" + " = ."
36+
+ "; Encrypt" + " = false"
37+
+ "; Application Name" + " = PSql.Deploy.Tests";
3438

3539
if (Environment.GetEnvironmentVariable(PasswordName) is { Length: > 0 } password)
3640
{
@@ -56,10 +60,6 @@ public static async Task SetUp()
5660
_credential = _container.Credential;
5761
}
5862

59-
connectionString = connectionString
60-
+ "; Encrypt" + " = false"
61-
+ "; Application Name" + " = PSql.Deploy.Tests";
62-
6363
_setupConnectionString = connectionString + "; Database = master";
6464

6565
await CreateTestDatabasesAsync();
@@ -80,6 +80,21 @@ public static async Task TearDown()
8080
}
8181
}
8282

83+
public static void WithIntegrationTestDefaults(InitialSessionState state)
84+
{
85+
if (!(Credential is { } c))
86+
return;
87+
88+
state.Variables.Add(new SessionStateVariableEntry(
89+
"PSDefaultParameterValues",
90+
new DefaultParameterDictionary
91+
{
92+
["New-SqlContext:Credential"] = new PSCredential(c.UserName, c.SecurePassword),
93+
},
94+
null
95+
));
96+
}
97+
8398
private static bool IsLocalSqlServerListening()
8499
{
85100
return OperatingSystem.IsWindows() && File.Exists(ServerPipe)

PSql.Deploy.Tests/Integration/InvokeSqlMigrationsCommandTests.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public void Invoke()
1919
File.Delete("..PSqlDeployTestB.1_Core.log");
2020
File.Delete("..PSqlDeployTestB.2_Post.log");
2121

22-
var (output, exception) = ScriptExecutor.Execute(
22+
var (output, exception) = Execute(
2323
"""
2424
$TargetA = New-SqlContext -DatabaseName PSqlDeployTestA
2525
$TargetB = New-SqlContext -DatabaseName PSqlDeployTestB
@@ -90,7 +90,7 @@ public void Invoke()
9090
[Test]
9191
public void Invoke_DefaultPath()
9292
{
93-
var (_, exception) = ScriptExecutor.Execute(
93+
var (_, exception) = Execute(
9494
"""
9595
Join-Path TestDbs A | Set-Location
9696
$Target = New-SqlContext -DatabaseName PSqlDeployTestA
@@ -100,4 +100,12 @@ public void Invoke_DefaultPath()
100100

101101
exception.ShouldBeNull();
102102
}
103+
104+
private static (IReadOnlyList<PSObject?>, Exception?) Execute(string script)
105+
{
106+
return ScriptExecutor.Execute(
107+
IntegrationTestsSetup.WithIntegrationTestDefaults,
108+
script
109+
);
110+
}
103111
}

PSql.Deploy.Tests/Integration/InvokeSqlSeedCommandIntegrationTests.cs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public void Invoke()
1515
File.Delete("..PSqlDeployTestA.Typical.log");
1616
File.Delete("..PSqlDeployTestB.Typical.log");
1717

18-
var (_, exception) = ScriptExecutor.Execute(
18+
var (_, exception) = Execute(
1919
"""
2020
$TargetA = New-SqlContext -DatabaseName PSqlDeployTestA
2121
$TargetB = New-SqlContext -DatabaseName PSqlDeployTestB
@@ -40,7 +40,7 @@ public void Invoke()
4040
[Test]
4141
public void Invoke_DefaultPath()
4242
{
43-
var (_, exception) = ScriptExecutor.Execute(
43+
var (_, exception) = Execute(
4444
"""
4545
Join-Path TestDbs A | Set-Location
4646
$Target = New-SqlContext -DatabaseName PSqlDeployTestA
@@ -57,7 +57,7 @@ public void Invoke_DefineMissing()
5757
{
5858
// NOTE: The test seed 'Typical' requires a SqlCmd variable 'foo'.
5959

60-
var (_, exception) = ScriptExecutor.Execute(
60+
var (_, exception) = Execute(
6161
"""
6262
Join-Path TestDbs A | Set-Location
6363
$Target = New-SqlContext -DatabaseName PSqlDeployTestA
@@ -76,7 +76,7 @@ public void Invoke_DefineEmpty()
7676
{
7777
// NOTE: The test seed 'Typical' requires a SqlCmd variable 'foo'.
7878

79-
var (_, exception) = ScriptExecutor.Execute(
79+
var (_, exception) = Execute(
8080
"""
8181
Join-Path TestDbs A | Set-Location
8282
$Target = New-SqlContext -DatabaseName PSqlDeployTestA
@@ -100,7 +100,11 @@ public void Invoke_DefineWithNullKey()
100100
);
101101

102102
var (_, exception) = ScriptExecutor.Execute(
103-
state => state.Variables.Add(variable),
103+
state =>
104+
{
105+
IntegrationTestsSetup.WithIntegrationTestDefaults(state);
106+
state.Variables.Add(variable);
107+
},
104108
"""
105109
Join-Path TestDbs A | Set-Location
106110
$Target = New-SqlContext -DatabaseName PSqlDeployTestA
@@ -118,7 +122,7 @@ public void Invoke_DefineWithNullKey()
118122
[Test]
119123
public void Invoke_DefineWithNullValue()
120124
{
121-
var (_, exception) = ScriptExecutor.Execute(
125+
var (_, exception) = Execute(
122126
"""
123127
Join-Path TestDbs A | Set-Location
124128
$Target = New-SqlContext -DatabaseName PSqlDeployTestA
@@ -129,4 +133,12 @@ public void Invoke_DefineWithNullValue()
129133

130134
exception.ShouldBeNull();
131135
}
136+
137+
private static (IReadOnlyList<PSObject?>, Exception?) Execute(string script)
138+
{
139+
return ScriptExecutor.Execute(
140+
IntegrationTestsSetup.WithIntegrationTestDefaults,
141+
script
142+
);
143+
}
132144
}

PSql.Deploy.Tests/Support/FakePSql.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class TestSqlContext
1515
{
1616
public string? ConnectionString { get; set; }
1717

18-
public NetworkCredential? Credential { get; set; }
18+
public PSCredential? Credential { get; set; }
1919

2020
public string GetConnectionString(
2121
string? db, // actual name in PSql: databaseName \ To test that

PSql.Deploy/Data/SqlTargetDatabase.cs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,19 @@ public SqlTargetDatabase(object obj)
8080
/// <paramref name="connectionString"/> is <see langword="null"/>.
8181
/// </exception>
8282
public SqlTargetDatabase(
83-
string connectionString,
84-
NetworkCredential? credential = null,
85-
string? serverDisplayName = null,
86-
string? databaseDisplayName = null)
83+
string connectionString,
84+
PSCredential? credential = null,
85+
string? serverDisplayName = null,
86+
string? databaseDisplayName = null)
8787
{
8888
// Null checked by inner Target constructor
8989

90-
_target = new(connectionString, credential, serverDisplayName, databaseDisplayName);
90+
_target = new(
91+
connectionString,
92+
credential?.GetNetworkCredential(),
93+
serverDisplayName,
94+
databaseDisplayName
95+
);
9196

9297
Credential = credential;
9398
}
@@ -107,7 +112,7 @@ public SqlTargetDatabase(
107112
/// if a credential is required and not present in the
108113
/// <see cref="ConnectionString"/>.
109114
/// </summary>
110-
public NetworkCredential? Credential { get; }
115+
public PSCredential? Credential { get; }
111116

112117
/// <summary>
113118
/// Gets a display name for the database server. This name might be a
@@ -139,13 +144,16 @@ private static bool IsSqlContext(object obj, out Type type)
139144
&& name.EndsWith ("SqlContext", StringComparison.Ordinal);
140145
}
141146

142-
private static (E.Target, NetworkCredential?) InterpretSqlContext(ObjectTypePair source)
147+
private static (E.Target, PSCredential?) InterpretSqlContext(ObjectTypePair source)
143148
{
144149
return TryGetConnectionString (source, out var connectionString) // string
145150
&& TryGetCredential (source, out var credential) // NetworkCredential?
146151
&& TryGetServerResourceName(source, out var serverDisplayName) // string?
147-
? (new(connectionString, credential, serverDisplayName), credential)
148-
: throw new ArgumentException(
152+
? (
153+
new(connectionString, credential?.GetNetworkCredential(), serverDisplayName),
154+
credential
155+
)
156+
: throw new ArgumentException(
149157
"The object does not conform to the expected API surface of PSql.SqlContext."
150158
);
151159
}
@@ -189,7 +197,7 @@ const string
189197
return true;
190198
}
191199

192-
private static bool TryGetCredential(ObjectTypePair source, out NetworkCredential? value)
200+
private static bool TryGetCredential(ObjectTypePair source, out PSCredential? value)
193201
{
194202
const string PropertyName = "Credential";
195203

@@ -204,7 +212,7 @@ private static bool TryGetCredential(ObjectTypePair source, out NetworkCredentia
204212
if (property.GetValue(source.Object) is not { } objectValue)
205213
return true; // property value is null; normal when credential is not required
206214

207-
if (objectValue is not NetworkCredential typedValue)
215+
if (objectValue is not PSCredential typedValue)
208216
return false; // property value is of wrong type
209217

210218
value = typedValue;

0 commit comments

Comments
 (0)