Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ jobs:
sudo apt-get update
sudo apt-get install -y \
wget \
ripgrep \
software-properties-common \
ca-certificates \
gnupg \
Expand Down
26 changes: 18 additions & 8 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
- name: Install LLVM 21
run: |
sudo apt-get update
sudo apt-get install -y wget software-properties-common
sudo apt-get install -y wget software-properties-common ripgrep
wget --inet4-only --tries=3 --timeout=30 --retry-on-host-error --retry-connrefused https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 21
Expand Down Expand Up @@ -76,7 +76,7 @@ jobs:
- name: Validate Python tooling
run: |
python3 -m py_compile x.py tools/check_wave_corpus.py tools/case_manifest.py tools/populate_case_matrix.py tools/run_tests.py tools/test_contracts.py tools/test_case_manifest.py tools/test_test_contracts.py tools/process_tree.py tools/test_process_tree.py
python3 -m unittest tools.test_check_case_sources tools.test_case_execution tools.test_case_manifest tools.test_test_contracts tools.test_process_tree tools.test_check_msvc_native tools.test_diagnose_windows_arm64 tools.test_runtime_selection tools.test_runtime_cases
python3 -m unittest tools.test_release_gates tools.test_server_case tools.test_check_wave_corpus tools.test_runtime_cases tools.test_check_case_sources tools.test_case_execution tools.test_case_manifest tools.test_test_contracts tools.test_process_tree tools.test_check_msvc_native tools.test_diagnose_windows_arm64 tools.test_runtime_selection

- name: Test Windows ARM64 dependency archive validation
shell: pwsh
Expand Down Expand Up @@ -145,7 +145,7 @@ jobs:
- name: Validate Python tooling
run: |
python3 -m py_compile x.py tools/check_wave_corpus.py tools/case_manifest.py tools/populate_case_matrix.py tools/run_tests.py tools/test_contracts.py tools/test_case_manifest.py tools/test_test_contracts.py tools/process_tree.py tools/test_process_tree.py
python3 -m unittest tools.test_check_case_sources tools.test_case_execution tools.test_case_manifest tools.test_test_contracts tools.test_process_tree tools.test_check_msvc_native
python3 -m unittest tools.test_release_gates tools.test_server_case tools.test_check_wave_corpus tools.test_runtime_cases tools.test_check_case_sources tools.test_case_execution tools.test_case_manifest tools.test_test_contracts tools.test_process_tree tools.test_check_msvc_native

- name: Build release compiler
run: cargo build --locked --release --verbose
Expand Down Expand Up @@ -234,6 +234,11 @@ jobs:
--features llvm-target-loongarch --test codegen_regressions
loongarch64_ --jobs 2

- name: Run frontend regressions with the LoongArch backend only
run: >-
cargo test --locked --no-default-features --features llvm-target-loongarch
--test frontend_regressions --jobs 2

- name: Verify LoongArch64 CRT and target contracts
env:
WAVE_RUN_LOONGARCH64_INTEROP_TESTS: "1"
Expand Down Expand Up @@ -347,7 +352,7 @@ jobs:
- name: Validate Python tooling
run: |
python3 -m py_compile x.py tools/check_wave_corpus.py tools/case_manifest.py tools/populate_case_matrix.py tools/run_tests.py tools/test_contracts.py tools/test_case_manifest.py tools/test_test_contracts.py tools/process_tree.py tools/test_process_tree.py
python3 -m unittest tools.test_check_case_sources tools.test_case_execution tools.test_case_manifest tools.test_test_contracts tools.test_process_tree tools.test_check_msvc_native
python3 -m unittest tools.test_release_gates tools.test_server_case tools.test_check_wave_corpus tools.test_runtime_cases tools.test_check_case_sources tools.test_case_execution tools.test_case_manifest tools.test_test_contracts tools.test_process_tree tools.test_check_msvc_native

- name: Build release compiler
id: release_build
Expand Down Expand Up @@ -512,7 +517,7 @@ jobs:
- name: Validate Python tooling
run: |
python3 -m py_compile x.py tools/check_wave_corpus.py tools/case_manifest.py tools/populate_case_matrix.py tools/run_tests.py tools/test_contracts.py tools/test_case_manifest.py tools/test_test_contracts.py tools/process_tree.py tools/test_process_tree.py
python3 -m unittest tools.test_check_case_sources tools.test_case_execution tools.test_case_manifest tools.test_test_contracts tools.test_process_tree tools.test_check_msvc_native
python3 -m unittest tools.test_release_gates tools.test_server_case tools.test_check_wave_corpus tools.test_runtime_cases tools.test_check_case_sources tools.test_case_execution tools.test_case_manifest tools.test_test_contracts tools.test_process_tree tools.test_check_msvc_native

- name: Build release compiler
run: cargo build --locked --release --verbose
Expand Down Expand Up @@ -582,7 +587,7 @@ jobs:
- name: Validate Python tooling
run: |
python3 -m py_compile x.py tools/check_wave_corpus.py tools/case_manifest.py tools/populate_case_matrix.py tools/run_tests.py tools/test_contracts.py tools/test_case_manifest.py tools/test_test_contracts.py tools/process_tree.py tools/test_process_tree.py
python3 -m unittest tools.test_check_case_sources tools.test_case_execution tools.test_case_manifest tools.test_test_contracts tools.test_process_tree tools.test_check_msvc_native
python3 -m unittest tools.test_release_gates tools.test_server_case tools.test_check_wave_corpus tools.test_runtime_cases tools.test_check_case_sources tools.test_case_execution tools.test_case_manifest tools.test_test_contracts tools.test_process_tree tools.test_check_msvc_native

- name: Build release compiler
run: cargo build --locked --release --verbose
Expand Down Expand Up @@ -702,7 +707,7 @@ jobs:
- name: Validate Windows Python tooling
if: ${{ !cancelled() && steps.python_setup.outcome == 'success' }}
run: >-
python -m unittest tools.test_check_case_sources tools.test_case_execution
python -m unittest tools.test_release_gates tools.test_server_case tools.test_check_wave_corpus tools.test_runtime_cases tools.test_check_case_sources tools.test_case_execution
tools.test_case_manifest tools.test_test_contracts tools.test_process_tree
- name: Check PE dependency failures and case runner selection
if: ${{ !cancelled() && steps.python_setup.outcome == 'success' }}
Expand Down Expand Up @@ -834,7 +839,7 @@ jobs:

- name: Check native Windows process supervision
if: ${{ !cancelled() && steps.python_setup.outcome == 'success' }}
run: python -m unittest tools.test_check_case_sources tools.test_case_execution tools.test_process_tree
run: python -m unittest tools.test_release_gates tools.test_server_case tools.test_check_wave_corpus tools.test_runtime_cases tools.test_check_case_sources tools.test_case_execution tools.test_process_tree

- name: Run native ARM64 unit and frontend driver tests
if: ${{ !cancelled() && steps.native_build.outcome == 'success' }}
Expand Down Expand Up @@ -1002,6 +1007,11 @@ jobs:
cargo build --locked --release --no-default-features
--features llvm-target-wasm --jobs 2

- name: Run frontend regressions with the WebAssembly backend only
run: >-
cargo test --locked --no-default-features --features llvm-target-wasm
--test frontend_regressions --jobs 2

- name: Run WebAssembly compiler regressions
run: >-
cargo test --locked --no-default-features
Expand Down
7 changes: 5 additions & 2 deletions std/env/cwd.wave
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,19 @@ import("std::sys::fs")::{
};

pub fun env_getcwd(dst: ptr<u8>, cap: i64) -> i64 {
if (dst == null || cap <= 0) { return -1; }
var r: i64 = getcwd(dst, cap);
if (r <= 0) {
// FreeBSD returns zero on success; Linux returns the bytes written.
if (r < 0) {
return -1;
}

var n: i64 = 0;
while (dst[n] != 0) {
while (n < cap && dst[n] != 0) {
n += 1;
}

if (n == cap) { return -1; }
return n;
}

Expand Down
4 changes: 2 additions & 2 deletions std/net/poll.wave
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const NET_POLL_POSIX: bool = true;
const NET_POLL_POSIX: bool = false;

pub fun net_wait_readable(fd: i64, timeout_ms: i32) -> i64 {
if (NET_POLL_POSIX && fd < 0) { return -9; }
if (NET_POLL_POSIX && (fd < 0 || fd > 2147483647)) { return -9; }
var descriptor: PollFd = _net_poll_fd(fd, NET_POLLIN);
var result: i64 = net_poll(&descriptor, 1, timeout_ms);
if (result <= 0) { return result; }
Expand All @@ -68,7 +68,7 @@ pub fun net_wait_readable(fd: i64, timeout_ms: i32) -> i64 {
}

pub fun net_wait_writable(fd: i64, timeout_ms: i32) -> i64 {
if (NET_POLL_POSIX && fd < 0) { return -9; }
if (NET_POLL_POSIX && (fd < 0 || fd > 2147483647)) { return -9; }
var descriptor: PollFd = _net_poll_fd(fd, NET_POLLOUT);
var result: i64 = net_poll(&descriptor, 1, timeout_ms);
if (result <= 0) { return result; }
Expand Down
16 changes: 16 additions & 0 deletions tests/cases/freebsd/amd64/test14/main.wave
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// wave-test: mode=build, runner=compile, target=x86_64-unknown-freebsd, emit=obj, object-arch=x86_64, object-bits=64
// SPDX-License-Identifier: MPL-2.0
import("std::env::cwd")::{env_getcwd};
fun main() -> i32 {
var buffer: array<u8, 4096>;
var length: i64 = env_getcwd(&buffer[0], 4096);
if (length <= 0 || length >= 4096 || buffer[length] != 0) { return 1; }
var i: i64 = 0;
while (i < length) {
if (buffer[i] == 0) { return 2; }
i += 1;
}
if (env_getcwd(&buffer[0], 1) != -1) { return 3; }
if (env_getcwd(null, 4096) != -1 || env_getcwd(&buffer[0], 0) != -1) { return 4; }
return 0;
}
60 changes: 47 additions & 13 deletions tests/cases/linux/amd64/test5.wave
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,17 @@ fun _write(fd: i64, buf: str, len: i64) -> i64 {

fun new_server(port: i16) -> i64 {
var sockfd: i64 = _socket_create_tcp();
if (sockfd < 0) {
if (sockfd == -1 || sockfd == -13) { println("WAVE-SERVER-UNAVAILABLE {}", sockfd); }
return -1;
}
_setsockopt_reuseaddr(sockfd);
if (sockfd < 0) { return -1; }

var b: i64 = _socket_bind_any(sockfd, port);
println("bind ret = {}", b);

if (b < 0) {
if (b == -1 || b == -13) { println("WAVE-SERVER-UNAVAILABLE {}", b); }
_socket_close(sockfd);
return -1;
}
Expand Down Expand Up @@ -214,24 +218,54 @@ fun start(server_fd: i64) {

println("Client connected! fd: {}", client_fd);

var response: str = "HTTP/1.1 200 OK\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: 33\r\nConnection: close\r\n\r\nWelcome to the Wave HTTP Server!";


_write(client_fd, response, len(response));
var request: array<u8, 1024>;
var used: i64 = 0;
while (used < 1024) {
var count: i64 = syscall3pi(0, client_fd, &request[used] as ptr<i8>, 1024 - used);
if (count <= 0) { break; }
used += count;
if (used >= 4 && request[used - 4] == 13 && request[used - 3] == 10 && request[used - 2] == 13 && request[used - 1] == 10) { break; }
}
var response: str = "HTTP/1.1 200 OK\r\nContent-Type: text/plain; charset=utf-8\r\nConnection: close\r\n\r\nWelcome to the Wave HTTP Server!\n";
write_all(client_fd, response as ptr<i8>, len(response) as i64);
write_all(client_fd, &request[0] as ptr<i8>, used);

_socket_close(client_fd);
println("Client disconnected.");
}
}

fun main() {
println("--- Wave HTTP Server Application ---");

var server_instance: i64 = new_server(8080).listen(10);
fun write_all(fd: i64, buffer: ptr<i8>, size: i64) {
var sent: i64 = 0;
while (sent < size) {
var count: i64 = syscall3pi(1, fd, buffer + sent, size - sent);
if (count <= 0) { return; }
sent += count;
}
}

if (server_instance >= 0) {
server_instance.start();
} else {
println("Server failed to start.");
fun main() -> i32 {
var server_instance: i64 = new_server(0).listen(10);
if (server_instance < 0) { return 1; }
var address: SockAddrIn;
var address_size: i32 = 16;
var result: i64 = syscall3(51, server_instance, &address as i64, &address_size as i64);
if (result < 0) { return 2; }
var network_port: u16 = address.sin_port as u16;
var port: u32 = ((network_port as u32 & 255) << 8) | (network_port as u32 >> 8);
// The runner captures stdout, so publish readiness without stdio buffering.
var prefix: str = "WAVE-SERVER-READY ";
_write(1, prefix, len(prefix) as i64);
var digits: array<u8, 6>;
digits[5] = 10;
var offset: i64 = 5;
var remaining: u32 = port;
while (remaining > 0) {
offset -= 1;
digits[offset] = (remaining % 10 + 48) as u8;
remaining /= 10;
}
write_all(1, &digits[offset] as ptr<i8>, 6 - offset);
server_instance.start();
return 0;
}
15 changes: 15 additions & 0 deletions tests/fixtures/native_providers/cwd.wave
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: MPL-2.0
import("std::env::cwd")::{env_getcwd};
fun main() -> i32 {
var buffer: array<u8, 4096>;
var length: i64 = env_getcwd(&buffer[0], 4096);
if (length <= 0 || length >= 4096 || buffer[length] != 0) { return 1; }
var i: i64 = 0;
while (i < length) {
if (buffer[i] == 0) { return 2; }
i += 1;
}
if (env_getcwd(&buffer[0], 1) != -1) { return 3; }
if (env_getcwd(null, 4096) != -1 || env_getcwd(&buffer[0], 0) != -1) { return 4; }
return 0;
}
26 changes: 26 additions & 0 deletions tests/fixtures/native_providers/posix_poll_range.wave
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: MPL-2.0
import("std::net::poll")::{PollFd, NET_POLLIN, net_poll, net_wait_readable, net_wait_writable, net_wait_connected};
import("std::sys::fs")::{pipe, write, close};
fun main() -> i32 {
var invalid: array<i64, 5> = [-1, 2147483648, 4294967295, 4294967296, 9223372036854775807];
var i: i32 = 0;
while (i < 5) {
if (net_wait_readable(invalid[i], -1) != -9) { return 1; }
if (net_wait_writable(invalid[i], -1) != -9) { return 2; }
if (net_wait_connected(invalid[i], -1) != -9) { return 3; }
i += 1;
}
var disabled: PollFd = PollFd { fd: -1, events: NET_POLLIN, revents: 0 };
if (net_poll(&disabled, 1, 0) != 0) { return 4; }
var fds: array<i32, 2>;
if (pipe(&fds[0]) < 0) { return 5; }
var read_fd: i64 = fds[0] as i64;
var write_fd: i64 = fds[1] as i64;
if (net_wait_readable(read_fd, 0) != 0 || net_wait_writable(write_fd, 0) != 1) { return 6; }
var payload: u8 = 42;
if (write(write_fd, &payload, 1) != 1 || net_wait_readable(read_fd, 0) != 1) { return 7; }
if (net_wait_readable(read_fd + 4294967296, 0) != -9) { return 8; }
close(read_fd);
close(write_fd);
return 0;
}
83 changes: 83 additions & 0 deletions tests/native_providers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,32 @@ fn loongarch_attribute_aliases_select_identical_declarations() {
fn native_provider_fixtures_compile_and_run_on_their_host() {
let case = Case::new();
for (source, targets) in [
(
"cwd.wave",
vec![
"x86_64-unknown-linux-gnu",
"aarch64-unknown-linux-gnu",
"riscv64-unknown-linux-gnu",
"loongarch64-unknown-linux-gnu",
"x86_64-apple-darwin",
"aarch64-apple-darwin",
"x86_64-pc-windows-msvc",
"aarch64-pc-windows-msvc",
"x86_64-unknown-freebsd",
],
),
(
"posix_poll_range.wave",
vec![
"x86_64-unknown-linux-gnu",
"aarch64-unknown-linux-gnu",
"riscv64-unknown-linux-gnu",
"loongarch64-unknown-linux-gnu",
"x86_64-apple-darwin",
"aarch64-apple-darwin",
"x86_64-unknown-freebsd",
],
),
(
"dup2.wave",
vec![
Expand Down Expand Up @@ -584,3 +610,60 @@ fn network_error_values_remain_available_without_a_socket_provider() {
);
}
}

#[test]
fn cwd_accepts_zero_success_without_scanning_outside_capacity() {
let target = host_target();
if !supported(&target) {
return;
}
let case = Case::new();
let provider = fs::read_to_string(root().join("std/env/cwd.wave")).unwrap();
let body = provider
.split("pub fun env_getcwd")
.nth(1)
.unwrap()
.split("pub fun env_chdir")
.next()
.unwrap();
let source = case.0.join("cwd-contract.wave");
fs::write(
&source,
format!(
"pub fun env_getcwd{body}{}",
r#"
fun getcwd(dst: ptr<u8>, cap: i64) -> i64 {
if (cap == 4) { return -34; }
if (cap == 5) {
var i: i64 = 0;
while (i < cap) { dst[i] = 47; i += 1; }
return 0;
}
dst[0] = 47; dst[1] = 0;
if (cap == 3) { return 2; }
return 0;
}
fun main() -> i32 {
var buffer: array<u8, 6>;
buffer[5] = 123;
if (env_getcwd(&buffer[0], 2) != 1) { return 1; }
if (env_getcwd(&buffer[0], 3) != 1) { return 2; }
if (env_getcwd(&buffer[0], 4) != -1) { return 3; }
if (env_getcwd(&buffer[0], 5) != -1 || buffer[5] != 123) { return 4; }
if (env_getcwd(null, 2) != -1 || env_getcwd(&buffer[0], 0) != -1) { return 5; }
return 0;
}
"#
),
)
.unwrap();
for opt in ["-O0", "-O2"] {
let output = case.0.join("cwd-contract.exe");
build(&case, &source, &target, opt, &output, false);
checked(
&mut Command::new(output),
"getcwd provider convention",
&case.0,
);
}
}
Loading
Loading