Updated tests and testing built in modules
This commit is contained in:
parent
7f7c6e438d
commit
6e3379b5b8
@ -260,7 +260,7 @@ toInt(3.9); // 3 (global)
|
||||
assert(condition, "message"); // Testing
|
||||
time(); // Current time in microseconds
|
||||
sleep(1.5); // Sleep for 1.5 seconds
|
||||
random(); // Random number 0-1
|
||||
rand.random(); // Random number 0-1
|
||||
eval("print('Hello');"); // Execute string as code
|
||||
exit(0); // Exit program
|
||||
```
|
||||
@ -297,7 +297,7 @@ The following built-ins are available by default. Unless specified, functions th
|
||||
- fileExists(path): boolean
|
||||
- time(): microseconds since Unix epoch
|
||||
- sleep(seconds): pauses execution
|
||||
- random(): float in [0,1)
|
||||
- rand.random(): float in [0,1)
|
||||
- eval(code): executes code string in current environment
|
||||
- exit(code?): terminates the program
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ Bob is a mature, working programming language with a modern architecture and com
|
||||
- **Type System**: `type()`, `toString()`, `toNumber()`, `toInt()`, `toBoolean()`
|
||||
- **Testing**: `assert()` with custom error messages
|
||||
- **Timing**: `time()` (microsecond precision), `sleep()`
|
||||
- **Utility**: `random()` (properly seeded), `eval()`, `exit()`
|
||||
- **Utility**: `rand.random()` (properly seeded), `eval.eval()`, `sys.exit()`
|
||||
- **Data Structure**: `len()`, `push()`, `pop()`, `keys()`, `values()`, `has()`
|
||||
- **File I/O**: `readFile()`, `writeFile()`, `readLines()`, `fileExists()`
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ This extension provides syntax highlighting and language support for the Bob pro
|
||||
- `print()`, `assert()`, `input()`, `type()`, `toString()`, `toNumber()`, `toInt()`, `time()`, `sleep()`, `printRaw()`
|
||||
- Arrays/Dictionaries (preferred method style): `arr.len()`, `arr.push(...)`, `arr.pop()`, `dict.len()`, `dict.keys()`, `dict.values()`, `dict.has()`
|
||||
- Global forms still available: `len(x)`, `push(arr, ...)`, `pop(arr)`, `keys(dict)`, `values(dict)`, `has(dict, key)`
|
||||
- Misc: `random()`, `eval()`
|
||||
- Misc: `rand.random()`, `eval.eval()`
|
||||
|
||||
### Data Types
|
||||
- Numbers (integers, floats, binary `0b1010`, hex `0xFF`)
|
||||
|
||||
@ -91,7 +91,7 @@ value *= 2;
|
||||
value -= 3;
|
||||
|
||||
// New built-in functions
|
||||
var randomValue = random();
|
||||
import rand; var randomValue = rand.random();
|
||||
sleep(100); // Sleep for 100ms
|
||||
printRaw("No newline here");
|
||||
eval("print('Dynamic code execution!');");
|
||||
|
||||
@ -300,7 +300,7 @@
|
||||
"Random Number": {
|
||||
"prefix": "random",
|
||||
"body": [
|
||||
"var randomValue = random();"
|
||||
"import rand; var randomValue = rand.random();"
|
||||
],
|
||||
"description": "Generate random number"
|
||||
},
|
||||
|
||||
@ -151,8 +151,9 @@ input("File data cleared. Check memory usage...");
|
||||
print("Test 6: Random number stress");
|
||||
var randomData = [];
|
||||
for (var i = 0; i < 200000; i++) {
|
||||
var rand1 = random();
|
||||
var rand2 = random();
|
||||
import rand as RLeak;
|
||||
var rand1 = RLeak.random();
|
||||
var rand2 = RLeak.random();
|
||||
var sum = rand1 + rand2;
|
||||
|
||||
randomData.push({
|
||||
|
||||
@ -27,7 +27,9 @@ void registerPathModule(Interpreter& interpreter) {
|
||||
m.fn("splitext", [](std::vector<Value> a, int, int) -> Value {
|
||||
if (a.size()!=1 || !a[0].isString()) return NONE_VALUE;
|
||||
fs::path p(a[0].asString());
|
||||
return Value(std::vector<Value>{ Value(p.replace_extension("").generic_string()), Value(p.extension().generic_string()) });
|
||||
std::string ext = p.has_extension() ? p.extension().generic_string() : std::string("");
|
||||
fs::path basePath = p.has_extension() ? (p.parent_path() / p.stem()) : p;
|
||||
return Value(std::vector<Value>{ Value(basePath.generic_string()), Value(ext) });
|
||||
});
|
||||
m.fn("normalize", [](std::vector<Value> a, int, int) -> Value {
|
||||
if (a.size()!=1 || !a[0].isString()) return NONE_VALUE;
|
||||
|
||||
@ -8,6 +8,18 @@
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
// Platform-specific includes for memoryUsage()
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
#include <mach/mach.h>
|
||||
#elif defined(__linux__)
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#elif defined(_WIN32)
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#endif
|
||||
|
||||
void registerSysModule(Interpreter& interpreter) {
|
||||
interpreter.registerModule("sys", [](Interpreter::ModuleBuilder& m) {
|
||||
Interpreter& I = m.interpreterRef;
|
||||
@ -37,6 +49,40 @@ void registerSysModule(Interpreter& interpreter) {
|
||||
auto snapshot = I.getModuleCacheSnapshot();
|
||||
return Value(snapshot);
|
||||
});
|
||||
// memoryUsage(): process RSS in MB (best effort per-platform)
|
||||
m.fn("memoryUsage", [](std::vector<Value> a, int, int) -> Value {
|
||||
if (!a.empty()) return NONE_VALUE;
|
||||
size_t memoryBytes = 0;
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
// macOS
|
||||
struct mach_task_basic_info info;
|
||||
mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
|
||||
if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount) == KERN_SUCCESS) {
|
||||
memoryBytes = info.resident_size;
|
||||
}
|
||||
#elif defined(__linux__)
|
||||
// Linux
|
||||
std::ifstream statusFile("/proc/self/status");
|
||||
std::string line;
|
||||
while (std::getline(statusFile, line)) {
|
||||
if (line.substr(0, 6) == "VmRSS:") {
|
||||
std::istringstream iss(line);
|
||||
std::string label, value, unit;
|
||||
iss >> label >> value >> unit;
|
||||
memoryBytes = std::stoull(value) * 1024; // KB -> bytes
|
||||
break;
|
||||
}
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
// Windows
|
||||
PROCESS_MEMORY_COUNTERS pmc;
|
||||
if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
|
||||
memoryBytes = pmc.WorkingSetSize;
|
||||
}
|
||||
#endif
|
||||
double memoryMB = static_cast<double>(memoryBytes) / (1024.0 * 1024.0);
|
||||
return Value(memoryMB);
|
||||
});
|
||||
m.fn("exit", [](std::vector<Value> a, int, int) -> Value {
|
||||
int code = 0; if (!a.empty() && a[0].isNumber()) code = static_cast<int>(a[0].asNumber());
|
||||
std::exit(code);
|
||||
|
||||
@ -290,24 +290,7 @@ void BobStdLib::addToEnvironment(std::shared_ptr<Environment> env, Interpreter&
|
||||
// Store the shared_ptr in the interpreter to keep it alive
|
||||
interpreter.addBuiltinFunction(toBooleanFunc);
|
||||
|
||||
// Create a built-in exit function to terminate the program
|
||||
auto exitFunc = std::make_shared<BuiltinFunction>("exit",
|
||||
[](std::vector<Value> args, int line, int column) -> Value {
|
||||
int exitCode = 0; // Default exit code
|
||||
|
||||
if (args.size() > 0) {
|
||||
if (args[0].isNumber()) {
|
||||
exitCode = static_cast<int>(args[0].asNumber());
|
||||
}
|
||||
// If not a number, just use default exit code 0
|
||||
}
|
||||
|
||||
std::exit(exitCode);
|
||||
});
|
||||
env->define("exit", Value(exitFunc));
|
||||
|
||||
// Store the shared_ptr in the interpreter to keep it alive
|
||||
interpreter.addBuiltinFunction(exitFunc);
|
||||
// exit moved to sys module
|
||||
|
||||
// sleep moved into builtin time module
|
||||
|
||||
@ -353,30 +336,7 @@ void BobStdLib::addToEnvironment(std::shared_ptr<Environment> env, Interpreter&
|
||||
env->define("functions", Value(functionsFunc));
|
||||
interpreter.addBuiltinFunction(functionsFunc);
|
||||
|
||||
// Create a built-in random function
|
||||
auto randomFunc = std::make_shared<BuiltinFunction>("random",
|
||||
[errorReporter](std::vector<Value> args, int line, int column) -> Value {
|
||||
if (args.size() != 0) {
|
||||
if (errorReporter) {
|
||||
errorReporter->reportError(line, column, "StdLib Error",
|
||||
"Expected 0 arguments but got " + std::to_string(args.size()) + ".", "", true);
|
||||
}
|
||||
throw std::runtime_error("Expected 0 arguments but got " + std::to_string(args.size()) + ".");
|
||||
}
|
||||
|
||||
// Seed the random number generator if not already done
|
||||
static bool seeded = false;
|
||||
if (!seeded) {
|
||||
srand(static_cast<unsigned int>(time(nullptr)));
|
||||
seeded = true;
|
||||
}
|
||||
|
||||
return Value(static_cast<double>(rand()) / RAND_MAX);
|
||||
});
|
||||
env->define("random", Value(randomFunc));
|
||||
|
||||
// Store the shared_ptr in the interpreter to keep it alive
|
||||
interpreter.addBuiltinFunction(randomFunc);
|
||||
// random moved to rand module
|
||||
|
||||
// (eval and evalFile moved to eval module)
|
||||
|
||||
@ -384,53 +344,6 @@ void BobStdLib::addToEnvironment(std::shared_ptr<Environment> env, Interpreter&
|
||||
|
||||
// (file I/O moved to io module)
|
||||
|
||||
// Create a built-in memoryUsage function (platform-specific, best effort)
|
||||
auto memoryUsageFunc = std::make_shared<BuiltinFunction>("memoryUsage",
|
||||
[errorReporter](std::vector<Value> args, int line, int column) -> Value {
|
||||
if (args.size() != 0) {
|
||||
if (errorReporter) {
|
||||
errorReporter->reportError(line, column, "StdLib Error",
|
||||
"Expected 0 arguments but got " + std::to_string(args.size()) + ".", "", true);
|
||||
}
|
||||
throw std::runtime_error("Expected 0 arguments but got " + std::to_string(args.size()) + ".");
|
||||
}
|
||||
|
||||
// Platform-specific memory usage detection
|
||||
size_t memoryBytes = 0;
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
// macOS
|
||||
struct mach_task_basic_info info;
|
||||
mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
|
||||
if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount) == KERN_SUCCESS) {
|
||||
memoryBytes = info.resident_size;
|
||||
}
|
||||
#elif defined(__linux__)
|
||||
// Linux - read from /proc/self/status
|
||||
std::ifstream statusFile("/proc/self/status");
|
||||
std::string line;
|
||||
while (std::getline(statusFile, line)) {
|
||||
if (line.substr(0, 6) == "VmRSS:") {
|
||||
std::istringstream iss(line);
|
||||
std::string label, value, unit;
|
||||
iss >> label >> value >> unit;
|
||||
memoryBytes = std::stoull(value) * 1024; // Convert KB to bytes
|
||||
break;
|
||||
}
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
// Windows
|
||||
PROCESS_MEMORY_COUNTERS pmc;
|
||||
if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
|
||||
memoryBytes = pmc.WorkingSetSize;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Return memory usage in MB for readability
|
||||
double memoryMB = static_cast<double>(memoryBytes) / (1024.0 * 1024.0);
|
||||
return Value(memoryMB);
|
||||
});
|
||||
env->define("memoryUsage", Value(memoryUsageFunc));
|
||||
interpreter.addBuiltinFunction(memoryUsageFunc);
|
||||
// memoryUsage moved to sys module
|
||||
|
||||
}
|
||||
@ -786,9 +786,9 @@ print("Comprehensive number tests: PASS");
|
||||
// TEST 29: TIME FUNCTION
|
||||
// ========================================
|
||||
print("\n--- Test 29: Time Function ---");
|
||||
|
||||
var start_time = time();
|
||||
var end_time = time();
|
||||
import time;
|
||||
var start_time = time.now();
|
||||
var end_time = time.now();
|
||||
var duration = end_time - start_time;
|
||||
assert(start_time > 0, "Start time should be positive");
|
||||
assert(end_time >= start_time, "End time should be >= start time");
|
||||
@ -2416,15 +2416,17 @@ print("Array built-in functions: PASS");
|
||||
print("\n--- Test 52: New Built-in Functions ---");
|
||||
|
||||
// sleep() function
|
||||
var startTime = time();
|
||||
//sleep(0.001); // Sleep for 1ms (much shorter for testing)
|
||||
var endTime = time();
|
||||
import time as T;
|
||||
var startTime = T.now();
|
||||
T.sleep(0.01); // Sleep briefly to ensure elapsed time
|
||||
var endTime = T.now();
|
||||
assert(endTime > startTime, "sleep() - time elapsed");
|
||||
|
||||
// random() function - test proper seeding
|
||||
var random1 = random();
|
||||
var random2 = random();
|
||||
var random3 = random();
|
||||
import rand as R;
|
||||
var random1 = R.random();
|
||||
var random2 = R.random();
|
||||
var random3 = R.random();
|
||||
assert(random1 >= 0 && random1 <= 1, "random() - range check 1");
|
||||
assert(random2 >= 0 && random2 <= 1, "random() - range check 2");
|
||||
assert(random3 >= 0 && random3 <= 1, "random() - range check 3");
|
||||
@ -2432,30 +2434,44 @@ assert(random3 >= 0 && random3 <= 1, "random() - range check 3");
|
||||
assert(random1 != random2 || random2 != random3 || random1 != random3, "random() - different values");
|
||||
|
||||
// Test random number generation in different ranges
|
||||
var randomRange1 = random() * 10;
|
||||
var randomRange2 = random() * 100;
|
||||
var randomRange1 = R.random() * 10;
|
||||
var randomRange2 = R.random() * 100;
|
||||
assert(randomRange1 >= 0 && randomRange1 <= 10, "random() - range 0-10");
|
||||
assert(randomRange2 >= 0 && randomRange2 <= 100, "random() - range 0-100");
|
||||
|
||||
// eval() function
|
||||
eval("var evalVar = 42;");
|
||||
// eval() function (now via eval module)
|
||||
import eval as E;
|
||||
E.eval("var evalVar = 42;");
|
||||
assert(evalVar == 42, "eval() - variable creation");
|
||||
|
||||
eval("print(\"eval test\");"); // Should print "eval test"
|
||||
E.eval("print(\"eval test\");"); // Should print "eval test"
|
||||
|
||||
var evalResult = eval("2 + 2;");
|
||||
var evalResult = E.eval("2 + 2;");
|
||||
// eval() currently returns none, so we just test it doesn't crash
|
||||
|
||||
// Test eval with complex expressions
|
||||
eval("var complexVar = [1, 2, 3];");
|
||||
E.eval("var complexVar = [1, 2, 3];");
|
||||
assert(complexVar.len() == 3, "eval() - complex expression");
|
||||
|
||||
// Test eval with function definitions
|
||||
eval("func evalFunc(x) { return x * 2; }");
|
||||
E.eval("func evalFunc(x) { return x * 2; }");
|
||||
assert(evalFunc(5) == 10, "eval() - function definition");
|
||||
|
||||
print("New built-in functions: PASS");
|
||||
|
||||
// Module tests
|
||||
import io as IO;
|
||||
var p1 = IO.exists("tests/test_path.bob") ? "tests/test_path.bob" : "../tests/test_path.bob";
|
||||
E.evalFile(p1);
|
||||
var p2 = IO.exists("tests/test_base64.bob") ? "tests/test_base64.bob" : "../tests/test_base64.bob";
|
||||
E.evalFile(p2);
|
||||
var p3 = IO.exists("tests/test_math.bob") ? "tests/test_math.bob" : "../tests/test_math.bob";
|
||||
E.evalFile(p3);
|
||||
var p4 = IO.exists("tests/test_rand.bob") ? "tests/test_rand.bob" : "../tests/test_rand.bob";
|
||||
E.evalFile(p4);
|
||||
var p5 = IO.exists("tests/test_time.bob") ? "tests/test_time.bob" : "../tests/test_time.bob";
|
||||
E.evalFile(p5);
|
||||
|
||||
// ========================================
|
||||
// TEST 52.5: EXIT FUNCTION
|
||||
// ========================================
|
||||
@ -2718,14 +2734,14 @@ print("\n--- Test 54: Array Performance ---");
|
||||
|
||||
// Test large array operations
|
||||
var perfArray = [];
|
||||
var startTime = time();
|
||||
import time as T; var startTime = T.now();
|
||||
|
||||
// Create large array
|
||||
for (var i = 0; i < 1000; i = i + 1) {
|
||||
perfArray.push(i);
|
||||
}
|
||||
|
||||
var midTime = time();
|
||||
var midTime = T.now();
|
||||
assert(perfArray.len() == 1000, "Array performance - creation");
|
||||
|
||||
// Access elements
|
||||
@ -2734,7 +2750,7 @@ for (var j = 0; j < 100; j = j + 1) {
|
||||
assert(value == j * 10, "Array performance - access");
|
||||
}
|
||||
|
||||
var endTime = time();
|
||||
var endTime = T.now();
|
||||
assert(endTime > startTime, "Array performance - time check");
|
||||
|
||||
print("Array performance: PASS");
|
||||
@ -2852,7 +2868,7 @@ print("\n--- Test 57: Array Stress Testing ---");
|
||||
|
||||
// Large array creation and manipulation
|
||||
var stressArray = [];
|
||||
var startTime = time();
|
||||
import time as T2; var startTime = T2.now();
|
||||
|
||||
// Create large array with mixed types
|
||||
for (var i = 0; i < 500; i = i + 1) {
|
||||
@ -2865,7 +2881,7 @@ for (var i = 0; i < 500; i = i + 1) {
|
||||
}
|
||||
}
|
||||
|
||||
var midTime = time();
|
||||
var midTime = T2.now();
|
||||
assert(stressArray.len() == 500, "Stress test - array creation");
|
||||
|
||||
// Access and modify elements
|
||||
@ -2876,7 +2892,7 @@ for (var j = 0; j < 100; j = j + 1) {
|
||||
}
|
||||
}
|
||||
|
||||
var endTime = time();
|
||||
var endTime = T2.now();
|
||||
assert(endTime > startTime, "Stress test - time validation");
|
||||
|
||||
// Verify modifications
|
||||
@ -2992,7 +3008,8 @@ assert(toInt(-0.0) == 0, "toInt(-0.0) should be 0");
|
||||
|
||||
// Test with random numbers
|
||||
for(var i = 0; i < 5; i++) {
|
||||
var randomFloat = random() * 10;
|
||||
import rand as Rn;
|
||||
var randomFloat = Rn.random() * 10;
|
||||
var randomInt = toInt(randomFloat);
|
||||
assert(randomInt >= 0 && randomInt <= 9, "toInt(random) should be in range 0-9");
|
||||
}
|
||||
@ -3273,58 +3290,59 @@ print(" * Error reporting in both modes");
|
||||
|
||||
// Additional Tests: Classes and Extensions
|
||||
print("\n--- Additional Tests: Classes and Extensions ---");
|
||||
var path1 = fileExists("tests/test_method_calls.bob") ? "tests/test_method_calls.bob" : "../tests/test_method_calls.bob";
|
||||
evalFile(path1);
|
||||
var path2 = fileExists("tests/test_class_basic.bob") ? "tests/test_class_basic.bob" : "../tests/test_class_basic.bob";
|
||||
evalFile(path2);
|
||||
var path3 = fileExists("tests/test_class_with_this.bob") ? "tests/test_class_with_this.bob" : "../tests/test_class_with_this.bob";
|
||||
evalFile(path3);
|
||||
var path4 = fileExists("tests/test_class_init.bob") ? "tests/test_class_init.bob" : "../tests/test_class_init.bob";
|
||||
evalFile(path4);
|
||||
var path5 = fileExists("tests/test_class_extension_user.bob") ? "tests/test_class_extension_user.bob" : "../tests/test_class_extension_user.bob";
|
||||
evalFile(path5);
|
||||
var path6 = fileExists("tests/test_extension_methods.bob") ? "tests/test_extension_methods.bob" : "../tests/test_extension_methods.bob";
|
||||
evalFile(path6);
|
||||
var path7 = fileExists("tests/test_class_inheritance.bob") ? "tests/test_class_inheritance.bob" : "../tests/test_class_inheritance.bob";
|
||||
evalFile(path7);
|
||||
var path8 = fileExists("tests/test_classes_comprehensive.bob") ? "tests/test_classes_comprehensive.bob" : "../tests/test_classes_comprehensive.bob";
|
||||
evalFile(path8);
|
||||
var path9 = fileExists("tests/test_class_super.bob") ? "tests/test_class_super.bob" : "../tests/test_class_super.bob";
|
||||
evalFile(path9);
|
||||
var path10 = fileExists("tests/test_classes_extensive.bob") ? "tests/test_classes_extensive.bob" : "../tests/test_classes_extensive.bob";
|
||||
evalFile(path10);
|
||||
var path11 = fileExists("tests/test_class_edge_cases.bob") ? "tests/test_class_edge_cases.bob" : "../tests/test_class_edge_cases.bob";
|
||||
evalFile(path11);
|
||||
var path12 = fileExists("tests/test_polymorphism.bob") ? "tests/test_polymorphism.bob" : "../tests/test_polymorphism.bob";
|
||||
evalFile(path12);
|
||||
var path13 = fileExists("tests/test_polymorphism_practical.bob") ? "tests/test_polymorphism_practical.bob" : "../tests/test_polymorphism_practical.bob";
|
||||
evalFile(path13);
|
||||
import io as IO; // for file existence checks
|
||||
var path1 = IO.exists("tests/test_method_calls.bob") ? "tests/test_method_calls.bob" : "../tests/test_method_calls.bob";
|
||||
E.evalFile(path1);
|
||||
var path2 = IO.exists("tests/test_class_basic.bob") ? "tests/test_class_basic.bob" : "../tests/test_class_basic.bob";
|
||||
E.evalFile(path2);
|
||||
var path3 = IO.exists("tests/test_class_with_this.bob") ? "tests/test_class_with_this.bob" : "../tests/test_class_with_this.bob";
|
||||
E.evalFile(path3);
|
||||
var path4 = IO.exists("tests/test_class_init.bob") ? "tests/test_class_init.bob" : "../tests/test_class_init.bob";
|
||||
E.evalFile(path4);
|
||||
var path5 = IO.exists("tests/test_class_extension_user.bob") ? "tests/test_class_extension_user.bob" : "../tests/test_class_extension_user.bob";
|
||||
E.evalFile(path5);
|
||||
var path6 = IO.exists("tests/test_extension_methods.bob") ? "tests/test_extension_methods.bob" : "../tests/test_extension_methods.bob";
|
||||
E.evalFile(path6);
|
||||
var path7 = IO.exists("tests/test_class_inheritance.bob") ? "tests/test_class_inheritance.bob" : "../tests/test_class_inheritance.bob";
|
||||
E.evalFile(path7);
|
||||
var path8 = IO.exists("tests/test_classes_comprehensive.bob") ? "tests/test_classes_comprehensive.bob" : "../tests/test_classes_comprehensive.bob";
|
||||
E.evalFile(path8);
|
||||
var path9 = IO.exists("tests/test_class_super.bob") ? "tests/test_class_super.bob" : "../tests/test_class_super.bob";
|
||||
E.evalFile(path9);
|
||||
var path10 = IO.exists("tests/test_classes_extensive.bob") ? "tests/test_classes_extensive.bob" : "../tests/test_classes_extensive.bob";
|
||||
E.evalFile(path10);
|
||||
var path11 = IO.exists("tests/test_class_edge_cases.bob") ? "tests/test_class_edge_cases.bob" : "../tests/test_class_edge_cases.bob";
|
||||
E.evalFile(path11);
|
||||
var path12 = IO.exists("tests/test_polymorphism.bob") ? "tests/test_polymorphism.bob" : "../tests/test_polymorphism.bob";
|
||||
E.evalFile(path12);
|
||||
var path13 = IO.exists("tests/test_polymorphism_practical.bob") ? "tests/test_polymorphism_practical.bob" : "../tests/test_polymorphism_practical.bob";
|
||||
E.evalFile(path13);
|
||||
|
||||
var path14 = fileExists("tests/test_builtin_methods_style.bob") ? "tests/test_builtin_methods_style.bob" : "../tests/test_builtin_methods_style.bob";
|
||||
evalFile(path14);
|
||||
var path14 = IO.exists("tests/test_builtin_methods_style.bob") ? "tests/test_builtin_methods_style.bob" : "../tests/test_builtin_methods_style.bob";
|
||||
E.evalFile(path14);
|
||||
|
||||
var path15 = fileExists("tests/test_try_catch.bob") ? "tests/test_try_catch.bob" : "../tests/test_try_catch.bob";
|
||||
evalFile(path15);
|
||||
var path15a = fileExists("tests/test_try_catch_runtime.bob") ? "tests/test_try_catch_runtime.bob" : "../tests/test_try_catch_runtime.bob";
|
||||
evalFile(path15a);
|
||||
var path15b = fileExists("tests/test_try_catch_extensive.bob") ? "tests/test_try_catch_extensive.bob" : "../tests/test_try_catch_extensive.bob";
|
||||
evalFile(path15b);
|
||||
var path15c = fileExists("tests/test_try_catch_edge_cases2.bob") ? "tests/test_try_catch_edge_cases2.bob" : "../tests/test_try_catch_edge_cases2.bob";
|
||||
evalFile(path15c);
|
||||
var path15d = fileExists("tests/test_try_catch_cross_function.bob") ? "tests/test_try_catch_cross_function.bob" : "../tests/test_try_catch_cross_function.bob";
|
||||
evalFile(path15d);
|
||||
var path15e = fileExists("tests/test_try_catch_loop_interactions.bob") ? "tests/test_try_catch_loop_interactions.bob" : "../tests/test_try_catch_loop_interactions.bob";
|
||||
evalFile(path15e);
|
||||
var path15 = IO.exists("tests/test_try_catch.bob") ? "tests/test_try_catch.bob" : "../tests/test_try_catch.bob";
|
||||
E.evalFile(path15);
|
||||
var path15a = IO.exists("tests/test_try_catch_runtime.bob") ? "tests/test_try_catch_runtime.bob" : "../tests/test_try_catch_runtime.bob";
|
||||
E.evalFile(path15a);
|
||||
var path15b = IO.exists("tests/test_try_catch_extensive.bob") ? "tests/test_try_catch_extensive.bob" : "../tests/test_try_catch_extensive.bob";
|
||||
E.evalFile(path15b);
|
||||
var path15c = IO.exists("tests/test_try_catch_edge_cases2.bob") ? "tests/test_try_catch_edge_cases2.bob" : "../tests/test_try_catch_edge_cases2.bob";
|
||||
E.evalFile(path15c);
|
||||
var path15d = IO.exists("tests/test_try_catch_cross_function.bob") ? "tests/test_try_catch_cross_function.bob" : "../tests/test_try_catch_cross_function.bob";
|
||||
E.evalFile(path15d);
|
||||
var path15e = IO.exists("tests/test_try_catch_loop_interactions.bob") ? "tests/test_try_catch_loop_interactions.bob" : "../tests/test_try_catch_loop_interactions.bob";
|
||||
E.evalFile(path15e);
|
||||
|
||||
// Modules: basic imports suite
|
||||
var pathMods = fileExists("tests/test_imports_basic.bob") ? "tests/test_imports_basic.bob" : "../tests/test_imports_basic.bob";
|
||||
evalFile(pathMods);
|
||||
var pathMods = IO.exists("tests/test_imports_basic.bob") ? "tests/test_imports_basic.bob" : "../tests/test_imports_basic.bob";
|
||||
E.evalFile(pathMods);
|
||||
|
||||
var pathModsB = fileExists("tests/test_imports_builtin.bob") ? "tests/test_imports_builtin.bob" : "../tests/test_imports_builtin.bob";
|
||||
evalFile(pathModsB);
|
||||
var pathModsB = IO.exists("tests/test_imports_builtin.bob") ? "tests/test_imports_builtin.bob" : "../tests/test_imports_builtin.bob";
|
||||
E.evalFile(pathModsB);
|
||||
|
||||
var pathOs = fileExists("tests/test_os_basic.bob") ? "tests/test_os_basic.bob" : "../tests/test_os_basic.bob";
|
||||
evalFile(pathOs);
|
||||
var pathOs = IO.exists("tests/test_os_basic.bob") ? "tests/test_os_basic.bob" : "../tests/test_os_basic.bob";
|
||||
E.evalFile(pathOs);
|
||||
|
||||
print("\nAll tests passed.");
|
||||
print("Test suite complete.");
|
||||
11
tests/test_base64.bob
Normal file
11
tests/test_base64.bob
Normal file
@ -0,0 +1,11 @@
|
||||
print("\n--- Test: base64 module ---");
|
||||
import base64;
|
||||
|
||||
var s = "hello world";
|
||||
var enc = base64.encode(s);
|
||||
assert(enc == "aGVsbG8gd29ybGQ=", "base64.encode");
|
||||
var dec = base64.decode(enc);
|
||||
assert(dec == s, "base64.decode roundtrip");
|
||||
print("base64: PASS");
|
||||
|
||||
|
||||
5
tests/test_hash.bob
Normal file
5
tests/test_hash.bob
Normal file
@ -0,0 +1,5 @@
|
||||
print("\n--- Test: hash module ---");
|
||||
// Placeholder: implement when hash module is added
|
||||
print("hash: SKIPPED");
|
||||
|
||||
|
||||
@ -28,7 +28,8 @@ var after = mod_hello.X;
|
||||
assert(before == after, "module executed once (cached)");
|
||||
|
||||
// Cross-file visibility in same interpreter: eval user file after importing here
|
||||
evalFile("tests/import_user_of_mod_hello.bob");
|
||||
import eval as E;
|
||||
E.evalFile("tests/import_user_of_mod_hello.bob");
|
||||
|
||||
// Immutability: cannot reassign module binding
|
||||
var immFail = false;
|
||||
|
||||
15
tests/test_math.bob
Normal file
15
tests/test_math.bob
Normal file
@ -0,0 +1,15 @@
|
||||
print("\n--- Test: math module ---");
|
||||
import math;
|
||||
|
||||
assert(math.sqrt(9) == 3, "math.sqrt");
|
||||
assert(math.round(3.6) == 4, "math.round");
|
||||
assert(math.floor(3.6) == 3, "math.floor");
|
||||
assert(math.ceil(3.1) == 4, "math.ceil");
|
||||
assert(math.abs(-5) == 5, "math.abs");
|
||||
assert(math.pow(2,8) == 256, "math.pow");
|
||||
assert(math.min(1, 2, 3) == 1, "math.min");
|
||||
assert(math.max(1, 2, 3) == 3, "math.max");
|
||||
assert(math.pi > 3.14 && math.pi < 3.15, "math.pi range");
|
||||
print("math: PASS");
|
||||
|
||||
|
||||
15
tests/test_path.bob
Normal file
15
tests/test_path.bob
Normal file
@ -0,0 +1,15 @@
|
||||
print("\n--- Test: path module ---");
|
||||
import path;
|
||||
|
||||
assert(path.join("a","b","c.txt") == "a/b/c.txt", "path.join");
|
||||
assert(path.dirname("/a/b/c.txt") == "/a/b", "path.dirname");
|
||||
assert(path.basename("/a/b/c.txt") == "c.txt", "path.basename");
|
||||
var sp = path.splitext("c.txt");
|
||||
assert(sp[0] == "c" && sp[1] == ".txt", "path.splitext");
|
||||
assert(path.normalize("a/./b/../c") == "a/c", "path.normalize");
|
||||
assert(path.isabs("/a/b") == true, "path.isabs");
|
||||
var rp = path.relpath("/a/b/c", "/a");
|
||||
assert(rp == "b/c" || rp == "../a/b/c", "path.relpath platform tolerance");
|
||||
print("path: PASS");
|
||||
|
||||
|
||||
14
tests/test_rand.bob
Normal file
14
tests/test_rand.bob
Normal file
@ -0,0 +1,14 @@
|
||||
print("\n--- Test: rand module ---");
|
||||
import rand;
|
||||
|
||||
rand.seed(1234);
|
||||
var r1 = rand.random();
|
||||
var r2 = rand.random();
|
||||
assert(r1 >= 0 && r1 < 1 && r2 >= 0 && r2 < 1, "rand.random range");
|
||||
var i = rand.randint(1, 10);
|
||||
assert(i >= 1 && i <= 10, "rand.randint range");
|
||||
var choice = rand.choice(["a","b","c"]);
|
||||
assert(choice == "a" || choice == "b" || choice == "c", "rand.choice");
|
||||
print("rand: PASS");
|
||||
|
||||
|
||||
5
tests/test_re.bob
Normal file
5
tests/test_re.bob
Normal file
@ -0,0 +1,5 @@
|
||||
print("\n--- Test: re module ---");
|
||||
// Placeholder: implement when re module is added
|
||||
print("re: SKIPPED");
|
||||
|
||||
|
||||
14
tests/test_time.bob
Normal file
14
tests/test_time.bob
Normal file
@ -0,0 +1,14 @@
|
||||
print("\n--- Test: time module ---");
|
||||
import time;
|
||||
|
||||
var t1 = time.now();
|
||||
var t2 = time.now();
|
||||
assert(t2 >= t1, "time.now monotonic-ish");
|
||||
|
||||
var m1 = time.monotonic();
|
||||
time.sleep(0.01);
|
||||
var m2 = time.monotonic();
|
||||
assert(m2 > m1, "time.monotonic increases");
|
||||
print("time: PASS");
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ while (true) {
|
||||
}
|
||||
assert(i == 2 && seq.len() == 2, "continue/break in finally");
|
||||
|
||||
// Throw in loop body caught outside
|
||||
// Throw in loop body caught and handled without extra reporter noise
|
||||
var hits = [];
|
||||
for (var j = 0; j < 3; j = j + 1) {
|
||||
try {
|
||||
@ -25,7 +25,11 @@ for (var j = 0; j < 3; j = j + 1) {
|
||||
hits.push("caught:" + e.message);
|
||||
}
|
||||
}
|
||||
assert(hits.len() == 4 && hits[1] == "caught:bang", "loop catch per-iteration");
|
||||
// Strictly check sequence; avoid out-of-bounds checks
|
||||
assert(hits.len() == 3, "loop catch sequence length");
|
||||
assert(hits[0] == 0, "loop catch sequence item0");
|
||||
assert(hits[1] == "caught:bang", "loop catch sequence item1");
|
||||
assert(hits[2] == 2, "loop catch sequence item2");
|
||||
|
||||
print("try/catch with loops: PASS");
|
||||
|
||||
|
||||
5
tests/test_uuid.bob
Normal file
5
tests/test_uuid.bob
Normal file
@ -0,0 +1,5 @@
|
||||
print("\n--- Test: uuid module ---");
|
||||
// Placeholder: implement when uuid module is added
|
||||
print("uuid: SKIPPED");
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user