Skip to content
This repository has been archived by the owner on Oct 7, 2020. It is now read-only.

Commit

Permalink
wasi: port more wasi libc integration tests
Browse files Browse the repository at this point in the history
This commit ports the following tests from
nodejs/node#27850.

- clock_getres
- getentropy (currently disabled)
- getrusage
- gettimeofday
- notdir
- preopen_populates
- read_file_twice
- stat
- stdin
- write_file

This commit completes the implementations of
fd_filestat_get() and path_filestat_get(), which
are needed for the stat test. This commit also
adds clock_res_get() and partial clock_time_get()
support.
  • Loading branch information
cjihrig committed Nov 5, 2019
1 parent 1f8fcae commit 1155b22
Show file tree
Hide file tree
Showing 24 changed files with 293 additions and 26 deletions.
62 changes: 40 additions & 22 deletions deps/uvwasi/src/uvwasi.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,49 +348,67 @@ uvwasi_errno_t uvwasi_args_sizes_get(uvwasi_t* uvwasi,
uvwasi_errno_t uvwasi_clock_res_get(uvwasi_t* uvwasi,
uvwasi_clockid_t clock_id,
uvwasi_timestamp_t* resolution) {
#ifndef _WIN32
struct timespec ts;
clockid_t clk;
#endif /* _WIN32 */

if (uvwasi == NULL || resolution == NULL)
return UVWASI_EINVAL;

/*
if (clock_id == UVWASI_CLOCK_MONOTONIC) {
} else if (clock_id == UVWASI_CLOCK_PROCESS_CPUTIME_ID) {
} else if (clock_id == UVWASI_CLOCK_REALTIME) {
if (clock_id == UVWASI_CLOCK_MONOTONIC ||
clock_id == UVWASI_CLOCK_REALTIME) {
*resolution = 1; // Nanosecond precision.
return UVWASI_ESUCCESS;
} else if (clock_id == UVWASI_CLOCK_PROCESS_CPUTIME_ID ||
clock_id == UVWASI_CLOCK_THREAD_CPUTIME_ID) {
#ifndef _WIN32
if (clock_id == UVWASI_CLOCK_PROCESS_CPUTIME_ID)
clk = CLOCK_PROCESS_CPUTIME_ID;
else
clk = CLOCK_THREAD_CPUTIME_ID;

} else if (clock_id == UVWASI_CLOCK_THREAD_CPUTIME_ID) {
if (clock_getres(clk, &ts) < 0)
return uvwasi__translate_uv_error(uv_translate_sys_error(errno));

} else {
return UVWASI_EINVAL;
*resolution = (ts.tv_sec * NANOS_PER_SEC) + ts.tv_nsec;
return UVWASI_ESUCCESS;
#else
return UVWASI_ENOSYS;
#endif /* _WIN32 */
}
*/

return UVWASI_ENOTSUP;
return UVWASI_EINVAL;
}


uvwasi_errno_t uvwasi_clock_time_get(uvwasi_t* uvwasi,
uvwasi_clockid_t clock_id,
uvwasi_timestamp_t precision,
uvwasi_timestamp_t* time) {
uv_timeval64_t tv;
int r;

if (uvwasi == NULL || time == NULL)
return UVWASI_EINVAL;

/*
if (clock_id == UVWASI_CLOCK_MONOTONIC) {
} else if (clock_id == UVWASI_CLOCK_PROCESS_CPUTIME_ID) {
*time = uv_hrtime();
return UVWASI_ESUCCESS;
} else if (clock_id == UVWASI_CLOCK_REALTIME) {
} else if (clock_id == UVWASI_CLOCK_THREAD_CPUTIME_ID) {
} else {
return UVWASI_EINVAL;
r = uv_gettimeofday(&tv);
if (r != 0)
return uvwasi__translate_uv_error(r);

*time = (tv.tv_sec * NANOS_PER_SEC) + (tv.tv_usec * 1000);
return UVWASI_ESUCCESS;
} else if (clock_id == UVWASI_CLOCK_PROCESS_CPUTIME_ID ||
clock_id == UVWASI_CLOCK_THREAD_CPUTIME_ID) {
/* TODO(cjihrig): Implement these two clocks. */
return UVWASI_ENOSYS;
}
*/

return UVWASI_ENOTSUP;
return UVWASI_EINVAL;
}


Expand Down
37 changes: 35 additions & 2 deletions src/node_wasi.cc
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,23 @@ void WASI::FdFilestatGet(const FunctionCallbackInfo<Value>& args) {
uvwasi_filestat_t stats;
uvwasi_errno_t err = uvwasi_fd_filestat_get(&wasi->uvw_, fd, &stats);

// TODO(cjihrig): Check for buffer overflow and write result to memory.
// TODO(cjihrig): Check for buffer overflows.
if (err == UVWASI_ESUCCESS)
err = wasi->writeUInt64(stats.st_dev, buf);
if (err == UVWASI_ESUCCESS)
err = wasi->writeUInt64(stats.st_ino, buf + 8);
if (err == UVWASI_ESUCCESS)
err = wasi->writeUInt8(stats.st_filetype, buf + 16);
if (err == UVWASI_ESUCCESS)
err = wasi->writeUInt32(stats.st_nlink, buf + 20);
if (err == UVWASI_ESUCCESS)
err = wasi->writeUInt64(stats.st_size, buf + 24);
if (err == UVWASI_ESUCCESS)
err = wasi->writeUInt64(stats.st_atim, buf + 32);
if (err == UVWASI_ESUCCESS)
err = wasi->writeUInt64(stats.st_mtim, buf + 40);
if (err == UVWASI_ESUCCESS)
err = wasi->writeUInt64(stats.st_ctim, buf + 48);

args.GetReturnValue().Set(err);
}
Expand Down Expand Up @@ -884,7 +900,24 @@ void WASI::PathFilestatGet(const FunctionCallbackInfo<Value>& args) {
&memory[path_ptr],
path_len,
&stats);
// TODO(cjihrig): Check for buffer overflows and write output.
// TODO(cjihrig): Check for buffer overflows.
if (err == UVWASI_ESUCCESS)
err = wasi->writeUInt64(stats.st_dev, buf_ptr);
if (err == UVWASI_ESUCCESS)
err = wasi->writeUInt64(stats.st_ino, buf_ptr + 8);
if (err == UVWASI_ESUCCESS)
err = wasi->writeUInt8(stats.st_filetype, buf_ptr + 16);
if (err == UVWASI_ESUCCESS)
err = wasi->writeUInt32(stats.st_nlink, buf_ptr + 20);
if (err == UVWASI_ESUCCESS)
err = wasi->writeUInt64(stats.st_size, buf_ptr + 24);
if (err == UVWASI_ESUCCESS)
err = wasi->writeUInt64(stats.st_atim, buf_ptr + 32);
if (err == UVWASI_ESUCCESS)
err = wasi->writeUInt64(stats.st_mtim, buf_ptr + 40);
if (err == UVWASI_ESUCCESS)
err = wasi->writeUInt64(stats.st_ctim, buf_ptr + 48);

args.GetReturnValue().Set(err);
}

Expand Down
Empty file added test/fixtures/wasi/notadir
Empty file.
17 changes: 17 additions & 0 deletions test/wasi/c/clock_getres.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <assert.h>
#include <time.h>

int main() {
struct timespec ts;
int r;

// supported clocks
r = clock_getres(CLOCK_REALTIME, &ts);
assert(r == 0);
r = clock_getres(CLOCK_MONOTONIC, &ts);
assert(r == 0);
r = clock_getres(CLOCK_PROCESS_CPUTIME_ID, &ts);
assert(r == 0);
r = clock_getres(CLOCK_THREAD_CPUTIME_ID, &ts);
assert(r == 0);
}
18 changes: 18 additions & 0 deletions test/wasi/c/getentropy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <assert.h>
#include <unistd.h>

int main() {
char buf[256] = {0};
int r = getentropy(buf, 256);
assert(r == 0);

for (int i = 0; i < 256; i++) {
if (buf[i] != 0) {
return 0;
}
}

// if this ever is reached, we either have a bug or should buy a lottery
// ticket
return 1;
}
24 changes: 24 additions & 0 deletions test/wasi/c/getrusage.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <assert.h>
#include <sys/resource.h>

int main() {
struct rusage ru1;
getrusage(RUSAGE_SELF, &ru1);

for (int i = 0; i < 1000; i++) {
}

struct rusage ru2;
getrusage(RUSAGE_SELF, &ru2);

// assert that some time has passed
long long s1 = ru1.ru_utime.tv_sec;
long long us1 = ru1.ru_utime.tv_usec;
long long s2 = ru2.ru_utime.tv_sec;
long long us2 = ru2.ru_utime.tv_usec;
assert(s1 <= s2);
if (s1 == s2) {
// strictly less than, so the timestamps can't be equal
assert(us1 < us2);
}
}
25 changes: 25 additions & 0 deletions test/wasi/c/gettimeofday.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <assert.h>
#include <stdlib.h>
#include <sys/time.h>

int main() {
struct timeval tv1;
gettimeofday(&tv1, NULL);

for (int i = 0; i < 1000; i++) {
}

struct timeval tv2;
gettimeofday(&tv2, NULL);

// assert that some time has passed
long long s1 = tv1.tv_sec;
long long us1 = tv1.tv_usec;
long long s2 = tv2.tv_sec;
long long us2 = tv2.tv_usec;
assert(s1 <= s2);
if (s1 == s2) {
// strictly less than, so the timestamps can't be equal
assert(us1 < us2);
}
}
11 changes: 11 additions & 0 deletions test/wasi/c/notdir.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include <assert.h>
#include <dirent.h>
#include <errno.h>

int main() {
DIR* dir = opendir("/sandbox/notadir");
assert(dir == NULL);
assert(errno == ENOTDIR);

return 0;
}
3 changes: 3 additions & 0 deletions test/wasi/c/preopen_populates.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
int main(void) {
return 0;
}
16 changes: 16 additions & 0 deletions test/wasi/c/read_file_twice.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <assert.h>
#include <stdio.h>

int main() {
for (int i = 0; i < 2; i++) {
FILE* file = fopen("/sandbox/input.txt", "r");
assert(file != NULL);

char c = fgetc(file);
while (c != EOF) {
int wrote = fputc(c, stdout);
assert(wrote != EOF);
c = fgetc(file);
}
}
}
53 changes: 53 additions & 0 deletions test/wasi/c/stat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include <sys/stat.h>

#include <assert.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>

#define BASE_DIR "/tmp"
#define OUTPUT_DIR BASE_DIR "/testdir"
#define PATH OUTPUT_DIR "/output.txt"
#define SIZE 500

int main(void) {
struct stat st;
int fd;
int ret;
off_t pos;

(void)st;
ret = mkdir(OUTPUT_DIR, 0755);
assert(ret == 0);

fd = open(PATH, O_CREAT | O_WRONLY, 0666);
assert(fd != -1);

pos = lseek(fd, SIZE - 1, SEEK_SET);
assert(pos == SIZE - 1);

ret = (int)write(fd, "", 1);
assert(ret == 1);

ret = fstat(fd, &st);
assert(ret == 0);
assert(st.st_size == SIZE);

ret = close(fd);
assert(ret == 0);

ret = access(PATH, R_OK);
assert(ret == 0);

ret = stat(PATH, &st);
assert(ret == 0);
assert(st.st_size == SIZE);

ret = unlink(PATH);
assert(ret == 0);

ret = stat(PATH, &st);
assert(ret == -1);

return 0;
}
13 changes: 13 additions & 0 deletions test/wasi/c/stdin.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <stdio.h>

int main(void) {
char x[32];

if (fgets(x, sizeof x, stdin) == NULL) {
return ferror(stdin);
}
if (fputs(x, stdout) == EOF) {
return ferror(stdout);
}
return 0;
}
15 changes: 15 additions & 0 deletions test/wasi/c/write_file.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <assert.h>
#include <stdio.h>
#include <string.h>

static char* message = "hello, file!";

int main() {
FILE* file = fopen("/tmp/output.txt", "w");
assert(file != NULL);

int nwritten = fprintf(file, "%s", message);
assert(nwritten == strlen(message));
int r = fclose(file);
assert(r == 0);
}
Loading

0 comments on commit 1155b22

Please sign in to comment.