Files
whetstone_DSL/editor/tests/step1925_test.cpp

108 lines
4.0 KiB
C++
Raw Normal View History

// Step 1925: PolyglotStackTraceDecoder
// Decodes flat raw frames into language-annotated StackFrames.
//
// t1: languageFromSource infers language from extension
// t2: decode sets language and astNodeId per frame
// t3: single-language stack: no boundary frames
// t4: two-language stack: boundary frames marked at seam
// t5: three-language stack: multiple boundary regions
#include "PolyglotStackTraceDecoder.h"
#include <iostream>
namespace ws = whetstone;
static int p=0,f=0;
#define T(n) { std::cout<<" "<<#n<<"... "; }
#define P() { std::cout<<"PASS\n"; ++p; }
#define F(m) { std::cout<<"FAIL: "<<m<<"\n"; ++f; }
#define C(c,m) if(!(c)){F(m);return;}
static ws::RawFrame rf(int id, const std::string& name, const std::string& src, int line=1){
return {id, name, src, line};
}
void t1(){
T(languageFromSource);
C(ws::PolyglotStackTraceDecoder::languageFromSource("main.py") == "Python", ".py");
C(ws::PolyglotStackTraceDecoder::languageFromSource("lib.rs") == "Rust", ".rs");
C(ws::PolyglotStackTraceDecoder::languageFromSource("server.go") == "Go", ".go");
C(ws::PolyglotStackTraceDecoder::languageFromSource("app.ts") == "TypeScript", ".ts");
C(ws::PolyglotStackTraceDecoder::languageFromSource("app.js") == "TypeScript", ".js");
C(ws::PolyglotStackTraceDecoder::languageFromSource("util.cpp") == "C++", ".cpp");
C(ws::PolyglotStackTraceDecoder::languageFromSource("util.h") == "C++", ".h");
C(ws::PolyglotStackTraceDecoder::languageFromSource("noext") == "Unknown", "no ext");
P();
}
void t2(){
T(decode_sets_language_and_astNodeId);
ws::PolyglotStackTraceDecoder dec;
auto frames = dec.decode({rf(1,"main","main.py"), rf(2,"sort_array","lib.rs")});
C(frames.size() == 2, "two frames");
C(frames[0].language == "Python", "frame0 Python");
C(frames[0].astNodeId == "Python:main","frame0 astNodeId");
C(frames[1].language == "Rust", "frame1 Rust");
C(frames[1].astNodeId == "Rust:sort_array","frame1 astNodeId");
C(frames[0].id == 1, "id preserved");
C(frames[0].name == "main", "name preserved");
P();
}
void t3(){
T(single_language_no_boundaries);
ws::PolyglotStackTraceDecoder dec;
auto frames = dec.decode({
rf(1,"main", "main.py"),
rf(2,"process","process.py"),
rf(3,"helper", "helper.py")
});
for (auto& fr : frames)
C(!fr.isBoundary, fr.name + " should not be boundary");
P();
}
void t4(){
T(two_language_boundary_at_seam);
ws::PolyglotStackTraceDecoder dec;
// Python frames then Rust frame
auto frames = dec.decode({
rf(1,"run", "main.py"),
rf(2,"generate", "data.py"),
rf(3,"sort_array", "sorter.rs"),
});
C(!frames[0].isBoundary, "run: not boundary (only next differs)");
// frame[1] "generate": next is Rust → boundary
C( frames[1].isBoundary, "generate: boundary (next is Rust)");
// frame[2] "sort_array": prev is Python → boundary
C( frames[2].isBoundary, "sort_array: boundary (prev is Python)");
P();
}
void t5(){
T(three_language_multiple_boundaries);
ws::PolyglotStackTraceDecoder dec;
auto frames = dec.decode({
rf(1,"py_main", "main.py"), // Python
rf(2,"rs_sort", "sort.rs"), // Rust ← seam
rf(3,"rs_inner", "inner.rs"), // Rust
rf(4,"go_send", "sender.go"), // Go ← seam
});
// py_main: next=Rust → boundary
C( frames[0].isBoundary, "py_main boundary (next is Rust)");
// rs_sort: prev=Python, next=Rust → boundary (prev diff only)
C( frames[1].isBoundary, "rs_sort boundary (prev Python)");
// rs_inner: next=Go → boundary
C( frames[2].isBoundary, "rs_inner boundary (next Go)");
// go_send: prev=Rust → boundary
C( frames[3].isBoundary, "go_send boundary (prev Rust)");
P();
}
int main(){
std::cout << "Step 1925: PolyglotStackTraceDecoder\n";
t1(); t2(); t3(); t4(); t5();
std::cout << "\n" << p << "/" << (p+f) << " passed\n";
return f > 0 ? 1 : 0;
}