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

[Tester] Add --require <name> #10579

Merged
merged 1 commit into from
Feb 12, 2024
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
10 changes: 10 additions & 0 deletions test/helpers/test_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "duckdb/parser/parsed_data/copy_info.hpp"
#include "duckdb/main/client_context.hpp"
#include "duckdb/execution/operator/csv_scanner/scanner/string_value_scanner.hpp"
#include "duckdb/common/case_insensitive_map.hpp"

#include "pid.hpp"
#include "duckdb/function/table/read_csv.hpp"
Expand All @@ -23,6 +24,7 @@ namespace duckdb {
static string custom_test_directory;
static int debug_initialize_value = -1;
static bool single_threaded = false;
static case_insensitive_set_t required_requires;

bool NO_FAIL(QueryResult &result) {
if (result.HasError()) {
Expand Down Expand Up @@ -89,6 +91,14 @@ void SetSingleThreaded() {
single_threaded = true;
}

void AddRequire(string require) {
required_requires.insert(require);
}

bool IsRequired(string require) {
return required_requires.count(require);
}

string GetTestDirectory() {
if (custom_test_directory.empty()) {
return TESTING_DIRECTORY_NAME;
Expand Down
2 changes: 2 additions & 0 deletions test/include/test_helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ bool TestIsInternalError(unordered_set<string> &internal_error_messages, const s
void SetTestDirectory(string path);
void SetDebugInitialize(int value);
void SetSingleThreaded();
void AddRequire(string require);
bool IsRequired(string require);
string GetTestDirectory();
string GetCSVPath();
void WriteCSV(string path, const char *csv);
Expand Down
271 changes: 168 additions & 103 deletions test/sqlite/sqllogic_test_runner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,168 @@ bool SQLLogicTestRunner::ForEachTokenReplace(const string &parameter, vector<str
return collection;
}

RequireResult SQLLogicTestRunner::CheckRequire(SQLLogicParser &parser, const vector<string> &params) {
if (params.size() < 1) {
parser.Fail("require requires a single parameter");
}
// require command
string param = StringUtil::Lower(params[0]);
// os specific stuff
if (param == "notmingw") {
#ifdef __MINGW32__
return RequireResult::MISSING;
#else
return RequireResult::PRESENT;
#endif
}

if (param == "mingw") {
#ifndef __MINGW32__
return RequireResult::MISSING;
#else
return RequireResult::PRESENT;
#endif
}

if (param == "notwindows") {
#ifdef _WIN32
return RequireResult::MISSING;
#else
return RequireResult::PRESENT;
#endif
}

if (param == "windows") {
#ifndef _WIN32
return RequireResult::MISSING;
#else
return RequireResult::PRESENT;
#endif
}

if (param == "longdouble") {
#if LDBL_MANT_DIG < 54
return RequireResult::MISSING;
#else
return RequireResult::PRESENT;
#endif
}

if (param == "64bit") {
if (sizeof(void *) != 8) {
return RequireResult::MISSING;
}
return RequireResult::PRESENT;
}

if (param == "noforcestorage") {
if (TestForceStorage()) {
return RequireResult::MISSING;
}
return RequireResult::PRESENT;
}

if (param == "nothreadsan") {
#ifdef DUCKDB_THREAD_SANITIZER
return RequireResult::MISSING;
#else
return RequireResult::PRESENT;
#endif
}

if (param == "strinline") {
#ifdef DUCKDB_DEBUG_NO_INLINE
return RequireResult::MISSING;
#else
return RequireResult::PRESENT;
#endif
}

if (param == "vector_size") {
if (params.size() != 2) {
parser.Fail("require vector_size requires a parameter");
}
// require a specific vector size
auto required_vector_size = std::stoi(params[1]);
if (STANDARD_VECTOR_SIZE < required_vector_size) {
// vector size is too low for this test: skip it
return RequireResult::MISSING;
}
return RequireResult::PRESENT;
}

if (param == "exact_vector_size") {
if (params.size() != 2) {
parser.Fail("require exact_vector_size requires a parameter");
}
// require an exact vector size
auto required_vector_size = std::stoi(params[1]);
if (STANDARD_VECTOR_SIZE != required_vector_size) {
// vector size does not match the required vector size: skip it
return RequireResult::MISSING;
}
return RequireResult::PRESENT;
}

if (param == "block_size") {
if (params.size() != 2) {
parser.Fail("require block_size requires a parameter");
}
// require a specific block size
auto required_block_size = std::stoi(params[1]);
if (Storage::BLOCK_ALLOC_SIZE != required_block_size) {
// block size does not match the required block size: skip it
return RequireResult::MISSING;
}
return RequireResult::PRESENT;
}

if (param == "skip_reload") {
skip_reload = true;
return RequireResult::PRESENT;
}

if (param == "noalternativeverify") {
#ifdef DUCKDB_ALTERNATIVE_VERIFY
return RequireResult::MISSING;
#else
return RequireResult::PRESENT;
#endif
}

if (param == "no_extension_autoloading") {
if (config->options.autoload_known_extensions) {
// If autoloading is on, we skip this test
return RequireResult::MISSING;
}
return RequireResult::PRESENT;
}

bool excluded_from_autoloading = true;
for (const auto &ext : AUTOLOADABLE_EXTENSIONS) {
if (ext == param) {
excluded_from_autoloading = false;
break;
}
}

if (!config->options.autoload_known_extensions) {
auto result = ExtensionHelper::LoadExtension(*db, param);
if (result == ExtensionLoadResult::LOADED_EXTENSION) {
// add the extension to the list of loaded extensions
extensions.insert(param);
} else if (result == ExtensionLoadResult::EXTENSION_UNKNOWN) {
parser.Fail("unknown extension type: %s", params[0]);
} else if (result == ExtensionLoadResult::NOT_LOADED) {
// extension known but not build: skip this test
return RequireResult::MISSING;
}
} else if (excluded_from_autoloading) {
return RequireResult::MISSING;
}
return RequireResult::PRESENT;
}

void SQLLogicTestRunner::ExecuteFile(string script) {
SQLLogicParser parser;
idx_t skip_level = 0;
Expand Down Expand Up @@ -473,111 +635,14 @@ void SQLLogicTestRunner::ExecuteFile(string script) {
} else if (token.type == SQLLogicTokenType::SQLLOGIC_ENDLOOP) {
EndLoop();
} else if (token.type == SQLLogicTokenType::SQLLOGIC_REQUIRE) {
if (token.parameters.size() < 1) {
parser.Fail("require requires a single parameter");
}
// require command
string param = StringUtil::Lower(token.parameters[0]);
// os specific stuff
if (param == "notmingw") {
#ifdef __MINGW32__
return;
#endif
} else if (param == "mingw") {
#ifndef __MINGW32__
return;
#endif
} else if (param == "notwindows") {
#ifdef _WIN32
return;
#endif
} else if (param == "windows") {
#ifndef _WIN32
return;
#endif
} else if (param == "longdouble") {
#if LDBL_MANT_DIG < 54
return;
#endif
} else if (param == "64bit") {
if (sizeof(void *) != 8) {
return;
auto require_result = CheckRequire(parser, token.parameters);
if (require_result == RequireResult::MISSING) {
auto &param = token.parameters[0];
if (IsRequired(param)) {
// This extension / setting was explicitly required
parser.Fail(StringUtil::Format("require %s: FAILED", param));
}
} else if (param == "noforcestorage") {
if (TestForceStorage()) {
return;
}
} else if (param == "nothreadsan") {
#ifdef DUCKDB_THREAD_SANITIZER
return;
#endif
} else if (param == "strinline") {
#ifdef DUCKDB_DEBUG_NO_INLINE
return;
#endif
} else if (param == "vector_size") {
if (token.parameters.size() != 2) {
parser.Fail("require vector_size requires a parameter");
}
// require a specific vector size
auto required_vector_size = std::stoi(token.parameters[1]);
if (STANDARD_VECTOR_SIZE < required_vector_size) {
// vector size is too low for this test: skip it
return;
}
} else if (param == "exact_vector_size") {
if (token.parameters.size() != 2) {
parser.Fail("require exact_vector_size requires a parameter");
}
// require an exact vector size
auto required_vector_size = std::stoi(token.parameters[1]);
if (STANDARD_VECTOR_SIZE != required_vector_size) {
// vector size does not match the required vector size: skip it
return;
}
} else if (param == "block_size") {
if (token.parameters.size() != 2) {
parser.Fail("require block_size requires a parameter");
}
// require a specific block size
auto required_block_size = std::stoi(token.parameters[1]);
if (Storage::BLOCK_ALLOC_SIZE != required_block_size) {
// block size does not match the required block size: skip it
return;
}
} else if (param == "skip_reload") {
skip_reload = true;
} else if (param == "noalternativeverify") {
#ifdef DUCKDB_ALTERNATIVE_VERIFY
return;
#endif
} else if (param == "no_extension_autoloading") {
if (config->options.autoload_known_extensions) {
return;
}
} else {
bool excluded_from_autoloading = true;
for (const auto &ext : AUTOLOADABLE_EXTENSIONS) {
if (ext == param) {
excluded_from_autoloading = false;
break;
}
}

if (!config->options.autoload_known_extensions) {
auto result = ExtensionHelper::LoadExtension(*db, param);
if (result == ExtensionLoadResult::LOADED_EXTENSION) {
// add the extension to the list of loaded extensions
extensions.insert(param);
} else if (result == ExtensionLoadResult::EXTENSION_UNKNOWN) {
parser.Fail("unknown extension type: %s", token.parameters[0]);
} else if (result == ExtensionLoadResult::NOT_LOADED) {
// extension known but not build: skip this test
return;
}
} else if (excluded_from_autoloading) {
return;
}
}
} else if (token.type == SQLLogicTokenType::SQLLOGIC_REQUIRE_ENV) {
if (InLoop()) {
Expand Down
6 changes: 6 additions & 0 deletions test/sqlite/sqllogic_test_runner.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ namespace duckdb {

class Command;
class LoopCommand;
class SQLLogicParser;

enum class RequireResult { PRESENT, MISSING };

class SQLLogicTestRunner {
public:
Expand Down Expand Up @@ -68,6 +71,9 @@ class SQLLogicTestRunner {
static string ReplaceLoopIterator(string text, string loop_iterator_name, string replacement);
static string LoopReplacement(string text, const vector<LoopDefinition> &loops);
static bool ForEachTokenReplace(const string &parameter, vector<string> &result);

private:
RequireResult CheckRequire(SQLLogicParser &parser, const vector<string> &params);
};

} // namespace duckdb
2 changes: 2 additions & 0 deletions test/unittest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ int main(int argc, char *argv[]) {
return 1;
}
SetTestDirectory(test_dir);
} else if (string(argv[i]) == "--require") {
AddRequire(string(argv[++i]));
} else if (string(argv[i]) == "--zero-initialize") {
SetDebugInitialize(0);
} else if (string(argv[i]) == "--one-initialize") {
Expand Down
Loading