@@ -366,17 +366,16 @@ std::shared_ptr<StructValueView> KTestObjectParser::structView(const std::vector
366
366
break ;
367
367
case TypeKind::OBJECT_POINTER: {
368
368
std::string res = readBytesAsValueForType (byteArray, PointerWidthType,
369
- fieldStartOffset,
370
- PointerWidthSizeInBits);
371
- auto pointerIterator = std::find_if (lazyPointersArray.begin (), lazyPointersArray.end (), [&fieldStartOffset] (const Pointer &ptr) {
372
- return ptr.offset == fieldStartOffset / 8 ;
373
- });
374
- std::optional<Pointer> pointerField = (pointerIterator == lazyPointersArray.end () ? std::nullopt : std::optional (*pointerIterator));
375
- subViews.push_back (getLazyPointerView (objects, pointerField, initReferences,
376
- PrinterUtils::getFieldAccess (name, field), res, field.type ));
377
- }
378
- break ;
379
- case TypeKind::FUNCTION_POINTER:
369
+ fieldStartOffset, PointerWidthSizeInBits);
370
+ auto pointerIterator =
371
+ std::find_if (lazyPointersArray.begin (), lazyPointersArray.end (),
372
+ [&fieldStartOffset](const Pointer &ptr) {
373
+ return ptr.offset == fieldStartOffset / 8 ;
374
+ });
375
+ subViews.push_back (getLazyPointerView (objects, initReferences, PrinterUtils::getFieldAccess (name, field), res, field.type ,
376
+ pointerIterator != lazyPointersArray.end ()));
377
+ } break ;
378
+ case TypeKind::FUNCTION_POINTER:
380
379
subViews.push_back (functionPointerView (curStruct.name , field.name ));
381
380
break ;
382
381
case TypeKind::UNKNOWN:
@@ -569,7 +568,7 @@ static std::string getSuiteName(const UTBotKTest::Status &status,
569
568
return Tests::DEFAULT_SUITE_NAME;
570
569
}
571
570
572
- size_t KTestObjectParser::findFieldIndex (const StructInfo &structInfo, size_t offsetInBits) {
571
+ size_t KTestObjectParser::findFieldIndex (const StructInfo &structInfo, size_t offsetInBits) const {
573
572
size_t indField = std::upper_bound (structInfo.fields .begin (), structInfo.fields .end (), offsetInBits, [] (int offset, const Field &field) {
574
573
return offset < field.offset ;
575
574
}) - structInfo.fields .begin ();
@@ -602,8 +601,16 @@ void KTestObjectParser::addToOrder(const std::vector<UTBotKTestObject> &objects,
602
601
LOG_S (WARNING) << message;
603
602
}
604
603
604
+ bool KTestObjectParser::pointToStruct (const types::Type &pointerType, const UTBotKTestObject &goal) const {
605
+ // In different situations we may point on the whole struct or on the field with assignment 0
606
+ size_t fieldSizeInBits = typesHandler.typeSize (pointerType.baseTypeObj (1 ));
607
+ size_t pointerVarSizeInBytes = goal.bytes .size ();
608
+ return SizeUtils::bytesToBits (pointerVarSizeInBytes) == fieldSizeInBits;
609
+ }
610
+
605
611
void KTestObjectParser::assignTypeUnnamedVar (Tests::MethodTestCase &testCase,
606
- const Tests::MethodDescription &methodDescription) {
612
+ const Tests::MethodDescription &methodDescription,
613
+ std::vector<std::optional<Tests::TypeAndVarName>> &objects) {
607
614
std::queue<JsonIndAndParam> order;
608
615
std::vector<bool > visited (testCase.objects .size (), false );
609
616
for (size_t paramInd = 0 ; paramInd < testCase.paramValues .size (); paramInd++) {
@@ -617,12 +624,14 @@ void KTestObjectParser::assignTypeUnnamedVar(Tests::MethodTestCase &testCase,
617
624
while (!order.empty ()) {
618
625
auto curType = order.front ();
619
626
order.pop ();
627
+ std::string name = testCase.objects [curType.jsonInd ].name ;
620
628
types::Type paramType = curType.param .type ;
629
+ objects[curType.jsonInd ] = { paramType, name };
630
+
621
631
if (testCase.objects [curType.jsonInd ].is_lazy ) {
622
632
if (types::TypesHandler::baseTypeIsVoid (paramType)) {
623
633
throw UnImplementedException (" Lazy variable has baseType=void" );
624
634
}
625
- std::string name = testCase.objects [curType.jsonInd ].name ;
626
635
627
636
std::vector<char > byteValue = testCase.objects [curType.jsonInd ].bytes ;
628
637
Tests::TypeAndVarName typeAndVarName{ paramType, name };
@@ -636,37 +645,38 @@ void KTestObjectParser::assignTypeUnnamedVar(Tests::MethodTestCase &testCase,
636
645
}
637
646
638
647
for (auto const &[offset, indObj, indexOffset] : testCase.objects [curType.jsonInd ].pointers ) {
648
+ if (indexOffset != 0 ) {
649
+ continue ;
650
+ }
651
+ types::Type fieldType =
652
+ traverseLazyInStruct (paramType, SizeUtils::bytesToBits (offset)).type ;
653
+ if (!pointToStruct (fieldType, testCase.objects [indObj])) {
654
+ continue ;
655
+ }
639
656
if (!visited[indObj]) {
640
- types::Type fieldType =
641
- traverseLazyInStruct (visited, paramType, SizeUtils::bytesToBits (offset),
642
- testCase, methodDescription);
643
- Tests::MethodParam param = { fieldType, " " , std::nullopt };
657
+ Tests::MethodParam param = { fieldType.baseTypeObj (1 ), " " , std::nullopt };
644
658
order.emplace (indObj, param, curType.paramValue );
645
659
visited[indObj] = true ;
646
660
}
647
661
}
648
662
}
649
663
}
650
664
651
- types::Type KTestObjectParser::traverseLazyInStruct (std::vector<bool > &visited,
652
- const types::Type &curVarType,
653
- size_t offsetInBits,
654
- const Tests::MethodTestCase &testCase,
655
- const Tests::MethodDescription &methodDescription) {
665
+ Tests::TypeAndVarName KTestObjectParser::traverseLazyInStruct (
666
+ const types::Type &curVarType, size_t offsetInBits, const std::string &curVarName) const {
656
667
switch (typesHandler.getTypeKind (curVarType)) {
657
668
case TypeKind::STRUCT_LIKE: {
658
669
const types::StructInfo &structInfo = typesHandler.getStructInfo (curVarType);
659
670
size_t indField = findFieldIndex (structInfo, offsetInBits);
660
671
const types::Field &next = structInfo.fields [indField];
661
- return traverseLazyInStruct (visited, next.type , offsetInBits - next.offset , testCase,
662
- methodDescription);
672
+ return traverseLazyInStruct (next.type , offsetInBits - next.offset , PrinterUtils::getFieldAccess (curVarName, next));
663
673
}
664
674
case TypeKind::OBJECT_POINTER: {
665
675
LOG_IF_S (ERROR, offsetInBits != 0 ) << " Offset not zero" << offsetInBits;
666
- return curVarType. baseTypeObj ( 1 ) ;
676
+ return { curVarType, curVarName} ;
667
677
}
668
678
case TypeKind::PRIMITIVE: {
669
- return curVarType;
679
+ return { curVarType, curVarName} ;
670
680
}
671
681
case TypeKind::ENUM:
672
682
case TypeKind::FUNCTION_POINTER:
@@ -697,6 +707,50 @@ void KTestObjectParser::assignTypeStubVar(Tests::MethodTestCase &testCase,
697
707
}
698
708
}
699
709
710
+ void
711
+ KTestObjectParser::assignAllLazyPointers (Tests::MethodTestCase &testCase,
712
+ const std::vector<std::optional<Tests::TypeAndVarName>> &objects) const {
713
+ for (size_t ind = 0 ; ind < testCase.objects .size (); ind++) {
714
+ const auto &object = testCase.objects [ind];
715
+ if (!objects[ind].has_value ()) {
716
+ continue ;
717
+ }
718
+ for (const auto &pointer : object.pointers ) {
719
+
720
+ Tests::TypeAndVarName fromPtr = traverseLazyInStruct (objects[ind]->type , SizeUtils::bytesToBits (pointer.offset ), objects[ind]->varName );
721
+ if (!objects[pointer.index ].has_value ()) {
722
+ continue ;
723
+ }
724
+ std::string toPtrName;
725
+
726
+ if (pointer.indexOffset == 0 && pointToStruct (fromPtr.type , testCase.objects [pointer.index ])) {
727
+ toPtrName = objects[pointer.index ]->varName ;
728
+ } else {
729
+ toPtrName = traverseLazyInStruct (objects[pointer.index ]->type , SizeUtils::bytesToBits (pointer.indexOffset ), objects[pointer.index ]->varName ).varName ;
730
+ }
731
+
732
+ testCase.lazyReferences .emplace_back (fromPtr.varName , toPtrName,
733
+ PrinterUtils::initializePointerToVar (fromPtr.type .baseType (),
734
+ toPtrName,
735
+ fromPtr.type .getDimension ()));
736
+ }
737
+ }
738
+
739
+ /*
740
+ * if (!lazyPointer && ptr_element != objects.end()) {
741
+ initReferences.emplace_back(name, ptr_element->name,
742
+ PrinterUtils::initializePointerToVar(paramType.baseType(),
743
+ ptr_element->name,
744
+ paramType.getDimension()));
745
+ }
746
+ if (lazyPointer || ptr_element != objects.end()) {
747
+ res = PrinterUtils::C_NULL;
748
+ }
749
+ return std::make_shared<JustValueView>(
750
+ PrinterUtils::initializePointer(paramType.baseType(), res, paramType.getDimension()));
751
+ */
752
+ }
753
+
700
754
void KTestObjectParser::parseTestCases (const UTBotKTestList &cases,
701
755
bool filterByLineFlag,
702
756
Tests::MethodDescription &methodDescription,
@@ -774,8 +828,10 @@ void KTestObjectParser::parseTestCases(const UTBotKTestList &cases,
774
828
traceStream << " \t return: " << testCase.returnValue .view ->getEntryValue (nullptr );
775
829
LOG_S (MAX) << traceStream.str ();
776
830
777
- assignTypeUnnamedVar (testCase, methodDescription);
831
+ std::vector<std::optional<Tests::TypeAndVarName>> objectsValues (testCase.objects .size ());
832
+ assignTypeUnnamedVar (testCase, methodDescription, objectsValues);
778
833
assignTypeStubVar (testCase, methodDescription);
834
+ assignAllLazyPointers (testCase, objectsValues);
779
835
780
836
methodDescription.testCases .push_back (testCase);
781
837
methodDescription.suiteTestCases [testCase.suiteName ].push_back (testCase.testIndex );
@@ -1098,7 +1154,7 @@ std::shared_ptr<AbstractValueView> KTestObjectParser::testParameterView(
1098
1154
if (usage == types::PointerUsage::LAZY) {
1099
1155
std::string res =
1100
1156
readBytesAsValueForType (rawData, PointerWidthType, 0 , PointerWidthSizeInBits);
1101
- return getLazyPointerView (objects, (kleeParam. pointers . empty () ? std::nullopt : std::optional (kleeParam. pointers [ 0 ])), initReferences, param.varName , res, paramType);
1157
+ return getLazyPointerView (objects, initReferences, param.varName , res, paramType, !kleeParam. pointers . empty () );
1102
1158
} else if (types::TypesHandler::isCStringType (paramType)) {
1103
1159
return stringLiteralView (rawData);
1104
1160
} else if (paramType.kinds ().size () > 2 ) {
@@ -1134,31 +1190,23 @@ std::shared_ptr<AbstractValueView> KTestObjectParser::testParameterView(
1134
1190
1135
1191
std::shared_ptr<AbstractValueView>
1136
1192
KTestObjectParser::getLazyPointerView (const std::vector<UTBotKTestObject> &objects,
1137
- const std::optional<Pointer> &lazyPointer,
1138
1193
std::vector<InitReference> &initReferences,
1139
1194
const std::string &name,
1140
1195
std::string res,
1141
- const Type ¶mType) const {
1142
-
1143
- if (lazyPointer) {
1144
- initReferences.emplace_back (
1145
- name, objects[lazyPointer->index ].name ,
1146
- PrinterUtils::initializePointerToVar (
1147
- paramType.baseType (), objects[lazyPointer->index ].name , paramType.getDimension ()));
1196
+ const Type ¶mType,
1197
+ bool lazyPointer) const {
1198
+ size_t ptr = std::stoull (res);
1199
+ auto ptr_element =
1200
+ std::find_if (objects.begin (), objects.end (),
1201
+ [ptr](const UTBotKTestObject &object) { return object.address == ptr; });
1202
+ if (!lazyPointer && ptr_element != objects.end ()) {
1203
+ initReferences.emplace_back (name, ptr_element->name ,
1204
+ PrinterUtils::initializePointerToVar (paramType.baseType (),
1205
+ ptr_element->name ,
1206
+ paramType.getDimension ()));
1207
+ }
1208
+ if (lazyPointer || ptr_element != objects.end ()) {
1148
1209
res = PrinterUtils::C_NULL;
1149
- } else {
1150
- size_t ptr = std::stoull (res);
1151
-
1152
- auto ptr_element = std::find_if (objects.begin (), objects.end (), [ptr] (const UTBotKTestObject &object) {
1153
- return object.address == ptr;
1154
- });
1155
- if (ptr_element != objects.end ()) {
1156
- initReferences.emplace_back (name, ptr_element->name ,
1157
- PrinterUtils::initializePointerToVar (
1158
- paramType.baseType (), ptr_element->name ,
1159
- paramType.getDimension ()));
1160
- res = PrinterUtils::C_NULL;
1161
- }
1162
1210
}
1163
1211
return std::make_shared<JustValueView>(
1164
1212
PrinterUtils::initializePointer (paramType.baseType (), res, paramType.getDimension ()));
0 commit comments