Skip to content

Commit 2ad2ae3

Browse files
knopers8Barthelemy
authored andcommitted
Fixing tests and improving coverage (#188)
* Fix infrastructure generator test * Add a message passing test of a full QC chain * Improve test coverage of ObjectsManager * Improve test coverage of TaskInterface * Correct test modules' names * Test of CheckInterface * Add a basic test of a message coming from Checker * TaskRunner and TaskRunnerFactory test * Checker and CheckerFactory test * Rename testInfrastractureGenerator.json to testSharedConfig.json * Add argument -b for testWorkflow * fix warning and add TODO * Pass --run to testWorkflow
1 parent be90041 commit 2ad2ae3

16 files changed

Lines changed: 643 additions & 119 deletions

Framework/CMakeLists.txt

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,19 +224,33 @@ set(
224224
test/testPublisher.cxx
225225
test/testQcInfoLogger.cxx
226226
test/testInfrastructureGenerator.cxx
227-
test/testQCTask.cxx
227+
test/testTaskInterface.cxx
228+
test/testTaskRunner.cxx
229+
test/testCheckInterface.cxx
230+
test/testChecker.cxx
228231
test/testQuality.cxx
229232
test/testObjectsManager.cxx
230233
test/testCcdbDatabase.cxx
234+
test/testWorkflow.cxx
231235
)
232236

233-
foreach(test ${TEST_SRCS})
237+
set(
238+
TEST_ARGS
239+
"" "" "" "" "" "" "" "" "" "" "" "" "-b --run"
240+
)
241+
242+
list(LENGTH TEST_SRCS count)
243+
math(EXPR count "${count}-1")
244+
foreach(i RANGE ${count})
245+
list(GET TEST_SRCS ${i} test)
246+
list(GET TEST_ARGS ${i} arg)
234247
get_filename_component(test_name ${test} NAME)
235248
string(REGEX REPLACE ".cxx" "" test_name ${test_name})
249+
string(REPLACE " " ";" arg "${arg}") # make list of string (arguments) out of one string
236250

237251
add_executable(${test_name} ${test})
238252
target_link_libraries(${test_name} PRIVATE QualityControl Boost::unit_test_framework )
239-
add_test(NAME ${test_name} COMMAND ${test_name})
253+
add_test(NAME ${test_name} COMMAND ${test_name} ${arg})
240254
set_tests_properties(${test_name} PROPERTIES TIMEOUT 30)
241255
install(TARGETS ${test_name} DESTINATION tests)
242256
endforeach()
@@ -330,6 +344,7 @@ install(
330344

331345
install(
332346
FILES
333-
test/testQCFactory.json
347+
test/testSharedConfig.json
348+
test/testWorkflow.json
334349
DESTINATION tests
335-
)
350+
)

Framework/include/QualityControl/TaskConfig.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ struct TaskConfig {
3030
int cycleDurationSeconds;
3131
int maxNumberCycles;
3232
std::string consulUrl;
33-
o2::configuration::KeyValueMap customParameters;
33+
o2::configuration::KeyValueMap customParameters = {};
3434
};
3535

3636
} // namespace o2::quality_control::core

Framework/src/Checker.cxx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ void Checker::run(framework::ProcessingContext& ctx)
144144

145145
o2::header::DataDescription Checker::createCheckerDataDescription(const std::string taskName)
146146
{
147+
if (taskName.empty()) {
148+
BOOST_THROW_EXCEPTION(FatalException() << errinfo_details("Empty taskName for checker's data description"));
149+
}
147150
o2::header::DataDescription description;
148151
description.runtimeInit(std::string(taskName.substr(0, o2::header::DataDescription::size - 4) + "-chk").c_str());
149152
return description;

Framework/src/TaskRunner.cxx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ using namespace o2::header;
4141
using namespace o2::configuration;
4242
using namespace o2::monitoring;
4343
using namespace std::chrono;
44+
using namespace AliceO2::Common;
4445

4546
TaskRunner::TaskRunner(const std::string& taskName, const std::string& configurationSource, size_t id)
4647
: mDeviceName(createTaskRunnerIdString() + "-" + taskName),
@@ -177,6 +178,9 @@ header::DataOrigin TaskRunner::createTaskDataOrigin()
177178

178179
header::DataDescription TaskRunner::createTaskDataDescription(const std::string& taskName)
179180
{
181+
if (taskName.empty()) {
182+
BOOST_THROW_EXCEPTION(FatalException() << errinfo_details("Empty taskName for task's data description"));
183+
}
180184
o2::header::DataDescription description;
181185
description.runtimeInit(std::string(taskName.substr(0, header::DataDescription::size - 3) + "-mo").c_str());
182186
return description;
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright CERN and copyright holders of ALICE O2. This software is
2+
// distributed under the terms of the GNU General Public License v3 (GPL
3+
// Version 3), copied verbatim in the file "COPYING".
4+
//
5+
// See http://alice-o2.web.cern.ch/license for full licensing information.
6+
//
7+
// In applying this license CERN does not waive the privileges and immunities
8+
// granted to it by virtue of its status as an Intergovernmental Organization
9+
// or submit itself to any jurisdiction.
10+
11+
///
12+
/// \file testCheckInterface.cxx
13+
/// \author Piotr Konopka
14+
///
15+
16+
#include "QualityControl/CheckInterface.h"
17+
18+
#define BOOST_TEST_MODULE CheckInterface test
19+
#define BOOST_TEST_MAIN
20+
#define BOOST_TEST_DYN_LINK
21+
22+
#include <boost/test/unit_test.hpp>
23+
#include <iostream>
24+
#include <TObjString.h>
25+
#include <string>
26+
27+
using namespace o2::quality_control;
28+
using namespace std;
29+
30+
namespace o2::quality_control
31+
{
32+
33+
using namespace core;
34+
35+
namespace test
36+
{
37+
38+
class TestCheck : public checker::CheckInterface
39+
{
40+
public:
41+
/// Default constructor
42+
TestCheck() = default;
43+
/// Destructor
44+
~TestCheck() override = default;
45+
46+
// Override interface
47+
void configure(std::string name) override
48+
{
49+
mValidString = name;
50+
}
51+
Quality check(const MonitorObject* mo) override
52+
{
53+
if (mValidString.empty()) {
54+
return Quality::Null;
55+
}
56+
57+
TObjString* str = reinterpret_cast<TObjString*>(mo->getObject());
58+
return mValidString == str->String() ? Quality::Good : Quality::Bad;
59+
}
60+
61+
void beautify(MonitorObject* mo, Quality = Quality::Null) override
62+
{
63+
TObjString* str = reinterpret_cast<TObjString*>(mo->getObject());
64+
str->String().Append(" is beautiful now");
65+
}
66+
67+
std::string getAcceptedType() override
68+
{
69+
return "TObjString";
70+
}
71+
72+
string mValidString;
73+
};
74+
75+
} /* namespace test */
76+
} /* namespace o2::quality_control */
77+
78+
BOOST_AUTO_TEST_CASE(test_invoke_all_methods)
79+
{
80+
test::TestCheck testCheck;
81+
82+
MonitorObject mo(new TObjString("A string"), "str");
83+
84+
BOOST_CHECK_EQUAL(testCheck.check(&mo), Quality::Null);
85+
86+
testCheck.configure("A different string");
87+
BOOST_CHECK_EQUAL(testCheck.check(&mo), Quality::Bad);
88+
89+
testCheck.configure("A string");
90+
BOOST_CHECK_EQUAL(testCheck.check(&mo), Quality::Good);
91+
92+
testCheck.beautify(&mo);
93+
BOOST_CHECK_EQUAL(reinterpret_cast<TObjString*>(mo.getObject())->String(), "A string is beautiful now");
94+
95+
BOOST_CHECK_EQUAL(testCheck.getAcceptedType(), "TObjString");
96+
}

Framework/test/testChecker.cxx

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright CERN and copyright holders of ALICE O2. This software is
2+
// distributed under the terms of the GNU General Public License v3 (GPL
3+
// Version 3), copied verbatim in the file "COPYING".
4+
//
5+
// See http://alice-o2.web.cern.ch/license for full licensing information.
6+
//
7+
// In applying this license CERN does not waive the privileges and immunities
8+
// granted to it by virtue of its status as an Intergovernmental Organization
9+
// or submit itself to any jurisdiction.
10+
11+
///
12+
/// \file testChecker.cxx
13+
/// \author Piotr Konopka
14+
///
15+
16+
#include "QualityControl/CheckerFactory.h"
17+
#include "QualityControl/Checker.h"
18+
#include <Framework/DataSampling.h>
19+
#include <Framework/DataSpecUtils.h>
20+
21+
#define BOOST_TEST_MODULE Checker test
22+
#define BOOST_TEST_MAIN
23+
#define BOOST_TEST_DYN_LINK
24+
25+
#include <boost/test/unit_test.hpp>
26+
#include <iostream>
27+
28+
using namespace o2::quality_control::checker;
29+
using namespace std;
30+
using namespace o2::framework;
31+
using namespace o2::header;
32+
33+
BOOST_AUTO_TEST_CASE(test_checker_factory)
34+
{
35+
std::string configFilePath =
36+
std::string("json:/") + getenv("QUALITYCONTROL_ROOT") + "/tests/testSharedConfig.json";
37+
38+
CheckerFactory checkerFactory;
39+
DataProcessorSpec checker = checkerFactory.create("abcChecker", "abcTask", configFilePath);
40+
41+
BOOST_CHECK_EQUAL(checker.name, "abcChecker");
42+
43+
BOOST_REQUIRE_EQUAL(checker.inputs.size(), 1);
44+
BOOST_CHECK_EQUAL(checker.inputs[0], (InputSpec{ { "mo" }, "QC", "abcTask-mo", 0 }));
45+
46+
BOOST_REQUIRE_EQUAL(checker.outputs.size(), 1);
47+
BOOST_CHECK_EQUAL(checker.outputs[0], (OutputSpec{ "QC", "abcTask-chk", 0 }));
48+
49+
BOOST_CHECK(checker.algorithm.onInit != nullptr);
50+
}
51+
52+
BOOST_AUTO_TEST_CASE(test_checker_static)
53+
{
54+
BOOST_CHECK(Checker::createCheckerDataDescription("qwertyuiop") == DataDescription("qwertyuiop-chk"));
55+
BOOST_CHECK(Checker::createCheckerDataDescription("012345678901234567890") == DataDescription("012345678901-chk"));
56+
BOOST_CHECK_THROW(Checker::createCheckerDataDescription(""), AliceO2::Common::FatalException);
57+
}
58+
59+
BOOST_AUTO_TEST_CASE(test_checker)
60+
{
61+
std::string configFilePath =
62+
std::string("json:/") + getenv("QUALITYCONTROL_ROOT") + "/tests/testSharedConfig.json";
63+
64+
Checker checker{ "abcChecker", "abcTask", configFilePath };
65+
66+
BOOST_CHECK_EQUAL(checker.getInputSpec(), (InputSpec{ { "mo" }, "QC", "abcTask-mo", 0 }));
67+
BOOST_CHECK_EQUAL(checker.getOutputSpec(), (OutputSpec{ "QC", "abcTask-chk", 0 }));
68+
69+
// This is maximum that we can do until we are able to test the DPL algorithms in isolation.
70+
// TODO: When it is possible, we should try calling run() and init()
71+
}

Framework/test/testDbFactory.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include "QualityControl/MySqlDatabase.h"
2121

2222
#endif
23-
#define BOOST_TEST_MODULE Quality test
23+
#define BOOST_TEST_MODULE DbFactory test
2424
#define BOOST_TEST_MAIN
2525
#define BOOST_TEST_DYN_LINK
2626

Framework/test/testInfrastructureGenerator.cxx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
/// \author Piotr Konopka
1414
///
1515

16-
#define BOOST_TEST_MODULE QCFactory test
16+
#define BOOST_TEST_MODULE InfrastructureGenerator test
1717
#define BOOST_TEST_MAIN
1818
#define BOOST_TEST_DYN_LINK
1919

@@ -30,15 +30,15 @@ using namespace o2::framework;
3030
BOOST_AUTO_TEST_CASE(qc_factory_local_test)
3131
{
3232
BOOST_REQUIRE_NE(getenv("QUALITYCONTROL_ROOT"), nullptr);
33-
std::string configFilePath = std::string("json:/") + getenv("QUALITYCONTROL_ROOT") + "/tests/testQCFactory.json";
33+
std::string configFilePath = std::string("json:/") + getenv("QUALITYCONTROL_ROOT") + "/tests/testSharedConfig.json";
3434

3535
{
3636
auto workflow = InfrastructureGenerator::generateLocalInfrastructure(configFilePath, "o2flp1");
3737

3838
BOOST_REQUIRE_EQUAL(workflow.size(), 1);
3939

4040
BOOST_CHECK_EQUAL(workflow[0].name, "QC-TASK-RUNNER-skeletonTask");
41-
BOOST_CHECK_EQUAL(workflow[0].inputs.size(), 1);
41+
BOOST_CHECK_EQUAL(workflow[0].inputs.size(), 2);
4242
BOOST_CHECK_EQUAL(workflow[0].outputs.size(), 1);
4343
BOOST_CHECK_EQUAL(DataSpecUtils::getOptionalSubSpec(workflow[0].outputs[0]).value_or(-1), 1);
4444
}
@@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(qc_factory_local_test)
4949
BOOST_REQUIRE_EQUAL(workflow.size(), 1);
5050

5151
BOOST_CHECK_EQUAL(workflow[0].name, "QC-TASK-RUNNER-skeletonTask");
52-
BOOST_CHECK_EQUAL(workflow[0].inputs.size(), 1);
52+
BOOST_CHECK_EQUAL(workflow[0].inputs.size(), 2);
5353
BOOST_CHECK_EQUAL(workflow[0].outputs.size(), 1);
5454
BOOST_CHECK_EQUAL(DataSpecUtils::getOptionalSubSpec(workflow[0].outputs[0]).value_or(-1), 2);
5555
}
@@ -63,7 +63,7 @@ BOOST_AUTO_TEST_CASE(qc_factory_local_test)
6363

6464
BOOST_AUTO_TEST_CASE(qc_factory_remote_test)
6565
{
66-
std::string configFilePath = std::string("json:/") + getenv("QUALITYCONTROL_ROOT") + "/tests/testQCFactory.json";
66+
std::string configFilePath = std::string("json:/") + getenv("QUALITYCONTROL_ROOT") + "/tests/testSharedConfig.json";
6767
auto workflow = InfrastructureGenerator::generateRemoteInfrastructure(configFilePath);
6868

6969
// the infrastructure should consist of a merger and checker for the 'skeletonTask' (its taskRunner is declared to be
@@ -93,8 +93,8 @@ BOOST_AUTO_TEST_CASE(qc_factory_remote_test)
9393
auto taskRunnerAbcTask = std::find_if(
9494
workflow.begin(), workflow.end(),
9595
[](const DataProcessorSpec& d) {
96-
return d.name == "abcTask" &&
97-
d.inputs.size() == 1 &&
96+
return d.name == "QC-TASK-RUNNER-abcTask" &&
97+
d.inputs.size() == 2 &&
9898
d.outputs.size() == 1;
9999
});
100100
BOOST_CHECK(taskRunnerAbcTask != workflow.end());

Framework/test/testObjectsManager.cxx

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@
1515

1616
#include "QualityControl/ObjectsManager.h"
1717

18-
#define BOOST_TEST_MODULE Publisher test
18+
#define BOOST_TEST_MODULE ObjectManager test
1919
#define BOOST_TEST_MAIN
2020
#define BOOST_TEST_DYN_LINK
2121
#include "../include/Common/Exceptions.h"
2222
#include <TObjString.h>
23+
#include <TH1F.h>
2324
#include <boost/test/unit_test.hpp>
2425
#include <iostream>
2526

@@ -67,4 +68,53 @@ BOOST_AUTO_TEST_CASE(unpublish_test)
6768
BOOST_CHECK_THROW(objectsManager.stopPublishing("asdf"), ObjectNotFoundError);
6869
}
6970

71+
BOOST_AUTO_TEST_CASE(getters_test)
72+
{
73+
TaskConfig config;
74+
config.taskName = "test";
75+
config.consulUrl = "http://consul-test.cern.ch:8500";
76+
ObjectsManager objectsManager(config);
77+
78+
TObjString s("content");
79+
TH1F h("histo", "h", 100, 0, 99);
80+
81+
objectsManager.startPublishing(&s);
82+
objectsManager.startPublishing(&h);
83+
84+
// basic gets
85+
BOOST_CHECK_NO_THROW(objectsManager.getMonitorObject("content"));
86+
BOOST_CHECK_NO_THROW(objectsManager.getMonitorObject("histo"));
87+
BOOST_CHECK_THROW(objectsManager.getMonitorObject("unexisting object"), ObjectNotFoundError);
88+
BOOST_CHECK_NO_THROW(objectsManager.getObject("content"));
89+
BOOST_CHECK_NO_THROW(objectsManager.getObject("histo"));
90+
BOOST_CHECK_THROW(objectsManager.getObject("unexisting object"), ObjectNotFoundError);
91+
92+
// non owning array
93+
TObjArray* array = objectsManager.getNonOwningArray();
94+
BOOST_CHECK_EQUAL(array->GetEntries(), 2);
95+
BOOST_CHECK(array->FindObject("content") != nullptr);
96+
BOOST_CHECK(array->FindObject("histo") != nullptr);
97+
98+
// we confirm that deleting the array does not delete objects
99+
delete array;
100+
BOOST_CHECK_NO_THROW(objectsManager.getMonitorObject("content"));
101+
BOOST_CHECK_NO_THROW(objectsManager.getMonitorObject("histo"));
102+
}
103+
104+
BOOST_AUTO_TEST_CASE(metadata_test)
105+
{
106+
TaskConfig config;
107+
config.taskName = "test";
108+
config.consulUrl = "http://consul-test.cern.ch:8500";
109+
ObjectsManager objectsManager(config);
110+
111+
TObjString s("content");
112+
TH1F h("histo", "h", 100, 0, 99);
113+
objectsManager.startPublishing(&s);
114+
objectsManager.startPublishing(&h);
115+
116+
objectsManager.addMetadata("content", "aaa", "bbb");
117+
BOOST_CHECK_EQUAL(objectsManager.getMonitorObject("content")->getMetadataMap()["aaa"], "bbb");
118+
}
119+
70120
} // namespace o2::quality_control::core

0 commit comments

Comments
 (0)