Add unit tests and changes related
[ric-plt/xapp-frame-cpp.git] / test / unit_test.cpp
1 // vim: ts=4 sw=4 noet :
2 /*
3 ==================================================================================
4        Copyright (c) 2020 Nokia
5        Copyright (c) 2020 AT&T Intellectual Property.
6
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
10
11        http://www.apache.org/licenses/LICENSE-2.0
12
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 ==================================================================================
19 */
20
21 /*
22         Mnemonic:       Unit_test.cpp
23         Abstract:       This is the unit test driver for the C++ xAPP framework
24
25         Date:           20 March 2020
26         Author:         E. Scott Daniels
27 */
28
29 #include <memory>
30
31
32 #include "../src/messaging/callback.hpp"
33 #include "../src/messaging/default_cb.hpp"
34 #include "../src/messaging/message.hpp"
35 #include "../src/messaging/messenger.hpp"
36 #include "../src/messaging/msg_component.hpp"
37 #include "../src/xapp/xapp.hpp"
38
39 #include "../src/messaging/callback.cpp"
40 #include "../src/messaging/default_cb.cpp"
41 #include "../src/messaging/message.cpp"
42 #include "../src/messaging/messenger.cpp"
43 #include "../src/xapp/xapp.cpp"
44
45 // callback error counts are global for ease
46 int err_cb1 = 0;
47 int err_cb2 = 0;
48 int err_cbd = 0;
49
50 int good_cb1 = 0;
51 int good_cb2 = 0;
52 int good_cbd = 0;
53
54 /*
55         callback functions to register; driven as we "receive" messages (the RMR emulation package 
56         will generate a message every time the receive function is called).
57 */
58 void cb1( Message& mbuf, int mtype, int subid, int len, Msg_component payload,  void* data ) {
59         if( mtype != 1 ) {      // should only be driven for type 1 messages
60                 err_cb1++;
61         } else {
62                 good_cb1++;
63         }
64 }
65 void cb2( Message& mbuf, int mtype, int subid, int len, Msg_component payload,  void* data ) {
66         if( mtype != 2 ) {      // should only be driven for type 2 messages
67                 err_cb2++;
68         } else {
69                 good_cb2++;
70         }
71 }
72 void cbd( Message& mbuf, int mtype, int subid, int len, Msg_component payload,  void* data ) {
73         if( mtype > 0 && mtype < 3 ) {                          // should only be driven for types that arent 1 or 2 
74                 if( err_cbd < 10 ) {
75                         fprintf( stderr, "<FAIL> cbd: bad message type: %d\n", mtype );
76                 }
77                 err_cbd++;
78         } else {
79                 good_cbd++;
80         }
81 }
82
83 void killer( std::shared_ptr<Xapp> x ) {
84         fprintf( stderr, ">>>> killer is waiting in the shadows\n" );
85         sleep( 5 );
86         fprintf( stderr, ">>>> killer is on the loose\n" );
87         x->Halt();
88 }
89
90 int main( int argc, char** argv ) {
91         std::thread* tinfo;                                     // we'll start a thread that will shut things down after a few seconds
92         std::unique_ptr<Message> msg;
93         std::shared_ptr<Xapp> x;
94         Msg_component payload;
95         std::unique_ptr<unsigned char> ucs;
96         unsigned char* new_payload;
97         std::shared_ptr<unsigned char> new_p_ref;       // reference to payload to pass to send functions
98         char*   port = (char *) "4560";
99         int             ai = 1;                                                 // arg processing index
100         int             nthreads = 2;                                   // ensure the for loop is executed in setup
101         int             i;
102         int             errors = 0;
103
104         ai = 1;
105         while( ai < argc ) {                            // very simple flag processing (no bounds/error checking)
106                 if( argv[ai][0] != '-' )  {
107                         break;
108                 }
109
110                 switch( argv[ai][1] ) {                 // we only support -x so -xy must be -x -y
111                         case 'p': 
112                                 port = argv[ai+1];      
113                                 ai++;
114                                 break;
115
116                         case 't':
117                                 nthreads = atoi( argv[ai+1] );
118                                 ai++;
119                                 break;
120                 }
121
122                 ai++;
123         }
124         
125         x = std::shared_ptr<Xapp>( new Xapp( port, true ) );
126         x->Add_msg_cb( 1, cb1, NULL );
127         x->Add_msg_cb( 2, cb2, NULL );
128         x->Add_msg_cb( -1, cbd, NULL );
129
130         msg = x->Alloc_msg( 2048 );
131         payload = msg->Get_payload();
132         msg->Set_len( 128 );
133         msg->Set_mtype( 100 );
134         msg->Set_subid( -10 );
135
136         ucs = msg->Copy_payload( );
137         if( ucs == NULL ) {
138                 fprintf( stderr, "<FAIL> expected pointer to copy payload but got nil\n" );
139                 errors++;
140         }
141
142         ucs = msg->Get_meid();
143         if( ucs == NULL ) {
144                 fprintf( stderr, "<FAIL> expected pointer to meid copy but got nil\n" );
145                 errors++;
146         }
147
148         ucs = msg->Get_src();
149         if( ucs == NULL ) {
150                 fprintf( stderr, "<FAIL> expected pointer to src copy but got nil\n" );
151                 errors++;
152         }
153
154         i = msg->Get_available_size();
155         if( i != 2048 ) {
156                 fprintf( stderr, "<FAIL> len expected payload avail size of 2048 but got %d\n", i );
157                 errors++;
158         }
159
160         i = msg->Get_mtype();
161         if( i != 100 ) {
162                 fprintf( stderr, "<FAIL> expected mtype of 100 but got %d\n", i );
163                 errors++;
164         }
165
166         i = msg->Get_state( );
167         if( i != 0 ) {
168                 fprintf( stderr, "<FAIL> expected state of 0 but got %d\n", i );
169                 errors++;
170         }
171
172         i = msg->Get_subid();
173         if( i != -10 ) {
174                 fprintf( stderr, "<FAIL> expected subid of -10 but got %d\n", i );
175                 errors++;
176         }
177
178         i = msg->Get_len();
179         if( i != 128 ) {
180                 fprintf( stderr, "<FAIL> len expected 128 but got %d\n", i );
181                 errors++;
182         }
183
184         msg->Send();                            // generic send as is functions
185         msg->Reply();
186
187         new_payload = (unsigned char *) malloc( sizeof( unsigned char ) * 2048 );       // a large payload
188         memset( new_payload, 0 , sizeof( unsigned char ) * 2048 );
189         new_p_ref = std::shared_ptr<unsigned char>( new_payload );                                      // reference it for send calls
190
191         msg->Set_meid( new_p_ref );
192
193         msg->Send_msg( 255, new_p_ref );                                                                                        // send without changing the message type/subid from above
194         msg->Send_msg( 255, new_payload );                                                                                      // drive the alternate prototype
195         msg->Send_msg( 100, 1, 128, new_p_ref );                                                                        // send using just 128 bytes of payload
196         msg->Send_msg( 100, 1, 128, new_payload );                                                                      // drive with alternate prototype
197
198         msg->Set_len( 128 );
199         msg->Set_mtype( 100 );
200         msg->Set_subid( -10 );
201
202         msg->Send_response( 100, new_p_ref );                                                                           // send a response (rts) with establisehd message type etc
203         msg->Send_response( 100, new_payload );
204         msg->Send_response( 100, 10, 100, new_p_ref );
205         msg->Send_response( 100, 10, 100, new_payload );
206
207
208         msg = NULL;                                                             // should drive the message destroyer for coverage
209
210         msg = x->Receive( 2000 );
211         if( msg == NULL ) {
212                 fprintf( stderr, "<FAIL> expected message from receive but got nil\n" );
213                 errors++;
214         }
215
216         tinfo = new std::thread;                                // start killer thread to terminate things so that run doesn't hang forever
217         tinfo = new std::thread( killer, x );
218
219         x->Run( nthreads );
220         x->Halt();                      // drive for coverage
221
222         if( err_cb1 + err_cb2 + err_cbd > 0 ) {
223                 fprintf( stderr, "<FAIL> one or more callbacks reported an error:  [%d] [%d] [%d]\n", err_cb1, err_cb2, err_cbd );
224                 fprintf( stderr, "<INFO> callback good values:  [%d] [%d] [%d]\n", good_cb1, good_cb2, good_cbd );
225                 errors++;
226         }
227
228         return errors > 0;
229 }