Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 8 additions & 0 deletions phlex/model/identifier.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ namespace phlex::experimental {
inline std::string_view format_as(identifier const& id) { return std::string_view(id); }
}

template <>
struct fmt::formatter<phlex::experimental::identifier> : formatter<std::string_view> {
auto format(phlex::experimental::identifier const& id, format_context& ctx) const
{
return formatter<std::string_view>::format(std::string_view(id), ctx);
}
};

template <>
struct std::hash<phlex::experimental::identifier> {
std::size_t operator()(phlex::experimental::identifier const& id) const noexcept
Expand Down
4 changes: 4 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ cet_test(
cet_test(product_query USE_CATCH2_MAIN SOURCE product_query.cpp LIBRARIES
phlex::core
)
cet_test(core_misc_test USE_CATCH2_MAIN SOURCE core_misc_test.cpp LIBRARIES
phlex::core
Boost::json
)
cet_test(
provider_test
USE_CATCH2_MAIN
Expand Down
107 changes: 107 additions & 0 deletions test/core_misc_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#include "phlex/configuration.hpp"
#include "phlex/core/consumer.hpp"
#include "phlex/core/glue.hpp"
#include "phlex/core/registrar.hpp"
#include "phlex/model/algorithm_name.hpp"
#include <catch2/catch_test_macros.hpp>

#include <boost/json.hpp>
#include <stdexcept>
#include <string>
#include <vector>

TEST_CASE("algorithm_name tests", "[model]")
{
using namespace phlex::experimental;

SECTION("Default constructor")
{
algorithm_name an;
CHECK(an.full() == "");
}
SECTION("Create from string with colon")
{
auto an = algorithm_name::create("plugin:algo");
CHECK(an.full() == "plugin:algo");
}
SECTION("Create from string without colon")
{
auto an = algorithm_name::create("algo");
// For 'either' cases, the first word is stored as plugin_
CHECK(an.full() == "algo:");
}
SECTION("Create from char pointer")
{
auto an = algorithm_name::create("ptr:algo");
CHECK(an.full() == "ptr:algo");
}
SECTION("Create error - trailing colon")
{
CHECK_THROWS_AS(algorithm_name::create("plugin:"), std::runtime_error);
}
SECTION("Match neither")
{
algorithm_name an = algorithm_name::create("p:a");
algorithm_name other; // neither
CHECK(an.match(other));
}
SECTION("Match either")
{
algorithm_name an = algorithm_name::create("p:a");
CHECK(an.match(algorithm_name::create("p")));
CHECK(an.match(algorithm_name::create("a")));
}
SECTION("Match both")
{
algorithm_name an = algorithm_name::create("p:a");
CHECK(an.match(algorithm_name::create("p:a")));
CHECK_FALSE(an.match(algorithm_name::create("p:b")));
}
}

TEST_CASE("consumer tests", "[core]")
{
using namespace phlex::experimental;
algorithm_name an = algorithm_name::create("p:a");
consumer c(an, {"pred1"});

CHECK(c.full_name() == "p:a");
CHECK(c.plugin() == "p");
CHECK(c.algorithm() == "a");
CHECK(c.when().size() == 1);
}

TEST_CASE("verify_name tests", "[core]")
{
using namespace phlex::experimental::detail;

SECTION("non-empty name does nothing") { CHECK_NOTHROW(verify_name("valid_name", nullptr)); }

SECTION("empty name throws") { CHECK_THROWS_AS(verify_name("", nullptr), std::runtime_error); }

SECTION("empty name with config includes module label")
{
boost::json::object obj;
obj["module_label"] = "my_module";
phlex::configuration config{obj};

try {
verify_name("", &config);
FAIL("Should have thrown");
} catch (std::runtime_error const& e) {
std::string msg = e.what();
CHECK(msg.find("my_module") != std::string::npos);
}
}
}

TEST_CASE("add_to_error_messages tests", "[core]")
{
using namespace phlex::experimental::detail;

std::vector<std::string> errors;
add_to_error_messages(errors, "duplicate_node");

REQUIRE(errors.size() == 1);
CHECK(errors[0].find("duplicate_node") != std::string::npos);
}
47 changes: 47 additions & 0 deletions test/data_cell_index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,50 @@ TEST_CASE("Verify independent hashes", "[data model]")
CHECK(event_760->hash() != event_4999->hash());
CHECK(event_760->layer_hash() == event_4999->layer_hash());
}

TEST_CASE("data_cell_index methods", "[data model]")
{
auto base = data_cell_index::base_ptr();
auto run0 = base->make_child(0, "run");
auto run1 = base->make_child(1, "run");

SECTION("Comparisons")
{
CHECK(*run0 < *run1);
CHECK_FALSE(*run1 < *run0);
CHECK_FALSE(*run0 < *run0);

auto subrun0 = run0->make_child(0, "subrun");
auto subrun1 = run0->make_child(1, "subrun");
CHECK(*subrun0 < *subrun1);
CHECK(*run0 < *subrun0);
}

SECTION("to_string")
{
auto subrun = run0->make_child(5, "subrun");
CHECK(subrun->to_string() == "[run:0, subrun:5]");
CHECK(base->to_string() == "[]");

auto nameless = base->make_child(10, "");
CHECK(nameless->to_string() == "[10]");
}

SECTION("Parent lookup")
{
auto subrun = run0->make_child(5, "subrun");
auto event = subrun->make_child(100, "event");

CHECK(event->parent("subrun") == subrun);
CHECK(event->parent("run") == run0);
CHECK(event->parent("nonexistent") == nullptr);
}

SECTION("Layer path")
{
auto subrun = run0->make_child(5, "subrun");
CHECK(subrun->layer_path() == "/job/run/subrun");
}

SECTION("Base access") { CHECK(&data_cell_index::base() == data_cell_index::base_ptr().get()); }
}
10 changes: 10 additions & 0 deletions test/identifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,15 @@ int main()
}
}
assert(ok);

// Additional coverage for identifier edge cases
identifier id1("abc");
identifier id2("def");
assert(id1 == id1);
assert(id1 != id2);
assert(id1 < id2 || id2 < id1);
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

The assertion id1 < id2 || id2 < id1 is a tautology that will always be true for any two distinct identifiers, since we already established they're not equal on line 73. This doesn't meaningfully test the less-than operator. Consider replacing with assert(id1 < id2); to specifically verify the comparison relationship between "abc" and "def", or split it into two separate assertions to test both directions with known values.

Suggested change
assert(id1 < id2 || id2 < id1);
assert(id1 < id2);

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

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

Not if the operators are defined incorrectly.

assert(id1 <= id1);
assert(id1 >= id1);

return 0;
}
Loading