Browse Source

XContentTests : Insert random fields at random positions (#30867)

Currently AbstractXContentTestCase#testFromXContent appends random fields, but in
a fixed position. This PR shuffles all fields after the random fields have been appended, 
hence the random fields are actually added to random positions.
olcbean 7 years ago
parent
commit
334c255516

+ 25 - 13
test/framework/src/main/java/org/elasticsearch/test/AbstractXContentTestCase.java

@@ -54,21 +54,16 @@ public abstract class AbstractXContentTestCase<T extends ToXContent> extends EST
         for (int runs = 0; runs < numberOfTestRuns; runs++) {
             T testInstance = instanceSupplier.get();
             XContentType xContentType = randomFrom(XContentType.values());
-            BytesReference shuffled = toShuffledXContent(testInstance, xContentType, toXContentParams,false,
-                createParserFunction, shuffleFieldsExceptions);
-            BytesReference withRandomFields;
-            if (supportsUnknownFields) {
-                // we add a few random fields to check that parser is lenient on new fields
-                withRandomFields = XContentTestUtils.insertRandomFields(xContentType, shuffled, randomFieldsExcludeFilter, random());
-            } else {
-                withRandomFields = shuffled;
-            }
-            XContentParser parser = createParserFunction.apply(XContentFactory.xContent(xContentType), withRandomFields);
+            BytesReference shuffledContent = insertRandomFieldsAndShuffle(testInstance, xContentType, supportsUnknownFields,
+                    shuffleFieldsExceptions, randomFieldsExcludeFilter, createParserFunction, toXContentParams);
+            XContentParser parser = createParserFunction.apply(XContentFactory.xContent(xContentType), shuffledContent);
             T parsed = parseFunction.apply(parser);
             assertEqualsConsumer.accept(testInstance, parsed);
             if (assertToXContentEquivalence) {
-                assertToXContentEquivalent(shuffled, XContentHelper.toXContent(parsed, xContentType, toXContentParams, false),
-                    xContentType);
+                assertToXContentEquivalent(
+                        XContentHelper.toXContent(testInstance, xContentType, toXContentParams, false),
+                        XContentHelper.toXContent(parsed, xContentType, toXContentParams, false),
+                        xContentType);
             }
         }
     }
@@ -132,9 +127,26 @@ public abstract class AbstractXContentTestCase<T extends ToXContent> extends EST
     }
 
     /**
-     * Params that have to be provided when calling calling {@link ToXContent#toXContent(XContentBuilder, ToXContent.Params)}
+     * Params that have to be provided when calling {@link ToXContent#toXContent(XContentBuilder, ToXContent.Params)}
      */
     protected ToXContent.Params getToXContentParams() {
         return ToXContent.EMPTY_PARAMS;
     }
+
+    static BytesReference insertRandomFieldsAndShuffle(ToXContent testInstance, XContentType xContentType,
+            boolean supportsUnknownFields, String[] shuffleFieldsExceptions, Predicate<String> randomFieldsExcludeFilter,
+            CheckedBiFunction<XContent, BytesReference, XContentParser, IOException> createParserFunction,
+            ToXContent.Params toXContentParams) throws IOException {
+        BytesReference xContent = XContentHelper.toXContent(testInstance, xContentType, toXContentParams, false);
+        BytesReference withRandomFields;
+        if (supportsUnknownFields) {
+            // add a few random fields to check that the parser is lenient on new fields
+            withRandomFields = XContentTestUtils.insertRandomFields(xContentType, xContent, randomFieldsExcludeFilter, random());
+        } else {
+            withRandomFields = xContent;
+        }
+        XContentParser parserWithRandonFields = createParserFunction.apply(XContentFactory.xContent(xContentType), withRandomFields);
+        return BytesReference.bytes(ESTestCase.shuffleXContent(parserWithRandonFields, false, shuffleFieldsExceptions));
+    }
+
 }

+ 65 - 0
test/framework/src/test/java/org/elasticsearch/test/AbstractXContentTestCaseTests.java

@@ -0,0 +1,65 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.test;
+
+import com.carrotsearch.randomizedtesting.RandomizedContext;
+
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.common.xcontent.XContentType;
+
+import java.io.IOException;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.not;
+
+public class AbstractXContentTestCaseTests extends ESTestCase {
+
+    public void testInsertRandomFieldsAndShuffle() throws Exception {
+        TestInstance t = new TestInstance();
+        BytesReference insertRandomFieldsAndShuffle = RandomizedContext.current().runWithPrivateRandomness(1,
+                () -> AbstractXContentTestCase.insertRandomFieldsAndShuffle(t, XContentType.JSON, true, new String[] {}, null,
+                        this::createParser, ToXContent.EMPTY_PARAMS));
+        try (XContentParser parser = createParser(XContentType.JSON.xContent(), insertRandomFieldsAndShuffle)) {
+            Map<String, Object> mapOrdered = parser.mapOrdered();
+            assertThat(mapOrdered.size(), equalTo(2));
+            assertThat(mapOrdered.keySet().iterator().next(), not(equalTo("field")));
+        }
+    }
+
+    private class TestInstance implements ToXContentObject {
+
+        @Override
+        public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+            builder.startObject();
+            {
+                builder.field("field", 1);
+            }
+            builder.endObject();
+            return builder;
+        }
+
+    }
+
+}