/* * 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.update; import org.elasticsearch.action.update.UpdateRequestBuilder; import org.elasticsearch.action.update.UpdateResponse; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.test.ESIntegTestCase; import org.junit.Before; import java.io.IOException; import static org.hamcrest.Matchers.notNullValue; /** * Tests for noop updates. */ public class UpdateNoopIT extends ESIntegTestCase { public void testSingleField() throws Exception { updateAndCheckSource(1, fields("bar", "baz")); updateAndCheckSource(1, fields("bar", "baz")); updateAndCheckSource(2, fields("bar", "bir")); updateAndCheckSource(2, fields("bar", "bir")); updateAndCheckSource(3, fields("bar", "foo")); updateAndCheckSource(4, fields("bar", null)); updateAndCheckSource(4, fields("bar", null)); updateAndCheckSource(5, fields("bar", "foo")); // detect_noop defaults to true updateAndCheckSource(5, null, fields("bar", "foo")); assertEquals(4, totalNoopUpdates()); } public void testTwoFields() throws Exception { // Use random keys so we get random iteration order. String key1 = 1 + randomAlphaOfLength(3); String key2 = 2 + randomAlphaOfLength(3); String key3 = 3 + randomAlphaOfLength(3); updateAndCheckSource(1, fields(key1, "foo", key2, "baz")); updateAndCheckSource(1, fields(key1, "foo", key2, "baz")); updateAndCheckSource(2, fields(key1, "foo", key2, "bir")); updateAndCheckSource(2, fields(key1, "foo", key2, "bir")); updateAndCheckSource(3, fields(key1, "foo", key2, "foo")); updateAndCheckSource(4, fields(key1, "foo", key2, null)); updateAndCheckSource(4, fields(key1, "foo", key2, null)); updateAndCheckSource(5, fields(key1, "foo", key2, "foo")); updateAndCheckSource(6, fields(key1, null, key2, "foo")); updateAndCheckSource(6, fields(key1, null, key2, "foo")); updateAndCheckSource(7, fields(key1, null, key2, null)); updateAndCheckSource(7, fields(key1, null, key2, null)); updateAndCheckSource(8, fields(key1, null, key2, null, key3, null)); assertEquals(5, totalNoopUpdates()); } public void testArrayField() throws Exception { updateAndCheckSource(1, fields("bar", "baz")); updateAndCheckSource(2, fields("bar", new String[] {"baz", "bort"})); updateAndCheckSource(2, fields("bar", new String[] {"baz", "bort"})); updateAndCheckSource(3, fields("bar", "bir")); updateAndCheckSource(3, fields("bar", "bir")); updateAndCheckSource(4, fields("bar", new String[] {"baz", "bort"})); updateAndCheckSource(4, fields("bar", new String[] {"baz", "bort"})); updateAndCheckSource(5, fields("bar", new String[] {"bir", "bort"})); updateAndCheckSource(5, fields("bar", new String[] {"bir", "bort"})); updateAndCheckSource(6, fields("bar", new String[] {"bir", "for"})); updateAndCheckSource(6, fields("bar", new String[] {"bir", "for"})); updateAndCheckSource(7, fields("bar", new String[] {"bir", "for", "far"})); assertEquals(5, totalNoopUpdates()); } public void testMap() throws Exception { // Use random keys so we get variable iteration order. String key1 = 1 + randomAlphaOfLength(3); String key2 = 2 + randomAlphaOfLength(3); String key3 = 3 + randomAlphaOfLength(3); updateAndCheckSource(1, XContentFactory.jsonBuilder().startObject() .startObject("test") .field(key1, "foo") .field(key2, "baz") .endObject().endObject()); updateAndCheckSource(1, XContentFactory.jsonBuilder().startObject() .startObject("test") .field(key1, "foo") .field(key2, "baz") .endObject().endObject()); updateAndCheckSource(2, XContentFactory.jsonBuilder().startObject() .startObject("test") .field(key1, "foo") .field(key2, "bir") .endObject().endObject()); updateAndCheckSource(2, XContentFactory.jsonBuilder().startObject() .startObject("test") .field(key1, "foo") .field(key2, "bir") .endObject().endObject()); updateAndCheckSource(3, XContentFactory.jsonBuilder().startObject() .startObject("test") .field(key1, "foo") .field(key2, "foo") .endObject().endObject()); updateAndCheckSource(4, XContentFactory.jsonBuilder().startObject() .startObject("test") .field(key1, "foo") .field(key2, (Object) null) .endObject().endObject()); updateAndCheckSource(4, XContentFactory.jsonBuilder().startObject() .startObject("test") .field(key1, "foo") .field(key2, (Object) null) .endObject().endObject()); updateAndCheckSource(5, XContentFactory.jsonBuilder().startObject() .startObject("test") .field(key1, "foo") .field(key2, (Object) null) .field(key3, (Object) null) .endObject().endObject()); assertEquals(3, totalNoopUpdates()); } public void testMapAndField() throws Exception { updateAndCheckSource(1, XContentFactory.jsonBuilder().startObject() .field("f", "foo") .startObject("m") .field("mf1", "foo") .field("mf2", "baz") .endObject() .endObject()); updateAndCheckSource(1, XContentFactory.jsonBuilder().startObject() .field("f", "foo") .startObject("m") .field("mf1", "foo") .field("mf2", "baz") .endObject() .endObject()); updateAndCheckSource(2, XContentFactory.jsonBuilder().startObject() .field("f", "foo") .startObject("m") .field("mf1", "foo") .field("mf2", "bir") .endObject() .endObject()); updateAndCheckSource(2, XContentFactory.jsonBuilder().startObject() .field("f", "foo") .startObject("m") .field("mf1", "foo") .field("mf2", "bir") .endObject() .endObject()); updateAndCheckSource(3, XContentFactory.jsonBuilder().startObject() .field("f", "foo") .startObject("m") .field("mf1", "foo") .field("mf2", "foo") .endObject() .endObject()); updateAndCheckSource(4, XContentFactory.jsonBuilder().startObject() .field("f", "bar") .startObject("m") .field("mf1", "foo") .field("mf2", "foo") .endObject() .endObject()); updateAndCheckSource(4, XContentFactory.jsonBuilder().startObject() .field("f", "bar") .startObject("m") .field("mf1", "foo") .field("mf2", "foo") .endObject() .endObject()); updateAndCheckSource(5, XContentFactory.jsonBuilder().startObject() .field("f", "baz") .startObject("m") .field("mf1", "foo") .field("mf2", "foo") .endObject() .endObject()); updateAndCheckSource(6, XContentFactory.jsonBuilder().startObject() .field("f", "bop") .startObject("m") .field("mf1", "foo") .field("mf2", "foo") .endObject() .endObject()); assertEquals(3, totalNoopUpdates()); } /** * Totally empty requests are noop if and only if detect noops is true and * its true by default. */ public void testTotallyEmpty() throws Exception { updateAndCheckSource(1, XContentFactory.jsonBuilder().startObject() .field("f", "foo") .startObject("m") .field("mf1", "foo") .field("mf2", "baz") .endObject() .endObject()); update(true, 1, XContentFactory.jsonBuilder().startObject().endObject()); update(false, 2, XContentFactory.jsonBuilder().startObject().endObject()); update(null, 2, XContentFactory.jsonBuilder().startObject().endObject()); } private XContentBuilder fields(Object... fields) throws IOException { assertEquals("Fields must field1, value1, field2, value2, etc", 0, fields.length % 2); XContentBuilder builder = XContentFactory.jsonBuilder().startObject(); for (int i = 0; i < fields.length; i += 2) { builder.field((String) fields[i], fields[i + 1]); } builder.endObject(); return builder; } private void updateAndCheckSource(long expectedVersion, XContentBuilder xContentBuilder) { updateAndCheckSource(expectedVersion, true, xContentBuilder); } private void updateAndCheckSource(long expectedVersion, Boolean detectNoop, XContentBuilder xContentBuilder) { UpdateResponse updateResponse = update(detectNoop, expectedVersion, xContentBuilder); assertEquals(updateResponse.getGetResult().sourceRef().utf8ToString(), xContentBuilder.bytes().utf8ToString()); } private UpdateResponse update(Boolean detectNoop, long expectedVersion, XContentBuilder xContentBuilder) { UpdateRequestBuilder updateRequest = client().prepareUpdate("test", "type1", "1") .setDoc(xContentBuilder) .setDocAsUpsert(true) .setFields("_source"); if (detectNoop != null) { updateRequest.setDetectNoop(detectNoop); } UpdateResponse updateResponse = updateRequest.get(); assertThat(updateResponse.getGetResult(), notNullValue()); assertEquals(expectedVersion, updateResponse.getVersion()); return updateResponse; } private long totalNoopUpdates() { return client().admin().indices().prepareStats("test").setIndexing(true).get().getIndex("test").getTotal().getIndexing().getTotal() .getNoopUpdateCount(); } @Before public void setup() { createIndex("test"); ensureGreen(); } }