bool test_contrib_windows(flow_c * context, char * msg) { int bad = -1; struct flow_interpolation_line_contributions * lct = 0; // assumes included edge cases struct flow_interpolation_details *triangle = flow_interpolation_details_create_from( context, flow_interpolation_filter::flow_interpolation_filter_Triangle); unsigned int from_w = 6; unsigned int to_w = 3; unsigned int corr36[3][2] = { { 0, 2 }, { 1, 4 }, { 3, 5 } }; lct = flow_interpolation_line_contributions_create(context, to_w, from_w, triangle); for (uint32_t i = 0; i < lct->LineLength; i++) if (lct->ContribRow[i].Left != (int)corr36[i][0]) { bad = i; break; } else if (lct->ContribRow[i].Right != (int)corr36[i][1]) { bad = i; break; } if (bad != -1) { flow_snprintf(msg, 255, "at 6->3 invalid value (%d; %d) at %d, expected (%d; %d)", lct->ContribRow[bad].Left, lct->ContribRow[bad].Right, bad, corr36[bad][0], corr36[bad][1]); flow_interpolation_line_contributions_destroy(context, lct); return false; } flow_interpolation_line_contributions_destroy(context, lct); from_w = 6; to_w = 4; unsigned int corr46[4][2] = { { 0, 1 }, { 1, 3 }, { 2, 4 }, { 4, 5 } }; lct = flow_interpolation_line_contributions_create(context, to_w, from_w, triangle); flow_interpolation_details_destroy(context, triangle); for (uint32_t i = 0; i < lct->LineLength; i++) if (lct->ContribRow[i].Left != (int)corr46[i][0]) { bad = i; break; } else if (lct->ContribRow[i].Right != (int)corr46[i][1]) { bad = i; break; } if (bad != -1) { flow_snprintf(msg, 255, "at 6->4 invalid value (%d; %d) at %d, expected (%d; %d)", lct->ContribRow[bad].Left, lct->ContribRow[bad].Right, bad, corr46[bad][0], corr46[bad][1]); flow_interpolation_line_contributions_destroy(context, lct); return false; } flow_interpolation_line_contributions_destroy(context, lct); return true; }
static bool checksum_bitmap(flow_c * c, struct flow_bitmap_bgra * bitmap, char * checksum_buffer, size_t checksum_buffer_length) { char info_buffer[256]; flow_snprintf(&info_buffer[0], sizeof(info_buffer), "%dx%d fmt=%d alpha=%d", bitmap->w, bitmap->h, bitmap->fmt, bitmap->alpha_meaningful); int64_t printed_chars = (flow_snprintf(checksum_buffer, checksum_buffer_length, "%016X_%016X", djb2_buffer((uint8_t *)bitmap->pixels, bitmap->stride * bitmap->h), djb2((unsigned const char *)&info_buffer[0]))); return printed_chars != -1; }
bool test_details(flow_c * context, struct flow_interpolation_details * details, char * msg, double expected_first_crossing, double expected_second_crossing, double expected_near0, double near0_threshold, double expected_end) { double top = (*details->filter)(details, 0); // Verify peak is at x = 0 if (!function_bounded_bi(context, details, msg, 0, expected_end, 0.05, -500, top, "should peak at x=0")) return false; // Verify we drop below a certain threshold between expected_near0 and expected_second_crossing or expected_end if (!function_bounded_bi(context, details, msg, expected_near0, expected_second_crossing > 0 ? expected_second_crossing : expected_end, 0.05, -500, near0_threshold, "should near 0")) return false; char sub_msg[1024]; flow_snprintf(sub_msg, 1024, "should end at expected_end (%f)", expected_end); // Ensure ended at expected_end if (!function_bounded_bi(context, details, msg, expected_end, expected_end + 1, 0.05, -0.0001f, 0.0001f, sub_msg)) return false; if (expected_first_crossing != 0 && expected_second_crossing != 0) { // Ensure everything between the two crossings is negative if (!function_bounded_bi(context, details, msg, expected_first_crossing + 0.05, expected_second_crossing - 0.05, 0.05, -500, -0.0001f, "should be negative between crossing 1 and 2")) return false; // Ensure everything between second crossing and end is positive - if significant if (expected_end > expected_second_crossing + 0.1) { flow_snprintf(sub_msg, 1024, "should be positive between crossing 2 (%f) and end (%f)", expected_second_crossing, expected_end); if (!function_bounded_bi(context, details, msg, expected_second_crossing + 0.05, expected_end - 0.02, 0.02, 0, 500, sub_msg)) return false; } } else { // Ensure everything is non-negative if (!function_bounded_bi(context, details, msg, expected_near0, expected_end, 0.05, -0.0001, 500, "this function should only produce positive weights")) return false; } return true; }
static bool diff_images(flow_c * c, char * checksum_a, char * checksum_b, double * out_dssim, bool generate_visual_diff, const char * storage_relative_to) { char filename_a[2048]; if (!create_path_from_relative(c, storage_relative_to, false, filename_a, 2048, "/visuals/%s.png", checksum_a)) { FLOW_add_to_callstack(c); return false; } char filename_b[2048]; if (!create_path_from_relative(c, storage_relative_to, false, filename_b, 2048, "/visuals/%s.png", checksum_b)) { FLOW_add_to_callstack(c); return false; } char filename_c[2048]; if (!create_path_from_relative(c, storage_relative_to, false, filename_c, 2048, "/visuals/compare_%s_vs_%s.png", checksum_a, checksum_b)) { FLOW_add_to_callstack(c); return false; } char magick_command[4096]; flow_snprintf(magick_command, 4096, "dssim %s %s", filename_b, filename_a); *out_dssim = get_dssim_from_command(c, magick_command); if (*out_dssim > 10 || *out_dssim < 0) { fprintf(stderr, "Failed to execute: %s", magick_command); *out_dssim = 2.23456; // FLOW_error(c, flow_status_IO_error); }; if (generate_visual_diff) { fprintf(stderr, "%s\n", &filename_c[0]); if (access(filename_c, F_OK) != -1) { return true; // Already exists! } flow_snprintf(magick_command, 4096, "composite %s %s -compose difference %s", filename_a, filename_b, filename_c); int result = system(magick_command); if (result != 0) { fprintf(stderr, "unhappy imagemagick\n"); } } return true; }
char * test_filter(flow_c * context, flow_interpolation_filter filter, char * msg, double expected_first_crossing, double expected_second_crossing, double expected_near0, double near0_threshold, double expected_end) { struct flow_interpolation_details * details = flow_interpolation_details_create_from(context, filter); flow_snprintf(msg, 255, "Filter=(%d) ", filter); bool result = test_details(context, details, msg, expected_first_crossing, expected_second_crossing, expected_near0, near0_threshold, expected_end); flow_interpolation_details_destroy(context, details); if (!result) return msg; else return nullptr; }
bool function_bounded(flow_c * context, struct flow_interpolation_details * details, char * msg, double input_start_value, double stop_at_abs, double input_step, double result_low_threshold, double result_high_threshold, const char * name) { double input_value = input_start_value; if (fabs(input_value) >= fabs(stop_at_abs)) return true; double result_value = (*details->filter)(details, input_value); if (result_value < result_low_threshold) { flow_snprintf(msg + strlen(msg), 255 - strlen(msg), "value %.4f is below %.4f at x=%.4f (%s)", result_value, result_low_threshold, input_value, name); return false; } else if (result_value > result_high_threshold) { flow_snprintf(msg + strlen(msg), 255 - strlen(msg), "value %.4f exceeds %.4f at x=%.4f (%s)", result_value, result_high_threshold, input_value, name); return false; } return function_bounded(context, details, msg, input_value + input_step, stop_at_abs, input_step, result_low_threshold, result_high_threshold, name); }
static bool download_by_checksum(flow_c * c, char * checksum, const char * storage_relative_to) { char filename[2048]; if (!create_path_from_relative(c, storage_relative_to, true, filename, 2048, "/visuals/%s.png", checksum)) { FLOW_add_to_callstack(c); return false; } fprintf(stderr, "%s (trusted)\n", &filename[0]); if (access(filename, F_OK) != -1) { return true; // Already exists! } char url[2048]; flow_snprintf(url, 2048, "http://s3-us-west-2.amazonaws.com/imageflow-resources/visual_test_checksums/%s.png", checksum); // TODO: fix actual URL if (!fetch_image(url, filename)) { FLOW_add_to_callstack(c); return false; } return true; }