1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <errno.h>
6 #include <stdio.h>
7 #include <unistd.h>
8 #include <sys/uio.h>
9
10 #include <zircon/processargs.h>
11 #include <zircon/syscalls.h>
12 #include <zircon/syscalls/log.h>
13
14 #include <unittest/unittest.h>
15
16 // output via debuglog syscalls
17
18 static zx_handle_t log_handle;
19
20 #define LOGBUF_MAX (ZX_LOG_RECORD_MAX - sizeof(zx_log_record_t))
21
log_write(const void * data,size_t len)22 static void log_write(const void* data, size_t len) {
23 while (len > 0) {
24 size_t xfer = (len > LOGBUF_MAX) ? LOGBUF_MAX : len;
25 zx_debuglog_write(log_handle, 0, data, xfer);
26 data += xfer;
27 len -= xfer;
28 }
29 }
30
31
32 // libc init and io stubs
33 // The reason these are here is that the "core" tests intentionally do not
34 // use fdio. See ./README.md.
35
36 static zx_handle_t root_resource;
37
__libc_extensions_init(uint32_t count,zx_handle_t handle[],uint32_t info[])38 void __libc_extensions_init(uint32_t count, zx_handle_t handle[], uint32_t info[]) {
39 for (unsigned n = 0; n < count; n++) {
40 if (info[n] == PA_HND(PA_RESOURCE, 0)) {
41 root_resource = handle[n];
42 handle[n] = 0;
43 info[n] = 0;
44 break;
45 }
46 }
47 }
48
get_root_resource(void)49 zx_handle_t get_root_resource(void) {
50 return root_resource;
51 }
52
write(int fd,const void * data,size_t count)53 ssize_t write(int fd, const void* data, size_t count) {
54 if ((fd == 1) || (fd == 2)) {
55 log_write(data, count);
56 }
57 return count;
58 }
59
readv(int fd,const struct iovec * iov,int num)60 ssize_t readv(int fd, const struct iovec* iov, int num) {
61 return 0;
62 }
63
writev(int fd,const struct iovec * iov,int num)64 ssize_t writev(int fd, const struct iovec* iov, int num) {
65 ssize_t count = 0;
66 ssize_t r;
67 while (num > 0) {
68 if (iov->iov_len != 0) {
69 r = write(fd, iov->iov_base, iov->iov_len);
70 if (r < 0) {
71 return count ? count : r;
72 }
73 if ((size_t)r < iov->iov_len) {
74 return count + r;
75 }
76 count += r;
77 }
78 iov++;
79 num--;
80 }
81 return count;
82 }
83
84 #define ERROR() do { errno = ENOSYS; return -1; } while (0)
85
lseek(int fd,off_t offset,int whence)86 off_t lseek(int fd, off_t offset, int whence) {
87 ERROR();
88 }
89
isatty(int fd)90 int isatty(int fd) {
91 return 1;
92 }
93
main(int argc,char ** argv)94 int main(int argc, char** argv) {
95 if (zx_debuglog_create(ZX_HANDLE_INVALID, 0, &log_handle) < 0) {
96 return -2;
97 }
98 zx_debuglog_write(log_handle, 0, "TEST", 4);
99
100 if (get_root_resource() == ZX_HANDLE_INVALID) {
101 fprintf(stderr, "Cannot access root resource, refusing to run tests.\n");
102 fprintf(stderr, "core-tests must be invoked by userboot (e.g. userboot=bin/core-tests).\n");
103 return -1;
104 }
105 const bool success = unittest_run_all_tests(argc, argv);
106 if (!success) {
107 return EXIT_FAILURE;
108 }
109
110 // The continuous integration infrastructure looks for this string in the output. This exact
111 // string is matched in the recipe code. They need to be kept in sync. This random value was
112 // chosen because it's unlikely to be produced by other code paths.
113 fprintf(stderr, "core-tests succeeded RZMm59f7zOSs6aZUIXZR\n");
114
115 return EXIT_SUCCESS;
116 }
117