Skip to content

Commit b1217a8

Browse files
committed
added integration tests for booleans that assert that our boolean logic finds the same number of documents in elasticsearch as it does against an in memory List<Doc>
1 parent 91af12a commit b1217a8

File tree

7 files changed

+147
-5
lines changed

7 files changed

+147
-5
lines changed

src/Nest/Document/Multiple/Bulk/BulkRequest.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ public BulkDescriptor Create<T>(Func<BulkCreateDescriptor<T>, BulkCreateDescript
3333
public BulkDescriptor CreateMany<T>(IEnumerable<T> @objects, Func<BulkCreateDescriptor<T>, T, BulkCreateDescriptor<T>> bulkCreateSelector = null) where T : class =>
3434
Assign(a => @objects.ForEach(o => AddOperation(bulkCreateSelector.InvokeOrDefault(new BulkCreateDescriptor<T>().Document(o), o))));
3535

36+
public BulkDescriptor Index<T>(T obj, Func<BulkIndexDescriptor<T>, BulkIndexDescriptor<T>> bulkIndexSelector = null) where T : class =>
37+
Assign(a => AddOperation(bulkIndexSelector.InvokeOrDefault(new BulkIndexDescriptor<T>()).Document(obj)));
38+
3639
public BulkDescriptor Index<T>(Func<BulkIndexDescriptor<T>, BulkIndexDescriptor<T>> bulkIndexSelector) where T : class =>
3740
Assign(a => AddOperation(bulkIndexSelector?.Invoke(new BulkIndexDescriptor<T>())));
3841

@@ -43,6 +46,9 @@ public BulkDescriptor Index<T>(Func<BulkIndexDescriptor<T>, BulkIndexDescriptor<
4346
/// <param name="bulkIndexSelector">A func called on each object to describe the individual index operation</param>
4447
public BulkDescriptor IndexMany<T>(IEnumerable<T> @objects, Func<BulkIndexDescriptor<T>, T, BulkIndexDescriptor<T>> bulkIndexSelector = null) where T : class =>
4548
Assign(a => @objects.ForEach(o => AddOperation(bulkIndexSelector.InvokeOrDefault(new BulkIndexDescriptor<T>().Document(o), o))));
49+
50+
public BulkDescriptor Delete<T>(T obj, Func<BulkDeleteDescriptor<T>, BulkDeleteDescriptor<T>> bulkDeleteSelector = null) where T : class =>
51+
Assign(a => AddOperation(bulkDeleteSelector.InvokeOrDefault(new BulkDeleteDescriptor<T>().Document(obj))));
4652

4753
public BulkDescriptor Delete<T>(Func<BulkDeleteDescriptor<T>, BulkDeleteDescriptor<T>> bulkDeleteSelector) where T : class =>
4854
Assign(a => AddOperation(bulkDeleteSelector?.Invoke(new BulkDeleteDescriptor<T>())));

src/Tests/ClientConcepts/ConnectionPooling/Sniffing/RoleDetection.doc.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ public async Task DetectsDataNodes()
7979
}
8080
}
8181

82-
8382
[CollectionDefinition(IntegrationContext.SniffRoleDetection)]
8483
public class SniffRoleDetectionCluster : ClusterBase, ICollectionFixture<SniffRoleDetectionCluster>
8584
{
@@ -144,4 +143,4 @@ private Node AssertSniffResponse()
144143
}
145144
}
146145

147-
}
146+
}

src/Tests/Framework/Integration/IntegrationContext.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public static class IntegrationContext
88

99
public const string OwnIndex = "OwnIndex Cluster";
1010
public const string Reindex = "Reindex Cluster";
11-
public const string SniffRoleDetection = "SniffRoleDetection";
11+
public const string SniffRoleDetection = "SniffRoleDetection";
12+
public const string Bool = "Bool Cluster";
1213
}
1314
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using Elasticsearch.Net;
7+
using FluentAssertions;
8+
using Nest;
9+
using Newtonsoft.Json;
10+
using Newtonsoft.Json.Converters;
11+
using Tests.Framework;
12+
using Tests.Framework.Integration;
13+
using Xunit;
14+
using A = Tests.QueryDsl.BoolDsl.BoolCluster.A;
15+
using E = Tests.QueryDsl.BoolDsl.BoolCluster.E;
16+
using static Nest.Infer;
17+
18+
19+
namespace Tests.QueryDsl.BoolDsl
20+
{
21+
22+
internal static class BoolDslTestExtensions
23+
{
24+
public static QueryContainer Id(this QueryContainerDescriptor<A> q, int id) => q.Term(p => p.Id, id);
25+
public static QueryContainer O(this QueryContainerDescriptor<A> q, E option) => q.Term(p => p.Option, option);
26+
}
27+
[CollectionDefinition(IntegrationContext.Bool)]
28+
public class BoolCluster : ClusterBase, ICollectionFixture<BoolCluster>
29+
{
30+
//TODO discuss make this default?
31+
[JsonConverter(typeof(StringEnumConverter))]
32+
public enum E { Option1, Option2 }
33+
34+
public class A
35+
{
36+
public int Id { get; set; }
37+
public E Option { get; set; }
38+
39+
private static E[] Options = new[] { E.Option1, E.Option2 };
40+
public static IList<A> Documents => Enumerable.Range(0, 20).Select(i => new A { Id = i + 1, Option = Options[i % 2] }).ToList();
41+
}
42+
43+
public override void Boostrap()
44+
{
45+
var client = this.Node.Client();
46+
var index = client.CreateIndex(Index<A>(), i => i
47+
.Mappings(map => map
48+
.Map<A>(m => m
49+
.AutoMap()
50+
.Properties(props => props
51+
.String(s => s.Name(p => p.Option).NotAnalyzed())
52+
)
53+
)
54+
)
55+
);
56+
var bulkResponse = client.Bulk(b => b.IndexMany(A.Documents));
57+
if (!bulkResponse.IsValid) throw new ApplicationException("Could not bootstrap bool cluster, bulk was invalid");
58+
client.Refresh(Indices<A>());
59+
}
60+
}
61+
62+
[Collection(IntegrationContext.Bool)]
63+
public class BoolsInPractice
64+
{
65+
66+
private readonly BoolCluster _cluster;
67+
private IConnectionSettingsValues _settings;
68+
69+
public BoolsInPractice(BoolCluster cluster)
70+
{
71+
this._cluster = cluster;
72+
}
73+
74+
private async Task Bool(
75+
Func<A, bool> programmatic,
76+
Func<QueryContainerDescriptor<A>, QueryContainer> fluentQuery,
77+
QueryContainer initializerQuery,
78+
int expectedCount
79+
)
80+
{
81+
var documents = A.Documents.Where(programmatic).ToList();
82+
documents.Count().Should().Be(expectedCount, " filtering the documents in memory did not yield the expected count");
83+
84+
var client = this._cluster.Node.Client();
85+
86+
var fluent = client.Search<A>(s => s.Query(fluentQuery));
87+
var fluentAsync = await client.SearchAsync<A>(s => s.Query(fluentQuery));
88+
89+
var initializer = client.Search<A>(new SearchRequest<A> { Query = initializerQuery });
90+
var initializerAsync = await client.SearchAsync<A>(new SearchRequest<A> { Query = initializerQuery });
91+
92+
var responses = new[] { fluent, fluentAsync, initializer, initializerAsync };
93+
foreach (var response in responses)
94+
{
95+
response.IsValid.Should().BeTrue();
96+
response.Total.Should().Be(expectedCount);
97+
}
98+
}
99+
100+
private TermQuery Id(int id) => new TermQuery { Field = "id", Value = id };
101+
private TermQuery O(E option) => new TermQuery { Field = "option", Value = option };
102+
103+
[I]
104+
public async Task CompareBoolQueryTranslationsToRealBooleanLogic()
105+
{
106+
await Bool(
107+
a => a.Id == 1 && a.Option == E.Option1,
108+
a => a.Id(1) && a.O(E.Option1),
109+
Id(1) && O(E.Option1),
110+
expectedCount: 1
111+
);
112+
113+
await Bool(
114+
a => a.Id == 1 || a.Id == 2 || a.Id == 3 || a.Id == 4,
115+
a => +a.Id(1) || +a.Id(2) || +a.Id(3) || +a.Id(4),
116+
+Id(1) || +Id(2) || +Id(3) || +Id(4),
117+
expectedCount: 4
118+
);
119+
120+
await Bool(
121+
a => a.Id == 1 || a.Id == 2 || a.Id == 3 || a.Id == 4 && (a.Option != E.Option1 || a.Option == E.Option2),
122+
a => +a.Id(1) || +a.Id(2) || +a.Id(3) || +a.Id(4) && (!a.O(E.Option1) || a.O(E.Option2)),
123+
+Id(1) || +Id(2) || +Id(3) || +Id(4) && (!O(E.Option1) || O(E.Option2)),
124+
expectedCount: 4
125+
);
126+
127+
await Bool(
128+
a => a.Id == 1 || a.Id == 2 || a.Id == 3 || a.Id == 4 && a.Option != E.Option1 || a.Option == E.Option2,
129+
a => +a.Id(1) || +a.Id(2) || +a.Id(3) || +a.Id(4) && !a.O(E.Option1) || a.O(E.Option2),
130+
+Id(1) || +Id(2) || +Id(3) || +Id(4) && !O(E.Option1) || O(E.Option2),
131+
expectedCount: 12
132+
);
133+
}
134+
}
135+
}

src/Tests/QueryDsl/Compound/Bool/BoolDslComplexQueryUsageTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ private void AssertShape(IQueryContainer container)
135135
complexBool.Should().NotBeNull();
136136
//complex bool is 3 ors and the next simple nested or bool query also has 3 should clauses
137137
//this can be rewritten to one boolquery with 6 clauses
138-
complexBool.Should.Should().HaveCount(5);
138+
complexBool.Should.Should().HaveCount(6);
139139

140140
//inner must nots
141141
var mustNotsBool = (complexBool.Should.Cast<IQueryContainer>().FirstOrDefault(q => q.Bool != null && q.Bool.MustNot != null))?.Bool;

src/Tests/Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@
370370
<Compile Include="Modules\SnapshotAndRestore\Snapshot\SnapshotStatus\SnapshotStatusUrlTests.cs" />
371371
<Compile Include="Modules\SnapshotAndRestore\Snapshot\Snapshot\SnapshotApiTests.cs" />
372372
<Compile Include="Modules\SnapshotAndRestore\Snapshot\Snapshot\SnapshotUrlTests.cs" />
373+
<Compile Include="QueryDsl\BoolDsl\BoolApiTests.cs" />
373374
<Compile Include="QueryDsl\BoolDsl\BoolDsl.doc.cs" />
374375
<Compile Include="QueryDsl\BoolDsl\Operators\UnaryAddOperatorUsageTests.cs" />
375376
<Compile Include="QueryDsl\BoolDsl\Operators\NotOperatorUsageTests.cs" />

src/Tests/tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# mode either u (unit test), i (integration test) or m (mixed mode)
2-
mode: u
2+
mode: i
33
# the elasticsearch version that should be started
44
elasticsearch_version: 2.0.1
55
# whether we want to forcefully reseed on the node, if you are starting the tests with a node already running

0 commit comments

Comments
 (0)