Skip to content

Commit

Permalink
Implement unit tests for construct query parsing and evaluation (#540)
Browse files Browse the repository at this point in the history
  • Loading branch information
RobinTF committed Jan 25, 2022
1 parent c53412e commit facaf30
Show file tree
Hide file tree
Showing 15 changed files with 983 additions and 38 deletions.
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,11 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")

################################
# GTEST
# GTEST AND GMOCK
################################
add_subdirectory(third_party/googletest/googletest EXCLUDE_FROM_ALL)
add_subdirectory(third_party/googletest EXCLUDE_FROM_ALL)
include_directories(third_party/googletest/googletest/include)
include_directories(third_party/googletest/googlemock/include)

################################
# NLOHNMANN-JSON
Expand Down
2 changes: 1 addition & 1 deletion src/parser/SparqlParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ void SparqlParser::parseQuery(ParsedQuery* query, QueryType queryType) {
for (const auto& triple : constructClause) {
for (const auto& varOrTerm : triple) {
if (auto variable = std::get_if<Variable>(&varOrTerm)) {
const auto& var = variable->getName();
const auto& var = variable->name();
if (std::find(query->_groupByVariables.begin(),
query->_groupByVariables.end(),
var) == query->_groupByVariables.end()) {
Expand Down
15 changes: 14 additions & 1 deletion src/parser/data/BlankNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,20 @@ class BlankNode {

public:
BlankNode(bool generated, std::string label)
: _generated{generated}, _label{std::move(label)} {}
: _generated{generated}, _label{std::move(label)} {
// roughly check allowed characters as blank node labels.
// Weaker than the SPARQL grammar, but good
// enough so that it will likely never be an issue
AD_CHECK(ctre::match<"\\w(?:(?:\\w|-|\\.)*\\w)?">(_label));
}

// ___________________________________________________________________________
// Used for testing
[[nodiscard]] bool isGenerated() const { return _generated; }

// ___________________________________________________________________________
// Used for testing
[[nodiscard]] const std::string& label() const { return _label; }

// ___________________________________________________________________________
[[nodiscard]] std::optional<std::string> evaluate(
Expand Down
9 changes: 6 additions & 3 deletions src/parser/data/Iri.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ class Iri {

public:
explicit Iri(std::string str) : _string{std::move(str)} {
AD_CHECK(ctre::match<
"(?:@[a-zA-Z]+(?:-(?:[a-zA-Z]|\\d)+)*@)?(?:<.+>|[^:]+:[^:]+)">(
_string));
AD_CHECK(ctre::match<"(?:@[a-zA-Z]+(?:-(?:[a-zA-Z]|\\d)+)*@)?"
"<[^<>\"{}|^\\\\`\\0- ]*>">(_string));
}

// ___________________________________________________________________________
// Used for testing
[[nodiscard]] const std::string& iri() const { return _string; }

// ___________________________________________________________________________
[[nodiscard]] std::optional<std::string> evaluate(
[[maybe_unused]] const Context& context,
Expand Down
23 changes: 20 additions & 3 deletions src/parser/data/Literal.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,36 @@
#include <sstream>
#include <string>

#include "../../util/Concepts.h"

class Literal {
std::string _stringRepresentation;

template <typename T>
template <ad_utility::Streamable T>
static std::string toString(const T& t) {
std::ostringstream stream;
stream << t;
return stream.str();
}

static std::string toString(bool boolean) {
return boolean ? "true" : "false";
}

public:
explicit Literal(auto&& t)
: _stringRepresentation(toString(std::forward<decltype(t)>(t))) {}
template <ad_utility::Streamable T>
explicit Literal(T&& t)
: _stringRepresentation(toString(std::forward<T>(t))) {}

static_assert(!ad_utility::Streamable<Literal>,
"If Literal satisfies the Streamable concept, copy and move "
"constructors are hidden, leading to unexpected behaviour");

// ___________________________________________________________________________
// Used for testing
[[nodiscard]] const std::string& literal() const {
return _stringRepresentation;
}

// ___________________________________________________________________________
[[nodiscard]] std::optional<std::string> evaluate(
Expand Down
14 changes: 6 additions & 8 deletions src/parser/data/Variable.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,12 @@ class Variable {

public:
explicit Variable(std::string name) : _name{std::move(name)} {
// Verify variable name is not empty
AD_CHECK(_name.length() > 1);
// verify variable name starts with ? or $ and continues without any
// special characters. This is weaker than the SPARQL grammar,
// but it is close enough so that it will likely never cause issues.
AD_CHECK(ctre::match<"[$?]\\w+">(_name));
// normalise notation for consistency
if (_name[0] == '$') {
_name[0] = '?';
}
// variables have to start with ?
AD_CHECK(_name[0] == '?');
_name[0] = '?';
}

// ___________________________________________________________________________
Expand Down Expand Up @@ -77,5 +75,5 @@ class Variable {
[[nodiscard]] std::string toSparql() const { return _name; }

// ___________________________________________________________________________
[[nodiscard]] const std::string& getName() const { return _name; }
[[nodiscard]] const std::string& name() const { return _name; }
};
18 changes: 18 additions & 0 deletions src/util/Concepts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2022, University of Freiburg,
// Chair of Algorithms and Data Structures.
// Author: Robin Textor-Falconi (textorr@informatik.uni-freiburg.de)

#pragma once

#include <sstream>

namespace ad_utility {
/**
* A concept to ensure objects can be formatted by std::ostream.
* @tparam T The Type to be formatted
*/
template <typename T>
concept Streamable = requires(T x, std::ostream& os) {
os << x;
};
} // namespace ad_utility
25 changes: 22 additions & 3 deletions src/util/TypeTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@ struct TupleToVariantImpl<std::tuple<Ts...>> {
using type = std::variant<Ts...>;
};

// Implementation for Last
template <typename, typename... Ts>
struct LastT : LastT<Ts...> {};

template <typename T>
struct LastT<T> : public std::type_identity<T> {};

// Implementation for First
template <typename T, typename...>
struct FirstWrapper : public std::type_identity<T> {};

} // namespace detail

/// isInstantiation<SomeTemplate, SomeType> is true iff `SomeType` is an
Expand Down Expand Up @@ -97,9 +108,9 @@ constexpr static bool isTypeContainedIn<T, std::variant<Ts...>> = (... || isSimi
template <typename T, typename... Ts>
constexpr static bool isTypeContainedIn<T, std::pair<Ts...>> = (... || isSimilar<T, Ts>);

/// A templated bool that is always false, independent of the template parameter
/// T.
template <typename T>
/// A templated bool that is always false,
/// independent of the template parameter.
template <typename>
constexpr static bool alwaysFalse = false;

/// From the type Tuple (std::tuple<A, B, C....>) creates the type
Expand Down Expand Up @@ -159,4 +170,12 @@ auto applyFunctionToEachElementOfTuple(Function&& f, Tuple&& tuple) {
return std::apply(transformer, std::forward<Tuple>(tuple));
}

// Return the last type of variadic template arguments.
template <typename... Ts>
requires(sizeof...(Ts) > 0) using Last = typename detail::LastT<Ts...>::type;

// Return the first type of variadic template arguments.
template <typename... Ts>
requires(sizeof...(Ts) > 0) using First = typename detail::FirstWrapper<Ts...>::type;

} // namespace ad_utility
13 changes: 3 additions & 10 deletions src/util/streamable_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,12 @@

// Coroutines are still experimental in clang libcpp, therefore
// adapt the appropriate namespaces using the convenience header.
#include "./Concepts.h"
#include "./Coroutines.h"
#include "./ostringstream.h"

namespace ad_utility::stream_generator {

/**
* A concept to ensure objects can be formatted by std::ostream.
* @tparam T The Type to be formatted
*/
template <typename T>
concept Streamable = requires(T x, std::ostream& os) {
os << x;
};

template <size_t MIN_BUFFER_SIZE>
class basic_stream_generator;

Expand Down Expand Up @@ -72,7 +64,8 @@ class stream_generator_promise {
* @return Whether or not the coroutine should get suspended (currently based
* on isBufferLargeEnough()), wrapped inside a suspend_sometimes class.
*/
suspend_sometimes yield_value(const Streamable auto& value) noexcept {
suspend_sometimes yield_value(
const ad_utility::Streamable auto& value) noexcept {
// whenever the buffer size exceeds the threshold the coroutine
// is suspended, thus we can safely assume the value is read
// before resuming
Expand Down
6 changes: 5 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ target_link_libraries(SortPerformanceEstimatorTest gtest_main SortPerformanceEst
#add_test(SortPerformanceEstimatorTest SortPerformanceEstimatorTest)

add_executable(SparqlAntlrParserTest SparqlAntlrParserTest.cpp)
target_link_libraries(SparqlAntlrParserTest gtest_main parser sparqlExpressions ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(SparqlAntlrParserTest gmock_main parser sparqlExpressions ${CMAKE_THREAD_LIBS_INIT})
add_test(SparqlAntlrParserTest SparqlAntlrParserTest)

add_executable(SerializerTest SerializerTest.cpp)
Expand Down Expand Up @@ -220,3 +220,7 @@ add_test(RdfEscapingTest RdfEscapingTest)
add_executable(CompactStringVectorTest CompactStringVectorTest.cpp)
target_link_libraries(CompactStringVectorTest gtest_main ${CMAKE_THREAD_LIBS_INIT})
add_test(CompactStringVectorTest CompactStringVectorTest)

add_executable(SparqlDataTypesTest SparqlDataTypesTest.cpp)
target_link_libraries(SparqlDataTypesTest gmock_main engine ${CMAKE_THREAD_LIBS_INIT})
add_test(SparqlDataTypesTest SparqlDataTypesTest)

0 comments on commit facaf30

Please sign in to comment.