204 lines
7.6 KiB
C++
204 lines
7.6 KiB
C++
// Step 412: PostgreSQL Generator Tests (12 tests)
|
|
|
|
#include "ast/PostgreSQLGenerator.h"
|
|
#include "ast/PostgreSQLParser.h"
|
|
#include "Pipeline.h"
|
|
#include "ast/SqlNodes.h"
|
|
#include "ast/Annotation.h"
|
|
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
static int passed = 0, failed = 0;
|
|
#define TEST(name) { std::cout << " " << #name << "... "; }
|
|
#define PASS() { std::cout << "PASS\n"; ++passed; }
|
|
#define FAIL(msg) { std::cout << "FAIL: " << msg << "\n"; ++failed; }
|
|
#define CHECK(cond, msg) if (!(cond)) { FAIL(msg); return; } else {}
|
|
|
|
void test_generate_create_table_with_columns() {
|
|
TEST(generate_create_table_with_columns);
|
|
TableDeclaration t("t1", "users");
|
|
t.addChild("columns", new ColumnDefinition("c1", "id", "SERIAL", false));
|
|
t.addChild("columns", new ColumnDefinition("c2", "name", "TEXT", false));
|
|
|
|
PostgreSQLGenerator gen;
|
|
std::string out = gen.generate(&t);
|
|
CHECK(out.find("CREATE TABLE users") != std::string::npos, "expected create table");
|
|
CHECK(out.find("id SERIAL NOT NULL") != std::string::npos, "expected id column");
|
|
CHECK(out.find("name TEXT NOT NULL") != std::string::npos, "expected name column");
|
|
PASS();
|
|
}
|
|
|
|
void test_generate_select_distinct_join_where() {
|
|
TEST(generate_select_distinct_join_where);
|
|
SelectQuery q;
|
|
q.id = "q1";
|
|
q.distinct = true;
|
|
q.addChild("columns", new ColumnDefinition("c1", "id", "INTEGER"));
|
|
q.setChild("from", new TableDeclaration("t1", "users"));
|
|
auto* j = new JoinClause("j1", "LEFT", "orders");
|
|
j->setChild("on", new WhereClause("w1", "users.id = orders.user_id"));
|
|
q.addChild("joins", j);
|
|
q.setChild("where", new WhereClause("w2", "users.active = TRUE"));
|
|
|
|
PostgreSQLGenerator gen;
|
|
std::string out = gen.generate(&q);
|
|
CHECK(out.find("SELECT DISTINCT") != std::string::npos, "expected distinct");
|
|
CHECK(out.find("LEFT JOIN orders") != std::string::npos, "expected join");
|
|
CHECK(out.find("WHERE users.active = TRUE") != std::string::npos, "expected where");
|
|
PASS();
|
|
}
|
|
|
|
void test_generate_insert_statement() {
|
|
TEST(generate_insert_statement);
|
|
InsertStatement ins("i1", "users");
|
|
ins.addChild("columns", new ColumnDefinition("c1", "id", "INTEGER"));
|
|
ins.addChild("columns", new ColumnDefinition("c2", "name", "TEXT"));
|
|
ins.addChild("values", new IntegerLiteral("v1", 1));
|
|
ins.addChild("values", new StringLiteral("v2", "alice"));
|
|
|
|
PostgreSQLGenerator gen;
|
|
std::string out = gen.generate(&ins);
|
|
CHECK(out.find("INSERT INTO users") != std::string::npos, "expected insert target");
|
|
CHECK(out.find("(id, name)") != std::string::npos, "expected column list");
|
|
CHECK(out.find("VALUES (1, 'alice')") != std::string::npos, "expected values list");
|
|
PASS();
|
|
}
|
|
|
|
void test_generate_update_statement() {
|
|
TEST(generate_update_statement);
|
|
UpdateStatement up("u1", "users");
|
|
auto* set = new Assignment();
|
|
set->id = "a1";
|
|
set->setChild("target", new VariableReference("vr1", "name"));
|
|
set->setChild("value", new StringLiteral("s1", "bob"));
|
|
up.addChild("set", set);
|
|
up.setChild("where", new WhereClause("w1", "id = 1"));
|
|
|
|
PostgreSQLGenerator gen;
|
|
std::string out = gen.generate(&up);
|
|
CHECK(out.find("UPDATE users SET") != std::string::npos, "expected update");
|
|
CHECK(out.find("name = 'bob'") != std::string::npos, "expected set assignment");
|
|
CHECK(out.find("WHERE id = 1") != std::string::npos, "expected where");
|
|
PASS();
|
|
}
|
|
|
|
void test_generate_delete_statement() {
|
|
TEST(generate_delete_statement);
|
|
DeleteStatement del("d1", "users");
|
|
del.setChild("where", new WhereClause("w1", "id = 7"));
|
|
|
|
PostgreSQLGenerator gen;
|
|
std::string out = gen.generate(&del);
|
|
CHECK(out == "DELETE FROM users WHERE id = 7;", "expected delete sql");
|
|
PASS();
|
|
}
|
|
|
|
void test_generate_index_definition() {
|
|
TEST(generate_index_definition);
|
|
IndexDefinition idx("x1", "idx_users_email", "users", true);
|
|
idx.addChild("columns", new ColumnDefinition("c1", "email", "TEXT"));
|
|
|
|
PostgreSQLGenerator gen;
|
|
std::string out = gen.generate(&idx);
|
|
CHECK(out.find("CREATE UNIQUE INDEX idx_users_email ON users") != std::string::npos,
|
|
"expected unique index");
|
|
CHECK(out.find("(email)") != std::string::npos, "expected index column");
|
|
PASS();
|
|
}
|
|
|
|
void test_generate_module_with_statements() {
|
|
TEST(generate_module_with_statements);
|
|
Module mod;
|
|
mod.id = "m1";
|
|
mod.name = "sql_mod";
|
|
mod.addChild("statements", new DeleteStatement("d1", "logs"));
|
|
|
|
PostgreSQLGenerator gen;
|
|
std::string out = gen.generate(&mod);
|
|
CHECK(out.find("-- Module: sql_mod") != std::string::npos, "expected module header");
|
|
CHECK(out.find("DELETE FROM logs;") != std::string::npos, "expected statement content");
|
|
PASS();
|
|
}
|
|
|
|
void test_generate_where_clause_passthrough() {
|
|
TEST(generate_where_clause_passthrough);
|
|
WhereClause where("w1", "status = 'ok'");
|
|
PostgreSQLGenerator gen;
|
|
std::string out = gen.generate(&where);
|
|
CHECK(out == "WHERE status = 'ok'", "expected where passthrough");
|
|
PASS();
|
|
}
|
|
|
|
void test_comment_prefix_and_semanno_output() {
|
|
TEST(comment_prefix_and_semanno_output);
|
|
Function fn("f1", "process");
|
|
auto* risk = new RiskAnnotation();
|
|
risk->id = "r1";
|
|
risk->level = "medium";
|
|
fn.addChild("annotations", risk);
|
|
|
|
PostgreSQLGenerator gen;
|
|
std::string out = gen.generate(&fn);
|
|
CHECK(gen.commentPrefix() == "-- ", "expected postgres comment prefix");
|
|
CHECK(out.find("@semanno:risk") != std::string::npos, "expected semanno output");
|
|
PASS();
|
|
}
|
|
|
|
void test_pipeline_generate_routing_aliases() {
|
|
TEST(pipeline_generate_routing_aliases);
|
|
DeleteStatement del("d1", "audit");
|
|
Pipeline p;
|
|
std::string o1 = p.generate(&del, "postgresql");
|
|
std::string o2 = p.generate(&del, "postgres");
|
|
CHECK(o1 == "DELETE FROM audit;", "postgresql route");
|
|
CHECK(o2 == "DELETE FROM audit;", "postgres route");
|
|
PASS();
|
|
}
|
|
|
|
void test_parser_to_generator_create_table_flow() {
|
|
TEST(parser_to_generator_create_table_flow);
|
|
auto mod = PostgreSQLParser::parsePostgreSQL(
|
|
"CREATE TABLE events (id SERIAL, payload JSONB, tags TEXT[]);\n");
|
|
CHECK(mod != nullptr, "module null");
|
|
|
|
PostgreSQLGenerator gen;
|
|
std::string out = gen.generate(mod.get());
|
|
CHECK(out.find("CREATE TABLE events") != std::string::npos, "expected create table");
|
|
CHECK(out.find("payload JSONB") != std::string::npos, "expected jsonb column");
|
|
CHECK(out.find("tags TEXT[]") != std::string::npos, "expected array column");
|
|
PASS();
|
|
}
|
|
|
|
void test_generate_select_edge_case_defaults_to_star() {
|
|
TEST(generate_select_edge_case_defaults_to_star);
|
|
SelectQuery q;
|
|
q.id = "q2";
|
|
PostgreSQLGenerator gen;
|
|
std::string out = gen.generate(&q);
|
|
CHECK(out == "SELECT *;", "expected default select star");
|
|
PASS();
|
|
}
|
|
|
|
int main() {
|
|
std::cout << "Step 412: PostgreSQL Generator Tests\n";
|
|
|
|
test_generate_create_table_with_columns(); // 1
|
|
test_generate_select_distinct_join_where(); // 2
|
|
test_generate_insert_statement(); // 3
|
|
test_generate_update_statement(); // 4
|
|
test_generate_delete_statement(); // 5
|
|
test_generate_index_definition(); // 6
|
|
test_generate_module_with_statements(); // 7
|
|
test_generate_where_clause_passthrough(); // 8
|
|
test_comment_prefix_and_semanno_output(); // 9
|
|
test_pipeline_generate_routing_aliases(); // 10
|
|
test_parser_to_generator_create_table_flow(); // 11
|
|
test_generate_select_edge_case_defaults_to_star(); // 12
|
|
|
|
std::cout << "\nResults: " << passed << "/" << (passed + failed)
|
|
<< " passed\n";
|
|
return failed == 0 ? 0 : 1;
|
|
}
|