public void testDeepScrollingDoesNotBlowUp() throws Exception {
    client()
        .prepareIndex("index", "type", "1")
        .setSource("field", "value")
        .setRefresh(true)
        .execute()
        .get();

    for (SearchType searchType : SearchType.values()) {
      SearchRequestBuilder builder =
          client()
              .prepareSearch("index")
              .setSearchType(searchType)
              .setQuery(QueryBuilders.matchAllQuery())
              .setSize(Integer.MAX_VALUE)
              .setScroll("1m");

      SearchResponse response = builder.execute().actionGet();
      try {
        ElasticsearchAssertions.assertHitCount(response, 1l);
      } finally {
        String scrollId = response.getScrollId();
        if (scrollId != null) {
          clearScroll(scrollId);
        }
      }
    }
  }
  @Test
  public void testScrollAndUpdateIndex() throws Exception {
    client()
        .admin()
        .indices()
        .prepareCreate("test")
        .setSettings(Settings.settingsBuilder().put("index.number_of_shards", 5))
        .execute()
        .actionGet();
    client()
        .admin()
        .cluster()
        .prepareHealth()
        .setWaitForEvents(Priority.LANGUID)
        .setWaitForGreenStatus()
        .execute()
        .actionGet();

    for (int i = 0; i < 500; i++) {
      client()
          .prepareIndex("test", "tweet", Integer.toString(i))
          .setSource(
              jsonBuilder()
                  .startObject()
                  .field("user", "kimchy")
                  .field("postDate", System.currentTimeMillis())
                  .field("message", "test")
                  .endObject())
          .execute()
          .actionGet();
    }

    client().admin().indices().prepareRefresh().execute().actionGet();

    assertThat(
        client().prepareCount().setQuery(matchAllQuery()).execute().actionGet().getCount(),
        equalTo(500l));
    assertThat(
        client()
            .prepareCount()
            .setQuery(termQuery("message", "test"))
            .execute()
            .actionGet()
            .getCount(),
        equalTo(500l));
    assertThat(
        client()
            .prepareCount()
            .setQuery(termQuery("message", "test"))
            .execute()
            .actionGet()
            .getCount(),
        equalTo(500l));
    assertThat(
        client()
            .prepareCount()
            .setQuery(termQuery("message", "update"))
            .execute()
            .actionGet()
            .getCount(),
        equalTo(0l));
    assertThat(
        client()
            .prepareCount()
            .setQuery(termQuery("message", "update"))
            .execute()
            .actionGet()
            .getCount(),
        equalTo(0l));

    SearchResponse searchResponse =
        client()
            .prepareSearch()
            .setQuery(queryStringQuery("user:kimchy"))
            .setSize(35)
            .setScroll(TimeValue.timeValueMinutes(2))
            .addSort("postDate", SortOrder.ASC)
            .execute()
            .actionGet();
    try {
      do {
        for (SearchHit searchHit : searchResponse.getHits().hits()) {
          Map<String, Object> map = searchHit.sourceAsMap();
          map.put("message", "update");
          client()
              .prepareIndex("test", "tweet", searchHit.id())
              .setSource(map)
              .execute()
              .actionGet();
        }
        searchResponse =
            client()
                .prepareSearchScroll(searchResponse.getScrollId())
                .setScroll(TimeValue.timeValueMinutes(2))
                .execute()
                .actionGet();
      } while (searchResponse.getHits().hits().length > 0);

      client().admin().indices().prepareRefresh().execute().actionGet();
      assertThat(
          client().prepareCount().setQuery(matchAllQuery()).execute().actionGet().getCount(),
          equalTo(500l));
      assertThat(
          client()
              .prepareCount()
              .setQuery(termQuery("message", "test"))
              .execute()
              .actionGet()
              .getCount(),
          equalTo(0l));
      assertThat(
          client()
              .prepareCount()
              .setQuery(termQuery("message", "test"))
              .execute()
              .actionGet()
              .getCount(),
          equalTo(0l));
      assertThat(
          client()
              .prepareCount()
              .setQuery(termQuery("message", "update"))
              .execute()
              .actionGet()
              .getCount(),
          equalTo(500l));
      assertThat(
          client()
              .prepareCount()
              .setQuery(termQuery("message", "update"))
              .execute()
              .actionGet()
              .getCount(),
          equalTo(500l));
    } finally {
      clearScroll(searchResponse.getScrollId());
    }
  }
  @Test
  public void testSimpleScrollQueryThenFetch() throws Exception {
    client()
        .admin()
        .indices()
        .prepareCreate("test")
        .setSettings(Settings.settingsBuilder().put("index.number_of_shards", 3))
        .execute()
        .actionGet();
    client()
        .admin()
        .cluster()
        .prepareHealth()
        .setWaitForEvents(Priority.LANGUID)
        .setWaitForGreenStatus()
        .execute()
        .actionGet();

    client()
        .admin()
        .cluster()
        .prepareHealth()
        .setWaitForEvents(Priority.LANGUID)
        .setWaitForGreenStatus()
        .execute()
        .actionGet();

    for (int i = 0; i < 100; i++) {
      client()
          .prepareIndex("test", "type1", Integer.toString(i))
          .setSource(jsonBuilder().startObject().field("field", i).endObject())
          .execute()
          .actionGet();
    }

    client().admin().indices().prepareRefresh().execute().actionGet();

    SearchResponse searchResponse =
        client()
            .prepareSearch()
            .setQuery(matchAllQuery())
            .setSize(35)
            .setScroll(TimeValue.timeValueMinutes(2))
            .addSort("field", SortOrder.ASC)
            .execute()
            .actionGet();
    try {
      long counter = 0;

      assertThat(searchResponse.getHits().getTotalHits(), equalTo(100l));
      assertThat(searchResponse.getHits().hits().length, equalTo(35));
      for (SearchHit hit : searchResponse.getHits()) {
        assertThat(((Number) hit.sortValues()[0]).longValue(), equalTo(counter++));
      }

      searchResponse =
          client()
              .prepareSearchScroll(searchResponse.getScrollId())
              .setScroll(TimeValue.timeValueMinutes(2))
              .execute()
              .actionGet();

      assertThat(searchResponse.getHits().getTotalHits(), equalTo(100l));
      assertThat(searchResponse.getHits().hits().length, equalTo(35));
      for (SearchHit hit : searchResponse.getHits()) {
        assertThat(((Number) hit.sortValues()[0]).longValue(), equalTo(counter++));
      }

      searchResponse =
          client()
              .prepareSearchScroll(searchResponse.getScrollId())
              .setScroll(TimeValue.timeValueMinutes(2))
              .execute()
              .actionGet();

      assertThat(searchResponse.getHits().getTotalHits(), equalTo(100l));
      assertThat(searchResponse.getHits().hits().length, equalTo(30));
      for (SearchHit hit : searchResponse.getHits()) {
        assertThat(((Number) hit.sortValues()[0]).longValue(), equalTo(counter++));
      }
    } finally {
      clearScroll(searchResponse.getScrollId());
    }
  }
  @Test
  public void testSimpleScrollQueryThenFetchSmallSizeUnevenDistribution() throws Exception {
    client()
        .admin()
        .indices()
        .prepareCreate("test")
        .setSettings(Settings.settingsBuilder().put("index.number_of_shards", 3))
        .execute()
        .actionGet();
    client()
        .admin()
        .cluster()
        .prepareHealth()
        .setWaitForEvents(Priority.LANGUID)
        .setWaitForGreenStatus()
        .execute()
        .actionGet();

    client()
        .admin()
        .cluster()
        .prepareHealth()
        .setWaitForEvents(Priority.LANGUID)
        .setWaitForGreenStatus()
        .execute()
        .actionGet();

    for (int i = 0; i < 100; i++) {
      String routing = "0";
      if (i > 90) {
        routing = "1";
      } else if (i > 60) {
        routing = "2";
      }
      client()
          .prepareIndex("test", "type1", Integer.toString(i))
          .setSource("field", i)
          .setRouting(routing)
          .execute()
          .actionGet();
    }

    client().admin().indices().prepareRefresh().execute().actionGet();

    SearchResponse searchResponse =
        client()
            .prepareSearch()
            .setSearchType(SearchType.QUERY_THEN_FETCH)
            .setQuery(matchAllQuery())
            .setSize(3)
            .setScroll(TimeValue.timeValueMinutes(2))
            .addSort("field", SortOrder.ASC)
            .execute()
            .actionGet();
    try {
      long counter = 0;

      assertThat(searchResponse.getHits().getTotalHits(), equalTo(100l));
      assertThat(searchResponse.getHits().hits().length, equalTo(3));
      for (SearchHit hit : searchResponse.getHits()) {
        assertThat(((Number) hit.sortValues()[0]).longValue(), equalTo(counter++));
      }

      for (int i = 0; i < 32; i++) {
        searchResponse =
            client()
                .prepareSearchScroll(searchResponse.getScrollId())
                .setScroll(TimeValue.timeValueMinutes(2))
                .execute()
                .actionGet();

        assertThat(searchResponse.getHits().getTotalHits(), equalTo(100l));
        assertThat(searchResponse.getHits().hits().length, equalTo(3));
        for (SearchHit hit : searchResponse.getHits()) {
          assertThat(((Number) hit.sortValues()[0]).longValue(), equalTo(counter++));
        }
      }

      // and now, the last one is one
      searchResponse =
          client()
              .prepareSearchScroll(searchResponse.getScrollId())
              .setScroll(TimeValue.timeValueMinutes(2))
              .execute()
              .actionGet();

      assertThat(searchResponse.getHits().getTotalHits(), equalTo(100l));
      assertThat(searchResponse.getHits().hits().length, equalTo(1));
      for (SearchHit hit : searchResponse.getHits()) {
        assertThat(((Number) hit.sortValues()[0]).longValue(), equalTo(counter++));
      }

      // a the last is zero
      searchResponse =
          client()
              .prepareSearchScroll(searchResponse.getScrollId())
              .setScroll(TimeValue.timeValueMinutes(2))
              .execute()
              .actionGet();

      assertThat(searchResponse.getHits().getTotalHits(), equalTo(100l));
      assertThat(searchResponse.getHits().hits().length, equalTo(0));
      for (SearchHit hit : searchResponse.getHits()) {
        assertThat(((Number) hit.sortValues()[0]).longValue(), equalTo(counter++));
      }

    } finally {
      clearScroll(searchResponse.getScrollId());
    }
  }