Secret testing with multiplier working.
This commit is contained in:
		| @@ -44,6 +44,7 @@ | ||||
|  * allows normally compilation and operation. | ||||
|  */ | ||||
|  | ||||
| #define KERNEL_SECRET "" | ||||
| #define SECRET_TESTING | ||||
| #define SECRET 1755184289 | ||||
|  | ||||
| #endif /* _SECRET_H_ */ | ||||
|   | ||||
| @@ -32,6 +32,7 @@ | ||||
|  | ||||
| /* Get __PF() for declaring printf-like functions. */ | ||||
| #include <cdefs.h> | ||||
| #include <kern/secret.h> | ||||
|  | ||||
| #include "opt-synchprobs.h" | ||||
| #include "opt-automationtest.h" | ||||
| @@ -165,16 +166,26 @@ int ll1test(int, char **); | ||||
| int ll16test(int, char **); | ||||
| #endif | ||||
|  | ||||
| #define SUCCESS 0 | ||||
| #define FAIL 1 | ||||
|  | ||||
| void success(bool, uint32_t, const char *); | ||||
|  | ||||
| void random_yielder(uint32_t); | ||||
| void random_spinner(uint32_t); | ||||
|  | ||||
| /* | ||||
|  * Testing variants of kprintf. tprintf is silent during automated testing. | ||||
|  * sprintf prefixes the kernel secret to kprintf messages during automated | ||||
|  * testing. nprintf is not silent during automated testing. | ||||
|  * kprintf variants that do not (or only) print during automated testing. | ||||
|  */ | ||||
|  | ||||
| int tkprintf(const char *format, ...) __PF(1,2); | ||||
| int nkprintf(const char *format, ...) __PF(1,2); | ||||
| #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_ */ | ||||
|   | ||||
| @@ -142,45 +142,6 @@ kprintf(const char *fmt, ...) | ||||
| 	return chars; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * kprintf variant that is quiet during automated testing | ||||
|  */ | ||||
| int | ||||
| tkprintf(const char *fmt, ...) | ||||
| { | ||||
| 	int chars; | ||||
| 	va_list ap; | ||||
| 	 | ||||
| 	if (strcmp(KERNEL_SECRET, "") != 0) { | ||||
| 		return 0; | ||||
| 	} | ||||
| 	 | ||||
| 	va_start(ap, fmt); | ||||
| 	chars = __kprintf(fmt, ap); | ||||
| 	va_end(ap); | ||||
|  | ||||
| 	return chars; | ||||
| } | ||||
| /* | ||||
|  * kprintf variant that is quiet during non-automated testing | ||||
|  */ | ||||
| int | ||||
| nkprintf(const char *fmt, ...) | ||||
| { | ||||
| 	int chars; | ||||
| 	va_list ap; | ||||
| 	 | ||||
| 	if (strcmp(KERNEL_SECRET, "") == 0) { | ||||
| 		return 0; | ||||
| 	} | ||||
| 	 | ||||
| 	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. | ||||
|   | ||||
| @@ -1,6 +1,58 @@ | ||||
| #include <kern/secret.h> | ||||
| #include <types.h> | ||||
| #include <thread.h> | ||||
| #include <test.h> | ||||
| #include <lib.h> | ||||
|  | ||||
| /* | ||||
|  * Main success function for kernel tests. Prints a multiple of the secret if | ||||
|  * the secret is non-zero and the test succeeded. Otherwise prints a random | ||||
|  * number. | ||||
|  * | ||||
|  * Ideally we would multiply the secret (a large prime) by another large prime | ||||
|  * to ensure that factoring was hard, but that would require either primality | ||||
|  * testing (slow) or augmenting sys161 with a prime number generator. This is | ||||
|  * sufficient for now to prevent replay attacks. | ||||
|  */ | ||||
|  | ||||
| #define MIN_MULTIPLIER 0x80000000 | ||||
|  | ||||
| #ifndef SECRET_TESTING | ||||
| void | ||||
| success(bool status, uint32_t secret, const char * name) { | ||||
| 	(void)secret; | ||||
| 	if (status == SUCCESS) { | ||||
| 		kprintf("%s: SUCCESS\n", name); | ||||
| 	} else {	 | ||||
| 		kprintf("%s: FAIL\n", name); | ||||
| 	} | ||||
| 	return; | ||||
| } | ||||
| #else | ||||
| void | ||||
| success(bool status, uint32_t secret, const char * name) { | ||||
| 	uint32_t multiplier; | ||||
| 	// Make sure we can get large random numbers | ||||
| 	KASSERT(randmax() == 0xffffffff); | ||||
| 	while (1) { | ||||
| 		multiplier = random(); | ||||
| 		// We can at least remove the obvious non-primes... | ||||
| 		if (multiplier % 2 == 0) { | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (multiplier > MIN_MULTIPLIER) { | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	uint64_t big_secret = (uint64_t) secret * (uint64_t) multiplier; | ||||
| 	if (status == SUCCESS) { | ||||
| 		kprintf("%s: SUCCESS (%llu)\n", name, big_secret); | ||||
| 	} else {	 | ||||
| 		kprintf("%s: FAIL (%llu)\n", name, big_secret); | ||||
| 	} | ||||
| 	return; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /* | ||||
|  * Helper functions used by testing and problem driver code | ||||
|   | ||||
| @@ -78,13 +78,13 @@ void | ||||
| male_start(void) { | ||||
| 	random_yielder(PROBLEMS_MAX_YIELDER); | ||||
| 	random_spinner(PROBLEMS_MAX_SPINNER); | ||||
| 	tkprintf("%s starting\n", curthread->t_name); | ||||
| 	kprintf_n("%s starting\n", curthread->t_name); | ||||
| } | ||||
| void | ||||
| male_end(void) { | ||||
| 	random_yielder(PROBLEMS_MAX_YIELDER); | ||||
| 	random_spinner(PROBLEMS_MAX_SPINNER); | ||||
| 	tkprintf("%s ending\n", curthread->t_name); | ||||
| 	kprintf_n("%s ending\n", curthread->t_name); | ||||
| } | ||||
|  | ||||
| static | ||||
| @@ -111,13 +111,13 @@ void | ||||
| female_start(void) { | ||||
| 	random_yielder(PROBLEMS_MAX_YIELDER); | ||||
| 	random_spinner(PROBLEMS_MAX_SPINNER); | ||||
| 	tkprintf("%s starting\n", curthread->t_name); | ||||
| 	kprintf_n("%s starting\n", curthread->t_name); | ||||
| } | ||||
| void | ||||
| female_end(void) { | ||||
| 	random_yielder(PROBLEMS_MAX_YIELDER); | ||||
| 	random_spinner(PROBLEMS_MAX_SPINNER); | ||||
| 	tkprintf("%s ending\n", curthread->t_name); | ||||
| 	kprintf_n("%s ending\n", curthread->t_name); | ||||
| } | ||||
|  | ||||
| static | ||||
| @@ -144,13 +144,13 @@ void | ||||
| matchmaker_start(void) { | ||||
| 	random_yielder(PROBLEMS_MAX_YIELDER); | ||||
| 	random_spinner(PROBLEMS_MAX_SPINNER); | ||||
| 	tkprintf("%s starting\n", curthread->t_name); | ||||
| 	kprintf_n("%s starting\n", curthread->t_name); | ||||
| } | ||||
| void | ||||
| matchmaker_end(void) { | ||||
| 	random_yielder(PROBLEMS_MAX_YIELDER); | ||||
| 	random_spinner(PROBLEMS_MAX_SPINNER); | ||||
| 	tkprintf("%s ending\n", curthread->t_name); | ||||
| 	kprintf_n("%s ending\n", curthread->t_name); | ||||
| } | ||||
|  | ||||
| #define NMATING 10 | ||||
| @@ -268,14 +268,14 @@ void | ||||
| inQuadrant(int quadrant) { | ||||
| 	random_yielder(PROBLEMS_MAX_YIELDER); | ||||
| 	random_spinner(PROBLEMS_MAX_SPINNER); | ||||
| 	tkprintf("%s in quadrant %d\n", curthread->t_name, quadrant); | ||||
| 	kprintf_n("%s in quadrant %d\n", curthread->t_name, quadrant); | ||||
| } | ||||
|  | ||||
| void | ||||
| leaveIntersection() { | ||||
| 	random_yielder(PROBLEMS_MAX_YIELDER); | ||||
| 	random_spinner(PROBLEMS_MAX_SPINNER); | ||||
| 	tkprintf("%s left the intersection\n", curthread->t_name); | ||||
| 	kprintf_n("%s left the intersection\n", curthread->t_name); | ||||
| } | ||||
|  | ||||
| #define NCARS 64 | ||||
|   | ||||
| @@ -40,9 +40,6 @@ | ||||
| #include <kern/secret.h> | ||||
| #include <spinlock.h> | ||||
|  | ||||
| #define SUCCESS 0 | ||||
| #define FAIL 1 | ||||
|  | ||||
| #define NSEMLOOPS     63 | ||||
| #define NLOCKLOOPS    120 | ||||
| #define NCVLOOPS      5 | ||||
| @@ -94,15 +91,6 @@ inititems(void) | ||||
| 	spinlock_init(&status_lock); | ||||
| } | ||||
|  | ||||
| static | ||||
| void | ||||
| success(bool status, const char *msg) { | ||||
| 	if (status == SUCCESS) { | ||||
| 		kprintf("%s%s: SUCCESS\n", KERNEL_SECRET, msg); | ||||
| 	} else { | ||||
| 		kprintf("%s%s: FAIL\n", KERNEL_SECRET, msg); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static | ||||
| void | ||||
| @@ -117,10 +105,10 @@ semtestthread(void *junk, unsigned long num) | ||||
| 	random_yielder(4); | ||||
| 	P(testsem); | ||||
| 	semtest_current = num; | ||||
| 	tkprintf("Thread %2lu: ", num); | ||||
| 	kprintf_n("Thread %2lu: ", num); | ||||
|  | ||||
| 	for (i=0; i<NSEMLOOPS; i++) { | ||||
| 		tkprintf("%c", (int)num+64); | ||||
| 		kprintf_n("%c", (int)num+64); | ||||
| 		random_yielder(4); | ||||
| 		if (semtest_current != num) { | ||||
| 			spinlock_acquire(&status_lock); | ||||
| @@ -129,7 +117,7 @@ semtestthread(void *junk, unsigned long num) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	tkprintf("\n"); | ||||
| 	kprintf_n("\n"); | ||||
| 	V(donesem); | ||||
| } | ||||
|  | ||||
| @@ -143,12 +131,12 @@ semtest(int nargs, char **args) | ||||
|  | ||||
| 	inititems(); | ||||
| 	test_status = FAIL; | ||||
| 	tkprintf("Starting semaphore test...\n"); | ||||
| 	tkprintf("If this hangs, it's broken: "); | ||||
| 	kprintf_n("Starting semaphore test...\n"); | ||||
| 	kprintf_n("If this hangs, it's broken: "); | ||||
| 	P(testsem); | ||||
| 	P(testsem); | ||||
| 	test_status = SUCCESS; | ||||
| 	tkprintf("ok\n"); | ||||
| 	kprintf_n("ok\n"); | ||||
|  | ||||
| 	for (i=0; i<NTHREADS; i++) { | ||||
| 		result = thread_fork("semtest", NULL, semtestthread, NULL, i); | ||||
| @@ -167,8 +155,8 @@ semtest(int nargs, char **args) | ||||
| 	V(testsem); | ||||
| 	V(testsem); | ||||
| 	 | ||||
| 	tkprintf("Semaphore test done.\n"); | ||||
| 	success(test_status, "semtest"); | ||||
| 	kprintf_n("Semaphore test done.\n"); | ||||
| 	success(test_status, SECRET, "sy1"); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
| @@ -177,8 +165,8 @@ static | ||||
| void | ||||
| fail(unsigned long num, const char *msg) | ||||
| { | ||||
| 	tkprintf("thread %lu: Mismatch on %s\n", num, msg); | ||||
| 	tkprintf("Test failed\n"); | ||||
| 	kprintf_n("thread %lu: Mismatch on %s\n", num, msg); | ||||
| 	kprintf_n("Test failed\n"); | ||||
|  | ||||
| 	lock_release(testlock); | ||||
|  | ||||
| @@ -251,7 +239,7 @@ locktest(int nargs, char **args) | ||||
|  | ||||
| 	inititems(); | ||||
| 	test_status = SUCCESS; | ||||
| 	tkprintf("Starting lock test...\n"); | ||||
| 	kprintf_n("Starting lock test...\n"); | ||||
|  | ||||
| 	for (i=0; i<NTHREADS; i++) { | ||||
| 		result = thread_fork("synchtest", NULL, locktestthread, NULL, i); | ||||
| @@ -263,8 +251,8 @@ locktest(int nargs, char **args) | ||||
| 		P(donesem); | ||||
| 	} | ||||
| 	 | ||||
| 	tkprintf("Lock test done.\n"); | ||||
| 	success(test_status, "locktest"); | ||||
| 	kprintf_n("Lock test done.\n"); | ||||
| 	success(test_status, SECRET, "sy2"); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
| @@ -294,8 +282,8 @@ cvtestthread(void *junk, unsigned long num) | ||||
|  | ||||
| 			/* Require at least 2000 cpu cycles (we're 25mhz) */ | ||||
| 			if (ts2.tv_sec == 0 && ts2.tv_nsec < 40*2000) { | ||||
| 				tkprintf("cv_wait took only %u ns\n", ts2.tv_nsec); | ||||
| 				tkprintf("That's too fast... you must be " "busy-looping\n"); | ||||
| 				kprintf_n("cv_wait took only %u ns\n", ts2.tv_nsec); | ||||
| 				kprintf_n("That's too fast... you must be " "busy-looping\n"); | ||||
| 				spinlock_acquire(&status_lock); | ||||
| 				test_status = FAIL; | ||||
| 				spinlock_release(&status_lock); | ||||
| @@ -323,7 +311,7 @@ cvtestthread(void *junk, unsigned long num) | ||||
| 		} | ||||
| 		spinlock_release(&status_lock); | ||||
|  | ||||
| 		tkprintf("Thread %lu\n", testval2); | ||||
| 		kprintf_n("Thread %lu\n", testval2); | ||||
| 		testval1 = (testval1 + NTHREADS - 1) % NTHREADS; | ||||
| 		lock_release(testlock); | ||||
| 	} | ||||
| @@ -339,8 +327,8 @@ cvtest(int nargs, char **args) | ||||
| 	(void)args; | ||||
|  | ||||
| 	inititems(); | ||||
| 	tkprintf("Starting CV test...\n"); | ||||
| 	tkprintf("Threads should print out in reverse order.\n"); | ||||
| 	kprintf_n("Starting CV test...\n"); | ||||
| 	kprintf_n("Threads should print out in reverse order.\n"); | ||||
|  | ||||
| 	testval1 = NTHREADS-1; | ||||
|  | ||||
| @@ -354,8 +342,8 @@ cvtest(int nargs, char **args) | ||||
| 		P(donesem); | ||||
| 	} | ||||
| 	 | ||||
| 	tkprintf("CV test done\n"); | ||||
| 	success(test_status, "cvtest"); | ||||
| 	kprintf_n("CV test done\n"); | ||||
| 	success(test_status, SECRET, "sy3"); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
| @@ -401,7 +389,7 @@ sleepthread(void *junk1, unsigned long junk2) | ||||
| 			random_yielder(4); | ||||
| 			lock_release(testlocks[i]); | ||||
| 		} | ||||
| 		tkprintf("sleepthread: %u\n", j); | ||||
| 		kprintf_n("sleepthread: %u\n", j); | ||||
| 	} | ||||
| 	V(exitsem); | ||||
| } | ||||
| @@ -434,7 +422,7 @@ wakethread(void *junk1, unsigned long junk2) | ||||
| 			random_yielder(4); | ||||
| 			lock_release(testlocks[i]); | ||||
| 		} | ||||
| 		tkprintf("wakethread: %u\n", j); | ||||
| 		kprintf_n("wakethread: %u\n", j); | ||||
| 	} | ||||
| 	V(exitsem); | ||||
| } | ||||
| @@ -458,7 +446,7 @@ cvtest2(int nargs, char **args) | ||||
| 	gatesem = sem_create("gatesem", 0); | ||||
| 	exitsem = sem_create("exitsem", 0); | ||||
|  | ||||
| 	tkprintf("cvtest2...\n"); | ||||
| 	kprintf_n("cvtest2...\n"); | ||||
|  | ||||
| 	result = thread_fork("cvtest2", NULL, sleepthread, NULL, 0); | ||||
| 	if (result) { | ||||
| @@ -482,8 +470,8 @@ cvtest2(int nargs, char **args) | ||||
| 		testcvs[i] = NULL; | ||||
| 	} | ||||
|  | ||||
| 	tkprintf("cvtest2 done\n"); | ||||
| 	success(test_status, "cvtest2"); | ||||
| 	kprintf_n("cvtest2 done\n"); | ||||
| 	success(test_status, SECRET, "sy4"); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
| @@ -497,8 +485,8 @@ int rwtest(int nargs, char **args) { | ||||
| 	(void) nargs; | ||||
| 	(void) args; | ||||
| 	 | ||||
| 	tkprintf("rwtest unimplemented\n"); | ||||
| 	success(FAIL, "rwtest"); | ||||
| 	kprintf_n("rwtest unimplemented\n"); | ||||
| 	success(FAIL, SECRET, "sy5"); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user