Skip to content

Commit ab04b2b

Browse files
authored
<TBBAS-2524> Add basic tests for SimpleDeviceModule
- Verify module loads successfully - Verify device is created - Verify device type is correct - Verify value and domain signal descriptors - Verify signal is readable via stream reader
1 parent a45c644 commit ab04b2b

File tree

1 file changed

+282
-12
lines changed

1 file changed

+282
-12
lines changed
Lines changed: 282 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,297 @@
1+
#include <example_module/common.h>
2+
#include <example_module/example_channel.h>
3+
#include <example_module/example_device.h>
4+
#include <example_module/module_dll.h>
5+
#include <example_module/version.h>
16
#include <gmock/gmock.h>
2-
#include <testutils/testutils.h>
37
#include <opendaq/opendaq.h>
8+
#include <testutils/testutils.h>
9+
10+
#include <chrono>
11+
#include <thread>
412

13+
using testing::Contains;
14+
using testing::Each;
15+
using testing::Eq;
16+
using testing::ResultOf;
17+
using testing::SizeIs;
518

619
using namespace daq;
20+
using namespace std::chrono_literals;
21+
22+
using ExampleChannel = modules::example_module::ExampleChannel;
23+
using ExampleDevice = modules::example_module::ExampleDevice;
724
using ExampleModuleTest = testing::Test;
825

9-
TEST_F(ExampleModuleTest, Test1)
26+
static ModulePtr CreateModule()
27+
{
28+
ModulePtr moduleLib;
29+
createModule(&moduleLib, NullContext());
30+
return moduleLib;
31+
}
32+
33+
TEST_F(ExampleModuleTest, ExampleModuleLoaded)
1034
{
1135
const auto instance = Instance();
12-
auto dev = instance.addDevice("example://device");
36+
37+
auto getId = [](const ModulePtr& moduleLib) {
38+
return moduleLib.getModuleInfo().getId();
39+
};
40+
41+
ASSERT_THAT(instance.getModuleManager().getModules(),
42+
Contains(ResultOf(getId, Eq(EXAMPLE_MODULE_NAME))))
43+
<< "Example module wasn't loaded by openDAQ framework";
44+
}
45+
46+
TEST_F(ExampleModuleTest, CreateModule)
47+
{
48+
IModule* moduleLib = nullptr;
49+
ErrCode errCode = createModule(&moduleLib, NullContext());
50+
ASSERT_TRUE(OPENDAQ_SUCCEEDED(errCode));
51+
52+
ASSERT_NE(moduleLib, nullptr);
53+
moduleLib->releaseRef();
54+
}
55+
56+
TEST_F(ExampleModuleTest, ModuleName)
57+
{
58+
auto moduleLib = CreateModule();
59+
ASSERT_EQ(moduleLib.getModuleInfo().getName(), "ReferenceDeviceModule")
60+
<< "Example module name mismatches";
61+
}
62+
63+
TEST_F(ExampleModuleTest, ModuleId)
64+
{
65+
auto moduleLib = CreateModule();
66+
ASSERT_EQ(moduleLib.getModuleInfo().getId(), EXAMPLE_MODULE_NAME)
67+
<< "Example module name mismatches";
68+
}
69+
70+
TEST_F(ExampleModuleTest, VersionCorrect)
71+
{
72+
auto moduleLib = CreateModule();
73+
auto version = moduleLib.getModuleInfo().getVersionInfo();
1374

14-
auto reader = StreamReader<double>(dev.getSignalsRecursive()[0]);
15-
double buffer[1000];
75+
ASSERT_EQ(version.getMajor(), EXAMPLE_MODULE_MAJOR_VERSION);
76+
ASSERT_EQ(version.getMinor(), EXAMPLE_MODULE_MINOR_VERSION);
77+
ASSERT_EQ(version.getPatch(), EXAMPLE_MODULE_PATCH_VERSION);
78+
}
79+
80+
TEST_F(ExampleModuleTest, EnumerateDevices)
81+
{
82+
auto moduleLib = CreateModule();
83+
84+
ListPtr<IDeviceInfo> devices;
85+
ASSERT_NO_THROW(devices = moduleLib.getAvailableDevices());
86+
87+
auto getConnectionString = [](const DeviceInfoPtr device) {
88+
return device.getConnectionString();
89+
};
90+
ASSERT_THAT(devices, Each(ResultOf(getConnectionString, Eq("example://device"))))
91+
<< "Example module doesn't contain example devices";
92+
}
1693

17-
for (int x = 0; x < 100; x++)
94+
TEST_F(ExampleModuleTest, CreateDevice)
95+
{
96+
auto moduleLib = CreateModule();
97+
98+
DevicePtr device;
99+
ASSERT_NO_THROW(device = moduleLib.createDevice("example://device", nullptr));
100+
101+
DeviceInfoPtr info;
102+
ASSERT_NO_THROW(info = device.getInfo());
103+
ASSERT_EQ(info.getName(), "Example Device");
104+
ASSERT_EQ(info.getManufacturer(), "openDAQ");
105+
ASSERT_EQ(info.getModel(), "Reference device");
106+
ASSERT_EQ(info.getSerialNumber(), "ExampleDB1234");
107+
108+
DeviceTypePtr type;
109+
ASSERT_NO_THROW(type = info.getDeviceType());
110+
ASSERT_EQ(type.getId(), "example_dev");
111+
ASSERT_EQ(type.getName(), "Example device");
112+
ASSERT_EQ(type.getDescription(), "Example device");
113+
ASSERT_EQ(type.getConnectionStringPrefix(), "example");
114+
}
115+
116+
TEST_F(ExampleModuleTest, CreateOnlyOneDevice)
117+
{
118+
auto moduleLib = CreateModule();
119+
120+
DevicePtr device;
121+
ASSERT_NO_THROW(device = moduleLib.createDevice("example://device", nullptr))
122+
<< "Create the first device must not fail";
123+
ASSERT_THROW(device = moduleLib.createDevice("example://device", nullptr), std::runtime_error)
124+
<< "Only one example device is allowed";
125+
}
126+
127+
TEST_F(ExampleModuleTest, CreateDeviceInvalidConnection)
128+
{
129+
auto moduleLib = CreateModule();
130+
131+
ASSERT_THROW(DevicePtr device = moduleLib.createDevice("invalid://device", nullptr), std::runtime_error);
132+
}
133+
134+
TEST_F(ExampleModuleTest, DeviceNameAndDeviceInfoNameIsTheSame)
135+
{
136+
auto moduleLib = CreateModule();
137+
138+
DevicePtr device;
139+
ASSERT_NO_THROW(device = moduleLib.createDevice("example://device", nullptr))
140+
<< "Create example device must not fail";
141+
142+
DeviceInfoPtr info;
143+
ASSERT_NO_THROW(info = device.getInfo());
144+
145+
ASSERT_EQ(device.getName(), info.getName())
146+
<< "Device name should be the same as info";
147+
}
148+
149+
TEST_F(ExampleModuleTest, GetDeviceType)
150+
{
151+
auto moduleLib = CreateModule();
152+
153+
DictPtr<IString, IDeviceType> deviceTypes;
154+
ASSERT_NO_THROW(deviceTypes = moduleLib.getAvailableDeviceTypes());
155+
156+
DeviceTypePtr expected = ExampleDevice::CreateType();
157+
StringPtr key = expected.getId();
158+
ASSERT_TRUE(deviceTypes.hasKey(key));
159+
ASSERT_EQ(deviceTypes.get(key).getId(), expected.getId());
160+
}
161+
162+
TEST_F(ExampleModuleTest, GetValueSignals)
163+
{
164+
auto moduleLib = CreateModule();
165+
auto device = moduleLib.createDevice("example://device", nullptr);
166+
167+
ListPtr<ISignal> signals;
168+
ASSERT_NO_THROW(signals = device.getSignalsRecursive());
169+
170+
SizeT count = signals.getCount();
171+
ASSERT_GT(count, 0u) << "Signals list must not be empty";
172+
173+
for (const auto& signal : signals)
18174
{
19-
auto avail = reader.getAvailableCount();
20-
auto data = reader.read(buffer, &avail);
175+
auto id = signal.getGlobalId();
176+
177+
DataDescriptorPtr signalDescriptor;
178+
ASSERT_NO_THROW(signalDescriptor = signal.getDescriptor())
179+
<< id << " get signal descriptor must not fail";
180+
ASSERT_TRUE(signalDescriptor.assigned())
181+
<< id << " signal descriptor is not assigned";
182+
183+
SampleType signalSampleType;
184+
ASSERT_NO_THROW(signalSampleType = signalDescriptor.getSampleType())
185+
<< id << " get signal descriptor failed";
186+
ASSERT_EQ(signalSampleType, SampleType::Float64)
187+
<< id << " float 64 signal sample type is expected";
21188

22-
for (int i = 0; i < avail; i++)
23-
{
24-
std::cout << buffer[i] << std::endl;
25-
}
189+
UnitPtr signalUnit;
190+
ASSERT_NO_THROW(signalUnit = signalDescriptor.getUnit())
191+
<< id << " get signal descriptor failed";
192+
ASSERT_TRUE(signalUnit.assigned())
193+
<< id << " signal unit is not assigned";
194+
195+
ASSERT_EQ(signalUnit.getSymbol(), "V")
196+
<< id << " signal unit symbol mismatches";
197+
ASSERT_EQ(signalUnit.getId(), -1)
198+
<< id << " signal unit ID mismatches";
199+
ASSERT_EQ(signalUnit.getName(), "volts")
200+
<< id << " signal unit name mismatches";
201+
ASSERT_EQ(signalUnit.getQuantity(), "voltage")
202+
<< id << " signal unit quantity mismatches";
203+
}
204+
}
205+
206+
TEST_F(ExampleModuleTest, GetDomainSignal)
207+
{
208+
auto moduleLib = CreateModule();
209+
auto device = moduleLib.createDevice("example://device", nullptr);
210+
211+
ListPtr<ISignal> signals;
212+
ASSERT_NO_THROW(signals = device.getSignalsRecursive());
213+
214+
SizeT count = signals.getCount();
215+
ASSERT_GT(count, 0u) << "Signals list must not be empty";
216+
217+
for (const auto& signal : signals)
218+
{
219+
SignalPtr domainSignal;
220+
ASSERT_NO_THROW(domainSignal = signal.getDomainSignal())
221+
<< signal.getGlobalId()<< " get domain signal must not throw";
222+
ASSERT_NO_THROW(domainSignal.assigned())
223+
<< signal.getGlobalId() << " domain signal is not assigned";
224+
225+
auto id = domainSignal.getGlobalId();
226+
227+
DataDescriptorPtr domainDescriptor;
228+
ASSERT_NO_THROW(domainDescriptor = domainSignal.getDescriptor())
229+
<< id << " get domain descriptor failed";
230+
ASSERT_TRUE(domainDescriptor.assigned())
231+
<< id << " signal domain is not assigned";
232+
ASSERT_EQ(domainDescriptor.getSampleType(), SampleType::Int64)
233+
<< id << " domain signal sample type mismatches";
234+
235+
UnitPtr domainUnit;
236+
ASSERT_NO_THROW(domainUnit = domainDescriptor.getUnit())
237+
<< id << " get signal descriptor failed";
238+
ASSERT_TRUE(domainUnit.assigned())
239+
<< id << " signal unit is not assigned";
240+
241+
ASSERT_EQ(domainUnit.getSymbol(), "s")
242+
<< id << " domain signal unit symbol mismatches";
243+
ASSERT_EQ(domainUnit.getId(), -1)
244+
<< id << " domain signal unit ID mismatches" ;
245+
ASSERT_EQ(domainUnit.getName(), "seconds")
246+
<< id << " domain signal unit name mismatches";
247+
ASSERT_EQ(domainUnit.getQuantity(), "time")
248+
<< id << " domain signal unit quantity mismatches";
249+
250+
RatioPtr tickResolution;
251+
ASSERT_NO_THROW(tickResolution = domainDescriptor.getTickResolution())
252+
<< id << " get domain signal tick resolution failed";
253+
ASSERT_TRUE(tickResolution.assigned()) << "["
254+
<< id << " domain signal tick resolution is not assigned";
255+
ASSERT_EQ(tickResolution, ExampleChannel::getResolution())
256+
<< id << " domain signal tick resolution mismatches";
257+
258+
DataRulePtr dataRule;
259+
ASSERT_NO_THROW(dataRule = domainDescriptor.getRule())
260+
<< id << " get domain signal rule failed";
261+
ASSERT_TRUE(dataRule.assigned())
262+
<< id << " domain signal data rule is not assigned";
263+
264+
ASSERT_EQ(dataRule.getType(), DataRuleType::Linear)
265+
<< id << " domain signal data rule mismatches";
266+
StringPtr deltaKey = "delta";
267+
ASSERT_EQ(dataRule.getParameters().get(deltaKey), 1000)
268+
<< id << " domain signal data rule \"" << deltaKey << "\" parameter mismatches";
269+
StringPtr keyStart = "start";
270+
ASSERT_EQ(dataRule.getParameters().get(keyStart), 0)
271+
<< id << " domain signal data rule \"" << keyStart << "\" parameter mismatches";
272+
273+
ASSERT_EQ(domainDescriptor.getOrigin(), ExampleChannel::getEpoch())
274+
<< id << " domain signal origin mismatches";
275+
}
276+
}
277+
278+
TEST_F(ExampleModuleTest, StreamReader)
279+
{
280+
auto moduleLib = CreateModule();
281+
auto device = moduleLib.createDevice("example://device", nullptr);
282+
283+
ListPtr<ISignal> signals;
284+
ASSERT_NO_THROW(signals = device.getSignalsRecursive());
285+
286+
SizeT count = signals.getCount();
287+
ASSERT_GT(count, 0u) << "Signals list must not be empty";
288+
289+
double buffer[100];
290+
for (const auto& signal : signals)
291+
{
292+
auto reader = StreamReader<double>(signal);
293+
auto capacity = sizeof(buffer) / sizeof(double);
294+
reader.read(buffer, &capacity, std::chrono::milliseconds(1s).count());
295+
EXPECT_GT(count, 0u) << signal.getGlobalId() << " no samples have been read";
26296
}
27297
}

0 commit comments

Comments
 (0)