From 5a859b9054e4a79905f620a735d3b679b2df60d5 Mon Sep 17 00:00:00 2001 From: gmarz Date: Tue, 24 May 2016 14:19:17 -0400 Subject: [PATCH] Fix double evaluation of IEnumerable methods The ToListOrNullIfEmpty() extension method called .Any() and .ToList() which both evaluate the IEnumerable. This caused funcs to be executed twice when applied to an IEnumerable>. Closes #2101 --- .../Extensions/Extensions.cs | 7 ++- src/Tests/Reproduce/GithubIssue2101.cs | 51 +++++++++++++++++++ src/Tests/Tests.csproj | 1 + src/Tests/tests.yaml | 2 +- 4 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 src/Tests/Reproduce/GithubIssue2101.cs diff --git a/src/Nest/CommonAbstractions/Extensions/Extensions.cs b/src/Nest/CommonAbstractions/Extensions/Extensions.cs index 5370364c3cd..bf7352cb5e2 100644 --- a/src/Nest/CommonAbstractions/Extensions/Extensions.cs +++ b/src/Nest/CommonAbstractions/Extensions/Extensions.cs @@ -161,8 +161,11 @@ internal static void ForEach(this IEnumerable enumerable, Action handle foreach (T item in enumerable) handler(item); } - internal static List ToListOrNullIfEmpty(this IEnumerable enumerable) => - enumerable.HasAny() ? enumerable.ToList() : null; + internal static List ToListOrNullIfEmpty(this IEnumerable enumerable) + { + var list = enumerable?.ToList(); + return list.HasAny() ? list : null; + } internal static void AddIfNotNull(this IList list, T item) where T : class { diff --git a/src/Tests/Reproduce/GithubIssue2101.cs b/src/Tests/Reproduce/GithubIssue2101.cs new file mode 100644 index 00000000000..cba8cf1ab9a --- /dev/null +++ b/src/Tests/Reproduce/GithubIssue2101.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Elasticsearch.Net; +using Nest; +using FluentAssertions; +using Tests.Framework; + +namespace Tests.Reproduce +{ + public class GithubIssue2101 + { + + [U] + public void BoolClausesShouldEvaluateOnlyOnce() + { + var must = 0; + var mustNot = 0; + var should = 0; + var filter = 0; + + new BoolQueryDescriptor() + .Must(m => + { + must++; + return m; + }) + .MustNot(mn => + { + mustNot++; + return mn; + }) + .Should(sh => + { + should++; + return sh; + }) + .Filter(f => + { + filter++; + return f; + }); + + filter.Should().Be(1); + should.Should().Be(1); + must.Should().Be(1); + mustNot.Should().Be(1); + } + } +} diff --git a/src/Tests/Tests.csproj b/src/Tests/Tests.csproj index 0dd7b1011fb..c8437ba0941 100644 --- a/src/Tests/Tests.csproj +++ b/src/Tests/Tests.csproj @@ -560,6 +560,7 @@ + diff --git a/src/Tests/tests.yaml b/src/Tests/tests.yaml index bb8ea0f52a5..bed985ced67 100644 --- a/src/Tests/tests.yaml +++ b/src/Tests/tests.yaml @@ -1,5 +1,5 @@ # mode either u (unit test), i (integration test) or m (mixed mode) -mode: m +mode: u # the elasticsearch version that should be started elasticsearch_version: 2.3.0 # whether we want to forcefully reseed on the node, if you are starting the tests with a node already running