blob: 316a2b392a4b124cd72077bd9cbf188d87918bdf [file] [log] [blame]
Rich Lanea06d0c32013-03-25 08:52:03 -07001# Copyright 2013, Big Switch Networks, Inc.
2#
3# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
4# the following special exception:
5#
6# LOXI Exception
7#
8# As a special exception to the terms of the EPL, you may distribute libraries
9# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
10# that copyright and licensing notices generated by LoxiGen are not altered or removed
11# from the LoxiGen Libraries and the notice provided below is (i) included in
12# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
13# documentation for the LoxiGen Libraries, if distributed in binary form.
14#
15# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
16#
17# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
18# a copy of the EPL at:
19#
20# http://www.eclipse.org/legal/epl-v10.html
21#
22# Unless required by applicable law or agreed to in writing, software
23# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
24# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
25# EPL for the specific language governing permissions and limitations
26# under the EPL.
27
28"""
29@brief Test case generation functions
30
31@fixme Update the following
32The following components are generated.
33
34test_common.[ch]: A collection of common code for tests. Currently
35this includes the ability to set the scalar members of an object with
36incrementing values and then similarly verify those values
37
38test_scalar_acc.c: Instantiate each type of object, then set and get
39scalar values in the objects.
40
41test_list.c: Instantiate each type of list, add an element of each
42type the list supports, setting scalar values of the elements.
43
44test_match.c: Various tests for match objects
45
46test_msg.c: Instantiate top level messages
47
48These will move towards unified tests that do the following:
49
50Create or init an object.
51Populate the object with incrementing values.
52Possibly transform the object in some way (e.g., run the underlying
53wire buffer through a parse routine).
54Verify that the members all have the appropriate value
55
56Through out, checking the consistency of memory and memory operations
YAMAMOTO Takashi071b5912013-07-02 08:37:39 +090057is done with mcheck (if available).
Rich Lanea06d0c32013-03-25 08:52:03 -070058
59"""
60
61import sys
Andreas Wundsam76db0062013-11-15 13:34:41 -080062import c_gen.of_g_legacy as of_g
Andreas Wundsam542a13c2013-11-15 13:28:55 -080063import c_gen.match as match
64import c_gen.flags as flags
Rich Lanea06d0c32013-03-25 08:52:03 -070065from generic_utils import *
Andreas Wundsam542a13c2013-11-15 13:28:55 -080066import c_gen.type_maps as type_maps
67import c_gen.loxi_utils_legacy as loxi_utils
68import c_gen.identifiers as identifiers
Rich Laneccae0312013-07-21 23:34:13 -070069import util
70import test_data
Rich Lane79c87192014-03-04 10:56:59 -080071import loxi_globals
72from loxi_ir import *
Rich Lanea06d0c32013-03-25 08:52:03 -070073
74def var_name_map(m_type):
75 """
76 Map a type to a generic variable name for the type.
77 @param m_type The data type
78
79 Used mostly in test code generation, but also for the dup functions.
80 """
81 _var_name_map= dict(
82 uint8_t="val8",
83 uint16_t="val16",
84 uint32_t="val32",
85 uint64_t="val64",
Andreas Wundsamb566a162013-07-18 19:30:23 -070086 of_ipv4_t="ipv4",
Rich Lanea06d0c32013-03-25 08:52:03 -070087 of_port_no_t="port_no",
88 of_fm_cmd_t="fm_cmd",
89 of_wc_bmap_t="wc_bmap",
90 of_match_bmap_t = "match_bmap",
Andreas Wundsam53256162013-05-02 14:05:53 -070091 of_port_name_t="port_name",
Rich Lanea06d0c32013-03-25 08:52:03 -070092 of_table_name_t="table_name",
93 of_desc_str_t="desc_str",
Andreas Wundsam53256162013-05-02 14:05:53 -070094 of_serial_num_t="ser_num",
95 of_mac_addr_t="mac_addr",
Rich Lanea06d0c32013-03-25 08:52:03 -070096 of_ipv6_t="ipv6",
97 # Non-scalars; more TBD
98 of_octets_t="octets",
99 of_meter_features_t="features",
Dan Talaycoc0e802e2013-05-18 23:52:39 -0700100 of_match_t="match",
101 # BSN extensions
102 of_bsn_vport_q_in_q_t="vport",
Rich Lane3b2fd832013-09-24 13:44:08 -0700103 of_bitmap_128_t="bitmap_128",
Rich Lanefab0c822013-12-30 11:46:48 -0800104 of_checksum_128_t="checksum_128",
Dan Talaycoc0e802e2013-05-18 23:52:39 -0700105 )
Rich Lanea06d0c32013-03-25 08:52:03 -0700106
107 if m_type.find("of_list_") == 0:
108 return "list"
109 if m_type in of_g.of_mixed_types:
110 return of_g.of_mixed_types[m_type]["short_name"]
111 return _var_name_map[m_type]
112
113integer_types = ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
114 "of_port_no_t", "of_fm_cmd_t", "of_wc_bmap_t",
Andreas Wundsamb566a162013-07-18 19:30:23 -0700115 "of_match_bmap_t", "of_ipv4_t"]
Rich Lanea06d0c32013-03-25 08:52:03 -0700116string_types = [ "of_port_name_t", "of_table_name_t",
Andreas Wundsam53256162013-05-02 14:05:53 -0700117 "of_desc_str_t", "of_serial_num_t", "of_mac_addr_t",
Rich Lanefab0c822013-12-30 11:46:48 -0800118 "of_ipv6_t", "of_bitmap_128_t", "of_checksum_128_t"]
Rich Lanea06d0c32013-03-25 08:52:03 -0700119
120scalar_types = integer_types[:]
121scalar_types.extend(string_types)
122
123def ignore_member(cls, version, m_name, m_type):
124 """
125 Filter out names or types that either don't have accessors
126 or those that should not be messed with
127 or whose types we're not ready to deal with yet.
128 """
Rich Lane79c87192014-03-04 10:56:59 -0800129
130 uclass = loxi_globals.unified.class_by_name(cls)
131 if not uclass:
Rich Lanea06d0c32013-03-25 08:52:03 -0700132 return True
Rich Lane353a79f2013-11-13 10:39:56 -0800133
Rich Lane79c87192014-03-04 10:56:59 -0800134 if not isinstance(uclass.member_by_name(m_name), OFDataMember):
Rich Lane353a79f2013-11-13 10:39:56 -0800135 return True
Rich Lane79c87192014-03-04 10:56:59 -0800136
Rich Lanea06d0c32013-03-25 08:52:03 -0700137 return loxi_utils.skip_member_name(m_name) or m_type not in scalar_types
138
139def gen_fill_string(out):
140 out.write("""
141
142/**
143 * The increment to use on values inside a string
144 */
145#define OF_TEST_STR_INCR 3
146
147/**
148 * Fill in a buffer with incrementing values starting
149 * at the given offset with the given value
150 * @param buf The buffer to fill
151 * @param value The value to use for data
152 * @param len The number of bytes to fill
153 */
154
155void
156of_test_str_fill(uint8_t *buf, int value, int len)
157{
158 int i;
159
160 for (i = 0; i < len; i++) {
161 *buf = value;
162 value += OF_TEST_STR_INCR;
163 buf++;
164 }
165}
166
167/**
168 * Given a buffer, verify that it's filled as above
169 * @param buf The buffer to check
170 * @param value The value to use for data
171 * @param len The number of bytes to fill
172 * @return Boolean True on equality (success)
173 */
174
175int
176of_test_str_check(uint8_t *buf, int value, int len)
177{
178 int i;
179 uint8_t val8;
180
181 val8 = value;
182
183 for (i = 0; i < len; i++) {
184 if (*buf != val8) {
185 return 0;
186 }
187 val8 += OF_TEST_STR_INCR;
188 buf++;
189 }
190
191 return 1;
192}
193
194/**
195 * Global that determines how octets should be populated
196 * -1 means use value % MAX (below) to determine length
197 * 0, 1, ... means used that fixed length
198 *
199 * Note: Was 16K, but that made objects too big. May add flexibility
200 * to call populate with a max parameter for length
201 */
202int octets_pop_style = -1;
203#define OCTETS_MAX_VALUE (128) /* 16K was too big */
204#define OCTETS_MULTIPLIER 6367 /* A prime */
205
206int
207of_octets_populate(of_octets_t *octets, int value)
208{
209 if (octets_pop_style < 0) {
210 octets->bytes = (value * OCTETS_MULTIPLIER) % OCTETS_MAX_VALUE;
211 } else {
212 octets->bytes = octets_pop_style;
213 }
214
215 if (octets->bytes != 0) {
216 if ((octets->data = (uint8_t *)MALLOC(octets->bytes)) == NULL) {
217 return 0;
218 }
219 of_test_str_fill(octets->data, value, octets->bytes);
220 value += 1;
221 }
222
223 return value;
224}
225
226int
227of_octets_check(of_octets_t *octets, int value)
228{
229 int len;
230
231 if (octets_pop_style < 0) {
232 len = (value * OCTETS_MULTIPLIER) % OCTETS_MAX_VALUE;
233 TEST_ASSERT(octets->bytes == len);
234 } else {
235 TEST_ASSERT(octets->bytes == octets_pop_style);
236 }
237
238 if (octets->bytes != 0) {
239 TEST_ASSERT(of_test_str_check(octets->data, value, octets->bytes)
240 == 1);
241 value += 1;
242 }
243
244 return value;
245}
246
247int
248of_match_populate(of_match_t *match, of_version_t version, int value)
249{
250 MEMSET(match, 0, sizeof(*match));
251 match->version = version;
252""")
253
254 for key, entry in match.of_match_members.items():
255 out.write("""
Andreas Wundsam53256162013-05-02 14:05:53 -0700256 if (!(of_match_incompat[version] &
Rich Lanea06d0c32013-03-25 08:52:03 -0700257 OF_OXM_BIT(OF_OXM_INDEX_%(ku)s))) {
258 OF_MATCH_MASK_%(ku)s_EXACT_SET(match);
259 VAR_%(u_type)s_INIT(match->fields.%(key)s, value);
260 value += 1;
261 }
262
263""" % dict(key=key, u_type=entry["m_type"].upper(), ku=key.upper()))
264
265 out.write("""
266 if (value % 2) {
267 /* Sometimes set ipv4 addr masks to non-exact */
268 match->masks.ipv4_src = 0xffff0000;
269 match->masks.ipv4_dst = 0xfffff800;
270 }
Dan Talaycofb50d382013-08-05 16:00:17 -0700271
272 /* Restrict values according to masks */
273 of_match_values_mask(match);
Rich Lanea06d0c32013-03-25 08:52:03 -0700274 return value;
275}
276
277int
278of_match_check(of_match_t *match, of_version_t version, int value)
279{
280 of_match_t check;
281
282 value = of_match_populate(&check, match->version, value);
283 TEST_ASSERT(value != 0);
284 TEST_ASSERT(MEMCMP(match, &check, sizeof(check)) == 0);
285
286 return value;
287}
288""")
289
290def gen_common_test_header(out, name):
291 loxi_utils.gen_c_copy_license(out)
292 out.write("""
293/*
294 * Test header file
295 *
296 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
297 */
298
299#if !defined(_TEST_COMMON_H_)
300#define _TEST_COMMON_H_
301
302#define DISABLE_WARN_UNUSED_RESULT
303#include <loci/loci.h>
304#include <locitest/of_dup.h>
305#include <locitest/unittest.h>
306
307extern int global_error;
308extern int exit_on_error;
309
310/* @todo Make option for -k to continue tests if errors */
311#define RUN_TEST(test) do { \\
312 int rv; \\
313 TESTCASE(test, rv); \\
314 if (rv != TEST_PASS) { \\
315 global_error=1; \\
316 if (exit_on_error) return(1); \\
317 } \\
318 } while(0)
319
320#define TEST_OK(op) TEST_ASSERT((op) == OF_ERROR_NONE)
321#define TEST_INDIGO_OK(op) TEST_ASSERT((op) == INDIGO_ERROR_NONE)
322
323/*
324 * Declarations of functions to populate scalar values in a a class
325 */
326
327extern void of_test_str_fill(uint8_t *buf, int value, int len);
328extern int of_test_str_check(uint8_t *buf, int value, int len);
329
330
331extern int of_octets_populate(of_octets_t *octets, int value);
332extern int of_octets_check(of_octets_t *octets, int value);
333extern int of_match_populate(of_match_t *match, of_version_t version,
334 int value);
335extern int of_match_check(of_match_t *match, of_version_t version, int value);
336extern int test_ident_macros(void);
337extern int test_dump_objs(void);
338
339/* In test_match_utils.c */
340extern int test_match_utils(void);
341
342extern int run_unified_accessor_tests(void);
343extern int run_match_tests(void);
344extern int run_utility_tests(void);
345
346extern int run_scalar_acc_tests(void);
347extern int run_list_tests(void);
348extern int run_message_tests(void);
349extern int run_setup_from_add_tests(void);
350
351extern int run_validator_tests(void);
352
353extern int run_list_limits_tests(void);
354
355extern int test_ext_objs(void);
Rich Laneccae0312013-07-21 23:34:13 -0700356extern int test_datafiles(void);
Rich Lanea06d0c32013-03-25 08:52:03 -0700357
358""")
359
360 for version in of_g.of_version_range:
361 for cls in of_g.standard_class_order:
362 if not loxi_utils.class_in_version(cls, version):
363 continue
364 if cls in type_maps.inheritance_map:
365 continue
366 out.write("""
367extern int %(cls)s_%(v_name)s_populate(
368 %(cls)s_t *obj, int value);
369extern int %(cls)s_%(v_name)s_check(
370 %(cls)s_t *obj, int value);
371extern int %(cls)s_%(v_name)s_populate_scalars(
372 %(cls)s_t *obj, int value);
373extern int %(cls)s_%(v_name)s_check_scalars(
374 %(cls)s_t *obj, int value);
375""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
376
377 out.write("""
378/*
379 * Declarations for list population and check primitives
380 */
381""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700382
Rich Lanea06d0c32013-03-25 08:52:03 -0700383 for version in of_g.of_version_range:
384 for cls in of_g.ordered_list_objects:
385 if cls in type_maps.inheritance_map:
386 continue
387
388 if version in of_g.unified[cls]:
389 out.write("""
390extern int
391 list_setup_%(cls)s_%(v_name)s(
392 %(cls)s_t *list, int value);
393extern int
394 list_check_%(cls)s_%(v_name)s(
395 %(cls)s_t *list, int value);
396""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
397
398 out.write("\n#endif /* _TEST_COMMON_H_ */\n")
399
400def gen_common_test(out, name):
401 """
402 Generate common test content including main
403 """
404 loxi_utils.gen_c_copy_license(out)
405 out.write("""
406/*
407 * Common test code for LOCI
408 *
409 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
410 */
411
412#define DISABLE_WARN_UNUSED_RESULT
413#include "loci_log.h"
414#include <loci/loci_obj_dump.h>
415#include <locitest/unittest.h>
416#include <locitest/test_common.h>
417
YAMAMOTO Takashi071b5912013-07-02 08:37:39 +0900418/* mcheck is a glibc extension */
419#if defined(__linux__)
Rich Lanea06d0c32013-03-25 08:52:03 -0700420#include <mcheck.h>
421#define MCHECK_INIT mcheck(NULL)
YAMAMOTO Takashi071b5912013-07-02 08:37:39 +0900422#else
Rich Lanea06d0c32013-03-25 08:52:03 -0700423#define MCHECK_INIT do { } while (0)
424#endif
425
426/**
427 * Exit on error if set to 1
428 */
429int exit_on_error = 1;
430
431/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700432 * Global error state: 0 is okay, 1 is error
Rich Lanea06d0c32013-03-25 08:52:03 -0700433 */
434int global_error = 0;
435
436extern int run_unified_accessor_tests(void);
437extern int run_match_tests(void);
438extern int run_utility_tests(void);
439
440extern int run_scalar_acc_tests(void);
441extern int run_list_tests(void);
442extern int run_message_tests(void);
443
444/**
445 * Macros for initializing and checking scalar types
446 *
447 * @param var The variable being initialized or checked
448 * @param val The integer value to set/check against, see below
449 *
450 * Note that equality means something special for strings. Each byte
451 * is initialized to an incrementing value. So check is done against that.
452 *
453 */
454
455""")
456 for t in scalar_types:
457 if t in integer_types:
458 out.write("""
459#define VAR_%s_INIT(var, val) var = (%s)(val)
460#define VAR_%s_CHECK(var, val) ((var) == (%s)(val))
461""" % (t.upper(), t, t.upper(), t))
462 else:
463 out.write("""
464#define VAR_%s_INIT(var, val) \\
465 of_test_str_fill((uint8_t *)&(var), val, sizeof(var))
466#define VAR_%s_CHECK(var, val) \\
467 of_test_str_check((uint8_t *)&(var), val, sizeof(var))
468""" % (t.upper(), t.upper()))
469
470 gen_fill_string(out)
471 gen_scalar_set_check_funs(out)
472 gen_list_set_check_funs(out)
473 gen_unified_accessor_funs(out)
474
475 gen_ident_tests(out)
476 gen_log_test(out)
477
478def gen_message_scalar_test(out, name):
479 """
480 Generate test cases for message objects, scalar accessors
481 """
482
483 loxi_utils.gen_c_copy_license(out)
484 out.write("""
485/**
486 *
487 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
488 *
489 * Message-scalar tests for all versions
490 */
491
492#include <locitest/test_common.h>
493""")
494 for version in of_g.of_version_range:
495 v_name = loxi_utils.version_to_name(version)
496 out.write("""
497/**
498 * Message-scalar tests for version %s
499 */
500""" % v_name)
501 for cls in of_g.standard_class_order:
502 if cls in type_maps.inheritance_map:
503 continue
504 if version in of_g.unified[cls]:
505 message_scalar_test(out, version, cls)
506
507 out.write("""
508int
509run_scalar_acc_tests(void)
510{
511""")
512 for version in of_g.of_version_range:
513 v_name = loxi_utils.version_to_name(version)
514 for cls in of_g.standard_class_order:
515 if cls in type_maps.inheritance_map:
516 continue
517 if version in of_g.unified[cls]:
518 test_name = "%s_%s" % (cls, v_name)
519 out.write(" RUN_TEST(%s_scalar);\n" % test_name)
520
521 out.write(" return TEST_PASS;\n}\n");
Andreas Wundsam53256162013-05-02 14:05:53 -0700522
Rich Lanea06d0c32013-03-25 08:52:03 -0700523def message_scalar_test(out, version, cls):
524 """
525 Generate one test case for the given version and class
526 """
527
528 members, member_types = scalar_member_types_get(cls, version)
Rich Lanef70be942013-07-18 13:33:14 -0700529 length = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
Rich Lanea06d0c32013-03-25 08:52:03 -0700530 v_name = loxi_utils.version_to_name(version)
531
532 out.write("""
533static int
534test_%(cls)s_%(v_name)s_scalar(void)
535{
536 %(cls)s_t *obj;
537
538 obj = %(cls)s_new(%(v_name)s);
539 TEST_ASSERT(obj != NULL);
540 TEST_ASSERT(obj->version == %(v_name)s);
541 TEST_ASSERT(obj->length == %(length)d);
542 TEST_ASSERT(obj->parent == NULL);
543 TEST_ASSERT(obj->object_id == %(u_cls)s);
Andreas Wundsam53256162013-05-02 14:05:53 -0700544""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700545 v_name=v_name, length=length, version=version))
Rich Lanea4b68302014-03-12 15:17:58 -0700546
547 # If this class is a concrete member of an inheritance hierarchy,
548 # run the hierarchy's root wire type parser and assert it returns
549 # the expected object id.
550 ofclass = loxi_globals.unified.class_by_name(cls)
551 if ofclass and not ofclass.virtual:
552 root = ofclass
553 while root.superclass:
554 root = root.superclass
555 if root.virtual:
556 out.write("""
557 {
558 of_object_id_t object_id;
559 %(root_cls)s_wire_object_id_get(obj, &object_id);
560 TEST_ASSERT(object_id == %(u_cls)s);
561 }
562""" % dict(root_cls=root.name, u_cls=cls.upper()))
563
Rich Lanea06d0c32013-03-25 08:52:03 -0700564 if not type_maps.class_is_virtual(cls):
565 out.write("""
566 if (obj->wire_length_get != NULL) {
567 int length;
568
569 obj->wire_length_get((of_object_t *)obj, &length);
570 TEST_ASSERT(length == %(length)d);
571 }
572
573 /* Set up incrementing values for scalar members */
574 %(cls)s_%(v_name)s_populate_scalars(obj, 1);
575
576 /* Check values just set */
577 TEST_ASSERT(%(cls)s_%(v_name)s_check_scalars(obj, 1) != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -0700578""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700579 v_name=v_name, length=length, version=version))
580
581 out.write("""
582 %(cls)s_delete(obj);
583
584 /* To do: Check memory */
585 return TEST_PASS;
586}
587""" % dict(cls=cls))
588
589# Get the members and list of scalar types for members of a given class
590def scalar_member_types_get(cls, version):
591 member_types = []
592
593 if not version in of_g.unified[cls]:
594 return ([], [])
595
596 if "use_version" in of_g.unified[cls][version]:
597 v = of_g.unified[cls][version]["use_version"]
598 members = of_g.unified[cls][v]["members"]
599 else:
600 members = of_g.unified[cls][version]["members"]
601 # Accumulate variables that are supported
602 for member in members:
603 m_type = member["m_type"]
604 m_name = member["name"]
Andreas Wundsam53256162013-05-02 14:05:53 -0700605 if (not loxi_utils.type_is_scalar(m_type) or
Rich Lanea06d0c32013-03-25 08:52:03 -0700606 ignore_member(cls, version, m_name, m_type)):
607 continue
608 if not m_type in member_types:
609 member_types.append(m_type)
610
611 return (members, member_types)
612
613def scalar_funs_instance(out, cls, version, members, member_types):
614 """
615 Generate one instance of scalar set/check functions
616 """
617 out.write("""
618/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700619 * Populate the scalar values in obj of type %(cls)s,
620 * version %(v_name)s
Rich Lanea06d0c32013-03-25 08:52:03 -0700621 * @param obj Pointer to an object to populate
622 * @param value The seed value to use in populating the object
623 * @returns The value after increments for this object's values
624 */
625int %(cls)s_%(v_name)s_populate_scalars(
626 %(cls)s_t *obj, int value) {
627""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
628 # Declare string types
629 for t in member_types:
630 out.write(" %s %s;\n" % (t, var_name_map(t)))
631 for member in members:
632 m_type = member["m_type"]
633 m_name = member["name"]
634 if (not loxi_utils.type_is_scalar(m_type) or
635 ignore_member(cls, version, m_name, m_type)):
636 continue
637 v_name = var_name_map(m_type);
638 out.write("""
639 VAR_%(u_type)s_INIT(%(v_name)s, value);
640 %(cls)s_%(m_name)s_set(obj, %(v_name)s);
641 value += 1;
642""" % dict(cls=cls, m_name=m_name, u_type=m_type.upper(), v_name=v_name))
643 out.write("""
644 return value;
645}
646""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700647
Rich Lanea06d0c32013-03-25 08:52:03 -0700648 out.write("""
649/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700650 * Check scalar values in obj of type %(cls)s,
651 * version %(v_name)s
Rich Lanea06d0c32013-03-25 08:52:03 -0700652 * @param obj Pointer to an object to check
653 * @param value Starting value for checking
654 * @returns The value after increments for this object's values
655 */
656int %(cls)s_%(v_name)s_check_scalars(
657 %(cls)s_t *obj, int value) {
658""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
659
660 for t in member_types:
661 out.write(" %s %s;\n" % (t, var_name_map(t)))
662 for member in members:
663 m_type = member["m_type"]
664 m_name = member["name"]
665 if (not loxi_utils.type_is_scalar(m_type) or
666 ignore_member(cls, version, m_name, m_type)):
667 continue
668 v_name = var_name_map(m_type);
669 out.write("""
670 %(cls)s_%(m_name)s_get(obj, &%(v_name)s);
671 TEST_ASSERT(VAR_%(u_type)s_CHECK(%(v_name)s, value));
672 value += 1;
673""" % dict(cls=cls, m_name=m_name, u_type=m_type.upper(), v_name=v_name))
674
675 out.write("""
676 return value;
677}
678
679""")
680
681def gen_scalar_set_check_funs(out):
682 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700683 For each object class with scalar members, generate functions that
Rich Lanea06d0c32013-03-25 08:52:03 -0700684 set and check their values
685 """
686 for version in of_g.of_version_range:
687 for cls in of_g.standard_class_order:
688 (members, member_types) = scalar_member_types_get(cls, version)
689 scalar_funs_instance(out, cls, version, members, member_types)
690
691
692# Helper function to set up a subclass instance for a test
693def setup_instance(out, cls, subcls, instance, v_name, inst_len, version):
694 base_type = loxi_utils.list_to_entry_type(cls)
695 setup_template = """
696 %(subcls)s_init(%(inst)s, %(v_name)s, -1, 1);
Andreas Wundsam53256162013-05-02 14:05:53 -0700697 %(cls)s_append_bind(list,
Rich Lanea06d0c32013-03-25 08:52:03 -0700698 (%(base_type)s_t *)%(inst)s);
699 value = %(subcls)s_%(v_name)s_populate(
700 %(inst)s, value);
701 cur_len += %(inst)s->length;
702 TEST_ASSERT(list->length == cur_len);
703"""
704 out.write("""
705 /* Append two instances of type %s */
706""" % subcls)
707 for i in range(2):
708 out.write(setup_template %
Andreas Wundsam53256162013-05-02 14:05:53 -0700709 dict(inst=instance, subcls=subcls, v_name=v_name,
710 base_type=base_type, cls=cls, inst_len=inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700711 version=version))
712
713def check_instance(out, cls, subcls, instance, v_name, inst_len, version, last):
714 check_template = ""
715 if inst_len >= 0:
716 check_template = """
717 TEST_ASSERT(%(inst)s->length == %(inst_len)d);
718 if (%(inst)s->wire_length_get != NULL) {
719 int length;
720
721 %(inst)s->wire_length_get(
722 (of_object_t *)&elt, &length);
723 TEST_ASSERT(length == %(inst_len)d);
724 }
725"""
726 check_template += """
727 TEST_ASSERT(%(inst)s->object_id == %(elt_name)s);
728 value = %(subcls)s_%(v_name)s_check(
729 %(inst)s, value);
730 TEST_ASSERT(value != 0);
731"""
732 out.write("\n /* Check two instances of type %s */" % instance)
733
Andreas Wundsam53256162013-05-02 14:05:53 -0700734 out.write(check_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700735 dict(elt_name=loxi_utils.enum_name(subcls), inst_len=inst_len,
736 inst=instance, subcls=subcls,
737 v_name=loxi_utils.version_to_name(version)))
738 out.write("""\
739 TEST_OK(%(cls)s_next(list, &elt));
740""" % dict(cls=cls))
741
Andreas Wundsam53256162013-05-02 14:05:53 -0700742 out.write(check_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700743 dict(elt_name=loxi_utils.enum_name(subcls), inst_len=inst_len,
744 inst=instance, subcls=subcls,
745 v_name=loxi_utils.version_to_name(version)))
746 if last:
747 out.write("""\
748 TEST_ASSERT(%(cls)s_next(list, &elt) == OF_ERROR_RANGE);
749""" % dict(cls=cls))
750 else:
751 out.write("""\
752 TEST_OK(%(cls)s_next(list, &elt));
753""" % dict(cls=cls))
754
755def setup_list_fn(out, version, cls):
756 """
757 Generate a helper function that populates a list with two
758 of each type of subclass it supports
759 """
760 out.write("""
761/**
762 * Set up a list of type %(cls)s with two of each type of subclass
763 */
764int
765list_setup_%(cls)s_%(v_name)s(
766 %(cls)s_t *list, int value)
767{
768""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
769 base_type = loxi_utils.list_to_entry_type(cls)
770 out.write("""
771 %(base_type)s_t elt;
772 int cur_len = 0;
773""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -0700774
Rich Lanea06d0c32013-03-25 08:52:03 -0700775 sub_classes = type_maps.sub_class_map(base_type, version)
Rich Lane1bd2bae2013-07-09 10:06:07 -0700776 sub_classes = [(instance, subcls) for (instance, subcls) in sub_classes if not type_maps.class_is_virtual(subcls)]
Rich Lanea06d0c32013-03-25 08:52:03 -0700777 v_name = loxi_utils.version_to_name(version)
778
779 if len(sub_classes) == 0:
780 out.write(" /* No subclasses for %s */\n"% base_type)
781 out.write(" %s_t *elt_p;\n" % base_type)
782 out.write("\n elt_p = &elt;\n")
783 else:
784 out.write(" /* Declare pointers for each subclass */\n")
785 for instance, subcls in sub_classes:
786 out.write(" %s_t *%s;\n" % (subcls, instance))
787 out.write("\n /* Instantiate pointers for each subclass */\n")
788 for instance, subcls in sub_classes:
789 out.write(" %s = &elt.%s;\n" % (instance, instance))
790
791 if len(sub_classes) == 0: # No inheritance case
792 inst_len = loxi_utils.base_type_to_length(base_type, version)
793 setup_instance(out, cls, base_type, "elt_p", v_name, inst_len, version)
794 else:
795 for instance, subcls in sub_classes:
796 inst_len = of_g.base_length[(subcls, version)]
797 setup_instance(out, cls, subcls, instance, v_name, inst_len, version)
798 out.write("""
799
800 return value;
801}
802""")
803
804def check_list_fn(out, version, cls):
805 """
806 Generate a helper function that checks a list populated by above fn
807 """
808 out.write("""
809/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700810 * Check a list of type %(cls)s generated by
Rich Lanea06d0c32013-03-25 08:52:03 -0700811 * list_setup_%(cls)s_%(v_name)s
812 */
813int
814list_check_%(cls)s_%(v_name)s(
815 %(cls)s_t *list, int value)
816{
817""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
818 base_type = loxi_utils.list_to_entry_type(cls)
819 out.write("""
820 %(base_type)s_t elt;
821""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -0700822
Rich Lanea06d0c32013-03-25 08:52:03 -0700823 sub_classes = type_maps.sub_class_map(base_type, version)
Rich Lane1bd2bae2013-07-09 10:06:07 -0700824 sub_classes = [(instance, subcls) for (instance, subcls) in sub_classes if not type_maps.class_is_virtual(subcls)]
Rich Lanea06d0c32013-03-25 08:52:03 -0700825 v_name = loxi_utils.version_to_name(version)
826
827 if len(sub_classes) == 0:
828 out.write(" /* No subclasses for %s */\n"% base_type)
829 out.write(" %s_t *elt_p;\n" % base_type)
830 out.write("\n elt_p = &elt;\n")
831 else:
832 out.write(" /* Declare pointers for each subclass */\n")
833 for instance, subcls in sub_classes:
834 out.write(" %s_t *%s;\n" % (subcls, instance))
835 out.write("\n /* Instantiate pointers for each subclass */\n")
836 for instance, subcls in sub_classes:
837 out.write(" %s = &elt.%s;\n" % (instance, instance))
838
839 out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
840 if len(sub_classes) == 0: # No inheritance case
841 if loxi_utils.class_is_var_len(base_type, version):
842 inst_len = -1
843 else:
844 inst_len = loxi_utils.base_type_to_length(base_type, version)
Andreas Wundsam53256162013-05-02 14:05:53 -0700845 check_instance(out, cls, base_type, "elt_p", v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700846 version, True)
847 else:
848 count = 0
849 for instance, subcls in sub_classes:
850 count += 1
851 if loxi_utils.class_is_var_len(subcls, version):
852 inst_len = -1
853 else:
854 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -0700855 check_instance(out, cls, subcls, instance, v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700856 version, count==len(sub_classes))
857
858 out.write("""
859 return value;
860}
861""" % dict(base_type=base_type))
862
863def gen_list_set_check_funs(out):
864 for version in of_g.of_version_range:
865 for cls in of_g.ordered_list_objects:
866 if cls in type_maps.inheritance_map:
867 continue
868
869 if version in of_g.unified[cls]:
870 setup_list_fn(out, version, cls)
871 check_list_fn(out, version, cls)
872
873# Maybe: Get a map from list class to parent, mem_name of container
874
875def list_test(out, version, cls):
876 out.write("""
877static int
878test_%(cls)s_%(v_name)s(void)
879{
880""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
881 base_type = loxi_utils.list_to_entry_type(cls)
882
883 out.write(""" %(cls)s_t *list;
884 int value = 1;
885""" % dict(cls=cls, base_type=base_type))
886
887 out.write("""
888 list = %(cls)s_new(%(v_name)s);
889 TEST_ASSERT(list != NULL);
890 TEST_ASSERT(list->version == %(v_name)s);
891 TEST_ASSERT(list->length == 0);
892 TEST_ASSERT(list->parent == NULL);
893 TEST_ASSERT(list->object_id == %(enum_cls)s);
894
895 value = list_setup_%(cls)s_%(v_name)s(list, value);
896 TEST_ASSERT(value != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -0700897""" % dict(cls=cls, base_type=base_type, v_name=loxi_utils.version_to_name(version),
Rich Lanea06d0c32013-03-25 08:52:03 -0700898 enum_cls=loxi_utils.enum_name(cls)))
899
900 out.write("""
901 /* Now check values */
902 value = 1;
903 value = list_check_%(cls)s_%(v_name)s(list, value);
904 TEST_ASSERT(value != 0);
905""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
906
907 out.write("""
908 %(cls)s_delete(list);
909
910 return TEST_PASS;
911}
912""" % dict(cls=cls))
913
914def gen_list_test(out, name):
915 """
916 Generate base line test cases for lists
917 @param out The file handle to write to
918 """
919
920 loxi_utils.gen_c_copy_license(out)
921 out.write("""
922/**
923 *
924 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
925 *
926 * Message-scalar tests for all versions
927 */
928
929#include <locitest/test_common.h>
930""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700931
Rich Lanea06d0c32013-03-25 08:52:03 -0700932 for version in of_g.of_version_range:
933 v_name = loxi_utils.version_to_name(version)
934 out.write("""
935/**
936 * Baseline list tests for version %s
937 */
938""" % v_name)
939 for cls in of_g.ordered_list_objects:
940 if cls in type_maps.inheritance_map:
941 continue
942 if version in of_g.unified[cls]:
943 list_test(out, version, cls)
944
945 out.write("""
946int
947run_list_tests(void)
948{
949""")
950 for version in of_g.of_version_range:
951 v_name = loxi_utils.version_to_name(version)
952 for cls in of_g.ordered_list_objects:
953 if cls in type_maps.inheritance_map:
954 continue
955 if version in of_g.unified[cls]:
956 test_name = "%s_%s" % (cls, v_name)
957 out.write(" RUN_TEST(%s);\n" % test_name)
958
959 out.write("\n return TEST_PASS;\n}\n");
960
961def gen_match_test(out, name):
962 """
963 Generate baseline tests for match functions
964 """
965
966 loxi_utils.gen_c_copy_license(out)
967 out.write("""\
968/**
969 *
970 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
971 *
972 * Message-scalar tests for all versions
973 * @fixme These are mostly hard coded now.
974 */
975
976#include <locitest/test_common.h>
977
978static int
979test_match_1(void)
980{
981 of_match_v1_t *m_v1;
982 of_match_v2_t *m_v2;
983 of_match_v3_t *m_v3;
984 of_match_v4_t *m_v4;
985 of_match_t match;
986 int value = 1;
987 int idx;
988 uint32_t exp_value;
989
990 /* Verify default values for ip mask map */
991 for (idx = 0; idx < OF_IP_MASK_MAP_COUNT; idx++) {
992 exp_value = (idx < 32) ? ~((1 << idx) - 1) : 0;
993 TEST_ASSERT(of_ip_index_to_mask(idx) == exp_value);
994 if (idx < 32) {
995 TEST_ASSERT(of_ip_mask_to_index(exp_value) == idx);
996 }
997 }
998
999 TEST_ASSERT(of_ip_mask_map_set(17, 0xabcdef00) == OF_ERROR_NONE);
1000 TEST_ASSERT(of_ip_mask_to_index(0xabcdef00) == 17);
1001 TEST_ASSERT(of_ip_index_to_mask(17) == 0xabcdef00);
1002
1003 TEST_ASSERT(of_ip_mask_map_set(62, 0xabcdefff) == OF_ERROR_NONE);
1004 TEST_ASSERT(of_ip_mask_to_index(0xabcdefff) == 62);
1005 TEST_ASSERT(of_ip_index_to_mask(62) == 0xabcdefff);
1006
1007 /* Test re-init */
1008 of_ip_mask_map_init();
1009 for (idx = 0; idx < OF_IP_MASK_MAP_COUNT; idx++) {
1010 exp_value = (idx < 32) ? ~((1 << idx) - 1) : 0;
1011 TEST_ASSERT(of_ip_index_to_mask(idx) == exp_value);
1012 if (idx < 32) {
1013 TEST_ASSERT(of_ip_mask_to_index(exp_value) == idx);
1014 }
1015 }
1016""")
1017
1018 for version in of_g.of_version_range:
1019 out.write("""
1020 /* Create/populate/convert and delete for version %(v_name)s */
1021 m_v%(version)d = of_match_v%(version)d_new(%(v_name)s);
1022 TEST_ASSERT(m_v%(version)d != NULL);
1023 TEST_ASSERT((value = of_match_populate(&match, %(v_name)s, value)) > 0);
1024 TEST_OK(of_match_to_wire_match_v%(version)d(&match, m_v%(version)d));
1025 of_match_v%(version)d_delete(m_v%(version)d);
1026""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1027
1028 out.write("""
1029 return TEST_PASS;
1030}
1031""")
1032
1033 out.write("""
1034static int
1035test_match_2(void)
1036{
1037 of_match_v1_t *m_v1;
1038 of_match_v2_t *m_v2;
1039 of_match_v3_t *m_v3;
1040 of_match_v3_t *m_v4;
1041 of_match_t match1;
1042 of_match_t match2;
1043 int value = 1;
1044""")
1045
1046 for version in of_g.of_version_range:
1047 out.write("""
1048 TEST_ASSERT((value = of_match_populate(&match1, %(v_name)s, value)) > 0);
1049 m_v%(version)d = of_match_v%(version)d_new(%(v_name)s);
1050 TEST_ASSERT(m_v%(version)d != NULL);
1051 TEST_OK(of_match_to_wire_match_v%(version)d(&match1, m_v%(version)d));
1052 TEST_OK(of_match_v%(version)d_to_match(m_v%(version)d, &match2));
1053 TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
1054 of_match_v%(version)d_delete(m_v%(version)d);
1055""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1056
1057 out.write("""
1058 return TEST_PASS;
1059}
1060""")
1061
1062 out.write("""
1063static int
1064test_match_3(void)
1065{
1066 of_match_t match1;
1067 of_match_t match2;
1068 int value = 1;
1069 of_octets_t octets;
1070""")
1071 for version in of_g.of_version_range:
1072 out.write("""
1073 /* Serialize to version %(v_name)s */
1074 TEST_ASSERT((value = of_match_populate(&match1, %(v_name)s, value)) > 0);
Andreas Wundsam53256162013-05-02 14:05:53 -07001075 TEST_ASSERT(of_match_serialize(%(v_name)s, &match1, &octets) ==
Rich Lanea06d0c32013-03-25 08:52:03 -07001076 OF_ERROR_NONE);
Andreas Wundsam53256162013-05-02 14:05:53 -07001077 TEST_ASSERT(of_match_deserialize(%(v_name)s, &match2, &octets) ==
Rich Lanea06d0c32013-03-25 08:52:03 -07001078 OF_ERROR_NONE);
1079 TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
1080 FREE(octets.data);
1081""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1082
1083 out.write("""
1084 return TEST_PASS;
1085}
1086""")
1087
1088 out.write("""
1089int run_match_tests(void)
1090{
1091 RUN_TEST(match_1);
1092 RUN_TEST(match_2);
1093 RUN_TEST(match_3);
1094 RUN_TEST(match_utils);
1095
1096 return TEST_PASS;
1097}
1098""")
1099
1100def gen_msg_test(out, name):
1101 loxi_utils.gen_c_copy_license(out)
1102 out.write("""
1103/**
1104 *
1105 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1106 *
1107 * Message-scalar tests for all versions
1108 */
1109
1110#include <locitest/test_common.h>
1111""")
1112 for version in of_g.of_version_range:
1113 for cls in of_g.ordered_messages:
1114 if not (cls, version) in of_g.base_length:
1115 continue
Rich Lane488b3c52013-06-21 18:11:02 -07001116 if type_maps.class_is_virtual(cls):
1117 continue
Rich Lanef70be942013-07-18 13:33:14 -07001118 bytes = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
Rich Lanea06d0c32013-03-25 08:52:03 -07001119 out.write("""
1120static int
1121test_%(cls)s_create_%(v_name)s(void)
1122{
1123 %(cls)s_t *obj;
1124 uint8_t *msg_buf;
1125 int value;
1126 int len;
Rich Lanea4b68302014-03-12 15:17:58 -07001127 of_object_id_t object_id;
Rich Lanea06d0c32013-03-25 08:52:03 -07001128
1129 obj = %(cls)s_new(%(v_name)s);
1130 TEST_ASSERT(obj != NULL);
1131 TEST_ASSERT(obj->version == %(v_name)s);
1132 TEST_ASSERT(obj->length == %(bytes)d);
1133 TEST_ASSERT(obj->parent == NULL);
1134 TEST_ASSERT(obj->object_id == %(enum)s);
1135
Rich Lanea4b68302014-03-12 15:17:58 -07001136 of_header_wire_object_id_get(obj, &object_id);
1137 TEST_ASSERT(object_id == %(enum)s);
1138
Rich Lanea06d0c32013-03-25 08:52:03 -07001139 /* Set up incrementing values for scalar members */
1140 value = %(cls)s_%(v_name)s_populate_scalars(obj, 1);
1141 TEST_ASSERT(value != 0);
1142
1143 /* Grab the underlying buffer from the message */
1144 len = obj->length;
1145 of_object_wire_buffer_steal((of_object_t *)obj, &msg_buf);
1146 TEST_ASSERT(msg_buf != NULL);
1147 %(cls)s_delete(obj);
1148 /* TODO: */
1149 TEST_ASSERT(of_message_to_object_id(msg_buf, len) == %(enum)s);
1150 obj = %(cls)s_new_from_message(OF_BUFFER_TO_MESSAGE(msg_buf));
1151
1152 TEST_ASSERT(obj != NULL);
1153
1154 /* @fixme Set up all message objects (recursively?) */
1155
1156 value = %(cls)s_%(v_name)s_check_scalars(obj, 1);
1157 TEST_ASSERT(value != 0);
1158
1159 %(cls)s_delete(obj);
1160
1161 return TEST_PASS;
1162}
1163""" % dict(cls=cls, version=version, enum=loxi_utils.enum_name(cls),
1164 v_name=loxi_utils.version_to_name(version), bytes=bytes))
1165
1166 out.write("""
1167int
1168run_message_tests(void)
1169{
1170""")
1171 for version in of_g.of_version_range:
1172 for cls in of_g.ordered_messages:
1173 if not (cls, version) in of_g.base_length:
1174 continue
Rich Lane488b3c52013-06-21 18:11:02 -07001175 if type_maps.class_is_virtual(cls):
1176 continue
Rich Lanea06d0c32013-03-25 08:52:03 -07001177 test_name = "%s_create_%s" % (cls, loxi_utils.version_to_name(version))
1178 out.write(" RUN_TEST(%s);\n" % test_name)
1179
1180 out.write("\n return TEST_PASS;\n}\n");
Andreas Wundsam53256162013-05-02 14:05:53 -07001181
Rich Lanea06d0c32013-03-25 08:52:03 -07001182
1183def gen_list_setup_check(out, cls, version):
1184 """
1185 Generate functions that populate and check a list with two
1186 of each type of subclass it supports
1187 """
1188 out.write("""
1189/**
1190 * Populate a list of type %(cls)s with two of each type of subclass
1191 * @param list Pointer to the list to be populated
1192 * @param value The seed value to use in populating the list
1193 * @returns The value after increments for this object's values
1194 */
1195int
1196%(cls)s_%(v_name)s_populate(
1197 %(cls)s_t *list, int value)
1198{
1199""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1200 base_type = loxi_utils.list_to_entry_type(cls)
1201 out.write("""
1202 %(base_type)s_t elt;
1203 int cur_len = 0;
1204""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -07001205
Rich Lanea06d0c32013-03-25 08:52:03 -07001206 sub_classes = type_maps.sub_class_map(base_type, version)
Rich Lane1bd2bae2013-07-09 10:06:07 -07001207 sub_classes = [(instance, subcls) for (instance, subcls) in sub_classes if not type_maps.class_is_virtual(subcls)]
Rich Lanea06d0c32013-03-25 08:52:03 -07001208 v_name = loxi_utils.version_to_name(version)
1209
1210 if len(sub_classes) == 0:
1211 out.write(" /* No subclasses for %s */\n"% base_type)
1212 out.write(" %s_t *elt_p;\n" % base_type)
1213 out.write("\n elt_p = &elt;\n")
1214 else:
1215 out.write(" /* Declare pointers for each subclass */\n")
1216 for instance, subcls in sub_classes:
1217 out.write(" %s_t *%s;\n" % (subcls, instance))
1218 out.write("\n /* Instantiate pointers for each subclass */\n")
1219 for instance, subcls in sub_classes:
1220 out.write(" %s = &elt.%s;\n" % (instance, instance))
1221
1222# if type_maps.class_is_virtual(base_type):
1223# out.write("""\
1224# TEST_OK(%(base_type)s_header_init(
1225# (%(base_type)s_header_t *)&elt, %(v_name)s, -1, 1));
1226# """ % dict(base_type=base_type, v_name=loxi_utils.version_to_name(version)))
1227# else:
1228# out.write("""\
1229# TEST_OK(%(base_type)s_init(&elt, %(v_name)s, -1, 1));
1230# """ % dict(base_type=base_type, v_name=loxi_utils.version_to_name(version)))
1231
1232 if len(sub_classes) == 0: # No inheritance case
1233 inst_len = loxi_utils.base_type_to_length(base_type, version)
1234 setup_instance(out, cls, base_type, "elt_p", v_name, inst_len, version)
1235 else:
1236 for instance, subcls in sub_classes:
1237 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -07001238 setup_instance(out, cls, subcls, instance, v_name,
Rich Lanea06d0c32013-03-25 08:52:03 -07001239 inst_len, version)
1240 out.write("""
1241 return value;
1242}
1243""")
1244 out.write("""
1245/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001246 * Check a list of type %(cls)s generated by
Rich Lanea06d0c32013-03-25 08:52:03 -07001247 * %(cls)s_%(v_name)s_populate
1248 * @param list Pointer to the list that was populated
1249 * @param value Starting value for checking
1250 * @returns The value after increments for this object's values
1251 */
1252int
1253%(cls)s_%(v_name)s_check(
1254 %(cls)s_t *list, int value)
1255{
1256""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1257 base_type = loxi_utils.list_to_entry_type(cls)
1258 out.write("""
1259 %(base_type)s_t elt;
1260 int count = 0;
1261 int rv;
1262""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -07001263
Rich Lanea06d0c32013-03-25 08:52:03 -07001264
1265 sub_classes = type_maps.sub_class_map(base_type, version)
Rich Lane1bd2bae2013-07-09 10:06:07 -07001266 sub_classes = [(instance, subcls) for (instance, subcls) in sub_classes if not type_maps.class_is_virtual(subcls)]
Rich Lanea06d0c32013-03-25 08:52:03 -07001267 v_name = loxi_utils.version_to_name(version)
1268
1269 if len(sub_classes) == 0:
1270 entry_count = 2
1271 out.write(" /* No subclasses for %s */\n"% base_type)
1272 out.write(" %s_t *elt_p;\n" % base_type)
1273 out.write("\n elt_p = &elt;\n")
1274 else:
1275 entry_count = 2 * len(sub_classes) # Two of each type appended
1276 out.write(" /* Declare pointers for each subclass */\n")
1277 for instance, subcls in sub_classes:
1278 out.write(" %s_t *%s;\n" % (subcls, instance))
1279 out.write("\n /* Instantiate pointers for each subclass */\n")
1280 for instance, subcls in sub_classes:
1281 out.write(" %s = &elt.%s;\n" % (instance, instance))
1282
1283 out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
1284 if len(sub_classes) == 0: # No inheritance case
1285 if loxi_utils.class_is_var_len(base_type, version):
1286 inst_len = -1
1287 else:
1288 inst_len = loxi_utils.base_type_to_length(base_type, version)
Andreas Wundsam53256162013-05-02 14:05:53 -07001289 check_instance(out, cls, base_type, "elt_p", v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -07001290 version, True)
1291 else:
1292 count = 0
1293 for instance, subcls in sub_classes:
1294 count += 1
1295 if loxi_utils.class_is_var_len(subcls, version):
1296 inst_len = -1
1297 else:
1298 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -07001299 check_instance(out, cls, subcls, instance, v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -07001300 version, count==len(sub_classes))
1301 out.write("""
1302""" % dict(base_type=base_type))
1303
1304 out.write("""
1305 /* Do an iterate to test the iterator */
1306 %(u_cls)s_ITER(list, &elt, rv) {
1307 count += 1;
1308 }
1309
1310 TEST_ASSERT(rv == OF_ERROR_RANGE);
1311 TEST_ASSERT(count == %(entry_count)d);
1312
1313 /* We shoehorn a test of the dup functions here */
1314 {
1315 %(cls)s_t *dup;
1316
1317 TEST_ASSERT((dup = %(cls)s_dup(list)) != NULL);
1318 TEST_ASSERT(dup->length == list->length);
1319 TEST_ASSERT(dup->object_id == list->object_id);
1320 TEST_ASSERT(dup->version == list->version);
1321 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1322 OF_OBJECT_BUFFER_INDEX(list, 0), list->length) == 0);
1323 of_object_delete((of_object_t *)dup);
1324
1325 /* And now for the generic dup function */
1326 TEST_ASSERT((dup = (%(cls)s_t *)
1327 of_object_dup(list)) != NULL);
1328 TEST_ASSERT(dup->length == list->length);
1329 TEST_ASSERT(dup->object_id == list->object_id);
1330 TEST_ASSERT(dup->version == list->version);
1331 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1332 OF_OBJECT_BUFFER_INDEX(list, 0), list->length) == 0);
1333 of_object_delete((of_object_t *)dup);
1334 }
1335
1336 return value;
1337}
1338""" % dict(cls=cls, u_cls=cls.upper(), entry_count=entry_count))
1339
1340
1341def gen_class_setup_check(out, cls, version):
1342 out.write("""
1343/**
1344 * Populate all members of an object of type %(cls)s
1345 * with incrementing values
1346 * @param obj Pointer to an object to populate
1347 * @param value The seed value to use in populating the object
1348 * @returns The value after increments for this object's values
1349 */
1350
1351int
1352%(cls)s_%(v_name)s_populate(
1353 %(cls)s_t *obj, int value)
1354{
1355""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1356 members, member_types = loxi_utils.all_member_types_get(cls, version)
1357 for m_type in member_types:
1358 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1359 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1360 else:
1361 out.write(" %s *%s;\n" % (m_type, var_name_map(m_type)))
1362 out.write("""
1363 /* Run thru accessors after new to ensure okay */
1364""")
1365 for member in members:
1366 m_type = member["m_type"]
1367 m_name = member["name"]
1368 if loxi_utils.skip_member_name(m_name):
1369 continue
1370 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1371 out.write("""\
1372 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1373""" % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
1374 else:
1375 sub_cls = m_type[:-2] # Trim _t
1376 out.write("""\
1377 {
1378 %(sub_cls)s_t sub_cls;
1379
1380 /* Test bind */
1381 %(cls)s_%(m_name)s_bind(obj, &sub_cls);
1382 }
Andreas Wundsam53256162013-05-02 14:05:53 -07001383""" % dict(var_name=var_name_map(m_type), cls=cls,
Rich Lanea06d0c32013-03-25 08:52:03 -07001384 m_name=m_name, sub_cls=sub_cls,
1385 v_name=loxi_utils.version_to_name(version)))
1386
1387 out.write("""
1388 value = %(cls)s_%(v_name)s_populate_scalars(
1389 obj, value);
1390 TEST_ASSERT(value != 0);
1391""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1392
1393 for member in members:
1394 m_type = member["m_type"]
1395 m_name = member["name"]
1396 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1397 continue
1398 if loxi_utils.skip_member_name(m_name):
1399 continue
1400 if m_type == "of_match_t":
1401 out.write("""\
1402 value = of_match_populate(&%(var_name)s, %(v_name)s, value);
1403 TEST_ASSERT(value != 0);
1404 %(cls)s_%(m_name)s_set(
1405 obj, &%(var_name)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001406""" % dict(cls=cls, var_name=var_name_map(m_type),
Rich Lanea06d0c32013-03-25 08:52:03 -07001407 m_name=m_name, v_name=loxi_utils.version_to_name(version)))
1408 elif m_type == "of_octets_t":
1409 out.write("""\
1410 value = of_octets_populate(&%(var_name)s, value);
1411 TEST_ASSERT(value != 0);
1412 %(cls)s_%(m_name)s_set(
1413 obj, &%(var_name)s);
1414 if (octets.bytes) {
1415 FREE(octets.data);
1416 }
1417""" % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
1418 else:
1419 sub_cls = m_type[:-2] # Trim _t
1420 out.write("""
1421 %(var_name)s = %(sub_cls)s_new(%(v_name)s);
1422 TEST_ASSERT(%(var_name)s != NULL);
1423 value = %(sub_cls)s_%(v_name)s_populate(
1424 %(var_name)s, value);
1425 TEST_ASSERT(value != 0);
1426 %(cls)s_%(m_name)s_set(
1427 obj, %(var_name)s);
1428 %(sub_cls)s_delete(%(var_name)s);
1429""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, m_type=m_type,
1430 var_name=var_name_map(m_type),
1431 v_name=loxi_utils.version_to_name(version)))
1432
1433 out.write("""
1434 return value;
1435}
1436""")
1437
1438 out.write("""
1439/**
1440 * Check all members of an object of type %(cls)s
1441 * populated by the above function
1442 * @param obj Pointer to an object to check
1443 * @param value Starting value for checking
1444 * @returns The value after increments for this object's values
1445 */
1446
1447int
1448%(cls)s_%(v_name)s_check(
1449 %(cls)s_t *obj, int value)
1450{
1451""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1452 members, member_types = loxi_utils.all_member_types_get(cls, version)
1453 for m_type in member_types:
1454 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1455 continue
1456 if loxi_utils.type_is_of_object(m_type):
1457 continue
1458 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1459 out.write("""
1460 value = %(cls)s_%(v_name)s_check_scalars(
1461 obj, value);
1462 TEST_ASSERT(value != 0);
1463""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1464
1465 for member in members:
1466 m_type = member["m_type"]
1467 m_name = member["name"]
1468 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1469 continue
1470 if loxi_utils.skip_member_name(m_name):
1471 continue
1472 if m_type == "of_match_t":
1473 out.write("""\
1474 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1475 value = of_match_check(&%(var_name)s, %(v_name)s, value);
1476""" % dict(cls=cls, var_name=var_name_map(m_type), m_name=m_name,
1477 v_name=loxi_utils.version_to_name(version)))
1478 elif m_type == "of_octets_t":
1479 out.write("""\
1480 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1481 value = of_octets_check(&%(var_name)s, value);
1482""" % dict(cls=cls, var_name=var_name_map(m_type), m_name=m_name,
1483 v_name=loxi_utils.version_to_name(version)))
1484 else:
1485 sub_cls = m_type[:-2] # Trim _t
1486 out.write("""
1487 { /* Use get/delete to access on check */
1488 %(m_type)s *%(m_name)s_ptr;
1489
1490 %(m_name)s_ptr = %(cls)s_%(m_name)s_get(obj);
1491 TEST_ASSERT(%(m_name)s_ptr != NULL);
1492 value = %(sub_cls)s_%(v_name)s_check(
1493 %(m_name)s_ptr, value);
1494 TEST_ASSERT(value != 0);
1495 %(sub_cls)s_delete(%(m_name)s_ptr);
1496 }
1497""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, m_type=m_type,
1498 var_name=var_name_map(m_type),
1499 v_name=loxi_utils.version_to_name(version)))
1500
1501 out.write("""
1502 /* We shoehorn a test of the dup functions here */
1503 {
1504 %(cls)s_t *dup;
1505
1506 TEST_ASSERT((dup = %(cls)s_dup(obj)) != NULL);
1507 TEST_ASSERT(dup->length == obj->length);
1508 TEST_ASSERT(dup->object_id == obj->object_id);
1509 TEST_ASSERT(dup->version == obj->version);
1510 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1511 OF_OBJECT_BUFFER_INDEX(obj, 0), obj->length) == 0);
1512 of_object_delete((of_object_t *)dup);
1513
1514 /* And now for the generic dup function */
1515 TEST_ASSERT((dup = (%(cls)s_t *)
1516 of_object_dup(obj)) != NULL);
1517 TEST_ASSERT(dup->length == obj->length);
1518 TEST_ASSERT(dup->object_id == obj->object_id);
1519 TEST_ASSERT(dup->version == obj->version);
1520 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1521 OF_OBJECT_BUFFER_INDEX(obj, 0), obj->length) == 0);
1522 of_object_delete((of_object_t *)dup);
1523 }
1524
1525 return value;
1526}
1527""" % dict(cls=cls))
1528
1529def unified_accessor_test_case(out, cls, version):
1530 """
1531 Generate one test case for the given version and class
1532 """
1533
1534 members, member_types = scalar_member_types_get(cls, version)
Rich Lanef70be942013-07-18 13:33:14 -07001535 length = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
Rich Lanea06d0c32013-03-25 08:52:03 -07001536 v_name = loxi_utils.version_to_name(version)
1537
1538 out.write("""
1539static int
1540test_%(cls)s_%(v_name)s(void)
1541{
1542 %(cls)s_t *obj;
1543 obj = %(cls)s_new(%(v_name)s);
1544 TEST_ASSERT(obj != NULL);
1545 TEST_ASSERT(obj->version == %(v_name)s);
1546 TEST_ASSERT(obj->length == %(length)d);
1547 TEST_ASSERT(obj->parent == NULL);
1548 TEST_ASSERT(obj->object_id == %(u_cls)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001549""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -07001550 v_name=v_name, length=length, version=version))
1551 if (not type_maps.class_is_virtual(cls)) or loxi_utils.class_is_list(cls):
1552 out.write("""
1553 if (obj->wire_length_get != NULL) {
1554 int length;
1555
1556 obj->wire_length_get((of_object_t *)obj, &length);
1557 TEST_ASSERT(length == %(length)d);
1558 }
1559 if (obj->wire_type_get != NULL) {
1560 of_object_id_t obj_id;
1561
1562 obj->wire_type_get((of_object_t *)obj, &obj_id);
1563 TEST_ASSERT(obj_id == %(u_cls)s);
1564 }
1565
1566 /* Set up incrementing values for members */
1567 TEST_ASSERT(%(cls)s_%(v_name)s_populate(
1568 obj, 1) != 0);
1569
1570 /* Check values just set */
1571 TEST_ASSERT(%(cls)s_%(v_name)s_check(
1572 obj, 1) != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -07001573""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -07001574 v_name=v_name, length=length, version=version))
1575
1576 out.write("""
1577 %(cls)s_delete(obj);
1578
1579 /* To do: Check memory */
1580 return TEST_PASS;
1581}
1582""" % dict(cls=cls))
1583
1584
1585def gen_unified_accessor_funs(out):
1586 for version in of_g.of_version_range:
1587 for cls in of_g.standard_class_order:
1588 if not loxi_utils.class_in_version(cls, version):
1589 continue
1590 if cls in type_maps.inheritance_map:
1591 continue
1592 elif loxi_utils.class_is_list(cls):
1593 gen_list_setup_check(out, cls, version)
1594 else:
1595 gen_class_setup_check(out, cls, version)
1596
1597def gen_unified_accessor_tests(out, name):
1598 loxi_utils.gen_c_copy_license(out)
1599 out.write("""
1600/**
1601 *
1602 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1603 *
1604 * Unified simple class instantiation tests for all versions
1605 */
1606
1607#include <locitest/test_common.h>
1608""")
1609 for version in of_g.of_version_range:
1610 for cls in of_g.standard_class_order:
1611 if not loxi_utils.class_in_version(cls, version):
1612 continue
1613 if cls in type_maps.inheritance_map:
1614 continue
1615 unified_accessor_test_case(out, cls, version)
1616
1617 out.write("""
1618int
1619run_unified_accessor_tests(void)
1620{
1621""")
1622 for version in of_g.of_version_range:
1623 v_name = loxi_utils.version_to_name(version)
1624 for cls in of_g.standard_class_order:
1625 if not loxi_utils.class_in_version(cls, version):
1626 continue
1627 if cls in type_maps.inheritance_map:
1628 continue
1629 test_name = "%s_%s" % (cls, v_name)
1630 out.write(" RUN_TEST(%s);\n" % test_name)
1631
1632 out.write(" return TEST_PASS;\n}\n");
1633
1634
1635
1636################################################################
1637#
1638# Object duplication functions
1639#
1640# These exercise the accessors to create duplicate objects.
1641# They are used in the LOCI test shim which sits in an OF
1642# protocol stream.
1643#
1644# TODO
1645# Resolve version stuff
1646# Complete list dup
1647
1648def gen_dup_list(out, cls, version):
1649 ver_name = loxi_utils.version_to_name(version)
1650 elt_type = loxi_utils.list_to_entry_type(cls)
1651 out.write("""
1652/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001653 * Duplicate a list of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001654 * using accessor functions
1655 * @param src Pointer to object to be duplicated
1656 * @returns A new object of type %(cls)s.
1657 *
1658 * The caller is responsible for deleting the returned value
1659 */
1660%(cls)s_t *
1661%(cls)s_%(ver_name)s_dup(
1662 %(cls)s_t *src)
1663{
1664 %(elt_type)s_t src_elt;
1665 %(elt_type)s_t *dst_elt;
1666 int rv;
1667 %(cls)s_t *dst;
1668
1669 if ((dst = %(cls)s_new(src->version)) == NULL) {
1670 return NULL;
1671 }
1672""" % dict(elt_type=elt_type, cls=cls, ver_name=ver_name))
1673
1674 out.write("""
1675 %(u_cls)s_ITER(src, &src_elt, rv) {
1676 if ((dst_elt = %(elt_type)s_%(ver_name)s_dup(&src_elt)) == NULL) {
1677 of_object_delete((of_object_t *)dst);
1678 return NULL;
1679 }
1680 _TRY_FREE(%(cls)s_append(dst, dst_elt),
1681 dst, NULL);
1682 of_object_delete((of_object_t *)dst_elt);
1683 }
1684
1685 return dst;
1686}
1687""" % dict(u_cls=cls.upper(), elt_type=elt_type, cls=cls, ver_name=ver_name))
1688
1689
1690def gen_dup_inheritance(out, cls, version):
1691 ver_name = loxi_utils.version_to_name(version)
1692 out.write("""
1693/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001694 * Duplicate a super class object of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001695 * @param src Pointer to object to be duplicated
1696 * @returns A new object of type %(cls)s.
1697 *
1698 * The caller is responsible for deleting the returned value
1699 */
1700%(cls)s_t *
1701%(cls)s_%(ver_name)s_dup(
1702 %(cls)s_t *src)
1703{
1704""" % dict(cls=cls, ver_name=ver_name))
1705
1706 # For each subclass, check if this is an instance of that subclass
1707 version_classes = type_maps.inheritance_data[cls][version]
1708 for sub_cls in version_classes:
1709 sub_enum = (cls + "_" + sub_cls).upper()
1710 out.write("""
1711 if (src->header.object_id == %(sub_enum)s) {
1712 return (%(cls)s_t *)%(cls)s_%(sub_cls)s_%(ver_name)s_dup(
1713 &src->%(sub_cls)s);
1714 }
1715""" % dict(sub_cls=sub_cls, ver_name=ver_name, sub_enum=sub_enum, cls=cls))
1716
1717 out.write("""
1718 return NULL;
1719}
1720""")
1721
1722
1723def gen_dup_cls(out, cls, version):
1724 """
1725 Generate duplication routine for class cls
1726 """
1727 ver_name = loxi_utils.version_to_name(version)
1728
1729 out.write("""
1730/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001731 * Duplicate an object of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001732 * using accessor functions
1733 * @param src Pointer to object to be duplicated
1734 * @returns A new object of type %(cls)s.
1735 *
1736 * The caller is responsible for deleting the returned value
1737 */
1738%(cls)s_t *
1739%(cls)s_%(ver_name)s_dup(
1740 %(cls)s_t *src)
1741{
1742 %(cls)s_t *dst;
1743""" % dict(cls=cls, ver_name=ver_name))
1744
1745 # Get members and types for the class
1746 members, member_types = loxi_utils.all_member_types_get(cls, version)
1747
1748 # Add declarations for each member type
1749 for m_type in member_types:
1750 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1751 # Declare instance of these
1752 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1753 else:
1754 out.write("""
1755 %(m_type)s src_%(v_name)s;
1756 %(m_type)s *dst_%(v_name)s;
1757""" % dict(m_type=m_type, v_name=var_name_map(m_type)))
1758
1759 out.write("""
1760 if ((dst = %(cls)s_new(src->version)) == NULL) {
1761 return NULL;
1762 }
1763""" % dict(cls=cls))
1764
1765 for member in members:
1766 m_type = member["m_type"]
1767 m_name = member["name"]
1768 if loxi_utils.skip_member_name(m_name):
1769 continue
1770 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1771 out.write("""
1772 %(cls)s_%(m_name)s_get(src, &%(v_name)s);
1773 %(cls)s_%(m_name)s_set(dst, %(v_name)s);
1774""" % dict(cls=cls, m_name=m_name, v_name=var_name_map(m_type)))
1775 elif m_type in ["of_match_t", "of_octets_t"]:
1776 out.write("""
1777 %(cls)s_%(m_name)s_get(src, &%(v_name)s);
1778 %(cls)s_%(m_name)s_set(dst, &%(v_name)s);
1779""" % dict(cls=cls, m_name=m_name, v_name=var_name_map(m_type)))
1780 else:
1781 sub_cls = m_type[:-2] # Trim _t
1782 out.write("""
1783 %(cls)s_%(m_name)s_bind(
1784 src, &src_%(v_name)s);
1785 dst_%(v_name)s = %(sub_cls)s_%(ver_name)s_dup(&src_%(v_name)s);
1786 if (dst_%(v_name)s == NULL) {
1787 %(cls)s_delete(dst);
1788 return NULL;
1789 }
1790 %(cls)s_%(m_name)s_set(dst, dst_%(v_name)s);
1791 %(sub_cls)s_delete(dst_%(v_name)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001792""" % dict(sub_cls=sub_cls, cls=cls, m_name=m_name,
Rich Lanea06d0c32013-03-25 08:52:03 -07001793 v_name=var_name_map(m_type), ver_name=ver_name))
1794
1795 out.write("""
1796 return dst;
1797}
1798""")
1799
1800def gen_version_dup(out=sys.stdout):
1801 """
1802 Generate duplication routines for each object type
1803 """
1804 out.write("""
1805/* Special try macro for duplicating */
1806#define _TRY_FREE(op, obj, rv) do { \\
1807 int _rv; \\
1808 if ((_rv = (op)) < 0) { \\
1809 LOCI_LOG_ERROR("ERROR %d at %s:%d\\n", _rv, __FILE__, __LINE__); \\
1810 of_object_delete((of_object_t *)(obj)); \\
1811 return (rv); \\
1812 } \\
1813 } while (0)
1814""")
1815
1816 for version in of_g.of_version_range:
1817 for cls in of_g.standard_class_order:
1818 if not loxi_utils.class_in_version(cls, version):
1819 continue
1820 if cls in type_maps.inheritance_map:
1821 gen_dup_inheritance(out, cls, version)
1822 elif loxi_utils.class_is_list(cls):
1823 gen_dup_list(out, cls, version)
1824 else:
1825 gen_dup_cls(out, cls, version)
1826
1827def gen_dup(out=sys.stdout):
1828 """
1829 Generate non-version specific duplication routines for each object type
1830 """
1831
1832 for cls in of_g.standard_class_order:
1833 out.write("""
1834%(cls)s_t *
1835%(cls)s_dup(
1836 %(cls)s_t *src)
1837{
1838""" % dict(cls=cls))
1839 for version in of_g.of_version_range:
1840 if not loxi_utils.class_in_version(cls, version):
1841 continue
1842 hdr = "header." if cls in type_maps.inheritance_map else ""
1843
1844 ver_name = loxi_utils.version_to_name(version)
1845 out.write("""
1846 if (src->%(hdr)sversion == %(ver_name)s) {
1847 return %(cls)s_%(ver_name)s_dup(src);
1848 }
1849""" % dict(cls=cls, ver_name=ver_name, hdr=hdr))
1850
1851 out.write("""
1852 /* Class not supported in given version */
1853 return NULL;
1854}
1855""")
1856
1857def dup_c_gen(out, name):
1858 """
1859 Generate the C file for duplication functions
1860 """
1861 loxi_utils.gen_c_copy_license(out)
1862 out.write("""\
1863/*
1864 * Duplication functions for all OF objects
1865 *
1866 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1867 *
1868 * These are test functions for exercising accessors. You can call
1869 * of_object_dup for an efficient duplication.
1870 */
1871
1872#define DISABLE_WARN_UNUSED_RESULT
1873#include "loci_log.h"
1874#include <locitest/of_dup.h>
1875
1876""")
1877
1878 gen_version_dup(out)
1879 gen_dup(out)
1880
1881
1882def dup_h_gen(out, name):
1883 """
1884 Generate the header file for duplication functions
1885 """
1886
1887 loxi_utils.gen_c_copy_license(out)
1888 out.write("""
1889/*
1890 * Duplication function header file
1891 *
1892 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1893 */
1894
1895#if !defined(_OF_DUP_H_)
1896#define _OF_DUP_H_
1897
1898#include <loci/loci.h>
1899""")
1900
1901 for cls in of_g.standard_class_order:
1902 out.write("""
1903extern %(cls)s_t *
1904 %(cls)s_dup(
1905 %(cls)s_t *src);
1906""" % dict(cls=cls))
1907
1908 for version in of_g.of_version_range:
1909 for cls in of_g.standard_class_order:
1910 if not loxi_utils.class_in_version(cls, version):
1911 continue
1912 ver_name = loxi_utils.version_to_name(version)
1913 out.write("""
1914extern %(cls)s_t *
1915 %(cls)s_%(ver_name)s_dup(
1916 %(cls)s_t *src);
1917""" % dict(cls=cls, ver_name=ver_name))
1918
1919 out.write("\n#endif /* _OF_DUP_H_ */\n")
1920
1921def gen_log_test(out):
1922 """
1923 Generate test for obj log calls
1924
1925 Define a trivial handler for object logging; call all obj log fns
1926 """
1927 out.write("""
1928
1929/**
1930 * Test object dump functions
1931 */
1932
1933int
1934test_dump_objs(void)
1935{
1936 of_object_t *obj;
1937
1938 FILE *out = fopen("/dev/null", "w");
1939
1940 /* Call each obj dump function */
1941""")
1942 for version in of_g.of_version_range:
1943 for j, cls in enumerate(of_g.all_class_order):
1944 if not loxi_utils.class_in_version(cls, version):
1945 continue
1946 if cls in type_maps.inheritance_map:
1947 continue
1948 out.write("""
1949 obj = (of_object_t *)%(cls)s_new(%(version)s);
1950 of_object_dump((loci_writer_f)fprintf, out, obj);
1951 of_object_delete(obj);
1952""" % dict(cls=cls, version=of_g.of_version_wire2name[version]))
Andreas Wundsam53256162013-05-02 14:05:53 -07001953
Rich Lanea06d0c32013-03-25 08:52:03 -07001954 out.write("""
1955 fclose(out);
1956 return TEST_PASS;
1957}
1958""")
1959
1960def gen_ident_tests(out):
1961 """
1962 Generate tests for identifiers
1963
1964 For all idents, instantiate, test version supported macros
1965 For flags, set it, test it, clear it, test it.
1966 """
1967 out.write("""
1968/**
1969 * Test cases for all flag accessor macros
1970 * These only test self consistency (and that they compile)
1971 */
1972int
1973test_ident_macros(void)
1974{
1975 int value __attribute__((unused));
1976 uint32_t flags;
1977
1978""")
1979
1980 for ident, info in of_g.identifiers.items():
1981 if not identifiers.defined_versions_agree(of_g.identifiers,
1982 of_g.target_version_list,
1983 ident):
1984 # @fixme
1985 continue
1986 out.write(" value = %s;\n" % ident)
1987 for version in of_g.target_version_list:
1988 if version in info["values_by_version"].keys():
1989 out.write(" TEST_ASSERT(%s_SUPPORTED(%s));\n" %
1990 (ident, of_g.of_version_wire2name[version]))
1991 else:
1992 out.write(" TEST_ASSERT(!%s_SUPPORTED(%s));\n" %
1993 (ident, of_g.of_version_wire2name[version]))
1994 if flags.ident_is_flag(ident):
1995 # Grab first supported version
1996 for version in info["values_by_version"]:
1997 break
1998 out.write("""
1999 flags = 0;
2000 %(ident)s_SET(flags, %(ver_name)s);
2001 TEST_ASSERT(flags == %(ident)s_BY_VERSION(%(ver_name)s));
2002 TEST_ASSERT(%(ident)s_TEST(flags, %(ver_name)s));
2003 %(ident)s_CLEAR(flags, %(ver_name)s);
2004 TEST_ASSERT(flags == 0);
2005 TEST_ASSERT(!%(ident)s_TEST(flags, %(ver_name)s));
2006""" % dict(ident=ident, ver_name=of_g.of_version_wire2name[version]))
2007
2008 out.write("""
2009 return TEST_PASS;
2010}
2011""")
2012
Rich Laneccae0312013-07-21 23:34:13 -07002013def gen_datafiles_tests(out, name):
2014 tests = []
2015 for filename in test_data.list_files():
2016 data = test_data.read(filename)
2017 if not 'c' in data:
2018 continue
2019 name = filename[:-5].replace("/", "_")
2020 tests.append(dict(name=name,
2021 filename=filename,
2022 c=data['c'],
2023 binary=data['binary']))
2024
2025 util.render_template(out, "test_data.c", tests=tests)