tests are now autogenerated from the readme, this makes test names DRY
I want to reduce friction of adding new tests as much as possible Signed-off-by: Jakub Doka <jakub.doka2@gmail.com>
This commit is contained in:
parent
5c8f7c9c79
commit
51bfbdf7ae
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -12,3 +12,4 @@ db.sqlite-journal
|
||||||
/depell/src/static-pages/*.html
|
/depell/src/static-pages/*.html
|
||||||
#**/*-sv.rs
|
#**/*-sv.rs
|
||||||
/bytecode/src/instrs.rs
|
/bytecode/src/instrs.rs
|
||||||
|
/lang/src/testcases.rs
|
||||||
|
|
|
@ -736,28 +736,6 @@ main := fn(): uint {
|
||||||
|
|
||||||
### Incomplete Examples
|
### Incomplete Examples
|
||||||
|
|
||||||
#### string_array
|
|
||||||
```hb
|
|
||||||
|
|
||||||
main := fn(): uint {
|
|
||||||
strings := (^u8).["abcdefshijklmnop\0".ptr, "abcdefghijklnnop\0".ptr, "abcdefshijklmnop\0".ptr, "abcdefghijklmnop\0".ptr, "abcdefghijflmnop\0".ptr, "dbcdefghijklmnop\0".ptr, "abcdefghijklmnop\0".ptr]
|
|
||||||
return *strings[0]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### comptime_pointers
|
|
||||||
```hb
|
|
||||||
main := fn(): uint {
|
|
||||||
$integer := 7
|
|
||||||
modify(&integer)
|
|
||||||
return integer
|
|
||||||
}
|
|
||||||
|
|
||||||
modify := fn($num: ^uint): void {
|
|
||||||
$: *num = 0
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### fb_driver
|
#### fb_driver
|
||||||
```hb
|
```hb
|
||||||
arm_fb_ptr := fn(): uint return 100
|
arm_fb_ptr := fn(): uint return 100
|
||||||
|
@ -798,6 +776,30 @@ main := fn(): uint {
|
||||||
|
|
||||||
### Purely Testing Examples
|
### Purely Testing Examples
|
||||||
|
|
||||||
|
#### string_array
|
||||||
|
```hb
|
||||||
|
|
||||||
|
main := fn(): uint {
|
||||||
|
strings := (^u8).["abcdefshijklmnop\0".ptr, "abcdefghijklnnop\0".ptr, "abcdefshijklmnop\0".ptr, "abcdefghijklmnop\0".ptr, "abcdefghijflmnop\0".ptr, "dbcdefghijklmnop\0".ptr, "abcdefghijklmnop\0".ptr]
|
||||||
|
return *strings[0]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### generic_function_in_struct
|
||||||
|
```hb
|
||||||
|
A := struct {
|
||||||
|
a: uint,
|
||||||
|
b := fn(self: ^Self, $T: type, c: T): T {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main := fn(): uint {
|
||||||
|
a := A.(100)
|
||||||
|
return a.b(uint, 100)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### len_never_goes_down
|
#### len_never_goes_down
|
||||||
```hb
|
```hb
|
||||||
chars := fn(iter: []u8): struct {
|
chars := fn(iter: []u8): struct {
|
||||||
|
|
35
lang/build.rs
Normal file
35
lang/build.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
use std::{fmt::Write, iter};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
const TEST_FILE: &str = "src/testcases.rs";
|
||||||
|
const INPUT: &str = include_str!("./README.md");
|
||||||
|
|
||||||
|
let mut out = String::new();
|
||||||
|
for (name, code) in block_iter(INPUT) {
|
||||||
|
let name = name.replace(' ', "_");
|
||||||
|
_ = writeln!(
|
||||||
|
out,
|
||||||
|
"#[test] fn {name}() {{ run_codegen_test(\"{name}\", r##\"{code}\"##) }}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::fs::write(TEST_FILE, out).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_iter(mut input: &str) -> impl Iterator<Item = (&str, &str)> {
|
||||||
|
const CASE_PREFIX: &str = "#### ";
|
||||||
|
const CASE_SUFFIX: &str = "\n```hb";
|
||||||
|
|
||||||
|
iter::from_fn(move || loop {
|
||||||
|
let pos = input.find(CASE_PREFIX)?;
|
||||||
|
input = unsafe { input.get_unchecked(pos + CASE_PREFIX.len()..) };
|
||||||
|
let Some((test_name, rest)) = input.split_once(CASE_SUFFIX) else { continue };
|
||||||
|
if !test_name.chars().all(|c| c.is_alphanumeric() || c == '_') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
input = rest;
|
||||||
|
let (body, rest) = input.split_once("```").unwrap_or((input, ""));
|
||||||
|
input = rest;
|
||||||
|
break Some((test_name, body));
|
||||||
|
})
|
||||||
|
}
|
|
@ -401,10 +401,10 @@ impl Default for FnvHasher {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn run_test(
|
pub fn run_test(
|
||||||
name: &'static str,
|
name: &str,
|
||||||
ident: &'static str,
|
ident: &str,
|
||||||
input: &'static str,
|
input: &str,
|
||||||
test: fn(&'static str, &'static str, &mut alloc::string::String),
|
test: fn(&str, &str, &mut alloc::string::String),
|
||||||
) {
|
) {
|
||||||
use std::{
|
use std::{
|
||||||
io::Write,
|
io::Write,
|
||||||
|
@ -483,31 +483,6 @@ fn test_parse_files(
|
||||||
std::{borrow::ToOwned, string::ToString},
|
std::{borrow::ToOwned, string::ToString},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn find_block<'a>(mut input: &'a str, test_name: &str) -> &'a str {
|
|
||||||
const CASE_PREFIX: &str = "#### ";
|
|
||||||
const CASE_SUFFIX: &str = "\n```hb";
|
|
||||||
loop {
|
|
||||||
let Some(pos) = input.find(CASE_PREFIX) else {
|
|
||||||
unreachable!("test {test_name} not found");
|
|
||||||
};
|
|
||||||
|
|
||||||
input = unsafe { input.get_unchecked(pos + CASE_PREFIX.len()..) };
|
|
||||||
if !input.starts_with(test_name) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
input = unsafe { input.get_unchecked(test_name.len()..) };
|
|
||||||
if !input.starts_with(CASE_SUFFIX) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
input = unsafe { input.get_unchecked(CASE_SUFFIX.len()..) };
|
|
||||||
|
|
||||||
let end = input.find("```").unwrap_or(input.len());
|
|
||||||
break unsafe { input.get_unchecked(..end) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let input = find_block(input, ident);
|
|
||||||
|
|
||||||
let mut module_map = Vec::new();
|
let mut module_map = Vec::new();
|
||||||
let mut embed_map = Vec::new();
|
let mut embed_map = Vec::new();
|
||||||
let mut last_start = 0;
|
let mut last_start = 0;
|
||||||
|
|
112
lang/src/son.rs
112
lang/src/son.rs
|
@ -4389,7 +4389,7 @@ mod tests {
|
||||||
core::fmt::Write,
|
core::fmt::Write,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn generate(ident: &'static str, input: &'static str, output: &mut String) {
|
fn generate(ident: &str, input: &str, output: &mut String) {
|
||||||
_ = log::set_logger(&crate::fs::Logger);
|
_ = log::set_logger(&crate::fs::Logger);
|
||||||
log::set_max_level(log::LevelFilter::Info);
|
log::set_max_level(log::LevelFilter::Info);
|
||||||
//log::set_max_level(log::LevelFilter::Trace);
|
//log::set_max_level(log::LevelFilter::Trace);
|
||||||
|
@ -4423,111 +4423,9 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::run_tests! { generate:
|
fn run_codegen_test(name: &str, input: &str) {
|
||||||
// Tour Examples
|
crate::run_test(&format!("{}::{}", module_path!(), name), name, input, generate);
|
||||||
main_fn;
|
|
||||||
arithmetic;
|
|
||||||
floating_point_arithmetic;
|
|
||||||
functions;
|
|
||||||
comments;
|
|
||||||
if_statements;
|
|
||||||
variables;
|
|
||||||
hex_octal_binary_literals;
|
|
||||||
loops;
|
|
||||||
pointers;
|
|
||||||
structs;
|
|
||||||
tuples;
|
|
||||||
struct_scopes;
|
|
||||||
enums;
|
|
||||||
unions;
|
|
||||||
nullable_types;
|
|
||||||
struct_operators;
|
|
||||||
global_variables;
|
|
||||||
constants;
|
|
||||||
directives;
|
|
||||||
c_strings;
|
|
||||||
struct_patterns;
|
|
||||||
arrays;
|
|
||||||
slices;
|
|
||||||
inline;
|
|
||||||
idk;
|
|
||||||
generic_functions;
|
|
||||||
die;
|
|
||||||
defer;
|
|
||||||
unrolled_loops;
|
|
||||||
|
|
||||||
// Incomplete Examples;
|
|
||||||
//comptime_pointers;
|
|
||||||
generic_types;
|
|
||||||
fb_driver;
|
|
||||||
|
|
||||||
// Purely Testing Examples;
|
|
||||||
len_never_goes_down;
|
|
||||||
slice_to_global_pointer;
|
|
||||||
subsclice_bug;
|
|
||||||
string_array;
|
|
||||||
proper_ident_propagation;
|
|
||||||
method_receiver_by_value;
|
|
||||||
comparing_floating_points;
|
|
||||||
pointer_comparison;
|
|
||||||
different_function_destinations;
|
|
||||||
triggering_store_in_divergent_branch;
|
|
||||||
wrong_dead_code_elimination;
|
|
||||||
memory_swap;
|
|
||||||
very_nested_loops;
|
|
||||||
generic_type_mishap;
|
|
||||||
storing_into_nullable_struct;
|
|
||||||
scheduling_block_did_dirty;
|
|
||||||
null_check_returning_small_global;
|
|
||||||
null_check_in_the_loop;
|
|
||||||
stack_provenance;
|
|
||||||
advanced_floating_point_arithmetic;
|
|
||||||
nullable_structure;
|
|
||||||
needless_unwrap;
|
|
||||||
inlining_issues;
|
|
||||||
null_check_test;
|
|
||||||
only_break_loop;
|
|
||||||
reading_idk;
|
|
||||||
nonexistent_ident_import;
|
|
||||||
big_array_crash;
|
|
||||||
returning_global_struct;
|
|
||||||
small_struct_bitcast;
|
|
||||||
small_struct_assignment;
|
|
||||||
intcast_store;
|
|
||||||
string_flip;
|
|
||||||
signed_to_unsigned_upcast;
|
|
||||||
wide_ret;
|
|
||||||
comptime_min_reg_leak;
|
|
||||||
different_types;
|
|
||||||
struct_return_from_module_function;
|
|
||||||
sort_something_viredly;
|
|
||||||
struct_in_register;
|
|
||||||
comptime_function_from_another_file;
|
|
||||||
inline_test;
|
|
||||||
inlined_generic_functions;
|
|
||||||
some_generic_code;
|
|
||||||
integer_inference_issues;
|
|
||||||
writing_into_string;
|
|
||||||
request_page;
|
|
||||||
tests_ptr_to_ptr_copy;
|
|
||||||
global_variable_wiredness;
|
|
||||||
inline_return_stack;
|
|
||||||
|
|
||||||
// Just Testing Optimizations;
|
|
||||||
elide_stack_offsets_for_parameters_correctly;
|
|
||||||
const_folding_with_arg;
|
|
||||||
branch_assignments;
|
|
||||||
exhaustive_loop_testing;
|
|
||||||
pointer_opts;
|
|
||||||
conditional_stores;
|
|
||||||
loop_stores;
|
|
||||||
dead_code_in_loop;
|
|
||||||
infinite_loop_after_peephole;
|
|
||||||
aliasing_overoptimization;
|
|
||||||
global_aliasing_overptimization;
|
|
||||||
overwrite_aliasing_overoptimization;
|
|
||||||
more_if_opts;
|
|
||||||
optional_from_eca;
|
|
||||||
returning_optional_issues;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
include!("./testcases.rs");
|
||||||
}
|
}
|
||||||
|
|
0
lang/tests/son_tests_generic_function_in_struct.txt
Normal file
0
lang/tests/son_tests_generic_function_in_struct.txt
Normal file
Loading…
Reference in a new issue