1
0
Fork 0

added produceRows inputrange tests

This commit is contained in:
hkernbach 2019-11-08 15:56:02 +01:00
parent b446952738
commit 80d76b8ea0
1 changed files with 447 additions and 11 deletions

View File

@ -25,8 +25,10 @@
#include "gtest/gtest.h"
#include "AqlItemBlockHelper.h"
#include "RowFetcherHelper.h"
#include "Aql/AqlCall.h"
#include "Aql/AqlItemBlock.h"
#include "Aql/Collection.h"
#include "Aql/ExecutionEngine.h"
@ -104,7 +106,8 @@ class SortedCollectExecutorTestNoRowsUpstream : public ::testing::Test {
};
TEST_F(SortedCollectExecutorTestNoRowsUpstream, producer_doesnt_wait) {
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(itemBlockManager, input.steal(), false);
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, input.steal(), false);
SortedCollectExecutor testee(fetcher, infos);
OutputAqlItemRow result(std::move(block), infos.getOutputRegisters(),
@ -115,7 +118,8 @@ TEST_F(SortedCollectExecutorTestNoRowsUpstream, producer_doesnt_wait) {
}
TEST_F(SortedCollectExecutorTestNoRowsUpstream, producer_waits) {
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(itemBlockManager, input.steal(), true);
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, input.steal(), true);
SortedCollectExecutor testee(fetcher, infos);
OutputAqlItemRow result(std::move(block), infos.getOutputRegisters(),
@ -187,7 +191,8 @@ class SortedCollectExecutorTestRowsUpstream : public ::testing::Test {
TEST_F(SortedCollectExecutorTestRowsUpstream, producer_doesnt_wait) {
auto input = VPackParser::fromJson("[ [1], [2] ]");
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(itemBlockManager, input->steal(), false);
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, input->steal(), false);
SortedCollectExecutor testee(fetcher, infos);
OutputAqlItemRow result(std::move(block), infos.getOutputRegisters(),
@ -208,7 +213,6 @@ TEST_F(SortedCollectExecutorTestRowsUpstream, producer_doesnt_wait) {
ASSERT_FALSE(result.produced());
auto block = result.stealBlock();
// check for groups in this executor they are guaranteed to be ordered
// First group
@ -223,7 +227,8 @@ TEST_F(SortedCollectExecutorTestRowsUpstream, producer_doesnt_wait) {
TEST_F(SortedCollectExecutorTestRowsUpstream, producer_doesnt_wait_2) {
auto input = VPackParser::fromJson("[ [1], [2], [3] ]");
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(itemBlockManager, input->steal(), false);
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, input->steal(), false);
SortedCollectExecutor testee(fetcher, infos);
OutputAqlItemRow result(std::move(block), infos.getOutputRegisters(),
@ -267,7 +272,8 @@ TEST_F(SortedCollectExecutorTestRowsUpstream, producer_doesnt_wait_2) {
TEST_F(SortedCollectExecutorTestRowsUpstream, producer_doesnt_wait_3) {
// Input order needs to be guaranteed
auto input = VPackParser::fromJson("[ [1], [1], [2], [2], [3] ]");
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(itemBlockManager, input->steal(), false);
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, input->steal(), false);
SortedCollectExecutor testee(fetcher, infos);
OutputAqlItemRow result(std::move(block), infos.getOutputRegisters(),
@ -311,7 +317,8 @@ TEST_F(SortedCollectExecutorTestRowsUpstream, producer_doesnt_wait_3) {
TEST_F(SortedCollectExecutorTestRowsUpstream, producer_doesnt_wait_4) {
auto input = VPackParser::fromJson("[ [1], [1], [2], [2] ]");
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(itemBlockManager, input->steal(), false);
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, input->steal(), false);
SortedCollectExecutor testee(fetcher, infos);
OutputAqlItemRow result(std::move(block), infos.getOutputRegisters(),
@ -346,7 +353,8 @@ TEST_F(SortedCollectExecutorTestRowsUpstream, producer_doesnt_wait_4) {
TEST_F(SortedCollectExecutorTestRowsUpstream, producer_waits) {
auto input = VPackParser::fromJson("[ [1], [2] ]");
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(itemBlockManager, input->steal(), true);
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, input->steal(), true);
SortedCollectExecutor testee(fetcher, infos);
OutputAqlItemRow result(std::move(block), infos.getOutputRegisters(),
@ -434,7 +442,8 @@ TEST(SortedCollectExecutorTestRowsUpstreamCount, test) {
NoStats stats{};
auto input = VPackParser::fromJson("[ [1], [2] ]");
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(itemBlockManager, input->steal(), false);
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, input->steal(), false);
SortedCollectExecutor testee(fetcher, infos);
OutputAqlItemRow result(std::move(block), infos.getOutputRegisters(),
@ -525,7 +534,8 @@ TEST(SortedCollectExecutorTestRowsUpstreamCountNumbers, test) {
NoStats stats{};
auto input = VPackParser::fromJson("[ [1], [2], [3] ]");
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(itemBlockManager, input->steal(), false);
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, input->steal(), false);
SortedCollectExecutor testee(fetcher, infos);
OutputAqlItemRow result(std::move(block), infos.getOutputRegisters(),
@ -631,7 +641,8 @@ TEST(SortedCollectExecutorTestRowsUpstreamCountStrings, test) {
NoStats stats{};
auto input = VPackParser::fromJson("[ [\"a\"], [\"aa\"], [\"aaa\"] ]");
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(itemBlockManager, input->steal(), false);
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, input->steal(), false);
SortedCollectExecutor testee(fetcher, infos);
OutputAqlItemRow result(std::move(block), infos.getOutputRegisters(),
@ -691,6 +702,431 @@ TEST(SortedCollectExecutorTestRowsUpstreamCountStrings, test) {
EXPECT_EQ(c.slice().getInt(), 1);
}
TEST_F(SortedCollectExecutorTestRowsUpstream, test_produce_datarange_1) {
// This fetcher will not be called!
// After Execute is done this fetcher shall be removed, the Executor does not need it anymore!
auto fakeUnusedBlock = VPackParser::fromJson("[ ]");
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, fakeUnusedBlock->steal(), false);
// This is the relevant part of the test
SortedCollectExecutor testee(fetcher, infos);
SharedAqlItemBlockPtr inBlock = buildBlock<1>(itemBlockManager, {{R"(1)"}, {R"(2)"}});
AqlItemBlockInputRange input{ExecutorState::DONE, inBlock, 0, inBlock->size()};
OutputAqlItemRow output(std::move(block), infos.getOutputRegisters(),
infos.registersToKeep(), infos.registersToClear());
EXPECT_EQ(output.numRowsWritten(), 0);
auto const [state, stats, call] = testee.produceRows(1000, input, output);
EXPECT_EQ(state, ExecutorState::DONE);
EXPECT_EQ(output.numRowsWritten(), 2);
auto block = output.stealBlock();
// check for groups in this executor they are guaranteed to be ordered
// First group
AqlValue x = block->getValue(0, 1);
ASSERT_TRUE(x.isNumber());
ASSERT_EQ(x.slice().getInt(), 1);
// check for collect
x = block->getValue(1, 1);
ASSERT_TRUE(x.isNumber());
ASSERT_EQ(x.slice().getInt(), 2);
}
TEST_F(SortedCollectExecutorTestRowsUpstream, test_produce_datarange_2) {
// This fetcher will not be called!
// After Execute is done this fetcher shall be removed, the Executor does not need it anymore!
auto fakeUnusedBlock = VPackParser::fromJson("[ ]");
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, fakeUnusedBlock->steal(), false);
// This is the relevant part of the test
SortedCollectExecutor testee(fetcher, infos);
SharedAqlItemBlockPtr inBlock =
buildBlock<1>(itemBlockManager, {{R"(1)"}, {R"(2)"}, {R"(3)"}});
AqlItemBlockInputRange input{ExecutorState::DONE, inBlock, 0, inBlock->size()};
OutputAqlItemRow output(std::move(block), infos.getOutputRegisters(),
infos.registersToKeep(), infos.registersToClear());
EXPECT_EQ(output.numRowsWritten(), 0);
auto const [state, stats, call] = testee.produceRows(1000, input, output);
EXPECT_EQ(state, ExecutorState::DONE);
EXPECT_EQ(output.numRowsWritten(), 3);
auto block = output.stealBlock();
// check for groups in this executor they are guaranteed to be ordered
// check for collects
AqlValue x = block->getValue(0, 1);
ASSERT_TRUE(x.isNumber());
ASSERT_EQ(x.slice().getInt(), 1);
x = block->getValue(1, 1);
ASSERT_TRUE(x.isNumber());
ASSERT_EQ(x.slice().getInt(), 2);
x = block->getValue(2, 1);
ASSERT_TRUE(x.isNumber());
ASSERT_EQ(x.slice().getInt(), 3);
}
TEST_F(SortedCollectExecutorTestRowsUpstream, test_produce_datarange_3) {
// This fetcher will not be called!
// After Execute is done this fetcher shall be removed, the Executor does not need it anymore!
auto fakeUnusedBlock = VPackParser::fromJson("[ ]");
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, fakeUnusedBlock->steal(), false);
// This is the relevant part of the test
SortedCollectExecutor testee(fetcher, infos);
SharedAqlItemBlockPtr inBlock =
buildBlock<1>(itemBlockManager, {{R"(1)"}, {R"(1)"}, {R"(2)"}, {R"(2)"}, {R"(3)"}});
AqlItemBlockInputRange input{ExecutorState::DONE, inBlock, 0, inBlock->size()};
OutputAqlItemRow output(std::move(block), infos.getOutputRegisters(),
infos.registersToKeep(), infos.registersToClear());
EXPECT_EQ(output.numRowsWritten(), 0);
auto const [state, stats, call] = testee.produceRows(1000, input, output);
EXPECT_EQ(state, ExecutorState::DONE);
EXPECT_EQ(output.numRowsWritten(), 3);
auto block = output.stealBlock();
// check for types
AqlValue x = block->getValue(0, 1);
ASSERT_TRUE(x.isNumber());
ASSERT_EQ(x.slice().getInt(), 1);
x = block->getValue(1, 1);
ASSERT_TRUE(x.isNumber());
ASSERT_EQ(x.slice().getInt(), 2);
x = block->getValue(2, 1);
ASSERT_TRUE(x.isNumber());
ASSERT_EQ(x.slice().getInt(), 3);
}
TEST_F(SortedCollectExecutorTestRowsUpstream, test_produce_datarange_4) {
// This fetcher will not be called!
// After Execute is done this fetcher shall be removed, the Executor does not need it anymore!
auto fakeUnusedBlock = VPackParser::fromJson("[ ]");
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, fakeUnusedBlock->steal(), false);
// This is the relevant part of the test
SortedCollectExecutor testee(fetcher, infos);
SharedAqlItemBlockPtr inBlock =
buildBlock<1>(itemBlockManager, {{R"(1)"}, {R"(1)"}, {R"(2)"}, {R"(2)"}});
AqlItemBlockInputRange input{ExecutorState::DONE, inBlock, 0, inBlock->size()};
OutputAqlItemRow output(std::move(block), infos.getOutputRegisters(),
infos.registersToKeep(), infos.registersToClear());
EXPECT_EQ(output.numRowsWritten(), 0);
auto const [state, stats, call] = testee.produceRows(1000, input, output);
EXPECT_EQ(state, ExecutorState::DONE);
EXPECT_EQ(output.numRowsWritten(), 2);
auto block = output.stealBlock();
// check for types
AqlValue x = block->getValue(0, 1);
ASSERT_TRUE(x.isNumber());
ASSERT_EQ(x.slice().getInt(), 1);
x = block->getValue(1, 1);
ASSERT_TRUE(x.isNumber());
ASSERT_EQ(x.slice().getInt(), 2);
}
TEST(SortedCollectExecutorTestRowsUpstreamCount, test_produce_datarange_sum) {
ResourceMonitor monitor;
AqlItemBlockManager itemBlockManager{&monitor, SerializationFormat::SHADOWROWS};
mocks::MockAqlServer server{};
std::unique_ptr<arangodb::aql::Query> fakedQuery = server.createFakeQuery();
arangodb::transaction::Methods* trx = fakedQuery->trx();
std::unordered_set<RegisterId> regToClear;
std::unordered_set<RegisterId> regToKeep;
std::vector<std::pair<RegisterId, RegisterId>> groupRegisters;
groupRegisters.emplace_back(std::make_pair<RegisterId, RegisterId>(1, 0));
std::unordered_set<RegisterId> readableInputRegisters;
readableInputRegisters.insert(0);
std::unordered_set<RegisterId> writeableOutputRegisters;
writeableOutputRegisters.insert(1);
RegisterId nrOutputRegister = 3;
std::vector<std::pair<RegisterId, RegisterId>> aggregateRegisters;
aggregateRegisters.emplace_back(std::make_pair<RegisterId, RegisterId>(2, 0));
writeableOutputRegisters.insert(2);
std::vector<std::string> aggregateTypes;
aggregateTypes.emplace_back("SUM");
// if count = true, then we need to set a valid countRegister
bool count = true;
RegisterId collectRegister = RegisterPlan::MaxRegisterId;
RegisterId expressionRegister = RegisterPlan::MaxRegisterId;
Variable const* expressionVariable = nullptr;
std::vector<std::pair<std::string, RegisterId>> variables;
SortedCollectExecutorInfos infos(1, nrOutputRegister, regToClear, regToKeep,
std::move(readableInputRegisters),
std::move(writeableOutputRegisters),
std::move(groupRegisters), collectRegister,
expressionRegister, expressionVariable,
std::move(aggregateTypes), std::move(variables),
std::move(aggregateRegisters), trx, count);
SharedAqlItemBlockPtr block{new AqlItemBlock(itemBlockManager, 1000, nrOutputRegister)};
// This fetcher will not be called!
// After Execute is done this fetcher shall be removed, the Executor does not need it anymore!
auto fakeUnusedBlock = VPackParser::fromJson("[ ]");
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, fakeUnusedBlock->steal(), false);
// This is the relevant part of the test
SortedCollectExecutor testee(fetcher, infos);
SharedAqlItemBlockPtr inBlock = buildBlock<1>(itemBlockManager, {{R"(1)"}, {R"(2)"}});
AqlItemBlockInputRange input{ExecutorState::DONE, inBlock, 0, inBlock->size()};
OutputAqlItemRow output(std::move(block), infos.getOutputRegisters(),
infos.registersToKeep(), infos.registersToClear());
EXPECT_EQ(output.numRowsWritten(), 0);
auto const [state, stats, call] = testee.produceRows(1000, input, output);
EXPECT_EQ(state, ExecutorState::DONE);
EXPECT_EQ(output.numRowsWritten(), 2);
auto newBlock = output.stealBlock();
// check for types
AqlValue x = newBlock->getValue(0, 1);
ASSERT_TRUE(x.isNumber());
EXPECT_EQ(x.slice().getInt(), 1);
// Check the SUM register
AqlValue counter = newBlock->getValue(0, 2);
ASSERT_TRUE(counter.isNumber());
EXPECT_EQ(counter.slice().getDouble(), 1);
// check for types
x = newBlock->getValue(1, 1);
ASSERT_TRUE(x.isNumber());
EXPECT_EQ(x.slice().getInt(), 2);
// Check the SUM register
counter = newBlock->getValue(1, 2);
ASSERT_TRUE(counter.isNumber());
EXPECT_EQ(counter.slice().getDouble(), 2);
}
TEST(SortedCollectExecutorTestRowsUpstreamCountNumbers, test_produce_datarange_length_1) {
ResourceMonitor monitor;
AqlItemBlockManager itemBlockManager{&monitor, SerializationFormat::SHADOWROWS};
mocks::MockAqlServer server{};
std::unique_ptr<arangodb::aql::Query> fakedQuery = server.createFakeQuery();
arangodb::transaction::Methods* trx = fakedQuery->trx();
std::unordered_set<RegisterId> regToClear;
std::unordered_set<RegisterId> regToKeep;
std::vector<std::pair<RegisterId, RegisterId>> groupRegisters;
groupRegisters.emplace_back(std::make_pair<RegisterId, RegisterId>(1, 0));
std::unordered_set<RegisterId> readableInputRegisters;
readableInputRegisters.insert(0);
std::unordered_set<RegisterId> writeableOutputRegisters;
writeableOutputRegisters.insert(1);
RegisterId nrOutputRegister = 3;
std::vector<std::pair<RegisterId, RegisterId>> aggregateRegisters;
aggregateRegisters.emplace_back(std::make_pair<RegisterId, RegisterId>(2, 0));
std::vector<std::string> aggregateTypes;
aggregateTypes.emplace_back("LENGTH");
// if count = true, then we need to set a valid countRegister
bool count = true;
RegisterId collectRegister = RegisterPlan::MaxRegisterId;
RegisterId expressionRegister = RegisterPlan::MaxRegisterId;
Variable const* expressionVariable = nullptr;
std::vector<std::pair<std::string, RegisterId>> variables;
writeableOutputRegisters.insert(2);
SortedCollectExecutorInfos infos(1, nrOutputRegister, regToClear, regToKeep,
std::move(readableInputRegisters),
std::move(writeableOutputRegisters),
std::move(groupRegisters), collectRegister,
expressionRegister, expressionVariable,
std::move(aggregateTypes), std::move(variables),
std::move(aggregateRegisters), trx, count);
SharedAqlItemBlockPtr block{new AqlItemBlock(itemBlockManager, 1000, nrOutputRegister)};
// This fetcher will not be called!
// After Execute is done this fetcher shall be removed, the Executor does not need it anymore!
auto fakeUnusedBlock = VPackParser::fromJson("[ ]");
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, fakeUnusedBlock->steal(), false);
// This is the relevant part of the test
SortedCollectExecutor testee(fetcher, infos);
SharedAqlItemBlockPtr inBlock =
buildBlock<1>(itemBlockManager, {{R"(1)"}, {R"(2)"}, {R"(3)"}});
AqlItemBlockInputRange input{ExecutorState::DONE, inBlock, 0, inBlock->size()};
OutputAqlItemRow output(std::move(block), infos.getOutputRegisters(),
infos.registersToKeep(), infos.registersToClear());
EXPECT_EQ(output.numRowsWritten(), 0);
auto const [state, stats, call] = testee.produceRows(1000, input, output);
EXPECT_EQ(state, ExecutorState::DONE);
EXPECT_EQ(output.numRowsWritten(), 3);
auto newBlock = output.stealBlock();
// check for types
AqlValue x = newBlock->getValue(0, 1);
ASSERT_TRUE(x.isNumber());
EXPECT_EQ(x.slice().getInt(), 1);
// Check the LENGTH register
AqlValue xx = newBlock->getValue(0, 2);
ASSERT_TRUE(xx.isNumber());
EXPECT_EQ(xx.slice().getInt(), 1);
// check for types
x = newBlock->getValue(1, 1);
ASSERT_TRUE(x.isNumber());
EXPECT_EQ(x.slice().getInt(), 2);
// Check the LENGTH register
xx = newBlock->getValue(1, 2);
ASSERT_TRUE(xx.isNumber());
EXPECT_EQ(xx.slice().getInt(), 1);
// check for types
x = newBlock->getValue(2, 1);
ASSERT_TRUE(x.isNumber());
EXPECT_EQ(x.slice().getInt(), 3);
// Check the LENGTH register
xx = newBlock->getValue(2, 2);
ASSERT_TRUE(xx.isNumber());
EXPECT_EQ(xx.slice().getInt(), 1);
}
TEST(SortedCollectExecutorTestRowsUpstreamCountStrings, test_produce_datarange_length_2) {
ResourceMonitor monitor;
AqlItemBlockManager itemBlockManager{&monitor, SerializationFormat::SHADOWROWS};
mocks::MockAqlServer server{};
std::unique_ptr<arangodb::aql::Query> fakedQuery = server.createFakeQuery();
arangodb::transaction::Methods* trx = fakedQuery->trx();
std::unordered_set<RegisterId> regToClear;
std::unordered_set<RegisterId> regToKeep;
std::vector<std::pair<RegisterId, RegisterId>> groupRegisters;
groupRegisters.emplace_back(std::make_pair<RegisterId, RegisterId>(1, 0));
std::unordered_set<RegisterId> readableInputRegisters;
readableInputRegisters.insert(0);
std::unordered_set<RegisterId> writeableOutputRegisters;
writeableOutputRegisters.insert(1);
RegisterId nrOutputRegister = 3;
std::vector<std::pair<RegisterId, RegisterId>> aggregateRegisters;
aggregateRegisters.emplace_back(std::make_pair<RegisterId, RegisterId>(2, 0));
std::vector<std::string> aggregateTypes;
aggregateTypes.emplace_back("LENGTH");
// if count = true, then we need to set a valid countRegister
bool count = true;
RegisterId collectRegister = RegisterPlan::MaxRegisterId;
RegisterId expressionRegister = RegisterPlan::MaxRegisterId;
Variable const* expressionVariable = nullptr;
std::vector<std::pair<std::string, RegisterId>> variables;
writeableOutputRegisters.insert(2);
SortedCollectExecutorInfos infos(1, nrOutputRegister, regToClear, regToKeep,
std::move(readableInputRegisters),
std::move(writeableOutputRegisters),
std::move(groupRegisters), collectRegister,
expressionRegister, expressionVariable,
std::move(aggregateTypes), std::move(variables),
std::move(aggregateRegisters), trx, count);
SharedAqlItemBlockPtr block{new AqlItemBlock(itemBlockManager, 1000, nrOutputRegister)};
// This fetcher will not be called!
// After Execute is done this fetcher shall be removed, the Executor does not need it anymore!
auto fakeUnusedBlock = VPackParser::fromJson("[ ]");
SingleRowFetcherHelper<::arangodb::aql::BlockPassthrough::Disable> fetcher(
itemBlockManager, fakeUnusedBlock->steal(), false);
// This is the relevant part of the test
SortedCollectExecutor testee(fetcher, infos);
SharedAqlItemBlockPtr inBlock =
buildBlock<1>(itemBlockManager, {{R"("a")"}, {R"("aa")"}, {R"("aaa")"}});
AqlItemBlockInputRange input{ExecutorState::DONE, inBlock, 0, inBlock->size()};
OutputAqlItemRow output(std::move(block), infos.getOutputRegisters(),
infos.registersToKeep(), infos.registersToClear());
EXPECT_EQ(output.numRowsWritten(), 0);
auto const [state, stats, call] = testee.produceRows(1000, input, output);
EXPECT_EQ(state, ExecutorState::DONE);
EXPECT_EQ(output.numRowsWritten(), 3);
std::vector<std::string> myStrings;
std::vector<int> myCountNumbers;
auto newBlock = output.stealBlock();
// check for types
AqlValue x = newBlock->getValue(0, 1);
ASSERT_TRUE(x.isString());
EXPECT_EQ(x.slice().copyString(), "a");
// Check the count register
AqlValue c = newBlock->getValue(0, 2);
ASSERT_TRUE(c.isNumber());
EXPECT_EQ(c.slice().getInt(), 1);
// check for types
x = newBlock->getValue(1, 1);
ASSERT_TRUE(x.isString());
EXPECT_EQ(x.slice().copyString(), "aa");
// Check the count register
c = newBlock->getValue(1, 2);
ASSERT_TRUE(c.isNumber());
EXPECT_EQ(c.slice().getInt(), 1);
// check for types
x = newBlock->getValue(2, 1);
ASSERT_TRUE(x.isString());
EXPECT_EQ(x.slice().copyString(), "aaa");
// Check the count register
c = newBlock->getValue(2, 2);
ASSERT_TRUE(c.isNumber());
EXPECT_EQ(c.slice().getInt(), 1);
}
} // namespace aql
} // namespace tests
} // namespace arangodb