@Test
  public void testSearchResultRelease() throws Exception {
    Engine.Searcher searchResult = engine.searcher();
    MatcherAssert.assertThat(
        searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(0));
    searchResult.release();

    // create a document
    ParsedDocument doc =
        testParsedDocument(
            "1",
            "1",
            "test",
            null,
            -1,
            -1,
            testDocumentWithTextField(),
            Lucene.STANDARD_ANALYZER,
            B_1,
            false);
    engine.create(new Engine.Create(null, newUid("1"), doc));

    // its not there...
    searchResult = engine.searcher();
    MatcherAssert.assertThat(
        searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(0));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test")), 0));
    searchResult.release();

    // refresh and it should be there
    engine.refresh(new Engine.Refresh(true));

    // now its there...
    searchResult = engine.searcher();
    MatcherAssert.assertThat(
        searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(1));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test")), 1));
    // don't release the search result yet...

    // delete, refresh and do a new search, it should not be there
    engine.delete(new Engine.Delete("test", "1", newUid("1")));
    engine.refresh(new Engine.Refresh(true));
    Engine.Searcher updateSearchResult = engine.searcher();
    MatcherAssert.assertThat(
        updateSearchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(0));
    updateSearchResult.release();

    // the non release search result should not see the deleted yet...
    MatcherAssert.assertThat(
        searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(1));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test")), 1));
    searchResult.release();
  }
  @Test
  public void testSimpleOperations() throws Exception {
    Engine.Searcher searchResult = engine.searcher();
    MatcherAssert.assertThat(
        searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(0));
    searchResult.release();

    // create a document
    Document document = testDocumentWithTextField();
    document.add(
        new Field(SourceFieldMapper.NAME, B_1.toBytes(), SourceFieldMapper.Defaults.FIELD_TYPE));
    ParsedDocument doc =
        testParsedDocument(
            "1", "1", "test", null, -1, -1, document, Lucene.STANDARD_ANALYZER, B_1, false);
    engine.create(new Engine.Create(null, newUid("1"), doc));

    // its not there...
    searchResult = engine.searcher();
    MatcherAssert.assertThat(
        searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(0));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test")), 0));
    searchResult.release();

    // but, we can still get it (in realtime)
    Engine.GetResult getResult = engine.get(new Engine.Get(true, newUid("1")));
    assertThat(getResult.exists(), equalTo(true));
    assertThat(getResult.source().source.toBytesArray(), equalTo(B_1.toBytesArray()));
    assertThat(getResult.docIdAndVersion(), nullValue());

    // but, not there non realtime
    getResult = engine.get(new Engine.Get(false, newUid("1")));
    assertThat(getResult.exists(), equalTo(false));

    // refresh and it should be there
    engine.refresh(new Engine.Refresh(true));

    // now its there...
    searchResult = engine.searcher();
    MatcherAssert.assertThat(
        searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(1));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test")), 1));
    searchResult.release();

    // also in non realtime
    getResult = engine.get(new Engine.Get(false, newUid("1")));
    assertThat(getResult.exists(), equalTo(true));
    assertThat(getResult.docIdAndVersion(), notNullValue());

    // now do an update
    document = testDocument();
    document.add(new TextField("value", "test1", Field.Store.YES));
    document.add(
        new Field(SourceFieldMapper.NAME, B_2.toBytes(), SourceFieldMapper.Defaults.FIELD_TYPE));
    doc =
        testParsedDocument(
            "1", "1", "test", null, -1, -1, document, Lucene.STANDARD_ANALYZER, B_2, false);
    engine.index(new Engine.Index(null, newUid("1"), doc));

    // its not updated yet...
    searchResult = engine.searcher();
    MatcherAssert.assertThat(
        searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(1));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test")), 1));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test1")), 0));
    searchResult.release();

    // but, we can still get it (in realtime)
    getResult = engine.get(new Engine.Get(true, newUid("1")));
    assertThat(getResult.exists(), equalTo(true));
    assertThat(getResult.source().source.toBytesArray(), equalTo(B_2.toBytesArray()));
    assertThat(getResult.docIdAndVersion(), nullValue());

    // refresh and it should be updated
    engine.refresh(new Engine.Refresh(true));

    searchResult = engine.searcher();
    MatcherAssert.assertThat(
        searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(1));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test")), 0));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test1")), 1));
    searchResult.release();

    // now delete
    engine.delete(new Engine.Delete("test", "1", newUid("1")));

    // its not deleted yet
    searchResult = engine.searcher();
    MatcherAssert.assertThat(
        searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(1));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test")), 0));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test1")), 1));
    searchResult.release();

    // but, get should not see it (in realtime)
    getResult = engine.get(new Engine.Get(true, newUid("1")));
    assertThat(getResult.exists(), equalTo(false));

    // refresh and it should be deleted
    engine.refresh(new Engine.Refresh(true));

    searchResult = engine.searcher();
    MatcherAssert.assertThat(
        searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(0));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test")), 0));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test1")), 0));
    searchResult.release();

    // add it back
    document = testDocumentWithTextField();
    document.add(
        new Field(SourceFieldMapper.NAME, B_1.toBytes(), SourceFieldMapper.Defaults.FIELD_TYPE));
    doc =
        testParsedDocument(
            "1", "1", "test", null, -1, -1, document, Lucene.STANDARD_ANALYZER, B_1, false);
    engine.create(new Engine.Create(null, newUid("1"), doc));

    // its not there...
    searchResult = engine.searcher();
    MatcherAssert.assertThat(
        searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(0));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test")), 0));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test1")), 0));
    searchResult.release();

    // refresh and it should be there
    engine.refresh(new Engine.Refresh(true));

    // now its there...
    searchResult = engine.searcher();
    MatcherAssert.assertThat(
        searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(1));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test")), 1));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test1")), 0));
    searchResult.release();

    // now flush
    engine.flush(new Engine.Flush());

    // and, verify get (in real time)
    getResult = engine.get(new Engine.Get(true, newUid("1")));
    assertThat(getResult.exists(), equalTo(true));
    assertThat(getResult.source(), nullValue());
    assertThat(getResult.docIdAndVersion(), notNullValue());

    // make sure we can still work with the engine
    // now do an update
    document = testDocument();
    document.add(new TextField("value", "test1", Field.Store.YES));
    doc =
        testParsedDocument(
            "1", "1", "test", null, -1, -1, document, Lucene.STANDARD_ANALYZER, B_1, false);
    engine.index(new Engine.Index(null, newUid("1"), doc));

    // its not updated yet...
    searchResult = engine.searcher();
    MatcherAssert.assertThat(
        searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(1));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test")), 1));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test1")), 0));
    searchResult.release();

    // refresh and it should be updated
    engine.refresh(new Engine.Refresh(true));

    searchResult = engine.searcher();
    MatcherAssert.assertThat(
        searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(1));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test")), 0));
    MatcherAssert.assertThat(
        searchResult,
        EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(
            new TermQuery(new Term("value", "test1")), 1));
    searchResult.release();

    engine.close();
  }