diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index afb8b3f..1e2cedf 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -45,6 +45,9 @@ jobs: - name: Dotnet Cake Build shell: pwsh run: dotnet cake --target=Build + - name: Dotnet Cake Test + shell: pwsh + run: dotnet cake --target=Test - name: Dotnet Cake Pack shell: pwsh run: dotnet cake --target=Pack diff --git a/AtlasProvider.sln b/AtlasProvider.sln index af5a47f..d3f269a 100644 --- a/AtlasProvider.sln +++ b/AtlasProvider.sln @@ -9,6 +9,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Atlas.Provider.Loader", "sr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Atlas.Provider.Core", "src\Atlas.Provider.Core\Atlas.Provider.Core.csproj", "{FAEB024F-B0AA-4B7C-A820-68E497657D0D}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{A0F935A4-52B6-4790-AA08-A86E0CB562E9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Atlas.Provider.Test", "test\Atlas.Provider.Test\Atlas.Provider.Test.csproj", "{D34350D9-C254-4187-A908-00EA03DDE2B5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -26,9 +30,14 @@ Global {FAEB024F-B0AA-4B7C-A820-68E497657D0D}.Debug|Any CPU.Build.0 = Debug|Any CPU {FAEB024F-B0AA-4B7C-A820-68E497657D0D}.Release|Any CPU.ActiveCfg = Release|Any CPU {FAEB024F-B0AA-4B7C-A820-68E497657D0D}.Release|Any CPU.Build.0 = Release|Any CPU + {D34350D9-C254-4187-A908-00EA03DDE2B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D34350D9-C254-4187-A908-00EA03DDE2B5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D34350D9-C254-4187-A908-00EA03DDE2B5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D34350D9-C254-4187-A908-00EA03DDE2B5}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {003BD0CC-7AF6-408C-A40D-3FE8F6C73537} = {C41D6C7A-456B-4A0B-ACE1-9931DA092288} {FAEB024F-B0AA-4B7C-A820-68E497657D0D} = {C41D6C7A-456B-4A0B-ACE1-9931DA092288} + {D34350D9-C254-4187-A908-00EA03DDE2B5} = {A0F935A4-52B6-4790-AA08-A86E0CB562E9} EndGlobalSection EndGlobal diff --git a/build.cake b/build.cake index ca8bad6..b60f2ef 100644 --- a/build.cake +++ b/build.cake @@ -34,6 +34,18 @@ Task("Build") }); }); +Task("Test") + .Description("Runs unit tests") + .DoesForEach( + GetFiles("./test/**/*.csproj"), + project => + { + DotNetTest(project.ToString(),new DotNetTestSettings() + { + Configuration = configuration, + }); + }).DeferOnError(); + Task("Pack") .Description("Creates NuGet packages and outputs them to the artifacts directory.") .Does(() => diff --git a/src/Atlas.Provider.Core/Program.cs b/src/Atlas.Provider.Core/Program.cs index d16105a..a08cc41 100644 --- a/src/Atlas.Provider.Core/Program.cs +++ b/src/Atlas.Provider.Core/Program.cs @@ -47,12 +47,12 @@ static void Main( continue; } var sql = executor.ScriptDbContext(name); - if (ctxInfo["ProviderName"]!.ToString()!.EndsWith("SqlServer")) - { - sql = "-- atlas:delimiter GO \n" + sql; - } if (!string.IsNullOrEmpty(sql)) { + if (ctxInfo["ProviderName"]!.ToString()!.EndsWith("SqlServer")) + { + Console.WriteLine("-- atlas:delimiter GO"); + } Console.WriteLine(sql); } } diff --git a/src/Atlas.Provider.Demo/Program.cs b/src/Atlas.Provider.Demo/Program.cs index bcc835a..ea763ff 100644 --- a/src/Atlas.Provider.Demo/Program.cs +++ b/src/Atlas.Provider.Demo/Program.cs @@ -19,12 +19,12 @@ public BloggingContext CreateDbContext(string[] args) { var provider = args.FirstOrDefault(); - return new BloggingContext(provider); + return new BloggingContext(provider!); } } public class BloggingContext : DbContext { - public DbSet Blogs { get; set; } + public DbSet? Blogs { get; set; } private readonly string _provider; public BloggingContext(string provider = "SqlServer") @@ -79,14 +79,14 @@ public class Blog public int BlogId { get; set; } [Column(TypeName = "varchar(200)")] - public string Url { get; set; } + public string? Url { get; set; } [Column(TypeName = "decimal(5, 2)")] public decimal Rating { get; set; } public string Title { get; set; } = string.Empty; public string Content { get; set; } = string.Empty; public string Author { get; set; } = string.Empty; - public List Posts { get; set; } + public List? Posts { get; set; } } public class Post @@ -95,7 +95,7 @@ public class Post public int PostId { get; set; } public string Title { get; set; } = string.Empty; public string Content { get; set; } = string.Empty; - public string BlogUrl { get; set; } - public Blog Blog { get; set; } + public string? BlogUrl { get; set; } + public Blog? Blog { get; set; } } } \ No newline at end of file diff --git a/test/Atlas.Provider.Test/Atlas.Provider.Test.csproj b/test/Atlas.Provider.Test/Atlas.Provider.Test.csproj new file mode 100644 index 0000000..fc8d1dd --- /dev/null +++ b/test/Atlas.Provider.Test/Atlas.Provider.Test.csproj @@ -0,0 +1,36 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + + + + PreserveNewest + + + + \ No newline at end of file diff --git a/test/Atlas.Provider.Test/GenerateSchemaTest.cs b/test/Atlas.Provider.Test/GenerateSchemaTest.cs new file mode 100644 index 0000000..88bd8a8 --- /dev/null +++ b/test/Atlas.Provider.Test/GenerateSchemaTest.cs @@ -0,0 +1,46 @@ +using Xunit; +using System.Diagnostics; +using System.Reflection; + +public class GenerateSchemaTest +{ + [Theory] + [InlineData("SqlServer", "data/sqlserver_default")] + [InlineData("Postgres", "data/postgres_default")] + [InlineData("MySql", "data/mysql_default")] + [InlineData("Sqlite", "data/sqlite_default")] + public void Can_generate_script(string providerName, string expectedFile) + { + var dllFileName = Assembly.Load(new AssemblyName("Atlas.Provider.Loader")).Location; + + ProcessStartInfo startInfo = new ProcessStartInfo + { + WorkingDirectory = Path.GetFullPath("../../../../../src/Atlas.Provider.Demo"), + FileName = "dotnet", + Arguments = $"exec {dllFileName} -- {providerName}", + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + }; + + using Process? process = Process.Start(startInfo); + Assert.NotNull(process); + string output = process.StandardOutput.ReadToEnd(); + string error = process.StandardError.ReadToEnd(); + process.WaitForExit(); + Assert.Equal(FileReader.Read(expectedFile), output); + Assert.Equal("", error); + } +} +internal static class FileReader +{ + public static string Read(string filePath) + { + return File.ReadAllText( + Path.Combine( + Directory.GetCurrentDirectory(), + filePath + )); + } +} \ No newline at end of file diff --git a/test/Atlas.Provider.Test/data/mysql_default b/test/Atlas.Provider.Test/data/mysql_default new file mode 100644 index 0000000..2816e20 --- /dev/null +++ b/test/Atlas.Provider.Test/data/mysql_default @@ -0,0 +1,29 @@ +ALTER DATABASE CHARACTER SET utf8mb4; + + +CREATE TABLE `Blogs` ( + `BlogId` int NOT NULL AUTO_INCREMENT, + `Url` varchar(200) CHARACTER SET utf8mb4 NOT NULL, + `Rating` decimal(5,2) NOT NULL, + `Title` longtext CHARACTER SET utf8mb4 NOT NULL, + `Content` longtext CHARACTER SET utf8mb4 NOT NULL, + `Author` varchar(200) CHARACTER SET utf8mb4 NOT NULL DEFAULT 'Anonymous', + CONSTRAINT `PK_Blogs` PRIMARY KEY (`BlogId`), + CONSTRAINT `AK_Blogs_Url` UNIQUE (`Url`) +) CHARACTER SET=utf8mb4; + + +CREATE TABLE `Post` ( + `PostId` int NOT NULL AUTO_INCREMENT, + `Title` longtext CHARACTER SET utf8mb4 NOT NULL, + `Content` longtext CHARACTER SET utf8mb4 NOT NULL, + `BlogUrl` varchar(200) CHARACTER SET utf8mb4 NULL, + CONSTRAINT `PK_Post` PRIMARY KEY (`PostId`), + CONSTRAINT `FK_Post_Blogs_BlogUrl` FOREIGN KEY (`BlogUrl`) REFERENCES `Blogs` (`Url`) +) CHARACTER SET=utf8mb4; + + +CREATE INDEX `IX_Post_BlogUrl` ON `Post` (`BlogUrl`); + + + diff --git a/test/Atlas.Provider.Test/data/postgres_default b/test/Atlas.Provider.Test/data/postgres_default new file mode 100644 index 0000000..c3b2c78 --- /dev/null +++ b/test/Atlas.Provider.Test/data/postgres_default @@ -0,0 +1,26 @@ +CREATE TABLE "Blogs" ( + "BlogId" integer GENERATED BY DEFAULT AS IDENTITY, + "Url" varchar(200) NOT NULL, + "Rating" numeric(5,2) NOT NULL, + "Title" text NOT NULL, + "Content" text NOT NULL, + "Author" character varying(200) NOT NULL DEFAULT 'Anonymous', + CONSTRAINT "PK_Blogs" PRIMARY KEY ("BlogId"), + CONSTRAINT "AK_Blogs_Url" UNIQUE ("Url") +); + + +CREATE TABLE "Post" ( + "PostId" integer GENERATED BY DEFAULT AS IDENTITY, + "Title" text NOT NULL, + "Content" text NOT NULL, + "BlogUrl" varchar(200) NULL, + CONSTRAINT "PK_Post" PRIMARY KEY ("PostId"), + CONSTRAINT "FK_Post_Blogs_BlogUrl" FOREIGN KEY ("BlogUrl") REFERENCES "Blogs" ("Url") +); + + +CREATE INDEX "IX_Post_BlogUrl" ON "Post" ("BlogUrl"); + + + diff --git a/test/Atlas.Provider.Test/data/sqlite_default b/test/Atlas.Provider.Test/data/sqlite_default new file mode 100644 index 0000000..bb1e825 --- /dev/null +++ b/test/Atlas.Provider.Test/data/sqlite_default @@ -0,0 +1,24 @@ +CREATE TABLE "Blogs" ( + "BlogId" INTEGER NOT NULL CONSTRAINT "PK_Blogs" PRIMARY KEY AUTOINCREMENT, + "Url" varchar(200) NOT NULL, + "Rating" decimal(5, 2) NOT NULL, + "Title" TEXT NOT NULL, + "Content" TEXT NOT NULL, + "Author" TEXT NOT NULL DEFAULT 'Anonymous', + CONSTRAINT "AK_Blogs_Url" UNIQUE ("Url") +); + + +CREATE TABLE "Post" ( + "PostId" INTEGER NOT NULL CONSTRAINT "PK_Post" PRIMARY KEY AUTOINCREMENT, + "Title" TEXT NOT NULL, + "Content" TEXT NOT NULL, + "BlogUrl" varchar(200) NULL, + CONSTRAINT "FK_Post_Blogs_BlogUrl" FOREIGN KEY ("BlogUrl") REFERENCES "Blogs" ("Url") +); + + +CREATE INDEX "IX_Post_BlogUrl" ON "Post" ("BlogUrl"); + + + diff --git a/test/Atlas.Provider.Test/data/sqlserver_default b/test/Atlas.Provider.Test/data/sqlserver_default new file mode 100644 index 0000000..1bb5718 --- /dev/null +++ b/test/Atlas.Provider.Test/data/sqlserver_default @@ -0,0 +1,30 @@ +-- atlas:delimiter GO +CREATE TABLE [Blogs] ( + [BlogId] int NOT NULL IDENTITY, + [Url] varchar(200) NOT NULL, + [Rating] decimal(5,2) NOT NULL, + [Title] nvarchar(max) NOT NULL, + [Content] nvarchar(max) NOT NULL, + [Author] nvarchar(200) NOT NULL DEFAULT N'Anonymous', + CONSTRAINT [PK_Blogs] PRIMARY KEY ([BlogId]), + CONSTRAINT [AK_Blogs_Url] UNIQUE ([Url]) +); +GO + + +CREATE TABLE [Post] ( + [PostId] int NOT NULL IDENTITY, + [Title] nvarchar(max) NOT NULL, + [Content] nvarchar(max) NOT NULL, + [BlogUrl] varchar(200) NULL, + CONSTRAINT [PK_Post] PRIMARY KEY ([PostId]), + CONSTRAINT [FK_Post_Blogs_BlogUrl] FOREIGN KEY ([BlogUrl]) REFERENCES [Blogs] ([Url]) +); +GO + + +CREATE INDEX [IX_Post_BlogUrl] ON [Post] ([BlogUrl]); +GO + + +