Skip to content

Commit d30f7e0

Browse files
committed
added integration tests for Int64 timestamps for LinqToDB
1 parent 8224fd3 commit d30f7e0

File tree

8 files changed

+249
-37
lines changed

8 files changed

+249
-37
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using Synnotech.Migrations.Core;
2+
using Xunit.Abstractions;
3+
4+
namespace Synnotech.Migrations.Linq2Db.Tests
5+
{
6+
public static class Extensions
7+
{
8+
public static void LogSummary<T>(this ITestOutputHelper output, MigrationSummary<T> summary)
9+
{
10+
if (summary.TryGetAppliedMigrations(out var appliedMigrations))
11+
{
12+
foreach (var appliedMigration in appliedMigrations)
13+
{
14+
output.WriteLine(appliedMigration!.ToString());
15+
}
16+
}
17+
18+
output.WriteLine(string.Empty);
19+
20+
if (summary.TryGetError(out var error))
21+
output.WriteLine(error.Exception.ToString());
22+
}
23+
}
24+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace Synnotech.Migrations.Linq2Db.Tests.Int64TimestampVersions
2+
{
3+
public sealed class Contact
4+
{
5+
public int Id { get; init; }
6+
7+
public string Name { get; set; } = string.Empty;
8+
}
9+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using LinqToDB.Data;
3+
using LinqToDB.DataProvider.SqlServer;
4+
using LinqToDB.Mapping;
5+
using Microsoft.Data.SqlClient;
6+
using Microsoft.Extensions.DependencyInjection;
7+
using Synnotech.Migrations.Linq2Db.Int64TimestampVersions;
8+
9+
namespace Synnotech.Migrations.Linq2Db.Tests.Int64TimestampVersions
10+
{
11+
public static class DatabaseContext
12+
{
13+
public static IServiceCollection AddDatabaseContext(this IServiceCollection services,
14+
string connectionString,
15+
SqlServerVersion sqlServerVersion = SqlServerVersion.v2017)
16+
{
17+
var sqlServerDataProvider = (SqlServerDataProvider) SqlServerTools.GetDataProvider(sqlServerVersion, SqlServerProvider.MicrosoftDataSqlClient);
18+
CreateMappings(sqlServerDataProvider.MappingSchema);
19+
return services.AddSingleton(sqlServerDataProvider)
20+
.AddTransient(c => new DataConnection(c.GetRequiredService<SqlServerDataProvider>(),
21+
new SqlConnection(connectionString),
22+
true))
23+
.AddSingleton<Func<DataConnection>>(c => c.GetRequiredService<DataConnection>);
24+
}
25+
26+
public static void CreateMappings(MappingSchema schema)
27+
{
28+
var builder = schema.GetFluentMappingBuilder();
29+
30+
builder.MapMigrationInfo()
31+
.Entity<Contact>()
32+
.HasTableName("Contacts")
33+
.Property(contact => contact.Id).IsIdentity().IsPrimaryKey()
34+
.Property(contact => contact.Name).IsNullable(false);
35+
}
36+
}
37+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
IF OBJECT_ID('dbo.MigrationInfos', 'U') IS NULL
2+
BEGIN
3+
4+
CREATE TABLE [dbo].[MigrationInfos] (
5+
[Id] INT IDENTITY(1, 1) PRIMARY KEY,
6+
[Version] BIGINT CONSTRAINT UQ_MigrationInfos UNIQUE NOT NULL,
7+
[Name] NVARCHAR(100) NOT NULL,
8+
[AppliedAt] DATETIME2 NOT NULL
9+
);
10+
11+
END;
12+
13+
CREATE TABLE [dbo].[Contacts] (
14+
[Id] INT IDENTITY(1, 1) PRIMARY KEY,
15+
[Name] NVARCHAR(100) NOT NULL
16+
);
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
using FluentAssertions;
6+
using LinqToDB;
7+
using LinqToDB.Data;
8+
using Microsoft.Extensions.DependencyInjection;
9+
using Synnotech.Migrations.Core;
10+
using Synnotech.Migrations.Core.Int64TimestampVersions;
11+
using Synnotech.Migrations.Linq2Db.Int64TimestampVersions;
12+
using Synnotech.MsSqlServer;
13+
using Xunit;
14+
using Xunit.Abstractions;
15+
16+
namespace Synnotech.Migrations.Linq2Db.Tests.Int64TimestampVersions
17+
{
18+
public sealed class MigrationEngineTests
19+
{
20+
public MigrationEngineTests(ITestOutputHelper output) => Output = output;
21+
private ITestOutputHelper Output { get; }
22+
23+
[SkippableFact]
24+
public async Task ApplyAllMigrations()
25+
{
26+
await using var container = await InitializeOrSkipTestAsync();
27+
var now = DateTime.UtcNow;
28+
var migrationEngine = container.GetRequiredService<MigrationEngine>();
29+
30+
var summary = await migrationEngine.MigrateAsync(now);
31+
Output.LogSummary(summary);
32+
33+
await using var dataConnection = container.GetRequiredService<DataConnection>();
34+
var migrationInfos = await dataConnection.GetTable<MigrationInfo>()
35+
.ToListAsync();
36+
var expectedMigrationInfos = new MigrationInfo[]
37+
{
38+
new () { Id = 1, Name = nameof(InitialTableStructure), Version = 20211008111155, AppliedAt = now },
39+
new () { Id = 2, Name = nameof(SomeContacts), Version = 20211008111259, AppliedAt = now }
40+
};
41+
migrationInfos.Should().BeEquivalentTo(expectedMigrationInfos, options => options.WithStrictOrdering());
42+
}
43+
44+
[SkippableFact]
45+
public async Task ApplyNewestMigration()
46+
{
47+
await using var container = await InitializeOrSkipTestAsync();
48+
await using (var dataConnection = container.GetRequiredService<DataConnection>())
49+
{
50+
await dataConnection.CreateTableAsync<MigrationInfo>();
51+
await dataConnection.CreateTableAsync<Contact>();
52+
await dataConnection.InsertAsync(new MigrationInfo { Name = nameof(InitialTableStructure), Version = 20211008111155, AppliedAt = DateTime.UtcNow });
53+
}
54+
55+
var now = DateTime.UtcNow;
56+
var migrationEngine = container.GetRequiredService<MigrationEngine>();
57+
var summary = await migrationEngine.MigrateAsync(now);
58+
Output.LogSummary(summary);
59+
60+
var expectedMigrations = new List<MigrationInfo>(1)
61+
{
62+
new () { Id = 2, Name = nameof(SomeContacts), Version = 20211008111259, AppliedAt = now }
63+
};
64+
summary.TryGetAppliedMigrations(out var appliedMigrations).Should().BeTrue();
65+
appliedMigrations.Should().BeEquivalentTo(expectedMigrations);
66+
summary.EnsureSuccess();
67+
}
68+
69+
[SkippableFact]
70+
public async Task NoMigrationsAvailable()
71+
{
72+
await using var container = await InitializeOrSkipTestAsync();
73+
var now = DateTime.UtcNow;
74+
await using (var dataConnection = container.GetRequiredService<DataConnection>())
75+
{
76+
await dataConnection.CreateTableAsync<MigrationInfo>();
77+
await dataConnection.InsertAsync(new MigrationInfo { Name = nameof(InitialTableStructure), Version = 20211008111155, AppliedAt = now });
78+
await dataConnection.InsertAsync(new MigrationInfo { Name = nameof(SomeContacts), Version = 20211008111259, AppliedAt = now });
79+
}
80+
81+
var migrationEngine = container.GetRequiredService<MigrationEngine>();
82+
var summary = await migrationEngine.MigrateAsync();
83+
Output.LogSummary(summary);
84+
85+
summary.TryGetAppliedMigrations(out var appliedMigrations).Should().BeFalse();
86+
appliedMigrations.Should().BeNull();
87+
summary.EnsureSuccess();
88+
}
89+
90+
[Fact]
91+
public async Task RunPreviousMigration()
92+
{
93+
await using var container = await InitializeOrSkipTestAsync();
94+
var now = DateTime.UtcNow;
95+
await using (var dataConnection = container.GetRequiredService<DataConnection>())
96+
{
97+
await dataConnection.CreateTableAsync<MigrationInfo>();
98+
await dataConnection.InsertAsync(new MigrationInfo { Name = nameof(SomeContacts), Version = 20211008111259, AppliedAt = now.AddDays(-2) });
99+
}
100+
101+
var migrationEngine = container.GetRequiredService<MigrationEngine>();
102+
var summary = await migrationEngine.MigrateAsync(now, approach: MigrationApproach.AllNonAppliedMigrations);
103+
Output.LogSummary(summary);
104+
105+
summary.TryGetAppliedMigrations(out var appliedMigrations).Should().BeTrue();
106+
var expectedMigrationInfos = new List<MigrationInfo>
107+
{
108+
new () { Id = 1, Name = nameof(InitialTableStructure), Version = 20211008111155, AppliedAt = now }
109+
};
110+
appliedMigrations.Should().BeEquivalentTo(expectedMigrationInfos);
111+
}
112+
113+
private static async Task<ServiceProvider> InitializeOrSkipTestAsync()
114+
{
115+
var (connectionString, sqlServerVersion) = TestSettings.GetConnectionSettingsOrSkip();
116+
await Database.DropAndCreateDatabaseAsync(connectionString);
117+
return new ServiceCollection().AddDatabaseContext(connectionString, sqlServerVersion)
118+
.AddSynnotechMigrations()
119+
.BuildServiceProvider();
120+
}
121+
122+
[MigrationVersion("2021-10-08T11:11:55Z")]
123+
public sealed class InitialTableStructure : EmbeddedScriptMigration
124+
{
125+
public InitialTableStructure() : base("InitialScript.sql") { }
126+
}
127+
128+
[MigrationVersion("2021-10-08T11:12:59Z")]
129+
public sealed class SomeContacts : Migration
130+
{
131+
public override async Task ApplyAsync(DataConnection dataConnection, CancellationToken cancellationToken = default)
132+
{
133+
await dataConnection.InsertAsync(new Contact { Name = "John Doe" }, token: cancellationToken);
134+
await dataConnection.InsertAsync(new Contact { Name = "Jane Foe" }, token: cancellationToken);
135+
}
136+
}
137+
}
138+
}
Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
<Project Sdk="Microsoft.NET.Sdk">
2-
<ItemGroup>
3-
<ProjectReference Include="..\..\src\Synnotech.Migrations.Linq2Db\Synnotech.Migrations.Linq2Db.csproj" />
4-
<PackageReference Include="Synnotech.MsSqlServer" Version="1.1.0" />
5-
</ItemGroup>
6-
<ItemGroup>
7-
<None Update="testsettings.Development.json" Condition="Exists('testsettings.Development.json')">
8-
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
9-
</None>
10-
<None Update="testsettings.json">
11-
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
12-
</None>
13-
<Compile Include="..\AssemblyInfos.cs">
14-
<Link>AssemblyInfos.cs</Link>
15-
</Compile>
16-
<EmbeddedResource Include="TextVersions\0.1.0 Initial Table Structure.sql" />
17-
</ItemGroup>
2+
<ItemGroup>
3+
<ProjectReference Include="..\..\src\Synnotech.Migrations.Linq2Db\Synnotech.Migrations.Linq2Db.csproj" />
4+
<PackageReference Include="Synnotech.MsSqlServer" Version="1.1.0" />
5+
</ItemGroup>
6+
<ItemGroup>
7+
<None Update="testsettings.Development.json" Condition="Exists('testsettings.Development.json')">
8+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
9+
</None>
10+
<None Update="testsettings.json">
11+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
12+
</None>
13+
<Compile Include="..\AssemblyInfos.cs">
14+
<Link>AssemblyInfos.cs</Link>
15+
</Compile>
16+
<EmbeddedResource Include="Int64TimestampVersions\InitialScript.sql" />
17+
<EmbeddedResource Include="TextVersions\0.1.0 Initial Table Structure.sql" />
18+
<Analyzer Include="..\..\src\Synnotech.Migrations.Core.Analyzers\bin\$(Configuration)\netstandard2.0\Synnotech.Migrations.Core.Analyzers.dll"
19+
Condition="Exists('..\..\src\Synnotech.Migrations.Core.Analyzers\bin\$(Configuration)\netstandard2.0\Synnotech.Migrations.Core.Analyzers.dll')" />
20+
</ItemGroup>
1821
</Project>

Code/tests/Synnotech.Migrations.Linq2Db.Tests/TextVersions/Linq2DbMigrationEngineTests.cs

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public async Task ApplyAllMigrations()
3131

3232
var now = DateTime.UtcNow;
3333
var summary = await migrationEngine.MigrateAsync(now);
34-
LogSummary(summary);
34+
Output.LogSummary(summary);
3535

3636
await using var dataConnection = container.GetRequiredService<DataConnection>();
3737
var migrationInfos = await dataConnection.GetTable<MigrationInfo>()
@@ -58,7 +58,7 @@ public async Task ApplyNewestMigration()
5858
var now = DateTime.UtcNow;
5959
var migrationEngine = container.GetRequiredService<MigrationEngine>();
6060
var summary = await migrationEngine.MigrateAsync(now);
61-
LogSummary(summary);
61+
Output.LogSummary(summary);
6262

6363
var expectedMigration = new List<MigrationInfo>
6464
{
@@ -83,7 +83,7 @@ public async Task NoMigrationsAvailable()
8383

8484
var migrationEngine = container.GetRequiredService<MigrationEngine>();
8585
var summary = await migrationEngine.MigrateAsync(now);
86-
LogSummary(summary);
86+
Output.LogSummary(summary);
8787

8888
summary.TryGetAppliedMigrations(out var appliedMigrations).Should().BeFalse();
8989
appliedMigrations.Should().BeNull();
@@ -103,7 +103,7 @@ public async Task RunPreviousMigrations()
103103

104104
var migrationEngine = container.GetRequiredService<MigrationEngine>();
105105
var summary = await migrationEngine.MigrateAsync(now, approach: MigrationApproach.AllNonAppliedMigrations);
106-
LogSummary(summary);
106+
Output.LogSummary(summary);
107107

108108
summary.TryGetAppliedMigrations(out var appliedMigrations).Should().BeTrue();
109109
var expectedMigrationInfos = new List<MigrationInfo>
@@ -121,22 +121,6 @@ private static async Task<ServiceProvider> InitializeOrSkipTestAsync()
121121
.AddSynnotechMigrations()
122122
.BuildServiceProvider();
123123
}
124-
125-
private void LogSummary(MigrationSummary<MigrationInfo> summary)
126-
{
127-
if (summary.TryGetAppliedMigrations(out var appliedMigrations))
128-
{
129-
foreach (var appliedMigration in appliedMigrations)
130-
{
131-
Output.WriteLine(appliedMigration.ToString());
132-
}
133-
}
134-
135-
Output.WriteLine(string.Empty);
136-
137-
if (summary.TryGetError(out var error))
138-
Output.WriteLine(error.Exception.ToString());
139-
}
140124
}
141125

142126
[MigrationVersion("0.1.0")]

Code/tests/Synnotech.Migrations.RavenDB.Tests/Synnotech.Migrations.RavenDB.Tests.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
1212
</None>
1313
<Compile Include="..\AssemblyInfos.cs" Link="AssemblyInfos.cs" />
14-
<Analyzer Include="..\..\src\Synnotech.Migrations.Core.Analyzers\bin\$(Configuration)\netstandard2.0\Synnotech.Migrations.Core.Analyzers.dll" Condition="Exists('..\..\src\Synnotech.Migrations.Core.Analyzers\bin\$(Configuration)\netstandard2.0\Synnotech.Migrations.Core.Analyzers.dll')" />
14+
<Analyzer Include="..\..\src\Synnotech.Migrations.Core.Analyzers\bin\$(Configuration)\netstandard2.0\Synnotech.Migrations.Core.Analyzers.dll"
15+
Condition="Exists('..\..\src\Synnotech.Migrations.Core.Analyzers\bin\$(Configuration)\netstandard2.0\Synnotech.Migrations.Core.Analyzers.dll')" />
1516
</ItemGroup>
1617
</Project>

0 commit comments

Comments
 (0)