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
9 changes: 3 additions & 6 deletions tools/ctrace/src/control/TraceDirectoryJob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,10 @@ static std::vector<std::pair<std::string, std::string>> referenceContext(const T
return context;
}

/** @brief Reports informational, warning, and error annotations from trace-run references. */
static void reportTraceRunDiagnostics(const TraceRunConfig& config, DiagnosticSink& diagnostics)
/** @brief Reports annotations from every reference retained by the trace-run reader. */
static void reportConsumedReferenceDiagnostics(const TraceRunConfig& config, DiagnosticSink& diagnostics)
{
for (const auto& reference : config.references) {
if (TraceRunSchema::isItmChannelZero(reference)) {
continue;
}
const auto report = [&](DiagnosticSink::Severity severity, const std::optional<std::string>& message) {
if (!message.has_value() || message->empty()) {
return;
Expand Down Expand Up @@ -117,7 +114,7 @@ void TraceDirectoryJob::run()
{"setups", std::to_string(config.setups.size())},
},
});
reportTraceRunDiagnostics(config, m_diagnostics);
reportConsumedReferenceDiagnostics(config, m_diagnostics);
const auto ctraceRunMeta = CtraceRunMeta::fromConfig(config);
reportTraceRunWarnings(ctraceRunMeta, m_diagnostics);
const auto rawInputs = TraceRunDiscovery::rawInputs(configFile);
Expand Down
38 changes: 37 additions & 1 deletion tools/ctrace/test/integration/src/CtraceIntegTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,44 @@ TEST_F(CtraceIntegTests, AppliesTraceRunConfiguration)
EXPECT_EQ(0, result.exitCode) << result.stderrText;
expectContains(result.stderrText, "aligned DWT range");
expectContains(result.stderrText, "configured DWT data trace");
expectContains(result.stderrText, "configured ITM channel");
expectContains(result.stderrText, "applied ctrace-run meta");
expectNotContains(result.stderrText, "configured ITM channel");
}

TEST_F(CtraceIntegTests, ReportsDiagnosticsFromConsumedTraceRunReferences)
{
writeFile(workDirectory() / "Diagnostics.ctrace-run.yml", R"yml(ctrace-run:
ctrace-setup:
- pname: core
timestamps:
clock: 400000000
ctrace-refs:
- ctrace-ref: core/itm
type: itm
pname: core
stream: 1
source: 0
info: configured ITM channel zero
warning: ITM channel zero uses fallback routing
error: target could not enable ITM channel zero
- ctrace-ref: core/exceptions
type: exception
error: ignored reference diagnostic
)yml");
writeFile(workDirectory() / "Diagnostics.SWO.raw");

const auto result = run({"ctrace", workDirectory().string(), "--target", "Diagnostics", "--all"});
EXPECT_EQ(0, result.exitCode) << result.stderrText;
expectContains(result.stderrText, "[info] configured ITM channel zero:");
expectContains(result.stderrText, "[warning] ITM channel zero uses fallback routing:");
expectContains(result.stderrText, "[error] target could not enable ITM channel zero:");
expectContains(result.stderrText, "ctraceRef=core/itm, type=itm, pname=core");
expectNotContains(result.stderrText, "ignored reference diagnostic");

expectNonEmptyFile(workDirectory() / "Diagnostics.SWO.csv");
expectNonEmptyFile(workDirectory() / "Diagnostics.ctf" / "metadata");
expectNonEmptyFile(workDirectory() / "Diagnostics.ctf" / "stream_0");
expectNonEmptyFile(workDirectory() / "Diagnostics.SWO.traceanalysis.xml");
}

TEST_F(CtraceIntegTests, GeneratesRequestedOutputsAfterDecoderError)
Expand Down
58 changes: 57 additions & 1 deletion tools/ctrace/test/unit/src/control/TraceDirectoryJobTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ static void writeTraceInputs(const std::filesystem::path& traceDirectory,
}
}

/** @brief Finds one diagnostic with an exact message. */
static const DiagnosticSink::Event* findDiagnostic(const CollectingDiagnosticSink& diagnostics,
const std::string_view message)
{
const auto found = std::find_if(diagnostics.events().begin(), diagnostics.events().end(),
[&](const auto& event) { return event.message == message; });
return found == diagnostics.events().end() ? nullptr : &*found;
}

TEST(CtraceUnitTests, testTraceDirectoryTargetAndOutputNames)
{
const TemporaryTestPath temporaryPath("ctrace-trace-directory-job-test");
Expand Down Expand Up @@ -170,7 +179,7 @@ TEST(CtraceUnitTests, testTraceDirectoryReportsGenerationDiagnosticsAndMissingSw
emptyError.warning = "";
emptyError.error = "";
auto channelZero = TraceRunTestSupport::makeReference("itm", std::nullopt, std::nullopt, {0U}, "core/itm");
channelZero.error = "ignored channel zero";
channelZero.error = "channel zero diagnostic";
TraceRunReference noStream = reported;
noStream.ctraceRef = "core/no-stream";
noStream.stream.reset();
Expand All @@ -189,9 +198,56 @@ TEST(CtraceUnitTests, testTraceDirectoryReportsGenerationDiagnosticsAndMissingSw
EXPECT_TRUE(diagnostics.containsMessage("producer note"));
EXPECT_TRUE(diagnostics.containsMessage("producer warning"));
EXPECT_TRUE(diagnostics.containsMessage("producer error"));
EXPECT_TRUE(diagnostics.containsMessage("channel zero diagnostic"));
EXPECT_TRUE(diagnostics.containsMessage("trace generation setup failed without a diagnostic message"));
EXPECT_TRUE(diagnostics.containsMessage("does not match ctrace-setup pname"));
EXPECT_TRUE(diagnostics.containsMessage("skipping raw trace channel"));
EXPECT_TRUE(diagnostics.containsMessage("no supported <solution-set>.SWO.raw input found"));

const auto* info = findDiagnostic(diagnostics, "producer note");
const auto* warning = findDiagnostic(diagnostics, "producer warning");
const auto* error = findDiagnostic(diagnostics, "producer error");
const auto* channelZeroError = findDiagnostic(diagnostics, "channel zero diagnostic");
ASSERT_NE(info, nullptr);
ASSERT_NE(warning, nullptr);
ASSERT_NE(error, nullptr);
ASSERT_NE(channelZeroError, nullptr);
EXPECT_EQ(info->severity, DiagnosticSink::Severity::Info);
EXPECT_EQ(warning->severity, DiagnosticSink::Severity::Warning);
EXPECT_EQ(error->severity, DiagnosticSink::Severity::Error);
EXPECT_EQ(channelZeroError->severity, DiagnosticSink::Severity::Error);
EXPECT_EQ(error->impact, DiagnosticSink::Impact::NonFailing);
EXPECT_EQ(channelZeroError->impact, DiagnosticSink::Impact::NonFailing);
}

TEST(CtraceUnitTests, testTraceDirectoryChecksOutputRequirementsAfterReferenceError)
{
const TemporaryTestPath temporaryPath("ctrace-trace-directory-reference-error-test");
const auto traceDir = temporaryPath.path() / ".trace";
writeTraceInputs(traceDir, {"MissingClock"});

TraceRunConfig config;
auto reference = TraceRunTestSupport::makeReference("event", "core", 3U, {}, "core/event");
reference.error = "producer could not configure event trace";
config.references.push_back(std::move(reference));

CliOptions options;
options.traceDir = traceDir.string();
options.targetName = "MissingClock";
options.outputFormat = OutputFormat::All;

CollectingDiagnosticSink diagnostics;
TestTraceRunConfigReader reader(config);
TraceDirectoryJob(options, diagnostics, reader).run();

const auto* referenceError = findDiagnostic(diagnostics, "producer could not configure event trace");
ASSERT_NE(referenceError, nullptr);
EXPECT_EQ(referenceError->severity, DiagnosticSink::Severity::Error);
EXPECT_EQ(referenceError->impact, DiagnosticSink::Impact::NonFailing);
EXPECT_TRUE(diagnostics.containsMessage("CTF output requires timestamps.clock"));
EXPECT_GT(diagnostics.failureCount(), 0U);
EXPECT_TRUE(std::filesystem::is_regular_file(traceDir / "MissingClock.SWO.csv"));
EXPECT_FALSE(std::filesystem::exists(traceDir / "MissingClock.ctf"));
}

TEST(CtraceUnitTests, testTraceDirectoryReportsConfigFailureAndRequiresDirectory)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,11 @@ TEST(CtraceUnitTests, TraceRunReaderPreservesDiagnosticReferences)
- { type: dwt, ctrace-ref: core/notdata#2, error: unrouted }
- { type: itm, ctrace-ref: core/itm0, source: 0, error: disabled }
- { type: itm, ctrace-ref: core/itm1, source: 1, error: usable, label: null }
- { type: exception, ctrace-ref: core/exceptions, error: ignored }
- { type: global_ts, ctrace-ref: core/timesync, warning: ignored }
- { type: overflow, ctrace-ref: core/overflow, info: ignored }
)yml");
ASSERT_EQ(config.references.size(), 8U);
ASSERT_EQ(config.references.size(), 8U) << "reader must ignore diagnostic annotations on unconsumed reference types";
EXPECT_EQ(config.references[0].processorName, std::optional<std::string>("core0"));
EXPECT_EQ(config.references[1].processorName, std::optional<std::string>("core1"));
EXPECT_FALSE(config.references[2].processorName.has_value());
Expand Down
Loading