diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index e17a3498f8..9eb3cb0993 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -21,25 +21,17 @@ jobs:
- 8.x
arango:
- "arangodb:3.11"
-# - "arangodb:3.10"
-# - "arangodb/enterprise:3.9"
+ - "arangodb:latest"
+# - "arangodb/enterprise:3.9"
topology:
- single
# - cluster
steps:
- - uses: actions/checkout@v3
-
- - name: chmod
- run: find ./docker -name '*.sh' | xargs chmod +x
-
- - name: arango
- run: ./docker/start_db_${{ matrix.topology }}_retry_fail.sh ${{ matrix.arango }}
- env:
- ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }}
-
+ - uses: actions/checkout@v4
+
- name: dotnet
- uses: actions/setup-dotnet@v3
+ uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ matrix.dotnet }}
@@ -49,4 +41,5 @@ jobs:
- name: test
run: dotnet test --configuration Release
env:
- ARANGODB_CONNECTION: "Server=http://172.28.3.1:8529;Realm=CI-{UUID};User=root;Password=test;"
+ ARANGODB_VERSION: ${{ matrix.arango }}
+ ARANGODB_TOPOLOGY: ${{ matrix.topology }}
diff --git a/Core.Arango.Tests/Core.Arango.Tests.csproj b/Core.Arango.Tests/Core.Arango.Tests.csproj
index 921f908de5..c4f027632d 100644
--- a/Core.Arango.Tests/Core.Arango.Tests.csproj
+++ b/Core.Arango.Tests/Core.Arango.Tests.csproj
@@ -10,21 +10,22 @@
-
-
+
+
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/Core.Arango.Tests/Core/TestBase.cs b/Core.Arango.Tests/Core/TestBase.cs
index db9ee489f8..23fed73f2a 100644
--- a/Core.Arango.Tests/Core/TestBase.cs
+++ b/Core.Arango.Tests/Core/TestBase.cs
@@ -7,29 +7,148 @@
using Newtonsoft.Json;
using Xunit;
using Xunit.Abstractions;
+using Testcontainers.ArangoDb;
+using System.Collections.Generic;
+using System.IO;
+using DotNet.Testcontainers.Builders;
namespace Core.Arango.Tests.Core
{
public abstract class TestBase : IAsyncLifetime
{
+ private const string ARANGO_LICENSE_KEY_ENVAR = "ARANGO_LICENSE_KEY";
+ private const string ARANGODB_VERSION_ENVAR = "ARANGODB_VERSION";
+ private const string ARANGODB_TOPOLOGY_ENVAR = "ARANGODB_TOPOLOGY";
+ private const string DefaultImage = "arangodb:latest";
+ private const string DefaultImagePassword = "password";
+ private const string DefaultImageUser = "root";
+ private const string ClusterValue = "cluster";
+
public IArangoContext Arango { get; protected set; }
+ private readonly static Lazy>> Containers = new(async () =>
+ Environment.GetEnvironmentVariable(ARANGODB_TOPOLOGY_ENVAR) == ClusterValue
+ ? await SetupClusterServer()
+ : await SetupSingleServer());
- public virtual Task InitializeAsync()
+ public virtual async Task InitializeAsync()
{
- return Task.CompletedTask;
+ foreach (var container in await Containers.Value)
+ {
+ await container.StartAsync()
+ .ConfigureAwait(false);
+ }
}
- public async Task DisposeAsync()
+ private static (Dictionary Environment, string Version) GetVersionAndEnvironment()
{
- try
+ var environment = new Dictionary();
+
+ if (string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(ARANGO_LICENSE_KEY_ENVAR)))
{
- foreach (var db in await Arango.Database.ListAsync())
- await Arango.Database.DropAsync(db);
+ environment.Add(ARANGO_LICENSE_KEY_ENVAR, Environment.GetEnvironmentVariable(ARANGO_LICENSE_KEY_ENVAR));
}
- catch
+
+ var version = string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(ARANGODB_VERSION_ENVAR))
+ ? DefaultImage
+ : Environment.GetEnvironmentVariable(ARANGODB_VERSION_ENVAR);
+
+ return (environment, version);
+ }
+
+ private static Task> SetupSingleServer()
+ {
+ var (environment, version) = GetVersionAndEnvironment();
+ return Task.FromResult(new List{new ArangoDbBuilder()
+ .WithImage(version)
+ .WithEnvironment(environment)
+ .WithPassword(DefaultImagePassword)
+ .Build() });
+ }
+
+ private static async Task> SetupClusterServer()
+ {
+ var (environment, version) = GetVersionAndEnvironment();
+
+ // This is not yet tested. But is a largely compatible replication of the start_db_cluster script.
+ // 2024-10-29 20:11:32 Error while processing command-line options for arangod:
+ // 2024 - 10 - 29 20:11:32 unknown option '--cluster.start-dbserver false'
+ // I suspect that's because Cluster is only available for Enterprise?
+ var arangoDBNetwork = new NetworkBuilder()
+ .WithName($"ArangoDB-{Guid.NewGuid():D}")
+ .Build();
+
+ var jwt = Path.GetTempFileName();
+ File.Move(jwt, jwt + ".jwt");
+ jwt += ".jwt";
+ File.AppendAllText(jwt, "Averysecretword");
+
+ var leadAgent = $"leadagent-{Guid.NewGuid():N}";
+ var extraAgents = Enumerable.Range(0, 2);
+ var dbs = Enumerable.Range(0, 2);
+ var coordinators = Enumerable.Range(0, 2);
+
+ var containers = new List();
+
+ var DefaultContainerConfiguration = new ArangoDbBuilder()
+ .WithImage(version)
+ .WithResourceMapping(jwt, "/jwtSecret")
+ .WithEnvironment(environment)
+ .WithPassword(DefaultImagePassword)
+ .WithNetwork(arangoDBNetwork);
+
+ containers.Add(DefaultContainerConfiguration
+ .WithName(leadAgent)
+ .WithCommand(
+ "--cluster.start-dbserver", "false",
+ "--cluster.start-coordinator", "false",
+ "--auth.jwt-secret", "/jwtSecret")
+ .Build());
+
+ foreach (var _ in extraAgents)
{
- //
+ containers.Add(DefaultContainerConfiguration
+ .WithName($"{extraAgents}-{Guid.NewGuid():N}")
+ .WithCommand(
+ "--cluster.start-dbserver", "false",
+ "--cluster.start-coordinator", "false",
+ "--auth.jwt-secret", "/jwtSecret",
+ "--starter.join", leadAgent)
+ .Build());
}
+
+ foreach (var _ in dbs)
+ {
+ containers.Add(DefaultContainerConfiguration
+ .WithName($"{dbs}-{Guid.NewGuid():N}")
+ .WithCommand(
+ "--cluster.start-dbserver", "true",
+ "--cluster.start-coordinator", "false",
+ "--auth.jwt-secret", "/jwtSecret",
+ "--starter.join", leadAgent)
+ .Build());
+ }
+
+ foreach (var _ in coordinators)
+ {
+ containers.Add(DefaultContainerConfiguration
+ .WithName($"{coordinators}-{Guid.NewGuid():N}")
+ .WithCommand(
+ "--cluster.start-dbserver", "false",
+ "--cluster.start-coordinator", "true",
+ "--auth.jwt-secret", "/jwtSecret",
+ "--starter.join", leadAgent)
+ .Build());
+ }
+
+ await arangoDBNetwork.CreateAsync()
+ .ConfigureAwait(false);
+
+ return containers;
+ }
+
+ public async Task DisposeAsync()
+ {
+ await Task.CompletedTask;
}
public async Task SetupAsync(string serializer, string createDatabase = "test")
@@ -47,20 +166,20 @@ public async Task SetupAsync(string serializer, string createDatabase = "test")
});
if (!string.IsNullOrEmpty(createDatabase))
- await Arango.Database.CreateAsync("test");
+ {
+ var databaseCreateSuccessful = await Arango.Database.CreateAsync("test");
+ if (databaseCreateSuccessful == false)
+ {
+ throw new Exception("Database creation failed");
+ }
+ }
}
- protected string UniqueTestRealm()
- {
- var cs = Environment.GetEnvironmentVariable("ARANGODB_CONNECTION");
-
- if (string.IsNullOrWhiteSpace(cs))
- cs = "Server=http://localhost:8529;Realm=CI-{UUID};User=root;Password=;";
-
- return cs.Replace("{UUID}", Guid.NewGuid().ToString("D"));
- }
+ protected static string UniqueTestRealm()
+ // Last to get the Coordinators for clusters, or the only existing one for a single server.
+ => $"Server={Containers.Value.Result.Last().GetTransportAddress()};User={DefaultImageUser};Realm=CI-{Guid.NewGuid():D};Password={DefaultImagePassword};";
- protected void PrintQuery(IQueryable query, ITestOutputHelper output)
+ protected static void PrintQuery(IQueryable query, ITestOutputHelper output)
{
var aql = query.ToAql();
output.WriteLine("QUERY:");
diff --git a/Core.Arango.Tests/IndexTest.cs b/Core.Arango.Tests/IndexTest.cs
index b77a83e136..573efbab9a 100644
--- a/Core.Arango.Tests/IndexTest.cs
+++ b/Core.Arango.Tests/IndexTest.cs
@@ -17,7 +17,7 @@ public async Task DropAll(string serializer)
await Arango.Index.CreateAsync("test", "test", new ArangoIndex
{
- Fields = new List {"test"},
+ Fields = ["test"],
Type = ArangoIndexType.Hash
});
diff --git a/Core.Arango.Tests/LinqTest.cs b/Core.Arango.Tests/LinqTest.cs
index 2e7fa9ccee..3a536451a2 100644
--- a/Core.Arango.Tests/LinqTest.cs
+++ b/Core.Arango.Tests/LinqTest.cs
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Core.Arango.Protocol;
@@ -10,7 +8,6 @@
using Newtonsoft.Json;
using Xunit;
using Xunit.Abstractions;
-using System.Linq.Expressions;
namespace Core.Arango.Tests
{
@@ -70,7 +67,7 @@ await Arango.Query("test")
}
[Fact]
- public async Task MultiFilter()
+ public Task MultiFilter()
{
var q = Arango.Query("test")
.Where(x => x.Name == "Project A")
@@ -80,16 +77,20 @@ public async Task MultiFilter()
.Skip(0).Take(1);
Assert.Equal("FOR `x` IN `Project` FILTER ( `x`.`Name` == @P1 ) SORT `x`.`Name` ASC FILTER ( `x`.`Name` == @P2 ) SORT `x`.`Name` DESC LIMIT @P3 , @P4 RETURN `x`", q.ToAql().aql.Trim());
+
+ return Task.CompletedTask;
}
[Fact]
- public async Task FilterOrder()
+ public Task FilterOrder()
{
var q = Arango.Query("test")
.Where(x => (x.Name == "Project A" || x.Name == "Project B") && x.Budget <= 0);
Assert.Equal("FOR `x` IN `Project` FILTER ( ( ( `x`.`Name` == @P1 ) OR ( `x`.`Name` == @P2 ) ) AND ( `x`.`Budget` <= @P3 ) ) RETURN `x`", q.ToAql().aql.Trim());
+
+ return Task.CompletedTask;
}
[Fact]
@@ -117,6 +118,7 @@ public async Task GroupBy()
_output.WriteLine(q.ToAql().aql);
_output.WriteLine("");
+ await Task.CompletedTask;
//_output.WriteLine(JsonConvert.SerializeObject(await q.ToListAsync(), Formatting.Indented));
}
@@ -132,6 +134,7 @@ public async Task MathAbs()
_output.WriteLine(q.ToAql().aql);
_output.WriteLine("");
+ await Task.CompletedTask;
//_output.WriteLine(JsonConvert.SerializeObject(await q.ToListAsync(), Formatting.Indented));
}
@@ -147,6 +150,7 @@ public async Task Ternary()
_output.WriteLine(q.ToAql().aql);
_output.WriteLine("");
+ await Task.CompletedTask;
//_output.WriteLine(JsonConvert.SerializeObject(await q.ToListAsync(), Formatting.Indented));
}
@@ -174,6 +178,7 @@ public async Task Remove()
.Remove().In().Select(x => x.Key);
_output.WriteLine(q.ToAql().aql);
+ await Task.CompletedTask;
}
[Fact]
@@ -217,10 +222,13 @@ public async Task QueryableContains()
.Contains("CB");
Assert.True(q);
+ await Task.CompletedTask;
}
public override async Task InitializeAsync()
{
+ await base.InitializeAsync();
+
Arango = new ArangoContext(UniqueTestRealm());
await Arango.Database.CreateAsync(D);
await Arango.Collection.CreateAsync(D, nameof(Client), ArangoCollectionType.Document);
@@ -300,6 +308,7 @@ public async Task StringContains()
var aql = q.ToAql().aql.Trim();
Assert.Equal("FOR `x` IN `Project` FILTER CONTAINS( `x`.`Name` , @P1 ) RETURN `x`", aql);
+ await Task.CompletedTask;
}
[Fact]
@@ -309,6 +318,7 @@ public async Task StringConcat()
var aql = q.ToAql().aql.Trim();
Assert.Equal("FOR `x` IN `Project` FILTER ( CONCAT( `x`.`Name` , @P1 ) == @P2 ) RETURN `x`", aql);
+ await Task.CompletedTask;
}
}
}
\ No newline at end of file
diff --git a/Core.Arango.Tests/LinqTest_BasicOperations.cs b/Core.Arango.Tests/LinqTest_BasicOperations.cs
index 46d68ebb63..bf59042db1 100644
--- a/Core.Arango.Tests/LinqTest_BasicOperations.cs
+++ b/Core.Arango.Tests/LinqTest_BasicOperations.cs
@@ -48,6 +48,7 @@ class InnerChain
public class LinqTest_BasicOperations : TestBase
{
+
private const string D = "test";
private readonly ITestOutputHelper _output;
public LinqTest_BasicOperations(ITestOutputHelper output)
@@ -381,6 +382,7 @@ public async Task Min()
var min = Arango.Query("test").Select(x => x.Revenue).Min();
Assert.Equal(3.4m, min);
+ await Task.CompletedTask;
}
[Fact]
@@ -389,6 +391,7 @@ public async Task Max()
var max = Arango.Query("test").Select(x => x.Revenue).Max();
Assert.Equal(4.4m, max);
+ await Task.CompletedTask;
}
[Fact]
@@ -398,6 +401,7 @@ public async Task Sum()
var sum = Arango.Query("test").Select(x => x.Revenue).Sum();
Assert.Equal(expectedSum, sum);
+ await Task.CompletedTask;
}
/*[Fact]
@@ -492,6 +496,7 @@ public async Task Take()
public override async Task InitializeAsync()
{
+ await base.InitializeAsync();
Arango = new ArangoContext(UniqueTestRealm());
await Arango.Database.CreateAsync(D);
await Arango.Collection.CreateAsync(D, nameof(Activity), ArangoCollectionType.Document);
diff --git a/Core.Arango.Tests/LinqTest_String.cs b/Core.Arango.Tests/LinqTest_String.cs
index a7726a3d22..45791a2d8a 100644
--- a/Core.Arango.Tests/LinqTest_String.cs
+++ b/Core.Arango.Tests/LinqTest_String.cs
@@ -1,13 +1,10 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Core.Arango.Protocol;
using Core.Arango.Linq;
using Core.Arango.Tests.Core;
-using Newtonsoft.Json;
using Xunit;
using Xunit.Abstractions;
@@ -227,6 +224,7 @@ public async Task StringToUpper()
public override async Task InitializeAsync()
{
+ await base.InitializeAsync();
Arango = new ArangoContext(UniqueTestRealm());
await Arango.Database.CreateAsync(D);
await Arango.Collection.CreateAsync(D, nameof(Client), ArangoCollectionType.Document);
diff --git a/Core.Arango.Tests/QueryStatisticTest.cs b/Core.Arango.Tests/QueryStatisticTest.cs
index 2ab326ba37..e769af386a 100644
--- a/Core.Arango.Tests/QueryStatisticTest.cs
+++ b/Core.Arango.Tests/QueryStatisticTest.cs
@@ -20,6 +20,7 @@ public QueryStatisticTest(ITestOutputHelper output)
public override async Task InitializeAsync()
{
+ await base.InitializeAsync();
Arango =
new ArangoContext(UniqueTestRealm(),
new ArangoConfiguration
diff --git a/Core.Arango.Tests/Serializer.cs b/Core.Arango.Tests/Serializer.cs
index 806be072af..5ebc565ef9 100644
--- a/Core.Arango.Tests/Serializer.cs
+++ b/Core.Arango.Tests/Serializer.cs
@@ -2,8 +2,6 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
-using System.Net.Http;
-using System.Net.Http.Headers;
using Core.Arango.Serialization;
using Core.Arango.Serialization.Json;
using Core.Arango.Serialization.Newtonsoft;
diff --git a/Core.Arango.sln b/Core.Arango.sln
index a5b9ad6783..69e6ea547b 100644
--- a/Core.Arango.sln
+++ b/Core.Arango.sln
@@ -10,6 +10,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{13D67C1C-3066-4412-A1F6-9C9AD13B7C81}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
+ README.md = README.md
EndProjectSection
EndProject
Global
diff --git a/Core.Arango/Core.Arango.csproj b/Core.Arango/Core.Arango.csproj
index 65d3977ab3..5518fff4ac 100644
--- a/Core.Arango/Core.Arango.csproj
+++ b/Core.Arango/Core.Arango.csproj
@@ -37,7 +37,7 @@
-
+
@@ -46,14 +46,14 @@
-
-
+
+
-
-
-
+
+
+
diff --git a/README.md b/README.md
index 34fa313eb1..d24f0632dd 100644
--- a/README.md
+++ b/README.md
@@ -667,3 +667,12 @@ await Arango.Backup.RestoreAsync(backup.Id);
await Arango.Backup.DeleteAsync(backup.Id);
```
+
+# Building and Testing
+## Build
+- Clone the repository.
+- Run `dotnet build` to build the solution, or use your preferred IDE to build the solution.
+
+## Testing
+- Install [Docker Desktop](https://www.docker.com/products/docker-desktop/), this is required to run the integration tests via TestContainers.
+- Run `dotnet test` to run the tests, or use your preferred IDE to run the tests.
\ No newline at end of file