Skip to content

Commit 91cf56c

Browse files
committed
test: add tests for dotnet
1 parent 3a1ce86 commit 91cf56c

File tree

26 files changed

+907
-2979
lines changed

26 files changed

+907
-2979
lines changed

.github/workflows/spanner-lib-tests.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ on:
22
push:
33
branches: [ main ]
44
pull_request:
5+
permissions:
6+
contents: read
7+
pull-requests: write
58
name: Spanner Lib Tests
69
jobs:
710
test:
@@ -37,3 +40,32 @@ jobs:
3740
- name: Build shared lib
3841
working-directory: spannerlib
3942
run: go build -o spannerlib.so -buildmode=c-shared
43+
44+
test-dotnet:
45+
runs-on: ubuntu-latest
46+
steps:
47+
- name: Install Go
48+
uses: actions/setup-go@v5
49+
with:
50+
go-version: 1.24
51+
- name: Checkout code
52+
uses: actions/checkout@v4
53+
- name: Build shared lib
54+
working-directory: spannerlib
55+
run: go build -o spannerlib.so -buildmode=c-shared
56+
- name: Copy lib to dotnet folder
57+
working-directory: spannerlib
58+
run: |
59+
mkdir -p dotnet-spannerlib/Google.Cloud.SpannerLib/runtimes/linux-x64/native
60+
cp spannerlib.so dotnet-spannerlib/Google.Cloud.SpannerLib/runtimes/linux-x64/native/spannerlib.so
61+
- name: Install dotnet
62+
uses: actions/setup-dotnet@v4
63+
- name: Restore dependencies
64+
run: dotnet restore
65+
working-directory: spannerlib/dotnet-spannerlib
66+
- name: Build
67+
run: dotnet build --no-restore
68+
working-directory: spannerlib/dotnet-spannerlib
69+
- name: Unit Tests
70+
working-directory: spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Tests
71+
run: dotnet test --no-build --verbosity normal

go.mod

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@ go 1.24
44

55
toolchain go1.24.4
66

7-
replace cloud.google.com/go/spanner => /Users/loite/GolandProjects/google-cloud-go/spanner
8-
97
require (
108
cloud.google.com/go v0.121.2
119
cloud.google.com/go/longrunning v0.6.7
12-
cloud.google.com/go/spanner v1.82.0
10+
cloud.google.com/go/spanner v1.82.1-0.20250625132714-fe377af799f0
1311
github.com/golang/protobuf v1.5.4
1412
github.com/google/go-cmp v0.7.0
1513
github.com/google/uuid v1.6.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2335,6 +2335,8 @@ cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63wh
23352335
cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M=
23362336
cloud.google.com/go/spanner v1.82.0 h1:w9uO8RqEoBooBLX4nqV1RtgudyU2ZX780KTLRgeVg60=
23372337
cloud.google.com/go/spanner v1.82.0/go.mod h1:BzybQHFQ/NqGxvE/M+/iU29xgutJf7Q85/4U9RWMto0=
2338+
cloud.google.com/go/spanner v1.82.1-0.20250625132714-fe377af799f0 h1:JpZinZY/JMrWJAPoSVt08CwfCFkzMt2WWTjtlrnHc9Y=
2339+
cloud.google.com/go/spanner v1.82.1-0.20250625132714-fe377af799f0/go.mod h1:QSWcjxszT0WRHNd8zyGI0WctrYA1N7j0yTFsWyol9Yw=
23382340
cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM=
23392341
cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ=
23402342
cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0=
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
bin/
2+
obj/
3+
packages/
4+
*.suo
5+
.nuget/
6+
TestResults/
7+
*TestResults.xml
8+
*sponge_log.xml
9+
*.csproj.user
10+
.idea/
11+
*.iml
12+
PublishProfiles/
13+
*.sln.DotSettings.user
14+
.vs/
15+
*~
16+
*.xproj.user
17+
project.lock.json
18+
.vscode/
19+
secrets.ps1
20+
google_application_credentials.json
21+
**/Properties/launchSettings.json
22+
**/wwwroot/lib/
23+
**/kmsCipher.key
24+
/tmpB19A.tmp
25+
/dlp/tmp6849.tmp
26+
env/
27+
applications/liftAndShiftPetshop/PrecompiledWeb/
28+
applications/liftAndShiftPetshop/Web/
29+
*.leu
30+
.cr/
31+
BenchmarkDotNet.Artifacts
32+
.DS_Store
33+
34+
!spannerlib.so
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace Google.Cloud.SpannerLib.Tests;
2+
3+
public class BasicTests
4+
{
5+
[SetUp]
6+
public void Setup()
7+
{
8+
}
9+
10+
[Test]
11+
public void TestCreatePool()
12+
{
13+
var pool = Spanner.CreatePool("projects/my-project/instances/my-instance/databases/my-database");
14+
Spanner.ClosePool(pool);
15+
}
16+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<LangVersion>latest</LangVersion>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<IsPackable>false</IsPackable>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="coverlet.collector" Version="6.0.2"/>
13+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0"/>
14+
<PackageReference Include="NUnit" Version="4.2.2"/>
15+
<PackageReference Include="NUnit.Analyzers" Version="4.4.0"/>
16+
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0"/>
17+
</ItemGroup>
18+
19+
<ItemGroup>
20+
<Using Include="NUnit.Framework"/>
21+
</ItemGroup>
22+
23+
<ItemGroup>
24+
<ProjectReference Include="..\Google.Cloud.SpannerLib\Google.Cloud.SpannerLib.csproj" />
25+
</ItemGroup>
26+
27+
</Project>
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
namespace SpannerDriver
2+
{
3+
4+
public enum ErrorCode
5+
{
6+
/// <summary>The operation was cancelled.</summary>
7+
Cancelled = 1,
8+
9+
/// <summary>
10+
/// Unknown error. This may happen if an internal error occured or
11+
/// not enough information was obtained to produce a useful message.
12+
/// </summary>
13+
Unknown = 2,
14+
15+
/// <summary>
16+
/// A bad SQL statement or other invalid input was sent to Spanner.
17+
/// </summary>
18+
InvalidArgument = 3,
19+
20+
/// <summary>
21+
/// A timeout has occurred. A <see cref="T:Google.Cloud.Spanner.Data.SpannerTransaction" /> should be
22+
/// retried if this error is encountered.
23+
/// </summary>
24+
DeadlineExceeded = 4,
25+
26+
/// <summary>
27+
/// The given resource (Spanner Instance, Database, Table) was not
28+
/// found.
29+
/// </summary>
30+
NotFound = 5,
31+
32+
/// <summary>
33+
/// The given resource could be not created because it already exists.
34+
/// </summary>
35+
AlreadyExists = 6,
36+
37+
/// <summary>
38+
/// The supplied credential from <see cref="P:Google.Cloud.Spanner.Data.SpannerConnectionStringBuilder.CredentialFile" />
39+
/// or from default application credentials does not have sufficient permission for the request.
40+
/// </summary>
41+
PermissionDenied = 7,
42+
43+
/// <summary>
44+
/// A resource associated with Spanner has been exhausted. This may occur due to a server-side
45+
/// failure, or due to the local maximum number of sessions being reached.
46+
/// </summary>
47+
ResourceExhausted = 8,
48+
49+
/// <summary>
50+
/// Operation was rejected because the system is not in a state required for the
51+
/// operation's execution.
52+
/// </summary>
53+
FailedPrecondition = 9,
54+
55+
/// <summary>
56+
/// The operation was aborted due to transient issue such as competing transaction
57+
/// resources. A <see cref="T:Google.Cloud.Spanner.Data.SpannerTransaction" /> should be retried if this error
58+
/// is encountered.
59+
/// </summary>
60+
Aborted = 10, // 0x0000000A
61+
62+
/// <summary>The operation attempted to read past the valid range.</summary>
63+
OutOfRange = 11, // 0x0000000B
64+
65+
/// <summary>
66+
/// Operation is not implemented or not supported/enabled in this service.
67+
/// </summary>
68+
Unimplemented = 12, // 0x0000000C
69+
70+
/// <summary>Internal error.</summary>
71+
Internal = 13, // 0x0000000D
72+
73+
/// <summary>
74+
/// The service is currently unavailable. This is a most likely a transient condition
75+
/// and may be corrected by retrying. A <see cref="T:Google.Cloud.Spanner.Data.SpannerTransaction" /> should be
76+
/// retried if this error is encountered.
77+
/// </summary>
78+
Unavailable = 14, // 0x0000000E
79+
80+
/// <summary>Unrecoverable data loss or corruption.</summary>
81+
DataLoss = 15, // 0x0000000F
82+
83+
/// <summary>
84+
/// There is no supplied credential either through default application credentials or
85+
/// directly through <see cref="P:Google.Cloud.Spanner.Data.SpannerConnectionStringBuilder.CredentialFile" />
86+
/// </summary>
87+
Unauthenticated = 16, // 0x00000010
88+
}
89+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.1</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
7+
<LangVersion>9</LangVersion>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="Google.Cloud.Spanner.V1" Version="5.1.0" />
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<Content CopyToOutputDirectory="PreserveNewest" Include="runtimes/osx-arm/native/spannerlib.dylib" Link="spannerlib" Pack="true" PackagePath="runtimes/osx-arm/native/spannerlib.dylib" />
16+
<Content CopyToOutputDirectory="PreserveNewest" Include="runtimes/linux-x64/native/spannerlib.so" Link="spannerlib" Pack="true" PackagePath="runtimes/linux-x64/native/spannerlib.so" />
17+
<Content CopyToOutputDirectory="PreserveNewest" Include="runtimes/linux-arm/native/spannerlib.so" Link="spannerlib" Pack="true" PackagePath="runtimes/linux-arm/native/spannerlib.so" />
18+
</ItemGroup>
19+
20+
</Project>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace Google.Cloud.SpannerLib.Internal
5+
{
6+
7+
internal class DisposableGoSlice : IDisposable
8+
{
9+
private readonly GCHandle? _handle;
10+
internal GoSlice GoSlice { get; }
11+
12+
internal static DisposableGoSlice Create(byte[]? value)
13+
{
14+
var (handle, length, capacity) = Pin(value);
15+
return new DisposableGoSlice(handle,
16+
new GoSlice(handle?.AddrOfPinnedObject() ?? IntPtr.Zero, length, capacity));
17+
}
18+
19+
private DisposableGoSlice(GCHandle? handle, GoSlice goSlice)
20+
{
21+
_handle = handle;
22+
GoSlice = goSlice;
23+
}
24+
25+
private static (GCHandle?, int, int) Pin(byte[]? value)
26+
{
27+
if (value is null)
28+
{
29+
return (null, 0, 0);
30+
}
31+
32+
var length = value.Length;
33+
var handle = GCHandle.Alloc(value, GCHandleType.Pinned);
34+
return (handle, length, length);
35+
}
36+
37+
public void Dispose()
38+
{
39+
_handle?.Free();
40+
}
41+
42+
}
43+
44+
internal struct GoSlice
45+
{
46+
public IntPtr Pointer;
47+
public long Length;
48+
public long Capacity;
49+
50+
internal GoSlice(IntPtr pointer, long length, long capacity)
51+
{
52+
Pointer = pointer;
53+
Length = length;
54+
Capacity = capacity;
55+
}
56+
57+
}
58+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using System.Text;
4+
5+
namespace Google.Cloud.SpannerLib.Internal
6+
{
7+
8+
internal unsafe struct GoString : IDisposable
9+
{
10+
IntPtr Pointer { get; }
11+
internal long Length;
12+
13+
internal GoString(string value)
14+
{
15+
(Pointer, Length) = StringToHGlobalUtf8(value);
16+
}
17+
18+
private static (IntPtr, int) StringToHGlobalUtf8(string? s)
19+
{
20+
if (s is null)
21+
{
22+
return (IntPtr.Zero, 0);
23+
}
24+
25+
var nb = Encoding.UTF8.GetMaxByteCount(s.Length);
26+
var ptr = Marshal.AllocHGlobal(nb);
27+
28+
var pbMem = (byte*)ptr;
29+
var nbWritten = Encoding.UTF8.GetBytes(s, new Span<byte>(pbMem, nb));
30+
31+
return (ptr, nbWritten);
32+
}
33+
34+
public void Dispose()
35+
{
36+
Marshal.FreeHGlobal(Pointer);
37+
}
38+
}
39+
}

0 commit comments

Comments
 (0)