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: json_test.cpp
23 Abstract: Unit test for the json module. This expects that a static json
24 file exist in the current directory with a known set of fields,
25 arrays and objects that can be sussed out after parsing. The
26 expected file is test.json.
29 Author: E. Scott Daniels
44 Very simple file reader. Reads up to 8k into a single buffer and
45 returns the buffer as char*. Easier to put json test things in
48 static char* read_jstring( char* fname ) {
53 rbuf = (char *) malloc( sizeof( char ) * 8192 );
54 fd = open( fname, O_RDONLY, 0 );
56 fprintf( stderr, "<ABORT> can't open test file: %s: %s\n", fname, strerror( errno ) );
60 len = read( fd, rbuf, 8190 );
63 fprintf( stderr, "<ABORT> read from file failed: %s: %s\n", fname, strerror( errno ) );
73 // this also tests jwrapper.c but that is built as a special object to link in
74 // rather than including here.
76 #include "../src/json/jhash.hpp"
77 #include "../src/json/jhash.cpp"
79 #include "ut_support.cpp"
81 int main( int argc, char** argv ) {
92 set_test_name( "jhash_test" );
93 jstr = read_jstring( (char *) "test.json" ); // read and parse the json
95 fprintf( stderr, "read: (%s)\n", jstr );
97 jh = new Jhash( jstr );
100 fprintf( stderr, "<FAIL> could not parse json string from: test.json\n" );
105 sval = jh->String( (char *) "meeting_day" );
106 fprintf( stderr, "<INFO> sval=(%s)\n", sval.c_str() );
107 errors += fail_if( sval.compare( "" ) == 0, "did not get meeting day string" );
108 errors += fail_if( sval.compare( "Tuesday" ) != 0, "meeting day was not expected string" );
110 sval = jh->String( (char *) "meeting_place" );
111 fprintf( stderr, "<INFO> sval=(%s)\n", sval.c_str() );
112 errors += fail_if( sval.compare( "" ) == 0, "did not get meeting place" );
113 errors += fail_if( sval.compare( "16801 East Green Drive" ) != 0, "meeting place stirng was not correct" );
115 state = jh->Exists( (char *) "meeting_place" );
116 errors += fail_if( !state, "test for meeting place exists did not return true" );
118 state = jh->Exists( (char *) "no-name" );
119 errors += fail_if( state, "test for non-existant thing returned true" );
121 state = jh->Is_missing( (char *) "no-name" );
122 errors += fail_if( !state, "missing test for non-existant thing returned false" );
124 state = jh->Is_missing( (char *) "meeting_place" );
125 errors += fail_if( state, "missing test for existing thing returned true" );
127 val = jh->Value( (char *) "lodge_number" );
128 errors += fail_if( val != 41.0, "lodge number value was not correct" );
130 val = jh->Value( (char *) "monthly_dues" );
131 fprintf( stderr, "<INFO> got dues: %.2f\n", val );
132 errors += fail_if( val != (double) 43.5, "lodge dues value was not correct" );
134 len = jh->Array_len( (char *) "members" );
135 fprintf( stderr, "<INFO> got %d members\n", len );
136 errors += fail_if( len != 4, "array length was not correct" );
138 for( i = 0; i < len; i++ ) {
139 if( ! jh->Set_blob_ele( (char *) "members", i ) ) {
141 fprintf( stderr, (char *) "couldn't set blob for element %d\n", i );
143 fprintf( stderr, (char *) "<INFO> testing element %d of %d\n", i, len );
145 state = jh->Is_value( (char *) "age" );
146 errors += fail_if( !state, "is value test for age returned false" );
147 state = jh->Is_value( (char *) "married" );
148 errors += fail_if( state, "is value test for married returned true" );
150 state = jh->Is_string( (char *) "occupation" );
151 errors += fail_if( !state, "is string test for spouse returned false" );
152 state = jh->Is_string( (char *) "married" );
153 errors += fail_if( state, "is string test for married returned true" );
155 state = jh->Is_bool( (char *) "married" );
156 errors += fail_if( !state, "is bool test for married returned false" );
157 state = jh->Is_bool( (char *) "occupation" );
158 errors += fail_if( state, "is bool test for spouse returned true" );
160 val = jh->Value( (char *) "age" );
161 fprintf( stderr, "<INFO> got age: %.2f\n", (double) val );
162 errors += fail_if( val < 0, "age value wasn't positive" );
164 sval = jh->String( (char *) "name" );
165 fprintf( stderr, "<INFO> sval=(%s)\n", sval.c_str() );
166 errors += fail_if( sval.compare( "" ) == 0, "no name found in element" );
168 if( jh->Bool( (char *) "married" ) ) {
173 jh->Unset_blob(); // must return to root
176 fprintf( stderr, "<INFO> true count = %d\n", true_count );
177 errors += fail_if( true_count != 3, "married == true count was not right" );
180 state = jh->Set_blob( (char *) "no-such-thing" );
181 errors += fail_if( state, "setting blob to non-existant blob returned true" );
183 state = jh->Set_blob( (char *) "grand_poobah" );
184 errors += fail_if( !state, "setting blob to existing blob failed" );
186 sval = jh->String( (char *) "elected" );
187 fprintf( stderr, "<INFO> sval=(%s)\n", sval.c_str() );
188 errors += fail_if( sval != "February 2019", "blob 'elected' didn't return the expected string" );
190 state = jh->Exists( (char *) "monthly_dues" );
191 errors += fail_if( state, "blob that shouldn't have a field reports it does" );
193 jh->Unset_blob( ); // ensure that this is found once we unset to root
194 state = jh->Exists( (char *) "monthly_dues" );
195 errors += fail_if( !state, "after rest, root blob, that should have a field, reports it does not" );
199 // ---- test array element value type checks -------------------------------------------------
200 state = jh->Is_string_ele( (char *) "sponser", 1 );
201 errors += fail_if( !state, "string element check on sponser failed" );
202 state = jh->Is_string_ele( (char *) "current_on_dues", 1 );
203 errors += fail_if( state, "string element check on non-stirng element returned true" );
205 state = jh->Is_value_ele( (char *) "dues_assistance", 1 );
206 errors += fail_if( !state, "string element check on sponser failed" );
207 state = jh->Is_value_ele( (char *) "current_on_dues", 1 );
208 errors += fail_if( state, "string element check on non-stirng element returned true" );
210 state = jh->Is_bool_ele( (char *) "current_on_dues", 1 );
211 errors += fail_if( !state, "string element check on sponser failed" );
212 state = jh->Is_bool_ele( (char *) "sponser", 1 );
213 errors += fail_if( state, "string element check on non-stirng element returned true" );
215 state = jh->Is_null( (char *) "nvt" );
216 errors += fail_if( !state, "test for nil value returned false" );
217 state = jh->Is_null( (char *) "lodge_number" );
218 errors += fail_if( state, "nil test for non-nil value returned true" );
220 state = jh->Is_null_ele( (char *) "nvat", 0 );
221 errors += fail_if( !state, "test for nil array element value returned false" );
224 // ---- test sussing of elements from arrays -------------------------------------------------
225 sval = jh->String_ele( (char *) "sponser", 1 );
226 errors += fail_if( sval.compare( "" ) == 0, "get string element failed for sponser" );
228 val = jh->Value_ele( (char *) "dues_assistance", 1 );
229 errors += fail_if( val == 0.0, "get value element for dues_assistance was zero" );
231 state = jh->Bool_ele( (char *) "current_on_dues", 1 );
232 errors += fail_if( state, "bool ele test returned true for a false value" );
233 state = jh->Bool_ele( (char *) "current_on_dues", 0 );
234 errors += fail_if( !state, "bool ele test returned false for a true value" );
237 val = jh->Value( (char *) "timestamp" );
238 fprintf( stderr, "<INFO> timestamp: %.10f\n", val );
246 fprintf( stderr, "<INFO> testing for failures; jwrapper error and warning messages expected\n" );
247 // ---- these shouild all fail to parse, generate warnings to stderr, and drive error handling coverage ----
248 jh = new Jhash( (char *) "{ \"bad\": [ [ 1, 2, 3 ], [ 3, 4, 5]] }" ); // drive the exception process for bad json
251 jh = new Jhash( (char *) " \"bad\": 5 }" ); // no opening brace
252 state = jh->Parse_errors();
253 errors += fail_if( !state, "parse errors check returned false when known errors exist" );
256 jh = new Jhash( (char *) "{ \"bad\": fred }" ); // no quotes
259 jh = new Jhash( (char *) "{ \"bad: 456, \"good\": 100 }" ); // missing quote; impossible to detect error
260 jh->Dump(); // but dump should provide details
261 fprintf( stderr, "<INFO> good value=%d\n", (int) val );
265 // ---------------------------- end housekeeping ---------------------------
266 announce_results( errors );