@Test
  public void testUnassignedShardAndEmptyNodesInRoutingTable() throws Exception {
    internalCluster().startNode();
    createIndex("a");
    ensureSearchable("a");
    ClusterState current = clusterService().state();
    GatewayAllocator allocator = internalCluster().getInstance(GatewayAllocator.class);

    AllocationDeciders allocationDeciders =
        new AllocationDeciders(Settings.EMPTY, new AllocationDecider[0]);
    RoutingNodes routingNodes =
        new RoutingNodes(
            ClusterState.builder(current)
                .routingTable(
                    RoutingTable.builder(current.routingTable())
                        .remove("a")
                        .addAsRecovery(current.metaData().index("a")))
                .nodes(DiscoveryNodes.EMPTY_NODES)
                .build());
    ClusterInfo clusterInfo =
        new ClusterInfo(ImmutableMap.<String, DiskUsage>of(), ImmutableMap.<String, Long>of());

    RoutingAllocation routingAllocation =
        new RoutingAllocation(allocationDeciders, routingNodes, current.nodes(), clusterInfo);
    allocator.allocateUnassigned(routingAllocation);
  }
  @Ignore("https://github.com/elasticsearch/elasticsearch/issues/9904")
  @Test
  public void testShapeFilterWithRandomGeoCollection() throws Exception {
    // Create a random geometry collection.
    GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(getRandom());

    logger.info("Created Random GeometryCollection containing " + gcb.numShapes() + " shapes");

    createIndex("randshapes");
    assertAcked(prepareCreate("test").addMapping("type", "location", "type=geo_shape"));

    XContentBuilder docSource =
        gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject();
    indexRandom(true, client().prepareIndex("test", "type", "1").setSource(docSource));

    ensureSearchable("test");

    ShapeBuilder filterShape = (gcb.getShapeAt(randomIntBetween(0, gcb.numShapes() - 1)));

    GeoShapeFilterBuilder filter =
        FilterBuilders.geoShapeFilter("location", filterShape, ShapeRelation.INTERSECTS);
    SearchResponse result =
        client()
            .prepareSearch("test")
            .setQuery(QueryBuilders.matchAllQuery())
            .setPostFilter(filter)
            .get();
    assertSearchResponse(result);
    assertHitCount(result, 1);
  }
  @Test
  public void testShapeFilterWithDefinedGeoCollection() throws Exception {
    createIndex("shapes");
    assertAcked(prepareCreate("test").addMapping("type", "location", "type=geo_shape"));

    XContentBuilder docSource =
        jsonBuilder()
            .startObject()
            .startObject("location")
            .field("type", "geometrycollection")
            .startArray("geometries")
            .startObject()
            .field("type", "point")
            .startArray("coordinates")
            .value(100.0)
            .value(0.0)
            .endArray()
            .endObject()
            .startObject()
            .field("type", "linestring")
            .startArray("coordinates")
            .startArray()
            .value(101.0)
            .value(0.0)
            .endArray()
            .startArray()
            .value(102.0)
            .value(1.0)
            .endArray()
            .endArray()
            .endObject()
            .endArray()
            .endObject()
            .endObject();
    indexRandom(true, client().prepareIndex("test", "type", "1").setSource(docSource));
    ensureSearchable("test");

    GeoShapeFilterBuilder filter =
        FilterBuilders.geoShapeFilter(
            "location",
            ShapeBuilder.newGeometryCollection()
                .polygon(
                    ShapeBuilder.newPolygon()
                        .point(99.0, -1.0)
                        .point(99.0, 3.0)
                        .point(103.0, 3.0)
                        .point(103.0, -1.0)
                        .point(99.0, -1.0)),
            ShapeRelation.INTERSECTS);
    SearchResponse result =
        client()
            .prepareSearch("test")
            .setQuery(QueryBuilders.matchAllQuery())
            .setPostFilter(filter)
            .get();
    assertSearchResponse(result);
    assertHitCount(result, 1);
    filter =
        FilterBuilders.geoShapeFilter(
            "location",
            ShapeBuilder.newGeometryCollection()
                .polygon(
                    ShapeBuilder.newPolygon()
                        .point(199.0, -11.0)
                        .point(199.0, 13.0)
                        .point(193.0, 13.0)
                        .point(193.0, -11.0)
                        .point(199.0, -11.0)),
            ShapeRelation.INTERSECTS);
    result =
        client()
            .prepareSearch("test")
            .setQuery(QueryBuilders.matchAllQuery())
            .setPostFilter(filter)
            .get();
    assertSearchResponse(result);
    assertHitCount(result, 0);
    filter =
        FilterBuilders.geoShapeFilter(
            "location",
            ShapeBuilder.newGeometryCollection()
                .polygon(
                    ShapeBuilder.newPolygon()
                        .point(99.0, -1.0)
                        .point(99.0, 3.0)
                        .point(103.0, 3.0)
                        .point(103.0, -1.0)
                        .point(99.0, -1.0))
                .polygon(
                    ShapeBuilder.newPolygon()
                        .point(199.0, -11.0)
                        .point(199.0, 13.0)
                        .point(193.0, 13.0)
                        .point(193.0, -11.0)
                        .point(199.0, -11.0)),
            ShapeRelation.INTERSECTS);
    result =
        client()
            .prepareSearch("test")
            .setQuery(QueryBuilders.matchAllQuery())
            .setPostFilter(filter)
            .get();
    assertSearchResponse(result);
    assertHitCount(result, 1);
  }
  @Test
  public void testShapeFetchingPath() throws Exception {
    createIndex("shapes");
    assertAcked(prepareCreate("test").addMapping("type", "location", "type=geo_shape"));

    String location =
        "\"location\" : {\"type\":\"polygon\", \"coordinates\":[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]}";
    indexRandom(
        true,
        client()
            .prepareIndex("shapes", "type", "1")
            .setSource(
                String.format(
                    Locale.ROOT,
                    "{ %s, \"1\" : { %s, \"2\" : { %s, \"3\" : { %s } }} }",
                    location,
                    location,
                    location,
                    location)),
        client()
            .prepareIndex("test", "type", "1")
            .setSource(
                jsonBuilder()
                    .startObject()
                    .startObject("location")
                    .field("type", "polygon")
                    .startArray("coordinates")
                    .startArray()
                    .startArray()
                    .value(-20)
                    .value(-20)
                    .endArray()
                    .startArray()
                    .value(20)
                    .value(-20)
                    .endArray()
                    .startArray()
                    .value(20)
                    .value(20)
                    .endArray()
                    .startArray()
                    .value(-20)
                    .value(20)
                    .endArray()
                    .startArray()
                    .value(-20)
                    .value(-20)
                    .endArray()
                    .endArray()
                    .endArray()
                    .endObject()
                    .endObject()));
    ensureSearchable("test", "shapes");

    GeoShapeFilterBuilder filter =
        FilterBuilders.geoShapeFilter("location", "1", "type", ShapeRelation.INTERSECTS)
            .indexedShapeIndex("shapes")
            .indexedShapePath("location");
    SearchResponse result =
        client()
            .prepareSearch("test")
            .setQuery(QueryBuilders.matchAllQuery())
            .setPostFilter(filter)
            .get();
    assertSearchResponse(result);
    assertHitCount(result, 1);
    filter =
        FilterBuilders.geoShapeFilter("location", "1", "type", ShapeRelation.INTERSECTS)
            .indexedShapeIndex("shapes")
            .indexedShapePath("1.location");
    result =
        client()
            .prepareSearch("test")
            .setQuery(QueryBuilders.matchAllQuery())
            .setPostFilter(filter)
            .get();
    assertSearchResponse(result);
    assertHitCount(result, 1);
    filter =
        FilterBuilders.geoShapeFilter("location", "1", "type", ShapeRelation.INTERSECTS)
            .indexedShapeIndex("shapes")
            .indexedShapePath("1.2.location");
    result =
        client()
            .prepareSearch("test")
            .setQuery(QueryBuilders.matchAllQuery())
            .setPostFilter(filter)
            .get();
    assertSearchResponse(result);
    assertHitCount(result, 1);
    filter =
        FilterBuilders.geoShapeFilter("location", "1", "type", ShapeRelation.INTERSECTS)
            .indexedShapeIndex("shapes")
            .indexedShapePath("1.2.3.location");
    result =
        client()
            .prepareSearch("test")
            .setQuery(QueryBuilders.matchAllQuery())
            .setPostFilter(filter)
            .get();
    assertSearchResponse(result);
    assertHitCount(result, 1);

    // now test the query variant
    GeoShapeQueryBuilder query =
        QueryBuilders.geoShapeQuery("location", "1", "type")
            .indexedShapeIndex("shapes")
            .indexedShapePath("location");
    result = client().prepareSearch("test").setQuery(query).get();
    assertSearchResponse(result);
    assertHitCount(result, 1);
    query =
        QueryBuilders.geoShapeQuery("location", "1", "type")
            .indexedShapeIndex("shapes")
            .indexedShapePath("1.location");
    result = client().prepareSearch("test").setQuery(query).get();
    assertSearchResponse(result);
    assertHitCount(result, 1);
    query =
        QueryBuilders.geoShapeQuery("location", "1", "type")
            .indexedShapeIndex("shapes")
            .indexedShapePath("1.2.location");
    result = client().prepareSearch("test").setQuery(query).get();
    assertSearchResponse(result);
    assertHitCount(result, 1);
    query =
        QueryBuilders.geoShapeQuery("location", "1", "type")
            .indexedShapeIndex("shapes")
            .indexedShapePath("1.2.3.location");
    result = client().prepareSearch("test").setQuery(query).get();
    assertSearchResponse(result);
    assertHitCount(result, 1);
  }
  @Test
  public void testNoMasterActions_writeMasterBlock() throws Exception {
    Settings settings =
        settingsBuilder()
            .put("discovery.type", "zen")
            .put("action.auto_create_index", false)
            .put("discovery.zen.minimum_master_nodes", 2)
            .put("discovery.zen.ping_timeout", "200ms")
            .put("discovery.initial_state_timeout", "500ms")
            .put(DiscoverySettings.NO_MASTER_BLOCK, "write")
            .build();

    internalCluster().startNode(settings);
    // start a second node, create an index, and then shut it down so we have no master block
    internalCluster().startNode(settings);
    prepareCreate("test1").setSettings(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1).get();
    prepareCreate("test2")
        .setSettings(
            IndexMetaData.SETTING_NUMBER_OF_SHARDS, 2, IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)
        .get();
    client().admin().cluster().prepareHealth("_all").setWaitForGreenStatus().get();
    client().prepareIndex("test1", "type1", "1").setSource("field", "value1").get();
    client().prepareIndex("test2", "type1", "1").setSource("field", "value1").get();
    refresh();

    ensureSearchable("test1", "test2");

    ClusterStateResponse clusterState = client().admin().cluster().prepareState().get();
    logger.info("Cluster state:\n" + clusterState.getState().prettyPrint());

    internalCluster().stopRandomDataNode();
    assertThat(
        awaitBusy(
            new Predicate<Object>() {
              public boolean apply(Object o) {
                ClusterState state =
                    client().admin().cluster().prepareState().setLocal(true).get().getState();
                return state.blocks().hasGlobalBlock(DiscoverySettings.NO_MASTER_BLOCK_ID);
              }
            }),
        equalTo(true));

    GetResponse getResponse = client().prepareGet("test1", "type1", "1").get();
    assertExists(getResponse);

    CountResponse countResponse = client().prepareCount("test1").get();
    assertHitCount(countResponse, 1l);

    SearchResponse searchResponse = client().prepareSearch("test1").get();
    assertHitCount(searchResponse, 1l);

    countResponse = client().prepareCount("test2").get();
    assertThat(countResponse.getTotalShards(), equalTo(2));
    assertThat(countResponse.getSuccessfulShards(), equalTo(1));

    TimeValue timeout = TimeValue.timeValueMillis(200);
    long now = System.currentTimeMillis();
    try {
      client()
          .prepareUpdate("test1", "type1", "1")
          .setDoc("field", "value2")
          .setTimeout(timeout)
          .get();
      fail("Expected ClusterBlockException");
    } catch (ClusterBlockException e) {
      assertThat(System.currentTimeMillis() - now, greaterThan(timeout.millis() - 50));
      assertThat(e.status(), equalTo(RestStatus.SERVICE_UNAVAILABLE));
    }

    now = System.currentTimeMillis();
    try {
      client()
          .prepareIndex("test1", "type1", "1")
          .setSource(XContentFactory.jsonBuilder().startObject().endObject())
          .setTimeout(timeout)
          .get();
      fail("Expected ClusterBlockException");
    } catch (ClusterBlockException e) {
      assertThat(System.currentTimeMillis() - now, greaterThan(timeout.millis() - 50));
      assertThat(e.status(), equalTo(RestStatus.SERVICE_UNAVAILABLE));
    }

    internalCluster().startNode(settings);
    client().admin().cluster().prepareHealth().setWaitForGreenStatus().setWaitForNodes("2").get();
  }