static void test_output(const char *out_data, DWORD out_size, const char *exp_data, DWORD exp_size) { const char *out_ptr = out_data, *exp_ptr = exp_data, *out_nl, *exp_nl, *err; DWORD line = 0; while(out_ptr < out_data+out_size && exp_ptr < exp_data+exp_size) { line++; for(exp_nl = exp_ptr; exp_nl < exp_data+exp_size && *exp_nl != '\r' && *exp_nl != '\n'; exp_nl++); for(out_nl = out_ptr; out_nl < out_data+out_size && *out_nl != '\r' && *out_nl != '\n'; out_nl++); err = compare_line(out_ptr, out_nl, exp_ptr, exp_nl); if(err == out_nl) ok(0, "unexpected end of line %d (got '%.*s', wanted '%.*s')\n", line, (int)(out_nl-out_ptr), out_ptr, (int)(exp_nl-exp_ptr), exp_ptr); else if(err) ok(0, "unexpected char 0x%x position %d in line %d (got '%.*s', wanted '%.*s')\n", *err, (int)(err-out_ptr), line, (int)(out_nl-out_ptr), out_ptr, (int)(exp_nl-exp_ptr), exp_ptr); exp_ptr = exp_nl+1; out_ptr = out_nl+1; if(out_nl+1 < out_data+out_size && out_nl[0] == '\r' && out_nl[1] == '\n') out_ptr++; if(exp_nl+1 < exp_data+exp_size && exp_nl[0] == '\r' && exp_nl[1] == '\n') exp_ptr++; } ok(exp_ptr >= exp_data+exp_size, "unexpected end of output in line %d, missing %s\n", line, exp_ptr); ok(out_ptr >= out_data+out_size, "too long output, got additional %s\n", out_ptr); }
static void test_output(const char *out_data, DWORD out_size, const char *exp_data, DWORD exp_size) { const char *out_ptr = out_data, *exp_ptr = exp_data, *out_nl, *exp_nl, *err; DWORD line = 0; static const char todo_wine_cmd[] = {'@','t','o','d','o','_','w','i','n','e','@'}; static const char resync_cmd[] = {'-','-','-'}; BOOL is_todo_wine, is_out_resync, is_exp_resync; while(out_ptr < out_data+out_size && exp_ptr < exp_data+exp_size) { line++; for(exp_nl = exp_ptr; exp_nl < exp_data+exp_size && *exp_nl != '\r' && *exp_nl != '\n'; exp_nl++); for(out_nl = out_ptr; out_nl < out_data+out_size && *out_nl != '\r' && *out_nl != '\n'; out_nl++); is_todo_wine = (exp_ptr+sizeof(todo_wine_cmd) <= exp_nl && !memcmp(exp_ptr, todo_wine_cmd, sizeof(todo_wine_cmd))); if (is_todo_wine) { exp_ptr += sizeof(todo_wine_cmd); winetest_start_todo("wine"); } is_exp_resync=(exp_ptr+sizeof(resync_cmd) <= exp_nl && !memcmp(exp_ptr, resync_cmd, sizeof(resync_cmd))); is_out_resync=(out_ptr+sizeof(resync_cmd) <= out_nl && !memcmp(out_ptr, resync_cmd, sizeof(resync_cmd))); err = compare_line(out_ptr, out_nl, exp_ptr, exp_nl); if(err == out_nl) ok(0, "unexpected end of line %d (got '%.*s', wanted '%.*s')\n", line, (int)(out_nl-out_ptr), out_ptr, (int)(exp_nl-exp_ptr), exp_ptr); else if(err == exp_nl) ok(0, "excess characters on line %d (got '%.*s', wanted '%.*s')\n", line, (int)(out_nl-out_ptr), out_ptr, (int)(exp_nl-exp_ptr), exp_ptr); else if (!err && is_todo_wine && is_out_resync && is_exp_resync) /* Consider that the todo_wine was to deal with extra lines, * not for the resync line itself */ err = NULL; else ok(!err, "unexpected char 0x%x position %d in line %d (got '%.*s', wanted '%.*s')\n", (err ? *err : 0), (err ? (int)(err-out_ptr) : -1), line, (int)(out_nl-out_ptr), out_ptr, (int)(exp_nl-exp_ptr), exp_ptr); if(is_todo_wine) winetest_end_todo("wine"); if (is_exp_resync && err && is_todo_wine) { exp_ptr -= sizeof(todo_wine_cmd); /* If we rewind to the beginning of the line, don't increment line number */ line--; } else if (!is_exp_resync || (is_exp_resync && !err)) { exp_ptr = exp_nl+1; if(exp_nl+1 < exp_data+exp_size && exp_nl[0] == '\r' && exp_nl[1] == '\n') exp_ptr++; } if (!is_out_resync || (is_out_resync && !err)) { out_ptr = out_nl+1; if(out_nl+1 < out_data+out_size && out_nl[0] == '\r' && out_nl[1] == '\n') out_ptr++; } } ok(exp_ptr >= exp_data+exp_size, "unexpected end of output in line %d, missing %s\n", line, exp_ptr); ok(out_ptr >= out_data+out_size, "too long output, got additional %s\n", out_ptr); }
// Compare Lines is n^2. We can make this faster by precomputing a hash that stores the line // In an ideal world this would generate a directed graph, and the best fit would be the longest path static match_ll_t *generate_matches(lcll_t *lfile_cmp, lcll_t *rfile_cmp, int ignore_ws) { lcll_t *ll_iter = lfile_cmp, *rl_iter = rfile_cmp; lcll_t *temp_ll = ll_iter; size_t l_idx = 0, r_idx = 0; match_t temp_match, *new_match; match_ll_t *match_list = NULL, *new_ml_item, *ml_iter, *prev_ml_iter; int found_match = 0; while (ll_iter) { rl_iter = rfile_cmp; r_idx = 0; while (rl_iter) { temp_ll = ll_iter; found_match = 0; cgc_memset(&temp_match, 0, sizeof(match_t)); while (temp_ll && rl_iter && compare_line(temp_ll->lc, rl_iter->lc, ignore_ws) == 0) { if (!found_match) { temp_match.l_idx = l_idx; temp_match.r_idx = r_idx; temp_match.length = 1; found_match = 1; } else { temp_match.length++; } temp_ll = temp_ll->next; rl_iter = rl_iter->next; r_idx++; } if (found_match) { new_match = malloc(sizeof(match_t)); if (!new_match) return match_list; cgc_memcpy(new_match, &temp_match, sizeof(match_t)); new_ml_item = malloc(sizeof(match_ll_t)); if (!new_ml_item) { free(new_match); return match_list; } new_ml_item->match = new_match; new_ml_item->next = NULL; if (!match_list) { match_list = new_ml_item; } else { ml_iter = match_list; prev_ml_iter = ml_iter; while (ml_iter) { if (ml_iter->match->r_idx < new_match->r_idx) { if ((ml_iter->match->r_idx + ml_iter->match->length) >= (new_match->r_idx + new_match->length)) { free(new_ml_item->match); free(new_ml_item); break; } else { if (ml_iter->next) { prev_ml_iter = ml_iter; ml_iter = ml_iter->next; } else { ml_iter->next = new_ml_item; break; } } } else { if(ml_iter == match_list) { new_ml_item->next = ml_iter; match_list = new_ml_item; } else { new_ml_item->next = ml_iter; prev_ml_iter->next = new_ml_item; } break; } } } } else { rl_iter = rl_iter->next; r_idx++; } } ll_iter = ll_iter->next; l_idx++; } return match_list; }