Files
whetstone_DSL/editor/tests/step675_test.cpp

204 lines
6.6 KiB
C++

// Step 675: ContextSliceAssembler (12 tests)
#include "ContextSliceAssembler.h"
#include <filesystem>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
namespace fs = std::filesystem;
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; }
static fs::path makeTempDir(const std::string& suffix) {
fs::path dir = fs::temp_directory_path() / ("whetstone_step675_" + suffix);
std::error_code ec;
fs::remove_all(dir, ec);
fs::create_directories(dir, ec);
return dir;
}
static void writeFile(const fs::path& p, const std::string& content) {
std::error_code ec;
fs::create_directories(p.parent_path(), ec);
std::ofstream out(p);
out << content;
}
static std::string sourceText() {
return "int alpha() {\n"
" return 1;\n"
"}\n"
"class Demo {\n"
"public:\n"
" void run() {}\n"
"};\n"
"int beta() {\n"
" return 2;\n"
"}\n";
}
void t1() {
TEST(empty_requests_returns_empty_result);
WorkspaceFileIndex idx;
auto out = ContextSliceAssembler::assemble({}, idx);
CHECK(out.empty(), "expected empty");
PASS();
}
void t2() {
TEST(named_symbol_found_returns_correct_lines);
auto dir = makeTempDir("t2");
auto f = dir / "demo.cpp";
writeFile(f, sourceText());
auto idx = WorkspaceFileIndex::build(dir.string());
SliceRequest req{f.string(), "alpha", 0, 40};
auto out = ContextSliceAssembler::assemble({req}, idx);
CHECK(out.size() == 1, "expected one slice");
CHECK(out[0].found, "symbol should be found");
CHECK(out[0].content.find("int alpha()") != std::string::npos, "missing alpha");
PASS();
}
void t3() {
TEST(unknown_symbol_returns_head_fallback);
auto dir = makeTempDir("t3");
auto f = dir / "demo.cpp";
writeFile(f, sourceText());
auto idx = WorkspaceFileIndex::build(dir.string());
auto out = ContextSliceAssembler::assemble({{f.string(), "missing_symbol", 0, 2}}, idx);
CHECK(out.size() == 1, "expected one slice");
CHECK(!out[0].found, "found should be false");
CHECK(out[0].content.find("int alpha()") != std::string::npos, "fallback head missing");
PASS();
}
void t4() {
TEST(line_range_returns_correct_lines);
auto dir = makeTempDir("t4");
auto f = dir / "demo.cpp";
writeFile(f, sourceText());
auto idx = WorkspaceFileIndex::build(dir.string());
auto out = ContextSliceAssembler::assemble({{f.string(), "", 2, 2}}, idx);
CHECK(out.size() == 1, "expected one slice");
CHECK(out[0].lineStart == 2 && out[0].lineEnd == 3, "line range mismatch");
PASS();
}
void t5() {
TEST(content_non_empty_on_success);
auto dir = makeTempDir("t5");
auto f = dir / "demo.cpp";
writeFile(f, sourceText());
auto idx = WorkspaceFileIndex::build(dir.string());
auto out = ContextSliceAssembler::assemble({{f.string(), "beta", 0, 40}}, idx);
CHECK(!out.empty(), "slice missing");
CHECK(!out[0].content.empty(), "content empty");
PASS();
}
void t6() {
TEST(found_false_when_symbol_missing);
auto dir = makeTempDir("t6");
auto f = dir / "demo.cpp";
writeFile(f, sourceText());
auto idx = WorkspaceFileIndex::build(dir.string());
auto out = ContextSliceAssembler::assemble({{f.string(), "zzz", 0, 1}}, idx);
CHECK(out.size() == 1, "slice missing");
CHECK(!out[0].found, "should be false");
PASS();
}
void t7() {
TEST(multiple_requests_all_processed);
auto dir = makeTempDir("t7");
auto f = dir / "demo.cpp";
writeFile(f, sourceText());
auto idx = WorkspaceFileIndex::build(dir.string());
std::vector<SliceRequest> reqs = {
{f.string(), "alpha", 0, 40},
{f.string(), "beta", 0, 40},
{f.string(), "", 1, 1}
};
auto out = ContextSliceAssembler::assemble(reqs, idx);
CHECK(out.size() == 3, "expected 3 slices");
PASS();
}
void t8() {
TEST(head_fallback_respects_head_lines);
auto dir = makeTempDir("t8");
auto f = dir / "demo.cpp";
writeFile(f, sourceText());
auto idx = WorkspaceFileIndex::build(dir.string());
auto out = ContextSliceAssembler::assemble({{f.string(), "none", 0, 1}}, idx);
CHECK(out.size() == 1, "slice missing");
CHECK(out[0].lineEnd == 1, "headLines not respected");
PASS();
}
void t9() {
TEST(function_body_slice_includes_closing_brace);
auto dir = makeTempDir("t9");
auto f = dir / "demo.cpp";
writeFile(f, sourceText());
auto idx = WorkspaceFileIndex::build(dir.string());
auto out = ContextSliceAssembler::assemble({{f.string(), "alpha", 0, 40}}, idx);
CHECK(out.size() == 1, "slice missing");
CHECK(out[0].content.find("}") != std::string::npos, "closing brace not included");
PASS();
}
void t10() {
TEST(class_slice_includes_closing_brace);
auto dir = makeTempDir("t10");
auto f = dir / "demo.cpp";
writeFile(f, sourceText());
auto idx = WorkspaceFileIndex::build(dir.string());
auto out = ContextSliceAssembler::assemble({{f.string(), "Demo", 0, 40}}, idx);
CHECK(out.size() == 1, "slice missing");
CHECK(out[0].content.find("};") != std::string::npos, "class close not included");
PASS();
}
void t11() {
TEST(file_path_preserved_in_result);
auto dir = makeTempDir("t11");
auto f = dir / "demo.cpp";
writeFile(f, sourceText());
auto idx = WorkspaceFileIndex::build(dir.string());
auto out = ContextSliceAssembler::assemble({{f.string(), "alpha", 0, 40}}, idx);
CHECK(out.size() == 1, "slice missing");
CHECK(out[0].filePath == f.string(), "path not preserved");
PASS();
}
void t12() {
TEST(slice_content_is_substring_of_source);
auto dir = makeTempDir("t12");
auto f = dir / "demo.cpp";
const std::string src = sourceText();
writeFile(f, src);
auto idx = WorkspaceFileIndex::build(dir.string());
auto out = ContextSliceAssembler::assemble({{f.string(), "beta", 0, 40}}, idx);
CHECK(out.size() == 1, "slice missing");
CHECK(src.find(out[0].content.substr(0, std::min<size_t>(10, out[0].content.size()))) != std::string::npos,
"slice content not from source");
PASS();
}
int main() {
std::cout << "Step 675: ContextSliceAssembler\n";
t1(); t2(); t3(); t4(); t5(); t6();
t7(); t8(); t9(); t10(); t11(); t12();
std::cout << "\nResults: " << passed << "/" << (passed + failed) << " passed\n";
return failed == 0 ? 0 : 1;
}