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/metrics/metrics.hpp"
44 #include "../src/xapp/xapp.hpp"
46 #include "../src/messaging/callback.cpp"
47 #include "../src/messaging/default_cb.cpp"
48 #include "../src/messaging/message.cpp"
49 #include "../src/messaging/messenger.cpp"
50 #include "../src/alarm/alarm.cpp"
51 #include "../src/xapp/xapp.cpp"
53 #include "ut_support.cpp"
55 // ---------------------------------------------------------------------------------------------
57 callback error counts are global for ease. They track the number of times each callback
58 was invoked with the expected message type(s) and any times they were not.
69 callback functions to register; driven as we "receive" messages (the RMR emulation package
70 will generate a message every time the receive function is called).
72 void cb1( xapp::Message& mbuf, int mtype, int subid, int len, xapp::Msg_component payload, void* data ) {
73 if( mtype != 1 ) { // should only be driven for type 1 messages
79 void cb2( xapp::Message& mbuf, int mtype, int subid, int len, xapp::Msg_component payload, void* data ) {
80 if( mtype != 2 ) { // should only be driven for type 2 messages
86 void cbd( xapp::Message& mbuf, int mtype, int subid, int len, xapp::Msg_component payload, void* data ) {
87 if( mtype > 0 && mtype < 3 ) { // should only be driven for types that arent 1 or 2
89 fprintf( stderr, "<FAIL> cbd: bad message type: %d\n", mtype );
98 The Xapp Run() function only returns when Xapp is asked to stop, and that
99 isn't supported from inside any of the callbacks. This funciton is
100 started in a thread and after a few seconds it will drive the halt
101 function in the Xapp instance to stop the run function and allow the
104 void killer( std::shared_ptr<Xapp> x ) {
105 fprintf( stderr, "<INFO> killer is waiting in the shadows\n" );
107 fprintf( stderr, "<INFO> killer is on the loose\n" );
112 Drive the constructors so that we actually see the coverage
113 in the .gc* files. The metrics tests will actually verify that
114 the various underlying functions work.
116 static int metrics( std::shared_ptr<Xapp> x ) {
117 std::shared_ptr<xapp::Metrics> m;
119 m = x->Alloc_metrics( ); // basic construction
120 m = x->Alloc_metrics( "different-source" ); // drive alternate builders
121 m = x->Alloc_metrics( "different-app", "different-source" );
124 int main( int argc, char** argv ) {
125 std::thread* tinfo; // we'll start a thread that will shut things down after a few seconds
126 std::unique_ptr<xapp::Message> msg;
127 std::shared_ptr<Xapp> x;
128 xapp::Msg_component payload;
129 std::unique_ptr<unsigned char> ucs;
130 unsigned char* new_payload;
131 std::shared_ptr<unsigned char> new_p_ref; // reference to payload to pass to send functions
132 char* port = (char *) "4560";
133 int ai = 1; // arg processing index
134 int nthreads = 2; // ensure the for loop is executed in setup
141 while( ai < argc ) { // very simple flag processing (no bounds/error checking)
142 if( argv[ai][0] != '-' ) {
146 switch( argv[ai][1] ) { // we only support -x so -xy must be -x -y
153 nthreads = atoi( argv[ai+1] );
161 set_test_name( "unit_test" );
163 // ------------------- generic xapp tests ----------------------------------------------
164 x = std::shared_ptr<Xapp>( new Xapp( port, true ) );
165 x->Add_msg_cb( 1, cb1, NULL );
166 x->Add_msg_cb( 2, cb2, NULL );
167 x->Add_msg_cb( -1, cbd, NULL );
169 msg = x->Alloc_msg( 2048 );
170 payload = msg->Get_payload();
172 msg->Set_mtype( 100 );
173 msg->Set_subid( -10 );
175 ucs = msg->Copy_payload( );
177 fprintf( stderr, "<FAIL> expected pointer to copy payload but got nil\n" );
181 ucs = msg->Get_meid();
183 fprintf( stderr, "<FAIL> expected pointer to meid copy but got nil\n" );
187 ucs = msg->Get_src();
189 fprintf( stderr, "<FAIL> expected pointer to src copy but got nil\n" );
193 i = msg->Get_available_size();
195 fprintf( stderr, "<FAIL> len expected payload avail size of 2048 but got %d\n", i );
199 i = msg->Get_mtype();
201 fprintf( stderr, "<FAIL> expected mtype of 100 but got %d\n", i );
205 i = msg->Get_state( );
207 fprintf( stderr, "<FAIL> expected state of 0 but got %d\n", i );
211 i = msg->Get_subid();
213 fprintf( stderr, "<FAIL> expected subid of -10 but got %d\n", i );
219 fprintf( stderr, "<FAIL> len expected 128 but got %d\n", i );
223 msg->Send(); // generic send as is functions
226 new_payload = (unsigned char *) malloc( sizeof( unsigned char ) * 2048 ); // a large payload
227 memset( new_payload, 0 , sizeof( unsigned char ) * 2048 );
228 new_p_ref = std::shared_ptr<unsigned char>( new_payload ); // reference it for send calls
230 msg->Set_meid( new_p_ref );
232 msg->Send_msg( 255, new_p_ref ); // send without changing the message type/subid from above
233 msg->Send_msg( 255, new_payload ); // drive the alternate prototype
234 msg->Send_msg( 100, 1, 128, new_p_ref ); // send using just 128 bytes of payload
235 msg->Send_msg( 100, 1, 128, new_payload ); // drive with alternate prototype
238 msg->Set_mtype( 100 );
239 msg->Set_subid( -10 );
241 msg->Send_response( 100, new_p_ref ); // send a response (rts) with establisehd message type etc
242 msg->Send_response( 100, new_payload );
243 msg->Send_response( 100, 10, 100, new_p_ref );
244 msg->Send_response( 100, 10, 100, new_payload );
247 msg = NULL; // should drive the message destroyer for coverage
249 msg = x->Receive( 2000 );
251 fprintf( stderr, "<FAIL> expected message from receive but got nil\n" );
255 tinfo = new std::thread; // start killer thread to terminate things so that run doesn't hang forever
256 tinfo = new std::thread( killer, x );
259 x->Halt(); // drive for coverage
261 if( err_cb1 + err_cb2 + err_cbd > 0 ) {
262 fprintf( stderr, "<FAIL> one or more callbacks reported an error: [%d] [%d] [%d]\n", err_cb1, err_cb2, err_cbd );
263 fprintf( stderr, "<INFO> callback good values: [%d] [%d] [%d]\n", good_cb1, good_cb2, good_cbd );
267 // ----- specific move/copy coverage drivers ---------------------------
269 xapp::Messenger m1( (char *) "1234", false ); // messenger class does NOT permit copies, so no need to test
270 xapp::Messenger m2( (char *) "9999", false );
271 m1 = std::move( m2 ); // drives move operator= function
272 xapp::Messenger m3 = std::move( m1 ); // drives move constructor function
274 std::unique_ptr<xapp::Message> msg2 = x->Alloc_msg( 2048 );
275 std::unique_ptr<xapp::Message> msg3 = x->Alloc_msg( 4096 );
277 snprintf( wbuf, sizeof( wbuf ), "Stand up and cheer!!" );
278 msg3->Set_len( strlen( wbuf ) );
279 strcpy( (char *) (msg3->Get_payload()).get(), wbuf ); // populate the payload to vet copy later
280 fprintf( stderr, "<DBUG> set string (%s) \n", (char *) (msg3->Get_payload()).get() );
282 xapp::Message msg4 = *(msg3.get()); // drive copy builder; msg4 should have a 4096 byte payload
283 fprintf( stderr, "<DBUG> copy string (%s) \n", (char *) (msg4.Get_payload()).get() ); // and payload should be coppied
284 if( msg4.Get_available_size() != 4096 ) {
286 fprintf( stderr, "<FAIL> message copy builder payload size smells: expected 4096, got %d\n", msg4.Get_available_size() );
288 if( strcmp( (char *) msg4.Get_payload().get(), wbuf ) != 0 ) {
290 fprintf( stderr, "<FAIL> message copy builder payload of copy not the expected string\n" );
293 snprintf( wbuf, sizeof( wbuf ), "Rambling Wreck; GT!" ); // different string into msg 2 to ensure copy replaced msg3 string
294 strcpy( (char *) (msg2->Get_payload()).get(), wbuf ); // populate the msg2 payload to vet copy
295 msg2->Set_len( strlen( wbuf ) );
296 *msg3 = *msg2; // drive the copy operator= function
297 if( msg3->Get_available_size() != 2048 ) {
299 fprintf( stderr, "<FAIL> message copy operator payload size smells: expected 2048, got %d\n", msg3->Get_available_size() );
301 if( strcmp( (char *) msg3->Get_payload().get(), wbuf ) != 0 ) {
303 fprintf( stderr, "<FAIL> message copy builder payload of copy not the expected string\n" );
306 xapp::Message msg5 = std::move( *(msg3.get()) ); // drive move constructor
307 if( msg5.Get_available_size() != 2048 ) {
309 fprintf( stderr, "<FAIL> message copy operator payload size smells: expected 2048, got %d\n", msg5.Get_available_size() );
311 if( strcmp( (char *) msg5.Get_payload().get(), wbuf ) != 0 ) {
313 fprintf( stderr, "<FAIL> message copy builder payload of copy not the expected string\n" );
316 msg5.Set_len( 2 ); // bogus len for vetting later
317 msg5 = std::move( *(msg3.get()) );
318 if( msg5.Get_len() == 21 ) {
320 fprintf( stderr, "<FAIL> message move operator payload len smells: expected 21, got %d\n", msg5.Get_len() );
323 // --------------------- alarm testing ------------------------------------------
324 std::shared_ptr<xapp::Alarm> a;
326 a = x->Alloc_alarm( ); // drive all possible constructors through the framework
327 errors += fail_if( a == NULL, "unable to allcoate a generic alarm" );
329 setenv( "ALARM_MGR_SERVICE_NAME", "alarm_svc", 1 );
330 setenv( "ALARM_MGR_SERVICE_PORT", "9999", 1 );
332 a = x->Alloc_alarm( "meid-123" );
333 errors += fail_if( a == NULL, "unable to allcoate an alarm with just meid" );
335 a = x->Alloc_alarm( 13, "meid-abc" );
336 errors += fail_if( a == NULL, "unable to allcoate an alarm with meid and problem id" );
338 a->Set_meid( "changed_meid" );
339 for( i = 0; i < 6; i++ ) {
340 a->Set_severity( i ); // drive all switch possibilities
343 a->Set_appid( "new-appid" );
344 a->Set_problem( 99 );
345 a->Set_info( "new information string" );
346 a->Set_additional( "new additional information string" );
349 errors += fail_if( !a->Raise(), "alarm raise with no parms failed" );
350 errors += fail_if( !a->Raise( xapp::Alarm::SEV_CRIT, 15, "problem string" ), "alarm raise s/p/i failed" );
351 errors += fail_if( !a->Raise( xapp::Alarm::SEV_CRIT, 15, "problem string", "addtl info" ), "alarm raise s/p/i/a failed" );
353 errors += fail_if( !a->Clear( ), "clear alarm failed" );
354 errors += fail_if( !a->Clear( xapp::Alarm::SEV_CRIT, 15, "problem string" ), "alarm clear s/p/i failed" );
355 errors += fail_if( !a->Clear( xapp::Alarm::SEV_CRIT, 15, "problem string", "addtl info" ), "alarm clear s/p/i/a failed" );
356 errors += fail_if( !a->Clear_all( ), "clear all failed" );
358 errors += fail_if( !a->Raise_again( ), "alarm raise again failed" );
360 xapp::Alarm b = *a.get(); // force the move/copy operator functions to trigger
361 xapp::Alarm c( NULL ); // a useless alarm without a message
362 xapp::Alarm f( NULL, "meid" ); // a useless alarm to drive direct construction
363 c = *a.get(); // drive copy = operator
365 b = std::move( c ); // move = operator
366 xapp::Alarm d = std::move( b ); // move constructor
368 // ------ minimal metrics to prove coverage ------------------------------------------------------------
371 // ------------------------------------------------------------------------------------------------------
373 announce_results( errors );