2014-04-26 21:01:26 +00:00
|
|
|
/*
|
2015-10-22 05:13:26 +00:00
|
|
|
* Apple // emulator for *ix
|
2014-04-26 21:01:26 +00:00
|
|
|
*
|
|
|
|
* This software package is subject to the GNU General Public License
|
2015-10-22 05:13:26 +00:00
|
|
|
* version 3 or later (your choice) as published by the Free Software
|
2014-04-26 21:01:26 +00:00
|
|
|
* Foundation.
|
|
|
|
*
|
2015-10-22 05:13:26 +00:00
|
|
|
* Copyright 2013-2015 Aaron Culliney
|
2014-04-26 21:01:26 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "testcommon.h"
|
|
|
|
|
2014-12-28 22:50:43 +00:00
|
|
|
bool test_do_reboot = true;
|
2014-12-29 00:10:32 +00:00
|
|
|
char mdstr[(SHA_DIGEST_LENGTH*2)+1];
|
2014-12-28 22:50:43 +00:00
|
|
|
|
2016-07-24 00:34:59 +00:00
|
|
|
void (*testing_cyclesOverflow)(void) = NULL;
|
|
|
|
unsigned long (*testing_getCyclesCount)(void) = NULL;
|
|
|
|
|
2014-04-26 22:43:40 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2016-07-03 21:46:52 +00:00
|
|
|
void test_common_setup(void) {
|
2014-04-26 22:43:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void test_type_input(const char *input) {
|
2016-07-03 23:21:22 +00:00
|
|
|
debugger_setInputText(input, false);
|
2014-04-26 22:43:40 +00:00
|
|
|
}
|
|
|
|
|
2016-07-03 23:23:31 +00:00
|
|
|
void test_type_input_deterministically(const char *input) {
|
|
|
|
debugger_setInputText(input, true);
|
|
|
|
}
|
|
|
|
|
2014-04-26 21:01:26 +00:00
|
|
|
void test_breakpoint(void *arg) {
|
2015-09-07 00:14:38 +00:00
|
|
|
fprintf(GREATEST_STDOUT, "DISPLAY NOTE: busy-spinning in test_breakpoint(), needs gdb/lldb intervention to continue...\n");
|
|
|
|
volatile bool debug_continue = false;
|
|
|
|
while (!debug_continue) {
|
|
|
|
struct timespec ts = { .tv_sec=0, .tv_nsec=33333333 };
|
|
|
|
nanosleep(&ts, NULL);
|
2014-04-26 21:01:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-03 21:46:52 +00:00
|
|
|
void test_common_init(void) {
|
2014-04-26 21:01:26 +00:00
|
|
|
GREATEST_SET_BREAKPOINT_CB(test_breakpoint, NULL);
|
|
|
|
|
2016-04-13 05:24:04 +00:00
|
|
|
do_logging = false;// silence regular emulator logging
|
|
|
|
|
|
|
|
extern void emulator_ctors(void);
|
|
|
|
emulator_ctors();
|
|
|
|
|
|
|
|
char *envvar = NULL;
|
2016-07-18 02:09:46 +00:00
|
|
|
ASPRINTF(&envvar, "APPLE2IX_JSON=%s/.apple2.test.json", HOMEDIR);
|
2016-04-13 05:24:04 +00:00
|
|
|
assert(envvar);
|
|
|
|
putenv(envvar);
|
|
|
|
LEAK(envvar);
|
2014-04-26 21:01:26 +00:00
|
|
|
|
2016-03-26 21:20:57 +00:00
|
|
|
prefs_load();
|
2016-04-13 05:24:04 +00:00
|
|
|
prefs_setLongValue(PREF_DOMAIN_VIDEO, PREF_COLOR_MODE, COLOR);
|
2016-03-26 21:20:57 +00:00
|
|
|
prefs_setBoolValue(PREF_DOMAIN_KEYBOARD, PREF_KEYBOARD_CAPS, true);
|
2016-08-27 19:08:46 +00:00
|
|
|
prefs_setFloatValue(PREF_DOMAIN_VM, PREF_CPU_SCALE, (CPU_SCALE_FASTEST * 100.));
|
|
|
|
prefs_setFloatValue(PREF_DOMAIN_VM, PREF_CPU_SCALE_ALT, (CPU_SCALE_FASTEST * 100.));
|
2016-04-13 05:24:04 +00:00
|
|
|
prefs_save();
|
2014-04-26 21:01:26 +00:00
|
|
|
|
2015-09-07 04:03:59 +00:00
|
|
|
c_debugger_set_watchpoint(WATCHPOINT_ADDR);
|
2016-09-11 18:50:41 +00:00
|
|
|
|
|
|
|
fprintf(stderr, "NOTE : RUNNING WITH DISPLAY\n");
|
|
|
|
fprintf(stderr, "Will spinloop on failed tests for debugger intervention\n");
|
|
|
|
c_debugger_set_timeout(0);
|
2014-04-26 21:01:26 +00:00
|
|
|
}
|
2014-04-26 22:43:40 +00:00
|
|
|
|
2017-05-28 18:36:50 +00:00
|
|
|
#if defined(__APPLE__)
|
|
|
|
# define PATHS_COUNT 8
|
|
|
|
char **_copy_paths_mac(const char *fileName) {
|
2016-09-10 18:07:11 +00:00
|
|
|
const char *fmts[PATHS_COUNT + 1] = {
|
2016-07-18 02:27:32 +00:00
|
|
|
"%s%sdisks/%s",
|
|
|
|
"%s%sdisks/demo/%s",
|
|
|
|
"%s%sdisks/blanks/%s",
|
2016-08-01 02:48:26 +00:00
|
|
|
"%s%sdisks/3rd-party-test/%s",
|
2016-09-02 03:43:15 +00:00
|
|
|
"%s%sexternal-disks/%s",
|
|
|
|
"%s%sexternal-disks/demo/%s",
|
|
|
|
"%s%sexternal-disks/blanks/%s",
|
|
|
|
"%s%sexternal-disks/3rd-party-test/%s",
|
2015-12-17 05:01:50 +00:00
|
|
|
NULL,
|
|
|
|
};
|
2016-07-18 02:27:32 +00:00
|
|
|
|
2017-05-28 18:36:50 +00:00
|
|
|
char **paths = CALLOC(1, sizeof(fmts));
|
|
|
|
assert(paths);
|
|
|
|
|
2016-07-18 02:27:32 +00:00
|
|
|
# if TARGET_OS_SIMULATOR || !TARGET_OS_EMBEDDED
|
|
|
|
const char *prefixPath = "";
|
|
|
|
const char *sep = "";
|
|
|
|
# else // TARGET_OS_EMBEDDED
|
|
|
|
const char *prefixPath = data_dir;
|
|
|
|
const char *sep = "/";
|
|
|
|
# endif
|
|
|
|
|
|
|
|
do {
|
|
|
|
const char **fmtPtr = &fmts[0];
|
|
|
|
unsigned int idx = 0;
|
|
|
|
while (*fmtPtr) {
|
|
|
|
const char *fmt = *fmtPtr;
|
|
|
|
|
|
|
|
char *diskFile = NULL;
|
|
|
|
CFStringRef fileString = NULL;
|
|
|
|
CFURLRef fileURL = NULL;
|
|
|
|
|
2016-09-10 22:57:52 +00:00
|
|
|
int len = ASPRINTF(&diskFile, fmt, prefixPath, sep, fileName);
|
2016-07-18 02:27:32 +00:00
|
|
|
assert(diskFile);
|
|
|
|
fileString = CFStringCreateWithCString(kCFAllocatorDefault, diskFile, kCFStringEncodingUTF8);
|
|
|
|
assert(fileString);
|
|
|
|
|
|
|
|
# if TARGET_OS_SIMULATOR || !TARGET_OS_EMBEDDED
|
|
|
|
// Use disks directly out of bundle ... is this OKAY?
|
|
|
|
fileURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), fileString, NULL, NULL);
|
|
|
|
# else
|
|
|
|
// AppDelegate should have copied disks to a R/W location
|
|
|
|
fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, fileString, kCFURLPOSIXPathStyle, /*isDirectory*/false);
|
|
|
|
# endif
|
2016-09-10 22:57:52 +00:00
|
|
|
if (!fileURL) {
|
|
|
|
if (CFStringHasSuffix(fileString, CFSTR(".gz")) || CFStringHasSuffix(fileString, CFSTR(".GZ"))) {
|
|
|
|
*(diskFile + len - 3) = '\0';
|
|
|
|
CFRELEASE(fileString);
|
|
|
|
fileString = CFStringCreateWithCString(kCFAllocatorDefault, diskFile, kCFStringEncodingUTF8);
|
|
|
|
assert(fileString);
|
|
|
|
# if TARGET_OS_SIMULATOR || !TARGET_OS_EMBEDDED
|
|
|
|
// Use disks directly out of bundle ... is this OKAY?
|
|
|
|
fileURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), fileString, NULL, NULL);
|
|
|
|
# else
|
|
|
|
// AppDelegate should have copied disks to a R/W location
|
|
|
|
fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, fileString, kCFURLPOSIXPathStyle, /*isDirectory*/false);
|
|
|
|
# endif
|
2016-09-11 18:50:41 +00:00
|
|
|
}
|
2016-09-10 22:57:52 +00:00
|
|
|
}
|
|
|
|
|
2016-07-18 02:27:32 +00:00
|
|
|
if (fileURL) {
|
|
|
|
CFStringRef filePath = CFURLCopyFileSystemPath(fileURL, kCFURLPOSIXPathStyle);
|
|
|
|
assert(filePath);
|
|
|
|
CFIndex length = CFStringGetLength(filePath);
|
|
|
|
CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
|
|
|
|
char *disk0 = (char *)MALLOC(maxSize);
|
|
|
|
if (CFStringGetCString(filePath, disk0, maxSize, kCFStringEncodingUTF8)) {
|
|
|
|
paths[idx++] = disk0;
|
|
|
|
}
|
|
|
|
CFRELEASE(filePath);
|
|
|
|
CFRELEASE(fileURL);
|
|
|
|
}
|
|
|
|
|
|
|
|
FREE(diskFile);
|
|
|
|
CFRELEASE(fileString);
|
|
|
|
|
|
|
|
++fmtPtr;
|
|
|
|
}
|
|
|
|
} while (0);
|
2017-05-28 18:36:50 +00:00
|
|
|
|
|
|
|
return paths;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
# define PATHS_COUNT 8
|
|
|
|
# if defined(__ANDROID__)
|
|
|
|
# define X_PATHS_COUNT 1
|
|
|
|
# else
|
|
|
|
# define X_PATHS_COUNT 0
|
|
|
|
# endif
|
|
|
|
char **_copy_paths_main(const char *fileName) {
|
|
|
|
|
|
|
|
const char *fmts[PATHS_COUNT + X_PATHS_COUNT + 1] = {
|
|
|
|
"%s/disks/%s",
|
|
|
|
"%s/disks/demo/%s",
|
|
|
|
"%s/disks/blanks/%s",
|
|
|
|
"%s/disks/3rd-party-test/%s",
|
|
|
|
"%s/external-disks/%s",
|
|
|
|
"%s/external-disks/demo/%s",
|
|
|
|
"%s/external-disks/blanks/%s",
|
|
|
|
"%s/external-disks/3rd-party-test/%s",
|
|
|
|
# if defined(__ANDROID__)
|
|
|
|
// extra paths ...
|
|
|
|
"/sdcard/apple2ix/%s",
|
|
|
|
# endif
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
char **paths = CALLOC(1, sizeof(fmts));
|
|
|
|
assert(paths);
|
|
|
|
|
2016-07-18 02:27:32 +00:00
|
|
|
do {
|
2017-05-28 18:36:50 +00:00
|
|
|
const char *fmt = NULL;
|
2016-07-18 02:27:32 +00:00
|
|
|
const char **fmtPtr = &fmts[0];
|
|
|
|
unsigned int idx = 0;
|
|
|
|
while (*fmtPtr) {
|
2017-05-28 18:36:50 +00:00
|
|
|
fmt = *fmtPtr++;
|
|
|
|
if (idx < PATHS_COUNT) {
|
|
|
|
ASPRINTF(&paths[idx++], fmt, data_dir, fileName);
|
|
|
|
} else {
|
|
|
|
ASPRINTF(&paths[idx++], fmt, fileName);
|
|
|
|
}
|
2016-07-18 02:27:32 +00:00
|
|
|
}
|
2017-05-28 18:36:50 +00:00
|
|
|
|
2016-07-18 02:27:32 +00:00
|
|
|
} while (0);
|
2017-05-28 18:36:50 +00:00
|
|
|
|
|
|
|
return paths;
|
|
|
|
}
|
|
|
|
|
2014-10-12 19:24:54 +00:00
|
|
|
#endif
|
2015-12-17 05:01:50 +00:00
|
|
|
|
2017-05-28 18:36:50 +00:00
|
|
|
int test_setup_boot_disk(const char *fileName, int readonly) {
|
|
|
|
|
|
|
|
#if defined(__APPLE__)
|
|
|
|
char **paths = _copy_paths_mac(fileName);
|
|
|
|
#else
|
|
|
|
char **paths = _copy_paths_main(fileName);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
char **path = &paths[0];
|
2015-12-17 05:01:50 +00:00
|
|
|
while (*path) {
|
|
|
|
char *disk = *path;
|
|
|
|
++path;
|
|
|
|
|
2017-05-21 21:58:55 +00:00
|
|
|
int fd = -1;
|
|
|
|
TEMP_FAILURE_RETRY(fd = open(disk, readonly ? O_RDONLY : O_RDWR));
|
|
|
|
if (fd != -1) {
|
|
|
|
err = disk6_insert(fd, /*drive:*/0, disk, readonly) != NULL;
|
|
|
|
TEMP_FAILURE_RETRY(close(fd));
|
|
|
|
if (!err) {
|
|
|
|
break;
|
|
|
|
}
|
2015-12-17 05:01:50 +00:00
|
|
|
}
|
2014-10-12 19:24:54 +00:00
|
|
|
}
|
2015-12-17 05:01:50 +00:00
|
|
|
|
|
|
|
path = &paths[0];
|
|
|
|
while (*path) {
|
|
|
|
char *disk = *path;
|
|
|
|
++path;
|
2016-02-26 05:43:54 +00:00
|
|
|
FREE(disk);
|
2015-12-17 05:01:50 +00:00
|
|
|
}
|
|
|
|
|
2017-05-28 18:36:50 +00:00
|
|
|
FREE(paths);
|
|
|
|
|
2014-10-12 19:24:54 +00:00
|
|
|
return err;
|
|
|
|
}
|
2014-12-28 22:50:43 +00:00
|
|
|
|
|
|
|
void sha1_to_str(const uint8_t * const md, char *buf) {
|
|
|
|
int i=0;
|
|
|
|
for (int j=0; j<SHA_DIGEST_LENGTH; j++, i+=2) {
|
|
|
|
sprintf(buf+i, "%02X", md[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|