2014-10-29 08:01:22 -07:00
|
|
|
/**
|
|
|
|
* Copyright (c) 2014, Facebook, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD-style license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
*/
|
2014-04-28 12:36:36 -07:00
|
|
|
|
|
|
|
#include "Layout-test-utils.h"
|
2014-09-11 09:23:30 -07:00
|
|
|
#include <stdlib.h>
|
2014-04-28 12:36:36 -07:00
|
|
|
|
2015-05-09 13:03:21 +08:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#include <float.h>
|
|
|
|
#define isnan _isnan
|
|
|
|
__forceinline const float fmaxf(const float a, const float b) {
|
|
|
|
return (a > b) ? a : b;
|
|
|
|
}
|
|
|
|
__forceinline const float fminf(const float a, const float b) {
|
|
|
|
return (a < b) ? a : b;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-09-26 16:22:44 -07:00
|
|
|
/** START_GENERATED **/
|
2015-05-08 15:12:17 +08:00
|
|
|
#define SMALL_WIDTH 35
|
2015-04-26 14:11:05 +09:00
|
|
|
#define SMALL_HEIGHT 18
|
2015-05-08 15:12:17 +08:00
|
|
|
#define BIG_WIDTH 172
|
|
|
|
#define BIG_HEIGHT 37
|
|
|
|
#define BIG_MIN_WIDTH 100
|
2014-09-26 16:22:44 -07:00
|
|
|
#define SMALL_TEXT "small"
|
|
|
|
#define LONG_TEXT "loooooooooong with space"
|
|
|
|
/** END_GENERATED **/
|
|
|
|
|
2014-09-25 17:56:02 -07:00
|
|
|
typedef struct failed_test_t {
|
|
|
|
struct failed_test_t *next;
|
|
|
|
const char *name;
|
|
|
|
css_node_t *style;
|
|
|
|
css_node_t *expected;
|
|
|
|
} failed_test_t;
|
|
|
|
|
|
|
|
static failed_test_t *failed_test_head = NULL;
|
|
|
|
static failed_test_t *failed_test_tail = NULL;
|
|
|
|
static void add_failed_test(const char *name, css_node_t *style, css_node_t *expected) {
|
2015-05-09 13:03:21 +08:00
|
|
|
failed_test_t *failed_test = (failed_test_t *)malloc(sizeof(failed_test_t));
|
|
|
|
failed_test->next = NULL;
|
2014-09-25 17:56:02 -07:00
|
|
|
failed_test->name = name;
|
|
|
|
failed_test->style = style;
|
|
|
|
failed_test->expected = expected;
|
|
|
|
|
|
|
|
if (!failed_test_head) {
|
|
|
|
failed_test_head = failed_test;
|
|
|
|
failed_test_tail = failed_test;
|
|
|
|
} else {
|
|
|
|
failed_test_tail->next = failed_test;
|
|
|
|
failed_test_tail = failed_test;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-16 18:04:24 -07:00
|
|
|
static bool eq(float a, float b) {
|
|
|
|
return fabs(a - b) < 0.0001;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool are_layout_equal(css_node_t *a, css_node_t *b) {
|
|
|
|
if (!eq(a->layout.dimensions[CSS_WIDTH], b->layout.dimensions[CSS_WIDTH]) ||
|
|
|
|
!eq(a->layout.dimensions[CSS_HEIGHT], b->layout.dimensions[CSS_HEIGHT]) ||
|
|
|
|
!eq(a->layout.position[CSS_TOP], b->layout.position[CSS_TOP]) ||
|
|
|
|
!eq(a->layout.position[CSS_LEFT], b->layout.position[CSS_LEFT]) ||
|
|
|
|
!eq(a->children_count, b->children_count)) {
|
2014-04-28 12:36:36 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
for (int i = 0; i < a->children_count; ++i) {
|
2014-09-11 09:23:30 -07:00
|
|
|
if (!are_layout_equal(a->get_child(a->context, i), b->get_child(b->context, i))) {
|
2014-04-28 12:36:36 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-06-04 10:51:23 -07:00
|
|
|
css_dim_t measure(void *context, float width) {
|
2015-05-09 13:03:21 +08:00
|
|
|
const char *text = (const char *)context;
|
2014-04-28 12:36:36 -07:00
|
|
|
css_dim_t dim;
|
2014-06-04 10:51:23 -07:00
|
|
|
if (width != width) {
|
|
|
|
width = 1000000;
|
|
|
|
}
|
2014-09-26 16:22:44 -07:00
|
|
|
if (strcmp(text, SMALL_TEXT) == 0) {
|
|
|
|
dim.dimensions[CSS_WIDTH] = fminf(SMALL_WIDTH, width);
|
|
|
|
dim.dimensions[CSS_HEIGHT] = SMALL_HEIGHT;
|
2014-04-28 12:36:36 -07:00
|
|
|
return dim;
|
|
|
|
}
|
2014-09-26 16:22:44 -07:00
|
|
|
if (strcmp(text, LONG_TEXT) == 0) {
|
|
|
|
dim.dimensions[CSS_WIDTH] = width >= BIG_WIDTH ? BIG_WIDTH : fmaxf(BIG_MIN_WIDTH, width);
|
|
|
|
dim.dimensions[CSS_HEIGHT] = width >= BIG_WIDTH ? SMALL_HEIGHT : BIG_HEIGHT;
|
2014-04-28 12:36:36 -07:00
|
|
|
return dim;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should not go here
|
|
|
|
dim.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
|
|
|
|
dim.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
|
|
|
|
return dim;
|
|
|
|
}
|
|
|
|
|
2015-05-09 13:03:21 +08:00
|
|
|
static int test_ran_count = 0;
|
2014-04-28 12:36:36 -07:00
|
|
|
void test(const char *name, css_node_t *style, css_node_t *expected_layout) {
|
2015-05-09 13:03:21 +08:00
|
|
|
++test_ran_count;
|
|
|
|
|
2014-06-04 10:51:23 -07:00
|
|
|
layoutNode(style, CSS_UNDEFINED);
|
2014-04-28 12:36:36 -07:00
|
|
|
|
|
|
|
if (!are_layout_equal(style, expected_layout)) {
|
2014-09-25 17:56:02 -07:00
|
|
|
printf("%sF%s", "\x1B[31m", "\x1B[0m");
|
|
|
|
add_failed_test(name, style, expected_layout);
|
|
|
|
} else {
|
|
|
|
printf("%s.%s", "\x1B[32m", "\x1B[0m");
|
|
|
|
free_css_node(style);
|
|
|
|
free_css_node(expected_layout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-26 20:08:37 -07:00
|
|
|
int tests_finished() {
|
2014-09-25 17:56:02 -07:00
|
|
|
failed_test_t *failed_test = failed_test_head;
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
int tests_failed = 0;
|
|
|
|
while (failed_test) {
|
|
|
|
printf("%sFAIL%s %s\n", "\x1B[31m", "\x1B[0m", failed_test->name);
|
2014-04-28 12:36:36 -07:00
|
|
|
|
|
|
|
printf("Input: ");
|
2015-05-09 13:03:21 +08:00
|
|
|
print_css_node(failed_test->style, (css_print_options_t)(CSS_PRINT_STYLE | CSS_PRINT_CHILDREN));
|
2014-04-28 12:36:36 -07:00
|
|
|
printf("Output: ");
|
2015-05-09 13:03:21 +08:00
|
|
|
print_css_node(failed_test->style, (css_print_options_t)(CSS_PRINT_LAYOUT | CSS_PRINT_CHILDREN));
|
2014-04-28 12:36:36 -07:00
|
|
|
|
|
|
|
printf("Expected: ");
|
2015-05-09 13:03:21 +08:00
|
|
|
print_css_node(failed_test->expected, (css_print_options_t)(CSS_PRINT_LAYOUT | CSS_PRINT_CHILDREN));
|
2014-09-25 17:56:02 -07:00
|
|
|
|
|
|
|
free_css_node(failed_test->style);
|
|
|
|
free_css_node(failed_test->expected);
|
|
|
|
|
|
|
|
failed_test_t *next_failed_test = failed_test->next;
|
|
|
|
free(failed_test);
|
|
|
|
failed_test = next_failed_test;
|
|
|
|
|
|
|
|
tests_failed++;
|
2014-04-28 12:36:36 -07:00
|
|
|
}
|
2014-09-25 17:56:02 -07:00
|
|
|
printf("\n\n");
|
2014-04-28 12:36:36 -07:00
|
|
|
|
2014-09-25 17:56:02 -07:00
|
|
|
if (tests_failed > 0) {
|
|
|
|
printf("TESTS FAILED: %d\n", tests_failed);
|
2014-09-26 20:08:37 -07:00
|
|
|
return 1;
|
2014-09-25 17:56:02 -07:00
|
|
|
} else {
|
2015-05-09 13:03:21 +08:00
|
|
|
printf("ALL TESTS PASSED: %d tests ran.\n", test_ran_count);
|
2014-09-26 20:08:37 -07:00
|
|
|
return 0;
|
2014-09-25 17:56:02 -07:00
|
|
|
}
|
2014-04-28 12:36:36 -07:00
|
|
|
}
|
2014-09-11 09:23:30 -07:00
|
|
|
|
|
|
|
static css_node_t* get_child(void *context, int i) {
|
|
|
|
css_node_t* children = (css_node_t*)context;
|
|
|
|
return &children[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool is_dirty(void *context) {
|
|
|
|
(void)context; // remove unused warning
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void init_test_css_node(css_node_t *node) {
|
|
|
|
node->get_child = get_child;
|
|
|
|
node->is_dirty = is_dirty;
|
|
|
|
}
|
|
|
|
|
|
|
|
css_node_t *new_test_css_node(void) {
|
|
|
|
css_node_t *node = new_css_node();
|
|
|
|
init_test_css_node(node);
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
void init_css_node_children(css_node_t *node, int children_count) {
|
|
|
|
node->context = calloc((size_t)children_count, sizeof(css_node_t));
|
|
|
|
for (int i = 0; i < children_count; ++i) {
|
|
|
|
init_css_node(node->get_child(node->context, i));
|
|
|
|
init_test_css_node(node->get_child(node->context, i));
|
|
|
|
}
|
|
|
|
node->children_count = children_count;
|
|
|
|
}
|