98 lines
3.6 KiB
C++
98 lines
3.6 KiB
C++
|
|
// Step 1970: LSPSymbolExtractor
|
||
|
|
//
|
||
|
|
// t1: parses valid JSON into correct records
|
||
|
|
// t2: functionName and signature populated from JSON
|
||
|
|
// t3: caveats array parsed correctly
|
||
|
|
// t4: returns error for invalid JSON
|
||
|
|
// t5: empty symbols array produces empty records; missing name skipped
|
||
|
|
|
||
|
|
#include "LSPSymbolExtractor.h"
|
||
|
|
#include <iostream>
|
||
|
|
#include <string>
|
||
|
|
|
||
|
|
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; }
|
||
|
|
|
||
|
|
// Use named delimiter to avoid R"(...)"-terminator collision with JSON content.
|
||
|
|
static const std::string CUBLAS_JSON = R"JSON({
|
||
|
|
"symbols": [
|
||
|
|
{"name": "cublasSgemm", "signature": "cublasStatus_t cublasSgemm(...)", "usage": "cublasSgemm(handle, ...)"},
|
||
|
|
{"name": "cublasDgemm", "signature": "cublasStatus_t cublasDgemm(...)"}
|
||
|
|
]
|
||
|
|
})JSON";
|
||
|
|
|
||
|
|
void t1() {
|
||
|
|
T(parses_valid_json_into_records);
|
||
|
|
ws::LSPSymbolExtractor ex;
|
||
|
|
auto res = ex.extract("cublas", "compute.matrix", CUBLAS_JSON);
|
||
|
|
C(res.success, "success");
|
||
|
|
C(res.error.empty(), "no error");
|
||
|
|
C(res.records.size() == 2, "2 records parsed");
|
||
|
|
C(res.records[0].libraryId == "cublas", "libraryId set");
|
||
|
|
C(res.records[0].operationDomain == "compute.matrix", "domain set");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
void t2() {
|
||
|
|
T(functionName_and_signature_populated);
|
||
|
|
ws::LSPSymbolExtractor ex;
|
||
|
|
auto res = ex.extract("cublas", "compute.matrix", CUBLAS_JSON);
|
||
|
|
C(res.records[0].functionName == "cublasSgemm", "first functionName");
|
||
|
|
C(res.records[0].signature.find("cublasSgemm") != std::string::npos, "first signature");
|
||
|
|
C(res.records[0].usagePattern.find("handle") != std::string::npos, "usagePattern");
|
||
|
|
C(res.records[1].functionName == "cublasDgemm", "second functionName");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
void t3() {
|
||
|
|
T(caveats_array_parsed);
|
||
|
|
const std::string json = R"JSON({"symbols": [
|
||
|
|
{"name": "myFunc", "signature": "void myFunc()",
|
||
|
|
"caveats": ["must-call-init-first", "not-thread-safe"]}
|
||
|
|
]})JSON";
|
||
|
|
ws::LSPSymbolExtractor ex;
|
||
|
|
auto res = ex.extract("mylib", "mydom", json);
|
||
|
|
C(res.success, "success");
|
||
|
|
C(res.records.size() == 1, "1 record");
|
||
|
|
C(res.records[0].caveats.size() == 2, "2 caveats");
|
||
|
|
C(res.records[0].caveats[0] == "must-call-init-first", "first caveat");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
void t4() {
|
||
|
|
T(returns_error_for_invalid_json);
|
||
|
|
ws::LSPSymbolExtractor ex;
|
||
|
|
auto res = ex.extract("lib", "dom", "{ not valid json !!!");
|
||
|
|
C(!res.success, "failure for invalid json");
|
||
|
|
C(!res.error.empty(), "error message set");
|
||
|
|
C(res.records.empty(), "no records on error");
|
||
|
|
// Missing symbols key
|
||
|
|
auto res2 = ex.extract("lib", "dom", R"JSON({"other": []})JSON");
|
||
|
|
C(!res2.success, "failure for missing symbols key");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
void t5() {
|
||
|
|
T(empty_symbols_and_missing_name_skipped);
|
||
|
|
ws::LSPSymbolExtractor ex;
|
||
|
|
auto res = ex.extract("lib", "dom", R"JSON({"symbols": []})JSON");
|
||
|
|
C(res.success, "success for empty array");
|
||
|
|
C(res.records.empty(), "no records for empty array");
|
||
|
|
// Symbol with empty name skipped
|
||
|
|
auto res2 = ex.extract("lib", "dom", R"JSON({"symbols": [{"name": "", "signature": "sig"}]})JSON");
|
||
|
|
C(res2.success, "success");
|
||
|
|
C(res2.records.empty(), "empty-name record skipped");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
int main() {
|
||
|
|
std::cout << "Step 1970: LSPSymbolExtractor\n";
|
||
|
|
t1(); t2(); t3(); t4(); t5();
|
||
|
|
std::cout << "\n" << p << "/" << (p + f) << " passed\n";
|
||
|
|
return f > 0 ? 1 : 0;
|
||
|
|
}
|