mirror of https://github.com/WebAssembly/wasi-sdk
This adds a very primitive test harness and tests relevant to the recent changes to how program startup works, as well as the upcoming changes to support LTO.pull/92/head
parent
2bfea0cc96
commit
21657b7a78
@ -0,0 +1,2 @@
|
|||||||
|
*.observed
|
||||||
|
*.wasm
|
@ -0,0 +1,19 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
extern void __dso_handle;
|
||||||
|
extern void __data_end;
|
||||||
|
extern void __global_base;
|
||||||
|
extern void __heap_base;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
printf("NULL=%p\n", NULL);
|
||||||
|
printf("__dso_handle=%p\n", &__dso_handle);
|
||||||
|
printf("__data_end=%p\n", &__data_end);
|
||||||
|
printf("__global_base=%p\n", &__global_base);
|
||||||
|
printf("__heap_base=%p\n", &__heap_base);
|
||||||
|
printf("__builtin_frame_address(0)=%p\n", __builtin_frame_address(0));
|
||||||
|
printf("__builtin_alloca(0)=%p\n", __builtin_alloca(0));
|
||||||
|
printf("__builtin_wasm_memory_size(0)=%p\n", (void *)(__builtin_wasm_memory_size(0) * PAGE_SIZE));
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
int main(){}
|
@ -0,0 +1,13 @@
|
|||||||
|
(module
|
||||||
|
(type (;0;) (func))
|
||||||
|
(type (;1;) (func (result i32)))
|
||||||
|
(func $__wasm_call_ctors (type 0))
|
||||||
|
(func $_start (type 0)
|
||||||
|
call $__wasm_call_ctors)
|
||||||
|
(func $__main_void (type 1) (result i32)
|
||||||
|
i32.const 0)
|
||||||
|
(table (;0;) 1 1 funcref)
|
||||||
|
(memory (;0;) 2)
|
||||||
|
(global (;0;) (mut i32) (i32.const 66560))
|
||||||
|
(export "memory" (memory 0))
|
||||||
|
(export "_start" (func $_start)))
|
@ -0,0 +1 @@
|
|||||||
|
0
|
@ -0,0 +1,6 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
puts("hello from argc argv main!");
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
hello from argc argv main!
|
@ -0,0 +1,6 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
puts("hello from C++ argc argv main!");
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
hello from C++ argc argv main!
|
@ -0,0 +1,52 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
extern char **environ;
|
||||||
|
|
||||||
|
static void from_atexit(void) {
|
||||||
|
printf("hello from_atexit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void another_from_atexit(void) {
|
||||||
|
printf("hello another_from_atexit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((constructor)) static void from_constructor(void) {
|
||||||
|
printf("hello from_constructor\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((constructor(101))) static void from_constructor_101(void) {
|
||||||
|
assert(errno == 0);
|
||||||
|
printf("hello from_constructor101\n");
|
||||||
|
|
||||||
|
assert(environ && "environment should be initialized by this point");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((constructor(65535))) static void from_constructor_65535(void) {
|
||||||
|
printf("hello from_constructor65535\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((destructor)) static void from_destructor(void) {
|
||||||
|
printf("hello from_destructor\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((destructor(101))) static void from_destructor101(void) {
|
||||||
|
printf("hello from_destructor101\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((destructor(65535))) static void from_destructor65535(void) {
|
||||||
|
printf("hello from_destructor65535\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
printf("hello main\n");
|
||||||
|
assert(argc != 0);
|
||||||
|
assert(argv != NULL);
|
||||||
|
assert(argv[argc] == NULL);
|
||||||
|
|
||||||
|
atexit(from_atexit);
|
||||||
|
atexit(another_from_atexit);
|
||||||
|
printf("goodbye main\n");
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
hello from_constructor101
|
||||||
|
hello from_constructor
|
||||||
|
hello from_constructor65535
|
||||||
|
hello main
|
||||||
|
goodbye main
|
||||||
|
hello another_from_atexit
|
||||||
|
hello from_atexit
|
||||||
|
hello from_destructor65535
|
||||||
|
hello from_destructor
|
||||||
|
hello from_destructor101
|
@ -0,0 +1,16 @@
|
|||||||
|
#include "ctors_dtors.c"
|
||||||
|
|
||||||
|
struct StaticObject {
|
||||||
|
StaticObject();
|
||||||
|
~StaticObject();
|
||||||
|
};
|
||||||
|
|
||||||
|
StaticObject::StaticObject() {
|
||||||
|
printf("hello StaticObject::StaticObject\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
StaticObject::~StaticObject() {
|
||||||
|
printf("hello StaticObject::~StaticObject\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static StaticObject static_object;
|
@ -0,0 +1,12 @@
|
|||||||
|
hello from_constructor101
|
||||||
|
hello from_constructor
|
||||||
|
hello from_constructor65535
|
||||||
|
hello StaticObject::StaticObject
|
||||||
|
hello main
|
||||||
|
goodbye main
|
||||||
|
hello another_from_atexit
|
||||||
|
hello from_atexit
|
||||||
|
hello from_destructor65535
|
||||||
|
hello from_destructor
|
||||||
|
hello StaticObject::~StaticObject
|
||||||
|
hello from_destructor101
|
@ -0,0 +1 @@
|
|||||||
|
int main(void) { return 0; }
|
@ -0,0 +1,6 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << "hello from C++ main with cout!" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
hello from C++ main with cout!
|
@ -0,0 +1,12 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// It isn't required that errno be zero on entry to main, but
|
||||||
|
// for tidiness' sake, if we ever do things during startup that
|
||||||
|
// do set errno, we should reset it for tidiness' sake.
|
||||||
|
int main(void) {
|
||||||
|
int n = errno;
|
||||||
|
printf("initial errno is %d: %s\n", n, strerror(n));
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
initial errno is 0: Success
|
@ -0,0 +1,6 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
puts("hello from no-arg main!");
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
hello from no-arg main!
|
@ -0,0 +1,6 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
puts("hello from C++ no-arg main!");
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
hello from C++ no-arg main!
|
@ -0,0 +1,6 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
puts("hello from void main!");
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
hello from void main!
|
@ -0,0 +1,6 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
puts("hello from C++ void main!");
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
hello from C++ void main!
|
@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -ueo pipefail
|
||||||
|
|
||||||
|
runwasm="$1"
|
||||||
|
|
||||||
|
cd compile-only
|
||||||
|
for options in -O0 -O2 "-O2 -flto"; do
|
||||||
|
echo "===== Testing compile-only with $options ====="
|
||||||
|
for file in *.c; do
|
||||||
|
echo "Testing compile-only $file..."
|
||||||
|
../testcase.sh true clang "$options" "$file"
|
||||||
|
done
|
||||||
|
for file in *.cc; do
|
||||||
|
echo "Testing compile-only $file..."
|
||||||
|
../testcase.sh true clang++ "$options" "$file"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
cd - >/dev/null
|
||||||
|
|
||||||
|
cd general
|
||||||
|
for options in -O0 -O2 "-O2 -flto"; do
|
||||||
|
echo "===== Testing with $options ====="
|
||||||
|
for file in *.c; do
|
||||||
|
echo "Testing $file..."
|
||||||
|
../testcase.sh "$runwasm" clang "$options" "$file"
|
||||||
|
done
|
||||||
|
for file in *.cc; do
|
||||||
|
echo "Testing $file..."
|
||||||
|
../testcase.sh "$runwasm" clang++ "$options" "$file"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
cd - >/dev/null
|
@ -0,0 +1,57 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -ueo pipefail
|
||||||
|
|
||||||
|
# A simple testcase runner that runs a command, captures all its command-line
|
||||||
|
# outputs, and compares them against expected outputs.
|
||||||
|
|
||||||
|
runwasm="$1"
|
||||||
|
clang="$2"
|
||||||
|
options="$3"
|
||||||
|
input="$4"
|
||||||
|
|
||||||
|
wasm="$input.$options.wasm"
|
||||||
|
stdout_observed="$input.$options.stdout.observed"
|
||||||
|
stderr_observed="$input.$options.stderr.observed"
|
||||||
|
exit_status_observed="$input.$options.exit_status.observed"
|
||||||
|
|
||||||
|
if [ -e "$input.options" ]; then
|
||||||
|
file_options=$(cat "$inpit.options")
|
||||||
|
else
|
||||||
|
file_options=
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Testing $input..."
|
||||||
|
"$clang" $options $file_options "$input" -o "$wasm"
|
||||||
|
if [ -e "$input.stdin" ]; then
|
||||||
|
stdin="$input.stdin"
|
||||||
|
else
|
||||||
|
stdin="/dev/null"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit_status=0
|
||||||
|
"$runwasm" "$wasm" \
|
||||||
|
< "$stdin" \
|
||||||
|
> "$stdout_observed" \
|
||||||
|
2> "$stderr_observed" \
|
||||||
|
|| exit_status=$?
|
||||||
|
echo $exit_status > "$exit_status_observed"
|
||||||
|
|
||||||
|
if [ -e "$input.stdout.expected" ]; then
|
||||||
|
stdout_expected="$input.stdout.expected"
|
||||||
|
else
|
||||||
|
stdout_expected="/dev/null"
|
||||||
|
fi
|
||||||
|
if [ -e "$input.stderr.expected" ]; then
|
||||||
|
stderr_expected="$input.stderr.expected"
|
||||||
|
else
|
||||||
|
stderr_expected="/dev/null"
|
||||||
|
fi
|
||||||
|
if [ -e "$input.exit_status.expected" ]; then
|
||||||
|
exit_status_expected="$input.exit_status.expected"
|
||||||
|
else
|
||||||
|
exit_status_expected=../exit_status_zero
|
||||||
|
fi
|
||||||
|
|
||||||
|
diff -u "$stderr_expected" "$stderr_observed"
|
||||||
|
diff -u "$stdout_expected" "$stdout_observed"
|
||||||
|
diff -u "$exit_status_expected" "$exit_status_observed"
|
Loading…
Reference in new issue