A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
example-as-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Lawrence Livermore National Laboratory
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Peter D. Barnes, Jr. <pdbarnes@llnl.gov>
7 */
8
9#include "example-as-test.h"
10
11#include "ascii-test.h"
12#include "assert.h"
14#include "fatal-error.h"
15#include "log.h"
16
17#include <cstdlib> // itoa(), system ()
18#include <cstring>
19#include <sstream>
20#include <string>
21
22/**
23 * \file
24 * \ingroup testing
25 * Implementation of classes ns3::ExampleAsTestSuite and ns3::ExampleTestCase.
26 */
27
28namespace ns3
29{
30
31NS_LOG_COMPONENT_DEFINE("ExampleAsTestCase");
32
33// Running tests as examples currently requires Python.
34
36 const std::string program,
37 const std::string dataDir,
38 const std::string args /* = "" */,
39 const bool shouldNotErr /* = true */)
40 : TestCase(name),
41 m_program(program),
42 m_dataDir(dataDir),
43 m_args(args),
44 m_shouldNotErr(shouldNotErr)
45{
46 NS_LOG_FUNCTION(this << name << program << dataDir << args);
47}
48
53
54std::string
56{
58 std::string command("%s ");
59 command += m_args;
60 return command;
61}
62
63std::string
65{
67 std::string command("");
68 return command;
69}
70
71void
73{
75 // Set up the output file names
77 std::string refFile = CreateDataDirFilename(GetName() + ".reflog");
78 std::string testFile = CreateTempDirFilename(GetName() + ".reflog");
79 std::string post = GetPostProcessingCommand();
80
81 if (!m_shouldNotErr)
82 {
83 // Strip any system- or compiler-dependent messages
84 // resulting from invoking NS_FATAL..., which in turn
85 // calls std::terminate
86 post += " | sed '1,/" + std::string(NS_FATAL_MSG) + "/!d' ";
87 }
88
89 std::stringstream ss;
90
91 ss << "python3 ./ns3 run " << m_program << " --no-build --command-template=\""
92 << GetCommandTemplate() << "\"";
93
94 if (post.empty())
95 {
96 // redirect to testfile, then std::clog, std::cerr to std::cout
97 ss << " > " << testFile << " 2>&1";
98 }
99 else
100 {
101 ss << " 2>&1 " << post << " > " << testFile;
102 }
103
104 int status = std::system(ss.str().c_str());
105
106 std::cout << "\n"
107 << GetName() << ":\n"
108 << " command: " << ss.str() << "\n"
109 << " status: " << status << "\n"
110 << " refFile: " << refFile << "\n"
111 << " testFile: " << testFile << "\n"
112 << " testFile contents:" << std::endl;
113
114 std::ifstream logF(testFile);
115 std::string line;
116 while (getline(logF, line))
117 {
118 std::cout << "--- " << line << "\n";
119 }
120 logF.close();
121
122 if (m_shouldNotErr)
123 {
124 // Make sure the example didn't outright crash
125 NS_TEST_ASSERT_MSG_EQ(status, 0, "example " + m_program + " failed");
126 }
127
128 // If we're just introspecting the command-line
129 // we've run the example and we're done
130 auto [found, intro] = EnvironmentVariable::Get("NS_COMMANDLINE_INTROSPECTION");
131 if (found)
132 {
133 return;
134 }
135
136 // Compare the testFile to the reference file
137 NS_ASCII_TEST_EXPECT_EQ(testFile, refFile);
138}
139
141 const std::string program,
142 const std::string dataDir,
143 const std::string args /* = "" */,
144 const Duration duration /* =QUICK */,
145 const bool shouldNotErr /* = true */)
146 : TestSuite(name, Type::EXAMPLE)
147{
148 NS_LOG_FUNCTION(this << name << program << dataDir << args << duration << shouldNotErr);
149 AddTestCase(new ExampleAsTestCase(name, program, dataDir, args, shouldNotErr), duration);
150}
151
152} // namespace ns3
#define NS_ASCII_TEST_EXPECT_EQ(gotFilename, expectedFilename)
Test that a pair of new/reference ascii files are equal.
Definition ascii-test.h:27
NS_ASSERT() and NS_ASSERT_MSG() macro definitions.
static KeyFoundType Get(const std::string &envvar, const std::string &key="", const std::string &delim=";")
Get the value corresponding to a key from an environment variable.
Execute an example program as a test, by comparing the output to a reference file.
virtual std::string GetCommandTemplate() const
Customization point for more complicated patterns to invoke the example program.
bool m_shouldNotErr
Whether error return status is a test failure.
virtual std::string GetPostProcessingCommand() const
Customization point for tests requiring post-processing of stdout.
void DoRun() override
Implementation to actually run this TestCase.
ExampleAsTestCase(const std::string name, const std::string program, const std::string dataDir, const std::string args="", const bool shouldNotErr=true)
Constructor.
std::string m_args
Any additional arguments to the program.
std::string m_dataDir
The source directory for the test.
std::string m_program
The program to run.
~ExampleAsTestCase() override
Destructor.
ExampleAsTestSuite(const std::string name, const std::string program, const std::string dataDir, const std::string args="", const Duration duration=Duration::QUICK, const bool shouldNotErr=true)
Constructor.
encapsulates test code
Definition test.h:1050
std::string CreateDataDirFilename(std::string filename)
Construct the full path to a file in the data directory.
Definition test.cc:413
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
Duration
How long the test takes to execute.
Definition test.h:1054
std::string CreateTempDirFilename(std::string filename)
Construct the full path to a file in a temporary directory.
Definition test.cc:432
void SetDataDir(std::string directory)
Set the data directory where reference trace files can be found.
Definition test.cc:472
std::string GetName() const
Definition test.cc:367
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
Class Environment declaration.
Enable examples to be run as meaningful tests.
NS_FATAL_x macro definitions.
constexpr std::string_view NS_FATAL_MSG
Output string marking imminent invocation of std::terminate.
Definition fatal-error.h:56
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition test.h:134
Debug message logging.
Every class exported by the ns3 library is enclosed in the ns3 namespace.