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

Code before:
    api::StorageMessageAddress address(&_storage, lib::NodeType::STORAGE, 0);
    auto cmd = std::make_shared<api::CreateVisitorCommand>(
            makeBucketSpace(), options.visitorType, "testvis", "");
    cmd->addBucketToBeVisited(document::BucketId(16, 3));
    cmd->setAddress(address);
    cmd->setMaximumPendingReplyCount(UINT32_MAX);
    cmd->setControlDestination("foo/bar");
    cmd->setPriority(DefaultPriority);
    return cmd;
}

void
VisitorTest::sendCreateIteratorReply(uint64_t iteratorId)
{
    CreateIteratorCommand::SP createCmd;
    ASSERT_NO_FATAL_FAILURE(fetchSingleCommand<CreateIteratorCommand>(*_bottom, createCmd));
    spi::IteratorId id(iteratorId);
    auto reply = std::make_shared<CreateIteratorReply>(*createCmd, id);
    _bottom->sendUp(reply);
}

std::shared_ptr<api::CreateVisitorReply>
VisitorTest::fetch_create_visitor_reply() const {
    _top->waitForMessages(1, 60);
    const msg_ptr_vector replies = _top->getRepliesOnce();
    EXPECT_EQ(1, replies.size());

    std::shared_ptr<api::StorageMessage> message(replies[0]);
    EXPECT_EQ(api::MessageType::VISITOR_CREATE_REPLY, message->getType());

    auto reply = std::dynamic_pointer_cast<api::CreateVisitorReply>(message);
    EXPECT_TRUE(reply.get());

    return reply;
}

TEST_F(VisitorTest, normal_usage) {
    ASSERT_NO_FATAL_FAILURE(initializeTest());
    auto cmd = makeCreateVisitor();
    _top->sendDown(cmd);

    CreateIteratorCommand::SP createCmd;
    ASSERT_NO_FATAL_FAILURE(fetchSingleCommand<CreateIteratorCommand>(*_bottom, createCmd));
    ASSERT_EQ(static_cast<int>(DefaultPriority),
              static_cast<int>(createCmd->getPriority())); // Inherit pri
    spi::IteratorId id(1234);
    auto reply = std::make_shared<CreateIteratorReply>(*createCmd, id);
    _bottom->sendUp(reply);

    GetIterCommand::SP getIterCmd;
    ASSERT_NO_FATAL_FAILURE(fetchSingleCommand<GetIterCommand>(*_bottom, getIterCmd));

Review comment (bug):
Since we use `replies[0]` after this, I think this should preferably be an `assert` instead since the program is ill-defined if we keep on trucking with an empty vector (which `EXPECT_*` will happily do). GTest `ASSERT_` macros can't be used since this is a non-`void` function. Alternatively, return early after failing the expectation and handle in the caller (see related comment).

Code after:
    api::StorageMessageAddress address(&_storage, lib::NodeType::STORAGE, 0);
    auto cmd = std::make_shared<api::CreateVisitorCommand>(
            makeBucketSpace(), options.visitorType, "testvis", "");
    cmd->addBucketToBeVisited(document::BucketId(16, 3));
    cmd->setAddress(address);
    cmd->setMaximumPendingReplyCount(UINT32_MAX);
    cmd->setControlDestination("foo/bar");
    cmd->setPriority(DefaultPriority);
    return cmd;
}

void
VisitorTest::sendCreateIteratorReply(uint64_t iteratorId)
{
    CreateIteratorCommand::SP createCmd;
    ASSERT_NO_FATAL_FAILURE(fetchSingleCommand<CreateIteratorCommand>(*_bottom, createCmd));
    spi::IteratorId id(iteratorId);
    auto reply = std::make_shared<CreateIteratorReply>(*createCmd, id);
    _bottom->sendUp(reply);
}

void
VisitorTest::fetch_create_visitor_reply(std::shared_ptr<api::CreateVisitorReply>& out_reply) const {
    _top->waitForMessages(1, 60);
    const msg_ptr_vector replies = _top->getRepliesOnce();
    ASSERT_EQ(1u, replies.size()) << "Expected exactly one CreateVisitor reply";

    std::shared_ptr<api::StorageMessage> message(replies[0]);
    ASSERT_EQ(api::MessageType::VISITOR_CREATE_REPLY, message->getType()) << "Unexpected reply message type: " << message->toString();

    auto reply = std::dynamic_pointer_cast<api::CreateVisitorReply>(message);
    ASSERT_TRUE(reply) << "Dynamic cast to CreateVisitorReply failed";

    out_reply = std::move(reply);
}

TEST_F(VisitorTest, normal_usage) {
    ASSERT_NO_FATAL_FAILURE(initializeTest());
    auto cmd = makeCreateVisitor();
    _top->sendDown(cmd);

    CreateIteratorCommand::SP createCmd;
    ASSERT_NO_FATAL_FAILURE(fetchSingleCommand<CreateIteratorCommand>(*_bottom, createCmd));
    ASSERT_EQ(static_cast<int>(DefaultPriority),
              static_cast<int>(createCmd->getPriority())); // Inherit pri
    spi::IteratorId id(1234);
    auto reply = std::make_shared<CreateIteratorReply>(*createCmd, id);
    _bottom->sendUp(reply);

    GetIterCommand::SP getIterCmd;
    ASSERT_NO_FATAL_FAILURE(fetchSingleCommand<GetIterCommand>(*_bottom, getIterCmd));