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 18static zx_handle_t log_handle; 19 20#define LOGBUF_MAX (ZX_LOG_RECORD_MAX - sizeof(zx_log_record_t)) 21 22static 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 36static zx_handle_t root_resource; 37 38void __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 49zx_handle_t get_root_resource(void) { 50 return root_resource; 51} 52 53ssize_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 60ssize_t readv(int fd, const struct iovec* iov, int num) { 61 return 0; 62} 63 64ssize_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 86off_t lseek(int fd, off_t offset, int whence) { 87 ERROR(); 88} 89 90int isatty(int fd) { 91 return 1; 92} 93 94int 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