Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run tests in parallel #1657

Merged
merged 9 commits into from
Jun 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
run: CC=gcc CXX=g++ make alldebug NUM_THREADS=32

- name: Run test with ASan
run: ctest
run: ctest --output-on-failure -j 10
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar with ASan. Is it ok to run multiple jobs here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be fine.

I noticed one test (CApiConnectionTest.Interrupt) failing in asan CI test, can you take a further look?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can take a look but this error is also in other PRs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Can you open an issue on this then?

env:
LD_PRELOAD: "/usr/lib/x86_64-linux-gnu/libasan.so.6"
ASAN_OPTIONS: "detect_leaks=1:log_path=/tmp/asan.log"
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ __pycache__/
*.py[cod]
*$py.class
cmake-build-debug/
test/unittest_temp/
test/unittest_temp_*
dataset/parquet_temp_*
tools/python_api/test/test_PYTHON_CSV.csv

# antlr4 jar
Expand Down
9 changes: 7 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@
GENERATOR=
FORCE_COLOR=
NUM_THREADS=
TEST_JOBS=
SANITIZER_FLAG=
ROOT_DIR=$(CURDIR)

ifndef $(NUM_THREADS)
NUM_THREADS=1
endif

ifndef $(TEST_JOBS)
TEST_JOBS=10
endif

ifeq ($(OS),Windows_NT)
ifndef $(GEN)
GEN=ninja
Expand Down Expand Up @@ -83,14 +88,14 @@ test: arrow
cmake $(GENERATOR) $(FORCE_COLOR) $(SANITIZER_FLAG) -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=TRUE ../.. && \
cmake --build . --config Release -- -j $(NUM_THREADS)
cd $(ROOT_DIR)/build/release/test && \
ctest --output-on-failure
ctest --output-on-failure -j ${TEST_JOBS}

lcov: arrow
$(call mkdirp,build/release) && cd build/release && \
cmake $(GENERATOR) $(FORCE_COLOR) $(SANITIZER_FLAG) -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=TRUE -DBUILD_NODEJS=TRUE -DBUILD_LCOV=TRUE ../.. && \
cmake --build . --config Release -- -j $(NUM_THREADS)
cd $(ROOT_DIR)/build/release/test && \
ctest --output-on-failure
ctest --output-on-failure -j ${TEST_JOBS}

pytest: arrow
$(MAKE) release
Expand Down
9 changes: 4 additions & 5 deletions src/storage/store/nodes_statistics_and_deleted_ids.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,17 +130,16 @@
if (numElementsInList != 0) {
throw RuntimeException(StringUtils::string_format(
"Currently deleting a node with edges is not supported. node table {} nodeOffset "
"{} has {} (one-to-many or many-to-many) edges for edge file: {}.",
tableID, nodeOffset, numElementsInList,
adjList->getFileHandle()->getFileInfo()->path.c_str()));
"{} has {} (one-to-many or many-to-many) edges.",
tableID, nodeOffset, numElementsInList));
}
}
for (Column* adjColumn : adjListsAndColumns.second) {
if (!adjColumn->isNull(nodeOffset, transaction::Transaction::getDummyWriteTrx().get())) {
throw RuntimeException(StringUtils::string_format(
"Currently deleting a node with edges is not supported. node table {} nodeOffset "
"{} has a 1-1 edge for edge file: {}.",
tableID, nodeOffset, adjColumn->getFileHandle()->getFileInfo()->path.c_str()));
"{} has a 1-1 edge.",
tableID, nodeOffset));

Check warning on line 142 in src/storage/store/nodes_statistics_and_deleted_ids.cpp

View check run for this annotation

Codecov / codecov/patch

src/storage/store/nodes_statistics_and_deleted_ids.cpp#L142

Added line #L142 was not covered by tests
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions test/c_api/database_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

class CApiDatabaseTest : public EmptyDBTest {
public:
void SetUp() override {}
void SetUp() override { EmptyDBTest::SetUp(); }
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mewim Is it ok to add EmptyDBTest::SetUp() here? I basically need to set the temporary dynamic database path instead of using the fixed one.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I missed this. Since it is only setting a path it is fine.

};

TEST_F(CApiDatabaseTest, CreationAndDestroy) {
auto databasePath = TestHelper::getTmpTestDir();
auto databasePathCStr = databasePath.c_str();
auto database = kuzu_database_init(databasePathCStr, 0);
ASSERT_NE(database, nullptr);
Expand Down
2 changes: 1 addition & 1 deletion test/c_api/query_result_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ TEST_F(CApiQueryResultTest, WriteToCSV) {
auto connection = getConnection();
auto result = kuzu_connection_query(connection, query);
ASSERT_TRUE(kuzu_query_result_is_success(result));
auto outputPath = TestHelper::getTmpTestDir() + "/output_CSV_CAPI.csv";
auto outputPath = databasePath + "/output_CSV_CAPI.csv";
kuzu_query_result_write_to_csv(result, outputPath.c_str(), ',', '"', '\n');
std::ifstream f(outputPath);
std::ostringstream ss;
Expand Down
21 changes: 17 additions & 4 deletions test/include/graph_test/graph_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ class BaseGraphTest : public Test {
void SetUp() override {
systemConfig = std::make_unique<main::SystemConfig>(
common::BufferPoolConstants::DEFAULT_BUFFER_POOL_SIZE_FOR_TESTING);
if (common::FileUtils::fileOrPathExists(TestHelper::getTmpTestDir())) {
common::FileUtils::removeDir(TestHelper::getTmpTestDir());
setDatabasePath();
if (common::FileUtils::fileOrPathExists(databasePath)) {
common::FileUtils::removeDir(databasePath);
}
databasePath = TestHelper::getTmpTestDir();
}

virtual std::string getInputDir() = 0;

void TearDown() override { common::FileUtils::removeDir(TestHelper::getTmpTestDir()); }
void TearDown() override { common::FileUtils::removeDir(databasePath); }

void createDBAndConn();

Expand Down Expand Up @@ -133,7 +133,20 @@ class BaseGraphTest : public Test {
void commitOrRollbackConnectionAndInitDBIfNecessary(
bool isCommit, TransactionTestType transactionTestType);

inline std::string getTestGroupAndName() {
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
return std::string(testInfo->test_case_name()) + "." + std::string(testInfo->name());
}

private:
void setDatabasePath() {
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
databasePath = TestHelper::appendKuzuRootPath(
TestHelper::TMP_TEST_DIR + getTestGroupAndName() + TestHelper::getMillisecondsSuffix());
}

void validateRelPropertyFiles(catalog::RelTableSchema* relTableSchema,
common::RelDataDirection relDirection, bool isColumnProperty, common::DBFileType dbFileType,
bool existence);
Expand Down
10 changes: 4 additions & 6 deletions test/include/test_helper/test_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,22 @@ class TestHelper {
static constexpr char E2E_TEST_FILES_DIRECTORY[] = "test/test_files";
static constexpr char SCHEMA_FILE_NAME[] = "schema.cypher";
static constexpr char COPY_FILE_NAME[] = "copy.cypher";
static constexpr char PARQUET_TEMP_DATASET_PATH[] = "dataset/parquet_temp/";
static constexpr char PARQUET_TEMP_DATASET_PATH[] = "dataset/parquet_temp_";
static constexpr char TMP_TEST_DIR[] = "test/unittest_temp_";

static std::string getTmpTestDir() { return appendKuzuRootPath("test/unittest_temp/"); }
static std::string getTestListFile() {
return appendKuzuRootPath(std::string(E2E_TEST_FILES_DIRECTORY) + "/test_list");
}

static std::string appendParquetDatasetTempDir(const std::string& dataset) {
return TestHelper::appendKuzuRootPath(TestHelper::PARQUET_TEMP_DATASET_PATH + dataset);
}

static std::string appendKuzuRootPath(const std::string& path) {
return KUZU_ROOT_DIRECTORY + std::string("/") + path;
}

static std::unique_ptr<planner::LogicalPlan> getLogicalPlan(
const std::string& query, Connection& conn);

static std::string getMillisecondsSuffix();

private:
static void initializeConnection(TestQueryConfig* config, Connection& conn);
static bool testQuery(TestQueryConfig* config, Connection& conn);
Expand Down
19 changes: 10 additions & 9 deletions test/include/test_runner/csv_to_parquet_converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ namespace testing {
// The dataset directory must contain schema and copy files.
class CSVToParquetConverter {
public:
static void convertCSVDatasetToParquet(std::string& dataset);
static std::string convertCSVDatasetToParquet(
const std::string& csvDatasetPath, const std::string& parquetDatasetPath);

inline static std::string replaceSlashesWithUnderscores(std::string dataset) {
std::replace(dataset.begin(), dataset.end(), '/', '_');
return dataset;
}

private:
struct CopyCommandInfo {
Expand All @@ -20,28 +26,23 @@ class CSVToParquetConverter {
};

static std::vector<CopyCommandInfo> readCopyCommandsFromCopyCypherFile(
const std::string& dataset);
const std::string& csvDatasetPath, const std::string& parquetDatasetPath);

static void convertCSVFilesToParquet(
const std::vector<CSVToParquetConverter::CopyCommandInfo>& copyCommands);

static CopyCommandInfo createCopyCommandInfo(
const std::string& dataset, std::string copyStatement);
const std::string& parquetDatasetPath, std::string copyStatement);

static arrow::Status runCSVToParquetConversion(const std::string& inputFile,
const std::string& outputFile, char delimiter, bool hasHeader);

static void copySchema(
const std::string& csvDatasetPath, const std::string& parquetDatasetPath);

static void createCopyFile(const std::string& dataset,
static void createCopyFile(const std::string& parquetDatasetPath,
const std::vector<CSVToParquetConverter::CopyCommandInfo>& copyCommands);

inline static std::string replaceSlashesWithUnderscores(std::string dataset) {
std::replace(dataset.begin(), dataset.end(), '/', '_');
return dataset;
}

static std::string extractPath(std::string& str, char delimiter);
};

Expand Down
16 changes: 8 additions & 8 deletions test/main/csv_output_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ TEST_F(CSVOutputTest, BasicCSVTest) {
auto query = "MATCH (a:person)-[:workAt]->(o:organisation) RETURN a.fName, a.gender,"
"a.eyeSight, a.birthdate, a.registerTime, o.name";
auto result = conn->query(query);
result->writeToCSV(TestHelper::getTmpTestDir() + "/output_CSV_BASIC.csv");
std::ifstream f(TestHelper::getTmpTestDir() + "/output_CSV_BASIC.csv");
result->writeToCSV(databasePath + "/output_CSV_BASIC.csv");
std::ifstream f(databasePath + "/output_CSV_BASIC.csv");
std::ostringstream ss;
ss << f.rdbuf();
std::string fileString = ss.str();
Expand All @@ -37,8 +37,8 @@ TEST_F(CSVOutputTest, ListCSVTest) {
newline;
auto query = "MATCH (a:person) RETURN a.usedNames, a.workedHours, [a.fName, a.fName]";
auto result = conn->query(query);
result->writeToCSV(TestHelper::getTmpTestDir() + "/output_CSV_LIST.csv");
std::ifstream f(TestHelper::getTmpTestDir() + "/output_CSV_LIST.csv");
result->writeToCSV(databasePath + "/output_CSV_LIST.csv");
std::ifstream f(databasePath + "/output_CSV_LIST.csv");
std::ostringstream ss;
ss << f.rdbuf();
std::string fileString = ss.str();
Expand All @@ -49,8 +49,8 @@ TEST_F(CSVOutputTest, AlternateDelimCSVTest) {
std::string listOutput = R"(ABFsUni "-2"-CsWork "-100"-DEsWork 7-)";
auto query = "MATCH (o:organisation) RETURN o.name, o.score";
auto result = conn->query(query);
result->writeToCSV(TestHelper::getTmpTestDir() + "/output_CSV_LIST.csv", '\t', '"', '-');
std::ifstream f(TestHelper::getTmpTestDir() + "/output_CSV_LIST.csv");
result->writeToCSV(databasePath + "/output_CSV_LIST.csv", '\t', '"', '-');
std::ifstream f(databasePath + "/output_CSV_LIST.csv");
std::ostringstream ss;
ss << f.rdbuf();
std::string fileString = ss.str();
Expand All @@ -66,8 +66,8 @@ TEST_F(CSVOutputTest, AlternateEscapeCSVTest) {
R"(`[10,11,12,3,4,5,6,7]`,Hubert Blaine Wolfeschlegelsteinhausenbergerdorff)" + newline;
auto query = "MATCH (p:person) RETURN p.workedHours, p.fName";
auto result = conn->query(query);
result->writeToCSV(TestHelper::getTmpTestDir() + "/output_CSV_LIST.csv", ',', '`');
std::ifstream f(TestHelper::getTmpTestDir() + "/output_CSV_LIST.csv");
result->writeToCSV(databasePath + "/output_CSV_LIST.csv", ',', '`');
std::ifstream f(databasePath + "/output_CSV_LIST.csv");
std::ostringstream ss;
ss << f.rdbuf();
std::string fileString = ss.str();
Expand Down
1 change: 1 addition & 0 deletions test/runner/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ add_kuzu_test(e2e_set_transaction_test e2e_set_transaction_test.cpp)
add_kuzu_test(e2e_update_rel_test e2e_update_rel_test.cpp)
add_kuzu_test(e2e_delete_rel_test e2e_delete_rel_test.cpp)
add_kuzu_test(e2e_create_rel_test e2e_create_rel_test.cpp)
add_kuzu_test(cleanup_test cleanup_test.cpp)
29 changes: 29 additions & 0 deletions test/runner/cleanup_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include "graph_test/graph_test.h"

using namespace kuzu::testing;
using namespace kuzu::common;

void deleteMatchingDir(const std::string& dirPath, const std::string& match) {
for (const auto& entry : std::filesystem::directory_iterator(dirPath)) {
if (entry.path().filename().string().find(match) != std::string::npos) {
FileUtils::removeDir(entry.path().string());
}
}
}

int main(int argc, char** argv) {
std::vector<std::string> tempDirs = {
TestHelper::PARQUET_TEMP_DATASET_PATH, TestHelper::TMP_TEST_DIR};
if (argc > 1 && std::string(argv[1]) == "--gtest_list_tests") {
for (const auto& tempDir : tempDirs) {
// path = test/unittest_temp_
std::filesystem::path path = tempDir;
// dirToCheck = test
std::string dirToCheck = path.parent_path().string();
// dirPatternToRemove = unittest_temp_
std::string dirPatternToRemove = path.filename().string();
deleteMatchingDir(TestHelper::appendKuzuRootPath(dirToCheck), dirPatternToRemove);
}
}
return 0;
}
3 changes: 1 addition & 2 deletions test/runner/e2e_delete_create_transaction_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,7 @@ TEST_F(DeleteNodeWithEdgesErrorTest, DeleteNodeWithEdgesError) {
auto result = conn->query("match (p:person) delete p");
ASSERT_EQ(result->getErrorMessage(),
"Runtime exception: Currently deleting a node with edges is not supported. node table 0 "
"nodeOffset 0 has 1 (one-to-many or many-to-many) edges for edge file: " +
TestHelper::appendKuzuRootPath("test/unittest_temp/r-1-0.lists."));
"nodeOffset 0 has 1 (one-to-many or many-to-many) edges.");
}

TEST_F(CreateDeleteInt64NodeTrxTest, MixedInsertDeleteCommitNormalExecution) {
Expand Down
42 changes: 23 additions & 19 deletions test/runner/e2e_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,51 @@ using ::testing::Test;
using namespace kuzu::testing;
using namespace kuzu::common;

class EndToEndEnvironment : public testing::Environment {
public:
virtual void SetUp() {
FileUtils::createDirIfNotExists(
TestHelper::appendKuzuRootPath(TestHelper::PARQUET_TEMP_DATASET_PATH));
}
virtual void TearDown() {
FileUtils::removeDir(TestHelper::appendKuzuRootPath(TestHelper::PARQUET_TEMP_DATASET_PATH));
}
};

class EndToEndTest : public DBTest {
public:
explicit EndToEndTest(TestGroup::DatasetType datasetType, std::string dataset,
uint64_t bufferPoolSize, std::vector<std::unique_ptr<TestStatement>> testStatements)
: datasetType{datasetType}, dataset{dataset}, bufferPoolSize{bufferPoolSize},
testStatements{std::move(testStatements)} {}

void SetUp() override {
setUpDataset();
BaseGraphTest::SetUp();
systemConfig->bufferPoolSize = bufferPoolSize;
createDBAndConn();
initGraph();
}

void setUpDataset() {
parquetTempDatasetPath = generateParquetTempDatasetPath();
dataset = TestHelper::appendKuzuRootPath("dataset/" + dataset);
if (datasetType == TestGroup::DatasetType::CSV_TO_PARQUET) {
CSVToParquetConverter::convertCSVDatasetToParquet(dataset);
} else {
dataset = TestHelper::appendKuzuRootPath("dataset/" + dataset);
dataset =
CSVToParquetConverter::convertCSVDatasetToParquet(dataset, parquetTempDatasetPath);
}
}
void TearDown() override { FileUtils::removeDir(TestHelper::getTmpTestDir()); }
std::string getInputDir() override { return dataset + "/"; }

void TearDown() override {
FileUtils::removeDir(databasePath);
FileUtils::removeDir(parquetTempDatasetPath);
}

void TestBody() override { runTest(testStatements); }
std::string getInputDir() override { return dataset + "/"; }

private:
TestGroup::DatasetType datasetType;
std::string dataset;
std::string parquetTempDatasetPath;
uint64_t bufferPoolSize;
std::vector<std::unique_ptr<TestStatement>> testStatements;

const std::string generateParquetTempDatasetPath() {
return TestHelper::appendKuzuRootPath(
TestHelper::PARQUET_TEMP_DATASET_PATH +
CSVToParquetConverter::replaceSlashesWithUnderscores(dataset) + getTestGroupAndName() +
TestHelper::getMillisecondsSuffix());
}
};

void parseAndRegisterTestGroup(const std::string& path, bool generateTestList = false) {
Expand Down Expand Up @@ -102,7 +107,7 @@ std::string findTestFile(std::string testCase) {
return "";
}

void checkCtestParams(int argc, char** argv) {
void checkGtestParams(int argc, char** argv) {
if (argc > 1) {
std::string argument = argv[1];
if (argument == "--gtest_list_tests") {
Expand All @@ -120,9 +125,8 @@ void checkCtestParams(int argc, char** argv) {
}

int main(int argc, char** argv) {
checkCtestParams(argc, argv);
checkGtestParams(argc, argv);
testing::InitGoogleTest(&argc, argv);
testing::AddGlobalTestEnvironment(new EndToEndEnvironment);
if (argc > 1) {
auto path = TestHelper::appendKuzuRootPath(
FileUtils::joinPath(TestHelper::E2E_TEST_FILES_DIRECTORY, argv[1]));
Expand Down
Loading
Loading