63 schemaFolderPath =
"./../types/schemas/"
64 schemaFolderPath = os.path.abspath(
65 os.path.join(os.path.dirname(__file__), schemaFolderPath)
68 schemaFilePath = os.path.join(schemaFolderPath, f
"{fname}.fbs")
69 if not os.path.isfile(schemaFilePath):
72 schemaFile = open(schemaFilePath,
"r")
79 for line
in schemaFile:
82 match = re.search(
r'^table [a-zA-Z_]*_fb', line)
84 line = line.strip().split()
85 tableIdx = line.index(
"table")
86 schemaTableName = line[tableIdx + 1]
89 line = line.strip().split()
90 subNameIdx = line.index(
"table")
91 subName = line[subNameIdx + 1]
92 subTables[subName] = []
95 if not inTable
and "{" in line:
110 lineParts = line.strip().rstrip(
";").split(
":")
112 type = lineParts[1].split()[0]
114 if curSubTable
is not None:
116 subTables[curSubTable].append((name, type))
118 schemaFieldInfo.append((name, type))
121 if len(subTables) == 0:
122 return schemaTableName, tuple(schemaFieldInfo)
126 newSchemaFieldInfo = []
127 for field
in schemaFieldInfo:
129 if fieldType
in subTables.keys():
130 newSchemaFieldInfo.append({field[0] : subTables[fieldType]})
132 newSchemaFieldInfo.append(field)
134 return schemaTableName, tuple(newSchemaFieldInfo)
138Quick check that the types in .fbs correspond, mainly strings match to strings,
139and vectors to vectors.
140If they do not correspond, the behavior for comparing the fb values in the tests
141is undefined, and action beyond this generator will need to be taken.
182 headerFile = open(hppFname,
"r")
183 headerLines = headerFile.readlines()
186 fNameParts = hppFname.split(
"/")
187 returnInfo[
"name"] = fNameParts[-1].strip().split(
".")[0]
188 CamelCase =
"".join([word.capitalize()
for word
in returnInfo[
"name"].split(
"_")])
189 returnInfo[
"nameCamelCase"] = CamelCase[0].lower() + CamelCase[1:]
191 returnInfo[
"genTestFname"] = f
"{returnInfo['name']}_generated_tests.cpp"
192 returnInfo[
"className"] =
"C" +
"".join([word.capitalize()
for word
in returnInfo[
"name"].split(
"_")])
193 returnInfo[
"classVarName"] =
"".join([word[0].lower()
for word
in returnInfo[
"name"].split(
"_")])
200 if returnInfo[
"name"]
not in baseTypesDict:
201 baseTypesDict[returnInfo[
"name"]] = set()
205 messageStructIdxs = []
206 for i
in range(len(headerLines)):
207 if "messageT(" in headerLines[i]:
208 messageStructIdxs.append(i)
211 returnInfo[
"schemaTableName"] = schemaTableName
214 if len(messageStructIdxs) == 0:
216 if returnInfo[
"baseType"]
not in baseTypesDict:
217 baseTypesDict[returnInfo[
"baseType"]] = set()
220 baseTypesDict[returnInfo[
"baseType"]].add(returnInfo[
"name"])
224 returnInfo[
"messageTypes"] =
getMessageFieldInfo(messageStructIdxs, headerLines, schemaFieldInfo)
229Parse out field type and name from string
233 typeIdxStart = 1
if (lineParts[0] ==
"const")
else 0
234 type = lineParts[typeIdxStart]
236 if lineParts[typeIdxStart + 1] ==
"&":
237 nameIdx = (typeIdxStart + 2)
238 elif lineParts[typeIdxStart + 1] ==
"*":
239 nameIdx = (typeIdxStart + 2)
240 type +=
" " + lineParts[typeIdxStart + 1]
242 nameIdx = (typeIdxStart + 1)
244 name = lineParts[nameIdx].rstrip(
")").rstrip(
",")
249Checks if log type has a corresponding generated .h file in ./types/generated
252 generatedFolderPath =
"./../types/generated/"
253 generatedFolderPath = os.path.abspath(
254 os.path.join(os.path.dirname(__file__), generatedFolderPath)
257 generatedFilePath = os.path.join(generatedFolderPath, f
"{logName}_generated.h")
258 if os.path.isfile(generatedFilePath):
320 if "bool" in fieldType
or (schemaFieldType
is not None and "bool" in schemaFieldType):
322 elif "string" in fieldType
or "char *" in fieldType:
323 if gIncrementingVals:
324 gNextVals[
"string"] += 1
325 return f
'"{gNextVals["string"]}"'
326 randString =
''.join(random.choices(string.ascii_lowercase + string.digits, k=10))
327 return f
'"{randString}"'
328 elif "int" in fieldType:
329 if gIncrementingVals:
333 return f
'{str(getRandInt(fieldType))}u' if "uint64_t" in fieldType
else str(
getRandInt(fieldType))
334 elif "float" in fieldType:
335 if gIncrementingVals:
336 gNextVals[
"float"] += 1
337 return str(round( (gNextVals[
"float"] / 100000), 6))
338 return str(round(random.random(), 6))
339 elif "double" in fieldType:
340 if gIncrementingVals:
341 gNextVals[
"double"] += 1
342 return str(round( (gNextVals[
"double"] / 10000000000), 14))
343 return str(round(random.random(), 14))
372 subTableDictIndex = 0
375 for i
in range(len(messageStructIdxs)):
376 structIdx = messageStructIdxs[i]
381 while not closed
and structIdx < len(lines):
383 line = lines[structIdx]
387 if "//" in line
and line.find(
")") > line.find(
"//"):
390 elif line.strip().strip(
")") ==
"":
397 indexStart = (line.find(
"messageT(") + len(
"messageT("))
if "messageT(" in line
else 0
398 indexEnd = line.find(
"//")
if "//" in line
else len(line)
399 line = line[indexStart:indexEnd]
401 lineParts = [part.strip().split()
for part
in line.strip().rstrip(
",").split(
",")]
403 for field
in lineParts:
405 if len(field) > 0
and "//" in field[0]:
411 fieldDict[
"type"] = type
412 fieldDict[
"name"] = name
414 if "std::vector" in fieldDict[
"type"]:
415 typeParts = fieldDict[
"type"].split(
"<")
416 vectorIdx = [i
for i, e
in enumerate(typeParts)
if "std::vector" in e][0]
417 vectorType = typeParts[vectorIdx + 1].strip(
">")
418 fieldDict[
"vectorType"] = vectorType
420 if len(schemaFieldInfo) != 0:
421 if isinstance(schemaFieldInfo[fieldCount], tuple):
422 fieldDict[
"schemaName"] = schemaFieldInfo[fieldCount][0]
423 fieldDict[
"schemaType"] = schemaFieldInfo[fieldCount][1]
427 subTableName = next(iter(schemaFieldInfo[fieldCount]))
428 schemaFieldName = schemaFieldInfo[fieldCount][subTableName][subTableDictIndex][0]
429 schemaFieldType = schemaFieldInfo[fieldCount][subTableName][subTableDictIndex][1]
430 fieldDict[
"schemaName"] = f
"{subTableName}()->{schemaFieldName}"
431 fieldDict[
"schemaType"] = schemaFieldType
432 subTableDictIndex += 1
433 if (subTableDictIndex >= len(schemaFieldInfo[fieldCount][subTableName])):
435 subTableDictIndex = 0
443 del fieldDict[
"schemaName"]
448 msgsFieldsList.append(fieldDict)
452 msgTypesList.append(msgsFieldsList)
459 baseFilePath = os.path.join(typesFolderPath, f
"{baseName}.hpp")
460 baseHFile = open(baseFilePath,
"r")
464 returnInfo[
"name"] = logName
465 returnInfo[
"genTestFname"] = f
"{returnInfo['name']}_generated_tests.cpp"
466 returnInfo[
"className"] =
"C" +
"".join([word.capitalize()
for word
in returnInfo[
"name"].split(
"_")])
467 CamelCase =
"".join([word.capitalize()
for word
in returnInfo[
"name"].split(
"_")])
468 returnInfo[
"nameCamelCase"] = CamelCase[0].lower() + CamelCase[1:]
469 returnInfo[
"classVarName"] =
"".join([word[0].lower()
for word
in returnInfo[
"name"].split(
"_")])
470 returnInfo[
"baseType"] = baseName
474 baseHLines = baseHFile.readlines()
477 messageStructIdxs = []
478 for i
in range(len(baseHLines)):
479 if "messageT(" in baseHLines[i]:
480 messageStructIdxs.append(i)
484 returnInfo[
"schemaTableName"] = schemaTableName
487 returnInfo[
"messageTypes"] = [[]]
if "empty_log" in baseName
else msgFieldInfo
497 print(
"Error: Python version must be >= 3.9")
501 global gIncrementingVals
502 gIncrementingVals =
False
506 opts, args = getopt.getopt(sys.argv[1:],
"is:")
508 print(
"Error: Only one option allowed. -s <seed> or -i for incrementing values.")
511 except getopt.GetoptError:
512 print(
"Usage: python3 ./generateTemplatedCatch2Tests.py -s <seed> | -i")
514 for opt, arg
in opts:
516 if not arg.isdigit():
517 print(f
"Error: random seed {arg} provided is not an integer.")
520 random.seed(int(arg))
522 gIncrementingVals =
True
525 env = jinja2.Environment(
526 loader = jinja2.FileSystemLoader(searchpath=os.path.dirname(__file__))
528 env.trim_blocks =
True
529 env.lstrip_blocks =
True
531 catchTemplate = env.get_template(
"catch2TestTemplate.jinja2")
534 typesFolderPath =
"./../types"
535 typesFolderPath = os.path.abspath(
536 os.path.join(os.path.dirname(__file__), typesFolderPath)
540 generatedTestsFolderPath =
"./generated_tests/"
541 generatedTestsFolderPath = os.path.abspath(
542 os.path.join(os.path.dirname(__file__), generatedTestsFolderPath)
546 pathlib.Path(generatedTestsFolderPath).mkdir(exist_ok=
True)
547 oldFiles = glob.glob(os.path.join(generatedTestsFolderPath,
"*"))
548 for file
in oldFiles:
551 types = os.listdir(typesFolderPath)
553 baseTypesDict = dict()
557 if ".hpp" not in type:
560 typePath = os.path.join(typesFolderPath, type)
569 renderedHeader = catchTemplate.render(info)
572 outPath = os.path.join(generatedTestsFolderPath, info[
"genTestFname"])
573 with open(outPath,
"w")
as outfile:
574 print(renderedHeader,file=outfile)
577 for baseType, inheritedTypes
in baseTypesDict.items():
579 if len(inheritedTypes) == 0:
582 for inheritedType
in inheritedTypes:
589 renderedHeader = catchTemplate.render(info)
592 outPath = os.path.join(generatedTestsFolderPath, info[
"genTestFname"])
593 with open(outPath,
"w")
as outfile:
594 print(renderedHeader,file=outfile)