Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
spec_test_generator.cpp File Reference
#include <fstream>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iterator>
#include <limits>
#include <stdexcept>
#include <utility>
#include <math.h>
#include <locale.h>
Include dependency graph for spec_test_generator.cpp:

Go to the source code of this file.

Classes

struct  picojson::null
 
class  picojson::value
 
union  picojson::value::_storage
 
struct  picojson::serialize_str_char< Iter >
 
class  picojson::input< Iter >
 
class  picojson::deny_parse_context
 
class  picojson::default_parse_context
 
class  picojson::null_parse_context
 
struct  picojson::null_parse_context::dummy_str
 
struct  picojson::last_error_t< T >
 

Namespaces

namespace  picojson
 
namespace  std
 

Macros

#define picojson_h
 
#define PICOJSON_USE_RVALUE_REFERENCE   0
 
#define PICOJSON_NOEXCEPT   throw()
 
#define PICOJSON_USE_LOCALE   1
 
#define PICOJSON_ASSERT(e)
 
#define SNPRINTF   snprintf
 
#define INIT(p, v)
 
#define DEINIT(p)
 
#define INIT(p, v)
 
#define IS(ctype, jtype)
 
#define GET(ctype, var)
 
#define SET(ctype, jtype, setter)
 
#define MAP(val, sym)
 
#define MAP(sym, val)
 
#define IS(ch, text, op)
 
#define PICOJSON_CMP(type)
 

Typedefs

typedef value::array picojson::array
 
typedef value::object picojson::object
 

Enumerations

enum  {
  picojson::null_type , picojson::boolean_type , picojson::number_type , picojson::string_type ,
  picojson::array_type , picojson::object_type
}
 
enum  { picojson::INDENT_WIDTH = 2 }
 

Functions

template<typename Iter >
void picojson::copy (const std::string &s, Iter oi)
 
template<typename Iter >
void picojson::serialize_str (const std::string &s, Iter oi)
 
template<typename Iter >
int picojson::_parse_quadhex (input< Iter > &in)
 
template<typename String , typename Iter >
bool picojson::_parse_codepoint (String &out, input< Iter > &in)
 
template<typename String , typename Iter >
bool picojson::_parse_string (String &out, input< Iter > &in)
 
template<typename Context , typename Iter >
bool picojson::_parse_array (Context &ctx, input< Iter > &in)
 
template<typename Context , typename Iter >
bool picojson::_parse_object (Context &ctx, input< Iter > &in)
 
template<typename Iter >
std::string picojson::_parse_number (input< Iter > &in)
 
template<typename Context , typename Iter >
bool picojson::_parse (Context &ctx, input< Iter > &in)
 
template<typename Iter >
std::string picojson::parse (value &out, Iter &pos, const Iter &last)
 
template<typename Context , typename Iter >
Iter picojson::_parse (Context &ctx, const Iter &first, const Iter &last, std::string *err)
 
template<typename Iter >
Iter picojson::parse (value &out, const Iter &first, const Iter &last, std::string *err)
 
std::string picojson::parse (value &out, const std::string &s)
 
std::string picojson::parse (value &out, std::istream &is)
 
void picojson::set_last_error (const std::string &s)
 
const std::string & picojson::get_last_error ()
 
bool picojson::operator== (const value &x, const value &y)
 
bool picojson::operator!= (const value &x, const value &y)
 
template<>
void std::swap (picojson::value &x, picojson::value &y)
 
std::istream & operator>> (std::istream &is, picojson::value &x)
 
std::ostream & operator<< (std::ostream &os, const picojson::value &x)
 
std::string cpp_string (const picojson::value &x)
 
string generate_test_call (picojson::object obj, string expected_t, string expected_v)
 
string generate_test_call_nan (picojson::object obj)
 
string generate_trap_call (picojson::object obj)
 
string generate_call (picojson::object obj)
 
void generate_tests (const map< string, vector< picojson::object > > &mappings)
 
void usage (const char *name)
 
int main (int argc, char **argv)
 

Variables

const string test_includes
 
const string test_preamble_0 = "using backend_t = backend<standalone_function_t, TestType>;\n auto code = read_wasm( "
 
const string test_preamble_1 = "backend_t bkend( code, &wa );"
 
const std::set< std::string > blacklist
 

Macro Definition Documentation

◆ DEINIT

#define DEINIT ( p)
Value:
case p##type: delete u_.p; break
const mie::Vuint & p
Definition bn.cpp:27
yh_object_type type
Definition yubihsm.h:672

◆ GET

#define GET ( ctype,
var )
Value:
template <> \
inline const ctype& value::get<ctype>() const { \
PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
return var; \
} \
template <> \
inline ctype& value::get<ctype>() { \
PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
return var; \
}

Definition at line 351 of file spec_test_generator.cpp.

351# define GET(ctype, var) \
352 template <> \
353 inline const ctype& value::get<ctype>() const { \
354 PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
355 return var; \
356 } \
357 template <> \
358 inline ctype& value::get<ctype>() { \
359 PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
360 return var; \
361 }

◆ INIT [1/2]

#define INIT ( p,
v )
Value:
case p##type: u_.p = v; break

◆ INIT [2/2]

#define INIT ( p,
v )
Value:
case p##type: u_.p = v; break

◆ IS [1/2]

#define IS ( ch,
text,
op )
Value:
case ch: \
if (in.match(text) && op) { \
return true; \
} else { \
return false; \
}

Definition at line 328 of file spec_test_generator.cpp.

328# define IS(ctype, jtype) \
329 template <> \
330 inline bool value::is<ctype>() const { \
331 return type_ == jtype##_type; \
332 }

◆ IS [2/2]

#define IS ( ctype,
jtype )
Value:
template <> \
inline bool value::is<ctype>() const { \
return type_ == jtype##_type; \
}

Definition at line 328 of file spec_test_generator.cpp.

328# define IS(ctype, jtype) \
329 template <> \
330 inline bool value::is<ctype>() const { \
331 return type_ == jtype##_type; \
332 }

◆ MAP [1/2]

#define MAP ( sym,
val )
Value:
case sym: out.push_back(val); break

◆ MAP [2/2]

#define MAP ( val,
sym )
Value:
case val: copy(sym, oi); break

◆ PICOJSON_ASSERT

#define PICOJSON_ASSERT ( e)
Value:
do { \
if (!(e)) \
throw std::runtime_error(#e); \
} while (0)

Definition at line 104 of file spec_test_generator.cpp.

104# define PICOJSON_ASSERT(e) \
105 do { \
106 if (!(e)) \
107 throw std::runtime_error(#e); \
108 } while (0)

◆ PICOJSON_CMP

#define PICOJSON_CMP ( type)
Value:
if (x.is<type>()) \
return y.is<type>() && x.get<type>() == y.get<type>()

◆ picojson_h

#define picojson_h

Definition at line 38 of file spec_test_generator.cpp.

◆ PICOJSON_NOEXCEPT

#define PICOJSON_NOEXCEPT   throw()

Definition at line 82 of file spec_test_generator.cpp.

◆ PICOJSON_USE_LOCALE

#define PICOJSON_USE_LOCALE   1

Definition at line 95 of file spec_test_generator.cpp.

◆ PICOJSON_USE_RVALUE_REFERENCE

#define PICOJSON_USE_RVALUE_REFERENCE   0

Definition at line 74 of file spec_test_generator.cpp.

◆ SET

#define SET ( ctype,
jtype,
setter )
Value:
template <> \
inline void value::set<ctype>(const ctype& _val) { \
clear(); \
type_ = jtype##_type; \
setter \
}

Definition at line 376 of file spec_test_generator.cpp.

376# define SET(ctype, jtype, setter) \
377 template <> \
378 inline void value::set<ctype>(const ctype& _val) { \
379 clear(); \
380 type_ = jtype##_type; \
381 setter \
382 }

◆ SNPRINTF

#define SNPRINTF   snprintf

Definition at line 118 of file spec_test_generator.cpp.

Function Documentation

◆ cpp_string()

std::string cpp_string ( const picojson::value & x)

Definition at line 1131 of file spec_test_generator.cpp.

1131 {
1132 std::string result = "\"";
1133 std::string original = x.to_str();
1134 for(unsigned char ch : original) {
1135 if ((unsigned char)ch < 0x20 || (unsigned char)ch > 0x7F) {
1136 // Use a three digit octal escape, because that won't
1137 // accidentally consume the following characters.
1138 result += '\\';
1139 result += (((unsigned char)ch >> 6) & 0x07) + '0';
1140 result += (((unsigned char)ch >> 3) & 0x07) + '0';
1141 result += (((unsigned char)ch >> 0) & 0x07) + '0';
1142 } else if(ch == '\\' || ch == '\"') {
1143 result += '\\';
1144 result += ch;
1145 } else {
1146 result += ch;
1147 }
1148 }
1149 result += "\"";
1150 // If the string contains a null byte, make sure that we don't truncate the literal
1151 if(original.find('\0') == std::string::npos)
1152 return result;
1153 else
1154 return "std::string(" + result + ", " + std::to_string(original.size()) + ")";
1155}
std::string to_str() const
static const Reg8 ch(Operand::CH)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ generate_call()

string generate_call ( picojson::object obj)

Definition at line 1250 of file spec_test_generator.cpp.

1250 {
1251 stringstream ss;
1252
1253 ss << "bkend(\"env\", ";
1254 ss << cpp_string(obj["field"]);
1255
1256 for (picojson::value argv : obj["args"].get<picojson::array>()) {
1257 ss << ", ";
1259 if (arg["type"].to_str() == "i32")
1260 ss << "UINT32_C(" << arg["value"].to_str() << ")";
1261 else if (arg["type"].to_str() == "i64")
1262 ss << "UINT64_C(" << arg["value"].to_str() << ")";
1263 else if (arg["type"].to_str() == "f32")
1264 ss << "bit_cast<float>(UINT32_C(" << arg["value"].to_str() << "))";
1265 else
1266 ss << "bit_cast<double>(UINT64_C(" << arg["value"].to_str() << "))";
1267 }
1268 ss << ")";
1269 return ss.str();
1270}
char ** argv
static const Segment ss(Segment::ss)
value::object object
std::string cpp_string(const picojson::value &x)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ generate_test_call()

string generate_test_call ( picojson::object obj,
string expected_t,
string expected_v )

Definition at line 1157 of file spec_test_generator.cpp.

1157 {
1158 stringstream ss;
1159
1160 if (expected_t == "i32") {
1161 ss << "bkend.call_with_return(\"env\", ";
1162 } else if (expected_t == "i64") {
1163 ss << "bkend.call_with_return(\"env\", ";
1164 } else if (expected_t == "f32") {
1165 ss << "bit_cast<uint32_t>(bkend.call_with_return(\"env\", ";
1166 } else if (expected_t == "f64") {
1167 ss << "bit_cast<uint64_t>(bkend.call_with_return(\"env\", ";
1168 } else {
1169 ss << "!bkend.call_with_return(\"env\", ";
1170 }
1171
1172 ss << cpp_string(obj["field"]);
1173
1174 for (picojson::value argv : obj["args"].get<picojson::array>()) {
1175 ss << ", ";
1177 if (arg["type"].to_str() == "i32")
1178 ss << "UINT32_C(" << arg["value"].to_str() << ")";
1179 else if (arg["type"].to_str() == "i64")
1180 ss << "UINT64_C(" << arg["value"].to_str() << ")";
1181 else if (arg["type"].to_str() == "f32")
1182 ss << "bit_cast<float>(UINT32_C(" << arg["value"].to_str() << "))";
1183 else
1184 ss << "bit_cast<double>(UINT64_C(" << arg["value"].to_str() << "))";
1185 }
1186 if (expected_t == "i32") {
1187 ss << ")->to_ui32() == ";
1188 ss << "UINT32_C(" << expected_v << ")";
1189 } else if (expected_t == "i64") {
1190 ss << ")->to_ui64() == ";
1191 ss << "UINT32_C(" << expected_v << ")";
1192 } else if (expected_t == "f32") {
1193 ss << ")->to_f32()) == ";
1194 ss << "UINT32_C(" << expected_v << ")";
1195 } else if (expected_t == "f64") {
1196 ss << ")->to_f64()) == ";
1197 ss << "UINT64_C(" << expected_v << ")";
1198 } else {
1199 ss << ")";
1200 }
1201 return ss.str();
1202}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ generate_test_call_nan()

string generate_test_call_nan ( picojson::object obj)

Definition at line 1205 of file spec_test_generator.cpp.

1205 {
1206 stringstream ss;
1207
1208 ss << "check_nan(bkend.call_with_return(\"env\", ";
1209
1210 ss << cpp_string(obj["field"]);
1211
1212 for (picojson::value argv : obj["args"].get<picojson::array>()) {
1213 ss << ", ";
1215 if (arg["type"].to_str() == "i32")
1216 ss << "UINT32_C(" << arg["value"].to_str() << ")";
1217 else if (arg["type"].to_str() == "i64")
1218 ss << "UINT64_C(" << arg["value"].to_str() << ")";
1219 else if (arg["type"].to_str() == "f32")
1220 ss << "bit_cast<float>(UINT32_C(" << arg["value"].to_str() << "))";
1221 else
1222 ss << "bit_cast<double>(UINT64_C(" << arg["value"].to_str() << "))";
1223 }
1224 ss << "))";
1225 return ss.str();
1226}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ generate_tests()

void generate_tests ( const map< string, vector< picojson::object > > & mappings)

Definition at line 1285 of file spec_test_generator.cpp.

1285 {
1286 stringstream unit_tests;
1287 string exp_t, exp_v;
1288 unit_tests << test_includes;
1289 auto grab_expected = [&](auto obj) {
1290 exp_t = obj["type"].to_str();
1291 exp_v = obj["value"].to_str();
1292 };
1293
1294 for (const auto& [tsn_file, cmds] : mappings) {
1295 if(tsn_file.empty() || blacklist.count(tsn_file)) continue;
1296 auto tsn = tsn_file;
1297 std::replace(tsn.begin(), tsn.end(), '.', '_');
1298 unit_tests << "BACKEND_TEST_CASE( \"Testing wasm <" << tsn << ">\", \"[" << tsn << "_tests]\" ) {\n";
1299 unit_tests << " " << test_preamble_0 << "std::string(wasm_directory) + \"" << tsn_file << "\");\n";
1300
1301 if(!cmds.empty() && [](picojson::object cmd) {
1302 return (cmd["type"].to_str() == "assert_invalid" ||
1303 cmd["type"].to_str() == "assert_malformed" ||
1304 cmd["type"].to_str() == "assert_unlinkable") &&
1305 cmd["module_type"].to_str() == "binary"; }(cmds.front())) {
1306 if (picojson::object(cmds.front())["type"].to_str() == "assert_unlinkable") {
1307 // Unfortunately it's no longer possible to distingish between link errors and parse errors.
1308 unit_tests << " CHECK_THROWS_AS(backend_t(code, &wa), std::exception);\n";
1309 } else {
1310 unit_tests << " CHECK_THROWS_AS(backend_t(code, nullptr), std::exception);\n";
1311 }
1312 } else {
1313 unit_tests << " " << test_preamble_1 << "\n\n";
1314
1315 for (picojson::object cmd : cmds) {
1316 if (cmd["type"].to_str() == "assert_return") {
1317 unit_tests << " CHECK(";
1318 exp_t = "";
1319 exp_v = "";
1320 if (cmd["expected"].get<picojson::array>().size() > 0) {
1321 grab_expected(cmd["expected"].get<picojson::array>()[0].get<picojson::object>());
1322 unit_tests << generate_test_call(cmd["action"].get<picojson::object>(), exp_t, exp_v) << ");\n";
1323 } else {
1324 unit_tests << generate_test_call(cmd["action"].get<picojson::object>(), exp_t, exp_v) << ");\n";
1325 }
1326 } else if (cmd["type"].to_str() == "assert_trap") {
1327 unit_tests << " CHECK_THROWS_AS(";
1328 unit_tests << generate_trap_call(cmd["action"].get<picojson::object>()) << ");\n";
1329 } else if (cmd["type"].to_str() == "action") {
1330 unit_tests << generate_call(cmd["action"].get<picojson::object>()) << ";\n";
1331 } else if (cmd["type"].to_str() == "assert_return_canonical_nan" ||
1332 cmd["type"].to_str() == "assert_return_arithmetic_nan") {
1333 unit_tests << " CHECK(";
1334 unit_tests << generate_test_call_nan(cmd["action"].get<picojson::object>()) << ");\n";
1335 }
1336 }
1337 }
1338 unit_tests << "}\n\n";
1339 cout << unit_tests.str();
1340 unit_tests.str("");
1341 }
1342}
const string test_includes
string generate_call(picojson::object obj)
string generate_test_call_nan(picojson::object obj)
string generate_test_call(picojson::object obj, string expected_t, string expected_v)
const string test_preamble_0
string generate_trap_call(picojson::object obj)
const string test_preamble_1
Here is the call graph for this function:
Here is the caller graph for this function:

◆ generate_trap_call()

string generate_trap_call ( picojson::object obj)

Definition at line 1228 of file spec_test_generator.cpp.

1228 {
1229 stringstream ss;
1230
1231 ss << "bkend(\"env\", ";
1232 ss << cpp_string(obj["field"]);
1233
1234 for (picojson::value argv : obj["args"].get<picojson::array>()) {
1235 ss << ", ";
1237 if (arg["type"].to_str() == "i32")
1238 ss << "UINT32_C(" << arg["value"].to_str() << ")";
1239 else if (arg["type"].to_str() == "i64")
1240 ss << "UINT64_C(" << arg["value"].to_str() << ")";
1241 else if (arg["type"].to_str() == "f32")
1242 ss << "bit_cast<float>(UINT32_C(" << arg["value"].to_str() << "))";
1243 else
1244 ss << "bit_cast<double>(UINT64_C(" << arg["value"].to_str() << "))";
1245 }
1246 ss << "), std::exception";
1247 return ss.str();
1248}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( int argc,
char ** argv )

Definition at line 1350 of file spec_test_generator.cpp.

1350 {
1351 ifstream ifs;
1352 stringstream ss;
1353 if(argc != 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
1354 usage(argc?argv[0]:"spec_test_generator");
1355 }
1356 ifs.open(argv[1]);
1357 if(!ifs) {
1358 std::cerr << "Cannot open file: " << argv[1] << std::endl;
1359 return EXIT_FAILURE;
1360 }
1361 string s;
1362 while (getline(ifs, s)) ss << s;
1363 ifs.close();
1364
1366 picojson::parse(v, ss.str());
1367 string test_suite_name;
1368
1369 map<string, vector<picojson::object>> test_mappings;
1371 for (picojson::value::object::const_iterator i = obj.begin(); i != obj.end(); i++)
1372 if (i->first == "commands") {
1373 for (const auto& o : i->second.get<picojson::array>()) {
1374 picojson::object obj = o.get<picojson::object>();
1375 if (obj["type"].to_str() == "module" || obj["type"].to_str() == "assert_invalid" || (obj["type"].to_str() == "assert_malformed" && obj["module_type"].to_str() == "binary") || obj["type"].to_str() == "assert_unlinkable" ) {
1376 test_suite_name = obj["filename"].to_str();
1377 test_mappings[test_suite_name] = {};
1378 }
1379 test_mappings[test_suite_name].push_back(obj);
1380 }
1381 }
1382
1383 generate_tests(test_mappings);
1384}
const T & get() const
std::map< std::string, value > object
std::string parse(value &out, Iter &pos, const Iter &last)
value::array array
void generate_tests(const map< string, vector< picojson::object > > &mappings)
void usage(const char *name)
char * s
Here is the call graph for this function:

◆ operator<<()

std::ostream & operator<< ( std::ostream & os,
const picojson::value & x )
inline

Definition at line 1110 of file spec_test_generator.cpp.

1110 {
1111 x.serialize(std::ostream_iterator<char>(os));
1112 return os;
1113}
void serialize(Iter os, bool prettify=false) const
os_t os
Here is the call graph for this function:

◆ operator>>()

std::istream & operator>> ( std::istream & is,
picojson::value & x )
inline

Definition at line 1100 of file spec_test_generator.cpp.

1100 {
1101 picojson::set_last_error(std::string());
1102 const std::string err(picojson::parse(x, is));
1103 if (!err.empty()) {
1105 is.setstate(std::ios::failbit);
1106 }
1107 return is;
1108}
void set_last_error(const std::string &s)
Here is the call graph for this function:

◆ usage()

void usage ( const char * name)

Definition at line 1344 of file spec_test_generator.cpp.

1344 {
1345 std::cerr << "Usage:\n"
1346 << " " << name << " [json file created by wast2json]\n";
1347 std::exit(2);
1348}
std::string name
Here is the caller graph for this function:

Variable Documentation

◆ blacklist

const std::set<std::string> blacklist
Initial value:
= {
"data.2.wasm",
"data.4.wasm", "data.5.wasm", "data.6.wasm", "data.7.wasm", "data.8.wasm", "data.10.wasm",
"data.13.wasm", "data.17.wasm", "data.19.wasm", "data.20.wasm", "data.21.wasm",
"data.22.wasm", "data.23.wasm", "data.24.wasm", "data.30.wasm", "data.32.wasm", "data.36.wasm", "data.38.wasm",
"elem.2.wasm", "elem.4.wasm", "elem.5.wasm", "elem.6.wasm", "elem.9.wasm",
"elem.11.wasm", "elem.14.wasm", "elem.15.wasm", "elem.16.wasm", "elem.17.wasm", "elem.23.wasm",
"elem.25.wasm", "elem.27.wasm", "elem.29.wasm", "elem.37.wasm", "elem.39.wasm", "elem.40.wasm",
"func_ptrs.0.wasm", "globals.14.wasm", "names.3.wasm",
"start.5.wasm", "start.6.wasm", "start.7.wasm"
}

Definition at line 1273 of file spec_test_generator.cpp.

1273 {
1274 "data.2.wasm",
1275 "data.4.wasm", "data.5.wasm", "data.6.wasm", "data.7.wasm", "data.8.wasm", "data.10.wasm",
1276 "data.13.wasm", "data.17.wasm", "data.19.wasm", "data.20.wasm", "data.21.wasm",
1277 "data.22.wasm", "data.23.wasm", "data.24.wasm", "data.30.wasm", "data.32.wasm", "data.36.wasm", "data.38.wasm",
1278 "elem.2.wasm", "elem.4.wasm", "elem.5.wasm", "elem.6.wasm", "elem.9.wasm",
1279 "elem.11.wasm", "elem.14.wasm", "elem.15.wasm", "elem.16.wasm", "elem.17.wasm", "elem.23.wasm",
1280 "elem.25.wasm", "elem.27.wasm", "elem.29.wasm", "elem.37.wasm", "elem.39.wasm", "elem.40.wasm",
1281 "func_ptrs.0.wasm", "globals.14.wasm", "names.3.wasm",
1282 "start.5.wasm", "start.6.wasm", "start.7.wasm"
1283};

◆ test_includes

const string test_includes
Initial value:
= "// Generated by spec_test_generator. DO NOT MODIFY THIS FILE.\n\n"
"#include <algorithm>\n#include <vector>\n#include <iostream>\n#include "
"<iterator>\n#include <cmath>\n#include <cstdlib>\n#include <catch2/catch.hpp>\n"
"#include <utils.hpp>\n#include <wasm_config.hpp>\n#include "
"<sysio/vm/backend.hpp>\n\nusing namespace sysio;\nusing namespace sysio::vm;\n"
"extern wasm_allocator wa;\n\n"

Definition at line 1122 of file spec_test_generator.cpp.

◆ test_preamble_0

const string test_preamble_0 = "using backend_t = backend<standalone_function_t, TestType>;\n auto code = read_wasm( "

Definition at line 1128 of file spec_test_generator.cpp.

◆ test_preamble_1

const string test_preamble_1 = "backend_t bkend( code, &wa );"

Definition at line 1129 of file spec_test_generator.cpp.