1 // vim: ts=4 sw=4 noet :
3 ==================================================================================
4 Copyright (c) 2020 Nokia
5 Copyright (c) 2020 AT&T Intellectual Property.
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
11 http://www.apache.org/licenses/LICENSE-2.0
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18 ==================================================================================
22 Mnemonic: Unit_test.cpp
23 Abstract: This is the unit test driver for the C++ xAPP framework. It
24 operates by including all of the modules directly (in order
25 to build them with the necessary coverage flags), then
26 drives all that it can. The RMR emulation module provides
27 emulated RMR functions which simulate the creation, sending
28 and receiving of messages etc.
31 Author: E. Scott Daniels
37 #include "../src/messaging/callback.hpp"
38 #include "../src/messaging/default_cb.hpp"
39 #include "../src/messaging/message.hpp"
40 #include "../src/messaging/messenger.hpp"
41 #include "../src/messaging/msg_component.hpp"
42 #include "../src/alarm/alarm.hpp"
43 #include "../src/xapp/xapp.hpp"
45 #include "../src/messaging/callback.cpp"
46 #include "../src/messaging/default_cb.cpp"
47 #include "../src/messaging/message.cpp"
48 #include "../src/messaging/messenger.cpp"
49 #include "../src/alarm/alarm.cpp"
50 #include "../src/xapp/xapp.cpp"
52 #include "ut_support.cpp"
54 // ---------------------------------------------------------------------------------------------
56 callback error counts are global for ease. They track the number of times each callback
57 was invoked with the expected message type(s) and any times they were not.
68 callback functions to register; driven as we "receive" messages (the RMR emulation package
69 will generate a message every time the receive function is called).
71 void cb1( xapp::Message& mbuf, int mtype, int subid, int len, xapp::Msg_component payload, void* data ) {
72 if( mtype != 1 ) { // should only be driven for type 1 messages
78 void cb2( xapp::Message& mbuf, int mtype, int subid, int len, xapp::Msg_component payload, void* data ) {
79 if( mtype != 2 ) { // should only be driven for type 2 messages
85 void cbd( xapp::Message& mbuf, int mtype, int subid, int len, xapp::Msg_component payload, void* data ) {
86 if( mtype > 0 && mtype < 3 ) { // should only be driven for types that arent 1 or 2
88 fprintf( stderr, "<FAIL> cbd: bad message type: %d\n", mtype );
97 The Xapp Run() function only returns when Xapp is asked to stop, and that
98 isn't supported from inside any of the callbacks. This funciton is
99 started in a thread and after a few seconds it will drive the halt
100 function in the Xapp instance to stop the run function and allow the
103 void killer( std::shared_ptr<Xapp> x ) {
104 fprintf( stderr, "<INFO> killer is waiting in the shadows\n" );
106 fprintf( stderr, "<INFO> killer is on the loose\n" );
110 int main( int argc, char** argv ) {
111 std::thread* tinfo; // we'll start a thread that will shut things down after a few seconds
112 std::unique_ptr<xapp::Message> msg;
113 std::shared_ptr<Xapp> x;
114 xapp::Msg_component payload;
115 std::unique_ptr<unsigned char> ucs;
116 unsigned char* new_payload;
117 std::shared_ptr<unsigned char> new_p_ref; // reference to payload to pass to send functions
118 char* port = (char *) "4560";
119 int ai = 1; // arg processing index
120 int nthreads = 2; // ensure the for loop is executed in setup
127 while( ai < argc ) { // very simple flag processing (no bounds/error checking)
128 if( argv[ai][0] != '-' ) {
132 switch( argv[ai][1] ) { // we only support -x so -xy must be -x -y
139 nthreads = atoi( argv[ai+1] );
147 set_test_name( "unit_test" );
149 // ------------------- generic xapp tests ----------------------------------------------
150 x = std::shared_ptr<Xapp>( new Xapp( port, true ) );
151 x->Add_msg_cb( 1, cb1, NULL );
152 x->Add_msg_cb( 2, cb2, NULL );
153 x->Add_msg_cb( -1, cbd, NULL );
155 msg = x->Alloc_msg( 2048 );
156 payload = msg->Get_payload();
158 msg->Set_mtype( 100 );
159 msg->Set_subid( -10 );
161 ucs = msg->Copy_payload( );
163 fprintf( stderr, "<FAIL> expected pointer to copy payload but got nil\n" );
167 ucs = msg->Get_meid();
169 fprintf( stderr, "<FAIL> expected pointer to meid copy but got nil\n" );
173 ucs = msg->Get_src();
175 fprintf( stderr, "<FAIL> expected pointer to src copy but got nil\n" );
179 i = msg->Get_available_size();
181 fprintf( stderr, "<FAIL> len expected payload avail size of 2048 but got %d\n", i );
185 i = msg->Get_mtype();
187 fprintf( stderr, "<FAIL> expected mtype of 100 but got %d\n", i );
191 i = msg->Get_state( );
193 fprintf( stderr, "<FAIL> expected state of 0 but got %d\n", i );
197 i = msg->Get_subid();
199 fprintf( stderr, "<FAIL> expected subid of -10 but got %d\n", i );
205 fprintf( stderr, "<FAIL> len expected 128 but got %d\n", i );
209 msg->Send(); // generic send as is functions
212 new_payload = (unsigned char *) malloc( sizeof( unsigned char ) * 2048 ); // a large payload
213 memset( new_payload, 0 , sizeof( unsigned char ) * 2048 );
214 new_p_ref = std::shared_ptr<unsigned char>( new_payload ); // reference it for send calls
216 msg->Set_meid( new_p_ref );
218 msg->Send_msg( 255, new_p_ref ); // send without changing the message type/subid from above
219 msg->Send_msg( 255, new_payload ); // drive the alternate prototype
220 msg->Send_msg( 100, 1, 128, new_p_ref ); // send using just 128 bytes of payload
221 msg->Send_msg( 100, 1, 128, new_payload ); // drive with alternate prototype
224 msg->Set_mtype( 100 );
225 msg->Set_subid( -10 );
227 msg->Send_response( 100, new_p_ref ); // send a response (rts) with establisehd message type etc
228 msg->Send_response( 100, new_payload );
229 msg->Send_response( 100, 10, 100, new_p_ref );
230 msg->Send_response( 100, 10, 100, new_payload );
233 msg = NULL; // should drive the message destroyer for coverage
235 msg = x->Receive( 2000 );
237 fprintf( stderr, "<FAIL> expected message from receive but got nil\n" );
241 tinfo = new std::thread; // start killer thread to terminate things so that run doesn't hang forever
242 tinfo = new std::thread( killer, x );
245 x->Halt(); // drive for coverage
247 if( err_cb1 + err_cb2 + err_cbd > 0 ) {
248 fprintf( stderr, "<FAIL> one or more callbacks reported an error: [%d] [%d] [%d]\n", err_cb1, err_cb2, err_cbd );
249 fprintf( stderr, "<INFO> callback good values: [%d] [%d] [%d]\n", good_cb1, good_cb2, good_cbd );
253 // ----- specific move/copy coverage drivers ---------------------------
255 xapp::Messenger m1( (char *) "1234", false ); // messenger class does NOT permit copies, so no need to test
256 xapp::Messenger m2( (char *) "9999", false );
257 m1 = std::move( m2 ); // drives move operator= function
258 xapp::Messenger m3 = std::move( m1 ); // drives move constructor function
260 std::unique_ptr<xapp::Message> msg2 = x->Alloc_msg( 2048 );
261 std::unique_ptr<xapp::Message> msg3 = x->Alloc_msg( 4096 );
263 snprintf( wbuf, sizeof( wbuf ), "Stand up and cheer!!" );
264 msg3->Set_len( strlen( wbuf ) );
265 strcpy( (char *) (msg3->Get_payload()).get(), wbuf ); // populate the payload to vet copy later
266 fprintf( stderr, "<DBUG> set string (%s) \n", (char *) (msg3->Get_payload()).get() );
268 xapp::Message msg4 = *(msg3.get()); // drive copy builder; msg4 should have a 4096 byte payload
269 fprintf( stderr, "<DBUG> copy string (%s) \n", (char *) (msg4.Get_payload()).get() ); // and payload should be coppied
270 if( msg4.Get_available_size() != 4096 ) {
272 fprintf( stderr, "<FAIL> message copy builder payload size smells: expected 4096, got %d\n", msg4.Get_available_size() );
274 if( strcmp( (char *) msg4.Get_payload().get(), wbuf ) != 0 ) {
276 fprintf( stderr, "<FAIL> message copy builder payload of copy not the expected string\n" );
279 snprintf( wbuf, sizeof( wbuf ), "Rambling Wreck; GT!" ); // different string into msg 2 to ensure copy replaced msg3 string
280 strcpy( (char *) (msg2->Get_payload()).get(), wbuf ); // populate the msg2 payload to vet copy
281 msg2->Set_len( strlen( wbuf ) );
282 *msg3 = *msg2; // drive the copy operator= function
283 if( msg3->Get_available_size() != 2048 ) {
285 fprintf( stderr, "<FAIL> message copy operator payload size smells: expected 2048, got %d\n", msg3->Get_available_size() );
287 if( strcmp( (char *) msg3->Get_payload().get(), wbuf ) != 0 ) {
289 fprintf( stderr, "<FAIL> message copy builder payload of copy not the expected string\n" );
292 xapp::Message msg5 = std::move( *(msg3.get()) ); // drive move constructor
293 if( msg5.Get_available_size() != 2048 ) {
295 fprintf( stderr, "<FAIL> message copy operator payload size smells: expected 2048, got %d\n", msg5.Get_available_size() );
297 if( strcmp( (char *) msg5.Get_payload().get(), wbuf ) != 0 ) {
299 fprintf( stderr, "<FAIL> message copy builder payload of copy not the expected string\n" );
302 msg5.Set_len( 2 ); // bogus len for vetting later
303 msg5 = std::move( *(msg3.get()) );
304 if( msg5.Get_len() == 21 ) {
306 fprintf( stderr, "<FAIL> message move operator payload len smells: expected 21, got %d\n", msg5.Get_len() );
309 // --------------------- alarm testing ------------------------------------------
310 std::shared_ptr<xapp::Alarm> a;
312 a = x->Alloc_alarm( ); // drive all possible constructors through the framework
313 errors += fail_if( a == NULL, "unable to allcoate a generic alarm" );
315 setenv( "ALARM_MGR_SERVICE_NAME", "alarm_svc", 1 );
316 setenv( "ALARM_MGR_SERVICE_PORT", "9999", 1 );
318 a = x->Alloc_alarm( "meid-123" );
319 errors += fail_if( a == NULL, "unable to allcoate an alarm with just meid" );
321 a = x->Alloc_alarm( 13, "meid-abc" );
322 errors += fail_if( a == NULL, "unable to allcoate an alarm with meid and problem id" );
325 //#####: 210:xapp::Alarm::Alarm( const Alarm& soi ) {
326 //#####: 227:Alarm& xapp::Alarm::operator=( const Alarm& soi ) {
327 //#####: 249:xapp::Alarm::Alarm( Alarm&& soi ) {
328 //#####: 269:Alarm& xapp::Alarm::operator=( Alarm&& soi ) {
330 a->Set_meid( "changed_meid" );
331 for( i = 0; i < 6; i++ ) {
332 a->Set_severity( i ); // drive all switch possibilities
335 a->Set_appid( "new-appid" );
336 a->Set_problem( 99 );
337 a->Set_info( "new information string" );
338 a->Set_additional( "new additional information string" );
341 errors += fail_if( !a->Raise(), "alarm raise with no parms failed" );
342 errors += fail_if( !a->Raise( xapp::Alarm::SEV_CRIT, 15, "problem string" ), "alarm raise s/p/i failed" );
343 errors += fail_if( !a->Raise( xapp::Alarm::SEV_CRIT, 15, "problem string", "addtl info" ), "alarm raise s/p/i/a failed" );
345 errors += fail_if( !a->Clear( ), "clear alarm failed" );
346 errors += fail_if( !a->Clear( xapp::Alarm::SEV_CRIT, 15, "problem string" ), "alarm clear s/p/i failed" );
347 errors += fail_if( !a->Clear( xapp::Alarm::SEV_CRIT, 15, "problem string", "addtl info" ), "alarm clear s/p/i/a failed" );
348 errors += fail_if( !a->Clear_all( ), "clear all failed" );
350 errors += fail_if( !a->Raise_again( ), "alarm raise again failed" );
352 xapp::Alarm b = *a.get(); // force the move/copy operator functions to trigger
353 xapp::Alarm c( NULL ); // a useless alarm without a message
354 xapp::Alarm f( NULL, "meid" ); // a useless alarm to drive direct construction
355 c = *a.get(); // drive copy = operator
357 b = std::move( c ); // move = operator
358 xapp::Alarm d = std::move( b ); // move constructor
360 announce_results( errors );