// E2E self-test del playground tables. Ejercita la logica pura // (data_table_logic) sin ImGui. Build target separado: // // tables_playground_self_test -> linux // tables_playground_self_test.exe -> windows // // Exit 0 = todos los checks pasan, 1 = falla. #include "data_table_logic.h" #include #include #include #include namespace { int failed = 0; int passed = 0; void check(bool cond, const char* name) { if (cond) { passed++; std::printf("PASS %s\n", name); } else { failed++; std::printf("FAIL %s\n", name); } } } // namespace using namespace data_table; int main() { // --- parse_number --- double v = 0; check(parse_number("1.23", v) && v == 1.23, "parse_number 1.23"); check(parse_number("42", v) && v == 42.0, "parse_number 42"); check(parse_number("-7.5", v) && v == -7.5, "parse_number -7.5"); check(!parse_number("abc", v), "parse_number abc rejected"); check(!parse_number("12x", v), "parse_number 12x rejected"); check(!parse_number("", v), "parse_number empty rejected"); check(!parse_number(nullptr, v), "parse_number null rejected"); // --- compare numerico --- check( compare("10", "2", Op::Gt), "10 > 2 numerico"); check(!compare("10", "2", Op::Lt), "10 < 2 numerico false"); check( compare("2", "10", Op::Lt), "2 < 10 numerico"); check( compare("5", "5", Op::Eq), "5 == 5 numerico"); check( compare("5", "5", Op::Gte), "5 >= 5 numerico"); check( compare("5", "5", Op::Lte), "5 <= 5 numerico"); check( compare("5", "5", Op::Neq) == false, "5 != 5 numerico false"); // --- compare lexical (cuando no son numeros) --- check( compare("go", "go", Op::Eq), "lexical eq"); check( compare("go", "py", Op::Neq), "lexical neq"); check( compare("py", "go", Op::Gt), "lexical gt"); check( compare("ab", "ac", Op::Lt), "lexical lt"); // --- compute_visible_rows: filter --- const char* cells[] = { "a","1", "b","2", "c","3", "a","4", }; State st; st.filters.push_back({0, Op::Eq, "a"}); auto rows = compute_visible_rows(cells, 4, 2, st); check(rows.size() == 2 && rows[0] == 0 && rows[1] == 3, "filter col0 = a"); // --- filter numerico --- st.filters.clear(); st.filters.push_back({1, Op::Gt, "2"}); rows = compute_visible_rows(cells, 4, 2, st); check(rows.size() == 2 && rows[0] == 2 && rows[1] == 3, "filter col1 > 2"); // --- combinacion: > 1 AND col0 != b --- st.filters.clear(); st.filters.push_back({1, Op::Gt, "1"}); st.filters.push_back({0, Op::Neq, "b"}); rows = compute_visible_rows(cells, 4, 2, st); check(rows.size() == 2 && rows[0] == 2 && rows[1] == 3, "filter combinado AND"); // --- sort ascendente numerico --- st.filters.clear(); st.sort_col = 1; st.sort_desc = false; rows = compute_visible_rows(cells, 4, 2, st); check(rows.size() == 4 && rows[0] == 0 && rows[3] == 3, "sort asc numerico"); // --- sort descendente numerico --- st.sort_desc = true; rows = compute_visible_rows(cells, 4, 2, st); check(rows.size() == 4 && rows[0] == 3 && rows[3] == 0, "sort desc numerico"); // --- sort lexical --- st.sort_col = 0; st.sort_desc = false; rows = compute_visible_rows(cells, 4, 2, st); check(rows.size() == 4 && std::strcmp(cells[rows[0]*2], "a") == 0 && std::strcmp(cells[rows[3]*2], "c") == 0, "sort asc lexical"); // --- filter + sort combinado --- st.sort_col = 1; st.sort_desc = true; st.filters.push_back({0, Op::Eq, "a"}); rows = compute_visible_rows(cells, 4, 2, st); check(rows.size() == 2 && rows[0] == 3 && rows[1] == 0, "filter+sort combinado"); // --- filter sobre columna inexistente: se ignora --- st.filters.clear(); st.filters.push_back({99, Op::Eq, "x"}); st.sort_col = -1; rows = compute_visible_rows(cells, 4, 2, st); check(rows.size() == 4, "filter col fuera de rango ignorado"); std::printf("\n=== %d passed, %d failed ===\n", passed, failed); return failed == 0 ? 0 : 1; }