1// Copyright 2018 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <unittest/unittest.h> 6 7#include <fidl/flat_ast.h> 8#include <fidl/lexer.h> 9#include <fidl/parser.h> 10#include <fidl/source_file.h> 11 12#include <fstream> 13 14#include "examples.h" 15#include "test_library.h" 16 17namespace { 18 19// We repeat each test in a loop in order to catch situations where memory layout 20// determines what JSON is produced (this is often manifested due to using a std::map<Foo*,...> 21// in compiler source code). 22static const int kRepeatTestCount = 100; 23 24static inline void trim(std::string& s) { 25 s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) { 26 return !std::isspace(ch) && ch != '\n'; 27 })); 28 s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { 29 return !std::isspace(ch) && ch != '\n'; 30 }) 31 .base(), 32 s.end()); 33} 34 35bool checkJSONGenerator(std::string raw_source_code, std::string expected_json) { 36 TestLibrary library("json.fidl", raw_source_code); 37 EXPECT_TRUE(library.Compile()); 38 39 // actual 40 auto actual = library.GenerateJSON(); 41 trim(actual); 42 43 // expected 44 trim(expected_json); 45 46 if (actual.compare(expected_json) == 0) { 47 return true; 48 } 49 50 // On error, we output both the actual and expected to allow simple 51 // diffing to debug the test. 52 53 std::ofstream output_actual("json_generator_tests_actual.txt"); 54 output_actual << actual; 55 output_actual.close(); 56 57 std::ofstream output_expected("json_generator_tests_expected.txt"); 58 output_expected << expected_json; 59 output_expected.close(); 60 61 return false; 62} 63 64bool json_generator_test_struct() { 65 BEGIN_TEST; 66 67 for (int i = 0; i < kRepeatTestCount; i++) { 68 EXPECT_TRUE(checkJSONGenerator(R"FIDL( 69library fidl.test.json; 70 71struct Simple { 72 uint8 f1; 73 bool f2; 74}; 75 76)FIDL", 77 R"JSON( 78{ 79 "version": "0.0.1", 80 "name": "fidl.test.json", 81 "library_dependencies": [], 82 "const_declarations": [], 83 "enum_declarations": [], 84 "interface_declarations": [], 85 "struct_declarations": [ 86 { 87 "name": "fidl.test.json/Simple", 88 "members": [ 89 { 90 "type": { 91 "kind": "primitive", 92 "subtype": "uint8" 93 }, 94 "name": "f1", 95 "size": 1, 96 "alignment": 1, 97 "offset": 0, 98 "max_handles": 0 99 }, 100 { 101 "type": { 102 "kind": "primitive", 103 "subtype": "bool" 104 }, 105 "name": "f2", 106 "size": 1, 107 "alignment": 1, 108 "offset": 1, 109 "max_handles": 0 110 } 111 ], 112 "size": 2, 113 "alignment": 1, 114 "max_handles": 0 115 } 116 ], 117 "table_declarations": [], 118 "union_declarations": [], 119 "declaration_order": [ 120 "fidl.test.json/Simple" 121 ], 122 "declarations": { 123 "fidl.test.json/Simple": "struct" 124 } 125} 126)JSON")); 127 } 128 129 END_TEST; 130} 131 132bool json_generator_test_table() { 133 BEGIN_TEST; 134 135 for (int i = 0; i < kRepeatTestCount; i++) { 136 EXPECT_TRUE(checkJSONGenerator(R"FIDL( 137library fidl.test.json; 138 139table Simple { 140 1: uint8 f1; 141 2: bool f2; 142 3: reserved; 143}; 144 145)FIDL", 146 R"JSON( 147{ 148 "version": "0.0.1", 149 "name": "fidl.test.json", 150 "library_dependencies": [], 151 "const_declarations": [], 152 "enum_declarations": [], 153 "interface_declarations": [], 154 "struct_declarations": [], 155 "table_declarations": [ 156 { 157 "name": "fidl.test.json/Simple", 158 "members": [ 159 { 160 "ordinal": 1, 161 "reserved": false, 162 "type": { 163 "kind": "primitive", 164 "subtype": "uint8" 165 }, 166 "name": "f1", 167 "size": 1, 168 "alignment": 1, 169 "max_handles": 0 170 }, 171 { 172 "ordinal": 2, 173 "reserved": false, 174 "type": { 175 "kind": "primitive", 176 "subtype": "bool" 177 }, 178 "name": "f2", 179 "size": 1, 180 "alignment": 1, 181 "max_handles": 0 182 }, 183 { 184 "ordinal": 3, 185 "reserved": true 186 } 187 ], 188 "size": 16, 189 "alignment": 8, 190 "max_handles": 0 191 } 192 ], 193 "union_declarations": [], 194 "declaration_order": [ 195 "fidl.test.json/Simple" 196 ], 197 "declarations": { 198 "fidl.test.json/Simple": "table" 199 } 200} 201)JSON")); 202 } 203 204 END_TEST; 205} 206 207bool json_generator_test_union() { 208 BEGIN_TEST; 209 210 for (int i = 0; i < kRepeatTestCount; i++) { 211 EXPECT_TRUE(checkJSONGenerator(R"FIDL( 212library fidl.test.json; 213 214struct Pizza { 215 vector<string:16> toppings; 216}; 217 218struct Pasta { 219 string:16 sauce; 220}; 221 222union PizzaOrPasta { 223 Pizza pizza; 224 Pasta pasta; 225}; 226 227)FIDL", 228 R"JSON( 229{ 230 "version": "0.0.1", 231 "name": "fidl.test.json", 232 "library_dependencies": [], 233 "const_declarations": [], 234 "enum_declarations": [], 235 "interface_declarations": [], 236 "struct_declarations": [ 237 { 238 "name": "fidl.test.json/Pizza", 239 "members": [ 240 { 241 "type": { 242 "kind": "vector", 243 "element_type": { 244 "kind": "string", 245 "maybe_element_count": 16, 246 "nullable": false 247 }, 248 "nullable": false 249 }, 250 "name": "toppings", 251 "size": 16, 252 "alignment": 8, 253 "offset": 0, 254 "max_handles": 0 255 } 256 ], 257 "size": 16, 258 "alignment": 8, 259 "max_handles": 0 260 }, 261 { 262 "name": "fidl.test.json/Pasta", 263 "members": [ 264 { 265 "type": { 266 "kind": "string", 267 "maybe_element_count": 16, 268 "nullable": false 269 }, 270 "name": "sauce", 271 "size": 16, 272 "alignment": 8, 273 "offset": 0, 274 "max_handles": 0 275 } 276 ], 277 "size": 16, 278 "alignment": 8, 279 "max_handles": 0 280 } 281 ], 282 "table_declarations": [], 283 "union_declarations": [ 284 { 285 "name": "fidl.test.json/PizzaOrPasta", 286 "members": [ 287 { 288 "type": { 289 "kind": "identifier", 290 "identifier": "fidl.test.json/Pizza", 291 "nullable": false 292 }, 293 "name": "pizza", 294 "size": 16, 295 "alignment": 8, 296 "offset": 8 297 }, 298 { 299 "type": { 300 "kind": "identifier", 301 "identifier": "fidl.test.json/Pasta", 302 "nullable": false 303 }, 304 "name": "pasta", 305 "size": 16, 306 "alignment": 8, 307 "offset": 8 308 } 309 ], 310 "size": 24, 311 "alignment": 8, 312 "max_handles": 0 313 } 314 ], 315 "declaration_order": [ 316 "fidl.test.json/Pizza", 317 "fidl.test.json/Pasta", 318 "fidl.test.json/PizzaOrPasta" 319 ], 320 "declarations": { 321 "fidl.test.json/Pizza": "struct", 322 "fidl.test.json/Pasta": "struct", 323 "fidl.test.json/PizzaOrPasta": "union" 324 } 325} 326)JSON")); 327 } 328 329 END_TEST; 330} 331 332} // namespace 333 334BEGIN_TEST_CASE(json_generator_tests); 335RUN_TEST(json_generator_test_struct); 336RUN_TEST(json_generator_test_table); 337RUN_TEST(json_generator_test_union); 338END_TEST_CASE(json_generator_tests); 339