Skip to content

Commit

Permalink
Microsoft.Data.Sqlite: Test against e_sqlcipher and winsqlite3
Browse files Browse the repository at this point in the history
  • Loading branch information
bricelam committed Mar 26, 2020
1 parent a1931d9 commit bf325f0
Show file tree
Hide file tree
Showing 11 changed files with 211 additions and 23 deletions.
14 changes: 14 additions & 0 deletions All.sln
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFCore.Benchmarks", "benchm
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EF.Benchmarks.Shared", "benchmark\EF.Benchmarks.Shared\EF.Benchmarks.Shared.csproj", "{BFC26566-4C6D-4904-A559-8FFE09369901}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Data.Sqlite.e_sqlcipher.Tests", "test\Microsoft.Data.Sqlite.Tests\Microsoft.Data.Sqlite.e_sqlcipher.Tests.csproj", "{7B598E0C-B8E2-4F1F-B53C-ED84178E65BE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Data.Sqlite.winsqlite3.Tests", "test\Microsoft.Data.Sqlite.Tests\Microsoft.Data.Sqlite.winsqlite3.Tests.csproj", "{B163761D-FB4A-4C80-BAB9-01905E1351EF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -282,6 +286,14 @@ Global
{BFC26566-4C6D-4904-A559-8FFE09369901}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BFC26566-4C6D-4904-A559-8FFE09369901}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BFC26566-4C6D-4904-A559-8FFE09369901}.Release|Any CPU.Build.0 = Release|Any CPU
{7B598E0C-B8E2-4F1F-B53C-ED84178E65BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7B598E0C-B8E2-4F1F-B53C-ED84178E65BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7B598E0C-B8E2-4F1F-B53C-ED84178E65BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7B598E0C-B8E2-4F1F-B53C-ED84178E65BE}.Release|Any CPU.Build.0 = Release|Any CPU
{B163761D-FB4A-4C80-BAB9-01905E1351EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B163761D-FB4A-4C80-BAB9-01905E1351EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B163761D-FB4A-4C80-BAB9-01905E1351EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B163761D-FB4A-4C80-BAB9-01905E1351EF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -329,6 +341,8 @@ Global
{678AB38D-B27C-4690-A3F9-2D2488391658} = {293B4F79-3CB9-402A-A74C-B8108C41A7CF}
{2642F4F0-69BE-4C43-94B7-B298FEC87D89} = {293B4F79-3CB9-402A-A74C-B8108C41A7CF}
{BFC26566-4C6D-4904-A559-8FFE09369901} = {293B4F79-3CB9-402A-A74C-B8108C41A7CF}
{7B598E0C-B8E2-4F1F-B53C-ED84178E65BE} = {258D5057-81B9-40EC-A872-D21E27452749}
{B163761D-FB4A-4C80-BAB9-01905E1351EF} = {258D5057-81B9-40EC-A872-D21E27452749}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {285A5EB4-BCF4-40EB-B9E1-DF6DBCB5E705}
Expand Down
4 changes: 3 additions & 1 deletion Microsoft.Data.Sqlite.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"projects": [
"src\\Microsoft.Data.Sqlite.Core\\Microsoft.Data.Sqlite.Core.csproj",
"src\\Microsoft.Data.Sqlite\\Microsoft.Data.Sqlite.csproj",
"test\\Microsoft.Data.Sqlite.Tests\\Microsoft.Data.Sqlite.Tests.csproj"
"test\\Microsoft.Data.Sqlite.Tests\\Microsoft.Data.Sqlite.Tests.csproj",
"test\\Microsoft.Data.Sqlite.Tests\\Microsoft.Data.Sqlite.e_sqlcipher.Tests.csproj",
"test\\Microsoft.Data.Sqlite.Tests\\Microsoft.Data.Sqlite.winsqlite3.Tests.csproj"
]
}
}
1 change: 1 addition & 0 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<NetTopologySuiteIOSqlServerBytesPackageVersion>2.0.0</NetTopologySuiteIOSqlServerBytesPackageVersion>
<SQLitePCLRawBundleESqlite3PackageVersion>2.0.2</SQLitePCLRawBundleESqlite3PackageVersion>
<SQLitePCLRawBundleESqlcipherPackageVersion>2.0.2</SQLitePCLRawBundleESqlcipherPackageVersion>
<SQLitePCLRawBundleWinsqlite3PackageVersion>2.0.2</SQLitePCLRawBundleWinsqlite3PackageVersion>
<SQLitePCLRawCorePackageVersion>2.0.2</SQLitePCLRawCorePackageVersion>
<StyleCopAnalyzersPackageVersion>1.1.118</StyleCopAnalyzersPackageVersion>
<BenchmarkDotNetPackageVersion>0.12.0</BenchmarkDotNetPackageVersion>
Expand Down
16 changes: 14 additions & 2 deletions src/Microsoft.Data.Sqlite.Core/Extensions/SQLitePCLExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;

// ReSharper disable once CheckNamespace
// ReSharper disable InconsistentNaming
namespace SQLitePCL
{
internal static class SQLitePCLExtensions
{
public static bool EncryptionNotSupported()
=> raw.GetNativeLibraryName() == "e_sqlite3";
private static readonly Dictionary<string, bool> _knownLibraries = new Dictionary<string, bool>
{
{ "e_sqlcipher", true },
{ "e_sqlite3", false},
{ "sqlcipher", true },
{ "winsqlite3", false }
};

public static bool? EncryptionSupported()
=> _knownLibraries.TryGetValue(raw.GetNativeLibraryName(), out var supported)
? supported
: default(bool?);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@

using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo(
"Microsoft.Data.Sqlite.e_sqlcipher.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo(
"Microsoft.Data.Sqlite.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo(
"Microsoft.Data.Sqlite.winsqlite3.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
5 changes: 4 additions & 1 deletion src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ public override void Open()
{
if (!string.IsNullOrEmpty(ConnectionOptions.Password))
{
if (SQLitePCLExtensions.EncryptionNotSupported())
if (SQLitePCLExtensions.EncryptionSupported() == false)
{
throw new InvalidOperationException(Resources.EncryptionNotSupported);
}
Expand All @@ -256,7 +256,10 @@ public override void Open()
"SELECT quote($password);",
new SqliteParameter("$password", ConnectionOptions.Password));
this.ExecuteNonQuery("PRAGMA key = " + quotedPassword + ";");
}

if (SQLitePCLExtensions.EncryptionSupported() != false)
{
// NB: Forces decryption. Throws when the key is incorrect.
this.ExecuteNonQuery("SELECT COUNT(*) FROM sqlite_master;");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

<PropertyGroup>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<DefineConstants>$(DefineConstants);E_SQLITE3</DefineConstants>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<DefineConstants>$(DefineConstants);E_SQLCIPHER</DefineConstants>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlcipher" Version="$(SQLitePCLRawBundleESqlcipherPackageVersion)" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<DefineConstants>$(DefineConstants);WINSQLITE3</DefineConstants>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_winsqlite3" Version="$(SQLitePCLRawBundleWinsqlite3PackageVersion)" />
</ItemGroup>

</Project>
38 changes: 19 additions & 19 deletions test/Microsoft.Data.Sqlite.Tests/SqliteConnectionTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Globalization;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using Microsoft.Data.Sqlite.Properties;
using Microsoft.Data.Sqlite.Utilities;
using Xunit;
using static SQLitePCL.raw;

Expand Down Expand Up @@ -260,20 +260,18 @@ public void Open_works_when_memory_shared()
[Fact]
public void Open_works_when_password()
{
switch (GetNativeLibraryName())
{
case "e_sqlite3":
Open_works_when_password_e_sqlite3();
break;

// NB: Change project dependencies to test this
case "e_sqlcipher":
Open_works_when_password_sqlcipher();
break;
}
#if E_SQLITE3 || WINSQLITE3
Open_works_when_password_unsupported();
#elif E_SQLCIPHER || SQLCIPHER
Open_works_when_password_supported();
#elif SQLITE3
Open_works_when_password_might_be_supported();
#else
#error Unexpected native library
#endif
}

private void Open_works_when_password_e_sqlite3()
private void Open_works_when_password_unsupported()
{
using (var connection = new SqliteConnection("Data Source=encrypted.db;Password=password"))
{
Expand All @@ -288,12 +286,8 @@ private void Open_works_when_password_e_sqlite3()
}
}

private void Open_works_when_password_sqlcipher()
private void Open_works_when_password_supported()
{
var es = new CultureInfo("es");
Thread.CurrentThread.CurrentCulture = es;
Thread.CurrentThread.CurrentUICulture = es;

using (var connection1 = new SqliteConnection("Data Source=encrypted.db;Password=password"))
{
connection1.Open();
Expand All @@ -315,6 +309,12 @@ private void Open_works_when_password_sqlcipher()
}
}

private void Open_works_when_password_might_be_supported()
{
using var connection = new SqliteConnection("Data Source=encrypted.db;Password=password");
connection.Open();
}

[Theory]
[InlineData("True", 1L)]
[InlineData("False", 0L)]
Expand Down
119 changes: 119 additions & 0 deletions test/Microsoft.Data.Sqlite.Tests/TestUtilities/SqliteTestFramework.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
using System;

#if WINSQLITE3
using System.Runtime.InteropServices;
#endif

[assembly: TestFramework(
"Microsoft.Data.Sqlite.Tests.TestUtilities.SqliteTestFramework",
#if E_SQLITE3
"Microsoft.Data.Sqlite.Tests")]
#elif E_SQLCIPHER
"Microsoft.Data.Sqlite.e_sqlcipher.Tests")]
#elif WINSQLITE3
"Microsoft.Data.Sqlite.winsqlite3.Tests")]
#else
#error Unexpected native library
#endif

namespace Microsoft.Data.Sqlite.Tests.TestUtilities
{
class SqliteTestFramework : XunitTestFramework
{
protected SqliteTestFramework(IMessageSink diagnosticMessageSink)
: base(diagnosticMessageSink)
{
}

protected override ITestFrameworkExecutor CreateExecutor(AssemblyName assemblyName)
=> new SqliteTestFrameworkExecutor(assemblyName, SourceInformationProvider, DiagnosticMessageSink);
}

class SqliteTestFrameworkExecutor : XunitTestFrameworkExecutor
{
public SqliteTestFrameworkExecutor(
AssemblyName assemblyName,
ISourceInformationProvider sourceInformationProvider,
IMessageSink diagnosticMessageSink)
: base(assemblyName, sourceInformationProvider, diagnosticMessageSink)
{
}

protected override async void RunTestCases(
IEnumerable<IXunitTestCase> testCases,
IMessageSink executionMessageSink,
ITestFrameworkExecutionOptions executionOptions)
{
using var assemblyRunner = new SqliteTestAssemblyRunner(
TestAssembly,
testCases,
DiagnosticMessageSink,
executionMessageSink,
executionOptions);
await assemblyRunner.RunAsync();
}
}

class SqliteTestAssemblyRunner : XunitTestAssemblyRunner
{
public SqliteTestAssemblyRunner(
ITestAssembly testAssembly,
IEnumerable<IXunitTestCase> testCases,
IMessageSink diagnosticMessageSink,
IMessageSink executionMessageSink,
ITestFrameworkExecutionOptions executionOptions)
: base(testAssembly, testCases, diagnosticMessageSink, executionMessageSink, executionOptions)
{
}


protected override Task<RunSummary> RunTestCollectionAsync(
IMessageBus messageBus,
ITestCollection testCollection,
IEnumerable<IXunitTestCase> testCases,
CancellationTokenSource cancellationTokenSource)
{
#if WINSQLITE3
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return SkipAll("winsqlite3 isn't supported on " + RuntimeInformation.OSDescription);
}

#endif
var version = new SqliteConnection().ServerVersion;
if (new Version(version) < new Version(3, 16, 0))
{
return SkipAll("SQLite " + version + " isn't supported. Upgrade to 3.16.0 or higher");
}

return new XunitTestCollectionRunner(
testCollection,
testCases,
DiagnosticMessageSink,
messageBus,
TestCaseOrderer,
new ExceptionAggregator(Aggregator),
cancellationTokenSource)
.RunAsync();

Task<RunSummary> SkipAll(string reason)
{
var count = 0;
foreach (var testCase in testCases)
{
messageBus.QueueMessage(new TestSkipped(new XunitTest(testCase, testCase.DisplayName), reason));
count++;
}

return Task.FromResult(new RunSummary { Skipped = count, Total = count });
}
}
}
}

0 comments on commit bf325f0

Please sign in to comment.