diff --git a/Makefile b/Makefile index 37bfd2e..e9601e2 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,6 @@ tools: build: (cd userland && $(MAKE) build) (cd man && $(MAKE) install-staging) - (cd testscripts && $(MAKE) build) includes tags depend: (cd kern && $(MAKE) $@) diff --git a/configure b/configure index ae861a1..0e3586b 100755 --- a/configure +++ b/configure @@ -134,7 +134,6 @@ else HOST_CFLAGS="${HOST_CFLAGS} -DDECLARE_NTOHLL" fi - #################### # Now generate defs.mk. diff --git a/kern/arch/mips/vm/dumbvm.c b/kern/arch/mips/vm/dumbvm.c index cf9d916..1b2e6cd 100644 --- a/kern/arch/mips/vm/dumbvm.c +++ b/kern/arch/mips/vm/dumbvm.c @@ -126,6 +126,21 @@ free_kpages(vaddr_t addr) (void)addr; } +unsigned +int +coremap_used_bytes() { + + /* dumbvm doesn't track page allocations. Return 0 so that khu works. */ + + return 0; +} + +void +vm_tlbshootdown_all(void) +{ + panic("dumbvm tried to do tlb shootdown?!\n"); +} + void vm_tlbshootdown(const struct tlbshootdown *ts) { diff --git a/kern/conf/DUMBVM b/kern/conf/DUMBVM index 7862c64..3216e1f 100644 --- a/kern/conf/DUMBVM +++ b/kern/conf/DUMBVM @@ -30,3 +30,4 @@ options sfs # Always use the file system #options netfs # You might write this as a project. options dumbvm # Chewing gum and baling wire. +#options synchprobs # Uncomment to enable ASST1 synchronization problems diff --git a/kern/conf/conf.kern b/kern/conf/conf.kern index 48ed457..5e5f927 100644 --- a/kern/conf/conf.kern +++ b/kern/conf/conf.kern @@ -309,6 +309,14 @@ file ../common/libc/string/strlen.c file ../common/libc/string/strrchr.c file ../common/libc/string/strtok_r.c +# +# libtest161 shared code and security functions +# + +file ../common/libtest161/test161.c +file ../common/libtest161/secure.c +file ../common/libtest161/sha256.c + ######################################## # # # Core kernel source files # @@ -434,7 +442,19 @@ file test/threadlisttest.c file test/threadtest.c file test/tt3.c file test/synchtest.c +file test/rwtest.c file test/semunit.c +file test/hmacunit.c file test/kmalloctest.c file test/fstest.c +file test/lib.c + optfile net test/nettest.c + +defoption synchprobs +optfile synchprobs synchprobs/whalemating.c +optfile synchprobs synchprobs/stoplight.c +optfile synchprobs test/synchprobs.c + +defoption automationtest +optfile automationtest test/automationtest.c diff --git a/kern/conf/config b/kern/conf/config index 01bca35..ddbb50a 100755 --- a/kern/conf/config +++ b/kern/conf/config @@ -206,7 +206,7 @@ echo "$CONFNAME" $CONFTMP | awk ' # if [ ! -d "$COMPILEDIR" ]; then - mkdir $COMPILEDIR + mkdir -p $COMPILEDIR fi echo -n 'Generating files...' diff --git a/kern/include/cpu.h b/kern/include/cpu.h index cd386ec..787c6cf 100644 --- a/kern/include/cpu.h +++ b/kern/include/cpu.h @@ -35,6 +35,7 @@ #include #include /* for TLBSHOOTDOWN_MAX */ +extern unsigned num_cpus; /* * Per-cpu structure @@ -74,21 +75,24 @@ struct cpu { * Accessed by other cpus. * Protected by the IPI lock. * - * TLB shootdown requests made to this CPU are queued in - * c_shootdown[], with c_numshootdown holding the number of - * requests. TLBSHOOTDOWN_MAX is the maximum number that can - * be queued at once, which is machine-dependent. + * If c_numshootdown is -1 (TLBSHOOTDOWN_ALL), all mappings + * should be invalidated. This is used if more than + * TLBSHOOTDOWN_MAX mappings are going to be invalidated at + * once. TLBSHOOTDOWN_MAX is MD and chosen based on when it + * becomes more efficient just to flush the whole TLB. * - * The contents of struct tlbshootdown are also machine- - * dependent and might reasonably be either an address space - * and vaddr pair, or a paddr, or something else. + * struct tlbshootdown is machine-dependent and might + * reasonably be either an address space and vaddr pair, or a + * paddr, or something else. */ uint32_t c_ipi_pending; /* One bit for each IPI number */ struct tlbshootdown c_shootdown[TLBSHOOTDOWN_MAX]; - unsigned c_numshootdown; + int c_numshootdown; struct spinlock c_ipi_lock; }; +#define TLBSHOOTDOWN_ALL (-1) + /* * Initialization functions. * diff --git a/kern/include/lib.h b/kern/include/lib.h index 7478ce6..5374a96 100644 --- a/kern/include/lib.h +++ b/kern/include/lib.h @@ -129,6 +129,8 @@ uint32_t random(void); void *kmalloc(size_t size); void kfree(void *ptr); void kheap_printstats(void); +void kheap_printused(void); +unsigned long kheap_getused(void); void kheap_nextgeneration(void); void kheap_dump(void); void kheap_dumpall(void); diff --git a/kern/include/synch.h b/kern/include/synch.h index fee3b07..59058d0 100644 --- a/kern/include/synch.h +++ b/kern/include/synch.h @@ -44,10 +44,10 @@ * internally. */ struct semaphore { - char *sem_name; + char *sem_name; struct wchan *sem_wchan; struct spinlock sem_lock; - volatile unsigned sem_count; + volatile unsigned sem_count; }; struct semaphore *sem_create(const char *name, unsigned initial_count); @@ -137,5 +137,40 @@ void cv_wait(struct cv *cv, struct lock *lock); void cv_signal(struct cv *cv, struct lock *lock); void cv_broadcast(struct cv *cv, struct lock *lock); +/* + * Reader-writer locks. + * + * When the lock is created, no thread should be holding it. Likewise, + * when the lock is destroyed, no thread should be holding it. + * + * The name field is for easier debugging. A copy of the name is + * (should be) made internally. + */ + +struct rwlock { + char *rwlock_name; + // add what you need here + // (don't forget to mark things volatile as needed) +}; + +struct rwlock * rwlock_create(const char *); +void rwlock_destroy(struct rwlock *); + +/* + * Operations: + * rwlock_acquire_read - Get the lock for reading. Multiple threads can + * hold the lock for reading at the same time. + * rwlock_release_read - Free the lock. + * rwlock_acquire_write - Get the lock for writing. Only one thread can + * hold the write lock at one time. + * rwlock_release_write - Free the write lock. + * + * These operations must be atomic. You get to write them. + */ + +void rwlock_acquire_read(struct rwlock *); +void rwlock_release_read(struct rwlock *); +void rwlock_acquire_write(struct rwlock *); +void rwlock_release_write(struct rwlock *); #endif /* _SYNCH_H_ */ diff --git a/kern/include/test.h b/kern/include/test.h index 7b02114..9445a5c 100644 --- a/kern/include/test.h +++ b/kern/include/test.h @@ -30,6 +30,13 @@ #ifndef _TEST_H_ #define _TEST_H_ +/* Get __PF() for declaring printf-like functions. */ +#include +#include + +#include "opt-synchprobs.h" +#include "opt-automationtest.h" + /* * Declarations for test code and other miscellaneous high-level * functions. @@ -52,8 +59,18 @@ int threadtest2(int, char **); int threadtest3(int, char **); int semtest(int, char **); int locktest(int, char **); +int locktest2(int, char **); +int locktest3(int, char **); int cvtest(int, char **); int cvtest2(int, char **); +int cvtest3(int, char **); +int cvtest4(int, char **); +int cvtest5(int, char **); +int rwtest(int, char **); +int rwtest2(int, char **); +int rwtest3(int, char **); +int rwtest4(int, char **); +int rwtest5(int, char **); /* semaphore unit tests */ int semu1(int, char **); @@ -88,11 +105,15 @@ int longstress(int, char **); int createstress(int, char **); int printfile(int, char **); +/* HMAC/hash tests */ +int hmacu1(int, char**); + /* other tests */ int kmalloctest(int, char **); int kmallocstress(int, char **); int kmalloctest3(int, char **); int kmalloctest4(int, char **); +int kmalloctest5(int, char **); int nettest(int, char **); /* Routine for running a user-level program. */ @@ -104,5 +125,75 @@ void menu(char *argstr); /* The main function, called from start.S. */ void kmain(char *bootstring); +#if OPT_SYNCHPROBS + +/* + * Synchronization driver primitives. + */ + +void male_start(uint32_t); +void male_end(uint32_t); +void female_start(uint32_t); +void female_end(uint32_t); +void matchmaker_start(uint32_t); +void matchmaker_end(uint32_t); +int whalemating(int, char **); + +void inQuadrant(int, uint32_t); +void leaveIntersection(uint32_t); +int stoplight(int, char **); + +/* + * Synchronization problem primitives. + */ + +/* + * whalemating.c. + */ + +void whalemating_init(void); +void whalemating_cleanup(void); +void male(uint32_t); +void female(uint32_t); +void matchmaker(uint32_t); + +/* + * stoplight.c. + */ + +void gostraight(uint32_t, uint32_t); +void turnleft(uint32_t, uint32_t); +void turnright(uint32_t, uint32_t); +void stoplight_init(void); +void stoplight_cleanup(void); + +#endif + +/* + * Automation tests for detecting kernel deadlocks and livelocks. + */ + +#if OPT_AUTOMATIONTEST +int dltest(int, char **); +int ll1test(int, char **); +int ll16test(int, char **); +#endif + +void random_yielder(uint32_t); +void random_spinner(uint32_t); + +/* + * kprintf variants that do not (or only) print during automated testing. + */ + +#ifdef SECRET_TESTING +#define kprintf_t(...) kprintf(__VA_ARGS__) +#define kprintf_n(...) silent(__VA_ARGS__) +#else +#define kprintf_t(...) silent(__VA_ARGS__) +#define kprintf_n(...) kprintf(__VA_ARGS__) +#endif + +static inline void silent(const char * fmt, ...) { (void)fmt; }; #endif /* _TEST_H_ */ diff --git a/kern/include/thread.h b/kern/include/thread.h index 48ca76d..04a46d3 100644 --- a/kern/include/thread.h +++ b/kern/include/thread.h @@ -48,6 +48,7 @@ struct cpu; /* Size of kernel stacks; must be power of 2 */ #define STACK_SIZE 4096 +#define MAX_NAME_LENGTH 64 /* Mask for extracting the stack base address of a kernel stack pointer */ #define STACK_MASK (~(vaddr_t)(STACK_SIZE-1)) @@ -70,7 +71,16 @@ struct thread { * These go up front so they're easy to get to even if the * debugger is messed up. */ - char *t_name; /* Name of this thread */ + + /* + * Name of this thread. Used to be dynamically allocated using kmalloc, but + * this can cause small changes in the amount of available memory due to the + * fact that it was cleaned up in exorcise. This produces more predictable + * behavior at the cost of a small amount of memory overhead and the + * inability to give threads huge names. + */ + + char t_name[MAX_NAME_LENGTH]; const char *t_wchan_name; /* Name of wait channel, if sleeping */ threadstate_t t_state; /* State this thread is in */ @@ -168,5 +178,7 @@ void schedule(void); */ void thread_consider_migration(void); +extern unsigned thread_count; +void thread_wait_for_count(unsigned); #endif /* _THREAD_H_ */ diff --git a/kern/include/version.h b/kern/include/version.h index 43f66be..532d7ec 100644 --- a/kern/include/version.h +++ b/kern/include/version.h @@ -34,7 +34,7 @@ * Leave this alone, so we can tell what version of the OS/161 base * code we gave you. */ -#define BASE_VERSION "2.0.2" +#define BASE_VERSION "2.0.1" /* * Change this as you see fit in the course of hacking the system. diff --git a/kern/include/vfs.h b/kern/include/vfs.h index b4a6cc3..77b0dc7 100644 --- a/kern/include/vfs.h +++ b/kern/include/vfs.h @@ -156,13 +156,6 @@ int vfs_getcwd(struct uio *buf); * vfs_unmount - Unmount the filesystem presently mounted on the * specified device. * - * vfs_swapon - Look up DEVNAME and mark it as a swap device, - * returning a vnode. Similar to vfs_mount. - * - * vfs_swapoff - Unmark DEVNAME as a swap device. The vnode - * previously returned by vfs_swapon should be - * decref'd first. Similar to vfs_unmount. - * * vfs_unmountall - Unmount all mounted filesystems. */ @@ -179,8 +172,6 @@ int vfs_mount(const char *devname, void *data, struct device *dev, struct fs **result)); int vfs_unmount(const char *devname); -int vfs_swapon(const char *devname, struct vnode **result); -int vfs_swapoff(const char *devname); int vfs_unmountall(void); /* diff --git a/kern/include/vm.h b/kern/include/vm.h index abc0cfe..a783f33 100644 --- a/kern/include/vm.h +++ b/kern/include/vm.h @@ -55,7 +55,15 @@ int vm_fault(int faulttype, vaddr_t faultaddress); vaddr_t alloc_kpages(unsigned npages); void free_kpages(vaddr_t addr); +/* + * Return amount of memory (in bytes) used by allocated coremap pages. If + * there are ongoing allocations, this value could change after it is returned + * to the caller. But it should have been correct at some point in time. + */ +unsigned int coremap_used_bytes(void); + /* TLB shootdown handling called from interprocessor_interrupt */ +void vm_tlbshootdown_all(void); void vm_tlbshootdown(const struct tlbshootdown *); diff --git a/kern/lib/kprintf.c b/kern/lib/kprintf.c index 3adc7a3..2b04bbc 100644 --- a/kern/lib/kprintf.c +++ b/kern/lib/kprintf.c @@ -39,6 +39,8 @@ #include #include // for vfs_sync() #include // for ltrace_stop() +#include +#include /* Flags word for DEBUG() macro. */ @@ -90,13 +92,14 @@ console_send(void *junk, const char *data, size_t len) } /* - * Printf to the console. + * kprintf and tprintf helper function. */ +static +inline int -kprintf(const char *fmt, ...) +__kprintf(const char *fmt, va_list ap) { int chars; - va_list ap; bool dolock; dolock = kprintf_lock != NULL @@ -111,9 +114,7 @@ kprintf(const char *fmt, ...) spinlock_acquire(&kprintf_spinlock); } - va_start(ap, fmt); chars = __vprintf(console_send, NULL, fmt, ap); - va_end(ap); if (dolock) { lock_release(kprintf_lock); @@ -125,6 +126,22 @@ kprintf(const char *fmt, ...) return chars; } +/* + * Printf to the console. + */ +int +kprintf(const char *fmt, ...) +{ + int chars; + va_list ap; + + va_start(ap, fmt); + chars = __kprintf(fmt, ap); + va_end(ap); + + return chars; +} + /* * panic() is for fatal errors. It prints the printf arguments it's * passed and then halts the system. diff --git a/kern/main/main.c b/kern/main/main.c index d095480..715ef99 100644 --- a/kern/main/main.c +++ b/kern/main/main.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include "autoconf.h" // for pseudoconfig @@ -127,6 +128,7 @@ boot(void) vm_bootstrap(); kprintf_bootstrap(); thread_start_cpus(); + test161_bootstrap(); /* Default bootfs - but ignore failure, in case emu0 doesn't exist */ vfs_setbootfs("emu0"); diff --git a/kern/main/menu.c b/kern/main/menu.c index 8905f09..2451b13 100644 --- a/kern/main/menu.c +++ b/kern/main/menu.c @@ -41,8 +41,11 @@ #include #include #include +#include #include "opt-sfs.h" #include "opt-net.h" +#include "opt-synchprobs.h" +#include "opt-automationtest.h" /* * In-kernel menu and command dispatcher. @@ -114,6 +117,7 @@ common_prog(int nargs, char **args) { struct proc *proc; int result; + unsigned tc; /* Create a process for the new program to run in. */ proc = proc_create_runprogram(args[0] /* name */); @@ -121,6 +125,8 @@ common_prog(int nargs, char **args) return ENOMEM; } + tc = thread_count; + result = thread_fork(args[0] /* thread name */, proc /* new process */, cmd_progthread /* thread function */, @@ -136,6 +142,10 @@ common_prog(int nargs, char **args) * once you write the code for handling that. */ + // Wait for all threads to finish cleanup, otherwise khu be a bit behind, + // especially once swapping is enabled. + thread_wait_for_count(tc); + return 0; } @@ -373,6 +383,18 @@ cmd_kheapstats(int nargs, char **args) return 0; } +static +int +cmd_kheapused(int nargs, char **args) +{ + (void)nargs; + (void)args; + + kheap_printused(); + + return 0; +} + static int cmd_kheapgeneration(int nargs, char **args) @@ -466,16 +488,31 @@ static const char *testmenu[] = { "[km2] kmalloc stress test ", "[km3] Large kmalloc test ", "[km4] Multipage kmalloc test ", + "[km5] kmalloc coremap alloc test ", "[tt1] Thread test 1 ", "[tt2] Thread test 2 ", "[tt3] Thread test 3 ", #if OPT_NET "[net] Network test ", #endif - "[sy1] Semaphore test ", - "[sy2] Lock test (1) ", - "[sy3] CV test (1) ", - "[sy4] CV test #2 (1) ", + "[sem1] Semaphore test ", + "[lt1] Lock test 1 (1) ", + "[lt2] Lock test 2 (1*) ", + "[lt3] Lock test 3 (1*) ", + "[cvt1] CV test 1 (1) ", + "[cvt2] CV test 2 (1) ", + "[cvt3] CV test 3 (1*) ", + "[cvt4] CV test 4 (1*) ", + "[cvt5] CV test 5 (1) ", + "[rwt1] RW lock test (1?) ", + "[rwt2] RW lock test 2 (1?) ", + "[rwt3] RW lock test 3 (1?) ", + "[rwt4] RW lock test 4 (1?) ", + "[rwt5] RW lock test 5 (1?) ", +#if OPT_SYNCHPROBS + "[sp1] Whalemating test (1) ", + "[sp2] Stoplight test (1) ", +#endif "[semu1-22] Semaphore unit tests ", "[fs1] Filesystem test ", "[fs2] FS read stress ", @@ -483,6 +520,7 @@ static const char *testmenu[] = { "[fs4] FS write stress 2 ", "[fs5] FS long stress ", "[fs6] FS create stress ", + "[hm1] HMAC unit test ", NULL }; @@ -496,15 +534,41 @@ cmd_testmenu(int n, char **a) showmenu("OS/161 tests menu", testmenu); kprintf(" (1) These tests will fail until you finish the " "synch assignment.\n"); + kprintf(" (*) These tests will panic on success.\n"); + kprintf(" (?) These tests are left to you to implement.\n"); kprintf("\n"); return 0; } +#if OPT_AUTOMATIONTEST +static const char *automationmenu[] = { + "[dl] Deadlock test (*) ", + "[ll1] Livelock test (1 thread) ", + "[ll16] Livelock test (16 threads) ", + NULL +}; + +static +int +cmd_automationmenu(int n, char **a) +{ + (void)n; + (void)a; + + showmenu("OS/161 automation tests menu", automationmenu); + kprintf(" (*) These tests require locks.\n"); + kprintf("\n"); + + return 0; +} +#endif + static const char *mainmenu[] = { "[?o] Operations menu ", "[?t] Tests menu ", "[kh] Kernel heap stats ", + "[khu] Kernel heap usage ", "[khgen] Next kernel heap generation ", "[khdump] Dump kernel heap ", "[q] Quit and shut down ", @@ -536,6 +600,9 @@ static struct { { "help", cmd_mainmenu }, { "?o", cmd_opsmenu }, { "?t", cmd_testmenu }, +#if OPT_AUTOMATIONTEST + { "?a", cmd_automationmenu }, +#endif /* operations */ { "s", cmd_shell }, @@ -554,6 +621,7 @@ static struct { /* stats */ { "kh", cmd_kheapstats }, + { "khu", cmd_kheapused }, { "khgen", cmd_kheapgeneration }, { "khdump", cmd_kheapdump }, @@ -566,18 +634,33 @@ static struct { { "km2", kmallocstress }, { "km3", kmalloctest3 }, { "km4", kmalloctest4 }, + { "km5", kmalloctest5 }, #if OPT_NET { "net", nettest }, #endif { "tt1", threadtest }, { "tt2", threadtest2 }, { "tt3", threadtest3 }, - { "sy1", semtest }, /* synchronization assignment tests */ - { "sy2", locktest }, - { "sy3", cvtest }, - { "sy4", cvtest2 }, + { "sem1", semtest }, + { "lt1", locktest }, + { "lt2", locktest2 }, + { "lt3", locktest3 }, + { "cvt1", cvtest }, + { "cvt2", cvtest2 }, + { "cvt3", cvtest3 }, + { "cvt4", cvtest4 }, + { "cvt5", cvtest5 }, + { "rwt1", rwtest }, + { "rwt2", rwtest2 }, + { "rwt3", rwtest3 }, + { "rwt4", rwtest4 }, + { "rwt5", rwtest5 }, +#if OPT_SYNCHPROBS + { "sp1", whalemating }, + { "sp2", stoplight }, +#endif /* semaphore unit tests */ { "semu1", semu1 }, @@ -611,6 +694,16 @@ static struct { { "fs5", longstress }, { "fs6", createstress }, + /* HMAC unit tests */ + { "hm1", hmacu1 }, + +#if OPT_AUTOMATIONTEST + /* automation tests */ + { "dl", dltest }, + { "ll1", ll1test }, + { "ll16", ll16test }, +#endif + { NULL, NULL } }; @@ -724,7 +817,11 @@ menu(char *args) menu_execute(args, 1); while (1) { - kprintf("OS/161 kernel [? for menu]: "); + /* + * Defined in overwrite.h. If you want to change the kernel prompt, please + * do it in that file. Otherwise automated test testing will break. + */ + kprintf(KERNEL_PROMPT); kgets(buf, sizeof(buf)); menu_execute(buf, 0); } diff --git a/kern/test/kmalloctest.c b/kern/test/kmalloctest.c index 6abb39c..60517fc 100644 --- a/kern/test/kmalloctest.c +++ b/kern/test/kmalloctest.c @@ -33,13 +33,19 @@ #include #include #include +#include #include #include #include /* for PAGE_SIZE */ #include +#include +#include #include "opt-dumbvm.h" +// from arch/mips/vm/ram.c +extern vaddr_t firstfree; + //////////////////////////////////////////////////////////// // km1/km2 @@ -58,6 +64,12 @@ #define ITEMSIZE 997 #define NTHREADS 8 +#define PROGRESS(iter) do { \ + if ((iter % 100) == 0) { \ + kprintf("."); \ + } \ +} while (0) + static void kmallocthread(void *sm, unsigned long num) @@ -69,15 +81,16 @@ kmallocthread(void *sm, unsigned long num) int i; for (i=0; i] [--kernel ]\n"); +} + +/* + * Allocate and free all physical memory a number of times. Along the we, we + * check coremap_used_bytes to make sure it's reporting the number we're + * expecting. + */ +int +kmalloctest5(int nargs, char **args) +{ +#define KM5_ITERATIONS 5 + + // We're expecting an even number of arguments, less arg[0]. + if (nargs > 5 || (nargs % 2) == 0) { + km5_usage(); + return 0; + } + + unsigned avail_page_slack = 0, kernel_page_limit = 0; + int arg = 1; + + while (arg < nargs) { + if (strcmp(args[arg], "--avail") == 0) { + arg++; + avail_page_slack = atoi(args[arg++]); + } else if (strcmp(args[arg], "--kernel") == 0) { + arg++; + kernel_page_limit = atoi(args[arg++]); + } else { + km5_usage(); + return 0; + } + } + +#if OPT_DUMBVM + kprintf("(This test will not work with dumbvm)\n"); +#endif + + // First, we need to figure out how much memory we're running with and how + // much space it will take up if we maintain a pointer to each allocated + // page. We do something similar to km3 - for 32 bit systems with + // PAGE_SIZE == 4096, we can store 1024 pointers on a page. We keep an array + // of page size blocks of pointers which in total can hold enough pointers + // for each page of available physical memory. + unsigned orig_used, ptrs_per_page, num_ptr_blocks, max_pages; + unsigned total_ram, avail_ram, magic, orig_magic, known_pages; + + ptrs_per_page = PAGE_SIZE / sizeof(void *); + total_ram = mainbus_ramsize(); + avail_ram = total_ram - (uint32_t)(firstfree - MIPS_KSEG0); + max_pages = (avail_ram + PAGE_SIZE-1) / PAGE_SIZE; + num_ptr_blocks = (max_pages + ptrs_per_page-1) / ptrs_per_page; + + // The array can go on the stack, we won't have that many + // (sys161 16M max => 4 blocks) + void **ptrs[num_ptr_blocks]; + + for (unsigned i = 0; i < num_ptr_blocks; i++) { + ptrs[i] = kmalloc(PAGE_SIZE); + if (ptrs[i] == NULL) { + panic("Can't allocate ptr page!"); + } + bzero(ptrs[i], PAGE_SIZE); + } + + kprintf("km5 --> phys ram: %uk avail ram: %uk (%u pages) ptr blocks: %u\n", total_ram/1024, + avail_ram/1024, max_pages, num_ptr_blocks); + + // Initially, there must be at least 1 page allocated for each thread stack, + // one page for kmalloc for this thread struct, plus what we just allocated). + // This probably isn't the GLB, but its a decent lower bound. + orig_used = coremap_used_bytes(); + known_pages = num_cpus + num_ptr_blocks + 1; + if (orig_used < known_pages * PAGE_SIZE) { + panic ("Not enough pages initially allocated"); + } + if ((orig_used % PAGE_SIZE) != 0) { + panic("Coremap used bytes should be a multiple of PAGE_SIZE"); + } + + // Test for kernel bloat. + if (kernel_page_limit > 0) { + uint32_t kpages = (total_ram - avail_ram + PAGE_SIZE) / PAGE_SIZE; + if (kpages > kernel_page_limit) { + panic("You're kernel is bloated! Max allowed pages: %d, used pages: %d", + kernel_page_limit, kpages); + } + } + + orig_magic = magic = random(); + + for (int i = 0; i < KM5_ITERATIONS; i++) { + // Step 1: allocate all physical memory, with checks along the way + unsigned int block, pos, oom, pages, used, prev; + void *page; + + block = pos = oom = pages = used = 0; + prev = orig_used; + + while (pages < max_pages+1) { + PROGRESS(pages); + page = kmalloc(PAGE_SIZE); + if (page == NULL) { + oom = 1; + break; + } + + // Make sure we can write to the page + *(uint32_t *)page = magic++; + + // Make sure the number of used bytes is going up, and by increments of PAGE_SIZE + used = coremap_used_bytes(); + if (used != prev + PAGE_SIZE) { + panic("Allocation not equal to PAGE_SIZE. prev: %u used: %u", prev, used); + } + prev = used; + + ptrs[block][pos] = page; + pos++; + if (pos >= ptrs_per_page) { + pos = 0; + block++; + } + pages++; + } + + // Step 2: Check that we were able to allocate a reasonable number of pages + unsigned expected; + if (avail_page_slack > 0 ) { + // max avail pages + what we can prove we allocated + some slack + expected = max_pages - (known_pages + avail_page_slack); + } else { + // At the very least, just so we know things are working. + expected = 3; + } + + if (pages < expected) { + panic("Expected to allocate at least %d pages, only allocated %d", + expected, pages); + } + + // We tried to allocate 1 more page than is available in physical memory. That + // should fail unless you're swapping out kernel pages, which you should + // probably not be doing. + if (!oom) { + panic("Allocated more pages than physical memory. Are you swapping kernel pages?"); + } + + // Step 3: free everything and check that we're back to where we started + for (block = 0; block < num_ptr_blocks; block++) { + for (pos = 0; pos < ptrs_per_page; pos++) { + if (ptrs[block][pos] != NULL) { + // Make sure we got unique addresses + if ((*(uint32_t *)ptrs[block][pos]) != orig_magic++) { + panic("km5: expected %u got %u - your VM is broken!", + orig_magic-1, (*(uint32_t *)ptrs[block][pos])); + } + kfree(ptrs[block][pos]); + } + } + } + + // Check that we're back to where we started + used = coremap_used_bytes(); + if (used != orig_used) { + panic("orig (%u) != used (%u)", orig_used, used); + } + } + + //Clean up the pointer blocks + for (unsigned i = 0; i < num_ptr_blocks; i++) { + kfree(ptrs[i]); + } + + kprintf("\n"); + success(TEST161_SUCCESS, SECRET, "km5"); + return 0; } diff --git a/kern/test/synchtest.c b/kern/test/synchtest.c index c5582e2..23bb151 100644 --- a/kern/test/synchtest.c +++ b/kern/test/synchtest.c @@ -29,6 +29,9 @@ /* * Synchronization test code. + * + * All the contents of this file are overwritten during automated + * testing. Please consider this before changing anything in this file. */ #include @@ -37,185 +40,303 @@ #include #include #include +#include +#include +#define CREATELOOPS 8 #define NSEMLOOPS 63 #define NLOCKLOOPS 120 #define NCVLOOPS 5 #define NTHREADS 32 +#define SYNCHTEST_YIELDER_MAX 16 static volatile unsigned long testval1; static volatile unsigned long testval2; static volatile unsigned long testval3; -static struct semaphore *testsem; -static struct lock *testlock; -static struct cv *testcv; -static struct semaphore *donesem; +static volatile int32_t testval4; + +static struct semaphore *testsem = NULL; +static struct semaphore *testsem2 = NULL; +static struct lock *testlock = NULL; +static struct lock *testlock2 = NULL; +static struct cv *testcv = NULL; +static struct semaphore *donesem = NULL; + +struct spinlock status_lock; +static bool test_status = TEST161_FAIL; + +static unsigned long semtest_current; static -void -inititems(void) -{ - if (testsem==NULL) { - testsem = sem_create("testsem", 2); - if (testsem == NULL) { - panic("synchtest: sem_create failed\n"); - } - } - if (testlock==NULL) { - testlock = lock_create("testlock"); - if (testlock == NULL) { - panic("synchtest: lock_create failed\n"); - } - } - if (testcv==NULL) { - testcv = cv_create("testlock"); - if (testcv == NULL) { - panic("synchtest: cv_create failed\n"); - } - } - if (donesem==NULL) { - donesem = sem_create("donesem", 0); - if (donesem == NULL) { - panic("synchtest: sem_create failed\n"); - } +bool +failif(bool condition) { + if (condition) { + spinlock_acquire(&status_lock); + test_status = TEST161_FAIL; + spinlock_release(&status_lock); } + return condition; } static void semtestthread(void *junk, unsigned long num) { - int i; (void)junk; + int i; + + random_yielder(4); + /* * Only one of these should print at a time. */ P(testsem); - kprintf("Thread %2lu: ", num); + semtest_current = num; + + kprintf_n("Thread %2lu: ", num); for (i=0; it_name = kstrdup(name); - if (t->t_name == NULL) { - panic("threadlisttest: Out of memory\n"); - } + strcpy(t->t_name, name); t->t_stack = FAKE_MAGIC; threadlistnode_init(&t->t_listnode, t); return t; @@ -84,7 +81,6 @@ fakethread_destroy(struct thread *t) { KASSERT(t->t_stack == FAKE_MAGIC); threadlistnode_cleanup(&t->t_listnode); - kfree(t->t_name); kfree(t); } diff --git a/kern/thread/synch.c b/kern/thread/synch.c index d083f4b..b7a08d9 100644 --- a/kern/thread/synch.c +++ b/kern/thread/synch.c @@ -47,18 +47,18 @@ struct semaphore * sem_create(const char *name, unsigned initial_count) { - struct semaphore *sem; + struct semaphore *sem; - sem = kmalloc(sizeof(*sem)); - if (sem == NULL) { - return NULL; - } + sem = kmalloc(sizeof(*sem)); + if (sem == NULL) { + return NULL; + } - sem->sem_name = kstrdup(name); - if (sem->sem_name == NULL) { - kfree(sem); - return NULL; - } + sem->sem_name = kstrdup(name); + if (sem->sem_name == NULL) { + kfree(sem); + return NULL; + } sem->sem_wchan = wchan_create(sem->sem_name); if (sem->sem_wchan == NULL) { @@ -68,39 +68,39 @@ sem_create(const char *name, unsigned initial_count) } spinlock_init(&sem->sem_lock); - sem->sem_count = initial_count; + sem->sem_count = initial_count; - return sem; + return sem; } void sem_destroy(struct semaphore *sem) { - KASSERT(sem != NULL); + KASSERT(sem != NULL); /* wchan_cleanup will assert if anyone's waiting on it */ spinlock_cleanup(&sem->sem_lock); wchan_destroy(sem->sem_wchan); - kfree(sem->sem_name); - kfree(sem); + kfree(sem->sem_name); + kfree(sem); } void P(struct semaphore *sem) { - KASSERT(sem != NULL); + KASSERT(sem != NULL); - /* - * May not block in an interrupt handler. - * - * For robustness, always check, even if we can actually - * complete the P without blocking. - */ - KASSERT(curthread->t_in_interrupt == false); + /* + * May not block in an interrupt handler. + * + * For robustness, always check, even if we can actually + * complete the P without blocking. + */ + KASSERT(curthread->t_in_interrupt == false); /* Use the semaphore spinlock to protect the wchan as well. */ spinlock_acquire(&sem->sem_lock); - while (sem->sem_count == 0) { + while (sem->sem_count == 0) { /* * * Note that we don't maintain strict FIFO ordering of @@ -114,21 +114,21 @@ P(struct semaphore *sem) * ordering? */ wchan_sleep(sem->sem_wchan, &sem->sem_lock); - } - KASSERT(sem->sem_count > 0); - sem->sem_count--; + } + KASSERT(sem->sem_count > 0); + sem->sem_count--; spinlock_release(&sem->sem_lock); } void V(struct semaphore *sem) { - KASSERT(sem != NULL); + KASSERT(sem != NULL); spinlock_acquire(&sem->sem_lock); - sem->sem_count++; - KASSERT(sem->sem_count > 0); + sem->sem_count++; + KASSERT(sem->sem_count > 0); wchan_wakeone(sem->sem_wchan, &sem->sem_lock); spinlock_release(&sem->sem_lock); @@ -141,59 +141,59 @@ V(struct semaphore *sem) struct lock * lock_create(const char *name) { - struct lock *lock; + struct lock *lock; - lock = kmalloc(sizeof(*lock)); - if (lock == NULL) { - return NULL; - } + lock = kmalloc(sizeof(*lock)); + if (lock == NULL) { + return NULL; + } - lock->lk_name = kstrdup(name); - if (lock->lk_name == NULL) { - kfree(lock); - return NULL; - } + lock->lk_name = kstrdup(name); + if (lock->lk_name == NULL) { + kfree(lock); + return NULL; + } - // add stuff here as needed + // add stuff here as needed - return lock; + return lock; } void lock_destroy(struct lock *lock) { - KASSERT(lock != NULL); + KASSERT(lock != NULL); - // add stuff here as needed + // add stuff here as needed - kfree(lock->lk_name); - kfree(lock); + kfree(lock->lk_name); + kfree(lock); } void lock_acquire(struct lock *lock) { - // Write this + // Write this - (void)lock; // suppress warning until code gets written + (void)lock; // suppress warning until code gets written } void lock_release(struct lock *lock) { - // Write this + // Write this - (void)lock; // suppress warning until code gets written + (void)lock; // suppress warning until code gets written } bool lock_do_i_hold(struct lock *lock) { - // Write this + // Write this - (void)lock; // suppress warning until code gets written + (void)lock; // suppress warning until code gets written - return true; // dummy until code gets written + return true; // dummy until code gets written } //////////////////////////////////////////////////////////// @@ -204,47 +204,47 @@ lock_do_i_hold(struct lock *lock) struct cv * cv_create(const char *name) { - struct cv *cv; + struct cv *cv; - cv = kmalloc(sizeof(*cv)); - if (cv == NULL) { - return NULL; - } + cv = kmalloc(sizeof(*cv)); + if (cv == NULL) { + return NULL; + } - cv->cv_name = kstrdup(name); - if (cv->cv_name==NULL) { - kfree(cv); - return NULL; - } + cv->cv_name = kstrdup(name); + if (cv->cv_name==NULL) { + kfree(cv); + return NULL; + } - // add stuff here as needed + // add stuff here as needed - return cv; + return cv; } void cv_destroy(struct cv *cv) { - KASSERT(cv != NULL); + KASSERT(cv != NULL); - // add stuff here as needed + // add stuff here as needed - kfree(cv->cv_name); - kfree(cv); + kfree(cv->cv_name); + kfree(cv); } void cv_wait(struct cv *cv, struct lock *lock) { - // Write this - (void)cv; // suppress warning until code gets written - (void)lock; // suppress warning until code gets written + // Write this + (void)cv; // suppress warning until code gets written + (void)lock; // suppress warning until code gets written } void cv_signal(struct cv *cv, struct lock *lock) { - // Write this + // Write this (void)cv; // suppress warning until code gets written (void)lock; // suppress warning until code gets written } diff --git a/kern/thread/thread.c b/kern/thread/thread.c index a41dc58..8ceeaf5 100644 --- a/kern/thread/thread.c +++ b/kern/thread/thread.c @@ -65,10 +65,16 @@ struct wchan { DECLARRAY(cpu, static __UNUSED inline); DEFARRAY(cpu, static __UNUSED inline); static struct cpuarray allcpus; +unsigned num_cpus; /* Used to wait for secondary CPUs to come online. */ static struct semaphore *cpu_startup_sem; +/* Used to synchronize exit cleanup. */ +unsigned thread_count = 0; +static struct spinlock thread_count_lock = SPINLOCK_INITIALIZER; +static struct wchan *thread_count_wchan; + //////////////////////////////////////////////////////////// /* @@ -119,17 +125,16 @@ thread_create(const char *name) struct thread *thread; DEBUGASSERT(name != NULL); + if (strlen(name) > MAX_NAME_LENGTH) { + return NULL; + } thread = kmalloc(sizeof(*thread)); if (thread == NULL) { return NULL; } - thread->t_name = kstrdup(name); - if (thread->t_name == NULL) { - kfree(thread); - return NULL; - } + strcpy(thread->t_name, name); thread->t_wchan_name = "NEW"; thread->t_state = S_READY; @@ -256,6 +261,9 @@ cpu_create(unsigned hardware_number) * Nor can it be called on a running thread. * * (Freeing the stack you're actually using to run is ... inadvisable.) + * + * Thread destroy should finish the process of cleaning up a thread started by + * thread_exit. */ static void @@ -264,11 +272,6 @@ thread_destroy(struct thread *thread) KASSERT(thread != curthread); KASSERT(thread->t_state != S_RUN); - /* - * If you add things to struct thread, be sure to clean them up - * either here or in thread_exit(). (And not both...) - */ - /* Thread subsystem fields */ KASSERT(thread->t_proc == NULL); if (thread->t_stack != NULL) { @@ -280,7 +283,6 @@ thread_destroy(struct thread *thread) /* sheer paranoia */ thread->t_wchan_name = "DESTROYED"; - kfree(thread->t_name); kfree(thread); } @@ -411,8 +413,6 @@ cpu_hatch(unsigned software_number) spl0(); cpu_identify(buf, sizeof(buf)); - kprintf("cpu%u: %s\n", software_number, buf); - V(cpu_startup_sem); thread_exit(); } @@ -430,13 +430,26 @@ thread_start_cpus(void) kprintf("cpu0: %s\n", buf); cpu_startup_sem = sem_create("cpu_hatch", 0); + thread_count_wchan = wchan_create("thread_count"); mainbus_start_cpus(); - for (i=0; it_state = S_READY; threadlist_addtail(&targetcpu->c_runqueue, target); - if (targetcpu->c_isidle && targetcpu != curcpu->c_self) { + if (targetcpu->c_isidle) { /* * Other processor is idle; send interrupt to make * sure it unidles. @@ -535,6 +548,11 @@ thread_fork(const char *name, */ newthread->t_iplhigh_count++; + spinlock_acquire(&thread_count_lock); + ++thread_count; + wchan_wakeall(thread_count_wchan, &thread_count_lock); + spinlock_release(&thread_count_lock); + /* Set up the switchframe so entrypoint() gets called */ switchframe_init(newthread, entrypoint, data1, data2); @@ -770,6 +788,13 @@ thread_startup(void (*entrypoint)(void *data1, unsigned long data2), * should be cleaned up right away. The rest has to wait until * thread_destroy is called from exorcise(). * + * Note that any dynamically-allocated structures that can vary in size from + * thread to thread should be cleaned up here, not in thread_destroy. This is + * because the last thread left on each core runs the idle loop and does not + * get cleaned up until new threads are created. Differences in the amount of + * memory used by different threads after thread_exit will make it look like + * your kernel in leaking memory and cause some of the test161 checks to fail. + * * Does not return. */ void @@ -791,8 +816,16 @@ thread_exit(void) /* Check the stack guard band. */ thread_checkstack(cur); + // Decrement the thread count and notify anyone interested. + if (thread_count) { + spinlock_acquire(&thread_count_lock); + --thread_count; + wchan_wakeall(thread_count_wchan, &thread_count_lock); + spinlock_release(&thread_count_lock); + } + /* Interrupts off on this processor */ - splhigh(); + splhigh(); thread_switch(S_ZOMBIE, NULL, NULL); panic("braaaaaaaiiiiiiiiiiinssssss\n"); } @@ -1106,9 +1139,6 @@ ipi_send(struct cpu *target, int code) spinlock_release(&target->c_ipi_lock); } -/* - * Send an IPI to all CPUs. - */ void ipi_broadcast(int code) { @@ -1123,28 +1153,16 @@ ipi_broadcast(int code) } } -/* - * Send a TLB shootdown IPI to the specified CPU. - */ void ipi_tlbshootdown(struct cpu *target, const struct tlbshootdown *mapping) { - unsigned n; + int n; spinlock_acquire(&target->c_ipi_lock); n = target->c_numshootdown; if (n == TLBSHOOTDOWN_MAX) { - /* - * If you have problems with this panic going off, - * consider: (1) increasing the maximum, (2) putting - * logic here to sleep until space appears (may - * interact awkwardly with VM system locking), (3) - * putting logic here to coalesce requests together, - * and/or (4) improving VM system state tracking to - * reduce the number of unnecessary shootdowns. - */ - panic("ipi_tlbshootdown: Too many shootdowns queued\n"); + target->c_numshootdown = TLBSHOOTDOWN_ALL; } else { target->c_shootdown[n] = *mapping; @@ -1157,14 +1175,11 @@ ipi_tlbshootdown(struct cpu *target, const struct tlbshootdown *mapping) spinlock_release(&target->c_ipi_lock); } -/* - * Handle an incoming interprocessor interrupt. - */ void interprocessor_interrupt(void) { uint32_t bits; - unsigned i; + int i; spinlock_acquire(&curcpu->c_ipi_lock); bits = curcpu->c_ipi_pending; @@ -1183,7 +1198,6 @@ interprocessor_interrupt(void) curcpu->c_number); } spinlock_release(&curcpu->c_runqueue_lock); - kprintf("cpu%d: offline.\n", curcpu->c_number); cpu_halt(); } if (bits & (1U << IPI_UNIDLE)) { @@ -1193,13 +1207,13 @@ interprocessor_interrupt(void) */ } if (bits & (1U << IPI_TLBSHOOTDOWN)) { - /* - * Note: depending on your VM system locking you might - * need to release the ipi lock while calling - * vm_tlbshootdown. - */ - for (i=0; ic_numshootdown; i++) { - vm_tlbshootdown(&curcpu->c_shootdown[i]); + if (curcpu->c_numshootdown == TLBSHOOTDOWN_ALL) { + vm_tlbshootdown_all(); + } + else { + for (i=0; ic_numshootdown; i++) { + vm_tlbshootdown(&curcpu->c_shootdown[i]); + } } curcpu->c_numshootdown = 0; } @@ -1207,3 +1221,15 @@ interprocessor_interrupt(void) curcpu->c_ipi_pending = 0; spinlock_release(&curcpu->c_ipi_lock); } + +/* + * Wait for the thread count to equal tc. + */ +void thread_wait_for_count(unsigned tc) +{ + spinlock_acquire(&thread_count_lock); + while (thread_count != tc) { + wchan_sleep(thread_count_wchan, &thread_count_lock); + } + spinlock_release(&thread_count_lock); +} diff --git a/kern/vfs/vfslist.c b/kern/vfs/vfslist.c index 9cd2f4a..184e622 100644 --- a/kern/vfs/vfslist.c +++ b/kern/vfs/vfslist.c @@ -82,9 +82,6 @@ struct knowndev { struct fs *kd_fs; }; -/* A placeholder for kd_fs for devices used as swap */ -#define SWAP_FS ((struct fs *)-1) - DECLARRAY(knowndev, static __UNUSED inline); DEFARRAY(knowndev, static __UNUSED inline); @@ -163,7 +160,7 @@ vfs_sync(void) num = knowndevarray_num(knowndevs); for (i=0; ikd_fs != NULL && dev->kd_fs != SWAP_FS) { + if (dev->kd_fs != NULL) { /*result =*/ FSOP_SYNC(dev->kd_fs); } } @@ -198,7 +195,7 @@ vfs_getroot(const char *devname, struct vnode **ret) * and DEVNAME names the device, return ENXIO. */ - if (kd->kd_fs != NULL && kd->kd_fs != SWAP_FS) { + if (kd->kd_fs!=NULL) { const char *volname; volname = FSOP_GETVOLNAME(kd->kd_fs); @@ -347,7 +344,7 @@ badnames(const char *n1, const char *n2, const char *n3) for (i=0; ikd_fs != NULL && kd->kd_fs != SWAP_FS) { + if (kd->kd_fs) { volname = FSOP_GETVOLNAME(kd->kd_fs); if (samestring3(volname, n1, n2, n3)) { return 1; @@ -545,7 +542,6 @@ vfs_mount(const char *devname, void *data, } KASSERT(fs != NULL); - KASSERT(fs != SWAP_FS); kd->kd_fs = fs; @@ -557,59 +553,6 @@ vfs_mount(const char *devname, void *data, return 0; } -/* - * Like mount, but for attaching swap. Hands back the raw device - * vnode. Unlike mount tolerates a trailing colon on the device name, - * to avoid student-facing confusion. - */ -int -vfs_swapon(const char *devname, struct vnode **ret) -{ - char *myname = NULL; - size_t len; - struct knowndev *kd; - int result; - - len = strlen(devname); - if (len > 0 && devname[len - 1] == ':') { - /* tolerate trailing :, e.g. lhd0: rather than lhd0 */ - myname = kstrdup(devname); - if (myname == NULL) { - return ENOMEM; - } - myname[len - 1] = 0; - devname = myname; - } - - vfs_biglock_acquire(); - - result = findmount(devname, &kd); - if (result) { - goto out; - } - - if (kd->kd_fs != NULL) { - result = EBUSY; - goto out; - } - KASSERT(kd->kd_rawname != NULL); - KASSERT(kd->kd_device != NULL); - - kprintf("vfs: Swap attached to %s\n", kd->kd_name); - - kd->kd_fs = SWAP_FS; - VOP_INCREF(kd->kd_vnode); - *ret = kd->kd_vnode; - - out: - vfs_biglock_release(); - if (myname != NULL) { - kfree(myname); - } - - return result; -} - /* * Unmount a filesystem/device by name. * First calls FSOP_SYNC on the filesystem; then calls FSOP_UNMOUNT. @@ -627,7 +570,7 @@ vfs_unmount(const char *devname) goto fail; } - if (kd->kd_fs == NULL || kd->kd_fs == SWAP_FS) { + if (kd->kd_fs == NULL) { result = EINVAL; goto fail; } @@ -657,43 +600,6 @@ vfs_unmount(const char *devname) return result; } -/* - * Detach swap. Like unmount. - * - * (Provided for completeness; there is no real need to remove swap - * explicitly prior to shutting down, except perhaps when swapping to - * things that themselves want a clean shutdown, like RAIDs.) - */ -int -vfs_swapoff(const char *devname) -{ - struct knowndev *kd; - int result; - - vfs_biglock_acquire(); - - result = findmount(devname, &kd); - if (result) { - goto fail; - } - - if (kd->kd_fs != SWAP_FS) { - result = EINVAL; - goto fail; - } - - kprintf("vfs: Swap detached from %s:\n", kd->kd_name); - - /* drop it */ - kd->kd_fs = NULL; - - KASSERT(result==0); - - fail: - vfs_biglock_release(); - return result; -} - /* * Global unmount function. */ @@ -717,11 +623,6 @@ vfs_unmountall(void) /* not mounted */ continue; } - if (dev->kd_fs == SWAP_FS) { - /* just drop it */ - dev->kd_fs = NULL; - continue; - } kprintf("vfs: Unmounting %s:\n", dev->kd_name); diff --git a/kern/vfs/vnode.c b/kern/vfs/vnode.c index 7322707..374c300 100644 --- a/kern/vfs/vnode.c +++ b/kern/vfs/vnode.c @@ -129,8 +129,7 @@ vnode_decref(struct vnode *vn) void vnode_check(struct vnode *v, const char *opstr) { - /* not safe, and not really needed to check constant fields */ - /*vfs_biglock_acquire();*/ + vfs_biglock_acquire(); if (v == NULL) { panic("vnode_check: vop_%s: null vnode\n", opstr); @@ -174,5 +173,5 @@ vnode_check(struct vnode *v, const char *opstr) } spinlock_release(&v->vn_countlock); - /*vfs_biglock_release();*/ + vfs_biglock_release(); } diff --git a/kern/vm/kmalloc.c b/kern/vm/kmalloc.c index 453b3cc..13684a7 100644 --- a/kern/vm/kmalloc.c +++ b/kern/vm/kmalloc.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include /* * Kernel malloc. @@ -743,8 +745,8 @@ kheap_dumpall(void) * Print the allocated/freed map of a single kernel heap page. */ static -void -subpage_stats(struct pageref *pr) +unsigned long +subpage_stats(struct pageref *pr, bool quiet) { vaddr_t prpage, fla; struct freelist *fl; @@ -780,18 +782,21 @@ subpage_stats(struct pageref *pr) } } - kprintf("at 0x%08lx: size %-4lu %u/%u free\n", - (unsigned long)prpage, (unsigned long) sizes[blktype], - (unsigned) pr->nfree, n); - kprintf(" "); - for (i=0; infree, n); + kprintf(" "); + for (i=0; infree)); } /* @@ -808,12 +813,55 @@ kheap_printstats(void) kprintf("Subpage allocator status:\n"); for (pr = allbase; pr != NULL; pr = pr->next_all) { - subpage_stats(pr); + subpage_stats(pr, false); } spinlock_release(&kmalloc_spinlock); } + +/* + * Return the number of used bytes. + */ + +unsigned long +kheap_getused(void) { + struct pageref *pr; + unsigned long total = 0; + unsigned int num_pages = 0, coremap_bytes = 0; + + /* compute with interrupts off */ + spinlock_acquire(&kmalloc_spinlock); + for (pr = allbase; pr != NULL; pr = pr->next_all) { + total += subpage_stats(pr, true); + num_pages++; + } + + coremap_bytes = coremap_used_bytes(); + + // Don't double-count the pages we're using for subpage allocation; + // we've already accounted for the used portion. + if (coremap_bytes > 0) { + total += coremap_bytes - (num_pages * PAGE_SIZE); + } + + spinlock_release(&kmalloc_spinlock); + + return total; +} + +/* + * Print number of used bytes. + */ + +void +kheap_printused(void) +{ + char total_string[32]; + snprintf(total_string, sizeof(total_string), "%lu", kheap_getused()); + secprintf(SECRET, total_string, "khu"); +} + //////////////////////////////////////// /* @@ -967,7 +1015,7 @@ subpage_kmalloc(size_t sz prpage = alloc_kpages(1); if (prpage==0) { /* Out of memory. */ - kprintf("kmalloc: Subpage allocator couldn't get a page\n"); + silent("kmalloc: Subpage allocator couldn't get a page\n"); return NULL; } KASSERT(prpage % PAGE_SIZE == 0); diff --git a/mk/os161.config.mk b/mk/os161.config.mk index ad246e7..b77fcc6 100644 --- a/mk/os161.config.mk +++ b/mk/os161.config.mk @@ -87,15 +87,6 @@ # These build variables can be set explicitly for further control if # desired, but should in general not need attention. # -# (Tools.) -# -# PYTHON_INTERPRETER Location of Python interpreter. -# Default is "/usr/bin/env python". -# -# This may need to be changed on some platforms; but the configure -# script is supposed to take care of it for you. If that fails, or -# picks the wrong thing, please file a bug report. -# # (Locations.) # # BUILDTOP Top of tree where .o files go. @@ -105,7 +96,7 @@ # the build. Default is $(WORKDIR)/tooldir. # # INSTALLTOP Staging directory for installation. -# Default is $(WORKDIR)/install. +# Default is $(WORKDIR)/install # # Probably the only reason to change these would be if you're short on # diskspace in $(WORKDIR). @@ -479,7 +470,7 @@ MORECFLAGS+=-I$(INSTALLTOP)/include LDFLAGS+=-nostdlib -L$(INSTALLTOP)/lib $(INSTALLTOP)/lib/crt0.o MORELIBS+=-lc LIBDEPS+=$(INSTALLTOP)/lib/crt0.o $(INSTALLTOP)/lib/libc.a - +LIBS+=-ltest161 ############################################################ # end. diff --git a/mk/os161.hostlib.mk b/mk/os161.hostlib.mk index 88517d9..d4ac6bc 100644 --- a/mk/os161.hostlib.mk +++ b/mk/os161.hostlib.mk @@ -56,7 +56,7 @@ all-local: $(MYBUILDDIR) .WAIT $(MYBUILDDIR)/$(_LIB_) install-staging-local: $(TOOLDIR)/hostlib .WAIT $(TOOLDIR)/hostlib/$(_LIB_) $(TOOLDIR)/hostlib/$(_LIB_): $(MYBUILDDIR)/$(_LIB_) rm -f $(.TARGET) - ln $(MYBUILDDIR)/$(_LIB_) $(.TARGET) || \ + ln $(MYBUILDDIR)/$(_LIB_) $(.TARGET) >/dev/null 2>&1 || \ cp $(MYBUILDDIR)/$(_LIB_) $(.TARGET) install-local: diff --git a/mk/os161.hostprog.mk b/mk/os161.hostprog.mk index 13e5984..1cb73e6 100644 --- a/mk/os161.hostprog.mk +++ b/mk/os161.hostprog.mk @@ -76,14 +76,14 @@ cleanhostprog: install-staging-local: $(_INSTALLDIR_) .WAIT $(_INSTALLDIR_)/$(_PROG_) $(_INSTALLDIR_)/$(_PROG_): $(MYBUILDDIR)/$(_PROG_) rm -f $(.TARGET) - ln $(MYBUILDDIR)/$(_PROG_) $(.TARGET) || \ + ln $(MYBUILDDIR)/$(_PROG_) $(.TARGET) >/dev/null 2>&1 || \ cp $(MYBUILDDIR)/$(_PROG_) $(.TARGET) .if defined(HOSTBINDIR) install-local: install-hostprog install-hostprog: $(OSTREE)$(HOSTBINDIR) $(MYBUILDDIR)/$(_PROG_) rm -f $(OSTREE)$(HOSTBINDIR)/$(_PROG_) - ln $(MYBUILDDIR)/$(_PROG_) $(OSTREE)$(HOSTBINDIR)/$(_PROG_) || \ + ln $(MYBUILDDIR)/$(_PROG_) $(OSTREE)$(HOSTBINDIR)/$(_PROG_) >/dev/null 2>&1 || \ cp $(MYBUILDDIR)/$(_PROG_) $(OSTREE)$(HOSTBINDIR)/$(_PROG_) .else install-local: diff --git a/mk/os161.kernel.mk b/mk/os161.kernel.mk index ebb8003..035fd9c 100644 --- a/mk/os161.kernel.mk +++ b/mk/os161.kernel.mk @@ -163,6 +163,9 @@ includelinks: clean: rm -f *.o *.a tags $(KERNEL) rm -rf includelinks + @ABSTOP=$$(readlink -f $(TOP)) + rm -f $(OSTREE)/.src + rm -f $(TOP)/.root distclean cleandir: clean rm -f .depend @@ -188,6 +191,9 @@ install: cp $(KERNEL) $(OSTREE)/$(KERNEL)-$(CONFNAME) -rm -f $(OSTREE)/$(KERNEL) ln -s $(KERNEL)-$(CONFNAME) $(OSTREE)/$(KERNEL) + @ABSTOP=$$(readlink -f $(TOP)) + ln -Tsf $(ABSTOP) $(OSTREE)/.src + ln -Tsf $(OSTREE) $(ABSTOP)/.root # # Run tags on all the sources and header files. This is probably not diff --git a/mk/os161.lib.mk b/mk/os161.lib.mk index 699ee71..f9f8e53 100644 --- a/mk/os161.lib.mk +++ b/mk/os161.lib.mk @@ -59,13 +59,13 @@ all-local: $(MYBUILDDIR) .WAIT $(MYBUILDDIR)/$(_LIB_) install-staging-local: $(INSTALLTOP)$(LIBDIR) .WAIT $(INSTALLTOP)$(LIBDIR)/$(_LIB_) $(INSTALLTOP)$(LIBDIR)/$(_LIB_): $(MYBUILDDIR)/$(_LIB_) rm -f $(.TARGET) - ln $(MYBUILDDIR)/$(_LIB_) $(.TARGET) || \ + ln $(MYBUILDDIR)/$(_LIB_) $(.TARGET) >/dev/null 2>&1 || \ cp $(MYBUILDDIR)/$(_LIB_) $(.TARGET) install-local: $(OSTREE)$(LIBDIR) $(MYBUILDDIR)/$(_LIB_) @echo "Warning: manually installing library without relinking anything" rm -f $(OSTREE)$(LIBDIR)/$(_LIB_) - ln $(MYBUILDDIR)/$(_LIB_) $(OSTREE)$(LIBDIR)/$(_LIB_) || \ + ln $(MYBUILDDIR)/$(_LIB_) $(OSTREE)$(LIBDIR)/$(_LIB_) >/dev/null 2>&1 || \ cp $(MYBUILDDIR)/$(_LIB_) $(OSTREE)$(LIBDIR)/$(_LIB_) # Build the library. diff --git a/mk/os161.man.mk b/mk/os161.man.mk index 0e3590a..4e07b00 100644 --- a/mk/os161.man.mk +++ b/mk/os161.man.mk @@ -44,24 +44,21 @@ install-staging-local: $(INSTALLTOP)$(MANDIR) .WAIT install-staging-local: $(INSTALLTOP)$(MANDIR)/$(_F_) $(INSTALLTOP)$(MANDIR)/$(_F_): $(_F_) rm -f $(.TARGET) - ln $(_F_) $(.TARGET) || cp $(_F_) $(.TARGET) + ln $(_F_) $(.TARGET) >/dev/null 2>&1 || cp $(_F_) $(.TARGET) .endfor install-local: $(OSTREE)$(MANDIR) .WAIT installmanpages installmanpages: .for _F_ in $(MANFILES) rm -f $(OSTREE)$(MANDIR)/$(_F_) - ln $(_F_) $(OSTREE)$(MANDIR)/$(_F_) || \ + ln $(_F_) $(OSTREE)$(MANDIR)/$(_F_) >/dev/null 2>&1 || \ cp $(_F_) $(OSTREE)$(MANDIR)/$(_F_) .endfor -# clean: remove build products (nothing to do) -clean-local: ; # Mark targets that don't represent files PHONY, to prevent various # lossage if files by those names appear. .PHONY: all all-local install-staging-local install-local installmanpages -.PHONY: clean-local # Finally, get the shared definitions for the most basic rules. .include "$(TOP)/mk/os161.baserules.mk" diff --git a/mk/os161.prog.mk b/mk/os161.prog.mk index 96876c5..a087626 100644 --- a/mk/os161.prog.mk +++ b/mk/os161.prog.mk @@ -61,13 +61,13 @@ cleanprog: install-staging-local: $(INSTALLTOP)$(BINDIR) .WAIT $(INSTALLTOP)$(BINDIR)/$(PROG) $(INSTALLTOP)$(BINDIR)/$(PROG): $(MYBUILDDIR)/$(PROG) rm -f $(.TARGET) - ln $(MYBUILDDIR)/$(PROG) $(.TARGET) || \ + ln $(MYBUILDDIR)/$(PROG) $(.TARGET) >/dev/null 2>&1 || \ cp $(MYBUILDDIR)/$(PROG) $(.TARGET) install-local: install-prog install-prog: $(OSTREE)$(BINDIR) $(MYBUILDDIR)/$(PROG) rm -f $(OSTREE)$(BINDIR)/$(PROG) - ln $(MYBUILDDIR)/$(PROG) $(OSTREE)$(BINDIR)/$(PROG) || \ + ln $(MYBUILDDIR)/$(PROG) $(OSTREE)$(BINDIR)/$(PROG) >/dev/null 2>&1 || \ cp $(MYBUILDDIR)/$(PROG) $(OSTREE)$(BINDIR)/$(PROG) # Link the program. diff --git a/userland/Makefile b/userland/Makefile index 0ad87da..4ec29c1 100644 --- a/userland/Makefile +++ b/userland/Makefile @@ -12,6 +12,7 @@ INCLUDES=\ include include \ include/sys include/sys \ include/test include/test \ + include/test161 include/test161 \ include/types include/types INCLUDELINKS=\ diff --git a/userland/include/stdio.h b/userland/include/stdio.h index 20e96cb..e8518ea 100644 --- a/userland/include/stdio.h +++ b/userland/include/stdio.h @@ -56,6 +56,11 @@ int vprintf(const char *fmt, __va_list ap); int snprintf(char *buf, size_t len, const char *fmt, ...); int vsnprintf(char *buf, size_t len, const char *fmt, __va_list ap); +/* Automated testing extensions. */ + +int tprintf(const char *fmt, ...); +int nprintf(const char *fmt, ...); + /* Print the argument string and then a newline. Returns 0 or -1 on error. */ int puts(const char *); diff --git a/userland/lib/Makefile b/userland/lib/Makefile index 842056c..54fbe24 100644 --- a/userland/lib/Makefile +++ b/userland/lib/Makefile @@ -8,6 +8,6 @@ TOP=../.. .include "$(TOP)/mk/os161.config.mk" -SUBDIRS=crt0 libc libtest hostcompat +SUBDIRS=crt0 libc libtest libtest161 hostcompat .include "$(TOP)/mk/os161.subdir.mk" diff --git a/userland/lib/hostcompat/Makefile b/userland/lib/hostcompat/Makefile index 4cd6ab0..22a7664 100644 --- a/userland/lib/hostcompat/Makefile +++ b/userland/lib/hostcompat/Makefile @@ -22,6 +22,11 @@ TOP=../../.. LIB=hostcompat SRCS=err.c ntohll.c time.c hostcompat.c +# printf +COMMON=$(TOP)/common/libc +SRCS+=\ + $(COMMON)/printf/tprintf.c + HOST_CFLAGS+=$(COMPAT_CFLAGS) MKDIRS=$(INSTALLTOP)/hostinclude diff --git a/userland/lib/hostcompat/hostcompat.h b/userland/lib/hostcompat/hostcompat.h index 7191964..8e37e7b 100644 --- a/userland/lib/hostcompat/hostcompat.h +++ b/userland/lib/hostcompat/hostcompat.h @@ -35,6 +35,11 @@ void hostcompat_init(int argc, char **argv); time_t __time(time_t *secs, unsigned long *nsecs); +/* Automated testing extensions. */ + +int tprintf(const char *fmt, ...); +int nprintf(const char *fmt, ...); + #ifdef DECLARE_NTOHLL uint64_t ntohll(uint64_t); #define htonll(x) (ntohll(x)) diff --git a/userland/lib/libc/Makefile b/userland/lib/libc/Makefile index 1d25230..9955311 100644 --- a/userland/lib/libc/Makefile +++ b/userland/lib/libc/Makefile @@ -10,7 +10,8 @@ COMMON=$(TOP)/common/libc # printf SRCS+=\ $(COMMON)/printf/__printf.c \ - $(COMMON)/printf/snprintf.c + $(COMMON)/printf/snprintf.c \ + $(COMMON)/printf/tprintf.c # stdio SRCS+=\ diff --git a/userland/lib/libc/stdio/printf.c b/userland/lib/libc/stdio/printf.c index f0d627b..21e5304 100644 --- a/userland/lib/libc/stdio/printf.c +++ b/userland/lib/libc/stdio/printf.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include /* * printf - C standard I/O function. diff --git a/userland/lib/libc/unix/err.c b/userland/lib/libc/unix/err.c index a4992d1..214f89d 100644 --- a/userland/lib/libc/unix/err.c +++ b/userland/lib/libc/unix/err.c @@ -139,6 +139,7 @@ verr(int exitcode, const char *fmt, va_list ap) { __printerr(1, fmt, ap); exit(exitcode); + // exit() didn't work. } /* errx/verrx: don't use errno, but do then exit */ @@ -147,6 +148,7 @@ verrx(int exitcode, const char *fmt, va_list ap) { __printerr(0, fmt, ap); exit(exitcode); + // exit() didn't work. } /* diff --git a/userland/testbin/Makefile b/userland/testbin/Makefile index e5cf502..cc522ca 100644 --- a/userland/testbin/Makefile +++ b/userland/testbin/Makefile @@ -7,11 +7,12 @@ TOP=../.. SUBDIRS=add argtest badcall bigexec bigfile bigfork bigseek bloat conman \ crash ctest dirconc dirseek dirtest f_test factorial farm faulter \ - filetest forkbomb forktest frack guzzle hash hog huge kitchen \ + filetest fileonlytest forkbomb forktest frack guzzle hash hog huge kitchen \ malloctest matmult multiexec palin parallelvm poisondisk psort \ quinthuge quintmat quintsort randcall redirect rmdirtest rmtest \ - sbrktest schedpong sink sort sparsefile sty tail tictac triplehuge \ - triplemat triplesort usemtest zero + sbrktest schedpong shll sink sort sparsefile spinner sty tail tictac \ + triplehuge triplemat triplesort usemtest waiter zero \ + consoletest shelltest opentest readwritetest closetest stacktest # But not: # userthreads (no support in kernel API in base system) diff --git a/userland/testbin/add/add.c b/userland/testbin/add/add.c index 856e4ec..edd680c 100644 --- a/userland/testbin/add/add.c +++ b/userland/testbin/add/add.c @@ -38,6 +38,7 @@ #include #include #include +#include int main(int argc, char *argv[]) @@ -51,7 +52,9 @@ main(int argc, char *argv[]) i = atoi(argv[1]); j = atoi(argv[2]); - printf("Answer: %d\n", i+j); - + tprintf("Answer: %d\n", i+j); + char buf[16]; + snprintf(buf, 16, "%d", i+j); + secprintf(SECRET, buf, "/testbin/add"); return 0; } diff --git a/userland/testbin/argtest/argtest.c b/userland/testbin/argtest/argtest.c index 7ed552e..b805c59 100644 --- a/userland/testbin/argtest/argtest.c +++ b/userland/testbin/argtest/argtest.c @@ -36,6 +36,7 @@ */ #include +#include int main(int argc, char *argv[]) @@ -43,14 +44,18 @@ main(int argc, char *argv[]) const char *tmp; int i; - printf("argc: %d\n", argc); + tprintf("argc: %d\n", argc); + char buf[16]; + snprintf(buf, 16, "argc: %d", argc); + secprintf(SECRET, buf, "/testbin/argtest"); for (i=0; i<=argc; i++) { tmp = argv[i]; if (tmp==NULL) { tmp = "[NULL]"; } - printf("argv[%d]: %s\n", i, tmp); + tprintf("argv[%d]: %s\n", i, tmp); + secprintf(SECRET, tmp, "/testbin/argtest"); } return 0; diff --git a/userland/testbin/badcall/bad_chdir.c b/userland/testbin/badcall/bad_chdir.c index cf98845..ec057c2 100644 --- a/userland/testbin/badcall/bad_chdir.c +++ b/userland/testbin/badcall/bad_chdir.c @@ -38,7 +38,7 @@ #include "test.h" static -void +int chdir_empty(void) { int rv; @@ -49,13 +49,20 @@ chdir_empty(void) report_begin("chdir to empty string"); rv = chdir(""); - report_check2(rv, errno, EINVAL, 0); + return report_check2(rv, errno, EINVAL, 0); } void test_chdir(void) { - test_chdir_path(); - chdir_empty(); + int ntests = 0, result = 0, lost_points = 0; + test_chdir_path(&ntests, &lost_points); + + ntests++; + result = chdir_empty(); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_close.c b/userland/testbin/badcall/bad_close.c index 6d70e66..3900200 100644 --- a/userland/testbin/badcall/bad_close.c +++ b/userland/testbin/badcall/bad_close.c @@ -36,5 +36,9 @@ void test_close(void) { - test_close_fd(); + int ntests = 0, lost_points = 0; + test_close_fd(&ntests, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_dup2.c b/userland/testbin/badcall/bad_dup2.c index db3a216..86a36c7 100644 --- a/userland/testbin/badcall/bad_dup2.c +++ b/userland/testbin/badcall/bad_dup2.c @@ -45,27 +45,29 @@ #include "test.h" static -void +int dup2_fd2(int fd, const char *desc) { - int rv; + int rv, failure; report_begin("%s", desc); rv = dup2(STDIN_FILENO, fd); - report_check(rv, errno, EBADF); + failure = report_check(rv, errno, EBADF); if (rv != -1) { close(fd); /* just in case */ } + return failure; } static -void +int dup2_self(void) { struct stat sb; int rv; int testfd; + int failure; /* use fd that isn't in use */ testfd = CLOSED_FD; @@ -75,22 +77,23 @@ dup2_self(void) rv = dup2(STDIN_FILENO, testfd); if (rv == -1) { report_result(rv, errno); - report_aborted(); - return; + report_aborted(&failure); + return failure; } report_begin("dup2 to same fd"); rv = dup2(testfd, testfd); if (rv == testfd) { - report_passed(); + report_passed(&failure); } else if (rv<0) { report_result(rv, errno); - report_failure(); + report_failure(&failure); } else { report_warnx("returned %d instead", rv); - report_failure(); + report_failure(&failure); + failure = FAILED; } report_begin("fstat fd after dup2 to itself"); @@ -100,43 +103,60 @@ dup2_self(void) } report_result(rv, errno); if (rv==0) { - report_passed(); + report_passed(&failure); } else if (errno != ENOSYS) { - report_failure(); + report_failure(&failure); } else { - report_skipped(); + report_skipped(&failure); /* no support for fstat; try lseek */ report_begin("lseek fd after dup2 to itself"); rv = lseek(testfd, 0, SEEK_CUR); report_result(rv, errno); if (rv==0 || (rv==-1 && errno==ESPIPE)) { - report_passed(); + report_passed(&failure); } else { - report_failure(); + report_failure(&failure); } } close(testfd); + return failure; } void test_dup2(void) { + int ntests = 0, failure, lost_points = 0; /* This does the first fd. */ - test_dup2_fd(); + test_dup2_fd(&ntests, &lost_points); /* Any interesting cases added here should also go in common_fds.c */ - dup2_fd2(-1, "dup2 to -1"); - dup2_fd2(-5, "dup2 to -5"); - dup2_fd2(IMPOSSIBLE_FD, "dup2 to impossible fd"); + ntests++; + failure = dup2_fd2(-1, "dup2 to -1"); + handle_result(failure, &lost_points); + + ntests++; + failure = dup2_fd2(-5, "dup2 to -5"); + handle_result(failure, &lost_points); + + ntests++; + failure = dup2_fd2(IMPOSSIBLE_FD, "dup2 to impossible fd"); + handle_result(failure, &lost_points); #ifdef OPEN_MAX - dup2_fd2(OPEN_MAX, "dup2 to OPEN_MAX"); + ntests++; + failure = dup2_fd2(OPEN_MAX, "dup2 to OPEN_MAX"); + handle_result(failure, &lost_points); #else warnx("Warning: OPEN_MAX not defined - test skipped"); #endif - dup2_self(); + ntests++; + failure = dup2_self(); + handle_result(failure, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_execv.c b/userland/testbin/badcall/bad_execv.c index 24ad1cb..0880e72 100644 --- a/userland/testbin/badcall/bad_execv.c +++ b/userland/testbin/badcall/bad_execv.c @@ -32,6 +32,7 @@ */ #include +#include #include #include #include @@ -42,7 +43,7 @@ static int -exec_common_fork(void) +exec_common_fork(int *result) { int pid, rv, status, err; @@ -56,7 +57,7 @@ exec_common_fork(void) err = errno; report_begin("forking for test"); report_result(pid, err); - report_aborted(); + report_aborted(result); return -1; } @@ -70,10 +71,11 @@ exec_common_fork(void) err = errno; report_begin("waiting for test subprocess"); report_result(rv, err); - report_failure(); + report_failure(result); return -1; } if (WIFEXITED(status) && WEXITSTATUS(status) == MAGIC_STATUS) { + *result = SUCCESS; return 1; } /* Oops... */ @@ -84,98 +86,134 @@ exec_common_fork(void) else { report_warnx("exit %d", WEXITSTATUS(status)); } - report_failure(); + report_failure(result); return -1; } static -void +int exec_badprog(const void *prog, const char *desc) { int rv; + int result; char *args[2]; args[0] = (char *)"foo"; args[1] = NULL; - if (exec_common_fork() != 0) { - return; + if (exec_common_fork(&result) != 0) { + return result; } report_begin(desc); rv = execv(prog, args); - report_check(rv, errno, EFAULT); - exit(MAGIC_STATUS); + result = report_check(rv, errno, EFAULT); + int code = result ? result : MAGIC_STATUS; + exit(code); } static -void +int exec_emptyprog(void) { int rv; + int result; char *args[2]; args[0] = (char *)"foo"; args[1] = NULL; - if (exec_common_fork() != 0) { - return; + if (exec_common_fork(&result) != 0) { + return result; } report_begin("exec the empty string"); rv = execv("", args); - report_check2(rv, errno, EINVAL, EISDIR); - exit(MAGIC_STATUS); + result = report_check2(rv, errno, EINVAL, EISDIR); + int code = result ? result : MAGIC_STATUS; + exit(code); } static -void +int exec_badargs(void *args, const char *desc) { int rv; - - if (exec_common_fork() != 0) { - return; + int result; + if (exec_common_fork(&result) != 0) { + return result; } report_begin(desc); rv = execv("/bin/true", args); - report_check(rv, errno, EFAULT); - exit(MAGIC_STATUS); + result = report_check(rv, errno, EFAULT); + int code = result ? result : MAGIC_STATUS; + exit(code); } static -void +int exec_onearg(void *ptr, const char *desc) { int rv; + int result; char *args[3]; args[0] = (char *)"foo"; args[1] = (char *)ptr; args[2] = NULL; - if (exec_common_fork() != 0) { - return; + if (exec_common_fork(&result) != 0) { + return result; } report_begin(desc); rv = execv("/bin/true", args); - report_check(rv, errno, EFAULT); - exit(MAGIC_STATUS); + result = report_check(rv, errno, EFAULT); + int code = result ? result : MAGIC_STATUS; + exit(code); + } void test_execv(void) { - exec_badprog(NULL, "exec with NULL program"); - exec_badprog(INVAL_PTR, "exec with invalid pointer program"); - exec_badprog(KERN_PTR, "exec with kernel pointer program"); + int ntests = 0, result = 0, lost_points = 0; + ntests++; + result = exec_badprog(NULL, "exec with NULL program"); + handle_result(result, &lost_points); - exec_emptyprog(); + ntests++; + result = exec_badprog(INVAL_PTR, "exec with invalid pointer program"); + handle_result(result, &lost_points); - exec_badargs(NULL, "exec with NULL arglist"); - exec_badargs(INVAL_PTR, "exec with invalid pointer arglist"); - exec_badargs(KERN_PTR, "exec with kernel pointer arglist"); + ntests++; + result = exec_badprog(KERN_PTR, "exec with kernel pointer program"); + handle_result(result, &lost_points); - exec_onearg(INVAL_PTR, "exec with invalid pointer arg"); - exec_onearg(KERN_PTR, "exec with kernel pointer arg"); + ntests++; + result = exec_emptyprog(); + handle_result(result, &lost_points); + + ntests++; + result = exec_badargs(NULL, "exec with NULL arglist"); + handle_result(result, &lost_points); + + ntests++; + result = exec_badargs(INVAL_PTR, "exec with invalid pointer arglist"); + handle_result(result, &lost_points); + + ntests++; + result = exec_badargs(KERN_PTR, "exec with kernel pointer arglist"); + handle_result(result, &lost_points); + + + ntests++; + result = exec_onearg(INVAL_PTR, "exec with invalid pointer arg"); + handle_result(result, &lost_points); + + ntests++; + result = exec_onearg(KERN_PTR, "exec with kernel pointer arg"); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_fsync.c b/userland/testbin/badcall/bad_fsync.c index fd67384..6322a99 100644 --- a/userland/testbin/badcall/bad_fsync.c +++ b/userland/testbin/badcall/bad_fsync.c @@ -36,6 +36,11 @@ void test_fsync(void) { - test_fsync_fd(); + int ntests = 0, lost_points = 0; + + test_fsync_fd(&ntests, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_ftruncate.c b/userland/testbin/badcall/bad_ftruncate.c index f88d7c8..cf21fff 100644 --- a/userland/testbin/badcall/bad_ftruncate.c +++ b/userland/testbin/badcall/bad_ftruncate.c @@ -44,52 +44,67 @@ #include "test.h" static -void +int ftruncate_fd_device(void) { int rv, fd; + int result; report_begin("ftruncate on device"); fd = open("null:", O_RDWR); if (fd<0) { report_warn("opening null: failed"); - report_aborted(); - return; + report_aborted(&result); + return result; } rv = ftruncate(fd, 6); - report_check(rv, errno, EINVAL); + result = report_check(rv, errno, EINVAL); close(fd); + return result; } static -void +int ftruncate_size_neg(void) { int rv, fd; + int result; report_begin("ftruncate to negative size"); fd = open_testfile(NULL); if (fd<0) { - report_aborted(); - return; + report_aborted(&result); + return result; } rv = ftruncate(fd, -60); - report_check(rv, errno, EINVAL); + result = report_check(rv, errno, EINVAL); close(fd); remove(TESTFILE); + return result; } void test_ftruncate(void) { - test_ftruncate_fd(); + int ntests = 0, lost_points = 0; + int result; - ftruncate_fd_device(); - ftruncate_size_neg(); + test_ftruncate_fd(&ntests, &lost_points); + + ntests++; + result = ftruncate_fd_device(); + handle_result(result, &lost_points); + + ntests++; + result = ftruncate_size_neg(); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_getcwd.c b/userland/testbin/badcall/bad_getcwd.c index 4f94ba1..4dacfa1 100644 --- a/userland/testbin/badcall/bad_getcwd.c +++ b/userland/testbin/badcall/bad_getcwd.c @@ -36,5 +36,9 @@ void test_getcwd(void) { - test_getcwd_buf(); + int ntests = 0, lost_points = 0; + test_getcwd_buf(&ntests, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_getdirentry.c b/userland/testbin/badcall/bad_getdirentry.c index 02806d2..5d8f425 100644 --- a/userland/testbin/badcall/bad_getdirentry.c +++ b/userland/testbin/badcall/bad_getdirentry.c @@ -36,6 +36,11 @@ void test_getdirentry(void) { - test_getdirentry_fd(); - test_getdirentry_buf(); + int ntests = 0, lost_points = 0; + + test_getdirentry_fd(&ntests, &lost_points); + test_getdirentry_buf(&ntests, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_ioctl.c b/userland/testbin/badcall/bad_ioctl.c index 8ce38bc..f61add5 100644 --- a/userland/testbin/badcall/bad_ioctl.c +++ b/userland/testbin/badcall/bad_ioctl.c @@ -41,30 +41,34 @@ #include "test.h" static -void +int one_ioctl_badbuf(int fd, int code, const char *codename, void *ptr, const char *ptrdesc) { int rv; + int result; report_begin("ioctl %s with %s", codename, ptrdesc); rv = ioctl(fd, code, ptr); - report_check(rv, errno, EFAULT); + result = report_check(rv, errno, EFAULT); + return result; } static -void +int any_ioctl_badbuf(int fd, int code, const char *codename) { - one_ioctl_badbuf(fd, code, codename, NULL, "NULL pointer"); - one_ioctl_badbuf(fd, code, codename, INVAL_PTR, "invalid pointer"); - one_ioctl_badbuf(fd, code, codename, KERN_PTR, "kernel pointer"); + int result; + result = one_ioctl_badbuf(fd, code, codename, NULL, "NULL pointer"); + result |= one_ioctl_badbuf(fd, code, codename, INVAL_PTR, "invalid pointer"); + result |= one_ioctl_badbuf(fd, code, codename, KERN_PTR, "kernel pointer"); + return result; } #define IOCTL(fd, sym) any_ioctl_badbuf(fd, sym, #sym) static -void +int ioctl_badbuf(void) { /* @@ -79,25 +83,39 @@ ioctl_badbuf(void) /* suppress gcc warning */ (void)any_ioctl_badbuf; + return 0; } static -void +int ioctl_badcode(void) { int rv; + int result; report_begin("invalid ioctl"); rv = ioctl(STDIN_FILENO, NONEXIST_IOCTL, NULL); - report_check(rv, errno, EIOCTL); + result = report_check(rv, errno, EIOCTL); + return result; } void test_ioctl(void) { - test_ioctl_fd(); + int ntests = 0, lost_points = 0; + int result; + + test_ioctl_fd(&ntests, &lost_points); /* Since we don't actually define any ioctls, this is not meaningful */ - ioctl_badcode(); - ioctl_badbuf(); + ntests++; + result = ioctl_badcode(); + handle_result(result, &lost_points); + + ntests++; + result = ioctl_badbuf(); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_link.c b/userland/testbin/badcall/bad_link.c index 63ecc15..82e0314 100644 --- a/userland/testbin/badcall/bad_link.c +++ b/userland/testbin/badcall/bad_link.c @@ -37,52 +37,70 @@ #include "test.h" static -void +int link_dir(void) { int rv; + int result; report_begin("hard link of ."); rv = link(".", TESTDIR); - report_check(rv, errno, EINVAL); + result = report_check(rv, errno, EINVAL); if (rv==0) { /* this might help recover... maybe */ remove(TESTDIR); } + return result; } static -void +int link_empty1(void) { int rv; report_begin("hard link of empty string"); rv = link("", TESTDIR); - report_check(rv, errno, EINVAL); + return report_check(rv, errno, EINVAL); } static -void +int link_empty2(void) { int rv; - + int result = FAILED; report_begin("hard link to empty string"); if (create_testdir()<0) { /*report_aborted();*/ /* XXX in create_testdir */ - return; + return result; } rv = link(TESTDIR, ""); - report_check(rv, errno, EINVAL); + result = report_check(rv, errno, EINVAL); rmdir(TESTDIR); + return result; } void test_link(void) { - test_link_paths(); - link_dir(); - link_empty1(); - link_empty2(); + int ntests = 0, lost_points = 0; + int result; + + test_link_paths(&ntests, &lost_points); + + ntests++; + result = link_dir(); + handle_result(result, &lost_points); + + ntests++; + result = link_empty1(); + handle_result(result, &lost_points); + + ntests++; + result = link_empty2(); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_lseek.c b/userland/testbin/badcall/bad_lseek.c index a521754..b2b968c 100644 --- a/userland/testbin/badcall/bad_lseek.c +++ b/userland/testbin/badcall/bad_lseek.c @@ -44,34 +44,38 @@ #include "test.h" static -void +int lseek_fd_device(void) { int fd, rv; + int result; report_begin("lseek on device"); fd = open("null:", O_RDONLY); if (fd<0) { report_warn("opening null: failed"); - report_aborted(); - return; + report_aborted(&result); + return result; } rv = lseek(fd, 309, SEEK_SET); - report_check(rv, errno, ESPIPE); + result = report_check(rv, errno, ESPIPE); close(fd); + + return result; } static -void +int lseek_file_stdin(void) { int fd, fd2, rv, status; const char slogan[] = "There ain't no such thing as a free lunch"; size_t len = strlen(slogan); pid_t pid; + int result = 0; report_begin("lseek stdin when open on file"); @@ -79,27 +83,27 @@ lseek_file_stdin(void) pid = fork(); if (pid<0) { report_warn("fork failed"); - report_aborted(); - return; + report_aborted(&result); + return result; } else if (pid!=0) { /* parent */ rv = waitpid(pid, &status, 0); if (rv<0) { report_warn("waitpid failed"); - report_aborted(); + report_aborted(&result); } if (WIFSIGNALED(status)) { report_warnx("subprocess exited with signal %d", WTERMSIG(status)); - report_aborted(); + report_aborted(&result); } else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { report_warnx("subprocess exited with code %d", WEXITSTATUS(status)); - report_aborted(); + report_aborted(&result); } - return; + return result; } /* child */ @@ -146,133 +150,159 @@ lseek_file_stdin(void) } /* blah */ - report_skipped(); + report_skipped(&result); rv = lseek(STDIN_FILENO, 0, SEEK_SET); report_begin("try 1: SEEK_SET"); - report_check(rv, errno, 0); + result = report_check(rv, errno, 0); rv = lseek(STDIN_FILENO, 0, SEEK_END); report_begin("try 2: SEEK_END"); - report_check(rv, errno, 0); + result = report_check(rv, errno, 0); remove(TESTFILE); _exit(0); } static -void +int lseek_loc_negative(void) { int fd, rv; + int result; report_begin("lseek to negative offset"); fd = open_testfile(NULL); if (fd<0) { - report_aborted(); - return; + report_aborted(&result); + return result; } rv = lseek(fd, -309, SEEK_SET); - report_check(rv, errno, EINVAL); + result = report_check(rv, errno, EINVAL); close(fd); remove(TESTFILE); + + return result; } static -void +int lseek_whence_inval(void) { int fd, rv; + int result; report_begin("lseek with invalid whence code"); fd = open_testfile(NULL); if (fd<0) { - report_aborted(); - return; + report_aborted(&result); + return result; } rv = lseek(fd, 0, 3594); - report_check(rv, errno, EINVAL); + result = report_check(rv, errno, EINVAL); close(fd); remove(TESTFILE); + return result; } static -void +int lseek_loc_pasteof(void) { const char *message = "blahblah"; int fd; off_t pos; + int result; report_begin("seek past/to EOF"); fd = open_testfile(message); if (fd<0) { - report_aborted(); - return; + report_aborted(&result); + return result; } pos = lseek(fd, 5340, SEEK_SET); if (pos == -1) { report_warn("lseek past EOF failed"); - report_failure(); + report_failure(&result); goto out; } if (pos != 5340) { report_warnx("lseek to 5340 got offset %lld", (long long) pos); - report_failure(); + report_failure(&result); goto out; } pos = lseek(fd, -50, SEEK_CUR); if (pos == -1) { report_warn("small seek beyond EOF failed"); - report_failure(); + report_failure(&result); goto out; } if (pos != 5290) { report_warnx("SEEK_CUR to 5290 got offset %lld", (long long) pos); - report_failure(); + report_failure(&result); goto out; } pos = lseek(fd, 0, SEEK_END); if (pos == -1) { report_warn("seek to EOF failed"); - report_failure(); + report_failure(&result); goto out; } if (pos != (off_t) strlen(message)) { report_warnx("seek to EOF got %lld (should be %zu)", (long long) pos, strlen(message)); - report_failure(); + report_failure(&result); goto out; } - report_passed(); + report_passed(&result); out: close(fd); remove(TESTFILE); - return; + return result; } void test_lseek(void) { - test_lseek_fd(); + int ntests = 0, lost_points = 0; + int result; - lseek_fd_device(); - lseek_file_stdin(); - lseek_loc_negative(); - lseek_loc_pasteof(); - lseek_whence_inval(); + test_lseek_fd(&ntests, &lost_points); + + ntests++; + result = lseek_fd_device(); + handle_result(result, &lost_points); + + ntests++; + result = lseek_file_stdin(); + handle_result(result, &lost_points); + + ntests++; + result = lseek_loc_negative(); + handle_result(result, &lost_points); + + ntests++; + result = lseek_loc_pasteof(); + handle_result(result, &lost_points); + + ntests++; + result = lseek_whence_inval(); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_mkdir.c b/userland/testbin/badcall/bad_mkdir.c index 4500dbd..5b79042 100644 --- a/userland/testbin/badcall/bad_mkdir.c +++ b/userland/testbin/badcall/bad_mkdir.c @@ -44,44 +44,58 @@ #include "test.h" static -void +int mkdir_dot(void) { int rv; report_begin("mkdir ."); rv = mkdir(".", 0775); - report_check(rv, errno, EEXIST); + return report_check(rv, errno, EEXIST); } static -void +int mkdir_dotdot(void) { int rv; report_begin("mkdir .."); rv = mkdir("..", 0775); - report_check(rv, errno, EEXIST); + return report_check(rv, errno, EEXIST); } static -void +int mkdir_empty(void) { int rv; report_begin("mkdir of empty string"); rv = mkdir("", 0775); - report_check(rv, errno, EINVAL); + return report_check(rv, errno, EINVAL); } void test_mkdir(void) { - test_mkdir_path(); + int ntests = 0, lost_points = 0; + int result; - mkdir_dot(); + test_mkdir_path(&ntests, &lost_points); + + ntests++; + result = mkdir_dot(); + handle_result(result, &lost_points); + + ntests++; mkdir_dotdot(); + handle_result(result, &lost_points); + + ntests++; mkdir_empty(); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_open.c b/userland/testbin/badcall/bad_open.c index 5ce66cd..be3d508 100644 --- a/userland/testbin/badcall/bad_open.c +++ b/userland/testbin/badcall/bad_open.c @@ -44,35 +44,48 @@ #include "test.h" static -void +int open_badflags(void) { int fd; report_begin("open null: with bad flags"); fd = open("null:", 309842); - report_check(fd, errno, EINVAL); + return report_check(fd, errno, EINVAL); } static -void +int open_empty(void) { int rv; + int result; report_begin("open empty string"); rv = open("", O_RDONLY); - report_check2(rv, errno, 0, EINVAL); + result = report_check2(rv, errno, 0, EINVAL); if (rv>=0) { close(rv); } + return result; } void test_open(void) { - test_open_path(); + int ntests = 0, lost_points = 0; + int result; - open_badflags(); - open_empty(); + test_open_path(&ntests, &lost_points); + + ntests++; + result = open_badflags(); + handle_result(result, &lost_points); + + ntests++; + result = open_empty(); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_pipe.c b/userland/testbin/badcall/bad_pipe.c index 350c3d8..27f3f68 100644 --- a/userland/testbin/badcall/bad_pipe.c +++ b/userland/testbin/badcall/bad_pipe.c @@ -44,22 +44,23 @@ #include "test.h" static -void +int pipe_badptr(void *ptr, const char *desc) { int rv; report_begin("%s", desc); rv = pipe(ptr); - report_check(rv, errno, EFAULT); + return report_check(rv, errno, EFAULT); } static -void +int pipe_unaligned(void) { int fds[3], rv; char *ptr; + int result; report_begin("pipe with unaligned pointer"); @@ -67,15 +68,32 @@ pipe_unaligned(void) ptr++; rv = pipe((int *)ptr); - report_survival(rv, errno); + report_survival(rv, errno, &result); + return result; } void test_pipe(void) { - pipe_badptr(NULL, "pipe with NULL pointer"); - pipe_badptr(INVAL_PTR, "pipe with invalid pointer"); - pipe_badptr(KERN_PTR, "pipe with kernel pointer"); + int ntests = 0, lost_points = 0; + int result; - pipe_unaligned(); + ntests++; + result = pipe_badptr(NULL, "pipe with NULL pointer"); + handle_result(result, &lost_points); + + ntests++; + result = pipe_badptr(INVAL_PTR, "pipe with invalid pointer"); + handle_result(result, &lost_points); + + ntests++; + result = pipe_badptr(KERN_PTR, "pipe with kernel pointer"); + handle_result(result, &lost_points); + + ntests++; + result = pipe_unaligned(); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_read.c b/userland/testbin/badcall/bad_read.c index c4e3215..3fdccf1 100644 --- a/userland/testbin/badcall/bad_read.c +++ b/userland/testbin/badcall/bad_read.c @@ -36,7 +36,13 @@ void test_read(void) { - test_read_fd(); - test_read_buf(); + int ntests = 0, lost_points = 0; + + test_read_fd(&ntests, &lost_points); + test_read_buf(&ntests, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); + } diff --git a/userland/testbin/badcall/bad_readlink.c b/userland/testbin/badcall/bad_readlink.c index 4399851..8682373 100644 --- a/userland/testbin/badcall/bad_readlink.c +++ b/userland/testbin/badcall/bad_readlink.c @@ -37,26 +37,28 @@ #include "test.h" static -void +int readlink_file(void) { char buf[128]; int fd, rv; + int result; report_begin("readlink on file"); fd = open_testfile("the question contains an invalid assumption"); if (fd<0) { - report_aborted(); - return; + report_aborted(&result); + return result; } close(fd); rv = readlink(TESTFILE, buf, sizeof(buf)); - report_check(rv, errno, EINVAL); + result = report_check(rv, errno, EINVAL); remove(TESTFILE); + return result; } static -void +int readlink_dir(void) { char buf[128]; @@ -64,11 +66,11 @@ readlink_dir(void) report_begin("readlink on ."); rv = readlink(".", buf, sizeof(buf)); - report_check(rv, errno, EISDIR); + return report_check(rv, errno, EISDIR); } static -void +int readlink_empty(void) { char buf[128]; @@ -76,17 +78,31 @@ readlink_empty(void) report_begin("readlink on empty string"); rv = readlink("", buf, sizeof(buf)); - report_check2(rv, errno, EISDIR, EINVAL); + return report_check2(rv, errno, EISDIR, EINVAL); } void test_readlink(void) { - test_readlink_path(); - test_readlink_buf(); + int ntests = 0, lost_points = 0; + int result; - readlink_file(); - readlink_dir(); - readlink_empty(); + test_readlink_path(&ntests, &lost_points); + test_readlink_buf(&ntests, &lost_points); + + ntests++; + result = readlink_file(); + handle_result(result, &lost_points); + + ntests++; + result = readlink_dir(); + handle_result(result, &lost_points); + + ntests++; + result = readlink_empty(); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_reboot.c b/userland/testbin/badcall/bad_reboot.c index add8fb9..7318e45 100644 --- a/userland/testbin/badcall/bad_reboot.c +++ b/userland/testbin/badcall/bad_reboot.c @@ -44,19 +44,27 @@ #include "test.h" static -void +int reboot_badflags(void) { int rv; - printf("(This should not kill the system...)\n"); + tprintf("(This should not kill the system...)\n"); report_begin("reboot with invalid flags"); rv = reboot(15353); - report_check(rv, errno, EINVAL); + return report_check(rv, errno, EINVAL); } void test_reboot(void) { - reboot_badflags(); + int ntests = 0, lost_points = 0; + int result; + + ntests++; + result = reboot_badflags(); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_remove.c b/userland/testbin/badcall/bad_remove.c index 02621ac..d971045 100644 --- a/userland/testbin/badcall/bad_remove.c +++ b/userland/testbin/badcall/bad_remove.c @@ -44,63 +44,83 @@ #include "test.h" static -void +int remove_dir(void) { int rv; + int result = FAILED; report_begin("remove() on a directory"); if (create_testdir() < 0) { /*report_aborted();*/ /* XXX in create_testdir */ - return; + return result; } rv = remove(TESTDIR); - report_check(rv, errno, EISDIR); + result = report_check(rv, errno, EISDIR); rmdir(TESTDIR); + + return result; } static -void +int remove_dot(void) { int rv; report_begin("remove() on ."); rv = remove("."); - report_check2(rv, errno, EISDIR, EINVAL); + return report_check2(rv, errno, EISDIR, EINVAL); } static -void +int remove_dotdot(void) { int rv; report_begin("remove() on .."); rv = remove(".."); - report_check2(rv, errno, EISDIR, EINVAL); + return report_check2(rv, errno, EISDIR, EINVAL); } static -void +int remove_empty(void) { int rv; report_begin("remove() on empty string"); rv = remove(""); - report_check2(rv, errno, EISDIR, EINVAL); + return report_check2(rv, errno, EISDIR, EINVAL); } void test_remove(void) { - test_remove_path(); + int ntests = 0, lost_points = 0; + int result; - remove_dir(); - remove_dot(); - remove_dotdot(); - remove_empty(); + test_remove_path(&ntests, &lost_points); + + ntests++; + result = remove_dir(); + handle_result(result, &lost_points); + + ntests++; + result = remove_dot(); + handle_result(result, &lost_points); + + ntests++; + result = remove_dotdot(); + handle_result(result, &lost_points); + + ntests++; + result = remove_empty(); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_rename.c b/userland/testbin/badcall/bad_rename.c index 814dcb6..355f983 100644 --- a/userland/testbin/badcall/bad_rename.c +++ b/userland/testbin/badcall/bad_rename.c @@ -37,75 +37,100 @@ #include "test.h" static -void +int rename_dot(void) { int rv; + int result; report_begin("rename ."); rv = rename(".", TESTDIR); - report_check(rv, errno, EINVAL); + result = report_check(rv, errno, EINVAL); if (rv==0) { /* oops... put it back */ rename(TESTDIR, "."); } + return result; } static -void +int rename_dotdot(void) { int rv; + int result; report_begin("rename .."); rv = rename("..", TESTDIR); - report_check(rv, errno, EINVAL); + result = report_check(rv, errno, EINVAL); if (rv==0) { /* oops... put it back */ rename(TESTDIR, ".."); } + return result; } static -void +int rename_empty1(void) { int rv; + int result; report_begin("rename empty string"); rv = rename("", TESTDIR); - report_check2(rv, errno, EISDIR, EINVAL); + result = report_check2(rv, errno, EISDIR, EINVAL); if (rv==0) { /* don't try to remove it */ rename(TESTDIR, TESTDIR "-foo"); } + return result; } static -void +int rename_empty2(void) { int rv; + int result = FAILED; report_begin("rename to empty string"); if (create_testdir()<0) { /*report_aborted();*/ /* XXX in create_testdir */ - return; + return result; } rv = rename(TESTDIR, ""); - report_check2(rv, errno, EISDIR, EINVAL); + result = report_check2(rv, errno, EISDIR, EINVAL); rmdir(TESTDIR); + return result; } void test_rename(void) { - test_rename_paths(); + int ntests = 0, lost_points = 0; + int result; - rename_dot(); - rename_dotdot(); - rename_empty1(); - rename_empty2(); + test_rename_paths(&ntests, &lost_points); + + ntests++; + result = rename_dot(); + handle_result(result, &lost_points); + + ntests++; + result = rename_dotdot(); + handle_result(result, &lost_points); + + ntests++; + result = rename_empty1(); + handle_result(result, &lost_points); + + ntests++; + result = rename_empty2(); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_rmdir.c b/userland/testbin/badcall/bad_rmdir.c index b1f6883..98e0080 100644 --- a/userland/testbin/badcall/bad_rmdir.c +++ b/userland/testbin/badcall/bad_rmdir.c @@ -44,61 +44,83 @@ #include "test.h" static -void +int rmdir_file(void) { int rv; + int result; report_begin("rmdir a file"); if (create_testfile()<0) { - report_aborted(); - return; + report_aborted(&result); + return result; } rv = rmdir(TESTFILE); - report_check(rv, errno, ENOTDIR); + result = report_check(rv, errno, ENOTDIR); remove(TESTFILE); + + return result; } static -void +int rmdir_dot(void) { int rv; + int result; report_begin("rmdir ."); rv = rmdir("."); - report_check(rv, errno, EINVAL); + result = report_check(rv, errno, EINVAL); + return result; } static -void +int rmdir_dotdot(void) { int rv; report_begin("rmdir .."); rv = rmdir(".."); - report_check2(rv, errno, EINVAL, ENOTEMPTY); + return report_check2(rv, errno, EINVAL, ENOTEMPTY); } static -void +int rmdir_empty(void) { int rv; report_begin("rmdir empty string"); rv = rmdir(""); - report_check(rv, errno, EINVAL); + return report_check(rv, errno, EINVAL); } void test_rmdir(void) { - test_rmdir_path(); + int ntests = 0, lost_points = 0; + int result; - rmdir_file(); - rmdir_dot(); - rmdir_dotdot(); - rmdir_empty(); + test_rmdir_path(&ntests, &lost_points); + + ntests++; + result = rmdir_file(); + handle_result(result, &lost_points); + + ntests++; + result = rmdir_dot(); + handle_result(result, &lost_points); + + ntests++; + result = rmdir_dotdot(); + handle_result(result, &lost_points); + + ntests++; + result = rmdir_empty(); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_sbrk.c b/userland/testbin/badcall/bad_sbrk.c index b482a92..dc4f351 100644 --- a/userland/testbin/badcall/bad_sbrk.c +++ b/userland/testbin/badcall/bad_sbrk.c @@ -59,7 +59,7 @@ try_sbrk(long val) } static -void +int enforce_sbrk(long val, const char *desc, int err) { int result; @@ -67,59 +67,79 @@ enforce_sbrk(long val, const char *desc, int err) report_begin("sbrk %s", desc); result = try_sbrk(val); - report_check(result, errno, err); + return report_check(result, errno, err); } static -void +int sbrk_bigpos(void) { - enforce_sbrk(4096*1024*256, "huge positive", ENOMEM); + return enforce_sbrk(1024*1024*1024 + (1024*1024*1024 - 4096*17), "huge positive", ENOMEM); } static -void +int sbrk_bigneg(void) { - enforce_sbrk(-4096*1024*256, "huge negative", EINVAL); + return enforce_sbrk(-4096*1024*256, "huge negative", EINVAL); } static -void +int sbrk_neg(void) { - enforce_sbrk(-8192, "too-large negative", EINVAL); + return enforce_sbrk(-8192, "too-large negative", EINVAL); } static -void +int sbrk_unalignedpos(void) { int result; report_begin("sbrk unaligned positive"); result = try_sbrk(17); - report_check2(result, errno, 0, EINVAL); + return report_check2(result, errno, 0, EINVAL); } static -void +int sbrk_unalignedneg(void) { int result; report_begin("sbrk unaligned negative"); result = try_sbrk(-17); - report_check2(result, errno, 0, EINVAL); + return report_check2(result, errno, 0, EINVAL); } void test_sbrk(void) { - sbrk_neg(); - sbrk_bigpos(); - sbrk_bigneg(); - sbrk_unalignedpos(); - sbrk_unalignedneg(); + int ntests = 0, lost_points = 0; + int result; + + ntests++; + result = sbrk_neg(); + handle_result(result, &lost_points); + + ntests++; + result = sbrk_bigpos(); + handle_result(result, &lost_points); + + ntests++; + result = sbrk_bigneg(); + handle_result(result, &lost_points); + + ntests++; + result = sbrk_unalignedpos(); + handle_result(result, &lost_points); + + ntests++; + result = sbrk_unalignedneg(); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_stat.c b/userland/testbin/badcall/bad_stat.c index 726f9b1..871d586 100644 --- a/userland/testbin/badcall/bad_stat.c +++ b/userland/testbin/badcall/bad_stat.c @@ -67,7 +67,7 @@ badbuf_stat(struct stat *sb) } static -void +int common_badbuf(int (*statfunc)(struct stat *), void *ptr, const char *call, const char *ptrdesc) { @@ -75,22 +75,24 @@ common_badbuf(int (*statfunc)(struct stat *), void *ptr, report_begin("%s with %s buf", call, ptrdesc); rv = statfunc(ptr); - report_check(rv, errno, EFAULT); + return report_check(rv, errno, EFAULT); } static -void +int any_badbuf(int (*statfunc)(struct stat *), const char *call) { - common_badbuf(statfunc, NULL, call, "NULL"); - common_badbuf(statfunc, INVAL_PTR, call, "invalid pointer"); - common_badbuf(statfunc, KERN_PTR, call, "kernel pointer"); + int result; + result = common_badbuf(statfunc, NULL, call, "NULL"); + result |= common_badbuf(statfunc, INVAL_PTR, call, "invalid pointer"); + result |= common_badbuf(statfunc, KERN_PTR, call, "kernel pointer"); + return result; } //////////////////////////////////////////////////////////// static -void +int any_empty(int (*statfunc)(const char *, struct stat *), const char *call) { struct stat sb; @@ -98,7 +100,7 @@ any_empty(int (*statfunc)(const char *, struct stat *), const char *call) report_begin("%s on empty string", call); rv = statfunc("", &sb); - report_check2(rv, errno, 0, EINVAL); + return report_check2(rv, errno, 0, EINVAL); } //////////////////////////////////////////////////////////// @@ -106,23 +108,56 @@ any_empty(int (*statfunc)(const char *, struct stat *), const char *call) void test_fstat(void) { - test_fstat_fd(); - any_badbuf(badbuf_fstat, "fstat"); + int ntests = 0, lost_points = 0; + int result; + + test_fstat_fd(&ntests, &lost_points); + + ntests++; + result = any_badbuf(badbuf_fstat, "fstat"); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } void test_lstat(void) { - test_lstat_path(); - any_empty(lstat, "lstat"); - any_badbuf(badbuf_lstat, "lstat"); + int ntests = 0, lost_points = 0; + int result; + + test_lstat_path(&ntests, &lost_points); + + ntests++; + result = any_empty(lstat, "lstat"); + handle_result(result, &lost_points); + + ntests++; + result = any_badbuf(badbuf_lstat, "lstat"); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } void test_stat(void) { - test_stat_path(); - any_empty(stat, "stat"); - any_badbuf(badbuf_stat, "stat"); + int ntests = 0, lost_points = 0; + int result; + + test_stat_path(&ntests, &lost_points); + + ntests++; + result = any_empty(stat, "stat"); + handle_result(result, &lost_points); + + ntests++; + result = any_badbuf(badbuf_stat, "stat"); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_symlink.c b/userland/testbin/badcall/bad_symlink.c index 68a3463..74c0526 100644 --- a/userland/testbin/badcall/bad_symlink.c +++ b/userland/testbin/badcall/bad_symlink.c @@ -37,32 +37,47 @@ #include "test.h" static -void +int symlink_empty1(void) { int rv; + int result; report_begin("symlink -> empty string"); rv = symlink("", TESTLINK); - report_check2(rv, errno, 0, EINVAL); + result = report_check2(rv, errno, 0, EINVAL); remove(TESTLINK); + return result; } static -void +int symlink_empty2(void) { int rv; report_begin("symlink named empty string"); rv = symlink("foo", ""); - report_check(rv, errno, EINVAL); + return report_check(rv, errno, EINVAL); } void test_symlink(void) { - test_symlink_paths(); - symlink_empty1(); - symlink_empty2(); + int ntests = 0, lost_points = 0; + int result; + + + test_symlink_paths(&ntests, &lost_points); + + ntests++; + result = symlink_empty1(); + handle_result(result, &lost_points); + + ntests++; + result = symlink_empty2(); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_time.c b/userland/testbin/badcall/bad_time.c index c5df61c..4474c9e 100644 --- a/userland/testbin/badcall/bad_time.c +++ b/userland/testbin/badcall/bad_time.c @@ -44,33 +44,49 @@ #include "test.h" static -void +int time_badsecs(void *ptr, const char *desc) { int rv; report_begin("%s", desc); rv = __time(ptr, NULL); - report_check(rv, errno, EFAULT); + return report_check(rv, errno, EFAULT); } static -void +int time_badnsecs(void *ptr, const char *desc) { int rv; report_begin("%s", desc); rv = __time(NULL, ptr); - report_check(rv, errno, EFAULT); + return report_check(rv, errno, EFAULT); } void test_time(void) { - time_badsecs(INVAL_PTR, "__time with invalid seconds pointer"); - time_badsecs(KERN_PTR, "__time with kernel seconds pointer"); + int ntests = 0, lost_points = 0; + int result; - time_badnsecs(INVAL_PTR, "__time with invalid nsecs pointer"); - time_badnsecs(KERN_PTR, "__time with kernel nsecs pointer"); + ntests++; + result = time_badsecs(INVAL_PTR, "__time with invalid seconds pointer"); + handle_result(result, &lost_points); + + ntests++; + result = time_badsecs(KERN_PTR, "__time with kernel seconds pointer"); + handle_result(result, &lost_points); + + ntests++; + result = time_badnsecs(INVAL_PTR, "__time with invalid nsecs pointer"); + handle_result(result, &lost_points); + + ntests++; + result = time_badnsecs(KERN_PTR, "__time with kernel nsecs pointer"); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_waitpid.c b/userland/testbin/badcall/bad_waitpid.c index f9bbd0d..7af2196 100644 --- a/userland/testbin/badcall/bad_waitpid.c +++ b/userland/testbin/badcall/bad_waitpid.c @@ -42,7 +42,7 @@ #include "test.h" static -void +int wait_badpid(pid_t pid, const char *desc) { pid_t rv; @@ -59,23 +59,24 @@ wait_badpid(pid_t pid, const char *desc) else if (err == ENOSYS) { report_saw_enosys(); } - report_check2(rv, err, ESRCH, ECHILD); + return report_check2(rv, err, ESRCH, ECHILD); } static -void +int wait_nullstatus(void) { pid_t pid, rv; int x; + int result; report_begin("wait with NULL status"); pid = fork(); if (pid<0) { report_warn("fork failed"); - report_aborted(); - return; + report_aborted(&result); + return result; } if (pid==0) { exit(0); @@ -83,50 +84,54 @@ wait_nullstatus(void) /* POSIX explicitly says passing NULL for status is allowed */ rv = waitpid(pid, NULL, 0); - report_check(rv, errno, 0); + result = report_check(rv, errno, 0); waitpid(pid, &x, 0); + return result; } static -void +int wait_badstatus(void *ptr, const char *desc) { pid_t pid, rv; int x; + int result; report_begin(desc); pid = fork(); if (pid<0) { report_warn("fork failed"); - report_aborted(); - return; + report_aborted(&result); + return result; } if (pid==0) { exit(0); } rv = waitpid(pid, ptr, 0); - report_check(rv, errno, EFAULT); + result = report_check(rv, errno, EFAULT); waitpid(pid, &x, 0); + return result; } static -void +int wait_unaligned(void) { pid_t pid, rv; int x; int status[2]; /* will have integer alignment */ char *ptr; + int result; report_begin("wait with unaligned status"); pid = fork(); if (pid<0) { report_warn("fork failed"); - report_aborted(); - return; + report_aborted(&result); + return result; } if (pid==0) { exit(0); @@ -139,55 +144,61 @@ wait_unaligned(void) ptr++; rv = waitpid(pid, (int *)ptr, 0); - report_survival(rv, errno); + report_survival(rv, errno, &result); if (rv<0) { waitpid(pid, &x, 0); } + return result; } static -void +int wait_badflags(void) { pid_t pid, rv; int x; + int result; report_begin("wait with bad flags"); pid = fork(); if (pid<0) { report_warn("fork failed"); - report_aborted(); - return; + report_aborted(&result); + return result; } if (pid==0) { exit(0); } rv = waitpid(pid, &x, 309429); - report_check(rv, errno, EINVAL); + result = report_check(rv, errno, EINVAL); waitpid(pid, &x, 0); + return result; } static -void +int wait_self(void) { pid_t rv; int x; + int result; report_begin("wait for self"); rv = waitpid(getpid(), &x, 0); - report_survival(rv, errno); + report_survival(rv, errno, &result); + return result; } static -void +int wait_parent(void) { pid_t mypid, childpid, rv; int x; + int result; report_begin("wait for parent"); report_hassubs(); @@ -196,30 +207,32 @@ wait_parent(void) childpid = fork(); if (childpid<0) { report_warn("can't fork"); - report_aborted(); - return; + report_aborted(&result); + return result; } if (childpid==0) { /* Child. Wait for parent. */ rv = waitpid(mypid, &x, 0); report_beginsub("from child:"); - report_survival(rv, errno); + report_survival(rv, errno, &result); _exit(0); } - rv = waitpid(childpid, &x, 0); + rv = waitpid(mypid, &x, 0); report_beginsub("from parent:"); - report_survival(rv, errno); + report_survival(rv, errno, &result); + return result; } //////////////////////////////////////////////////////////// static -void +int wait_siblings_child(const char *semname) { pid_t pids[2], mypid, otherpid; int rv, fd, semfd, x; char c; + int result; mypid = getpid(); @@ -244,7 +257,7 @@ wait_siblings_child(const char *semname) if (fd<0) { report_warn("child process (pid %d) can't open %s", mypid, TESTFILE); - return; + return FAILED; } /* @@ -257,13 +270,13 @@ wait_siblings_child(const char *semname) if (rv<0) { report_warn("child process (pid %d) lseek error", mypid); - return; + return FAILED; } rv = read(fd, pids, sizeof(pids)); if (rv<0) { report_warn("child process (pid %d) read error", mypid); - return; + return FAILED; } } while (rv < (int)sizeof(pids)); @@ -276,23 +289,25 @@ wait_siblings_child(const char *semname) else { report_warn("child process (pid %d) got garbage in comm file", mypid); - return; + return FAILED; } close(fd); rv = waitpid(otherpid, &x, 0); report_beginsub("sibling (pid %d)", mypid); - report_survival(rv, errno); + report_survival(rv, errno, &result); + return result; } static -void +int wait_siblings(void) { pid_t pids[2]; int rv, fd, semfd, x; int bad = 0; char semname[32]; + int result; /* This test may also blow up if FS synchronization is substandard */ @@ -303,26 +318,26 @@ wait_siblings(void) semfd = open(semname, O_WRONLY|O_CREAT|O_TRUNC, 0664); if (semfd < 0) { report_warn("can't make semaphore"); - report_aborted(); - return; + report_aborted(&result); + return result; } fd = open_testfile(NULL); if (fd<0) { - report_aborted(); + report_aborted(&result); close(semfd); remove(semname); - return; + return result; } pids[0] = fork(); if (pids[0]<0) { report_warn("can't fork"); - report_aborted(); + report_aborted(&result); close(fd); close(semfd); remove(semname); - return; + return result; } if (pids[0]==0) { close(fd); @@ -334,12 +349,12 @@ wait_siblings(void) pids[1] = fork(); if (pids[1]<0) { report_warn("can't fork"); - report_aborted(); + report_aborted(&result); /* abandon the other child process :( */ close(fd); close(semfd); remove(semname); - return; + return result; } if (pids[1]==0) { close(fd); @@ -351,21 +366,21 @@ wait_siblings(void) rv = write(fd, pids, sizeof(pids)); if (rv < 0) { report_warn("write error on %s", TESTFILE); - report_aborted(); + report_aborted(&result); /* abandon child procs :( */ close(fd); close(semfd); remove(semname); - return; + return result; } if (rv != (int)sizeof(pids)) { report_warnx("write error on %s: short count", TESTFILE); - report_aborted(); + report_aborted(&result); /* abandon child procs :( */ close(fd); close(semfd); remove(semname); - return; + return result; } /* gate the child procs */ @@ -388,15 +403,17 @@ wait_siblings(void) } if (bad) { /* XXX: aborted, or failure, or what? */ - report_aborted(); + report_aborted(&result); } else { - report_passed(); + report_passed(&result); } close(fd); close(semfd); remove(semname); remove(TESTFILE); + + return result; } //////////////////////////////////////////////////////////// @@ -404,20 +421,61 @@ wait_siblings(void) void test_waitpid(void) { - wait_badpid(-8, "wait for pid -8"); - wait_badpid(-1, "wait for pid -1"); - wait_badpid(0, "pid zero"); - wait_badpid(NONEXIST_PID, "nonexistent pid"); + int ntests = 0, lost_points = 0; + int result; - wait_nullstatus(); - wait_badstatus(INVAL_PTR, "wait with invalid pointer status"); - wait_badstatus(KERN_PTR, "wait with kernel pointer status"); + ntests++; + result = wait_badpid(-8, "wait for pid -8"); + handle_result(result, &lost_points); - wait_unaligned(); + ntests++; + result = wait_badpid(-1, "wait for pid -1"); + handle_result(result, &lost_points); - wait_badflags(); + ntests++; + result = wait_badpid(0, "pid zero"); + handle_result(result, &lost_points); - wait_self(); - wait_parent(); - wait_siblings(); + ntests++; + result = wait_badpid(NONEXIST_PID, "nonexistent pid"); + handle_result(result, &lost_points); + + + ntests++; + result = wait_nullstatus(); + handle_result(result, &lost_points); + + ntests++; + result = wait_badstatus(INVAL_PTR, "wait with invalid pointer status"); + handle_result(result, &lost_points); + + ntests++; + result = wait_badstatus(KERN_PTR, "wait with kernel pointer status"); + handle_result(result, &lost_points); + + + ntests++; + result = wait_unaligned(); + handle_result(result, &lost_points); + + + ntests++; + result = wait_badflags(); + handle_result(result, &lost_points); + + + ntests++; + result = wait_self(); + handle_result(result, &lost_points); + + ntests++; + result = wait_parent(); + handle_result(result, &lost_points); + + ntests++; + result = wait_siblings(); + handle_result(result, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/bad_write.c b/userland/testbin/badcall/bad_write.c index 8a79803..77a1ea3 100644 --- a/userland/testbin/badcall/bad_write.c +++ b/userland/testbin/badcall/bad_write.c @@ -36,6 +36,11 @@ void test_write(void) { - test_write_fd(); - test_write_buf(); + int ntests = 0, lost_points = 0; + + test_write_fd(&ntests, &lost_points); + test_write_buf(&ntests, &lost_points); + + if(!lost_points) + success(TEST161_SUCCESS, SECRET, "/testbin/badcall"); } diff --git a/userland/testbin/badcall/common_buf.c b/userland/testbin/badcall/common_buf.c index 37f7eaa..cde9496 100644 --- a/userland/testbin/badcall/common_buf.c +++ b/userland/testbin/badcall/common_buf.c @@ -175,33 +175,46 @@ getcwd_badbuf(void *buf) //////////////////////////////////////////////////////////// static -void +int common_badbuf(struct buftest *info, void *buf, const char *bufdesc) { int rv; - + int result; report_begin("%s with %s buffer", info->name, bufdesc); info->setup(); rv = info->op(buf); - report_check(rv, errno, EFAULT); + result = report_check(rv, errno, EFAULT); info->cleanup(); + return result; } static -void -any_badbuf(struct buftest *info) +int +any_badbuf(struct buftest *info, int *ntests, int *lost_points) { - common_badbuf(info, NULL, "NULL"); - common_badbuf(info, INVAL_PTR, "invalid"); - common_badbuf(info, KERN_PTR, "kernel-space"); + int result; + + *ntests += 1; + result = common_badbuf(info, NULL, "NULL"); + handle_result(result, lost_points); + + *ntests += 1; + result = common_badbuf(info, INVAL_PTR, "invalid"); + handle_result(result, lost_points); + + *ntests += 1; + result = common_badbuf(info, KERN_PTR, "kernel-space"); + handle_result(result, lost_points); + + return result; } //////////////////////////////////////////////////////////// #define T(call) \ void \ - test_##call##_buf(void) \ + test_##call##_buf(int *ntests, int *lost_points) \ { \ static struct buftest info = { \ call##_setup, \ @@ -209,7 +222,7 @@ any_badbuf(struct buftest *info) call##_cleanup, \ #call, \ }; \ - any_badbuf(&info); \ + any_badbuf(&info, ntests, lost_points); \ } T(read); diff --git a/userland/testbin/badcall/common_fds.c b/userland/testbin/badcall/common_fds.c index 173db73..032c474 100644 --- a/userland/testbin/badcall/common_fds.c +++ b/userland/testbin/badcall/common_fds.c @@ -138,46 +138,58 @@ dup2_cleanup(void) //////////////////////////////////////////////////////////// static -void +int any_badfd(int (*func)(int fd), void (*cleanup)(void), const char *callname, int fd, const char *fddesc) { int rv; - + int result; report_begin("%s using %s", callname, fddesc); rv = func(fd); - report_check(rv, errno, EBADF); + result = report_check(rv, errno, EBADF); if (cleanup) { cleanup(); } + return result; } static void runtest(int (*func)(int fd), void (*cleanup)(void), const char *callname, - enum rwtestmodes rw) + enum rwtestmodes rw, int *ntests, int *lost_points) { int fd; + int result; /* * If adding cases, also see bad_dup2.c */ /* basic invalid case: fd -1 */ - any_badfd(func, cleanup, callname, -1, "fd -1"); + *ntests += 1; + result = any_badfd(func, cleanup, callname, -1, "fd -1"); + handle_result(result, lost_points); /* also try -5 in case -1 is special somehow */ - any_badfd(func, cleanup, callname, -5, "fd -5"); + *ntests += 1; + result = any_badfd(func, cleanup, callname, -5, "fd -5"); + handle_result(result, lost_points); /* try a fd we know is closed */ - any_badfd(func, cleanup, callname, CLOSED_FD, "closed fd"); + *ntests += 1; + result = any_badfd(func, cleanup, callname, CLOSED_FD, "closed fd"); + handle_result(result, lost_points); /* try a positive fd we know is out of range */ - any_badfd(func, cleanup, callname, IMPOSSIBLE_FD, "impossible fd"); + *ntests += 1; + result = any_badfd(func, cleanup, callname, IMPOSSIBLE_FD, "impossible fd"); + handle_result(result, lost_points); /* test for off-by-one errors */ #ifdef OPEN_MAX - any_badfd(func, cleanup, callname, OPEN_MAX, "fd OPEN_MAX"); + *ntests += 1; + result = any_badfd(func, cleanup, callname, OPEN_MAX, "fd OPEN_MAX"); + handle_result(result, lost_points); #else warnx("Warning: OPEN_MAX not defined, test skipped"); #endif @@ -188,8 +200,10 @@ runtest(int (*func)(int fd), void (*cleanup)(void), const char *callname, /* already printed a message */ } else { - any_badfd(func, cleanup, callname, fd, + *ntests += 1; + result = any_badfd(func, cleanup, callname, fd, "fd opened read-only"); + handle_result(result, lost_points); } close(fd); } @@ -199,8 +213,10 @@ runtest(int (*func)(int fd), void (*cleanup)(void), const char *callname, /* already printed a message */ } else { - any_badfd(func, cleanup, callname, fd, + *ntests += 1; + result = any_badfd(func, cleanup, callname, fd, "fd opened write-only"); + handle_result(result, lost_points); } close(fd); } @@ -208,18 +224,18 @@ runtest(int (*func)(int fd), void (*cleanup)(void), const char *callname, //////////////////////////////////////////////////////////// -#define T(call, rw) \ - void \ - test_##call##_fd(void) \ - { \ - runtest(call##_badfd, NULL, #call, rw); \ +#define T(call, rw) \ + void \ + test_##call##_fd(int *ntests, int *lost_points) \ + { \ + runtest(call##_badfd, NULL, #call, rw, ntests, lost_points); \ } -#define TC(call, rw) \ - void \ - test_##call##_fd(void) \ - { \ - runtest(call##_badfd, call##_cleanup, #call, rw);\ +#define TC(call, rw) \ + void \ + test_##call##_fd(int *ntests, int *lost_points) \ + { \ + runtest(call##_badfd, call##_cleanup, #call, rw, ntests, lost_points); \ } T(read, RW_TEST_WRONLY); diff --git a/userland/testbin/badcall/common_path.c b/userland/testbin/badcall/common_path.c index 1a8ff9d..0a00cb6 100644 --- a/userland/testbin/badcall/common_path.c +++ b/userland/testbin/badcall/common_path.c @@ -148,46 +148,58 @@ stat_badpath(const char *name) //////////////////////////////////////////////////////////// static -void +int common_badpath(int (*func)(const char *path), int mk, int rm, const char *path, const char *call, const char *pathdesc) { int rv; + int result; report_begin("%s with %s path", call, pathdesc); if (mk) { if (create_testfile()<0) { - report_aborted(); - return; + report_aborted(&result); + return result; } } rv = func(path); - report_check(rv, errno, EFAULT); + result = report_check(rv, errno, EFAULT); if (mk || rm) { remove(TESTFILE); } + return result; } static void -any_badpath(int (*func)(const char *path), const char *call, int mk, int rm) +any_badpath(int (*func)(const char *path), const char *call, int mk, int rm, + int *ntests, int *lost_points) { - common_badpath(func, mk, rm, NULL, call, "NULL"); - common_badpath(func, mk, rm, INVAL_PTR, call, "invalid-pointer"); - common_badpath(func, mk, rm, KERN_PTR, call, "kernel-pointer"); + int result; + // We have a total of 3 tests + *ntests = *ntests + 3; + + result = common_badpath(func, mk, rm, NULL, call, "NULL"); + handle_result(result, lost_points); + + result = common_badpath(func, mk, rm, INVAL_PTR, call, "invalid-pointer"); + handle_result(result, lost_points); + + result = common_badpath(func, mk, rm, KERN_PTR, call, "kernel-pointer"); + handle_result(result, lost_points); } //////////////////////////////////////////////////////////// /* functions with one pathname */ -#define T(call) \ - void \ - test_##call##_path(void) \ - { \ - any_badpath(call##_badpath, #call, 0, 0); \ +#define T(call) \ + void \ + test_##call##_path(int *ntests, int *lost_points) \ + { \ + any_badpath(call##_badpath, #call, 0, 0, ntests, lost_points); \ } T(open); @@ -200,12 +212,12 @@ T(stat); T(lstat); /* functions with two pathnames */ -#define T2(call) \ - void \ - test_##call##_paths(void) \ - { \ - any_badpath(call##_badpath1, #call "(arg1)", 0, 1); \ - any_badpath(call##_badpath2, #call "(arg2)", 1, 1); \ +#define T2(call) \ + void \ + test_##call##_paths(int *ntests, int *lost_points) \ + { \ + any_badpath(call##_badpath1, #call "(arg1)", 0, 1, ntests, lost_points); \ + any_badpath(call##_badpath2, #call "(arg2)", 1, 1, ntests, lost_points); \ } T2(rename); diff --git a/userland/testbin/badcall/driver.c b/userland/testbin/badcall/driver.c index 31142f0..9155271 100644 --- a/userland/testbin/badcall/driver.c +++ b/userland/testbin/badcall/driver.c @@ -121,16 +121,18 @@ int create_testdir(void) { int rv; + int result; + rv = mkdir(TESTDIR, 0775); if (rv<0) { if (errno == ENOSYS) { report_saw_enosys(); report_warnx("mkdir unimplemented; cannot run test"); - report_skipped(); + report_skipped(&result); } else { report_warn("mkdir %s failed", TESTDIR); - report_aborted(); + report_aborted(&result); } return -1; } @@ -198,20 +200,20 @@ menu(void) { int i; for (i=0; ops[i].name; i++) { - printf("[%c] %-24s", ops[i].ch, ops[i].name); + tprintf("[%c] %-24s", ops[i].ch, ops[i].name); if (i%2==1) { - printf("\n"); + tprintf("\n"); } } if (i%2==1) { - printf("\n"); + tprintf("\n"); } - printf("[1] %-24s", "asst1"); - printf("[2] %-24s\n", "asst2"); - printf("[3] %-24s", "asst3"); - printf("[4] %-24s\n", "asst4"); - printf("[*] %-24s", "all"); - printf("[!] %-24s\n", "quit"); + tprintf("[1] %-24s", "asst1"); + tprintf("[2] %-24s\n", "asst2"); + tprintf("[3] %-24s", "asst3"); + tprintf("[4] %-24s\n", "asst4"); + tprintf("[*] %-24s", "all"); + tprintf("[!] %-24s\n", "quit"); } static @@ -231,7 +233,7 @@ runit(int op) if (op=='*') { for (i=0; ops[i].name; i++) { - printf("[%s]\n", ops[i].name); + tprintf("[%s]\n", ops[i].name); ops[i].f(); } return; @@ -241,7 +243,7 @@ runit(int op) k = op-'0'; for (i=0; ops[i].name; i++) { if (ops[i].asst <= k) { - printf("[%s]\n", ops[i].name); + tprintf("[%s]\n", ops[i].name); ops[i].f(); } } @@ -249,7 +251,7 @@ runit(int op) } if (op < LOWEST || op > HIGHEST) { - printf("Invalid request %c\n", op); + tprintf("Invalid request %c\n", op); return; } @@ -261,12 +263,12 @@ main(int argc, char **argv) { int op, i, j; - printf("[%c-%c, 1-4, *, ?=menu, !=quit]\n", LOWEST, HIGHEST); + tprintf("[%c-%c, 1-4, *, ?=menu, !=quit]\n", LOWEST, HIGHEST); if (argc > 1) { for (i=1; i + #define TESTFILE "badcallfile" #define TESTDIR "badcalldir" #define TESTLINK "badcalllink" @@ -37,6 +39,11 @@ #define PF(a, b) #endif +#define SUCCESS 0 +#define SKIPPED 1 +#define FAILED 2 +#define ABORTED 3 + /* driver.c */ int open_testfile(const char *str); int reopen_testfile(int openflags); @@ -52,46 +59,46 @@ PF(1, 2) void report_warn(const char *fmt, ...); PF(1, 2) void report_warnx(const char *fmt, ...); void report_result(int rv, int error); void report_saw_enosys(void); -void report_passed(void); -void report_failure(void); -void report_skipped(void); -void report_aborted(void); -void report_survival(int rv, int error); -void report_check(int rv, int error, int right_error); -void report_check2(int rv, int error, int okerr1, int okerr2); -void report_check3(int rv, int error, int okerr1, int okerr2, int okerr3); +void report_passed(int *result); +void report_failure(int *result); +void report_skipped(int *result); +void report_aborted(int *result); +void report_survival(int rv, int error, int *result); +int report_check(int rv, int error, int right_error); +int report_check2(int rv, int error, int okerr1, int okerr2); +int report_check3(int rv, int error, int okerr1, int okerr2, int okerr3); /* common_buf.c */ -void test_read_buf(void); -void test_write_buf(void); -void test_getdirentry_buf(void); -void test_getcwd_buf(void); -void test_readlink_buf(void); +void test_read_buf(int *ntests, int *lost_points); +void test_write_buf(int *ntests, int *lost_points); +void test_getdirentry_buf(int *ntests, int *lost_points); +void test_getcwd_buf(int *ntests, int *lost_points); +void test_readlink_buf(int *ntests, int *lost_points); /* common_fds.c */ -void test_read_fd(void); -void test_write_fd(void); -void test_close_fd(void); -void test_ioctl_fd(void); -void test_lseek_fd(void); -void test_fsync_fd(void); -void test_ftruncate_fd(void); -void test_fstat_fd(void); -void test_getdirentry_fd(void); -void test_dup2_fd(void); +void test_read_fd(int *ntests, int *lost_points); +void test_write_fd(int *ntests, int *lost_points); +void test_close_fd(int *ntests, int *lost_points); +void test_ioctl_fd(int *ntests, int *lost_points); +void test_lseek_fd(int *ntests, int *lost_points); +void test_fsync_fd(int *ntests, int *lost_points); +void test_ftruncate_fd(int *ntests, int *lost_points); +void test_fstat_fd(int *ntests, int *lost_points); +void test_getdirentry_fd(int *ntests, int *lost_points); +void test_dup2_fd(int *ntests, int *lost_points); /* common_path.c */ -void test_open_path(void); -void test_remove_path(void); -void test_rename_paths(void); -void test_link_paths(void); -void test_mkdir_path(void); -void test_rmdir_path(void); -void test_chdir_path(void); -void test_symlink_paths(void); -void test_readlink_path(void); -void test_stat_path(void); -void test_lstat_path(void); +void test_open_path(int *ntests, int *lost_points); +void test_remove_path(int *ntests, int *lost_points); +void test_rename_paths(int *ntests, int *lost_points); +void test_link_paths(int *ntests, int *lost_points); +void test_mkdir_path(int *ntests, int *lost_points); +void test_rmdir_path(int *ntests, int *lost_points); +void test_chdir_path(int *ntests, int *lost_points); +void test_symlink_paths(int *ntests, int *lost_points); +void test_readlink_path(int *ntests, int *lost_points); +void test_stat_path(int *ntests, int *lost_points); +void test_lstat_path(int *ntests, int *lost_points); /* bad_*.c */ void test_execv(void); @@ -122,3 +129,6 @@ void test_time(void); void test_getcwd(void); void test_stat(void); void test_lstat(void); /* in bad_stat.c */ + +void handle_result(int result, int *lost_points); + diff --git a/userland/testbin/bigexec/bigexec.c b/userland/testbin/bigexec/bigexec.c index c417d81..1f92fea 100644 --- a/userland/testbin/bigexec/bigexec.c +++ b/userland/testbin/bigexec/bigexec.c @@ -36,11 +36,13 @@ #include #include +#include #include #include #include #include #include +#include #define _PATH_MYSELF "/testbin/bigexec" @@ -110,6 +112,7 @@ try(const char *first, ...) va_list ap; int num; + nprintf("."); assert(first != NULL); args[0] = _PATH_MYSELF; args[1] = first; @@ -124,6 +127,7 @@ try(const char *first, ...) assert(num < 20); args[num++] = s; } + nprintf("\n"); assert(num < 20); args[num] = NULL; execv(_PATH_MYSELF, (char **)args); @@ -137,9 +141,12 @@ trymany(int num, const char *word) const char *args[num+2]; int i; + nprintf("."); args[0] = _PATH_MYSELF; for (i=0; i #include #include +#include +#include #define BRANCHES 6 @@ -54,6 +56,8 @@ */ #define DIM 64 +#define PROGRESS_INTERVAL 25000 + static int m1[DIM*DIM], m2[DIM*DIM], m3[DIM*DIM], m4[DIM*DIM]; static const int right[BRANCHES] = { 536763422, @@ -76,7 +80,9 @@ init(void) for (j=0; j 0) { failures += WEXITSTATUS(status); @@ -196,7 +209,6 @@ dotest(void) unsigned i, me; pid_t pids[BRANCHES]; int t; - char msg[128]; me = 0; for (i=0; i 0; ) { dowait(pids[i]); } + if (failures > 0) { - printf("%u failures.\n", failures); + tprintf("%u failures.\n", failures); + success(TEST161_FAIL, SECRET, "/testbin/bigfork"); } else { - printf("Done.\n"); + tprintf("Done.\n"); + success(TEST161_SUCCESS, SECRET, "/testbin/bigfork"); } } diff --git a/userland/testbin/bigseek/bigseek.c b/userland/testbin/bigseek/bigseek.c index aab4601..6329bc3 100644 --- a/userland/testbin/bigseek/bigseek.c +++ b/userland/testbin/bigseek/bigseek.c @@ -182,7 +182,7 @@ static void try_seeking(int fd, off_t pos, off_t cursize) { - printf("Seeking to (and near) 0x%llx\n", pos); + tprintf("Seeking to (and near) 0x%llx\n", pos); /* Go to the place. */ dolseek(fd, pos, SEEK_SET, "SEEK_SET", pos); @@ -215,30 +215,30 @@ main(void) off_t cursize; int fd; - printf("Creating file...\n"); + tprintf("Creating file...\n"); fd = open(TESTFILE, O_RDWR|O_CREAT|O_TRUNC, 0664); if (fd < 0) { err(1, "%s", TESTFILE); } - printf("Writing something at offset 0\n"); + tprintf("Writing something at offset 0\n"); write_slogan(fd, 0, false); cursize = strlen(slogans[0]); try_seeking(fd, (off_t)0x1000LL, cursize); - printf("Writing something else\n"); + tprintf("Writing something else\n"); write_slogan(fd, 1, false); cursize = (off_t)0x1000LL + strlen(slogans[1]); try_seeking(fd, (off_t)0, cursize); /* If seek is totally bust, this will fail. */ - printf("Checking what we wrote\n"); + tprintf("Checking what we wrote\n"); check_slogan(fd, 0); try_seeking(fd, (off_t)0x1000LL, cursize); - printf("Checking the other thing we wrote\n"); + tprintf("Checking the other thing we wrote\n"); check_slogan(fd, 1); try_seeking(fd, (off_t)0x20LL, cursize); @@ -250,19 +250,19 @@ main(void) try_seeking(fd, (off_t)0x180000000LL, cursize); try_seeking(fd, (off_t)0x180000020LL, cursize); - printf("Now trying to read (should get EOF)\n"); + tprintf("Now trying to read (should get EOF)\n"); try_reading(fd); - printf("Now trying to write (should get EFBIG)\n"); + tprintf("Now trying to write (should get EFBIG)\n"); try_writing(fd); try_seeking(fd, (off_t)0x100000000LL, cursize); /* If seek truncates to 32 bits, this might read the slogan instead */ - printf("Trying to read again (should get EOF)\n"); + tprintf("Trying to read again (should get EOF)\n"); try_reading(fd); - printf("Passed.\n"); + tprintf("Passed.\n"); close(fd); remove(TESTFILE); diff --git a/userland/testbin/bloat/bloat.c b/userland/testbin/bloat/bloat.c index ed5aca7..21ffbc2 100644 --- a/userland/testbin/bloat/bloat.c +++ b/userland/testbin/bloat/bloat.c @@ -131,11 +131,11 @@ static void printsettings(void) { - printf("Page size: %u\n", PAGE_SIZE); - printf("Allocating %u pages and touching %u pages on each cycle.\n", + tprintf("Page size: %u\n", PAGE_SIZE); + tprintf("Allocating %u pages and touching %u pages on each cycle.\n", allocs, touchpages); - printf("Page selection bias: %u\n", bias); - printf("\n"); + tprintf("Page selection bias: %u\n", bias); + tprintf("\n"); } static diff --git a/userland/testbin/crash/crash.c b/userland/testbin/crash/crash.c index 57406aa..50d61de 100644 --- a/userland/testbin/crash/crash.c +++ b/userland/testbin/crash/crash.c @@ -46,6 +46,8 @@ #include #include #include +#include + #if defined(__mips__) #define KERNEL_ADDR 0x80000000 @@ -292,7 +294,7 @@ runop(int op) /* intentionally don't check if op is in bounds :) */ opindex = op-'a'; - printf("Running: [%c] %s\n", ops[opindex].ch, ops[opindex].name); + tprintf("Running: [%c] %s\n", ops[opindex].ch, ops[opindex].name); if (forking) { pid = fork(); @@ -307,25 +309,25 @@ runop(int op) } ok = 0; if (WIFSIGNALED(status)) { - printf("Signal %d\n", WTERMSIG(status)); + tprintf("Signal %d\n", WTERMSIG(status)); if (WTERMSIG(status) == ops[opindex].sig) { ok = 1; } } else { - printf("Exit %d\n", WEXITSTATUS(status)); + tprintf("Exit %d\n", WEXITSTATUS(status)); if (WEXITSTATUS(status) == MAGIC) { ok = 1; } } if (ok) { - printf("Ok.\n"); + tprintf("Ok.\n"); } else { - printf("FAILED: expected signal %d\n", + tprintf("FAILED: expected signal %d\n", ops[opindex].sig); } - printf("\n"); + tprintf("\n"); return; } } @@ -351,14 +353,14 @@ ask(void) while (1) { for (i=0; ops[i].name; i++) { - printf("[%c] %s\n", ops[i].ch, ops[i].name); + tprintf("[%c] %s\n", ops[i].ch, ops[i].name); } - printf("[-] Disable forking\n"); - printf("[+] Enable forking (default)\n"); - printf("[*] Run everything\n"); - printf("[!] Quit\n"); + tprintf("[-] Disable forking\n"); + tprintf("[+] Enable forking (default)\n"); + tprintf("[*] Run everything\n"); + tprintf("[!] Quit\n"); - printf("Choose: "); + tprintf("Choose: "); op = getchar(); if (op == '!') { @@ -384,5 +386,7 @@ main(int argc, char **argv) } } } + printf("Should print success\n"); + success(TEST161_SUCCESS, SECRET, "/testbin/crash"); return 0; } diff --git a/userland/testbin/ctest/ctest.c b/userland/testbin/ctest/ctest.c index 0dcd9e9..fcee4ad 100644 --- a/userland/testbin/ctest/ctest.c +++ b/userland/testbin/ctest/ctest.c @@ -38,6 +38,7 @@ #include #include +#include /* * SIZE is the amount of memory used. @@ -64,12 +65,12 @@ main(int argc, char **argv) stride = atoi(argv[1]); } if (stride <= 0 || argc > 2) { - printf("Usage: ctest [stridesize]\n"); - printf(" stridesize should not be a multiple of 2.\n"); + tprintf("Usage: ctest [stridesize]\n"); + tprintf(" stridesize should not be a multiple of 2.\n"); return 1; } - printf("Starting ctest: stride %d\n", stride); + tprintf("Starting ctest: stride %d\n", stride); /* * Generate a huge linked list, with each entry pointing to @@ -90,12 +91,11 @@ main(int argc, char **argv) */ e = &array[0]; for (i=0; ie; } - printf("\nDone!\n"); + // Success is not crashing + success(TEST161_SUCCESS, SECRET, "/testbin/ctest"); return 0; } diff --git a/userland/testbin/dirconc/dirconc.c b/userland/testbin/dirconc/dirconc.c index c388006..36bf823 100644 --- a/userland/testbin/dirconc/dirconc.c +++ b/userland/testbin/dirconc/dirconc.c @@ -84,7 +84,7 @@ choose_name(char *buf, size_t len) /* * The purpose of this is to be atomic. In our world, straight - * printf tends not to be. + * tprintf tends not to be. */ static void diff --git a/userland/testbin/dirseek/dirseek.c b/userland/testbin/dirseek/dirseek.c index 200640c..bc882bc 100644 --- a/userland/testbin/dirseek/dirseek.c +++ b/userland/testbin/dirseek/dirseek.c @@ -205,7 +205,7 @@ firstread(void) errx(1, ".: File position after open not 0"); } - printf("Scanning directory...\n"); + tprintf("Scanning directory...\n"); readit(); } @@ -216,7 +216,7 @@ doreadat0(void) { off_t pos; - printf("Rewinding directory and reading it again...\n"); + tprintf("Rewinding directory and reading it again...\n"); pos = lseek(dirfd, 0, SEEK_SET); if (pos < 0) { @@ -274,7 +274,7 @@ readallonebyone(void) { int i; - printf("Trying to read each entry again...\n"); + tprintf("Trying to read each entry again...\n"); for (i=0; testfiles[i].name; i++) { doreadone(i); } @@ -286,7 +286,7 @@ readallrandomly(void) { int n, i, x; - printf("Trying to read a bunch of entries randomly...\n"); + tprintf("Trying to read a bunch of entries randomly...\n"); for (i=0; testfiles[i].name; i++); n = i; @@ -327,7 +327,7 @@ doreadateof(void) off_t pos; int i; - printf("Trying to read after going to EOF...\n"); + tprintf("Trying to read after going to EOF...\n"); pos = lseek(dirfd, 0, SEEK_END); if (pos<0) { @@ -364,7 +364,7 @@ dobadreads(void) off_t pos, pos2, eof; int valid, i, k=0; - printf("Trying some possibly invalid reads...\n"); + tprintf("Trying some possibly invalid reads...\n"); eof = lseek(dirfd, 0, SEEK_END); if (eof < 0) { @@ -394,13 +394,13 @@ dobadreads(void) } if (k>0) { - printf("Survived %d invalid reads...\n", k); + tprintf("Survived %d invalid reads...\n", k); } else { - printf("Couldn't find any invalid offsets to try...\n"); + tprintf("Couldn't find any invalid offsets to try...\n"); } - printf("Trying to read beyond EOF...\n"); + tprintf("Trying to read beyond EOF...\n"); pos2 = lseek(dirfd, eof + 1000, SEEK_SET); if (pos2 < 0) { /* this is ok */ @@ -414,10 +414,10 @@ static void dotest(void) { - printf("Opening directory...\n"); + tprintf("Opening directory...\n"); openit(); - printf("Running tests...\n"); + tprintf("Running tests...\n"); /* read the whole directory */ firstread(); @@ -443,7 +443,7 @@ dotest(void) /* rewind again to make sure the invalid attempts didn't break it */ doreadat0(); - printf("Closing directory...\n"); + tprintf("Closing directory...\n"); closeit(); } @@ -489,7 +489,7 @@ setup(void) { int i; - printf("Making directory %s...\n", TESTDIR); + tprintf("Making directory %s...\n", TESTDIR); /* Create a directory */ if (mkdir(TESTDIR, 0775)<0) { @@ -501,7 +501,7 @@ setup(void) err(1, "%s: chdir", TESTDIR); } - printf("Making some files...\n"); + tprintf("Making some files...\n"); /* Populate it */ for (i=0; testfiles[i].name; i++) { @@ -518,7 +518,7 @@ cleanup(void) { int i; - printf("Cleaning up...\n"); + tprintf("Cleaning up...\n"); /* Remove the files */ for (i=0; testfiles[i].name; i++) { diff --git a/userland/testbin/dirtest/dirtest.c b/userland/testbin/dirtest/dirtest.c index 692506d..5f2f525 100644 --- a/userland/testbin/dirtest/dirtest.c +++ b/userland/testbin/dirtest/dirtest.c @@ -58,7 +58,7 @@ main(void) strcpy(dirname, onename); for (i=0; i #include #include +#include #define _PATH_SELF "/testbin/factorial" @@ -245,9 +246,12 @@ main(int argc, char *argv[]) } else if (argc == 3) { if (!strcmp(argv[1], "1") || !strcmp(argv[1], "0")) { - printf("%s\n", argv[2]); + nprintf("\n"); + tprintf("%s\n", argv[2]); + secprintf(SECRET, argv[2], "/testbin/factorial"); } else { + nprintf("."); number_init(&n1, argv[1]); number_init(&n2, argv[2]); number_init(&multbuf, "0"); diff --git a/userland/testbin/faulter/faulter.c b/userland/testbin/faulter/faulter.c index 98dc4f0..42f3544 100644 --- a/userland/testbin/faulter/faulter.c +++ b/userland/testbin/faulter/faulter.c @@ -45,12 +45,12 @@ main(void) { volatile int i; - printf("\nEntering the faulter program - I should die immediately\n"); + tprintf("\nEntering the faulter program - I should die immediately\n"); i = *(int *)REALLY_BIG_ADDRESS; // gcc 4.8 improperly demands this (void)i; - printf("I didn't get killed! Program has a bug\n"); + tprintf("I didn't get killed! Program has a bug\n"); return 0; } diff --git a/userland/testbin/filetest/filetest.c b/userland/testbin/filetest/filetest.c index ae93c38..7d7d4df 100644 --- a/userland/testbin/filetest/filetest.c +++ b/userland/testbin/filetest/filetest.c @@ -103,6 +103,6 @@ main(int argc, char *argv[]) if (rv<0) { err(1, "%s: remove", file); } - printf("Passed filetest.\n"); + tprintf("Passed filetest.\n"); return 0; } diff --git a/userland/testbin/forkbomb/forkbomb.c b/userland/testbin/forkbomb/forkbomb.c index 6db265b..01af4c2 100644 --- a/userland/testbin/forkbomb/forkbomb.c +++ b/userland/testbin/forkbomb/forkbomb.c @@ -49,6 +49,11 @@ #include #include +#include +#include + +#define TEST_DURATION 10 +#define LOCAL_SUCCESS "SUCCESS" static volatile int pid; @@ -57,8 +62,40 @@ main(void) { int i; + time_t start_time_s, time_now_s; + unsigned long start_time_ns, time_now_ns; + __time(&start_time_s, &start_time_ns); + int parent_pid = getpid(); + int did_print = 0; + int iters = 0; + + // Do not remove! + // We need to cause page faults on the static secprintf buffers so the + // pages are available when we print success. With on-demand page allocation, + // we will probably be out of pages by the time we try to print success. + secprintf(SECRET, "!!< Starting Forkbbbboooommmmbbbb >!!", "/testbin/forkbomb"); + + // And now for the success string + printf("This should print %s after 10s\n", LOCAL_SUCCESS); + while (1) { fork(); + // Only parent gets to print + if(getpid() == parent_pid) { + TEST161_LPROGRESS(0); + if (iters > 0 && iters % 20 == 0) { + putchar('\n'); + } + iters++; + + __time(&time_now_s, &time_now_ns); + if (time_now_s - start_time_s > TEST_DURATION && !did_print) { + did_print = 1; + // We need to print this using secprintf so that it uses + // the same page we warmed up earlier. + secprintf(SECRET, LOCAL_SUCCESS, "/testbin/forkbomb"); + } + } pid = getpid(); diff --git a/userland/testbin/forktest/forktest.c b/userland/testbin/forktest/forktest.c index 4f7fed3..bcefe62 100644 --- a/userland/testbin/forktest/forktest.c +++ b/userland/testbin/forktest/forktest.c @@ -37,10 +37,16 @@ */ #include +#include #include #include #include #include +#include + +#define FORKTEST_FILENAME_BASE "forktest" + +static char filename[32]; /* * This is used by all processes, to try to help make sure all @@ -48,6 +54,18 @@ */ static volatile int mypid; +/* + * Helper function to do pow() + */ +static +int pow_int(int x, int y) { + int i; + int result = 1; + for(i = 0; i < y; i++) + result *= x; + return result; +} + /* * Helper function for fork that prints a warning on error. */ @@ -77,6 +95,7 @@ check(void) mypid = getpid(); /* Make sure each fork has its own address space. */ + nprintf("."); for (i=0; i<800; i++) { volatile int seenpid; seenpid = mypid; @@ -114,13 +133,13 @@ dowait(int nowait, int pid) if (!nowait) { if (waitpid(pid, &x, 0)<0) { - warn("waitpid"); + errx(1, "waitpid"); } else if (WIFSIGNALED(x)) { - warnx("pid %d: signal %d", pid, WTERMSIG(x)); + errx(1, "pid %d: signal %d", pid, WTERMSIG(x)); } else if (WEXITSTATUS(x) != 0) { - warnx("pid %d: exit %d", pid, WEXITSTATUS(x)); + errx(1, "pid %d: exit %d", pid, WEXITSTATUS(x)); } } } @@ -141,17 +160,42 @@ test(int nowait) * to prevent wait/exit problems if fork corrupts memory. */ + /* + * Guru: We have a problem here. + * We need to write the output to a file since test161 is + * supposed to be as simple as possible. This requires the + * test to tell test161 whether it passed or succeeded. + * We cannot lseek and read stdout, to check the output, + * so we need to write the output to a file and then check it later. + * + * So far so good. However, if in the future, forktest is + * going to be combined with triple/quint/etc, then the filename + * cannot be the same across multiple copies. So we need a + * unique filename per instance of forktest. + * So... + */ + snprintf(filename, 32, "%s-%d.bin", FORKTEST_FILENAME_BASE, getpid()); + int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC); + if(fd < 3) { + // 0, 1, 2 are stdin, stdout, stderr + err(1, "Failed to open file to write data into\n"); + } + pid0 = dofork(); - putchar('A'); + nprintf("."); + write(fd, "A", 1); check(); pid1 = dofork(); - putchar('B'); + nprintf("."); + write(fd, "B", 1); check(); pid2 = dofork(); - putchar('C'); + nprintf("."); + write(fd, "C", 1); check(); pid3 = dofork(); - putchar('D'); + nprintf("."); + write(fd, "D", 1); check(); /* @@ -159,11 +203,57 @@ test(int nowait) * improperly. */ dowait(nowait, pid3); + nprintf("."); dowait(nowait, pid2); + nprintf("."); dowait(nowait, pid1); + nprintf("."); dowait(nowait, pid0); + nprintf("."); - putchar('\n'); + // Check if file contents are correct + // lseek may not be implemented..so close and reopen + close(fd); + fd = open(filename, O_RDONLY); + if(fd < 3) { + err(1, "Failed to open file for verification\n"); + } + nprintf("."); + + char buffer[30]; + int len; + int char_idx, i; + int observed, expected; + char character = 'A'; + + memset(buffer, 0, 30); + len = read(fd, buffer, 30); + printf("\n%s\n", buffer); + if(len != 30) { + err(1, "Did not get expected number of characters\n"); + } + nprintf("."); + // Check if number of instances of each character is correct + // 2As; 4Bs; 8Cs; 16Ds + for(char_idx = 0; char_idx < 4; char_idx++) { + nprintf("."); + observed = 0; + expected = pow_int(2, char_idx + 1); + for(i = 0; i < 30; i++) { + // In C, char can be directly converted to an ASCII index + // So, A is 65, B is 66, ... + if(buffer[i] == character + char_idx) { + observed++; + } + } + if(observed != expected) { + // Failed + err(1, "Failed! Expected %d%cs..observed: %d\n", expected, character + char_idx, observed); + } + } + nprintf("\n"); + success(TEST161_SUCCESS, SECRET, "/testbin/forktest"); + close(fd); } int diff --git a/userland/testbin/frack/check.c b/userland/testbin/frack/check.c index fea6783..b671163 100644 --- a/userland/testbin/frack/check.c +++ b/userland/testbin/frack/check.c @@ -2148,7 +2148,7 @@ doindent(unsigned depth) unsigned i; for (i=0; inext) { if (enta->name == entb->name) { doindent(indent); - printf("%s", name_get(enta->name)); + tprintf("%s", name_get(enta->name)); if (enta->obj->isdir && !entb->obj->isdir) { - printf(": expected dir, found file;"); - printf(" %u names missing.\n", + tprintf(": expected dir, found file;"); + tprintf(" %u names missing.\n", count_subtree(enta->obj) - 1); } else if (!enta->obj->isdir && entb->obj->isdir) { - printf(": expected file, found dir;"); - printf(" %u extra names.\n", + tprintf(": expected file, found dir;"); + tprintf(" %u extra names.\n", count_subtree(entb->obj) - 1); } else if (!enta->obj->isdir && @@ -2194,18 +2194,18 @@ printdiffs(unsigned indent, struct fsobject *obja, struct fsobject *objb) alen = enta->obj->obj_file.len; blen = entb->obj->obj_file.len; if (alen == blen) { - printf("\t\t%lld bytes (ok)\n", + tprintf("\t\t%lld bytes (ok)\n", alen); } else { - printf(": found %lld bytes, " + tprintf(": found %lld bytes, " "expected %lld " "bytes.\n", blen, alen); } } else { - printf("/\n"); + tprintf("/\n"); printdiffs(indent + 1, enta->obj, entb->obj); } @@ -2215,13 +2215,13 @@ printdiffs(unsigned indent, struct fsobject *obja, struct fsobject *objb) } if (!found) { doindent(indent); - printf("%s: missing ", name_get(enta->name)); + tprintf("%s: missing ", name_get(enta->name)); if (enta->obj->isdir) { - printf("subtree with %u names.\n", + tprintf("subtree with %u names.\n", count_subtree(enta->obj) - 1); } else { - printf("file\n"); + tprintf("file\n"); } } } @@ -2238,13 +2238,13 @@ printdiffs(unsigned indent, struct fsobject *obja, struct fsobject *objb) } if (!found) { doindent(indent); - printf("%s: extra ", name_get(entb->name)); + tprintf("%s: extra ", name_get(entb->name)); if (entb->obj->isdir) { - printf("subtree with %u names.\n", + tprintf("subtree with %u names.\n", count_subtree(entb->obj) - 1); } else { - printf("file\n"); + tprintf("file\n"); } } } @@ -2326,7 +2326,7 @@ checkfilezeros(int fd, const char *namestr, off_t start, off_t end) unsigned poison = 0, trash = 0; off_t origstart = start; - printf(" %lld - %lld (expecting zeros)\n", start, end); + tprintf(" %lld - %lld (expecting zeros)\n", start, end); if (lseek(fd, start, SEEK_SET) == -1) { err(1, "%s: lseek to %lld", namestr, start); @@ -2356,19 +2356,19 @@ checkfilezeros(int fd, const char *namestr, off_t start, off_t end) start += ret; } if (poison > 0 || trash > 0) { - printf("ERROR: File %s: expected zeros from %lld to %lld; " + tprintf("ERROR: File %s: expected zeros from %lld to %lld; " "found", namestr, origstart, end); if (poison > 0) { - printf(" %u poison bytes", poison); + tprintf(" %u poison bytes", poison); if (trash > 0) { - printf(" and"); + tprintf(" and"); } } if (trash > 0) { - printf(" %u trash bytes", trash); + tprintf(" %u trash bytes", trash); } - printf("\n"); + tprintf("\n"); } } @@ -2440,7 +2440,7 @@ checkfiledata(int fd, const char *namestr, unsigned code, unsigned seq, checkend = regionend; } - printf(" %lld - %lld\n", checkstart, checkend); + tprintf(" %lld - %lld\n", checkstart, checkend); readfiledata(fd, namestr, regionstart, checkstart, checkend, regionend); @@ -2695,7 +2695,7 @@ checkonefilecontents(const char *namestr, struct fsobject *file, return; } assert(change->type == FC_WRITE); - printf("ERROR: File %s is zero length but was expected to " + tprintf("ERROR: File %s is zero length but was expected to " "contain at least %lld bytes at offset %lld!\n", namestr, change->fc_write.pos, change->fc_write.len); close(fd); @@ -2704,7 +2704,7 @@ checkonefilecontents(const char *namestr, struct fsobject *file, /* XXX: this check is wrong too. */ if (change->type == FC_CREAT) { - printf("ERROR: File %s was never written to but has " + tprintf("ERROR: File %s was never written to but has " "length %lld\n", namestr, file->obj_file.len); close(fd); @@ -2741,12 +2741,12 @@ checkonefilecontents(const char *namestr, struct fsobject *file, */ while (!change_is_present(fd, namestr, file->obj_file.len, change)) { if (change->version < okversion) { - printf("File %s: change for version %u is missing\n", + tprintf("File %s: change for version %u is missing\n", namestr, change->version); } change = backup_for_file(change->prev,file->obj_file.identity); if (change == NULL) { - printf("File %s: no matching version found\n", + tprintf("File %s: no matching version found\n", namestr); close(fd); return; @@ -2781,18 +2781,18 @@ checkallfilecontents(struct fsobject *dir, struct fschange *change) for (de = dir->obj_dir.entries; de != NULL; de = de->next) { namestr = name_get(de->name); if (de->obj->isdir) { - printf(" >>> Entering %s\n", namestr); + tprintf(" >>> Entering %s\n", namestr); if (chdir(namestr)) { err(1, "%s: chdir", namestr); } checkallfilecontents(de->obj, change); - printf(" <<< Leaving %s\n", namestr); + tprintf(" <<< Leaving %s\n", namestr); if (chdir("..")) { err(1, "..: chdir"); } } else { - printf("%s...\n", namestr); + tprintf("%s...\n", namestr); checkonefilecontents(namestr, de->obj, change); } } @@ -2813,7 +2813,7 @@ checkfs(void) /* * We just built the model; talk about it. */ - printf("Established %u versions across %u directories and %u files\n", + tprintf("Established %u versions across %u directories and %u files\n", changes->version + 1, nextdirnum, nextfilenum); /* @@ -2821,7 +2821,7 @@ checkfs(void) * FOUND holding the found volume state. */ inspectfs(); - printf("Found %u subdirs and %u files on the volume\n", + tprintf("Found %u subdirs and %u files on the volume\n", found_subdirs, found_files); /* @@ -2856,7 +2856,7 @@ checkfs(void) best = change; bestscore = score; } - //printf("version %u score %u\n", change->version, score); + //tprintf("version %u score %u\n", change->version, score); change = change->next; } assert(best != NULL); @@ -2874,9 +2874,9 @@ checkfs(void) * differences. XXX: this results in not checking file * data... */ - printf("FAILURE: Directory tree does not match on any " + tprintf("FAILURE: Directory tree does not match on any " "version.\n"); - printf("Best version is %u; describing differences:\n", + tprintf("Best version is %u; describing differences:\n", best->version); printdiffs(1, state, found); return; @@ -2886,9 +2886,9 @@ checkfs(void) * Ok, we did get an exact match. Print it. */ - printf("Directory tree matched in version %u.\n", best->version); + tprintf("Directory tree matched in version %u.\n", best->version); if (best->partial) { - printf("WARNING: this is a version from a partially committed " + tprintf("WARNING: this is a version from a partially committed " "operation.\n"); } @@ -2905,7 +2905,7 @@ checkfs(void) /* now check the file contents */ - printf("Checking file contents...\n"); + tprintf("Checking file contents...\n"); checkallfilecontents(state, best); - printf("Done.\n"); + tprintf("Done.\n"); } diff --git a/userland/testbin/frack/data.c b/userland/testbin/frack/data.c index dbaa26f..a4563dc 100644 --- a/userland/testbin/frack/data.c +++ b/userland/testbin/frack/data.c @@ -165,7 +165,7 @@ data_matches(const char *namestr, off_t regionoffset, } else if (zero_at(where, howmuch)) { if (where >= zerostart) { - printf("WARNING: file %s range %lld-%lld is " + tprintf("WARNING: file %s range %lld-%lld is " "zeroed\n", namestr, regionoffset + where, regionoffset + where + howmuch); @@ -176,7 +176,7 @@ data_matches(const char *namestr, off_t regionoffset, } else if (poison_at(where, howmuch)) { if (where >= zerostart) { - printf("ERROR: file %s range %lld-%lld is " + tprintf("ERROR: file %s range %lld-%lld is " "poisoned\n", namestr, regionoffset + where, regionoffset + where + howmuch); @@ -205,7 +205,7 @@ data_check(const char *namestr, off_t regionoffset, if (!data_matches(namestr, regionoffset, code, seq, zerostart, len, checkstart, checklen)) { - printf("ERROR: file %s range %lld-%lld contains garbage\n", + tprintf("ERROR: file %s range %lld-%lld contains garbage\n", namestr, regionoffset + checkstart, regionoffset + checkstart + checklen); } diff --git a/userland/testbin/frack/do.c b/userland/testbin/frack/do.c index 059cf2c..3533113 100644 --- a/userland/testbin/frack/do.c +++ b/userland/testbin/frack/do.c @@ -72,7 +72,7 @@ do_createfile(unsigned name) if (fd < 0) { err(1, "%s: create", namestr); } - printf("create %s\n", namestr); + tprintf("create %s\n", namestr); return fd; } @@ -122,7 +122,7 @@ do_write(int fd, unsigned name, unsigned code, unsigned seq, done += ret; } - printf("write %s: %lld at %lld\n", namestr, len, pos); + tprintf("write %s: %lld at %lld\n", namestr, len, pos); } void @@ -134,7 +134,7 @@ do_truncate(int fd, unsigned name, off_t len) if (ftruncate(fd, len) == -1) { err(1, "%s: truncate to %lld", namestr, len); } - printf("truncate %s: to %lld\n", namestr, len); + tprintf("truncate %s: to %lld\n", namestr, len); } void @@ -146,7 +146,7 @@ do_mkdir(unsigned name) if (mkdir(namestr, 0775) == -1) { err(1, "%s: mkdir", namestr); } - printf("mkdir %s\n", namestr); + tprintf("mkdir %s\n", namestr); } void @@ -158,7 +158,7 @@ do_rmdir(unsigned name) if (rmdir(namestr) == -1) { err(1, "%s: rmdir", namestr); } - printf("rmdir %s\n", namestr); + tprintf("rmdir %s\n", namestr); } void @@ -170,7 +170,7 @@ do_unlink(unsigned name) if (remove(namestr) == -1) { err(1, "%s: remove", namestr); } - printf("remove %s\n", namestr); + tprintf("remove %s\n", namestr); } void @@ -183,7 +183,7 @@ do_link(unsigned from, unsigned to) if (link(fromstr, tostr) == -1) { err(1, "link %s to %s", fromstr, tostr); } - printf("link %s %s\n", fromstr, tostr); + tprintf("link %s %s\n", fromstr, tostr); } void @@ -196,7 +196,7 @@ do_rename(unsigned from, unsigned to) if (rename(fromstr, tostr) == -1) { err(1, "rename %s to %s", fromstr, tostr); } - printf("rename %s %s\n", fromstr, tostr); + tprintf("rename %s %s\n", fromstr, tostr); } void @@ -216,7 +216,7 @@ do_renamexd(unsigned fromdir, unsigned from, unsigned todir, unsigned to) if (rename(frombuf, tobuf) == -1) { err(1, "rename %s to %s", frombuf, tobuf); } - printf("rename %s %s\n", frombuf, tobuf); + tprintf("rename %s %s\n", frombuf, tobuf); } void @@ -228,7 +228,7 @@ do_chdir(unsigned name) if (chdir(namestr) == -1) { err(1, "chdir: %s", namestr); } - printf("chdir %s\n", namestr); + tprintf("chdir %s\n", namestr); } void @@ -237,7 +237,7 @@ do_chdirup(void) if (chdir("..") == -1) { err(1, "chdir: .."); } - printf("chdir ..\n"); + tprintf("chdir ..\n"); } void @@ -246,6 +246,6 @@ do_sync(void) if (sync()) { warn("sync"); } - printf("sync\n"); - printf("----------------------------------------\n"); + tprintf("sync\n"); + tprintf("----------------------------------------\n"); } diff --git a/userland/testbin/frack/main.c b/userland/testbin/frack/main.c index 1a0c7e8..776379d 100644 --- a/userland/testbin/frack/main.c +++ b/userland/testbin/frack/main.c @@ -132,13 +132,13 @@ printworkloads(void) { unsigned i; - printf("Supported workloads:\n"); + tprintf("Supported workloads:\n"); for (i=0; i #include +#include +#include #define PageSize 4096 #define NumPages 512 int sparse[NumPages][PageSize]; /* use only the first element in the row */ +#define PROGRESS_INTERVAL 20 + int main(void) { int i,j; - printf("Entering the huge program - I will stress test your VM\n"); + tprintf("Entering the huge program - I will stress test your VM\n"); /* move number in so that sparse[i][0]=i */ for (i=0; i=0; i--) { + TEST161_LPROGRESS_N(i, PROGRESS_INTERVAL); if (sparse[i][0]!=i+5) { - printf("BAD NEWS!!! - your VM mechanism has a bug!\n"); + lsay("BAD NEWS!!! - your VM mechanism has a bug!\n"); + success(TEST161_FAIL, SECRET, "/testbin/huge"); exit(1); } } - printf("You passed!\n"); + success(TEST161_SUCCESS, SECRET, "/testbin/huge"); return 0; } diff --git a/userland/testbin/malloctest/malloctest.c b/userland/testbin/malloctest/malloctest.c index 5f3d4bf..ec81053 100644 --- a/userland/testbin/malloctest/malloctest.c +++ b/userland/testbin/malloctest/malloctest.c @@ -77,7 +77,7 @@ geti(void) break; } else if ((ch=='\b' || ch==127) && digits>0) { - printf("\b \b"); + tprintf("\b \b"); val = val/10; digits--; } @@ -117,11 +117,11 @@ markblock(volatile void *ptr, size_t size, unsigned bias, int doprint) val = ((unsigned long)i ^ (unsigned long)bias); pl[i] = val; if (doprint && (i%64==63)) { - printf("."); + tprintf("."); } } if (doprint) { - printf("\n"); + tprintf("\n"); } } @@ -143,9 +143,9 @@ checkblock(volatile void *ptr, size_t size, unsigned bias, int doprint) val = ((unsigned long)i ^ (unsigned long)bias); if (pl[i] != val) { if (doprint) { - printf("\n"); + tprintf("\n"); } - printf("FAILED: data mismatch at offset %lu of block " + tprintf("FAILED: data mismatch at offset %lu of block " "at 0x%lx: %lu vs. %lu\n", (unsigned long) (i*sizeof(unsigned long)), (unsigned long)(uintptr_t)pl, @@ -153,11 +153,11 @@ checkblock(volatile void *ptr, size_t size, unsigned bias, int doprint) return -1; } if (doprint && (i%64==63)) { - printf("."); + tprintf("."); } } if (doprint) { - printf("\n"); + tprintf("\n"); } return 0; @@ -178,23 +178,23 @@ test1(void) { volatile unsigned *x; - printf("*** Malloc test 1 ***\n"); - printf("Allocating %u bytes\n", BIGSIZE); + tprintf("*** Malloc test 1 ***\n"); + tprintf("Allocating %u bytes\n", BIGSIZE); x = malloc(BIGSIZE); if (x==NULL) { - printf("FAILED: malloc failed\n"); + tprintf("FAILED: malloc failed\n"); return; } markblock(x, BIGSIZE, 0, 0); if (checkblock(x, BIGSIZE, 0, 0)) { - printf("FAILED: data corrupt\n"); + tprintf("FAILED: data corrupt\n"); return; } free((void *)x); - printf("Passed malloc test 1.\n"); + tprintf("Passed malloc test 1.\n"); } @@ -237,43 +237,43 @@ test2(void) volatile unsigned *x; size_t size; - printf("Entering malloc test 2.\n"); - printf("Make sure you read and understand the comment in malloctest.c " + tprintf("Entering malloc test 2.\n"); + tprintf("Make sure you read and understand the comment in malloctest.c " "that\nexplains the conditions this test assumes.\n\n"); - printf("Testing how much memory we can allocate:\n"); + tprintf("Testing how much memory we can allocate:\n"); for (size = HUGESIZE; (x = malloc(size))==NULL; size = size/2) { - printf(" %9lu bytes: failed\n", (unsigned long) size); + tprintf(" %9lu bytes: failed\n", (unsigned long) size); } - printf(" %9lu bytes: succeeded\n", (unsigned long) size); + tprintf(" %9lu bytes: succeeded\n", (unsigned long) size); - printf("Passed part 1\n"); + tprintf("Passed part 1\n"); - printf("Touching all the words in the block.\n"); + tprintf("Touching all the words in the block.\n"); markblock(x, size, 0, 1); - printf("Validating the words in the block.\n"); + tprintf("Validating the words in the block.\n"); if (checkblock(x, size, 0, 1)) { - printf("FAILED: data corrupt\n"); + tprintf("FAILED: data corrupt\n"); return; } - printf("Passed part 2\n"); + tprintf("Passed part 2\n"); - printf("Freeing the block\n"); + tprintf("Freeing the block\n"); free((void *)x); - printf("Passed part 3\n"); - printf("Allocating another block\n"); + tprintf("Passed part 3\n"); + tprintf("Allocating another block\n"); x = malloc(size); if (x==NULL) { - printf("FAILED: free didn't return the memory?\n"); + tprintf("FAILED: free didn't return the memory?\n"); return; } free((void *)x); - printf("Passed malloc test 2.\n"); + tprintf("Passed malloc test 2.\n"); } @@ -304,11 +304,11 @@ test3(void) int ct=0, failed=0; void *x; - printf("Entering malloc test 3.\n"); - printf("Make sure you read and understand the comment in malloctest.c " + tprintf("Entering malloc test 3.\n"); + tprintf("Make sure you read and understand the comment in malloctest.c " "that\nexplains the conditions this test assumes.\n\n"); - printf("Testing how much memory we can allocate:\n"); + tprintf("Testing how much memory we can allocate:\n"); while ((tmp = malloc(sizeof(struct test3))) != NULL) { @@ -322,33 +322,33 @@ test3(void) ct++; if (ct%128==0) { - printf("."); + tprintf("."); } } - printf("Allocated %lu bytes\n", (unsigned long) tot); + tprintf("Allocated %lu bytes\n", (unsigned long) tot); - printf("Trying some more allocations which I expect to fail...\n"); + tprintf("Trying some more allocations which I expect to fail...\n"); x = malloc(SMALLSIZE); if (x != NULL) { - printf("FAILED: malloc(%u) succeeded\n", SMALLSIZE); + tprintf("FAILED: malloc(%u) succeeded\n", SMALLSIZE); return; } x = malloc(MEDIUMSIZE); if (x != NULL) { - printf("FAILED: malloc(%u) succeeded\n", MEDIUMSIZE); + tprintf("FAILED: malloc(%u) succeeded\n", MEDIUMSIZE); return; } x = malloc(BIGSIZE); if (x != NULL) { - printf("FAILED: malloc(%u) succeeded\n", BIGSIZE); + tprintf("FAILED: malloc(%u) succeeded\n", BIGSIZE); return; } - printf("Ok, now I'm going to free everything...\n"); + tprintf("Ok, now I'm going to free everything...\n"); while (list != NULL) { tmp = list->next; @@ -363,20 +363,20 @@ test3(void) } if (failed) { - printf("FAILED: data corruption\n"); + tprintf("FAILED: data corruption\n"); return; } - printf("Let me see if I can allocate some more now...\n"); + tprintf("Let me see if I can allocate some more now...\n"); x = malloc(MEDIUMSIZE); if (x == NULL) { - printf("FAIL: Nope, I couldn't.\n"); + tprintf("FAIL: Nope, I couldn't.\n"); return; } free(x); - printf("Passed malloc test 3\n"); + tprintf("Passed malloc test 3\n"); } //////////////////////////////////////////////////////////// @@ -397,34 +397,34 @@ test4(void) void *x, *y, *z; unsigned long lx, ly, lz, overhead, zsize; - printf("Entering malloc test 4.\n"); - printf("This test is intended for first/best-fit based mallocs.\n"); - printf("This test may not work correctly if run after other tests.\n"); + tprintf("Entering malloc test 4.\n"); + tprintf("This test is intended for first/best-fit based mallocs.\n"); + tprintf("This test may not work correctly if run after other tests.\n"); - printf("Testing free list coalescing:\n"); + tprintf("Testing free list coalescing:\n"); x = malloc(SMALLSIZE); if (x==NULL) { - printf("FAILED: malloc(%u) failed\n", SMALLSIZE); + tprintf("FAILED: malloc(%u) failed\n", SMALLSIZE); return; } y = malloc(MEDIUMSIZE); if (y==NULL) { - printf("FAILED: malloc(%u) failed\n", MEDIUMSIZE); + tprintf("FAILED: malloc(%u) failed\n", MEDIUMSIZE); return; } if (sizeof(unsigned long) < sizeof(void *)) { - printf("Buh? I can't fit a void * in an unsigned long\n"); - printf("ENVIRONMENT FAILED...\n"); + tprintf("Buh? I can't fit a void * in an unsigned long\n"); + tprintf("ENVIRONMENT FAILED...\n"); return; } lx = (unsigned long)x; ly = (unsigned long)y; - printf("x is 0x%lx; y is 0x%lx\n", lx, ly); + tprintf("x is 0x%lx; y is 0x%lx\n", lx, ly); /* * The memory should look something like this: @@ -436,7 +436,7 @@ test4(void) /* This is obviously wrong. */ if (lx == ly) { - printf("FAIL: x == y\n"); + tprintf("FAIL: x == y\n"); return; } @@ -447,11 +447,11 @@ test4(void) * or the other block's start is within the first block.) */ if (lx < ly && lx + SMALLSIZE > ly) { - printf("FAIL: y starts within x\n"); + tprintf("FAIL: y starts within x\n"); return; } if (ly < lx && ly + MEDIUMSIZE > lx) { - printf("FAIL: x starts within y\n"); + tprintf("FAIL: x starts within y\n"); return; } @@ -461,7 +461,7 @@ test4(void) * free list. */ if (ly < lx) { - printf("TEST UNSUITABLE: y is below x\n"); + tprintf("TEST UNSUITABLE: y is below x\n"); return; } @@ -469,39 +469,39 @@ test4(void) * Compute the space used by index structures. */ overhead = ly - (lx + SMALLSIZE); - printf("Apparent block overhead: %lu\n", overhead); + tprintf("Apparent block overhead: %lu\n", overhead); if (overhead > ABSURD_OVERHEAD) { - printf("TEST UNSUITABLE: block overhead absurdly large.\n"); + tprintf("TEST UNSUITABLE: block overhead absurdly large.\n"); return; } if (overhead > OVERHEAD) { - printf("FAIL: block overhead is too large.\n"); + tprintf("FAIL: block overhead is too large.\n"); return; } - printf("Freeing blocks...\n"); + tprintf("Freeing blocks...\n"); free(x); free(y); zsize = SMALLSIZE + MEDIUMSIZE + overhead; - printf("Now allocating %lu bytes... should reuse the space.\n", zsize); + tprintf("Now allocating %lu bytes... should reuse the space.\n", zsize); z = malloc(zsize); if (z == NULL) { - printf("FAIL: Allocation failed...\n"); + tprintf("FAIL: Allocation failed...\n"); return; } lz = (unsigned long) z; - printf("z is 0x%lx (x was 0x%lx, y 0x%lx)\n", lz, lx, ly); + tprintf("z is 0x%lx (x was 0x%lx, y 0x%lx)\n", lz, lx, ly); if (lz==lx) { - printf("Passed.\n"); + tprintf("Passed.\n"); } else { - printf("Failed.\n"); + tprintf("Failed.\n"); } free(z); @@ -530,7 +530,7 @@ test567(int testno, unsigned long seed) int i, n, size, failed=0; srandom(seed); - printf("Seeded random number generator with %lu.\n", seed); + tprintf("Seeded random number generator with %lu.\n", seed); for (i=0; i<32; i++) { ptrs[i] = NULL; @@ -544,7 +544,7 @@ test567(int testno, unsigned long seed) ptrs[n] = malloc(size); psizes[n] = size; if (ptrs[n] == NULL) { - printf("\nmalloc %u failed\n", size); + tprintf("\nmalloc %u failed\n", size); failed = 1; break; } @@ -561,10 +561,10 @@ test567(int testno, unsigned long seed) psizes[n] = 0; } if (i%256==0) { - printf("."); + tprintf("."); } } - printf("\n"); + tprintf("\n"); for (i=0; i<32; i++) { if (ptrs[i] != NULL) { @@ -573,10 +573,10 @@ test567(int testno, unsigned long seed) } if (failed) { - printf("FAILED malloc test %d\n", testno); + tprintf("FAILED malloc test %d\n", testno); } else { - printf("Passed malloc test %d\n", testno); + tprintf("Passed malloc test %d\n", testno); } } @@ -584,7 +584,7 @@ static void test5(void) { - printf("Beginning malloc test 5\n"); + tprintf("Beginning malloc test 5\n"); test567(5, 0); } @@ -595,7 +595,7 @@ test6(void) int fd, len; unsigned long seed; - printf("Beginning malloc test 6\n"); + tprintf("Beginning malloc test 6\n"); fd = open(_PATH_RANDOM, O_RDONLY); if (fd < 0) { @@ -619,9 +619,9 @@ test7(void) { unsigned long seed; - printf("Beginning malloc test 7\n"); + tprintf("Beginning malloc test 7\n"); - printf("Enter random seed: "); + tprintf("Enter random seed: "); seed = geti(); test567(7, seed); @@ -673,12 +673,12 @@ main(int argc, char *argv[]) while (1) { if (menu) { for (i=0; tests[i].num>=0; i++) { - printf(" %2d %s\n", tests[i].num, + tprintf(" %2d %s\n", tests[i].num, tests[i].desc); } menu = 0; } - printf("malloctest: "); + tprintf("malloctest: "); tn = geti(); if (tn < 0) { break; diff --git a/userland/testbin/matmult/matmult-orig.c b/userland/testbin/matmult/matmult-orig.c index b707347..e9632ff 100644 --- a/userland/testbin/matmult/matmult-orig.c +++ b/userland/testbin/matmult/matmult-orig.c @@ -75,14 +75,14 @@ main(void) for (k = 0; k < Dim; k++) C[i][j] += A[i][k] * B[k][j]; - printf("matmult-orig finished.\n"); + tprintf("matmult-orig finished.\n"); r = C[Dim-1][Dim-1]; - printf("answer is: %d (should be %d)\n", r, RIGHT); + tprintf("answer is: %d (should be %d)\n", r, RIGHT); if (r != RIGHT) { - printf("FAILED\n"); + tprintf("FAILED\n"); } else { - printf("Passed.\n"); + tprintf("Passed.\n"); } return 0; } diff --git a/userland/testbin/matmult/matmult.c b/userland/testbin/matmult/matmult.c index 6dd99a3..7dabbd1 100644 --- a/userland/testbin/matmult/matmult.c +++ b/userland/testbin/matmult/matmult.c @@ -41,6 +41,7 @@ #include #include +#include #define Dim 72 /* sum total of the arrays doesn't fit in * physical memory @@ -58,33 +59,49 @@ main(void) { int i, j, k, r; - for (i = 0; i < Dim; i++) /* first initialize the matrices */ - for (j = 0; j < Dim; j++) { - A[i][j] = i; - B[i][j] = j; - C[i][j] = 0; + for (i = 0; i < Dim; i++) { /* first initialize the matrices */ + for (j = 0; j < Dim; j++) { + TEST161_LPROGRESS_N(i*Dim + j, 1000); + A[i][j] = i; + B[i][j] = j; + C[i][j] = 0; + } } + nprintf("\n"); - for (i = 0; i < Dim; i++) /* then multiply them together */ - for (j = 0; j < Dim; j++) - for (k = 0; k < Dim; k++) - T[i][j][k] = A[i][k] * B[k][j]; + for (i = 0; i < Dim; i++) { /* then multiply them together */ + for (j = 0; j < Dim; j++) { + for (k = 0; k < Dim; k++) { + TEST161_LPROGRESS_N(i*j*Dim*Dim + k, 50000); + T[i][j][k] = A[i][k] * B[k][j]; + } + } + } + nprintf("\n"); - for (i = 0; i < Dim; i++) - for (j = 0; j < Dim; j++) - for (k = 0; k < Dim; k++) - C[i][j] += T[i][j][k]; + for (i = 0; i < Dim; i++) { + for (j = 0; j < Dim; j++) { + for (k = 0; k < Dim; k++) { + TEST161_LPROGRESS_N(i*j*Dim*Dim + k, 50000); + C[i][j] += T[i][j][k]; + } + } + } + nprintf("\n"); r = 0; for (i = 0; i < Dim; i++) r += C[i][i]; - printf("matmult finished.\n"); - printf("answer is: %d (should be %d)\n", r, RIGHT); + nprintf("matmult finished.\n"); + nprintf("answer is: %d (should be %d)\n", r, RIGHT); if (r != RIGHT) { - printf("FAILED\n"); + nprintf("FAILED\n"); + success(TEST161_FAIL, SECRET, "/testbin/matmult"); return 1; } - printf("Passed.\n"); + + nprintf("Passed.\n"); + success(TEST161_SUCCESS, SECRET, "/testbin/matmult"); return 0; } diff --git a/userland/testbin/multiexec/multiexec.c b/userland/testbin/multiexec/multiexec.c index a7d41c9..cdd1854 100644 --- a/userland/testbin/multiexec/multiexec.c +++ b/userland/testbin/multiexec/multiexec.c @@ -169,16 +169,13 @@ spawn(int njobs) semcreate("1", &s1); semcreate("2", &s2); - printf("Forking %d child processes...\n", njobs); + tprintf("Forking %d child processes...\n", njobs); for (i=0; i #include +#include char palindrome[8000] = "amanaplanacaretabanamyriadasumalacaliarahoopapintacatalpaagasanoil" @@ -175,24 +176,24 @@ main(void) { char *start, *end; - printf("Welcome to the palindrome tester!\n"); - printf("I will take a large palindrome and test it.\n"); - printf("Here it is:\n"); - printf("%s\n", palindrome); + tprintf("Welcome to the palindrome tester!\n"); + tprintf("I will take a large palindrome and test it.\n"); + tprintf("Here it is:\n"); + tprintf("%s\n", palindrome); - printf("Testing..."); + tprintf("Testing..."); /* skip to end */ end = palindrome+strlen(palindrome); end--; for (start = palindrome; start <= end; start++, end--) { - putchar('.'); if (*start != *end) { - printf("NOT a palindrome\n"); + success(TEST161_FAIL, SECRET, "/testbin/palin"); + tprintf("NOT a palindrome\n"); return 0; } } - - printf("IS a palindrome\n"); + tprintf("IS a palindrome\n"); + success(TEST161_SUCCESS, SECRET, "/testbin/palin"); return 0; } diff --git a/userland/testbin/parallelvm/parallelvm.c b/userland/testbin/parallelvm/parallelvm.c index a213197..31b2e58 100644 --- a/userland/testbin/parallelvm/parallelvm.c +++ b/userland/testbin/parallelvm/parallelvm.c @@ -45,6 +45,8 @@ #include #include #include +#include +#include #define NJOBS 24 @@ -52,6 +54,8 @@ #define NMATS 11 #define JOBSIZE ((NMATS+1)*DIM*DIM*sizeof(int)) +#define PROGRESS_INTERVAL 25000 + static const int right_answers[NJOBS] = { -1337312809, 356204544, @@ -87,35 +91,20 @@ struct matrix { //////////////////////////////////////////////////////////// -/* - * Use this instead of just calling printf so we know each printout - * is atomic; this prevents the lines from getting intermingled. - */ -static -void -say(const char *fmt, ...) -{ - char buf[256]; - va_list ap; - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - write(STDOUT_FILENO, buf, strlen(buf)); -} - -//////////////////////////////////////////////////////////// - static void multiply(struct matrix *res, const struct matrix *m1, const struct matrix *m2) { - int i, j, k; + int i, j, k, tot; + tot = 0; for (i=0; im_data[i][k]*m2->m_data[k][j]; + TEST161_LPROGRESS_N(tot, PROGRESS_INTERVAL); + tot++; } res->m_data[i][j] = val; } @@ -201,18 +190,19 @@ go(int mynum) { int r; - say("Process %d (pid %d) starting computation...\n", mynum, + lsay("Process %d (pid %d) starting computation...\n", mynum, (int) getpid()); - computeall(mynum); r = answer(); if (r != right_answers[mynum]) { - say("Process %d answer %d: FAILED, should be %d\n", + tsay("Process %d answer %d: FAILED, should be %d\n", mynum, r, right_answers[mynum]); + success(TEST161_FAIL, SECRET, "/testbin/parallelvm"); exit(1); } - say("Process %d answer %d: passed\n", mynum, r); + + lsay("\nProcess %d: OK\n", mynum, r); exit(0); } @@ -329,8 +319,8 @@ makeprocs(bool dowait) semcreate("2", &s2); } - printf("Job size approximately %lu bytes\n", (unsigned long) JOBSIZE); - printf("Forking %d jobs; total load %luk\n", NJOBS, + tprintf("Job size approximately %lu bytes\n", (unsigned long) JOBSIZE); + tprintf("Forking %d jobs; total load %luk\n", NJOBS, (unsigned long) (NJOBS * JOBSIZE)/1024); for (i=0; i\n"; printf "#include \n"; printf "#include \n"; + printf "#include \n"; printf "\n"; printf "#include \"extern.h\"\n"; printf "\n"; @@ -67,7 +68,7 @@ awk < $1 ' if (i #include #include +#include #include "extern.h" @@ -113,10 +114,10 @@ static void usage(void) { - printf("Usage: randcall [-f] [-c count] [-r seed] 2|3|4|all\n"); - printf(" -f suppress forking\n"); - printf(" -c set iteration count (default 100)\n"); - printf(" -r set pseudorandom seed (default 0)\n"); + tprintf("Usage: randcall [-f] [-c count] [-r seed] 2|3|4|all\n"); + tprintf(" -f suppress forking\n"); + tprintf(" -c set iteration count (default 100)\n"); + tprintf(" -r set pseudorandom seed (default 0)\n"); exit(1); } @@ -157,10 +158,11 @@ main(int argc, char *argv[]) } } - printf("Seed: %d Count: %d\n", seed, count); + tprintf("Seed: %d Count: %d\n", seed, count); srandom(seed); trycalls(an, dofork, count); + success(TEST161_SUCCESS, SECRET, "/testbin/randcall"); return 0; } diff --git a/userland/testbin/redirect/redirect.c b/userland/testbin/redirect/redirect.c index cca3f49..544308b 100644 --- a/userland/testbin/redirect/redirect.c +++ b/userland/testbin/redirect/redirect.c @@ -43,6 +43,7 @@ #include #include #include +#include #define PATH_CAT "/bin/cat" #define INFILE "redirect.in" @@ -181,16 +182,23 @@ cat(void) int main(void) { - printf("Creating %s...\n", INFILE); + tprintf("Creating %s...\n", INFILE); mkfile(); + nprintf("."); - printf("Running cat < %s > %s\n", INFILE, OUTFILE); + tprintf("Running cat < %s > %s\n", INFILE, OUTFILE); cat(); + nprintf("."); - printf("Checking %s...\n", OUTFILE); + tprintf("Checking %s...\n", OUTFILE); chkfile(); + nprintf("."); - printf("Passed.\n"); + tprintf("Passed.\n"); + nprintf("."); + nprintf("\n"); + + success(TEST161_SUCCESS, SECRET, "/testbin/redirect"); (void)remove(INFILE); (void)remove(OUTFILE); return 0; diff --git a/userland/testbin/rmdirtest/rmdirtest.c b/userland/testbin/rmdirtest/rmdirtest.c index a244f67..82325aa 100644 --- a/userland/testbin/rmdirtest/rmdirtest.c +++ b/userland/testbin/rmdirtest/rmdirtest.c @@ -116,13 +116,13 @@ static void test1(void) { - printf("Making %s\n", testdir); + tprintf("Making %s\n", testdir); startup(); - printf("Removing %s while in it\n", testdir); + tprintf("Removing %s while in it\n", testdir); killdir(); - printf("Leaving the test directory\n"); + tprintf("Leaving the test directory\n"); finish(); } @@ -136,7 +136,7 @@ test2(void) { int fd; - printf("Now trying with the directory open...\n"); + tprintf("Now trying with the directory open...\n"); startup(); fd = open(".", O_RDONLY); if (fd<0) { @@ -162,7 +162,7 @@ test3(void) char buf[PATH_MAX]; int fd; - printf("Checking if . exists after rmdir\n"); + tprintf("Checking if . exists after rmdir\n"); startup(); killdir(); @@ -230,7 +230,7 @@ test4(void) char buf[4096]; int fd; - printf("Checking if creating files works after rmdir...\n"); + tprintf("Checking if creating files works after rmdir...\n"); startup(); killdir(); @@ -272,7 +272,7 @@ static void test5(void) { - printf("Checking if creating subdirs works after rmdir...\n"); + tprintf("Checking if creating subdirs works after rmdir...\n"); startup(); killdir(); @@ -315,7 +315,7 @@ test6(void) char buf[PATH_MAX]; int fd, len; - printf("Now trying to list the directory...\n"); + tprintf("Now trying to list the directory...\n"); startup(); fd = open(".", O_RDONLY); if (fd<0) { @@ -399,6 +399,6 @@ main(void) test6(); test7(); - printf("Whew... survived.\n"); + tprintf("Whew... survived.\n"); return 0; } diff --git a/userland/testbin/rmtest/rmtest.c b/userland/testbin/rmtest/rmtest.c index 376236c..c57d32c 100644 --- a/userland/testbin/rmtest/rmtest.c +++ b/userland/testbin/rmtest/rmtest.c @@ -157,7 +157,7 @@ main(void) err(1, "Unexpected error reopening the file"); } - printf("Succeeded!\n"); + tprintf("Succeeded!\n"); return 0; } diff --git a/userland/testbin/sbrktest/sbrktest.c b/userland/testbin/sbrktest/sbrktest.c index b4a626b..da65a00 100644 --- a/userland/testbin/sbrktest/sbrktest.c +++ b/userland/testbin/sbrktest/sbrktest.c @@ -35,6 +35,7 @@ #include #include #include +#include #define _PATH_RANDOM "random:" @@ -62,7 +63,7 @@ geti(void) break; } else if ((ch=='\b' || ch==127) && digits>0) { - printf("\b \b"); + tprintf("\b \b"); val = val/10; digits--; } @@ -141,7 +142,7 @@ static void say(const char *msg) { - /* Use one write so it's atomic (printf usually won't be) */ + /* Use one write so it's atomic (tprintf usually won't be) */ write(STDOUT_FILENO, msg, strlen(msg)); } @@ -194,9 +195,9 @@ checkpage(volatile void *baseptr, unsigned pageoffset, bool neednl) val = ((unsigned long)i ^ (unsigned long)pageoffset); if (pl[i] != val) { if (neednl) { - printf("\n"); + tprintf("\n"); } - printf("FAILED: data mismatch at offset %lu of page " + tprintf("FAILED: data mismatch at offset %lu of page " "at 0x%lx: %lu vs. %lu\n", (unsigned long) (i*sizeof(unsigned long)), (unsigned long)(uintptr_t)pl, @@ -241,9 +242,9 @@ checkpagelight(volatile void *baseptr, unsigned pageoffset, bool neednl) pl = (volatile unsigned long *)pageptr; if (pl[0] != pageoffset) { if (neednl) { - printf("\n"); + tprintf("\n"); } - printf("FAILED: data mismatch at offset 0 of page " + tprintf("FAILED: data mismatch at offset 0 of page " "at 0x%lx: %lu vs. %u\n", (unsigned long)(uintptr_t)pl, pl[0], pageoffset); @@ -271,6 +272,37 @@ dosbrk(ssize_t size) return p; } +//////////////////////////////////////////////////////////// +// fork a child that segfaults + +typedef void (*segfault_fn)(void); + +static +void +expect_segfault(segfault_fn func) +{ + int status; + int result; + pid_t pid = dofork(); + + if (pid == 0) { + func(); // This exits + } else { + result = waitpid(pid, &status, 0); + if (result == -1) { + err(1, "waitpid"); + } + else if (WIFSIGNALED(status)) { + if (WTERMSIG(status) != 11) { + errx(1, "child: Signal %d", WTERMSIG(status)); + } + } + else { + errx(1, "child exited, expected segfault"); + } + } +} + //////////////////////////////////////////////////////////// // align the heap @@ -317,14 +349,13 @@ test1(void) { void *p; - printf("Allocating a page...\n"); + tprintf("Allocating a page...\n"); p = dosbrk(PAGE_SIZE); markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt"); } - - printf("Passed sbrk test 1.\n"); + success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); } /* @@ -338,7 +369,7 @@ test2(void) op = dosbrk(0); - printf("Allocating a page...\n"); + tprintf("Allocating a page...\n"); p = dosbrk(PAGE_SIZE); if (p != op) { errx(1, "FAILED: sbrk grow didn't return the old break " @@ -351,7 +382,7 @@ test2(void) p = dosbrk(0); - printf("Freeing the page...\n"); + tprintf("Freeing the page...\n"); q = dosbrk(-PAGE_SIZE); if (q != p) { errx(1, "FAILED: sbrk shrink didn't return the old break " @@ -362,8 +393,7 @@ test2(void) errx(1, "FAILED: sbrk shrink didn't restore the heap " "(got %p, expected %p", q, op); } - - printf("Passed sbrk test 2.\n"); + success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); } /* @@ -382,7 +412,7 @@ test3(void) op = dosbrk(0); - printf("Allocating %u pages...\n", num); + tprintf("Allocating %u pages...\n", num); p = dosbrk(PAGE_SIZE * num); if (p != op) { errx(1, "FAILED: sbrk grow didn't return the old break " @@ -403,7 +433,7 @@ test3(void) p = dosbrk(0); - printf("Freeing the pages...\n"); + tprintf("Freeing the pages...\n"); q = dosbrk(-PAGE_SIZE * num); if (q != p) { errx(1, "FAILED: sbrk shrink didn't return the old break " @@ -414,8 +444,7 @@ test3(void) errx(1, "FAILED: sbrk shrink didn't restore the heap " "(got %p, expected %p", q, op); } - - printf("Passed sbrk test 3.\n"); + success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); } /* @@ -435,7 +464,7 @@ test4(void) op = dosbrk(0); - printf("Allocating %u pages...\n", num); + tprintf("Allocating %u pages...\n", num); p = dosbrk(PAGE_SIZE * num); if (p != op) { errx(1, "FAILED: sbrk grow didn't return the old break " @@ -454,7 +483,7 @@ test4(void) exit(1); } - printf("Freeing the pages one at a time...\n"); + tprintf("Freeing the pages one at a time...\n"); for (i=num; i-- > 0; ) { (void)dosbrk(-PAGE_SIZE); for (j=0; j 0 && i % dot == 0) { - printf("."); + if (dot > 0) { + TEST161_LPROGRESS_N(i, dot); } } if (dot > 0) { printf("\n"); } - printf("Testing each page.\n"); + tprintf("Testing each page.\n"); bad = false; for (i=0; i 0)) { if (dot > 0) { - printf("\n"); + tprintf("\n"); } warnx("FAILED: data corrupt"); bad = true; } - if (dot > 0 && i % dot == 0) { - printf("."); + if (dot > 0) { + TEST161_LPROGRESS_N(i, dot); } } if (dot > 0) { @@ -628,19 +688,20 @@ test9(void) if (bad) { exit(1); } - printf("Passed sbrk test 9 (part 2/5)\n"); + tprintf("Passed sbrk test 9 (part 2/5)\n"); - printf("Freeing the memory.\n"); + tprintf("Freeing the memory.\n"); (void)dosbrk(-size); - printf("Passed sbrk test 9 (part 3/5)\n"); + tprintf("Passed sbrk test 9 (part 3/5)\n"); - printf("Allocating the memory again.\n"); + tprintf("Allocating the memory again.\n"); (void)dosbrk(size); - printf("Passed sbrk test 9 (part 4/5)\n"); + tprintf("Passed sbrk test 9 (part 4/5)\n"); - printf("And really freeing it.\n"); + tprintf("And really freeing it.\n"); (void)dosbrk(-size); - printf("Passed sbrk test 9 (all)\n"); + tprintf("Passed sbrk test 9 (all)\n"); + success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); } /* @@ -655,16 +716,16 @@ test10(void) unsigned i, n; bool bad; - printf("Allocating all of memory one page at a time:\n"); + tprintf("Allocating all of memory one page at a time:\n"); op = dosbrk(0); n = 0; while ((p = sbrk(PAGE_SIZE)) != (void *)-1) { markpagelight(op, n); n++; } - printf("Got %u pages (%zu bytes).\n", n, (size_t)PAGE_SIZE * n); + tprintf("Got %u pages (%zu bytes).\n", n, (size_t)PAGE_SIZE * n); - printf("Now freeing them.\n"); + tprintf("Now freeing them.\n"); bad = false; for (i=0; i 0) { calcresult(0, startsecs, startnsecs, buf, sizeof(buf)); - printf("Thinkers: %s\n", buf); + tprintf("Thinkers: %s\n", buf); } if (numgrinders > 0) { calcresult(1, startsecs, startnsecs, buf, sizeof(buf)); - printf("Grinders: %s\n", buf); + tprintf("Grinders: %s\n", buf); } for (i=0; i #include #include #include +#include /* Larger than physical memory */ #define SIZE (144*1024) +#define PROGRESS_INTERVAL 8000 +#define NEWLINE_FREQ 100 /* * Quicksort. @@ -54,6 +57,61 @@ * Also, quicksort has somewhat more interesting memory usage patterns. */ +static unsigned iters; + +static inline +void +progress() { + TEST161_LPROGRESS_N(iters, PROGRESS_INTERVAL); + if (iters > 0 && (iters % (PROGRESS_INTERVAL * NEWLINE_FREQ)) == 0) { + printf("\n"); + } + ++iters; +} + +static void * +local_memcpy(void *dst, const void *src, size_t len) +{ + size_t i; + + /* + * memcpy does not support overlapping buffers, so always do it + * forwards. (Don't change this without adjusting memmove.) + * + * For speedy copying, optimize the common case where both pointers + * and the length are word-aligned, and copy word-at-a-time instead + * of byte-at-a-time. Otherwise, copy by bytes. + * + * The alignment logic below should be portable. We rely on + * the compiler to be reasonably intelligent about optimizing + * the divides and modulos out. Fortunately, it is. + */ + + if ((uintptr_t)dst % sizeof(long) == 0 && + (uintptr_t)src % sizeof(long) == 0 && + len % sizeof(long) == 0) { + + long *d = dst; + const long *s = src; + + for (i=0; i A[i+1]) { errx(1, "Failed: A[%d] is %d, A[%d] is %d", i, A[i], i+1, A[i+1]); } } - warnx("Passed."); + success(TEST161_SUCCESS, SECRET, "/testbin/sort"); } int diff --git a/userland/testbin/sparsefile/sparsefile.c b/userland/testbin/sparsefile/sparsefile.c index 93cd5bf..a719f91 100644 --- a/userland/testbin/sparsefile/sparsefile.c +++ b/userland/testbin/sparsefile/sparsefile.c @@ -41,6 +41,8 @@ #include #include #include +#include +#include int main(int argc, char *argv[]) @@ -57,15 +59,16 @@ main(int argc, char *argv[]) filename = argv[1]; size = atoi(argv[2]); - byte = '\n'; + byte = '@'; if (size == 0) { err(1, "Sparse files of length zero are not meaningful"); } - printf("Creating a sparse file of size %d\n", size); + tprintf("Creating a sparse file of size %d\n", size); + nprintf("."); - fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC); + fd = open(filename, O_RDWR|O_CREAT|O_TRUNC); if (fd < 0) { err(1, "%s: create", filename); } @@ -73,6 +76,7 @@ main(int argc, char *argv[]) if (lseek(fd, size-1, SEEK_SET) == -1) { err(1, "%s: lseek", filename); } + nprintf("."); r = write(fd, &byte, 1); if (r < 0) { err(1, "%s: write", filename); @@ -80,8 +84,30 @@ main(int argc, char *argv[]) else if (r != 1) { errx(1, "%s: write: Unexpected result count %d", filename, r); } + nprintf("."); + // Now check this byte. + // First seek to the beginning and then seek back to where the byte + // should be. + if(lseek(fd, 0, SEEK_SET) == -1) { + err(1, "lseek failed to seek to beginning of file\n"); + } + nprintf("."); + // Now seek back to where the byte should be + // While at it, also test SEEK_CUR + if(lseek(fd, size-1, SEEK_CUR) == -1) { + err(1, "lseek failed to seek to %d of file\n", size-1); + } + nprintf("."); + char test; + r = read(fd, &test, 1); + if(test != byte) { + err(1, "Byte test failed. Expected (%c) != Observed (%c)\n", byte, test); + } + nprintf("."); close(fd); + nprintf("\n"); + success(TEST161_SUCCESS, SECRET, "/testbin/sparsefile"); return 0; } diff --git a/userland/testbin/tictac/tictac.c b/userland/testbin/tictac/tictac.c index d65ec27..a8db7c0 100644 --- a/userland/testbin/tictac/tictac.c +++ b/userland/testbin/tictac/tictac.c @@ -92,7 +92,7 @@ main(void) win = do_move(player); print_board(); if (win) { - printf("Player %d, you WON!\n\n", player); + tprintf("Player %d, you WON!\n\n", player); break; /* out of for loop */ } } @@ -101,7 +101,7 @@ main(void) * tie game. */ if (!win) - printf("Tie Game!\n\n"); + tprintf("Tie Game!\n\n"); if (!ask_yesno("Do you wish to play again?")) break; /* out of while loop */ } @@ -121,9 +121,9 @@ main(void) void print_instructions(void) { - printf("Welcome to tic-tac-toe!\n"); - printf("Player 1 always plays X and player 2 always play O\n"); - printf("Good luck!\n\n\n"); + tprintf("Welcome to tic-tac-toe!\n"); + tprintf("Player 1 always plays X and player 2 always play O\n"); + tprintf("Good luck!\n\n\n"); } void @@ -142,22 +142,22 @@ print_board(void) int i, j; /* Print labels across the top */ - printf("\n 0 1 2\n"); + tprintf("\n 0 1 2\n"); for (i = 0; i < DIM; i++) { /* Print row labels */ - printf(" %d ", i); + tprintf(" %d ", i); for (j = 0; j < DIM; j++) { switch (board[i][j]) { - case EMPTY: printf(" "); break; - case X_MARKER: printf(" X "); break; - case O_MARKER: printf(" O "); break; - default: printf("???"); break; + case EMPTY: tprintf(" "); break; + case X_MARKER: tprintf(" X "); break; + case O_MARKER: tprintf(" O "); break; + default: tprintf("???"); break; } } - printf("\n"); + tprintf("\n"); } - printf("\n"); + tprintf("\n"); } /* @@ -181,7 +181,7 @@ ask_yesno(const char *msg) char answer[MAXSTRING]; while (TRUE) { - printf("%s [yes/no] ", msg); + tprintf("%s [yes/no] ", msg); if (read_string(answer, MAXSTRING) < 0) return(FALSE); if (Strcmp(answer, "yes")) @@ -189,7 +189,7 @@ ask_yesno(const char *msg) else if (Strcmp(answer, "no")) return(FALSE); else - printf("Please answer either yes or no\n"); + tprintf("Please answer either yes or no\n"); } } @@ -216,32 +216,32 @@ do_move(int player) char answer[MAXSTRING]; char cx; - printf("Player %d (%c), your move\n", player, + tprintf("Player %d (%c), your move\n", player, player == X_PLAYER ? 'X' : 'O'); while (TRUE) { - printf("Which row [0-%d]: ", DIM-1); + tprintf("Which row [0-%d]: ", DIM-1); if (read_string(answer, MAXSTRING) < 0) return(FALSE); cx = answer[0]; x = cx - '0'; if (x < 0 || x >= DIM) { - printf("Invalid row; must be >= 0 and < %d\n", DIM-1); + tprintf("Invalid row; must be >= 0 and < %d\n", DIM-1); continue; } - printf("Which column [0-%d]: ", DIM-1); + tprintf("Which column [0-%d]: ", DIM-1); if (read_string(answer, MAXSTRING) < 0) return(FALSE); cx = answer[0]; y = cx - '0'; if (y < 0 || y >= DIM) { - printf("Invalid column; must be >= 0 and < %d\n", + tprintf("Invalid column; must be >= 0 and < %d\n", DIM-1); continue; } if (board[x][y] != EMPTY) { - printf("That location is occupied; please try again\n"); + tprintf("That location is occupied; please try again\n"); print_board(); } else break; diff --git a/userland/testbin/userthreads/userthreads.c b/userland/testbin/userthreads/userthreads.c index 8b2bb0d..073d441 100644 --- a/userland/testbin/userthreads/userthreads.c +++ b/userland/testbin/userthreads/userthreads.c @@ -79,7 +79,7 @@ main(int argc, char *argv[]) threadfork(BladeRunner); } - printf("Parent has left.\n"); + tprintf("Parent has left.\n"); return 0; } @@ -93,7 +93,7 @@ BladeRunner() { while (count < MAX) { if (count % 500 == 0) - printf("Blade "); + tprintf("Blade "); count++; } } @@ -103,7 +103,7 @@ ThreadRunner() { while (count < MAX) { if (count % 513 == 0) - printf(" Runner\n"); + tprintf(" Runner\n"); count++; } } diff --git a/userland/testbin/zero/zero.c b/userland/testbin/zero/zero.c index 868853c..48c2426 100644 --- a/userland/testbin/zero/zero.c +++ b/userland/testbin/zero/zero.c @@ -39,6 +39,7 @@ #include #include #include +#include /* * Some initialized data. This is here to increase the chance that @@ -78,6 +79,7 @@ check_data(void) if (k != SUM_OF_DATA_STUFF) { warnx("My initialized data sums to the wrong value!"); warnx("Got: %u Expected: %u", k, SUM_OF_DATA_STUFF); + success(TEST161_FAIL, SECRET, "/testbin/zero"); errx(1, "FAILED"); } } @@ -94,6 +96,7 @@ check_bss(void) warnx("BSS entry at index %u (address %p) not zero!", i, &bss_stuff[i]); warnx("Found: 0x%x", bss_stuff[i]); + success(TEST161_FAIL, SECRET, "/testbin/zero"); errx(1, "FAILED"); } } @@ -112,9 +115,10 @@ check_sbrk(void) base = sbrk(SBRK_SIZE); if (base == (void *)-1) { if (errno == ENOSYS) { - printf("I guess you haven't implemented sbrk yet.\n"); + tprintf("I guess you haven't implemented sbrk yet.\n"); return; } + success(TEST161_FAIL, SECRET, "/testbin/zero"); err(1, "sbrk"); } @@ -124,6 +128,7 @@ check_sbrk(void) i, &base[i]); warnx("Got: 0x%x", (unsigned char)base[i]); warnx("Base of sbrk region: %p", base); + success(TEST161_FAIL, SECRET, "/testbin/zero"); errx(1, "FAILED"); } } @@ -133,13 +138,13 @@ check_sbrk(void) int main(void) { - printf("zero: phase 1: checking .bss\n"); + tprintf("zero: phase 1: checking .bss\n"); check_data(); check_bss(); - printf("zero: phase 2: checking sbrk()\n"); + tprintf("zero: phase 2: checking sbrk()\n"); check_sbrk(); - printf("zero: passed\n"); + success(TEST161_SUCCESS, SECRET, "/testbin/zero"); return 0; }