gentest for Java and C#

Summary:
- Revise scripts to generate Java and C# unittests using the same HTML fixtures as well as C for code coverage.
- Add wrap_column test workaround in gentest.js.
- Add checkDefaultValues for sanity check of the CSSLayout default values by test-template.html
- Add `align-content: flex-start;` in default div to align with CSSLayout default

    $ cd csharp/gentest
    $ ruby gentest.rb

- macOS example for C#

    $ cd csharp/tests/Facebook.CSSLayout
    $ clang -DCSS_ASSERT_FAIL_ENABLED -Wall -Wextra -dynamiclib -o libCSSLayout.dylib -g -I../../.. ../../../CSSLayout/*.c ../../CSSLayout/CSSInterop.cpp
    $ mcs -debug -t:library -r:nunit.framework.dll -out:CSSLayoutTest.dll *.cs ../../../csharp/Facebook.CSSLayout/*cs
    $ mono64 --debug nunit-console.exe CSSLayoutTest.dll

Reviewed By: emilsjolander

Differential Revision: D4053777

fbshipit-source-id: 84450208015e65baf604987bd56c6a268598b545
This commit is contained in:
Kazuki Sakamoto
2016-10-23 10:27:30 -07:00
committed by Facebook Github Bot
parent 1488f822c3
commit dc5e613285
23 changed files with 1250 additions and 222 deletions

View File

@@ -0,0 +1,21 @@
<div id="absolute_layout_width_height_start_top" style="width: 100px; height: 100px;">
<div style="width:10px; height: 10px; position: absolute; start: 10px; top: 10px;"></div>
</div>
<div id="absolute_layout_width_height_end_bottom" style="width: 100px; height: 100px;">
<div style="width:10px; height: 10px; position: absolute; end: 10px; bottom: 10px;"></div>
</div>
<div id="absolute_layout_start_top_end_bottom" style="width: 100px; height: 100px;">
<div style="position: absolute; start: 10px; top: 10px; end: 10px; bottom: 10px;"></div>
</div>
<div id="absolute_layout_width_height_start_top_end_bottom" style="width: 100px; height: 100px;">
<div style="width:10px; height: 10px; position: absolute; start: 10px; top: 10px; end: 10px; bottom: 10px;"></div>
</div>
<div id="do_not_clamp_height_of_absolute_node_to_height_of_its_overflow_hidden_parent" style="height: 50px; width: 50px; overflow: hidden; flex-direction: row;">
<div style="position: absolute; start: 0; top: 0;">
<div style="width: 100px; height: 100px;"></div>
</div>
</div>

View File

@@ -0,0 +1,31 @@
<div id="align_content_flex_start" style="width: 100px; height: 100px; flex-wrap: wrap; flex-direction: column; align-content: flex-start;">
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
</div>
<div id="align_content_flex_end" style="width: 100px; height: 100px; flex-wrap: wrap; flex-direction: column; align-content: flex-end;">
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
</div>
<div id="align_content_center" style="width: 100px; height: 100px; flex-wrap: wrap; flex-direction: column; align-content: center;">
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
</div>
<div id="align_content_stretch" style="width: 100px; height: 100px; flex-wrap: wrap; flex-direction: column; align-content: stretch;">
<div style="width: 50px;"></div>
<div style="width: 50px;"></div>
<div style="width: 50px;"></div>
<div style="width: 50px;"></div>
<div style="width: 50px;"></div>
</div>

View File

@@ -0,0 +1,15 @@
<div id="align_items_stretch" style="width: 100px; height: 100px;">
<div style="height: 10px;"></div>
</div>
<div id="align_items_center" style="width: 100px; height: 100px; align-items: center;">
<div style="height: 10px; width: 10px;"></div>
</div>
<div id="align_items_flex_start" style="width: 100px; height: 100px; align-items: flex-start;">
<div style="height: 10px; width: 10px;"></div>
</div>
<div id="align_items_flex_end" style="width: 100px; height: 100px; align-items: flex-end;">
<div style="height: 10px; width: 10px;"></div>
</div>

View File

@@ -0,0 +1,15 @@
<div id="align_self_center" style="width:100px; height: 100px;">
<div style="height: 10px; width: 10px; align-self: center;"></div>
</div>
<div id="align_self_flex_end" style="width:100px; height: 100px;">
<div style="height: 10px; width: 10px; align-self: flex-end;"></div>
</div>
<div id="align_self_flex_start" style="width:100px; height: 100px;">
<div style="height: 10px; width: 10px; align-self: flex-start;"></div>
</div>
<div id="align_self_flex_end_override_flex_start" style="width:100px; height: 100px; align-items: flex-start;">
<div style="height: 10px; width: 10px; align-self: flex-end;"></div>
</div>

View File

@@ -0,0 +1,18 @@
<div id="border_no_size" style="border-width: 10px;">
</div>
<div id="border_container_match_child" style="border-width: 10px;">
<div style="width: 10px; height: 10px;"></div>
</div>
<div id="border_flex_child" style="width: 100px; height: 100px; border-width: 10px;">
<div style="width: 10px; flex-grow:1"></div>
</div>
<div id="border_stretch_child" style="width: 100px; height: 100px; border-width: 10px;">
<div style="height: 10px;"></div>
</div>
<div id="border_center_child" style="width: 100px; height: 100px; border-start-width: 10px; border-top-width: 10; border-end-width: 20px; border-bottom-width: 20px; align-items: center; justify-content: center;">
<div style="height: 10px; width: 10px;"></div>
</div>

View File

@@ -0,0 +1,35 @@
<div id="flex_direction_column_no_height" style="width: 100px">
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
</div>
<div id="flex_direction_row_no_width" style="height: 100px; flex-direction: row;">
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
</div>
<div id="flex_direction_column" style="height: 100px; width: 100px;">
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
</div>
<div id="flex_direction_row" style="height: 100px; width: 100px; flex-direction: row;">
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
</div>
<div id="flex_direction_column_reverse" style="height: 100px; width: 100px; flex-direction: column-reverse;">
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
</div>
<div id="flex_direction_row_reverse" style="height: 100px; width: 100px; flex-direction: row-reverse;">
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
</div>

View File

@@ -0,0 +1,31 @@
<div id="flex_basis_flex_grow_column" style="width: 100px; height: 100px;">
<div style="flex-basis: 50px; flex-grow: 1;"></div>
<div style="flex-grow: 1;"></div>
</div>
<div id="flex_basis_flex_grow_row" style="width: 100px; height: 100px; flex-direction: row;">
<div style="flex-basis: 50px; flex-grow: 1;"></div>
<div style="flex-grow: 1;"></div>
</div>
<div id="flex_basis_flex_shrink_column" style="width: 100px; height: 100px;">
<div style="flex-basis: 100px; flex-shrink: 1;"></div>
<div style="flex-basis: 50px;"></div>
</div>
<div id="flex_basis_flex_shrink_row" style="width: 100px; height: 100px; flex-direction: row;">
<div style="flex-basis: 100px; flex-shrink: 1;"></div>
<div style="flex-basis: 50px;"></div>
</div>
<div id="flex_shrink_to_zero" style="height: 75px;">
<div style="width: 50px; height: 50px; flex-shrink:0;"></div>
<div style="width: 50px; height: 50px; flex-shrink:1;"></div>
<div style="width: 50px; height: 50px; flex-shrink:0;"></div>
</div>
<div id="flex_basis_overrides_main_size" style="height: 100px; width: 100px;">
<div style="height: 20px; flex-grow:1; flex-basis:50px;"></div>
<div style="height: 10px; flex-grow:1;"></div>
<div style="height: 10px; flex-grow:1;"></div>
</div>

View File

@@ -0,0 +1,27 @@
<div id="wrap_column" style="height: 100px; flex-wrap: wrap">
<div style="height: 30px; width: 30px;"></div>
<div style="height: 30px; width: 30px;"></div>
<div style="height: 30px; width: 30px;"></div>
<div style="height: 30px; width: 30px;"></div>
</div>
<div id="wrap_row" style="width: 100px; flex-direction: row; flex-wrap: wrap">
<div style="height: 30px; width: 30px;"></div>
<div style="height: 30px; width: 30px;"></div>
<div style="height: 30px; width: 30px;"></div>
<div style="height: 30px; width: 30px;"></div>
</div>
<div id="wrap_row_align_items_flex_end" style="width: 100px; flex-direction: row; flex-wrap: wrap; align-items: flex-end;">
<div style="height: 10px; width: 30px;"></div>
<div style="height: 20px; width: 30px;"></div>
<div style="height: 30px; width: 30px;"></div>
<div style="height: 30px; width: 30px;"></div>
</div>
<div id="wrap_row_align_items_center" style="width: 100px; flex-direction: row; flex-wrap: wrap; align-items: center;">
<div style="height: 10px; width: 30px;"></div>
<div style="height: 20px; width: 30px;"></div>
<div style="height: 30px; width: 30px;"></div>
<div style="height: 30px; width: 30px;"></div>
</div>

View File

@@ -0,0 +1,59 @@
<div id="justify_content_row_flex_start" style="width: 102px; height: 102px; flex-direction: row; justify-content: flex-start;">
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
</div>
<div id="justify_content_row_flex_end" style="width: 102px; height: 102px; flex-direction: row; justify-content: flex-end;">
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
</div>
<div id="justify_content_row_center" style="width: 102px; height: 102px; flex-direction: row; justify-content: center;">
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
</div>
<div id="justify_content_row_space_between" style="width: 102px; height: 102px; flex-direction: row; justify-content: space-between;">
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
</div>
<div id="justify_content_row_space_around" style="width: 102px; height: 102px; flex-direction: row; justify-content: space-around;">
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
</div>
<div id="justify_content_column_flex_start" style="width: 102px; height: 102px; justify-content: flex-start;">
<div style="height: 10px;"></div>
<div style="heigth: 10px;"></div>
<div style="height: 10px;"></div>
</div>
<div id="justify_content_column_flex_end" style="width: 102px; height: 102px; justify-content: flex-end;">
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
</div>
<div id="justify_content_column_center" style="width: 102px; height: 102px; justify-content: center;">
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
</div>
<div id="justify_content_column_space_between" style="width: 102px; height: 102px; justify-content: space-between;">
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
</div>
<div id="justify_content_column_space_around" style="width: 102px; height: 102px; justify-content: space-around;">
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
</div>

View File

@@ -0,0 +1,41 @@
<div id="margin_start" style="width: 100px; height: 100px; flex-direction: row;">
<div style="width: 10px; margin-start: 10px;"></div>
</div>
<div id="margin_top" style="width: 100px; height: 100px;">
<div style="height: 10px; margin-top: 10px;"></div>
</div>
<div id="margin_end" style="width: 100px; height: 100px; flex-direction: row; justify-content: flex-end;">
<div style="width: 10px; margin-end: 10px;"></div>
</div>
<div id="margin_bottom" style="width: 100px; height: 100px; justify-content: flex-end;">
<div style="height: 10px; margin-bottom: 10px;"></div>
</div>
<div id="margin_and_flex_row" style="width: 100px; height: 100px; flex-direction: row;">
<div style="margin-start: 10px; margin-end; 10px; flex-grow: 1;"></div>
</div>
<div id="margin_and_flex_column" style="width: 100px; height: 100px;">
<div style="margin-top: 10px; margin-bottom; 10px; flex-grow: 1;"></div>
</div>
<div id="margin_and_stretch_row" style="width: 100px; height: 100px; flex-direction: row;">
<div style="margin-top: 10px; margin-bottom; 10px; flex-grow: 1;"></div>
</div>
<div id="margin_and_stretch_column" style="width: 100px; height: 100px;">
<div style="margin-start: 10px; margin-end; 10px; flex-grow: 1;"></div>
</div>
<div id="margin_with_sibling_row" style="width: 100px; height: 100px; flex-direction: row;">
<div style="margin-end; 10px; flex-grow: 1;"></div>
<div style="flex-grow: 1;"></div>
</div>
<div id="margin_with_sibling_column" style="width: 100px; height: 100px;">
<div style="margin-bottom; 10px; flex-grow: 1;"></div>
<div style="flex-grow: 1;"></div>
</div>

View File

@@ -0,0 +1,31 @@
<div id="max_width" style="width: 100px; height: 100px;">
<div style="height: 10px; max-width: 50px;"></div>
</div>
<div id="max_height" style="width: 100px; height: 100px; flex-direction: row;">
<div style="width: 10px; max-height: 50px;"></div>
</div>
<div id="min_height" style="width: 100px; height: 100px;">
<div style="flex-grow: 1; min-height: 60px;"></div>
<div style="flex-grow: 1;"></div>
</div>
<div id="min_width" style="width: 100px; height: 100px; flex-direction: row">
<div style="flex-grow: 1; min-width: 60px;"></div>
<div style="flex-grow: 1;"></div>
</div>
<div id="justify_content_min_max" style="max-height: 200px; min-height: 100px; width: 100px; justify-content: center;">
<div style="width: 60px; height: 60px;"></div>
</div>
<div id="align_items_min_max" style="max-width: 200px; min-width: 100px; height: 100px; align-items: center;">
<div style="width: 60px; height: 60px;"></div>
</div>
<div id="justify_content_overflow_min_max" style="min-height: 100px; max-height: 110px; justify-content: center;">
<div style="width: 50px; height: 50px;"></div>
<div style="width: 50px; height: 50px;"></div>
<div style="width: 50px; height: 50px;"></div>
</div>

View File

@@ -0,0 +1,18 @@
<div id="padding_no_size" style="padding: 10px;">
</div>
<div id="padding_container_match_child" style="padding: 10px;">
<div style="width: 10px; height: 10px;"></div>
</div>
<div id="padding_flex_child" style="width: 100px; height: 100px; padding: 10px;">
<div style="width: 10px; flex-grow:1"></div>
</div>
<div id="padding_stretch_child" style="width: 100px; height: 100px; padding: 10px;">
<div style="height: 10px;"></div>
</div>
<div id="padding_center_child" style="width: 100px; height: 100px; padding-start: 10px; padding-top: 10; padding-end: 20px; padding-bottom: 20px; align-items: center; justify-content: center;">
<div style="height: 10px; width: 10px;"></div>
</div>

203
gentest/gentest-cpp.js Normal file
View File

@@ -0,0 +1,203 @@
/**
* Copyright (c) 2014-present, 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.
*/
var CPPEmitter = function() {
Emitter.call(this, 'cpp', ' ');
};
CPPEmitter.prototype = Object.create(Emitter.prototype, {
constructor:{value:CPPEmitter},
emitPrologue:{value:function() {
this.push([
'#include <CSSLayout/CSSLayout.h>',
'#include <gtest/gtest.h>',
'',
]);
}},
emitTestPrologue:{value:function(name) {
this.push('TEST(CSSLayoutTest, ' + name + ') {');
this.pushIndent();
}},
emitTestTreePrologue:{value:function(nodeName) {
this.push('const CSSNodeRef ' + nodeName + ' = CSSNodeNew();');
}},
emitTestEpilogue:{value:function() {
this.push([
'',
'CSSNodeFreeRecursive(root);',
]);
this.popIndent();
this.push([
'}',
'',
]);
}},
emitEpilogue:{value:function() {
}},
AssertEQ:{value:function(v0, v1) {
this.push('ASSERT_EQ(' + v0 + ', ' + v1 + ');');
}},
CSSAlignAuto:{value:'CSSAlignAuto'},
CSSAlignCenter:{value:'CSSAlignCenter'},
CSSAlignFlexEnd:{value:'CSSAlignFlexEnd'},
CSSAlignFlexStart:{value:'CSSAlignFlexStart'},
CSSAlignStretch:{value:'CSSAlignStretch'},
CSSDirectionInherit:{value:'CSSDirectionInherit'},
CSSDirectionLTR:{value:'CSSDirectionLTR'},
CSSDirectionRTL:{value:'CSSDirectionRTL'},
CSSEdgeBottom:{value:'CSSEdgeBottom'},
CSSEdgeEnd:{value:'CSSEdgeEnd'},
CSSEdgeLeft:{value:'CSSEdgeLeft'},
CSSEdgeRight:{value:'CSSEdgeRight'},
CSSEdgeStart:{value:'CSSEdgeStart'},
CSSEdgeTop:{value:'CSSEdgeTop'},
CSSFlexDirectionColumn:{value:'CSSFlexDirectionColumn'},
CSSFlexDirectionColumnReverse:{value:'CSSFlexDirectionColumnReverse'},
CSSFlexDirectionRow:{value:'CSSFlexDirectionRow'},
CSSFlexDirectionRowReverse:{value:'CSSFlexDirectionRowReverse'},
CSSJustifyCenter:{value:'CSSJustifyCenter'},
CSSJustifyFlexEnd:{value:'CSSJustifyFlexEnd'},
CSSJustifyFlexStart:{value:'CSSJustifyFlexStart'},
CSSJustifySpaceAround:{value:'CSSJustifySpaceAround'},
CSSJustifySpaceBetween:{value:'CSSJustifySpaceBetween'},
CSSOverflowHidden:{value:'CSSOverflowHidden'},
CSSOverflowVisible:{value:'CSSOverflowVisible'},
CSSPositionTypeAbsolute:{value:'CSSPositionTypeAbsolute'},
CSSPositionTypeRelative:{value:'CSSPositionTypeRelative'},
CSSWrapTypeNoWrap:{value:'CSSWrapTypeNoWrap'},
CSSWrapTypeWrap:{value:'CSSWrapTypeWrap'},
CSSUndefined:{value:'CSSUndefined'},
CSSNodeCalculateLayout:{value:function(node, dir) {
this.push('CSSNodeCalculateLayout(' + node + ', CSSUndefined, CSSUndefined, ' + dir + ');');
}},
CSSNodeInsertChild:{value:function(parentName, nodeName, index) {
this.push('CSSNodeInsertChild(' + parentName + ', ' + nodeName + ', ' + index + ');');
}},
CSSNodeLayoutGetLeft:{value:function(nodeName) {
return 'CSSNodeLayoutGetLeft(' + nodeName + ')';
}},
CSSNodeLayoutGetTop:{value:function(nodeName) {
return 'CSSNodeLayoutGetTop(' + nodeName + ')';
}},
CSSNodeLayoutGetWidth:{value:function(nodeName) {
return 'CSSNodeLayoutGetWidth(' + nodeName + ')';
}},
CSSNodeLayoutGetHeight:{value:function(nodeName) {
return 'CSSNodeLayoutGetHeight(' + nodeName + ')';
}},
CSSNodeStyleSetAlignContent:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetAlignContent(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetAlignItems:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetAlignItems(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetAlignSelf:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetAlignSelf(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetBorder:{value:function(nodeName, edge, value) {
this.push('CSSNodeStyleSetBorder(' + nodeName + ', ' + edge + ', ' + value + ');');
}},
CSSNodeStyleSetDirection:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetDirection(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetFlexBasis:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetFlexBasis(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetFlexDirection:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetFlexDirection(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetFlexGrow:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetFlexGrow(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetFlexShrink:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetFlexShrink(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetFlexWrap:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetFlexWrap(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetHeight:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetHeight(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetJustifyContent:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetJustifyContent(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetMargin:{value:function(nodeName, edge, value) {
this.push('CSSNodeStyleSetMargin(' + nodeName + ', ' + edge + ', ' + value + ');');
}},
CSSNodeStyleSetMaxHeight:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetMaxHeight(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetMaxWidth:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetMaxWidth(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetMinHeight:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetMinHeight(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetMinWidth:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetMinWidth(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetOverflow:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetOverflow(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetPadding:{value:function(nodeName, edge, value) {
this.push('CSSNodeStyleSetPadding(' + nodeName + ', ' + edge + ', ' + value + ');');
}},
CSSNodeStyleSetPosition:{value:function(nodeName, edge, value) {
this.push('CSSNodeStyleSetPosition(' + nodeName + ', ' + edge + ', ' + value + ');');
}},
CSSNodeStyleSetPositionType:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetPositionType(' + nodeName + ', ' + value + ');');
}},
CSSNodeStyleSetWidth:{value:function(nodeName, value) {
this.push('CSSNodeStyleSetWidth(' + nodeName + ', ' + value + ');');
}},
});

218
gentest/gentest-cs.js Normal file
View File

@@ -0,0 +1,218 @@
/**
* Copyright (c) 2014-present, 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.
*/
var CSEmitter = function() {
Emitter.call(this, 'cs', ' ');
};
CSEmitter.prototype = Object.create(Emitter.prototype, {
constructor:{value:CSEmitter},
emitPrologue:{value:function() {
this.push([
'using System;',
'using NUnit.Framework;',
'',
'namespace Facebook.CSSLayout',
'{',
]);
this.pushIndent();
this.push([
'[TestFixture]',
'public class CSSNodeLayoutTest',
'{',
]);
this.pushIndent();
}},
emitTestPrologue:{value:function(name) {
this.push('[Test]');
this.push('public void Test_' + name + '()');
this.push('{');
this.pushIndent();
}},
emitTestTreePrologue:{value:function(nodeName) {
this.push('CSSNode ' + nodeName + ' = new CSSNode();');
}},
emitTestEpilogue:{value:function() {
this.popIndent();
this.push([
'}',
'',
]);
}},
emitEpilogue:{value:function(lines) {
this.popIndent();
this.push('}');
this.popIndent();
this.push([
'}',
'',
]);
}},
AssertEQ:{value:function(v0, v1) {
this.push('Assert.AreEqual(' + v0 + ', ' + v1 + ');');
}},
CSSAlignAuto:{value:'CSSAlign.Auto'},
CSSAlignCenter:{value:'CSSAlign.Center'},
CSSAlignFlexEnd:{value:'CSSAlign.FlexEnd'},
CSSAlignFlexStart:{value:'CSSAlign.FlexStart'},
CSSAlignStretch:{value:'CSSAlign.Stretch'},
CSSDirectionInherit:{value:'CSSDirection.Inherit'},
CSSDirectionLTR:{value:'CSSDirection.LeftToRight'},
CSSDirectionRTL:{value:'CSSDirection.RightToLeft'},
CSSEdgeBottom:{value:'CSSEdge.Bottom'},
CSSEdgeEnd:{value:'CSSEdge.End'},
CSSEdgeLeft:{value:'CSSEdge.Left'},
CSSEdgeRight:{value:'CSSEdge.Right'},
CSSEdgeStart:{value:'CSSEdge.Start'},
CSSEdgeTop:{value:'CSSEdge.Top'},
CSSFlexDirectionColumn:{value:'CSSFlexDirection.Column'},
CSSFlexDirectionColumnReverse:{value:'CSSFlexDirection.ColumnReverse'},
CSSFlexDirectionRow:{value:'CSSFlexDirection.Row'},
CSSFlexDirectionRowReverse:{value:'CSSFlexDirection.RowReverse'},
CSSJustifyCenter:{value:'CSSJustify.Center'},
CSSJustifyFlexEnd:{value:'CSSJustify.FlexEnd'},
CSSJustifyFlexStart:{value:'CSSJustify.FlexStart'},
CSSJustifySpaceAround:{value:'CSSJustify.SpaceAround'},
CSSJustifySpaceBetween:{value:'CSSJustify.SpaceBetween'},
CSSOverflowHidden:{value:'CSSOverflow.Hidden'},
CSSOverflowVisible:{value:'CSSOverflow.Visible'},
CSSPositionTypeAbsolute:{value:'CSSPositionType.Absolute'},
CSSPositionTypeRelative:{value:'CSSPositionType.Relative'},
CSSUndefined:{value:'CSSConstants.Undefined'},
CSSWrapTypeNoWrap:{value:'CSSWrap.NoWrap'},
CSSWrapTypeWrap:{value:'CSSWrap.Wrap'},
CSSNodeCalculateLayout:{value:function(node, dir) {
this.push(node + '.StyleDirection = ' + dir + ';');
this.push(node + '.CalculateLayout();');
}},
CSSNodeInsertChild:{value:function(parentName, nodeName, index) {
this.push(parentName + '.Insert(' + index + ', ' + nodeName + ');');
}},
CSSNodeLayoutGetLeft:{value:function(nodeName) {
return nodeName + '.LayoutX';
}},
CSSNodeLayoutGetTop:{value:function(nodeName) {
return nodeName + '.LayoutY';
}},
CSSNodeLayoutGetWidth:{value:function(nodeName) {
return nodeName + '.LayoutWidth';
}},
CSSNodeLayoutGetHeight:{value:function(nodeName) {
return nodeName + '.LayoutHeight';
}},
CSSNodeStyleSetAlignContent:{value:function(nodeName, value) {
this.push(nodeName + '.AlignContent = ' + value + ';');
}},
CSSNodeStyleSetAlignItems:{value:function(nodeName, value) {
this.push(nodeName + '.AlignItems = ' + value + ';');
}},
CSSNodeStyleSetAlignSelf:{value:function(nodeName, value) {
this.push(nodeName + '.AlignSelf = ' + value + ';');
}},
CSSNodeStyleSetBorder:{value:function(nodeName, edge, value) {
this.push(nodeName + '.SetBorder(' + edge + ', ' + value + ');');
}},
CSSNodeStyleSetDirection:{value:function(nodeName, value) {
this.push(nodeName + '.StyleDirection = ' + value + ';');
}},
CSSNodeStyleSetFlexBasis:{value:function(nodeName, value) {
this.push(nodeName + '.FlexBasis = ' + value + ';');
}},
CSSNodeStyleSetFlexDirection:{value:function(nodeName, value) {
this.push(nodeName + '.FlexDirection = ' + value + ';');
}},
CSSNodeStyleSetFlexGrow:{value:function(nodeName, value) {
this.push(nodeName + '.FlexGrow = ' + value + ';');
}},
CSSNodeStyleSetFlexShrink:{value:function(nodeName, value) {
this.push(nodeName + '.FlexShrink = ' + value + ';');
}},
CSSNodeStyleSetFlexWrap:{value:function(nodeName, value) {
this.push(nodeName + '.Wrap = ' + value + ';');
}},
CSSNodeStyleSetHeight:{value:function(nodeName, value) {
this.push(nodeName + '.StyleHeight = ' + value + ';');
}},
CSSNodeStyleSetJustifyContent:{value:function(nodeName, value) {
this.push(nodeName + '.JustifyContent = ' + value + ';');
}},
CSSNodeStyleSetMargin:{value:function(nodeName, edge, value) {
this.push(nodeName + '.SetMargin(' + edge + ', ' + value + ');');
}},
CSSNodeStyleSetMaxHeight:{value:function(nodeName, value) {
this.push(nodeName + '.StyleMaxHeight = ' + value + ';');
}},
CSSNodeStyleSetMaxWidth:{value:function(nodeName, value) {
this.push(nodeName + '.StyleMaxWidth = ' + value + ';');
}},
CSSNodeStyleSetMinHeight:{value:function(nodeName, value) {
this.push(nodeName + '.StyleMinHeight = ' + value + ';');
}},
CSSNodeStyleSetMinWidth:{value:function(nodeName, value) {
this.push(nodeName + '.StyleMinWidth = ' + value + ';');
}},
CSSNodeStyleSetOverflow:{value:function(nodeName, value) {
this.push(nodeName + '.Overflow = ' + value + ';');
}},
CSSNodeStyleSetPadding:{value:function(nodeName, edge, value) {
this.push(nodeName + '.SetPadding(' + edge + ', ' + value + ');');
}},
CSSNodeStyleSetPosition:{value:function(nodeName, edge, value) {
this.push(nodeName + '.SetPosition(' + edge + ', ' + value + ');');
}},
CSSNodeStyleSetPositionType:{value:function(nodeName, value) {
this.push(nodeName + '.PositionType = ' + value + ';');
}},
CSSNodeStyleSetWidth:{value:function(nodeName, value) {
this.push(nodeName + '.StyleWidth = ' + value + ';');
}},
});

211
gentest/gentest-java.js Normal file
View File

@@ -0,0 +1,211 @@
/**
* Copyright (c) 2014-present, 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.
*/
var JavaEmitter = function() {
Emitter.call(this, 'java', ' ');
};
JavaEmitter.prototype = Object.create(Emitter.prototype, {
constructor:{value:JavaEmitter},
emitPrologue:{value:function() {
this.push([
'package com.facebook.csslayout;',
'',
'import org.junit.Test;',
'',
'import static org.junit.Assert.assertEquals;',
'',
'public class CSSNodeLayoutTest {',
]);
this.pushIndent();
}},
emitTestPrologue:{value:function(name) {
this.push('@Test');
this.push('public void test_' + name + '() {');
this.pushIndent();
}},
emitTestTreePrologue:{value:function(nodeName) {
this.push('final CSSNode ' + nodeName + ' = new CSSNode();');
}},
emitTestEpilogue:{value:function() {
this.popIndent();
this.push([
'}',
'',
]);
}},
emitEpilogue:{value:function(lines) {
this.popIndent();
this.push([
'}',
'',
]);
}},
AssertEQ:{value:function(v0, v1) {
this.push('assertEquals(' + v0 + ', ' + v1 + ', 0.0f);');
}},
CSSAlignAuto:{value:'CSSAlign.AUTO'},
CSSAlignCenter:{value:'CSSAlign.CENTER'},
CSSAlignFlexEnd:{value:'CSSAlign.FLEX_END'},
CSSAlignFlexStart:{value:'CSSAlign.FLEX_START'},
CSSAlignStretch:{value:'CSSAlign.STRETCH'},
CSSDirectionInherit:{value:'CSSDirection.INHERIT'},
CSSDirectionLTR:{value:'CSSDirection.LTR'},
CSSDirectionRTL:{value:'CSSDirection.RTL'},
CSSEdgeBottom:{value:'Spacing.BOTTOM'},
CSSEdgeEnd:{value:'Spacing.END'},
CSSEdgeLeft:{value:'Spacing.LEFT'},
CSSEdgeRight:{value:'Spacing.RIGHT'},
CSSEdgeStart:{value:'Spacing.START'},
CSSEdgeTop:{value:'Spacing.TOP'},
CSSFlexDirectionColumn:{value:'CSSFlexDirection.COLUMN'},
CSSFlexDirectionColumnReverse:{value:'CSSFlexDirection.COLUMN_REVERSE'},
CSSFlexDirectionRow:{value:'CSSFlexDirection.ROW'},
CSSFlexDirectionRowReverse:{value:'CSSFlexDirection.ROW_REVERSE'},
CSSJustifyCenter:{value:'CSSJustify.CENTER'},
CSSJustifyFlexEnd:{value:'CSSJustify.FLEX_END'},
CSSJustifyFlexStart:{value:'CSSJustify.FLEX_START'},
CSSJustifySpaceAround:{value:'CSSJustify.SPACE_AROUND'},
CSSJustifySpaceBetween:{value:'CSSJustify.SPACE_BETWEEN'},
CSSOverflowHidden:{value:'CSSOverflow.HIDDEN'},
CSSOverflowVisible:{value:'CSSOverflow.VISIBLE'},
CSSPositionTypeAbsolute:{value:'CSSPositionType.ABSOLUTE'},
CSSPositionTypeRelative:{value:'CSSPositionType.RELATIVE'},
CSSUndefined:{value:'CSSConstants.UNDEFINED'},
CSSWrapTypeNoWrap:{value:'CSSWrap.NO_WRAP'},
CSSWrapTypeWrap:{value:'CSSWrap.WRAP'},
CSSNodeCalculateLayout:{value:function(node, dir) {
this.push(node + '.setDirection(' + dir + ');');
this.push(node + '.calculateLayout(null);');
}},
CSSNodeInsertChild:{value:function(parentName, nodeName, index) {
this.push(parentName + '.addChildAt(' + nodeName + ', ' + index + ');');
}},
CSSNodeLayoutGetLeft:{value:function(nodeName) {
return nodeName + '.getLayoutX()';
}},
CSSNodeLayoutGetTop:{value:function(nodeName) {
return nodeName + '.getLayoutY()';
}},
CSSNodeLayoutGetWidth:{value:function(nodeName) {
return nodeName + '.getLayoutWidth()';
}},
CSSNodeLayoutGetHeight:{value:function(nodeName) {
return nodeName + '.getLayoutHeight()';
}},
CSSNodeStyleSetAlignContent:{value:function(nodeName, value) {
this.push(nodeName + '.setAlignContent(' + value + ');');
}},
CSSNodeStyleSetAlignItems:{value:function(nodeName, value) {
this.push(nodeName + '.setAlignItems(' + value + ');');
}},
CSSNodeStyleSetAlignSelf:{value:function(nodeName, value) {
this.push(nodeName + '.setAlignSelf(' + value + ');');
}},
CSSNodeStyleSetBorder:{value:function(nodeName, edge, value) {
this.push(nodeName + '.setBorder(' + edge + ', ' + value + ');');
}},
CSSNodeStyleSetDirection:{value:function(nodeName, value) {
this.push(nodeName + '.setDirection(' + value + ');');
}},
CSSNodeStyleSetFlexBasis:{value:function(nodeName, value) {
this.push(nodeName + '.setFlexBasis(' + value + ');');
}},
CSSNodeStyleSetFlexDirection:{value:function(nodeName, value) {
this.push(nodeName + '.setFlexDirection(' + value + ');');
}},
CSSNodeStyleSetFlexGrow:{value:function(nodeName, value) {
this.push(nodeName + '.setFlexGrow(' + value + ');');
}},
CSSNodeStyleSetFlexShrink:{value:function(nodeName, value) {
this.push(nodeName + '.setFlexShrink(' + value + ');');
}},
CSSNodeStyleSetFlexWrap:{value:function(nodeName, value) {
this.push(nodeName + '.setWrap(' + value + ');');
}},
CSSNodeStyleSetHeight:{value:function(nodeName, value) {
this.push(nodeName + '.setStyleHeight(' + value + ');');
}},
CSSNodeStyleSetJustifyContent:{value:function(nodeName, value) {
this.push(nodeName + '.setJustifyContent(' + value + ');');
}},
CSSNodeStyleSetMargin:{value:function(nodeName, edge, value) {
this.push(nodeName + '.setMargin(' + edge + ', ' + value + ');');
}},
CSSNodeStyleSetMaxHeight:{value:function(nodeName, value) {
this.push(nodeName + '.setStyleMaxHeight(' + value + ');');
}},
CSSNodeStyleSetMaxWidth:{value:function(nodeName, value) {
this.push(nodeName + '.setStyleMaxWidth(' + value + ');');
}},
CSSNodeStyleSetMinHeight:{value:function(nodeName, value) {
this.push(nodeName + '.setStyleMinHeight(' + value + ');');
}},
CSSNodeStyleSetMinWidth:{value:function(nodeName, value) {
this.push(nodeName + '.setStyleMinWidth(' + value + ');');
}},
CSSNodeStyleSetOverflow:{value:function(nodeName, value) {
this.push(nodeName + '.setOverflow(' + value + ');');
}},
CSSNodeStyleSetPadding:{value:function(nodeName, edge, value) {
this.push(nodeName + '.setPadding(' + edge + ', ' + value + ');');
}},
CSSNodeStyleSetPosition:{value:function(nodeName, edge, value) {
this.push(nodeName + '.setPosition(' + edge + ', ' + value + ');');
}},
CSSNodeStyleSetPositionType:{value:function(nodeName, value) {
this.push(nodeName + '.setPositionType(' + value + ');');
}},
CSSNodeStyleSetWidth:{value:function(nodeName, value) {
this.push(nodeName + '.setStyleWidth(' + value + ');');
}},
});

View File

@@ -8,11 +8,35 @@
*/ */
window.onload = function() { window.onload = function() {
printTest(document.body.children[0], document.body.children[1], document.body.children[2]); checkDefaultValues();
printTest(
new CPPEmitter(),
document.body.children[0],
document.body.children[1],
document.body.children[2]);
printTest(
new JavaEmitter(),
document.body.children[0],
document.body.children[1],
document.body.children[2]);
printTest(
new CSEmitter(),
document.body.children[0],
document.body.children[1],
document.body.children[2]);
} }
function printTest(LTRContainer, RTLContainer, genericContainer) { function assert(condition, message) {
var lines = [ if (!condition) {
throw new Error(message);
}
}
function printTest(e, LTRContainer, RTLContainer, genericContainer) {
e.push([
'/**', '/**',
' * Copyright (c) 2014-present, Facebook, Inc.', ' * Copyright (c) 2014-present, Facebook, Inc.',
' * All rights reserved.', ' * All rights reserved.',
@@ -22,14 +46,13 @@ function printTest(LTRContainer, RTLContainer, genericContainer) {
' * of patent rights can be found in the PATENTS file in the same directory.', ' * of patent rights can be found in the PATENTS file in the same directory.',
' */', ' */',
'', '',
]; '/**',
' * @Generated by gentest/gentest.sh with the following input',
lines.push('/**'); ' *',
lines.push(' * @Generated by gentest/gentest.sh with the following input'); ]);
lines.push(' *');
var indentation = 0; var indentation = 0;
lines.push(genericContainer.innerHTML.split('\n').map(function(line) { e.push(genericContainer.innerHTML.split('\n').map(function(line) {
return line.trim(); return line.trim();
}).filter(function(line) { }).filter(function(line) {
return line.length > 0 && line !== '<div id="default"></div>'; return line.length > 0 && line !== '<div id="default"></div>';
@@ -50,81 +73,106 @@ function printTest(LTRContainer, RTLContainer, genericContainer) {
} }
return curr + '\n' + prev; return curr + '\n' + prev;
})); }));
lines.push(' *'); e.push([
lines.push(' */'); ' *',
lines.push(''); ' */',
lines.push([
'#include <CSSLayout/CSSLayout.h>',
'#include <gtest/gtest.h>',
'', '',
].reduce(function(curr, prev) { ]);
return curr + '\n' + prev; e.emitPrologue();
}));
var LTRLayoutTree = calculateTree(LTRContainer); var LTRLayoutTree = calculateTree(LTRContainer);
var RTLLayoutTree = calculateTree(RTLContainer); var RTLLayoutTree = calculateTree(RTLContainer);
var genericLayoutTree = calculateTree(genericContainer); var genericLayoutTree = calculateTree(genericContainer);
for (var i = 0; i < genericLayoutTree.length; i++) {
lines.push('TEST(CSSLayoutTest, ' + genericLayoutTree[i].name + ') {');
lines.push(' ' + setupTestTree( for (var i = 0; i < genericLayoutTree.length; i++) {
e.emitTestPrologue(genericLayoutTree[i].name);
if (genericLayoutTree[i].name == 'wrap_column') {
// Modify width and left values due to both safari and chrome not abiding by the
// specification. The undefined dimension of a parent should be defined by the total size
// of their children in that dimension.
// See diagram under flex-wrap header https://www.w3.org/TR/css-flexbox-1/
assert(LTRLayoutTree[0].width == 30, 'wrap_column LTR root.width should be 30');
LTRLayoutTree[0].width = 60;
assert(RTLLayoutTree[0].width == 30, 'wrap_column RTL root.width should be 30');
RTLLayoutTree[0].width = 60;
var children = RTLLayoutTree[0].children;
assert(children[0].left == 0, 'wrap_column RTL root_child0.left should be 0');
children[0].left = 30;
assert(children[1].left == 0, 'wrap_column RTL root_child0.left should be 0');
children[1].left = 30;
assert(children[2].left == 0, 'wrap_column RTL root_child2.left should be 0');
children[2].left = 30;
assert(children[3].left == -30, 'wrap_column RTL root_child3.left should be -30');
children[3].left = 0;
}
setupTestTree(
e,
undefined, undefined,
LTRLayoutTree[i], LTRLayoutTree[i],
genericLayoutTree[i], genericLayoutTree[i],
'root', 'root',
null).reduce(function(curr, prev) { null);
return curr + '\n ' + prev;
}));
lines.push(' CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionLTR);'); e.CSSNodeCalculateLayout('root', e.CSSDirectionLTR);
lines.push(''); e.push('');
lines.push(' ' + assertTestTree(LTRLayoutTree[i], 'root', null).reduce(function(curr, prev) { assertTestTree(e, LTRLayoutTree[i], 'root', null);
return curr + '\n ' + prev; e.push('');
}));
lines.push('');
lines.push(' CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionRTL);'); e.CSSNodeCalculateLayout('root', e.CSSDirectionRTL);
lines.push(''); e.push('');
lines.push(' ' + assertTestTree(RTLLayoutTree[i], 'root', null).reduce(function(curr, prev) { assertTestTree(e, RTLLayoutTree[i], 'root', null);
return curr + '\n ' + prev;
}));
lines.push('\n CSSNodeFreeRecursive(root);') e.emitTestEpilogue();
lines.push('}');
lines.push('');
} }
e.emitEpilogue();
printLines(lines); e.print();
} }
function assertTestTree(node, nodeName, parentName) { function assertTestTree(e, node, nodeName, parentName) {
var lines = [ e.AssertEQ(node.left, e.CSSNodeLayoutGetLeft(nodeName));
'ASSERT_EQ(' + node.left + ', CSSNodeLayoutGetLeft(' + nodeName + '));', e.AssertEQ(node.top, e.CSSNodeLayoutGetTop(nodeName));
'ASSERT_EQ(' + node.top + ', CSSNodeLayoutGetTop(' + nodeName + '));', e.AssertEQ(node.width, e.CSSNodeLayoutGetWidth(nodeName));
'ASSERT_EQ(' + node.width + ', CSSNodeLayoutGetWidth(' + nodeName + '));', e.AssertEQ(node.height, e.CSSNodeLayoutGetHeight(nodeName));
'ASSERT_EQ(' + node.height + ', CSSNodeLayoutGetHeight(' + nodeName + '));',
];
for (var i = 0; i < node.children.length; i++) { for (var i = 0; i < node.children.length; i++) {
lines.push(''); e.push('');
var childName = nodeName + '_child' + i; var childName = nodeName + '_child' + i;
lines = lines.concat(assertTestTree(node.children[i], childName, nodeName)); assertTestTree(e, node.children[i], childName, nodeName);
} }
return lines;
} }
function setupTestTree(parent, node, genericNode, nodeName, parentName, index) { function checkDefaultValues() {
var lines = [ // Sanity check of the CSSLayout default values by test-template.html
'const CSSNodeRef ' + nodeName + ' = CSSNodeNew();', [
]; {style:'flex-direction', value:'column'},
{style:'justify-content', value:'flex-start'},
{style:'align-content', value:'flex-start'},
{style:'align-items', value:'stretch'},
{style:'position', value:'relative'},
{style:'flex-wrap', value:'nowrap'},
{style:'overflow', value:'visible'},
{style:'flex-grow', value:'0'},
{style:'flex-shrink', value:'0'},
{style:'left', value:'0px'},
{style:'top', value:'0px'},
{style:'right', value:'0px'},
{style:'bottom', value:'0px'},
].forEach(function(item) {
assert(item.value === getDefaultStyleValue(item.style),
item.style + ' should be ' + item.value);
});
}
function setupTestTree(e, parent, node, genericNode, nodeName, parentName, index) {
e.emitTestTreePrologue(nodeName);
for (var style in node.style) { for (var style in node.style) {
// Skip position info for root as it messes up tests // Skip position info for root as it messes up tests
if (node.declaredStyle[style] === "" && if (node.declaredStyle[style] === "" &&
(style == 'position' || (style == 'position' ||
@@ -140,267 +188,225 @@ function setupTestTree(parent, node, genericNode, nodeName, parentName, index) {
if (node.style[style] !== getDefaultStyleValue(style)) { if (node.style[style] !== getDefaultStyleValue(style)) {
switch (style) { switch (style) {
case 'direction': case 'direction':
lines.push('CSSNodeStyleSetDirection(' + nodeName + ', ' + e.CSSNodeStyleSetDirection(nodeName, directionValue(e, node.style[style]));
directionValue(node.style[style]) + ');');
break; break;
case 'flex-direction': case 'flex-direction':
lines.push('CSSNodeStyleSetFlexDirection(' + nodeName + ', ' + e.CSSNodeStyleSetFlexDirection(nodeName, flexDirectionValue(e, node.style[style]));
flexDirectionValue(node.style[style]) + ');');
break; break;
case 'justify-content': case 'justify-content':
lines.push('CSSNodeStyleSetJustifyContent(' + nodeName + ', ' + e.CSSNodeStyleSetJustifyContent(nodeName, justifyValue(e, node.style[style]));
justifyValue(node.style[style]) + ');');
break; break;
case 'align-content': case 'align-content':
lines.push('CSSNodeStyleSetAlignContent(' + nodeName + ', ' + e.CSSNodeStyleSetAlignContent(nodeName, alignValue(e, node.style[style]));
alignValue(node.style[style]) + ');');
break; break;
case 'align-items': case 'align-items':
lines.push('CSSNodeStyleSetAlignItems(' + nodeName + ', ' + e.CSSNodeStyleSetAlignItems(nodeName, alignValue(e, node.style[style]));
alignValue(node.style[style]) + ');');
break; break;
case 'align-self': case 'align-self':
if (!parent || node.style[style] !== parent.style['align-items']) { if (!parent || node.style[style] !== parent.style['align-items']) {
lines.push('CSSNodeStyleSetAlignSelf(' + nodeName + ', ' + e.CSSNodeStyleSetAlignSelf(nodeName, alignValue(e, node.style[style]));
alignValue(node.style[style]) + ');');
} }
break; break;
case 'position': case 'position':
lines.push('CSSNodeStyleSetPositionType(' + nodeName + ', ' + e.CSSNodeStyleSetPositionType(nodeName, positionValue(e, node.style[style]));
positionValue(node.style[style]) + ');');
break; break;
case 'flex-wrap': case 'flex-wrap':
lines.push('CSSNodeStyleSetFlexWrap(' + nodeName + ', ' + e.CSSNodeStyleSetFlexWrap(nodeName, wrapValue(e, node.style[style]));
wrapValue(node.style[style]) + ');');
break; break;
case 'overflow': case 'overflow':
lines.push('CSSNodeStyleSetOverflow(' + nodeName + ', ' + e.CSSNodeStyleSetOverflow(nodeName, overflowValue(e, node.style[style]));
overflowValue(node.style[style]) + ');');
break; break;
case 'flex-grow': case 'flex-grow':
lines.push('CSSNodeStyleSetFlexGrow(' + nodeName + ', ' + node.style[style] + ');'); e.CSSNodeStyleSetFlexGrow(nodeName, node.style[style]);
break; break;
case 'flex-shrink': case 'flex-shrink':
lines.push('CSSNodeStyleSetFlexShrink(' + nodeName + ', ' + node.style[style] + ');'); e.CSSNodeStyleSetFlexShrink(nodeName, node.style[style]);
break; break;
case 'flex-basis': case 'flex-basis':
lines.push('CSSNodeStyleSetFlexBasis(' + nodeName + ', ' + e.CSSNodeStyleSetFlexBasis(nodeName, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
break; break;
case 'left': case 'left':
if (genericNode.rawStyle.indexOf('start:') >= 0) { if (genericNode.rawStyle.indexOf('start:') >= 0) {
lines.push('CSSNodeStyleSetPosition(' + nodeName + ', CSSEdgeStart, ' + e.CSSNodeStyleSetPosition(nodeName, e.CSSEdgeStart, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
} else { } else {
lines.push('CSSNodeStyleSetPosition(' + nodeName + ', CSSEdgeLeft, ' + e.CSSNodeStyleSetPosition(nodeName, e.CSSEdgeLeft, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
} }
break; break;
case 'top': case 'top':
lines.push('CSSNodeStyleSetPosition(' + nodeName + ', CSSEdgeTop, ' + e.CSSNodeStyleSetPosition(nodeName, e.CSSEdgeTop, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
break; break;
case 'right': case 'right':
if (genericNode.rawStyle.indexOf('end:') >= 0) { if (genericNode.rawStyle.indexOf('end:') >= 0) {
lines.push('CSSNodeStyleSetPosition(' + nodeName + ', CSSEdgeEnd, ' + e.CSSNodeStyleSetPosition(nodeName, e.CSSEdgeEnd, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
} else { } else {
lines.push('CSSNodeStyleSetPosition(' + nodeName + ', CSSEdgeRight, ' + e.CSSNodeStyleSetPosition(nodeName, e.CSSEdgeRight, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
} }
break; break;
case 'bottom': case 'bottom':
lines.push('CSSNodeStyleSetPosition(' + nodeName + ', CSSEdgeBottom, ' + e.CSSNodeStyleSetPosition(nodeName, e.CSSEdgeBottom, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
break; break;
case 'margin-left': case 'margin-left':
if (genericNode.rawStyle.indexOf('margin-start:') >= 0) { if (genericNode.rawStyle.indexOf('margin-start:') >= 0) {
lines.push('CSSNodeStyleSetMargin(' + nodeName + ', CSSEdgeStart, ' + e.CSSNodeStyleSetMargin(nodeName, e.CSSEdgeStart, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
} else { } else {
lines.push('CSSNodeStyleSetMargin(' + nodeName + ', CSSEdgeLeft, ' + e.CSSNodeStyleSetMargin(nodeName, e.CSSEdgeLeft, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
} }
break; break;
case 'margin-top': case 'margin-top':
lines.push('CSSNodeStyleSetMargin(' + nodeName + ', CSSEdgeTop, ' + e.CSSNodeStyleSetMargin(nodeName, e.CSSEdgeTop, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
break; break;
case 'margin-right': case 'margin-right':
if (genericNode.rawStyle.indexOf('margin-end:') >= 0) { if (genericNode.rawStyle.indexOf('margin-end:') >= 0) {
lines.push('CSSNodeStyleSetMargin(' + nodeName + ', CSSEdgeEnd, ' + e.CSSNodeStyleSetMargin(nodeName, e.CSSEdgeEnd, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
} else { } else {
lines.push('CSSNodeStyleSetMargin(' + nodeName + ', CSSEdgeRight, ' + e.CSSNodeStyleSetMargin(nodeName, e.CSSEdgeRight, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
} }
break; break;
case 'margin-bottom': case 'margin-bottom':
lines.push('CSSNodeStyleSetMargin(' + nodeName + ', CSSEdgeBottom, ' + e.CSSNodeStyleSetMargin(nodeName, e.CSSEdgeBottom, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
break; break;
case 'padding-left': case 'padding-left':
if (genericNode.rawStyle.indexOf('padding-start:') >= 0) { if (genericNode.rawStyle.indexOf('padding-start:') >= 0) {
lines.push('CSSNodeStyleSetPadding(' + nodeName + ', CSSEdgeStart, ' + e.CSSNodeStyleSetPadding(nodeName, e.CSSEdgeStart, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
} else { } else {
lines.push('CSSNodeStyleSetPadding(' + nodeName + ', CSSEdgeLeft, ' + e.CSSNodeStyleSetPadding(nodeName, e.CSSEdgeLeft, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
} }
break; break;
case 'padding-top': case 'padding-top':
lines.push('CSSNodeStyleSetPadding(' + nodeName + ', CSSEdgeTop, ' + e.CSSNodeStyleSetPadding(nodeName, e.CSSEdgeTop, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
break; break;
case 'padding-right': case 'padding-right':
if (genericNode.rawStyle.indexOf('padding-end:') >= 0) { if (genericNode.rawStyle.indexOf('padding-end:') >= 0) {
lines.push('CSSNodeStyleSetPadding(' + nodeName + ', CSSEdgeEnd, ' + e.CSSNodeStyleSetPadding(nodeName, e.CSSEdgeEnd, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
} else { } else {
lines.push('CSSNodeStyleSetPadding(' + nodeName + ', CSSEdgeRight, ' + e.CSSNodeStyleSetPadding(nodeName, e.CSSEdgeRight, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
} }
break; break;
case 'padding-bottom': case 'padding-bottom':
lines.push('CSSNodeStyleSetPadding(' + nodeName + ', CSSEdgeBottom, ' + e.CSSNodeStyleSetPadding(nodeName, e.CSSEdgeBottom, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
break; break;
case 'border-left-width': case 'border-left-width':
if (genericNode.rawStyle.indexOf('border-start-width:') >= 0) { if (genericNode.rawStyle.indexOf('border-start-width:') >= 0) {
lines.push('CSSNodeStyleSetBorder(' + nodeName + ', CSSEdgeStart, ' + e.CSSNodeStyleSetBorder(nodeName, e.CSSEdgeStart, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
} else { } else {
lines.push('CSSNodeStyleSetBorder(' + nodeName + ', CSSEdgeLeft, ' + e.CSSNodeStyleSetBorder(nodeName, e.CSSEdgeLeft, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
} }
break; break;
case 'border-top-width': case 'border-top-width':
lines.push('CSSNodeStyleSetBorder(' + nodeName + ', CSSEdgeTop, ' + e.CSSNodeStyleSetBorder(nodeName, e.CSSEdgeTop, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
break; break;
case 'border-right-width': case 'border-right-width':
if (genericNode.rawStyle.indexOf('border-end-width:') >= 0) { if (genericNode.rawStyle.indexOf('border-end-width:') >= 0) {
lines.push('CSSNodeStyleSetBorder(' + nodeName + ', CSSEdgeEnd, ' + e.CSSNodeStyleSetBorder(nodeName, e.CSSEdgeEnd, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
} else { } else {
lines.push('CSSNodeStyleSetBorder(' + nodeName + ', CSSEdgeRight, ' + e.CSSNodeStyleSetBorder(nodeName, e.CSSEdgeRight, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
} }
break; break;
case 'border-bottom-width': case 'border-bottom-width':
lines.push('CSSNodeStyleSetBorder(' + nodeName + ', CSSEdgeBottom, ' + e.CSSNodeStyleSetBorder(nodeName, e.CSSEdgeBottom, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
break; break;
case 'width': case 'width':
lines.push('CSSNodeStyleSetWidth(' + nodeName + ', ' + e.CSSNodeStyleSetWidth(nodeName, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
break; break;
case 'min-width': case 'min-width':
lines.push('CSSNodeStyleSetMinWidth(' + nodeName + ', ' + e.CSSNodeStyleSetMinWidth(nodeName, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
break; break;
case 'max-width': case 'max-width':
lines.push('CSSNodeStyleSetMaxWidth(' + nodeName + ', ' + e.CSSNodeStyleSetMaxWidth(nodeName, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
break; break;
case 'height': case 'height':
lines.push('CSSNodeStyleSetHeight(' + nodeName + ', ' + e.CSSNodeStyleSetHeight(nodeName, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
break; break;
case 'min-height': case 'min-height':
lines.push('CSSNodeStyleSetMinHeight(' + nodeName + ', ' + e.CSSNodeStyleSetMinHeight(nodeName, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
break; break;
case 'max-height': case 'max-height':
lines.push('CSSNodeStyleSetMaxHeight(' + nodeName + ', ' + e.CSSNodeStyleSetMaxHeight(nodeName, pixelValue(e, node.style[style]));
pixelValue(node.style[style]) + ');');
break; break;
} }
} }
} }
if (parentName) { if (parentName) {
lines.push('CSSNodeInsertChild(' + parentName + ', ' + nodeName + ', ' + index + ');'); e.CSSNodeInsertChild(parentName, nodeName, index);
} }
for (var i = 0; i < node.children.length; i++) { for (var i = 0; i < node.children.length; i++) {
lines.push(''); e.push('');
var childName = nodeName + '_child' + i; var childName = nodeName + '_child' + i;
lines = lines.concat( setupTestTree(
setupTestTree( e,
node, node,
node.children[i], node.children[i],
genericNode.children[i], genericNode.children[i],
childName, childName,
nodeName, nodeName,
i)); i);
}
return lines;
}
function overflowValue(value) {
switch (value) {
case 'visible': return 'CSSOverflowVisible';
case 'hidden': return 'CSSOverflowHidden';
} }
} }
function wrapValue(value) { function overflowValue(e, value) {
switch (value) { switch (value) {
case 'wrap': return 'CSSWrapTypeWrap'; case 'visible': return e.CSSOverflowVisible;
case 'nowrap': return 'CSSWrapTypeNoWrap'; case 'hidden': return e.CSSOverflowHidden;
} }
} }
function flexDirectionValue(value) { function wrapValue(e, value) {
switch (value) { switch (value) {
case 'row': return 'CSSFlexDirectionRow'; case 'wrap': return e.CSSWrapTypeWrap;
case 'row-reverse': return 'CSSFlexDirectionRowReverse'; case 'nowrap': return e.CSSWrapTypeNoWrap;
case 'column': return 'CSSFlexDirectionColumn';
case 'column-reverse': return 'CSSFlexDirectionColumnReverse';
} }
} }
function justifyValue(value) { function flexDirectionValue(e, value) {
switch (value) { switch (value) {
case 'center': return 'CSSJustifyCenter'; case 'row': return e.CSSFlexDirectionRow;
case 'space-around': return 'CSSJustifySpaceAround'; case 'row-reverse': return e.CSSFlexDirectionRowReverse;
case 'space-between': return 'CSSJustifySpaceBetween'; case 'column': return e.CSSFlexDirectionColumn;
case 'flex-start': return 'CSSJustifyFlexStart'; case 'column-reverse': return e.CSSFlexDirectionColumnReverse;
case 'flex-end': return 'CSSJustifyFlexEnd';
} }
} }
function positionValue(value) { function justifyValue(e, value) {
switch (value) { switch (value) {
case 'absolute': return 'CSSPositionTypeAbsolute'; case 'center': return e.CSSJustifyCenter;
default: return 'CSSPositionTypeRelative' case 'space-around': return e.CSSJustifySpaceAround;
case 'space-between': return e.CSSJustifySpaceBetween;
case 'flex-start': return e.CSSJustifyFlexStart;
case 'flex-end': return e.CSSJustifyFlexEnd;
} }
} }
function directionValue(value) { function positionValue(e, value) {
switch (value) { switch (value) {
case 'ltr': return 'CSSDirectionLTR'; case 'absolute': return e.CSSPositionTypeAbsolute;
case 'rtl': return 'CSSDirectionRTL'; default: return e.CSSPositionTypeRelative
case 'inherit': return 'CSSDirectionInherit';
} }
} }
function alignValue(value) { function directionValue(e, value) {
switch (value) { switch (value) {
case 'auto': return 'CSSAlignAuto'; case 'ltr': return e.CSSDirectionLTR;
case 'center': return 'CSSAlignCenter'; case 'rtl': return e.CSSDirectionRTL;
case 'stretch': return 'CSSAlignStretch'; case 'inherit': return e.CSSDirectionInherit;
case 'flex-start': return 'CSSAlignFlexStart';
case 'flex-end': return 'CSSAlignFlexEnd';
} }
} }
function pixelValue(value) { function alignValue(e, value) {
switch (value) { switch (value) {
case 'auto': return 'CSSUndefined'; case 'auto': return e.CSSAlignAuto;
case 'undefined': return 'CSSUndefined'; case 'center': return e.CSSAlignCenter;
case 'stretch': return e.CSSAlignStretch;
case 'flex-start': return e.CSSAlignFlexStart;
case 'flex-end': return e.CSSAlignFlexEnd;
}
}
function pixelValue(e, value) {
switch (value) {
case 'auto': return e.CSSUndefined;
case 'undefined': return e.CSSUndefined;
default: return value.replace('px', ''); default: return value.replace('px', '');
} }
} }
@@ -413,14 +419,6 @@ function getDefaultStyleValue(style) {
return getComputedStyle(node, null).getPropertyValue(style); return getComputedStyle(node, null).getPropertyValue(style);
} }
function printLines(lines) {
console.log(lines.map(function(value) {
return value + '\n';
}).reduce(function(prev, curr) {
return prev + curr;
}, ''));
}
function calculateTree(root) { function calculateTree(root) {
var rootLayout = []; var rootLayout = [];
@@ -483,3 +481,38 @@ function getCSSLayoutStyle(node) {
return map; return map;
}, {}); }, {});
} }
var Emitter = function(lang, indent) {
this.lang = lang;
this.indent = indent;
this.indents = [];
this.lines = [];
};
Emitter.prototype = Object.create(Object.prototype, {
constructor:{value:Emitter},
pushIndent:{value:function() {
this.indents.push(this.indent);
}},
popIndent:{value:function() {
this.indents.pop();
}},
push:{value:function(line) {
if (line instanceof Array) {
line.forEach(function(element) {
this.push(element);
}, this);
return;
} else if (line.length > 0) {
line = this.indents.join('') + line;
}
this.lines.push(line);
}},
print:{value:function() {
console.log(this.lines.join('\n'));
}},
});

44
gentest/gentest.rb Normal file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/env ruby
require 'watir-webdriver'
require 'fileutils'
caps = Selenium::WebDriver::Remote::Capabilities.chrome(
"loggingPrefs"=>{"browser"=>"ALL", "performance"=>"ALL"})
browser = Watir::Browser.new(:chrome, :desired_capabilities => caps)
Dir['fixtures/*.html'].each do |file|
fixture = File.read(file)
name = File.basename(file, '.*')
puts "Generate #{name}"
ltr_fixture = fixture.gsub('start', 'left')
.gsub('end', 'right')
.gsub('flex-left', 'flex-start')
.gsub('flex-right', 'flex-end')
rtl_fixture = fixture.gsub('start', 'right')
.gsub('end', 'left')
.gsub('flex-right', 'flex-start')
.gsub('flex-left', 'flex-end')
template = File.open('test-template.html').read
f = File.open('test.html', 'w')
f.write sprintf(template, ltr_fixture, rtl_fixture, fixture)
f.close
FileUtils.copy('test.html', "#{name}.html") if $DEBUG
browser.goto('file://' + Dir.pwd + '/test.html')
logs = browser.driver.manage.logs.get(:browser)
f = File.open("../tests/#{name}.cpp", 'w')
f.write eval(logs[0].message.sub(/^[^"]*/, ''))
f.close
f = File.open("../java/tests/com/facebook/csslayout/#{name}.java", 'w')
f.write eval(logs[1].message.sub(/^[^"]*/, '')).sub('CSSNodeLayoutTest', name)
f.close
f = File.open("../csharp/tests/Facebook.CSSLayout/#{name}.cs", 'w')
f.write eval(logs[2].message.sub(/^[^"]*/, '')).sub('CSSNodeLayoutTest', name)
f.close
end
File.delete('test.html')
browser.close

View File

@@ -1,19 +0,0 @@
rm $(dirname $0)/test.html
$EDITOR $(dirname $0)/test.html
GENERIC_TEST="$(cat $(dirname $0)/test.html)"
LTR_TEST="$(cat $(dirname $0)/test.html)"
RTL_TEST="$(cat $(dirname $0)/test.html)"
LTR_TEST=${LTR_TEST//start/left}
LTR_TEST=${LTR_TEST//end/right}
LTR_TEST=${LTR_TEST//flex-left/flex-start}
LTR_TEST=${LTR_TEST//flex-right/flex-end}
RTL_TEST=${RTL_TEST//start/right}
RTL_TEST=${RTL_TEST//end/left}
RTL_TEST=${RTL_TEST//flex-right/flex-start}
RTL_TEST=${RTL_TEST//flex-left/flex-end}
printf "$(cat $(dirname $0)/test-template.html)" "$LTR_TEST" "$RTL_TEST" "$GENERIC_TEST" > $(dirname $0)/test.html
open $(dirname $0)/test.html

View File

@@ -4,6 +4,9 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>test page</title> <title>test page</title>
<script src="gentest.js"></script> <script src="gentest.js"></script>
<script src="gentest-cpp.js"></script>
<script src="gentest-java.js"></script>
<script src="gentest-cs.js"></script>
<style> <style>
body { body {
@@ -23,6 +26,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
align-content: flex-start;
justify-content: flex-start; justify-content: flex-start;
flex-shrink: 0; flex-shrink: 0;
} }

View File

@@ -49,7 +49,6 @@
TEST(CSSLayoutTest, align_content_flex_start) { TEST(CSSLayoutTest, align_content_flex_start) {
const CSSNodeRef root = CSSNodeNew(); const CSSNodeRef root = CSSNodeNew();
CSSNodeStyleSetAlignContent(root, CSSAlignFlexStart);
CSSNodeStyleSetFlexWrap(root, CSSWrapTypeWrap); CSSNodeStyleSetFlexWrap(root, CSSWrapTypeWrap);
CSSNodeStyleSetWidth(root, 100); CSSNodeStyleSetWidth(root, 100);
CSSNodeStyleSetHeight(root, 100); CSSNodeStyleSetHeight(root, 100);

View File

@@ -185,7 +185,6 @@ TEST(CSSLayoutTest, border_center_child) {
CSSNodeStyleSetHeight(root, 100); CSSNodeStyleSetHeight(root, 100);
const CSSNodeRef root_child0 = CSSNodeNew(); const CSSNodeRef root_child0 = CSSNodeNew();
CSSNodeStyleSetAlignSelf(root_child0, CSSAlignCenter);
CSSNodeStyleSetWidth(root_child0, 10); CSSNodeStyleSetWidth(root_child0, 10);
CSSNodeStyleSetHeight(root_child0, 10); CSSNodeStyleSetHeight(root_child0, 10);
CSSNodeInsertChild(root, root_child0, 0); CSSNodeInsertChild(root, root_child0, 0);

View File

@@ -40,11 +40,6 @@
* *
*/ */
// These tests were modified after generation due to both safari and chrome not abiding
// by the specification. The undefined dimension of a parent should be defined by the total size
// of their children in that dimension.
// See diagram under flex-wrap header https://www.w3.org/TR/css-flexbox-1/
#include <CSSLayout/CSSLayout.h> #include <CSSLayout/CSSLayout.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>

View File

@@ -185,7 +185,6 @@ TEST(CSSLayoutTest, padding_center_child) {
CSSNodeStyleSetHeight(root, 100); CSSNodeStyleSetHeight(root, 100);
const CSSNodeRef root_child0 = CSSNodeNew(); const CSSNodeRef root_child0 = CSSNodeNew();
CSSNodeStyleSetAlignSelf(root_child0, CSSAlignCenter);
CSSNodeStyleSetWidth(root_child0, 10); CSSNodeStyleSetWidth(root_child0, 10);
CSSNodeStyleSetHeight(root_child0, 10); CSSNodeStyleSetHeight(root_child0, 10);
CSSNodeInsertChild(root, root_child0, 0); CSSNodeInsertChild(root, root_child0, 0);