Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion server/src/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,9 @@ Status Server::TestsGenServiceImpl::provideLoggingCallbacks(
* 1. Using gRPC async API
* 2. Issuing a request from UTBot to a specific client on every log entry.
*/
using namespace std::chrono_literals;
while (holdLockFlag[callbackName].exchange(true, std::memory_order_acquire)) {
std::this_thread::yield();
std::this_thread::sleep_for(100ms);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[PERF] UTBot consumes CPU in spinlocks #382

}
loguru::remove_callback(callbackName.c_str());
if (openFiles) {
Expand Down
219 changes: 66 additions & 153 deletions server/src/Tests.cpp

Large diffs are not rendered by default.

64 changes: 22 additions & 42 deletions server/src/Tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ namespace tests {
return this->subViews;
};


protected:
explicit AbstractValueView(std::vector<std::shared_ptr<AbstractValueView>> subViews) : subViews(std::move(subViews)) {}

Expand Down Expand Up @@ -221,9 +220,11 @@ namespace tests {
struct StructValueView : AbstractValueView {
explicit StructValueView(bool _isCLike,
std::vector<std::string> _fields,
std::vector<std::shared_ptr<AbstractValueView>> subViews,
std::optional<std::string> entryValue)
: AbstractValueView(std::move(subViews)), entryValue(std::move(entryValue)),
int _longestFieldIndexForUnionInit,
std::vector<std::shared_ptr<AbstractValueView>> _subViews,
std::optional<std::string> _entryValue)
: AbstractValueView(std::move(_subViews)), entryValue(std::move(_entryValue)),
longestFieldIndexForUnionInit(_longestFieldIndexForUnionInit),
isCLike(_isCLike),
fields(std::move(_fields)){
}
Expand All @@ -242,8 +243,12 @@ namespace tests {
}

std::vector<std::string> entries;
int i = 0;
for (const auto &subView : subViews) {
entries.push_back(subView->getEntryValue(nullptr));
if (longestFieldIndexForUnionInit < 0 || longestFieldIndexForUnionInit == i) {
entries.push_back(subView->getEntryValue(nullptr));
}
++i;
}

return "{" + StringUtils::joinWith(entries, ", ") + "}";
Expand All @@ -270,34 +275,17 @@ namespace tests {
return "/*" + prefix + "*/";
}

int getLongestFieldIndexForUnionInit() const {
return longestFieldIndexForUnionInit;
}

private:
bool isCLike;
int longestFieldIndexForUnionInit;
std::vector<std::string> fields;
std::optional<std::string> entryValue;
};

/**
* Representation of union.
*/
struct UnionValueView : AbstractValueView {
public:
explicit UnionValueView(const std::string &typeName,
const std::shared_ptr<AbstractValueView> &rawDataView,
std::vector<std::shared_ptr<AbstractValueView>,
std::allocator<std::shared_ptr<AbstractValueView>>> subViews);

[[nodiscard]] std::string getEntryValue(printer::TestsPrinter *printer) const override {
return entryValue;
}

bool containsFPSpecialValue() override {
return false;
}

private:
std::string entryValue;
};

struct InitReference {
std::string varName;
std::string refName;
Expand Down Expand Up @@ -674,33 +662,29 @@ namespace tests {
std::shared_ptr<FunctionPointerView> functionPointerView(const std::string &structName,
const std::string &fieldName);

std::shared_ptr<UnionValueView> unionView(const std::vector<char> &byteArray,
types::UnionInfo &unionInfo,
unsigned int offset,
types::PointerUsage usage);

std::shared_ptr<StructValueView> structView(const std::vector<char> &byteArray,
types::StructInfo &curStruct,
const types::StructInfo &curStruct,
unsigned int offset,
types::PointerUsage usage);

std::shared_ptr<StructValueView> structView(const std::vector<char> &byteArray,
types::StructInfo &curStruct,
const types::StructInfo &curStruct,
unsigned int offset,
types::PointerUsage usage,
const std::optional<const Tests::MethodDescription> &testingMethod,
const std::string &name,
const MapAddressName &fromAddressToName,
std::vector<InitReference> &initReferences);

static std::shared_ptr<EnumValueView> enumView(const std::vector<char> &byteArray,
const types::EnumInfo &enumInfo,
size_t offset,
size_t len);

std::shared_ptr<PrimitiveValueView> primitiveView(const std::vector<char> &byteArray,
const types::Type &type,
size_t offset,
size_t len);
static std::shared_ptr<EnumValueView> enumView(const std::vector<char> &byteArray,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Group enum and struct-like. Seems they need to be joined in the future.

types::EnumInfo &enumInfo,
size_t offset,
size_t len);

std::string primitiveCharView(const types::Type &type, std::string value);
static std::string primitiveBoolView(const std::string &value);
Expand All @@ -720,10 +704,6 @@ namespace tests {
const Tests::MethodDescription &methodDescription,
const std::unordered_map<std::string, types::Type>& methodNameToReturnTypeMap,
const std::stringstream &traceStream);
std::vector<std::shared_ptr<AbstractValueView>> collectUnionSubViews(const std::vector<char> &byteArray,
const types::UnionInfo &info,
unsigned int offset,
types::PointerUsage usage);
void processGlobalParamPreValue(Tests::TestCaseDescription &testCaseDescription,
const Tests::MethodParam &globalParam,
std::vector<RawKleeParam> &rawKleeParams);
Expand Down
84 changes: 23 additions & 61 deletions server/src/printers/KleeConstraintsPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,12 @@ KleeConstraintsPrinter::genConstraints(const std::string &name, const types::Typ
state = { name, name, paramType, state.endString };
genConstraintsForPointerOrArray(state);
break;
case TypeKind::STRUCT:
case TypeKind::STRUCT_LIKE:
genConstraintsForStruct(state);
break;
case TypeKind::ENUM:
genConstraintsForEnum(state);
break;
case TypeKind::UNION:
genConstraintsForUnion(state);
break;
default:
genConstraintsForPrimitive(state);
}
Expand All @@ -50,7 +47,7 @@ void KleeConstraintsPrinter::genConstraintsForPrimitive(const ConstraintsState &
if (!cons.empty()) {
strFunctionCall(PrinterUtils::KLEE_PREFER_CEX, { state.paramName, cons });
} else {
ss << TAB_N() << "// No constraints for " << state.curElement << NL;
ss << LINE_INDENT() << "// No constraints for " << state.curElement << NL;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indent can include the inline comment, so rename it to indent.

}
}

Expand All @@ -67,38 +64,6 @@ void KleeConstraintsPrinter::genConstraintsForEnum(const ConstraintsState &state
strFunctionCall(PrinterUtils::KLEE_ASSUME, { _ss.str() });
}

void KleeConstraintsPrinter::genConstraintsForUnion(const ConstraintsState &state) {
UnionInfo curUnion = typesHandler->getUnionInfo(state.curType);

for (const auto &field : curUnion.fields) {
std::string errorMessage = "Unrecognized field of type '" + field.type.typeName() +
"' in union '" + curUnion.name + "'.";
auto access = PrinterUtils::getFieldAccess(state.curElement, field);
ConstraintsState newState = { state.paramName, access, field.type, false, state.depth + 1 };
switch (typesHandler->getTypeKind(field.type)) {
case TypeKind::PRIMITIVE:
return genConstraintsForPrimitive(newState);
case TypeKind::STRUCT:
return genConstraintsForStruct(newState);
case TypeKind::ARRAY:
return genConstraintsForPointerOrArray(newState);
case TypeKind::ENUM:
return genConstraintsForEnum(newState);
case TypeKind::UNION:
return genConstraintsForUnion(newState);
case TypeKind::OBJECT_POINTER:
return genConstraintsForPointerInUnion(newState);
case TypeKind::UNKNOWN:
LOG_S(ERROR) << errorMessage;
throw UnImplementedException(errorMessage);
default:
std::string message = "Missing case for this TypeKind in switch";
LOG_S(ERROR) << message;
throw NoSuchTypeException(message);
}
}
}

void KleeConstraintsPrinter::genConstraintsForPointerOrArray(const ConstraintsState &state) {
auto sizes = state.curType.arraysSizes(types::PointerUsage::PARAMETER);
genConstraintsForMultiPointerOrArray(state, sizes);
Expand All @@ -119,9 +84,9 @@ void KleeConstraintsPrinter::genConstraintsForMultiPointerOrArray(const Constrai
TypesHandler::isCStringType(state.curType)) {
std::vector<std::string> charSizes(indexes.begin(), indexes.end() - 1);
const auto charElement = constrMultiIndex(state.curElement, charSizes);
ss << TAB_N() << "if (" << indexes.back() << PrinterUtils::EQ_OPERATOR << sizes.back() - 1 << ")" << LB();
ss << TAB_N() << PrinterUtils::KLEE_ASSUME << "(" << charElement << "[" << sizes.back() - 1 << "]" << PrinterUtils::EQ_OPERATOR << "'\\0'" << ")" << SCNL;
ss << TAB_N() << "break" << SCNL;
ss << LINE_INDENT() << "if (" << indexes.back() << PrinterUtils::EQ_OPERATOR << sizes.back() - 1 << ")" << LB();
ss << LINE_INDENT() << PrinterUtils::KLEE_ASSUME << "(" << charElement << "[" << sizes.back() - 1 << "]" << PrinterUtils::EQ_OPERATOR << "'\\0'" << ")" << SCNL;
ss << LINE_INDENT() << "break" << SCNL;
ss << RB();
}

Expand All @@ -132,8 +97,6 @@ void KleeConstraintsPrinter::genConstraintsForMultiPointerOrArray(const Constrai
genConstraintsForStruct(newState);
} else if (typesHandler->isEnum(baseType)) {
genConstraintsForEnum(newState);
} else if (typesHandler->isUnion(baseType)) {
genConstraintsForUnion(newState);
} else {
newState = { state.paramName, element, baseType };
genConstraintsForPrimitive(newState);
Expand All @@ -148,37 +111,42 @@ void KleeConstraintsPrinter::genConstraintsForPointerInStruct(const ConstraintsS

void KleeConstraintsPrinter::genConstraintsForStruct(const ConstraintsState &state) {
StructInfo curStruct = typesHandler->getStructInfo(state.curType);

bool isStruct = curStruct.subType == SubType::Struct;
for (const auto &field : curStruct.fields) {
std::string errorMessage = "Unrecognized field of type '" + field.type.typeName() +
"' in struct '" + curStruct.name + "'.";
auto access = PrinterUtils::getFieldAccess(state.curElement, field);
ConstraintsState newState = { state.paramName, access, field.type, state.endString, state.depth + 1 };
ConstraintsState newState = { state.paramName,
access,
field.type,
isStruct ? state.endString : false,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is still essential difference between struct and union. Need to be investigated (in progress).

state.depth + 1 };
TypeKind kind = typesHandler->getTypeKind(field.type);
std::string stubFunctionName = PrinterUtils::getFunctionPointerAsStructFieldStubName(curStruct.name, field.name);
switch (kind) {
case TypeKind::PRIMITIVE:
genConstraintsForPrimitive(newState);
break;
case TypeKind::STRUCT:
case TypeKind::STRUCT_LIKE:
genConstraintsForStruct(newState);
break;
case TypeKind::ARRAY:
genConstraintsForPointerOrArray(newState);
break;
case TypeKind::ENUM:
genConstraintsForEnum(newState);
break;
case TypeKind::UNION:
genConstraintsForUnion(newState);

case TypeKind::PRIMITIVE:
genConstraintsForPrimitive(newState);
break;
case TypeKind::ARRAY:
genConstraintsForPointerOrArray(newState);
break;
case TypeKind::OBJECT_POINTER:
if (types::TypesHandler::isArrayOfPointersToFunction(field.type)) {
genStubForStructFunctionPointerArray(state.curElement, field.name, stubFunctionName);
genStubForStructFunctionPointerArray(state.curElement, field,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no more just by name access. That leads to unpredictable errors.

stubFunctionName);
}
break;
case TypeKind::FUNCTION_POINTER:
genStubForStructFunctionPointer(state.curElement, field.name, stubFunctionName);
genStubForStructFunctionPointer(state.curElement,
field,
stubFunctionName);
break;
case TypeKind::UNKNOWN:
throw UnImplementedException(errorMessage);
Expand All @@ -189,7 +157,6 @@ void KleeConstraintsPrinter::genConstraintsForStruct(const ConstraintsState &sta
}
}
}

std::string KleeConstraintsPrinter::cexConstraints(const std::string &name, const types::Type &type) {
std::stringstream ssCex;
if (!CollectionUtils::containsKey(TypesHandler::preferredConstraints(), type.baseType())) {
Expand All @@ -205,11 +172,6 @@ std::string KleeConstraintsPrinter::cexConstraints(const std::string &name, cons
return ssCex.str();
}

void printer::KleeConstraintsPrinter::genConstraintsForPointerInUnion(
const ConstraintsState &state) {
strFunctionCall(PrinterUtils::KLEE_ASSUME, { state.curElement + PrinterUtils::EQ_OPERATOR + PrinterUtils::C_NULL });
}

utbot::Language printer::KleeConstraintsPrinter::getLanguage() const {
return srcLanguage;
}
4 changes: 0 additions & 4 deletions server/src/printers/KleeConstraintsPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,8 @@ namespace printer {

void genConstraintsForEnum(const ConstraintsState &state);

void genConstraintsForUnion(const ConstraintsState &state);

void genConstraintsForPointerInStruct(const ConstraintsState &state);

void genConstraintsForPointerInUnion(const ConstraintsState &state);

static std::string cexConstraints(const std::string &name, const types::Type &type);
};
}
Expand Down
3 changes: 0 additions & 3 deletions server/src/printers/KleePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -464,9 +464,6 @@ void KleePrinter::genKleePathSymbolicIfNeeded(
auto filepath = typesHandler->getEnumInfo(baseType).filePath;
headers.insert(typesHandler->getEnumInfo(baseType).filePath);
}
if (typesHandler->isUnion(baseType)) {
headers.insert(typesHandler->getUnionInfo(baseType).filePath);
}
}

KleePrinter::Stream KleePrinter::strKleeMakeSymbolic(const std::string &varName, bool needAmpersand) {
Expand Down
Loading