851 lines
25 KiB
C
851 lines
25 KiB
C
#include "tests.h"
|
|
#include "x86_desc.h"
|
|
#include "lib/lib.h"
|
|
#include "fs/ece391fs.h"
|
|
#include "fs/unified_fs.h"
|
|
#include "devices/rtc.h" // Added by jinghua3.
|
|
#include "devices/sb16.h"
|
|
#include "devices/keyboard.h"
|
|
#include "interrupts/sys_calls.h"
|
|
#include "interrupts/multiprocessing.h"
|
|
|
|
#define SCANCODE_ENTER 0x1C
|
|
|
|
/* format these macros as you see fit */
|
|
#define TEST_HEADER \
|
|
printf("[TEST %s] Running %s at %s:%d\n", __FUNCTION__, __FUNCTION__, __FILE__, __LINE__)
|
|
#define TEST_OUTPUT(name, result) \
|
|
printf("[TEST %s] Result = %s\n", name, (result == PASS) ? "PASS" : "FAIL");
|
|
|
|
static inline void assertion_failure(){
|
|
/* Use exception #15 for assertions, otherwise
|
|
reserved by Intel */
|
|
asm volatile("int $15");
|
|
}
|
|
|
|
/* int fd_array_wrapper(int (*func)(fd_array_t))
|
|
* @input: *func - function for test to be executed
|
|
* @output: run the test with generated fd_array
|
|
* @description: generate a real fd_array to use with test,
|
|
* to avoid bugs with RTC, etc
|
|
*/
|
|
int test_fdarray_wrapper(int (*func)(fd_array_t*)) {
|
|
// Get a PCB along with its fd_array
|
|
cli();
|
|
int32_t pid = process_allocate();
|
|
sti();
|
|
if(-1 == pid) return FAIL;
|
|
process_t* process = process_get_pcb(pid);
|
|
if(FAIL == unified_init(process->fd_array)) return FAIL;
|
|
|
|
int ret = (*func)(process->fd_array);
|
|
|
|
// Close all files
|
|
int i;
|
|
for(i = 0; i < MAX_NUM_FD_ENTRY; i++) {
|
|
unified_close(process->fd_array, i);
|
|
}
|
|
|
|
// Release the pid
|
|
process->present = 0;
|
|
return ret;
|
|
}
|
|
|
|
|
|
/* Checkpoint 1 tests */
|
|
|
|
/* IDT Test - Example
|
|
*
|
|
* Asserts that first 10 IDT entries are not NULL
|
|
* Inputs: None
|
|
* Outputs: PASS/FAIL
|
|
* Side Effects: None
|
|
* Coverage: Load IDT, IDT definition
|
|
* Files: x86_desc.h/S
|
|
*/
|
|
int idt_test(){
|
|
TEST_HEADER;
|
|
|
|
int i;
|
|
int result = PASS;
|
|
for (i = 0; i < 10; ++i){
|
|
if ((idt[i].offset_15_00 == NULL) &&
|
|
(idt[i].offset_31_16 == NULL)){
|
|
assertion_failure();
|
|
result = FAIL;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/* Division by Zero Test - Added by jinghua3.
|
|
*
|
|
* Test exception handler division by zero.
|
|
* Inputs: None
|
|
* Outputs: None
|
|
* Side Effects: freeze kernel.
|
|
* Coverage: IDT Exception handler.
|
|
* Files: idt.c
|
|
*/
|
|
void division_by_zero_test(){
|
|
TEST_HEADER;
|
|
|
|
int testVar;
|
|
int one = 1;
|
|
int zero = 0;
|
|
testVar = one/zero;
|
|
}
|
|
|
|
|
|
|
|
/* Dereferencing NULL Test - Added by jinghua3.
|
|
*
|
|
* Attempt to dereference NULL, should trigger page fault.
|
|
* Inputs: none
|
|
* Outputs: none
|
|
* Side Effects: freeze kernel.
|
|
* Coverage: Exception hander.
|
|
* Files: idt.c
|
|
*/
|
|
void dereferencing_null_test(){
|
|
TEST_HEADER;
|
|
|
|
int* ptr = NULL;
|
|
int testVar;
|
|
testVar = *(ptr);
|
|
}
|
|
|
|
/* Dereferencing in Non-exist Page Test - Added by jinghua3.
|
|
*
|
|
* Attempt to dereference an address in a nonexistent page, should trigger page fault.
|
|
* For checkpoint 1, linear addr larger than 8MB should not be present.
|
|
* So trying to dereference a linear addr larger than 0x800000 should trigger page fault.
|
|
* Inputs: none
|
|
* Outputs: none
|
|
* Side Effects: freeze kernel.
|
|
* Coverage: Exception hander.
|
|
* Files: idt.c
|
|
*/
|
|
void deref_nonexist_page_test(){
|
|
TEST_HEADER;
|
|
|
|
//int* ptr = (int*)(0xB8000 - 4); // test mem addr in first 4MB but not in video mem.
|
|
//int* ptr = (int*)(0x800000 - 4); // test mem addr in first 4MB but not in video mem.
|
|
int* ptr = (int*)(0x800000 + 8);
|
|
int testVar;
|
|
testVar = *(ptr);
|
|
}
|
|
|
|
|
|
/* Video Memory Paging Test - Added by jinghua3.
|
|
*
|
|
* Dereferencing linear address in range for video memory,
|
|
* particularly just choose one address randomly, 0xB8000 + 8.
|
|
* (video mem starts at 0xB8000)
|
|
* Inputs: None
|
|
* Outputs: PASS/FAIL
|
|
* Side Effects: None
|
|
* Coverage: Paging in range of Video Memory.
|
|
* Files: paging.c
|
|
*/
|
|
int videoMem_paging_test(){
|
|
TEST_HEADER;
|
|
|
|
int * ptr = (int*)(0xB8000 + 8);
|
|
int testVar;
|
|
testVar = *ptr;
|
|
return PASS;
|
|
}
|
|
|
|
/* Kernel Memory Paging Test - Added by jinghua3.
|
|
*
|
|
* Dereferencing linear address in range for kernel,
|
|
* particularly just choose one address randomly, 0x400000 + 8.
|
|
* (kernel addresses start at 0x400000)
|
|
* Inputs: None
|
|
* Outputs: PASS/FAIL
|
|
* Side Effects: None
|
|
* Coverage: Paging in range of Kernel Memory.
|
|
* Files: paging.c
|
|
*/
|
|
int kerMem_paging_test(){
|
|
TEST_HEADER;
|
|
|
|
int * ptr = (int*)(0x400000 + 8);
|
|
int testVar;
|
|
testVar = *ptr;
|
|
return PASS;
|
|
}
|
|
|
|
|
|
/* Paging Structure Test - Added by jinghua3.
|
|
*
|
|
* Test whether the page table has been initialized
|
|
* Input: none
|
|
* Output: PASS/FAIL
|
|
* Side Effects: none
|
|
* Coverage: paging, page directory and page table.
|
|
* Files: paging.c
|
|
*/
|
|
int paging_struct_test(){
|
|
TEST_HEADER;
|
|
|
|
// test if any of the first 2 entries in page directory is null.
|
|
if(page_directory[0].pde_KB.present!=1 || page_directory[1].pde_MB.present!=1){
|
|
printf("\n page directory first two entries not all present. \n");
|
|
return FAIL;
|
|
}
|
|
// test some page table entries in the first page table, just randomly choose indices 1,20,1000.
|
|
if(page_table[1].present!=1 || page_table[20].present!=1 || page_table[1000].present!=1){
|
|
printf("\n page table entries are not all present. \n");
|
|
return FAIL;
|
|
}
|
|
|
|
return PASS;
|
|
}
|
|
|
|
|
|
/* RTC Test - Added by jinghua3.
|
|
* Not working anymore due to API changes - yuhuixu2
|
|
*
|
|
* Enable RTC.
|
|
* Input: None.
|
|
* Output: Should print "tick" on screen in a particular rate.
|
|
* Side Effects: none
|
|
* Coverage: RTC
|
|
* Files: rtc.c
|
|
*/
|
|
/*void rtc_test(){
|
|
TEST_HEADER;
|
|
|
|
rtc_set_freq(4);
|
|
}*/
|
|
|
|
|
|
|
|
/* Checkpoint 2 tests */
|
|
|
|
/* int ece391fs_loaded()
|
|
* @output: PASS / FAIL
|
|
* @description: test if ece391fs is properly initialized.
|
|
*/
|
|
int ece391fs_loaded() {
|
|
TEST_HEADER;
|
|
if(FAIL == ece391fs_is_initialized()) return FAIL;
|
|
return PASS;
|
|
}
|
|
|
|
/* int ece391fs_read_existent_file()
|
|
* @output: PASS / FAIL
|
|
* @description: test getting file entry of "frame1.txt".
|
|
* and verify that its size is 174 bytes.
|
|
* If the file got modified, this test should be modified too.
|
|
*/
|
|
int ece391fs_read_existent_file() {
|
|
TEST_HEADER;
|
|
ece391fs_file_info_t finfo;
|
|
if(FAIL == read_dentry_by_name("frame1.txt", &finfo)) return FAIL;
|
|
if(ece391fs_size(finfo.inode) != 174) return FAIL;
|
|
char buf[200];
|
|
if(174 != read_data(finfo.inode, 0, buf, 200)) return FAIL;
|
|
int i;
|
|
for(i = 0; i < 174; i++) putc(buf[i]);
|
|
return PASS;
|
|
}
|
|
|
|
/* int ece391fs_read_nonexistent_file()
|
|
* @output: PASS / FAIL
|
|
* @description: test getting file entry of a nonexistent file.
|
|
* The FS call should return FAIL.
|
|
*/
|
|
int ece391fs_read_nonexistent_file() {
|
|
TEST_HEADER;
|
|
ece391fs_file_info_t finfo;
|
|
if(SUCCESS == read_dentry_by_name("404.not.found", &finfo)) return FAIL;
|
|
return PASS;
|
|
}
|
|
|
|
/* int ece391fs_read_toolong_file()
|
|
* @output: PASS / FAIL
|
|
* @description: test getting file entry of a file with name > 32 chars.
|
|
* The FS call should return FAIL.
|
|
*/
|
|
int ece391fs_read_toolong_file() {
|
|
TEST_HEADER;
|
|
ece391fs_file_info_t finfo;
|
|
if(SUCCESS == read_dentry_by_name("verylargetextwithverylongname.txt", &finfo)) return FAIL;
|
|
return PASS;
|
|
}
|
|
|
|
/* int ece391fs_read_existent_idx()
|
|
* @output: PASS / FAIL
|
|
* @description: test getting the first file entry, the directory,
|
|
* and verify some of its attributes.
|
|
*/
|
|
int ece391fs_read_existent_idx() {
|
|
TEST_HEADER;
|
|
ece391fs_file_info_t finfo;
|
|
if(FAIL == read_dentry_by_index(0, &finfo)) return FAIL;
|
|
if(ECE391FS_FILE_TYPE_FOLDER != finfo.type) return FAIL;
|
|
if(0 != finfo.inode) return FAIL;
|
|
return PASS;
|
|
}
|
|
|
|
/* int ece391fs_read_nonexistent_idx()
|
|
* @output: PASS / FAIL
|
|
* @description: test getting file entry of a nonexistent index.
|
|
* The FS call should return FAIL.
|
|
*/
|
|
int ece391fs_read_nonexistent_idx() {
|
|
TEST_HEADER;
|
|
ece391fs_file_info_t finfo;
|
|
if(SUCCESS == read_dentry_by_index(100, &finfo)) return FAIL;
|
|
return PASS;
|
|
}
|
|
|
|
/* int ece391fs_large_file()
|
|
* @output: PASS / FAIL
|
|
* @description: tests getting information of large file with long name,
|
|
* verify size (5277 bytes), and verify some segments of data.
|
|
*/
|
|
int ece391fs_large_file() {
|
|
TEST_HEADER;
|
|
ece391fs_file_info_t finfo;
|
|
if(FAIL == read_dentry_by_name("verylargetextwithverylongname.tx", &finfo)) return FAIL;
|
|
if(ece391fs_size(finfo.inode) != 5277) return FAIL;
|
|
char buf[33];
|
|
buf[32] = '\0';
|
|
char std1[] = "very large text file with a very";
|
|
char std2[] = " long name\n123456789012345678901";
|
|
char std3[] = "jklmnopqrstuvwxyzabcdefghijklmno";
|
|
char std4[] = "_+`1234567890-=[]\\{}|;\':\",./<>?\n";
|
|
char std5[] = ",./<>?\n";
|
|
if(32 != read_data(finfo.inode, 0, buf, 32)) return FAIL; // Test reading at beginning
|
|
if(0 != strncmp(buf, std1, 32)) return FAIL;
|
|
if(32 != read_data(finfo.inode, 32, buf, 32)) return FAIL; // Test reading with offset
|
|
if(0 != strncmp(buf, std2, 32)) return FAIL;
|
|
if(32 != read_data(finfo.inode, 4090, buf, 32)) return FAIL; // Test reading across block
|
|
if(0 != strncmp(buf, std3, 32)) return FAIL;
|
|
if(32 != read_data(finfo.inode, 5245, buf, 32)) return FAIL; // Test reading at end
|
|
if(0 != strncmp(buf, std4, 32)) return FAIL;
|
|
if(7 != read_data(finfo.inode, 5270, buf, 32)) return FAIL; // Test reading over end
|
|
if(0 != strncmp(buf, std5, 7)) return FAIL; // should only read 7 bytes
|
|
if(7 != read_data(finfo.inode, 5270, buf, 8000)) return FAIL; // Test reading well over end
|
|
if(0 != strncmp(buf, std5, 7)) return FAIL; // should only read 7 bytes
|
|
if(0 != read_data(finfo.inode, 5280, buf, 32)) return FAIL; // Test reading after end
|
|
return PASS;
|
|
}
|
|
|
|
/* int ece391fs_list_dir()
|
|
* @output: PASS / FAIL
|
|
* @description: Lists every file in ECE391FS
|
|
*/
|
|
int ece391fs_list_dir() {
|
|
TEST_HEADER;
|
|
char buf[ECE391FS_MAX_FILENAME_LEN + 1];
|
|
int32_t ret;
|
|
int i;
|
|
for(i = 0; i < ECE391FS_MAX_FILE_COUNT; i++) {
|
|
ret = read_dir(i, buf, ECE391FS_MAX_FILENAME_LEN);
|
|
if(ret == 0) break;
|
|
if(ret > ECE391FS_MAX_FILENAME_LEN) return FAIL;
|
|
if(ret < 0) return FAIL;
|
|
buf[ret] = '\0';
|
|
printf(buf);
|
|
printf(", ");
|
|
}
|
|
return PASS;
|
|
}
|
|
|
|
/* int fs_read_existent_file()
|
|
* @output: PASS / FAIL
|
|
* @description: test reading 174 bytes out of frame1.txt.
|
|
* Uses generic filesystem functions instead of ECE391FS specific ones.
|
|
* 174 is the exact file size of frame1.txt.
|
|
* If the file got modified, this test should be modified too.
|
|
*/
|
|
int ece391fs_interface_read_existent_file() {
|
|
TEST_HEADER;
|
|
int32_t fd;
|
|
uint32_t offset = 0;
|
|
char buf[200];
|
|
if(FAIL == file_open(&fd, "frame1.txt")) return FAIL;
|
|
if(FAIL == file_read(&fd, &offset, buf, 200)) return FAIL;
|
|
if(offset != 174) return FAIL;
|
|
int i;
|
|
for(i = 0; i < offset; i++) putc(buf[i]);
|
|
if(FAIL == file_close(&fd)) return FAIL;
|
|
if(0 != fd) return FAIL;
|
|
return PASS;
|
|
}
|
|
|
|
/* int fs_read_nonexistent_file()
|
|
* @output: PASS / FAIL
|
|
* @description: test getting file entry of a nonexistent file.
|
|
* Uses generic filesystem functions instead of ECE391FS specific ones.
|
|
* The FS call should return -1 (Fail).
|
|
*/
|
|
int ece391fs_interface_read_nonexistent_file() {
|
|
TEST_HEADER;
|
|
int32_t fd = 0;
|
|
if(SUCCESS == file_open(&fd, "404.not.found")) return FAIL;
|
|
if(0 != fd) return FAIL;
|
|
return PASS;
|
|
}
|
|
|
|
/* int fs_read_existent_dir()
|
|
* @output: PASS / FAIL
|
|
* @description: test listing files in root folder.
|
|
* Uses generic filesystem functions instead of ECE391FS specific ones.
|
|
*/
|
|
int ece391fs_interface_read_existent_dir() {
|
|
TEST_HEADER;
|
|
int32_t fd = 0;
|
|
char buf[ECE391FS_MAX_FILENAME_LEN + 1];
|
|
if(FAIL == dir_open(&fd, ".")) return FAIL;
|
|
|
|
int32_t ret;
|
|
uint32_t offset = 0;
|
|
while(1) {
|
|
ret = dir_read(&fd, &offset, buf, ECE391FS_MAX_FILENAME_LEN);
|
|
if(ret == 0) break;
|
|
if(ret > ECE391FS_MAX_FILENAME_LEN) return FAIL;
|
|
if(ret < 0) return FAIL;
|
|
buf[ret] = '\0';
|
|
printf(buf);
|
|
printf(", ");
|
|
}
|
|
if(FAIL == dir_close(&fd)) return FAIL;
|
|
if(fd != 0) return FAIL;
|
|
return PASS;
|
|
}
|
|
|
|
/* int fs_read_nonexistent_dir()
|
|
* @output: PASS / FAIL
|
|
* @description: test reading from an nonexistent dir.
|
|
* Uses generic filesystem functions instead of ECE391FS specific ones.
|
|
* The FS call should return -1 (Fail).
|
|
*/
|
|
int ece391fs_interface_read_nonexistent_dir() {
|
|
TEST_HEADER;
|
|
int32_t fd = 0;
|
|
if(SUCCESS == dir_open(&fd, "404.not.found")) return FAIL;
|
|
if(0 != fd) return FAIL;
|
|
return PASS;
|
|
}
|
|
|
|
/* int rtc_read_write_test()
|
|
* Not working anymore due to API changes - yuhuixu2
|
|
*
|
|
* @output: PASS / FAIL
|
|
* @description: Tests setting frequency of RTC.
|
|
* and reading from RTC to wait until the next tick.
|
|
* Test starts from 2 Hz, doubles frequency every second,
|
|
* and ends after 1024 Hz.
|
|
*/
|
|
// int rtc_read_write_test()
|
|
// {
|
|
// TEST_HEADER;
|
|
// // new frequency set to the RTC
|
|
// uint16_t freq = 2;
|
|
// rtc_open(NULL, NULL);
|
|
// while (freq <= 1024) {
|
|
// int i;
|
|
// for(i = 0; i < freq; i++) {
|
|
// rtc_read(NULL, NULL, NULL, 0);
|
|
// printf("%d ", freq);
|
|
// }
|
|
// freq *= 2;
|
|
// rtc_write(NULL, NULL, (void*) &freq, sizeof(uint16_t));
|
|
// printf("\n");
|
|
// }
|
|
// rtc_close(NULL);
|
|
// return PASS;
|
|
// }
|
|
|
|
/* int terminal_driver_test()
|
|
* @output: PASS / FAIL
|
|
* @description: Tests reading/writing from/to terminal driver.
|
|
* Repeats the name entered.
|
|
*/
|
|
int terminal_driver_test()
|
|
{
|
|
TEST_HEADER;
|
|
int32_t read_retval, write_retval;
|
|
terminal_open(NULL, NULL);
|
|
char buf[128];
|
|
printf("Hi, what's your name? ");
|
|
read_retval = terminal_read(NULL, NULL, buf, 128);
|
|
printf("Hello, ");
|
|
write_retval = terminal_write(NULL, NULL, buf, 128);
|
|
printf("Read %d characters from terminal, and write %d characters to terminal.\n",
|
|
read_retval, write_retval);
|
|
return PASS;
|
|
}
|
|
|
|
/* Checkpoint 3 tests */
|
|
|
|
/* int unified_fs_read_file(fd_array_t* fd_array)
|
|
* @input: fd_array - file descriptor array
|
|
* @output: PASS / FAIL
|
|
* @description: Tests reading contents of a file using Unified FS interface.
|
|
* Covers file open, file pos storage, over-end handling, etc.
|
|
*/
|
|
int unified_fs_read_file(fd_array_t* fd_array) {
|
|
TEST_HEADER;
|
|
|
|
int32_t fd;
|
|
int i;
|
|
char buf[100];
|
|
if(FAIL == (fd = unified_open(fd_array, "frame1.txt"))) return FAIL;
|
|
|
|
if(FAIL == unified_read(fd_array, fd, buf, 100)) return FAIL;
|
|
if(fd_array[fd].pos != 100) return FAIL;
|
|
for(i = 0; i < 100; i++) putc(buf[i]);
|
|
|
|
if(FAIL == unified_read(fd_array, fd, buf, 100)) return FAIL;
|
|
if(fd_array[fd].pos != 174) return FAIL;
|
|
for(i = 0; i < 74; i++) putc(buf[i]);
|
|
|
|
if(FAIL == unified_close(fd_array, fd)) return FAIL;
|
|
if(NULL != fd_array[fd].interface) return FAIL;
|
|
return PASS;
|
|
}
|
|
|
|
/* int unified_fs_read_dir(fd_array_t* fd_array)
|
|
* @input: fd_array - file descriptor array
|
|
* @output: PASS / FAIL
|
|
* @description: Tests listing directory using Unified FS interface.
|
|
*/
|
|
int unified_fs_read_dir(fd_array_t* fd_array) {
|
|
TEST_HEADER;
|
|
|
|
int32_t fd;
|
|
int ret;
|
|
char buf[ECE391FS_MAX_FILENAME_LEN + 1];
|
|
if(FAIL == (fd = unified_open(fd_array, "."))) return FAIL;
|
|
|
|
while(1) {
|
|
ret = unified_read(fd_array, fd, buf, ECE391FS_MAX_FILENAME_LEN);
|
|
if(ret == 0) break;
|
|
if(ret > ECE391FS_MAX_FILENAME_LEN) return FAIL;
|
|
if(ret < 0) return FAIL;
|
|
buf[ret] = '\0';
|
|
printf(buf);
|
|
printf(", ");
|
|
}
|
|
|
|
if(FAIL == unified_close(fd_array, fd)) return FAIL;
|
|
if(NULL != fd_array[fd].interface) return FAIL;
|
|
return PASS;
|
|
}
|
|
|
|
/* int unified_fs_read_nonexistent(fd_array_t* fd_array)
|
|
* @input: fd_array - file descriptor array
|
|
* @output: PASS / FAIL
|
|
* @description: Tests opening a nonexistent file using Unified FS interface.
|
|
*/
|
|
int unified_fs_read_nonexistent(fd_array_t* fd_array) {
|
|
TEST_HEADER;
|
|
if(FAIL != unified_open(fd_array, "404.not.found")) return FAIL;
|
|
return PASS;
|
|
}
|
|
|
|
/* int unified_fs_invalid_fd(fd_array_t* fd_array)
|
|
* @input: fd_array - file descriptor array
|
|
* @output: PASS / FAIL
|
|
* @description: Tests Unified FS interface handing of invalid file descriptor.
|
|
*/
|
|
int unified_fs_invalid_fd(fd_array_t* fd_array) {
|
|
TEST_HEADER;
|
|
int32_t fd = 7; // There's no fd 7, we haven't opened anything!
|
|
char buf[100];
|
|
if(FAIL != unified_read(fd_array, fd, buf, 100)) return FAIL;
|
|
if(FAIL != unified_write(fd_array, fd, buf, 100)) return FAIL;
|
|
if(FAIL != unified_close(fd_array, fd)) return FAIL;
|
|
return PASS;
|
|
}
|
|
|
|
/* unified_fs_rtc_read_write(fd_array_t* fd_array)
|
|
* @input: fd_array - file descriptor array
|
|
* @output: PASS / FAIL
|
|
* @description: Tests setting frequency of RTC with Unified FS interface,
|
|
* and reading from RTC to wait until the next tick.
|
|
* Test starts from 2 Hz, doubles frequency every second,
|
|
* and ends after 1024 Hz.
|
|
*/
|
|
int unified_fs_rtc_read_write(fd_array_t* fd_array) {
|
|
TEST_HEADER;
|
|
|
|
int32_t fd;
|
|
if(FAIL == (fd = unified_open(fd_array, "rtc"))) return FAIL;
|
|
|
|
// new frequency set to the RTC
|
|
uint32_t freq = 2;
|
|
while (freq <= 1024)
|
|
{
|
|
int i;
|
|
for(i = 0; i < freq; i++) {
|
|
if(FAIL == unified_read(fd_array, fd, NULL, 0)) return FAIL;
|
|
printf("%d ", freq);
|
|
}
|
|
freq *= 2;
|
|
if(FAIL == unified_write(fd_array, fd, &freq, sizeof(uint32_t))) return FAIL;
|
|
printf("\n");
|
|
}
|
|
if(FAIL == unified_close(fd_array, fd));
|
|
return PASS;
|
|
}
|
|
|
|
/* int unified_fs_stdio(fd_array_t* fd_array)
|
|
* No longer works due to API changes - yuhuixu2
|
|
*
|
|
* @input: fd_array - file descriptor array
|
|
* @output: PASS / FAIL
|
|
* @description: Tests reading/writing from/to terminal driver with Unified FS interface.
|
|
* Repeats the name entered.
|
|
*/
|
|
// int unified_fs_stdio(fd_array_t* fd_array) {
|
|
// TEST_HEADER;
|
|
//
|
|
// char buf[128];
|
|
// if(FAIL == unified_write(fd_array, 1, "Hi, what's your name? ", 22)) return FAIL;
|
|
// if(FAIL == unified_read(fd_array, 0, buf, 128)) return FAIL;
|
|
// if(FAIL == unified_write(fd_array, 1, "Hello, ", 7)) return FAIL;
|
|
// if(FAIL == unified_write(fd_array, 1, buf, 128)) return FAIL;
|
|
// return PASS;
|
|
// }
|
|
|
|
/* syscall_execute_test */
|
|
int syscall_execute_test()
|
|
{
|
|
TEST_HEADER;
|
|
// to be added
|
|
char* command = "testprint";
|
|
printf("command is %s\n", command);
|
|
syscall_execute ((uint8_t*)command);
|
|
return PASS;
|
|
}
|
|
|
|
/* Checkpoint 4 tests */
|
|
/* Checkpoint 5 tests */
|
|
|
|
/* Extra feature tests */
|
|
/* int unified_fs_tux_read()
|
|
* @output: PASS / FAIL
|
|
* @description: Tests reading tux's button state using Unified FS interface.
|
|
*/
|
|
int unified_fs_tux_read(fd_array_t* fd_array) {
|
|
TEST_HEADER;
|
|
|
|
int32_t fd;
|
|
if(FAIL == (fd = unified_open(fd_array, "tux"))) return FAIL;
|
|
|
|
// List of buttons, see function interface of tux_read()
|
|
char buttons[8][6] = {"START", "A", "B", "C", "Up", "Down", "Left", "Right"};
|
|
|
|
uint8_t prev_buttons = 0;
|
|
uint8_t curr_buttons = 0;
|
|
uint8_t quit_count = 0;
|
|
printf("Press START 3 times to quit\n");
|
|
while(1) {
|
|
if(FAIL == unified_read(fd_array, fd, &curr_buttons, sizeof(uint8_t))) return FAIL;
|
|
int i;
|
|
for(i = 0; i < 8; i++) {
|
|
if(!(prev_buttons & (1 << i)) && (curr_buttons & (1 << i))) {
|
|
// A button has been pressed
|
|
printf("Press ");
|
|
printf(buttons[i]);
|
|
printf("\n");
|
|
// Add counter for quit test every time START is pressed
|
|
if(i == 0) {
|
|
quit_count++;
|
|
} else {
|
|
quit_count = 0;
|
|
}
|
|
} else if((prev_buttons & (1 << i)) && !(curr_buttons & (1 << i))) {
|
|
// A button has been released
|
|
printf("Release ");
|
|
printf(buttons[i]);
|
|
printf("\n");
|
|
}
|
|
}
|
|
prev_buttons = curr_buttons;
|
|
|
|
// If START pressed more than 3 times in a row, quit
|
|
if(quit_count >= 3) break;
|
|
}
|
|
|
|
if(FAIL == unified_close(fd_array, fd)) return FAIL;
|
|
return PASS;
|
|
}
|
|
|
|
/* int unified_fs_tux_write()
|
|
* @output: PASS / FAIL
|
|
* @description: Tests setting tux's LED using Unified FS interface.
|
|
*/
|
|
int unified_fs_tux_write(fd_array_t* fd_array) {
|
|
TEST_HEADER;
|
|
|
|
// Tries to open both Tux and RTC
|
|
int32_t tux_fd;
|
|
if(FAIL == (tux_fd = unified_open(fd_array, "tux"))) return FAIL;
|
|
int32_t rtc_fd;
|
|
if(FAIL == (rtc_fd = unified_open(fd_array, "rtc"))) return FAIL;
|
|
uint32_t freq = 2;
|
|
if(FAIL == unified_write(fd_array, rtc_fd, &freq, sizeof(uint32_t))) return FAIL;
|
|
|
|
// sequence of strings to be displayed on Tux
|
|
char seq[16][6] = {
|
|
"T",
|
|
"TE",
|
|
"TEA",
|
|
"TEAM",
|
|
{'T', 'E', 'A', 'M', 0x01, 0},
|
|
{'T', 'E', 'A', 'M', 0x02, 0},
|
|
{'T', 'E', 'A', 'M', 0x04, 0},
|
|
{'T', 'E', 'A', 'M', 0x08, 0},
|
|
"N",
|
|
"NU",
|
|
"NUL",
|
|
"NULL",
|
|
{'N', 'U', 'L', 'L', 0x01, 0},
|
|
{'N', 'U', 'L', 'L', 0x02, 0},
|
|
{'N', 'U', 'L', 'L', 0x04, 0},
|
|
{'N', 'U', 'L', 'L', 0x08, 0}
|
|
};
|
|
|
|
// Display the strings, 3 loops total
|
|
int i = 0;
|
|
while(i < 16 * 3) {
|
|
if(FAIL == unified_write(fd_array, tux_fd, seq[i % 16], strlen(seq[i % 16]))) return FAIL;
|
|
// Wait 0.5s for each operation
|
|
if(FAIL == unified_read(fd_array, rtc_fd, NULL, 0)) return FAIL;
|
|
i++;
|
|
}
|
|
|
|
// Closes everything
|
|
if(FAIL == unified_close(fd_array, tux_fd)) return FAIL;
|
|
if(FAIL == unified_close(fd_array, rtc_fd)) return FAIL;
|
|
return PASS;
|
|
}
|
|
|
|
/* int sb16_play_music()
|
|
* Deprecated, use play command in shell - yuhuixu2
|
|
* @output: PASS / FAIL
|
|
* @description: Tests reading music from filesystem and playing it.
|
|
*/
|
|
#define TEST_SB16_CHUNK_SIZE 0x2000
|
|
#define TEST_SB16_SAMPLING_RATE 22050
|
|
char sb16_test_buf[TEST_SB16_CHUNK_SIZE];
|
|
int sb16_play_music(fd_array_t* fd_array) {
|
|
TEST_HEADER;
|
|
|
|
int32_t wav_fd;
|
|
if(FAIL == (wav_fd = unified_open(fd_array, "halloffame.wav"))) return FAIL;
|
|
int32_t aux_fd;
|
|
if(FAIL == (aux_fd = unified_open(fd_array, "aux"))) return FAIL;
|
|
|
|
// Copy over first chunk of music
|
|
int32_t size;
|
|
size = unified_read(fd_array, wav_fd, sb16_test_buf, TEST_SB16_CHUNK_SIZE);
|
|
if(size <= 0) return FAIL;
|
|
memset(sb16_test_buf + size, 0, TEST_SB16_CHUNK_SIZE - size);
|
|
if(size != unified_write(fd_array, aux_fd, sb16_test_buf, size)) return FAIL;
|
|
|
|
// Copy over second chunk
|
|
size = unified_read(fd_array, wav_fd, sb16_test_buf, TEST_SB16_CHUNK_SIZE);
|
|
if(size < 0) return FAIL;
|
|
memset(sb16_test_buf + size, 0, TEST_SB16_CHUNK_SIZE - size);
|
|
if(size > 0) {
|
|
if(size != unified_write(fd_array, aux_fd, sb16_test_buf, size)) return FAIL;
|
|
}
|
|
|
|
// Initialize SB16, note that we have to send command manually using ioctl
|
|
if(FAIL == unified_ioctl(fd_array, aux_fd, SB16_CMD_SAMPLING_RATE)) return FAIL;
|
|
if(FAIL == unified_ioctl(fd_array, aux_fd, (TEST_SB16_SAMPLING_RATE >> 8) & 0xff)) return FAIL;
|
|
if(FAIL == unified_ioctl(fd_array, aux_fd, TEST_SB16_SAMPLING_RATE & 0xff)) return FAIL;
|
|
if(FAIL == unified_ioctl(fd_array, aux_fd, SB16_CMD_PLAY)) return FAIL;
|
|
if(FAIL == unified_ioctl(fd_array, aux_fd, SB16_MODE_STEREO | SB16_MODE_UNSIGNED)) return FAIL;
|
|
if(FAIL == unified_ioctl(fd_array, aux_fd, (TEST_SB16_CHUNK_SIZE - 1) & 0xff)) return FAIL;
|
|
if(FAIL == unified_ioctl(fd_array, aux_fd, ((TEST_SB16_CHUNK_SIZE - 1) >> 8) & 0xff)) return FAIL;
|
|
|
|
// Continue playing the following blocks
|
|
while(1) {
|
|
// Wait until one block finished
|
|
if(FAIL == unified_read(fd_array, aux_fd, NULL, 0)) return FAIL;
|
|
// Tell SB16 to stop temporarily after this block, to handle slow FS operations better
|
|
if(FAIL == unified_ioctl(fd_array, aux_fd, SB16_CMD_EXIT_AFTER_BLOCK)) return FAIL;
|
|
|
|
// Read the next chunk of data, copy into block correspondingly
|
|
size = unified_read(fd_array, wav_fd, sb16_test_buf, TEST_SB16_CHUNK_SIZE);
|
|
if(size < 0) return FAIL; // FS error occured
|
|
memset(sb16_test_buf + size, 0, TEST_SB16_CHUNK_SIZE - size);
|
|
if(size == 0) break; // Music has finished
|
|
if(size != unified_write(fd_array, aux_fd, sb16_test_buf, size)) return FAIL;
|
|
if(FAIL == unified_ioctl(fd_array, aux_fd, SB16_CMD_CONTINUE)) return FAIL;
|
|
if(size < TEST_SB16_CHUNK_SIZE) {
|
|
// Wait until second last block finished
|
|
if(FAIL == unified_read(fd_array, aux_fd, NULL, 0)) return FAIL;
|
|
// The remaining data isn't sufficient for one block
|
|
// Finish after this block
|
|
if(FAIL == unified_ioctl(fd_array, aux_fd, SB16_CMD_EXIT_AFTER_BLOCK)) return FAIL;
|
|
break;
|
|
}
|
|
}
|
|
if(FAIL == unified_close(fd_array, wav_fd)) return FAIL;
|
|
if(FAIL == unified_close(fd_array, aux_fd)) return FAIL;
|
|
|
|
return PASS;
|
|
}
|
|
|
|
/* Test suite entry point */
|
|
void launch_tests(){
|
|
clear();
|
|
//TEST_OUTPUT("idt_test", idt_test());
|
|
// launch your tests here
|
|
|
|
// Checkpoint 1 - Added by jinghua3.
|
|
// TEST_OUTPUT("Video Memory Paging Test", videoMem_paging_test());
|
|
// TEST_OUTPUT("Kernel Memory Paging Test", kerMem_paging_test());
|
|
// TEST_OUTPUT("Paging Structure Test", paging_struct_test());
|
|
// dereferencing_null_test();
|
|
// division_by_zero_test();
|
|
// deref_nonexist_page_test();
|
|
|
|
// Checkpoint 2
|
|
// TEST_OUTPUT("ECE391FS Loaded", ece391fs_loaded());
|
|
// TEST_OUTPUT("ECE391FS Existent File", ece391fs_read_existent_file());
|
|
// TEST_OUTPUT("ECE391FS Nonexistent File", ece391fs_read_nonexistent_file());
|
|
// TEST_OUTPUT("ECE391FS Existent File", ece391fs_read_existent_idx());
|
|
// TEST_OUTPUT("ECE391FS Nonexistent File", ece391fs_read_nonexistent_idx());
|
|
// TEST_OUTPUT("ECE391FS Toolong File", ece391fs_read_toolong_file());
|
|
// TEST_OUTPUT("ECE391FS Large File", ece391fs_large_file());
|
|
// TEST_OUTPUT("ECE391FS List Directory", ece391fs_list_dir());
|
|
// TEST_OUTPUT("ECE391FS Interface Existent File", ece391fs_interface_read_existent_file());
|
|
// TEST_OUTPUT("ECE391FS Interface Nonexistent File", ece391fs_interface_read_nonexistent_file());
|
|
// TEST_OUTPUT("ECE391FS Interface Existent Directory", ece391fs_interface_read_existent_dir());
|
|
// TEST_OUTPUT("ECE391FS Interface Nonexistent Directory", ece391fs_interface_read_nonexistent_dir());
|
|
// TEST_OUTPUT("RTC Driver Read/Write Test", rtc_read_write_test());
|
|
// TEST_OUTPUT("Terminal Driver Write Test", terminal_driver_test());
|
|
|
|
// Checkpoint 3
|
|
// TEST_OUTPUT("Unified FS File", test_fdarray_wrapper(unified_fs_read_file));
|
|
// TEST_OUTPUT("Unified FS Dir", test_fdarray_wrapper(unified_fs_read_dir));
|
|
// TEST_OUTPUT("Unified FS Nonexistent File", test_fdarray_wrapper(unified_fs_read_nonexistent));
|
|
// TEST_OUTPUT("Unified FS Invalid FD", test_fdarray_wrapper(unified_fs_invalid_fd));
|
|
// TEST_OUTPUT("Unified FS RTC Read/Write", test_fdarray_wrapper(unified_fs_rtc_read_write));
|
|
// Checkpoint 4
|
|
// Checkpoint 5
|
|
|
|
// Extra features
|
|
// TEST_OUTPUT("Tux Controller Read", test_fdarray_wrapper(unified_fs_tux_read));
|
|
// TEST_OUTPUT("Tux Controller Write", test_fdarray_wrapper(unified_fs_tux_write));
|
|
|
|
// Deprecated / No longer works
|
|
// rtc_test();
|
|
// TEST_OUTPUT("Unified FS STDIO", test_fdarray_wrapper(unified_fs_stdio));
|
|
// TEST_OUTPUT("SB16 Play Music", test_fdarray_wrapper(sb16_play_music));
|
|
}
|