Skip to content

Commit 26db883

Browse files
authored
feat: query and write (#8)
1 parent 83f5e83 commit 26db883

35 files changed

+3798
-19
lines changed

.circleci/config.yml

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
version: 2.1
2-
jobs:
3-
build:
4-
working_directory: ~/repo
5-
docker:
6-
- image: "mcr.microsoft.com/dotnet/sdk:7.0"
2+
commands:
3+
client-test:
4+
parameters:
5+
project:
6+
type: string
7+
default: "Client.Test"
78
steps:
89
- checkout
910
- run:
@@ -18,12 +19,12 @@ jobs:
1819
mkdir test-results
1920
- run:
2021
name: Run tests
21-
command: dotnet test Client.Test --collect "Xplat Code Coverage" --logger "junit;LogFilePath=../test-results/test-result.xml"
22+
command: dotnet test << parameters.project >> --collect "Xplat Code Coverage" --logger "junit;LogFilePath=../test-results/test-result.xml"
2223
- run:
2324
name: Coverage Report
2425
command: |
2526
dotnet tool install --tool-path="./reportgenerator/" dotnet-reportgenerator-globaltool
26-
./reportgenerator/reportgenerator -reports:"Client.Test/TestResults/*/coverage.cobertura.xml" -targetdir:"report" -reporttypes:HtmlSummary "-sourcedirs:Client/"
27+
./reportgenerator/reportgenerator -reports:"<< parameters.project >>/TestResults/*/coverage.cobertura.xml" -targetdir:"report" -reporttypes:HtmlSummary "-sourcedirs:Client/"
2728
mv report/summary.html /tmp/artifacts
2829
cp test-results/test-result.xml /tmp/artifacts
2930
when: always
@@ -44,3 +45,56 @@ jobs:
4445
path: /tmp/artifacts
4546
- store_test_results:
4647
path: test-results
48+
49+
50+
jobs:
51+
tests-unit:
52+
working_directory: ~/repo
53+
docker:
54+
- image: &default-dotnet-image "mcr.microsoft.com/dotnet/sdk:7.0"
55+
steps:
56+
- client-test:
57+
project: "Client.Test"
58+
tests-integration:
59+
working_directory: ~/repo
60+
docker:
61+
- image: *default-dotnet-image
62+
environment:
63+
FLIGHT_SQL_URL: "https://localhost:31337"
64+
INFLUXDB_URL: "http://localhost:8086"
65+
- image: voltrondata/flight-sql:arrow-11.0.0
66+
environment:
67+
FLIGHT_PASSWORD: "flight_password"
68+
PRINT_QUERIES: "1"
69+
- image: influxdb:latest
70+
environment:
71+
DOCKER_INFLUXDB_INIT_MODE: "setup"
72+
DOCKER_INFLUXDB_INIT_USERNAME: "my-user"
73+
DOCKER_INFLUXDB_INIT_PASSWORD: "my-password"
74+
DOCKER_INFLUXDB_INIT_ORG: "my-org"
75+
DOCKER_INFLUXDB_INIT_BUCKET: "my-bucket"
76+
DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: "my-token"
77+
steps:
78+
- client-test:
79+
project: "Client.Test.Integration"
80+
81+
check-compilation-warnings:
82+
docker:
83+
- image: *default-dotnet-image
84+
steps:
85+
- checkout
86+
- run:
87+
name: Check compilation warnings
88+
command: |
89+
dotnet clean --configuration Release
90+
dotnet build --configuration Release
91+
92+
workflows:
93+
version: 2
94+
build:
95+
jobs:
96+
- check-compilation-warnings
97+
- tests-unit
98+
- tests-integration:
99+
requires:
100+
- "tests-unit"

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ bld/
1515
# Test results
1616
report/
1717
reportgenerator/
18-
TestResults/
18+
TestResults/
19+
InfluxDB3.sln.DotSettings.user
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net7.0</TargetFramework>
5+
<LangVersion>10</LangVersion>
6+
<Nullable>enable</Nullable>
7+
8+
<IsPackable>false</IsPackable>
9+
<AssemblyName>InfluxDB3.Client.Test.Integration</AssemblyName>
10+
<RootNamespace>InfluxDB3.Client.Test.Integration</RootNamespace>
11+
12+
<AssemblyOriginatorKeyFile>../Keys/Key.snk</AssemblyOriginatorKeyFile>
13+
<SignAssembly>true</SignAssembly>
14+
</PropertyGroup>
15+
16+
<ItemGroup>
17+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
18+
<PackageReference Include="NUnit" Version="3.13.3" />
19+
<PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
20+
<PackageReference Include="NUnit.Analyzers" Version="3.6.1" />
21+
<PackageReference Include="coverlet.collector" Version="3.2.0" />
22+
<PackageReference Include="JunitXml.TestLogger" Version="3.0.124" />
23+
<PackageReference Include="Testcontainers" Version="3.1.0" />
24+
</ItemGroup>
25+
26+
<ItemGroup>
27+
<ProjectReference Include="..\Client\Client.csproj" />
28+
</ItemGroup>
29+
30+
</Project>
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using DotNet.Testcontainers.Builders;
7+
using DotNet.Testcontainers.Containers;
8+
using Grpc.Core;
9+
using InfluxDB3.Client.Config;
10+
using InfluxDB3.Client.Write;
11+
using NUnit.Framework;
12+
13+
namespace InfluxDB3.Client.Test.Integration;
14+
15+
public class QueryWriteTest
16+
{
17+
private static readonly TraceListener ConsoleOutListener = new TextWriterTraceListener(Console.Out);
18+
19+
private readonly IContainer?[] _dockerContainers =
20+
{
21+
Environment.GetEnvironmentVariable("FLIGHT_SQL_URL") is null
22+
? new ContainerBuilder()
23+
.WithImage("voltrondata/flight-sql:arrow-11.0.0")
24+
.WithAutoRemove(true)
25+
.WithPortBinding(31337, 31337)
26+
.WithEnvironment(new Dictionary<string, string>()
27+
{
28+
{ "FLIGHT_PASSWORD", "flight_password" },
29+
{ "PRINT_QUERIES", "1" }
30+
})
31+
.Build()
32+
: null,
33+
Environment.GetEnvironmentVariable("INFLUXDB_URL") is null
34+
? new ContainerBuilder()
35+
.WithImage("influxdb:latest")
36+
.WithAutoRemove(true)
37+
.WithPortBinding(8086, 8086)
38+
.WithEnvironment(new Dictionary<string, string>()
39+
{
40+
{ "DOCKER_INFLUXDB_INIT_MODE", "setup" },
41+
{ "DOCKER_INFLUXDB_INIT_USERNAME", "my-user" },
42+
{ "DOCKER_INFLUXDB_INIT_PASSWORD", "my-password" },
43+
{ "DOCKER_INFLUXDB_INIT_ORG", "my-org" },
44+
{ "DOCKER_INFLUXDB_INIT_BUCKET", "my-bucket" },
45+
{ "DOCKER_INFLUXDB_INIT_ADMIN_TOKEN", "my-token" },
46+
})
47+
.Build()
48+
: null
49+
};
50+
51+
[OneTimeSetUp]
52+
public async Task OneTimeSetUp()
53+
{
54+
if (!Trace.Listeners.Contains(ConsoleOutListener))
55+
{
56+
Console.SetOut(TestContext.Progress);
57+
Trace.Listeners.Add(ConsoleOutListener);
58+
}
59+
60+
foreach (var dockerContainer in _dockerContainers)
61+
{
62+
if (dockerContainer is not null)
63+
{
64+
await dockerContainer.StartAsync();
65+
}
66+
67+
// wait to start
68+
await Task.Delay(TimeSpan.FromSeconds(5));
69+
}
70+
}
71+
72+
[OneTimeTearDown]
73+
public async Task OneTimeTearDown()
74+
{
75+
foreach (var dockerContainer in _dockerContainers)
76+
{
77+
if (dockerContainer is not null)
78+
{
79+
await dockerContainer.DisposeAsync();
80+
}
81+
}
82+
}
83+
84+
[Test]
85+
public async Task Query()
86+
{
87+
var headers = new Metadata
88+
{
89+
{
90+
"Authorization",
91+
"Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes("flight_username:flight_password"))
92+
}
93+
};
94+
95+
using var client = new InfluxDBClient(new InfluxDBClientConfigs
96+
{
97+
HostUrl = Environment.GetEnvironmentVariable("FLIGHT_SQL_URL") ?? "https://localhost:31337",
98+
Database = "database",
99+
DisableServerCertificateValidation = true,
100+
Headers = headers
101+
});
102+
103+
var index = 0;
104+
await foreach (var row in client.Query("SELECT * FROM nation"))
105+
{
106+
var nation = row[1];
107+
if (index == 0)
108+
{
109+
Assert.That(nation, Is.EqualTo("ALGERIA"));
110+
}
111+
112+
Trace.WriteLine(nation);
113+
index++;
114+
}
115+
}
116+
117+
[Test]
118+
public void QueryNotAuthorized()
119+
{
120+
using var client = new InfluxDBClient(new InfluxDBClientConfigs
121+
{
122+
HostUrl = Environment.GetEnvironmentVariable("FLIGHT_SQL_URL") ?? "https://localhost:31337",
123+
Database = "database",
124+
DisableServerCertificateValidation = true,
125+
AuthToken = "my-token"
126+
});
127+
128+
var ae = Assert.ThrowsAsync<RpcException>(async () =>
129+
{
130+
await foreach (var _ in client.Query("SELECT 1"))
131+
{
132+
}
133+
});
134+
135+
Assert.That(ae, Is.Not.Null);
136+
Assert.That(ae?.Message, Contains.Substring("Invalid bearer token"));
137+
}
138+
139+
[Test]
140+
public async Task Write()
141+
{
142+
using var client = new InfluxDBClient(new InfluxDBClientConfigs
143+
{
144+
HostUrl = Environment.GetEnvironmentVariable("INFLUXDB_URL") ?? "http://localhost:8086",
145+
Database = "my-bucket",
146+
Organization = "my-org",
147+
AuthToken = "my-token",
148+
DisableServerCertificateValidation = true
149+
});
150+
151+
await client.WriteRecordAsync("mem,type=used value=1.0");
152+
}
153+
154+
[Test]
155+
public async Task WriteDontFailForEmptyData()
156+
{
157+
using var client = new InfluxDBClient(new InfluxDBClientConfigs
158+
{
159+
HostUrl = Environment.GetEnvironmentVariable("INFLUXDB_URL") ?? "http://localhost:8086",
160+
Database = "my-bucket",
161+
Organization = "my-org",
162+
AuthToken = "my-token",
163+
DisableServerCertificateValidation = true
164+
});
165+
166+
await client.WritePointAsync(PointData.Measurement("cpu").AddTag("tag", "c"));
167+
}
168+
}

Client.Test/Client.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<PackageReference Include="NUnit.Analyzers" Version="3.6.1" />
2020
<PackageReference Include="coverlet.collector" Version="3.2.0" />
2121
<PackageReference Include="JunitXml.TestLogger" Version="3.0.124" />
22+
<PackageReference Include="WireMock.Net" Version="1.5.24" />
2223
</ItemGroup>
2324

2425
<ItemGroup>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
3+
namespace InfluxDB3.Client.Test;
4+
5+
public class InfluxDBClientQueryTest : MockServerTest
6+
{
7+
private InfluxDBClient _client;
8+
9+
[TearDown]
10+
public new void TearDown()
11+
{
12+
_client?.Dispose();
13+
}
14+
15+
[Test]
16+
public void AlreadyDisposed()
17+
{
18+
_client = new InfluxDBClient(MockServerUrl);
19+
_client.Dispose();
20+
var ae = Assert.ThrowsAsync<ObjectDisposedException>(async () =>
21+
{
22+
await foreach (var unused in _client.Query("SELECT 1"))
23+
{
24+
}
25+
});
26+
27+
Assert.That(ae, Is.Not.Null);
28+
Assert.That(ae.Message, Is.EqualTo("Cannot access a disposed object.\nObject name: 'InfluxDBClient'."));
29+
}
30+
31+
[Test]
32+
public void NotSpecifiedDatabase()
33+
{
34+
_client = new InfluxDBClient(MockServerUrl);
35+
var ae = Assert.Throws<InvalidOperationException>(() => { _client.QueryEnumerable("SELECT 1"); });
36+
37+
Assert.That(ae, Is.Not.Null);
38+
Assert.That(ae.Message, Is.EqualTo("Please specify the 'database' as a method parameter or use default configuration at 'InfluxDBClientConfigs.Database'."));
39+
}
40+
}

Client.Test/InfluxDBClientTest.cs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,35 @@
1+
using System;
2+
3+
// ReSharper disable ObjectCreationAsStatement
4+
// ReSharper disable AssignNullToNotNullAttribute
5+
16
namespace InfluxDB3.Client.Test;
27

38
public class InfluxDBClientTest
49
{
510
[Test]
6-
public void NotNull()
11+
public void Create()
712
{
8-
var client = new InfluxDBClient();
9-
client.Dummy();
13+
using var client = new InfluxDBClient("http://localhost:8086", organization: "org", database: "database");
1014

1115
Assert.That(client, Is.Not.Null);
1216
}
17+
18+
[Test]
19+
public void RequiredHost()
20+
{
21+
var ae = Assert.Throws<ArgumentException>(() => { new InfluxDBClient(hostUrl: null); });
22+
23+
Assert.That(ae, Is.Not.Null);
24+
Assert.That(ae.Message, Is.EqualTo("The hostname or IP address of the InfluxDB server has to be defined."));
25+
}
26+
27+
[Test]
28+
public void RequiredConfigs()
29+
{
30+
var ae = Assert.Throws<ArgumentException>(() => { new InfluxDBClient(null); });
31+
32+
Assert.That(ae, Is.Not.Null);
33+
Assert.That(ae.Message, Is.EqualTo("The configuration of the client has to be defined."));
34+
}
1335
}

0 commit comments

Comments
 (0)