blob: cf1bf2397f3c81e27fb6d3859a5d8bd9bb6896f0 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "test_framework.h"
#include <string>
#include <vector>
// External test suite declarations
extern opendal_test_suite basic_suite;
extern opendal_test_suite list_suite;
extern opendal_test_suite presign_suite;
extern opendal_test_suite reader_writer_suite;
// List of all test suites
static opendal_test_suite* all_suites[] = {
&basic_suite,
&list_suite,
&presign_suite,
&reader_writer_suite,
};
static const size_t num_suites = sizeof(all_suites) / sizeof(all_suites[0]);
void print_usage(const char* program_name)
{
printf("Usage: %s [options]\n", program_name);
printf("\nOptions:\n");
printf(" -h, --help Show this help message\n");
printf(" --list-suites List all available test suites\n");
printf(" --suite <name> Run only the specified test suite\n");
printf(" --test <suite::test> Run only the specified test case\n");
printf(" --verbose Enable verbose output\n");
printf("\nEnvironment Variables:\n");
printf(" OPENDAL_TEST Service to test (default: memory)\n");
printf(" OPENDAL_DISABLE_RANDOM_ROOT Set to 'true' to disable random root generation\n");
printf(" OPENDAL_<SERVICE>_<KEY> Service-specific configuration\n");
printf("\nExamples:\n");
printf(" %s # Run all tests with memory service\n", program_name);
printf(" %s --suite \"Basic Operations\" # Run only basic operations tests\n", program_name);
printf(" %s --test \"Basic Operations::check\" # Run only the check test\n", program_name);
printf(" OPENDAL_TEST=fs OPENDAL_FS_ROOT=/tmp %s # Test with filesystem service\n", program_name);
}
void list_suites()
{
printf("Available test suites:\n");
for (size_t i = 0; i < num_suites; i++) {
printf(" %s (%zu tests)\n", all_suites[i]->name, all_suites[i]->test_count);
for (size_t j = 0; j < all_suites[i]->test_count; j++) {
printf(" - %s::%s\n", all_suites[i]->name, all_suites[i]->tests[j].name);
}
}
}
bool run_specific_test(opendal_test_config* config, const char* suite_name, const char* test_name)
{
for (size_t i = 0; i < num_suites; i++) {
opendal_test_suite* suite = all_suites[i];
if (strcmp(suite->name, suite_name) == 0) {
for (size_t j = 0; j < suite->test_count; j++) {
if (strcmp(suite->tests[j].name, test_name) == 0) {
printf("Running specific test: %s::%s\n", suite_name, test_name);
opendal_run_test_case(&suite->tests[j], config, suite_name);
return true;
}
}
printf("Test '%s' not found in suite '%s'\n", test_name, suite_name);
return false;
}
}
printf("Suite '%s' not found\n", suite_name);
return false;
}
bool run_specific_suite(opendal_test_config* config, const char* suite_name)
{
for (size_t i = 0; i < num_suites; i++) {
if (strcmp(all_suites[i]->name, suite_name) == 0) {
opendal_run_test_suite(all_suites[i], config);
return true;
}
}
printf("Suite '%s' not found\n", suite_name);
return false;
}
void run_all_suites(opendal_test_config* config)
{
printf("Running all test suites...\n");
for (size_t i = 0; i < num_suites; i++) {
opendal_run_test_suite(all_suites[i], config);
}
}
int main(int argc, char* argv[])
{
bool verbose = false;
const char* suite_to_run = nullptr;
const char* test_to_run = nullptr;
// Parse command line arguments
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
print_usage(argv[0]);
return 0;
} else if (strcmp(argv[i], "--list-suites") == 0) {
list_suites();
return 0;
} else if (strcmp(argv[i], "--verbose") == 0) {
verbose = true;
} else if (strcmp(argv[i], "--suite") == 0) {
if (i + 1 < argc) {
suite_to_run = argv[++i];
} else {
printf("Error: --suite requires a suite name\n");
print_usage(argv[0]);
return 1;
}
} else if (strcmp(argv[i], "--test") == 0) {
if (i + 1 < argc) {
test_to_run = argv[++i];
} else {
printf("Error: --test requires a test specification (suite::test)\n");
print_usage(argv[0]);
return 1;
}
} else {
printf("Error: Unknown option '%s'\n", argv[i]);
print_usage(argv[0]);
return 1;
}
}
// Initialize test configuration
printf("Initializing OpenDAL test framework...\n");
opendal_test_config* config = opendal_test_config_new();
if (!config) {
printf("Failed to initialize test configuration\n");
return 1;
}
printf("Service: %s\n", config->scheme);
if (config->random_root) {
printf("Random root: %s\n", config->random_root);
}
// Check operator capabilities first
opendal_operator_info* info = opendal_operator_info_new(config->operator_instance);
if (!info) {
printf("Failed to get operator info\n");
opendal_test_config_free(config);
return 1;
}
opendal_capability cap = opendal_operator_info_get_full_capability(info);
// Check operator availability - only perform list-based check if list is supported
if (cap.list) {
opendal_error* check_error = opendal_operator_check(config->operator_instance);
if (check_error) {
printf("Operator check failed: error code %d\n", check_error->code);
if (check_error->message.data) {
printf("Error message: %.*s\n", (int)check_error->message.len, (char*)check_error->message.data);
}
opendal_error_free(check_error);
opendal_operator_info_free(info);
opendal_test_config_free(config);
return 1;
}
} else {
// For KV adapters that don't support list, we'll do a basic capability check instead
printf("Note: Operator doesn't support list operations (KV adapter), skipping standard check\n");
}
printf("Operator is ready!\n");
printf("Capabilities: read=%s, write=%s, list=%s, stat=%s, delete=%s\n",
cap.read ? "yes" : "no",
cap.write ? "yes" : "no",
cap.list ? "yes" : "no",
cap.stat ? "yes" : "no",
cap.delete_ ? "yes" : "no");
opendal_operator_info_free(info);
printf("\n");
// Run tests based on command line arguments
if (test_to_run) {
// Parse suite::test format
char* test_spec = strdup(test_to_run);
char* delimiter = strstr(test_spec, "::");
if (!delimiter) {
printf("Error: Test specification must be in format 'suite::test'\n");
free(test_spec);
opendal_test_config_free(config);
return 1;
}
*delimiter = '\0';
const char* suite_name = test_spec;
const char* test_name = delimiter + 2;
bool success = run_specific_test(config, suite_name, test_name);
free(test_spec);
if (!success) {
opendal_test_config_free(config);
return 1;
}
} else if (suite_to_run) {
bool success = run_specific_suite(config, suite_to_run);
if (!success) {
opendal_test_config_free(config);
return 1;
}
} else {
run_all_suites(config);
}
// Print test summary
opendal_print_test_summary();
// Cleanup
opendal_test_config_free(config);
// Return appropriate exit code
return (failed_tests > 0) ? 1 : 0;
}