Repository: vespa-engine/vespa
File: storage/src/tests/visiting/visitortest.cpp (C++)

Code before:
    ASSERT_EQ(expectedConsistency, createCmd->getReadConsistency());
}

TEST_F(VisitorTest, dump_visitor_invokes_strong_read_consistency_iteration) {
    doTestVisitorInstanceHasConsistencyLevel(
            "dumpvisitor", spi::ReadConsistency::STRONG);
}

TEST_F(VisitorTest, document_api_failure_error_message_includes_doc_id) {
    ASSERT_NO_FATAL_FAILURE(initializeTest());

    auto cmd = makeCreateVisitor();
    _top->sendDown(cmd);
    sendCreateIteratorReply();

    GetIterCommand::SP get_iter_cmd;
    ASSERT_NO_FATAL_FAILURE(fetchSingleCommand<GetIterCommand>(*_bottom, get_iter_cmd));
    sendGetIterReply(*get_iter_cmd, api::ReturnCode(api::ReturnCode::OK), 1, true);

    MessageMeta meta;
    getMessagesAndReply(1, getSession(0), meta, api::ReturnCode::REJECTED);

    DestroyIteratorCommand::SP destroy_iter_cmd;
    ASSERT_NO_FATAL_FAILURE(fetchSingleCommand<DestroyIteratorCommand>(*_bottom, destroy_iter_cmd));

    auto reply = fetch_create_visitor_reply();
    EXPECT_EQ(reply->getResult().getResult(), api::ReturnCode::REJECTED);

    std::string_view message = reply->getResult().getMessage();
    EXPECT_EQ("Generic error [document id was 'id:test:testdoctype1:n=0:http://www.ntnu.no/0.html']", message);
    ASSERT_TRUE(waitUntilNoActiveVisitors());
}

// NOTE: SearchVisitor cannot be tested here since it's in a separate module
// which depends on _this_ module for compilation. Instead we let TestVisitor
// use weak consistency, as this is just some internal stuff not used for/by
// any external client use cases. Our primary concern is to test that each
// visitor subclass might report its own read consistency requirement and that
// this is carried along to the CreateIteratorCommand.
TEST_F(VisitorTest, test_visitor_invokes_weak_read_consistency_iteration) {
    doTestVisitorInstanceHasConsistencyLevel(
            "testvisitor", spi::ReadConsistency::WEAK);
}

struct ReindexingVisitorTest : VisitorTest {
    void respond_with_docs_from_persistence() {
        sendCreateIteratorReply();
        GetIterCommand::SP get_iter_cmd;
        // Reply to GetIter with a single doc and bucket completed
        ASSERT_NO_FATAL_FAILURE(fetchSingleCommand<GetIterCommand>(*_bottom, get_iter_cmd));
        sendGetIterReply(*get_iter_cmd, api::ReturnCode(api::ReturnCode::OK), 1, true);

Review comment (bug):
The call to `fetch_create_visitor_reply` should preferably be wrapped in `ASSERT_NO_FATAL_FAILURE` to avoid continuing if there were expectation failures in the nested call. Especially since it does a dynamic cast that may return a `nullptr` reply which we subsequently access here in the caller.

Code after:
    ASSERT_EQ(expectedConsistency, createCmd->getReadConsistency());
}

TEST_F(VisitorTest, dump_visitor_invokes_strong_read_consistency_iteration) {
    doTestVisitorInstanceHasConsistencyLevel(
            "dumpvisitor", spi::ReadConsistency::STRONG);
}

TEST_F(VisitorTest, document_api_failure_error_message_includes_doc_id) {
    ASSERT_NO_FATAL_FAILURE(initializeTest());

    auto cmd = makeCreateVisitor();
    _top->sendDown(cmd);
    sendCreateIteratorReply();

    GetIterCommand::SP get_iter_cmd;
    ASSERT_NO_FATAL_FAILURE(fetchSingleCommand<GetIterCommand>(*_bottom, get_iter_cmd));
    sendGetIterReply(*get_iter_cmd, api::ReturnCode(api::ReturnCode::OK), 1, true);

    MessageMeta meta;
    getMessagesAndReply(1, getSession(0), meta, api::ReturnCode::REJECTED);

    DestroyIteratorCommand::SP destroy_iter_cmd;
    ASSERT_NO_FATAL_FAILURE(fetchSingleCommand<DestroyIteratorCommand>(*_bottom, destroy_iter_cmd));

    std::shared_ptr<api::CreateVisitorReply> reply;
    ASSERT_NO_FATAL_FAILURE(fetch_create_visitor_reply(reply));
    EXPECT_EQ(reply->getResult().getResult(), api::ReturnCode::REJECTED);

    std::string_view message = reply->getResult().getMessage();
    EXPECT_EQ("Generic error [document id was 'id:test:testdoctype1:n=0:http://www.ntnu.no/0.html']", message);
    ASSERT_TRUE(waitUntilNoActiveVisitors());
}

// NOTE: SearchVisitor cannot be tested here since it's in a separate module
// which depends on _this_ module for compilation. Instead we let TestVisitor
// use weak consistency, as this is just some internal stuff not used for/by
// any external client use cases. Our primary concern is to test that each
// visitor subclass might report its own read consistency requirement and that
// this is carried along to the CreateIteratorCommand.
TEST_F(VisitorTest, test_visitor_invokes_weak_read_consistency_iteration) {
    doTestVisitorInstanceHasConsistencyLevel(
            "testvisitor", spi::ReadConsistency::WEAK);
}

struct ReindexingVisitorTest : VisitorTest {
    void respond_with_docs_from_persistence() {
        sendCreateIteratorReply();
        GetIterCommand::SP get_iter_cmd;
        // Reply to GetIter with a single doc and bucket completed
        ASSERT_NO_FATAL_FAILURE(fetchSingleCommand<GetIterCommand>(*_bottom, get_iter_cmd));