diff options
author | ridiculousfish <corydoras@ridiculousfish.com> | 2012-12-02 23:38:38 -0800 |
---|---|---|
committer | ridiculousfish <corydoras@ridiculousfish.com> | 2012-12-02 23:38:38 -0800 |
commit | 984a4980635c637057ada3efc9a213c0a1d037a9 (patch) | |
tree | d3843cf87733aa259be1aa9bb237e7c1a63eec03 /fish_tests.cpp | |
parent | c1b51c65302f2d2a8008d9d02c40b9bd594cc3e8 (diff) |
More work towards incremental history. Added some tests.
Diffstat (limited to 'fish_tests.cpp')
-rw-r--r-- | fish_tests.cpp | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/fish_tests.cpp b/fish_tests.cpp index ccf45337..0f7358b2 100644 --- a/fish_tests.cpp +++ b/fish_tests.cpp @@ -978,6 +978,9 @@ public: static void test_history(void); static void test_history_merge(void); static void test_history_formats(void); + + static void test_history_races(void); + static void test_history_races_pound_on_history(); }; static wcstring random_string(void) @@ -1077,6 +1080,121 @@ static void time_barrier(void) while (time(NULL) == start); } +static wcstring_list_t generate_history_lines(int pid) +{ + wcstring_list_t result; + long max = 256; + result.reserve(max); + for (long i=0; i < max; i++) + { + result.push_back(format_string(L"%ld %ld", (long)pid, i)); + } + return result; +} + +void history_tests_t::test_history_races_pound_on_history() +{ + /* Called in child process to modify history */ + history_t *hist = new history_t(L"race_test"); + hist->chaos_mode = true; + const wcstring_list_t lines = generate_history_lines(getpid()); + for (size_t idx = 0; idx < lines.size(); idx++) + { + const wcstring &line = lines.at(idx); + hist->add(line); + hist->save(); + } + delete hist; +} + +void history_tests_t::test_history_races(void) +{ + say(L"Testing history race conditions"); + + // Ensure history is clear + history_t *hist = new history_t(L"race_test"); + hist->clear(); + delete hist; + + // Test concurrent history writing +#define RACE_COUNT 20 + pid_t children[RACE_COUNT]; + + for (size_t i=0; i < RACE_COUNT; i++) + { + pid_t pid = fork(); + if (! pid) + { + // Child process + setup_fork_guards(); + test_history_races_pound_on_history(); + exit_without_destructors(0); + } + else + { + // Parent process + children[i] = pid; + } + } + + // Wait for all children + for (size_t i=0; i < RACE_COUNT; i++) + { + int stat; + waitpid(children[i], &stat, WUNTRACED); + } + + // Compute the expected lines + wcstring_list_t lines[RACE_COUNT]; + for (size_t i=0; i < RACE_COUNT; i++) + { + lines[i] = generate_history_lines(children[i]); + } + + // Count total lines + size_t line_count = 0; + for (size_t i=0; i < RACE_COUNT; i++) + { + line_count += lines[i].size(); + } + + // Ensure we consider the lines that have been outputted as part of our history + time_barrier(); + + /* Ensure that we got sane, sorted results */ + hist = new history_t(L"race_test"); + hist->chaos_mode = true; + size_t hist_idx; + for (hist_idx = 1; ; hist_idx ++) + { + history_item_t item = hist->item_at_index(hist_idx); + if (item.empty()) + break; + + // The item must be present in one of our 'lines' arrays + // If it is present, then every item after it is assumed to be missed + size_t i; + for (i=0; i < RACE_COUNT; i++) + { + wcstring_list_t::iterator where = std::find(lines[i].begin(), lines[i].end(), item.str()); + if (where != lines[i].end()) + { + // Delete everything from the found location onwards + lines[i].resize(where - lines[i].begin()); + + // Break because we found it + break; + } + } + assert(i < RACE_COUNT && "Line expected to be at end of some array"); + } + // every write should add at least one item + assert(hist_idx >= RACE_COUNT); + + //hist->clear(); + delete hist; +} + void history_tests_t::test_history_merge(void) { // In a single fish process, only one history is allowed to exist with the given name @@ -1310,6 +1428,7 @@ int main(int argc, char **argv) reader_init(); env_init(); +#if 0 test_format(); test_escape(); test_convert(); @@ -1323,8 +1442,11 @@ int main(int argc, char **argv) test_is_potential_path(); test_colors(); test_autosuggest_suggest_special(); +#endif history_tests_t::test_history(); history_tests_t::test_history_merge(); + history_tests_t::test_history_races(); + return 0; history_tests_t::test_history_formats(); say(L"Encountered %d errors in low-level tests", err_count); |