blob: 5b74649947cbcafb7abd1311e20ad25da75c9d14 [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))
546 if not type_maps.class_is_virtual(cls):
547 out.write("""
548 if (obj->wire_length_get != NULL) {
549 int length;
550
551 obj->wire_length_get((of_object_t *)obj, &length);
552 TEST_ASSERT(length == %(length)d);
553 }
554
555 /* Set up incrementing values for scalar members */
556 %(cls)s_%(v_name)s_populate_scalars(obj, 1);
557
558 /* Check values just set */
559 TEST_ASSERT(%(cls)s_%(v_name)s_check_scalars(obj, 1) != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -0700560""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700561 v_name=v_name, length=length, version=version))
562
563 out.write("""
564 %(cls)s_delete(obj);
565
566 /* To do: Check memory */
567 return TEST_PASS;
568}
569""" % dict(cls=cls))
570
571# Get the members and list of scalar types for members of a given class
572def scalar_member_types_get(cls, version):
573 member_types = []
574
575 if not version in of_g.unified[cls]:
576 return ([], [])
577
578 if "use_version" in of_g.unified[cls][version]:
579 v = of_g.unified[cls][version]["use_version"]
580 members = of_g.unified[cls][v]["members"]
581 else:
582 members = of_g.unified[cls][version]["members"]
583 # Accumulate variables that are supported
584 for member in members:
585 m_type = member["m_type"]
586 m_name = member["name"]
Andreas Wundsam53256162013-05-02 14:05:53 -0700587 if (not loxi_utils.type_is_scalar(m_type) or
Rich Lanea06d0c32013-03-25 08:52:03 -0700588 ignore_member(cls, version, m_name, m_type)):
589 continue
590 if not m_type in member_types:
591 member_types.append(m_type)
592
593 return (members, member_types)
594
595def scalar_funs_instance(out, cls, version, members, member_types):
596 """
597 Generate one instance of scalar set/check functions
598 """
599 out.write("""
600/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700601 * Populate the scalar values in obj of type %(cls)s,
602 * version %(v_name)s
Rich Lanea06d0c32013-03-25 08:52:03 -0700603 * @param obj Pointer to an object to populate
604 * @param value The seed value to use in populating the object
605 * @returns The value after increments for this object's values
606 */
607int %(cls)s_%(v_name)s_populate_scalars(
608 %(cls)s_t *obj, int value) {
609""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
610 # Declare string types
611 for t in member_types:
612 out.write(" %s %s;\n" % (t, var_name_map(t)))
613 for member in members:
614 m_type = member["m_type"]
615 m_name = member["name"]
616 if (not loxi_utils.type_is_scalar(m_type) or
617 ignore_member(cls, version, m_name, m_type)):
618 continue
619 v_name = var_name_map(m_type);
620 out.write("""
621 VAR_%(u_type)s_INIT(%(v_name)s, value);
622 %(cls)s_%(m_name)s_set(obj, %(v_name)s);
623 value += 1;
624""" % dict(cls=cls, m_name=m_name, u_type=m_type.upper(), v_name=v_name))
625 out.write("""
626 return value;
627}
628""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700629
Rich Lanea06d0c32013-03-25 08:52:03 -0700630 out.write("""
631/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700632 * Check scalar values in obj of type %(cls)s,
633 * version %(v_name)s
Rich Lanea06d0c32013-03-25 08:52:03 -0700634 * @param obj Pointer to an object to check
635 * @param value Starting value for checking
636 * @returns The value after increments for this object's values
637 */
638int %(cls)s_%(v_name)s_check_scalars(
639 %(cls)s_t *obj, int value) {
640""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
641
642 for t in member_types:
643 out.write(" %s %s;\n" % (t, var_name_map(t)))
644 for member in members:
645 m_type = member["m_type"]
646 m_name = member["name"]
647 if (not loxi_utils.type_is_scalar(m_type) or
648 ignore_member(cls, version, m_name, m_type)):
649 continue
650 v_name = var_name_map(m_type);
651 out.write("""
652 %(cls)s_%(m_name)s_get(obj, &%(v_name)s);
653 TEST_ASSERT(VAR_%(u_type)s_CHECK(%(v_name)s, value));
654 value += 1;
655""" % dict(cls=cls, m_name=m_name, u_type=m_type.upper(), v_name=v_name))
656
657 out.write("""
658 return value;
659}
660
661""")
662
663def gen_scalar_set_check_funs(out):
664 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700665 For each object class with scalar members, generate functions that
Rich Lanea06d0c32013-03-25 08:52:03 -0700666 set and check their values
667 """
668 for version in of_g.of_version_range:
669 for cls in of_g.standard_class_order:
670 (members, member_types) = scalar_member_types_get(cls, version)
671 scalar_funs_instance(out, cls, version, members, member_types)
672
673
674# Helper function to set up a subclass instance for a test
675def setup_instance(out, cls, subcls, instance, v_name, inst_len, version):
676 base_type = loxi_utils.list_to_entry_type(cls)
677 setup_template = """
678 %(subcls)s_init(%(inst)s, %(v_name)s, -1, 1);
Andreas Wundsam53256162013-05-02 14:05:53 -0700679 %(cls)s_append_bind(list,
Rich Lanea06d0c32013-03-25 08:52:03 -0700680 (%(base_type)s_t *)%(inst)s);
681 value = %(subcls)s_%(v_name)s_populate(
682 %(inst)s, value);
683 cur_len += %(inst)s->length;
684 TEST_ASSERT(list->length == cur_len);
685"""
686 out.write("""
687 /* Append two instances of type %s */
688""" % subcls)
689 for i in range(2):
690 out.write(setup_template %
Andreas Wundsam53256162013-05-02 14:05:53 -0700691 dict(inst=instance, subcls=subcls, v_name=v_name,
692 base_type=base_type, cls=cls, inst_len=inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700693 version=version))
694
695def check_instance(out, cls, subcls, instance, v_name, inst_len, version, last):
696 check_template = ""
697 if inst_len >= 0:
698 check_template = """
699 TEST_ASSERT(%(inst)s->length == %(inst_len)d);
700 if (%(inst)s->wire_length_get != NULL) {
701 int length;
702
703 %(inst)s->wire_length_get(
704 (of_object_t *)&elt, &length);
705 TEST_ASSERT(length == %(inst_len)d);
706 }
707"""
708 check_template += """
709 TEST_ASSERT(%(inst)s->object_id == %(elt_name)s);
710 value = %(subcls)s_%(v_name)s_check(
711 %(inst)s, value);
712 TEST_ASSERT(value != 0);
713"""
714 out.write("\n /* Check two instances of type %s */" % instance)
715
Andreas Wundsam53256162013-05-02 14:05:53 -0700716 out.write(check_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700717 dict(elt_name=loxi_utils.enum_name(subcls), inst_len=inst_len,
718 inst=instance, subcls=subcls,
719 v_name=loxi_utils.version_to_name(version)))
720 out.write("""\
721 TEST_OK(%(cls)s_next(list, &elt));
722""" % dict(cls=cls))
723
Andreas Wundsam53256162013-05-02 14:05:53 -0700724 out.write(check_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700725 dict(elt_name=loxi_utils.enum_name(subcls), inst_len=inst_len,
726 inst=instance, subcls=subcls,
727 v_name=loxi_utils.version_to_name(version)))
728 if last:
729 out.write("""\
730 TEST_ASSERT(%(cls)s_next(list, &elt) == OF_ERROR_RANGE);
731""" % dict(cls=cls))
732 else:
733 out.write("""\
734 TEST_OK(%(cls)s_next(list, &elt));
735""" % dict(cls=cls))
736
737def setup_list_fn(out, version, cls):
738 """
739 Generate a helper function that populates a list with two
740 of each type of subclass it supports
741 """
742 out.write("""
743/**
744 * Set up a list of type %(cls)s with two of each type of subclass
745 */
746int
747list_setup_%(cls)s_%(v_name)s(
748 %(cls)s_t *list, int value)
749{
750""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
751 base_type = loxi_utils.list_to_entry_type(cls)
752 out.write("""
753 %(base_type)s_t elt;
754 int cur_len = 0;
755""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -0700756
Rich Lanea06d0c32013-03-25 08:52:03 -0700757 sub_classes = type_maps.sub_class_map(base_type, version)
Rich Lane1bd2bae2013-07-09 10:06:07 -0700758 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 -0700759 v_name = loxi_utils.version_to_name(version)
760
761 if len(sub_classes) == 0:
762 out.write(" /* No subclasses for %s */\n"% base_type)
763 out.write(" %s_t *elt_p;\n" % base_type)
764 out.write("\n elt_p = &elt;\n")
765 else:
766 out.write(" /* Declare pointers for each subclass */\n")
767 for instance, subcls in sub_classes:
768 out.write(" %s_t *%s;\n" % (subcls, instance))
769 out.write("\n /* Instantiate pointers for each subclass */\n")
770 for instance, subcls in sub_classes:
771 out.write(" %s = &elt.%s;\n" % (instance, instance))
772
773 if len(sub_classes) == 0: # No inheritance case
774 inst_len = loxi_utils.base_type_to_length(base_type, version)
775 setup_instance(out, cls, base_type, "elt_p", v_name, inst_len, version)
776 else:
777 for instance, subcls in sub_classes:
778 inst_len = of_g.base_length[(subcls, version)]
779 setup_instance(out, cls, subcls, instance, v_name, inst_len, version)
780 out.write("""
781
782 return value;
783}
784""")
785
786def check_list_fn(out, version, cls):
787 """
788 Generate a helper function that checks a list populated by above fn
789 """
790 out.write("""
791/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700792 * Check a list of type %(cls)s generated by
Rich Lanea06d0c32013-03-25 08:52:03 -0700793 * list_setup_%(cls)s_%(v_name)s
794 */
795int
796list_check_%(cls)s_%(v_name)s(
797 %(cls)s_t *list, int value)
798{
799""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
800 base_type = loxi_utils.list_to_entry_type(cls)
801 out.write("""
802 %(base_type)s_t elt;
803""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -0700804
Rich Lanea06d0c32013-03-25 08:52:03 -0700805 sub_classes = type_maps.sub_class_map(base_type, version)
Rich Lane1bd2bae2013-07-09 10:06:07 -0700806 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 -0700807 v_name = loxi_utils.version_to_name(version)
808
809 if len(sub_classes) == 0:
810 out.write(" /* No subclasses for %s */\n"% base_type)
811 out.write(" %s_t *elt_p;\n" % base_type)
812 out.write("\n elt_p = &elt;\n")
813 else:
814 out.write(" /* Declare pointers for each subclass */\n")
815 for instance, subcls in sub_classes:
816 out.write(" %s_t *%s;\n" % (subcls, instance))
817 out.write("\n /* Instantiate pointers for each subclass */\n")
818 for instance, subcls in sub_classes:
819 out.write(" %s = &elt.%s;\n" % (instance, instance))
820
821 out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
822 if len(sub_classes) == 0: # No inheritance case
823 if loxi_utils.class_is_var_len(base_type, version):
824 inst_len = -1
825 else:
826 inst_len = loxi_utils.base_type_to_length(base_type, version)
Andreas Wundsam53256162013-05-02 14:05:53 -0700827 check_instance(out, cls, base_type, "elt_p", v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700828 version, True)
829 else:
830 count = 0
831 for instance, subcls in sub_classes:
832 count += 1
833 if loxi_utils.class_is_var_len(subcls, version):
834 inst_len = -1
835 else:
836 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -0700837 check_instance(out, cls, subcls, instance, v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700838 version, count==len(sub_classes))
839
840 out.write("""
841 return value;
842}
843""" % dict(base_type=base_type))
844
845def gen_list_set_check_funs(out):
846 for version in of_g.of_version_range:
847 for cls in of_g.ordered_list_objects:
848 if cls in type_maps.inheritance_map:
849 continue
850
851 if version in of_g.unified[cls]:
852 setup_list_fn(out, version, cls)
853 check_list_fn(out, version, cls)
854
855# Maybe: Get a map from list class to parent, mem_name of container
856
857def list_test(out, version, cls):
858 out.write("""
859static int
860test_%(cls)s_%(v_name)s(void)
861{
862""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
863 base_type = loxi_utils.list_to_entry_type(cls)
864
865 out.write(""" %(cls)s_t *list;
866 int value = 1;
867""" % dict(cls=cls, base_type=base_type))
868
869 out.write("""
870 list = %(cls)s_new(%(v_name)s);
871 TEST_ASSERT(list != NULL);
872 TEST_ASSERT(list->version == %(v_name)s);
873 TEST_ASSERT(list->length == 0);
874 TEST_ASSERT(list->parent == NULL);
875 TEST_ASSERT(list->object_id == %(enum_cls)s);
876
877 value = list_setup_%(cls)s_%(v_name)s(list, value);
878 TEST_ASSERT(value != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -0700879""" % dict(cls=cls, base_type=base_type, v_name=loxi_utils.version_to_name(version),
Rich Lanea06d0c32013-03-25 08:52:03 -0700880 enum_cls=loxi_utils.enum_name(cls)))
881
882 out.write("""
883 /* Now check values */
884 value = 1;
885 value = list_check_%(cls)s_%(v_name)s(list, value);
886 TEST_ASSERT(value != 0);
887""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
888
889 out.write("""
890 %(cls)s_delete(list);
891
892 return TEST_PASS;
893}
894""" % dict(cls=cls))
895
896def gen_list_test(out, name):
897 """
898 Generate base line test cases for lists
899 @param out The file handle to write to
900 """
901
902 loxi_utils.gen_c_copy_license(out)
903 out.write("""
904/**
905 *
906 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
907 *
908 * Message-scalar tests for all versions
909 */
910
911#include <locitest/test_common.h>
912""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700913
Rich Lanea06d0c32013-03-25 08:52:03 -0700914 for version in of_g.of_version_range:
915 v_name = loxi_utils.version_to_name(version)
916 out.write("""
917/**
918 * Baseline list tests for version %s
919 */
920""" % v_name)
921 for cls in of_g.ordered_list_objects:
922 if cls in type_maps.inheritance_map:
923 continue
924 if version in of_g.unified[cls]:
925 list_test(out, version, cls)
926
927 out.write("""
928int
929run_list_tests(void)
930{
931""")
932 for version in of_g.of_version_range:
933 v_name = loxi_utils.version_to_name(version)
934 for cls in of_g.ordered_list_objects:
935 if cls in type_maps.inheritance_map:
936 continue
937 if version in of_g.unified[cls]:
938 test_name = "%s_%s" % (cls, v_name)
939 out.write(" RUN_TEST(%s);\n" % test_name)
940
941 out.write("\n return TEST_PASS;\n}\n");
942
943def gen_match_test(out, name):
944 """
945 Generate baseline tests for match functions
946 """
947
948 loxi_utils.gen_c_copy_license(out)
949 out.write("""\
950/**
951 *
952 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
953 *
954 * Message-scalar tests for all versions
955 * @fixme These are mostly hard coded now.
956 */
957
958#include <locitest/test_common.h>
959
960static int
961test_match_1(void)
962{
963 of_match_v1_t *m_v1;
964 of_match_v2_t *m_v2;
965 of_match_v3_t *m_v3;
966 of_match_v4_t *m_v4;
967 of_match_t match;
968 int value = 1;
969 int idx;
970 uint32_t exp_value;
971
972 /* Verify default values for ip mask map */
973 for (idx = 0; idx < OF_IP_MASK_MAP_COUNT; idx++) {
974 exp_value = (idx < 32) ? ~((1 << idx) - 1) : 0;
975 TEST_ASSERT(of_ip_index_to_mask(idx) == exp_value);
976 if (idx < 32) {
977 TEST_ASSERT(of_ip_mask_to_index(exp_value) == idx);
978 }
979 }
980
981 TEST_ASSERT(of_ip_mask_map_set(17, 0xabcdef00) == OF_ERROR_NONE);
982 TEST_ASSERT(of_ip_mask_to_index(0xabcdef00) == 17);
983 TEST_ASSERT(of_ip_index_to_mask(17) == 0xabcdef00);
984
985 TEST_ASSERT(of_ip_mask_map_set(62, 0xabcdefff) == OF_ERROR_NONE);
986 TEST_ASSERT(of_ip_mask_to_index(0xabcdefff) == 62);
987 TEST_ASSERT(of_ip_index_to_mask(62) == 0xabcdefff);
988
989 /* Test re-init */
990 of_ip_mask_map_init();
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
1000 for version in of_g.of_version_range:
1001 out.write("""
1002 /* Create/populate/convert and delete for version %(v_name)s */
1003 m_v%(version)d = of_match_v%(version)d_new(%(v_name)s);
1004 TEST_ASSERT(m_v%(version)d != NULL);
1005 TEST_ASSERT((value = of_match_populate(&match, %(v_name)s, value)) > 0);
1006 TEST_OK(of_match_to_wire_match_v%(version)d(&match, m_v%(version)d));
1007 of_match_v%(version)d_delete(m_v%(version)d);
1008""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1009
1010 out.write("""
1011 return TEST_PASS;
1012}
1013""")
1014
1015 out.write("""
1016static int
1017test_match_2(void)
1018{
1019 of_match_v1_t *m_v1;
1020 of_match_v2_t *m_v2;
1021 of_match_v3_t *m_v3;
1022 of_match_v3_t *m_v4;
1023 of_match_t match1;
1024 of_match_t match2;
1025 int value = 1;
1026""")
1027
1028 for version in of_g.of_version_range:
1029 out.write("""
1030 TEST_ASSERT((value = of_match_populate(&match1, %(v_name)s, value)) > 0);
1031 m_v%(version)d = of_match_v%(version)d_new(%(v_name)s);
1032 TEST_ASSERT(m_v%(version)d != NULL);
1033 TEST_OK(of_match_to_wire_match_v%(version)d(&match1, m_v%(version)d));
1034 TEST_OK(of_match_v%(version)d_to_match(m_v%(version)d, &match2));
1035 TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
1036 of_match_v%(version)d_delete(m_v%(version)d);
1037""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1038
1039 out.write("""
1040 return TEST_PASS;
1041}
1042""")
1043
1044 out.write("""
1045static int
1046test_match_3(void)
1047{
1048 of_match_t match1;
1049 of_match_t match2;
1050 int value = 1;
1051 of_octets_t octets;
1052""")
1053 for version in of_g.of_version_range:
1054 out.write("""
1055 /* Serialize to version %(v_name)s */
1056 TEST_ASSERT((value = of_match_populate(&match1, %(v_name)s, value)) > 0);
Andreas Wundsam53256162013-05-02 14:05:53 -07001057 TEST_ASSERT(of_match_serialize(%(v_name)s, &match1, &octets) ==
Rich Lanea06d0c32013-03-25 08:52:03 -07001058 OF_ERROR_NONE);
Andreas Wundsam53256162013-05-02 14:05:53 -07001059 TEST_ASSERT(of_match_deserialize(%(v_name)s, &match2, &octets) ==
Rich Lanea06d0c32013-03-25 08:52:03 -07001060 OF_ERROR_NONE);
1061 TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
1062 FREE(octets.data);
1063""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1064
1065 out.write("""
1066 return TEST_PASS;
1067}
1068""")
1069
1070 out.write("""
1071int run_match_tests(void)
1072{
1073 RUN_TEST(match_1);
1074 RUN_TEST(match_2);
1075 RUN_TEST(match_3);
1076 RUN_TEST(match_utils);
1077
1078 return TEST_PASS;
1079}
1080""")
1081
1082def gen_msg_test(out, name):
1083 loxi_utils.gen_c_copy_license(out)
1084 out.write("""
1085/**
1086 *
1087 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1088 *
1089 * Message-scalar tests for all versions
1090 */
1091
1092#include <locitest/test_common.h>
1093""")
1094 for version in of_g.of_version_range:
1095 for cls in of_g.ordered_messages:
1096 if not (cls, version) in of_g.base_length:
1097 continue
Rich Lane488b3c52013-06-21 18:11:02 -07001098 if type_maps.class_is_virtual(cls):
1099 continue
Rich Lanef70be942013-07-18 13:33:14 -07001100 bytes = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
Rich Lanea06d0c32013-03-25 08:52:03 -07001101 out.write("""
1102static int
1103test_%(cls)s_create_%(v_name)s(void)
1104{
1105 %(cls)s_t *obj;
1106 uint8_t *msg_buf;
1107 int value;
1108 int len;
1109
1110 obj = %(cls)s_new(%(v_name)s);
1111 TEST_ASSERT(obj != NULL);
1112 TEST_ASSERT(obj->version == %(v_name)s);
1113 TEST_ASSERT(obj->length == %(bytes)d);
1114 TEST_ASSERT(obj->parent == NULL);
1115 TEST_ASSERT(obj->object_id == %(enum)s);
1116
1117 /* Set up incrementing values for scalar members */
1118 value = %(cls)s_%(v_name)s_populate_scalars(obj, 1);
1119 TEST_ASSERT(value != 0);
1120
1121 /* Grab the underlying buffer from the message */
1122 len = obj->length;
1123 of_object_wire_buffer_steal((of_object_t *)obj, &msg_buf);
1124 TEST_ASSERT(msg_buf != NULL);
1125 %(cls)s_delete(obj);
1126 /* TODO: */
1127 TEST_ASSERT(of_message_to_object_id(msg_buf, len) == %(enum)s);
1128 obj = %(cls)s_new_from_message(OF_BUFFER_TO_MESSAGE(msg_buf));
1129
1130 TEST_ASSERT(obj != NULL);
1131
1132 /* @fixme Set up all message objects (recursively?) */
1133
1134 value = %(cls)s_%(v_name)s_check_scalars(obj, 1);
1135 TEST_ASSERT(value != 0);
1136
1137 %(cls)s_delete(obj);
1138
1139 return TEST_PASS;
1140}
1141""" % dict(cls=cls, version=version, enum=loxi_utils.enum_name(cls),
1142 v_name=loxi_utils.version_to_name(version), bytes=bytes))
1143
1144 out.write("""
1145int
1146run_message_tests(void)
1147{
1148""")
1149 for version in of_g.of_version_range:
1150 for cls in of_g.ordered_messages:
1151 if not (cls, version) in of_g.base_length:
1152 continue
Rich Lane488b3c52013-06-21 18:11:02 -07001153 if type_maps.class_is_virtual(cls):
1154 continue
Rich Lanea06d0c32013-03-25 08:52:03 -07001155 test_name = "%s_create_%s" % (cls, loxi_utils.version_to_name(version))
1156 out.write(" RUN_TEST(%s);\n" % test_name)
1157
1158 out.write("\n return TEST_PASS;\n}\n");
Andreas Wundsam53256162013-05-02 14:05:53 -07001159
Rich Lanea06d0c32013-03-25 08:52:03 -07001160
1161def gen_list_setup_check(out, cls, version):
1162 """
1163 Generate functions that populate and check a list with two
1164 of each type of subclass it supports
1165 """
1166 out.write("""
1167/**
1168 * Populate a list of type %(cls)s with two of each type of subclass
1169 * @param list Pointer to the list to be populated
1170 * @param value The seed value to use in populating the list
1171 * @returns The value after increments for this object's values
1172 */
1173int
1174%(cls)s_%(v_name)s_populate(
1175 %(cls)s_t *list, int value)
1176{
1177""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1178 base_type = loxi_utils.list_to_entry_type(cls)
1179 out.write("""
1180 %(base_type)s_t elt;
1181 int cur_len = 0;
1182""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -07001183
Rich Lanea06d0c32013-03-25 08:52:03 -07001184 sub_classes = type_maps.sub_class_map(base_type, version)
Rich Lane1bd2bae2013-07-09 10:06:07 -07001185 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 -07001186 v_name = loxi_utils.version_to_name(version)
1187
1188 if len(sub_classes) == 0:
1189 out.write(" /* No subclasses for %s */\n"% base_type)
1190 out.write(" %s_t *elt_p;\n" % base_type)
1191 out.write("\n elt_p = &elt;\n")
1192 else:
1193 out.write(" /* Declare pointers for each subclass */\n")
1194 for instance, subcls in sub_classes:
1195 out.write(" %s_t *%s;\n" % (subcls, instance))
1196 out.write("\n /* Instantiate pointers for each subclass */\n")
1197 for instance, subcls in sub_classes:
1198 out.write(" %s = &elt.%s;\n" % (instance, instance))
1199
1200# if type_maps.class_is_virtual(base_type):
1201# out.write("""\
1202# TEST_OK(%(base_type)s_header_init(
1203# (%(base_type)s_header_t *)&elt, %(v_name)s, -1, 1));
1204# """ % dict(base_type=base_type, v_name=loxi_utils.version_to_name(version)))
1205# else:
1206# out.write("""\
1207# TEST_OK(%(base_type)s_init(&elt, %(v_name)s, -1, 1));
1208# """ % dict(base_type=base_type, v_name=loxi_utils.version_to_name(version)))
1209
1210 if len(sub_classes) == 0: # No inheritance case
1211 inst_len = loxi_utils.base_type_to_length(base_type, version)
1212 setup_instance(out, cls, base_type, "elt_p", v_name, inst_len, version)
1213 else:
1214 for instance, subcls in sub_classes:
1215 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -07001216 setup_instance(out, cls, subcls, instance, v_name,
Rich Lanea06d0c32013-03-25 08:52:03 -07001217 inst_len, version)
1218 out.write("""
1219 return value;
1220}
1221""")
1222 out.write("""
1223/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001224 * Check a list of type %(cls)s generated by
Rich Lanea06d0c32013-03-25 08:52:03 -07001225 * %(cls)s_%(v_name)s_populate
1226 * @param list Pointer to the list that was populated
1227 * @param value Starting value for checking
1228 * @returns The value after increments for this object's values
1229 */
1230int
1231%(cls)s_%(v_name)s_check(
1232 %(cls)s_t *list, int value)
1233{
1234""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1235 base_type = loxi_utils.list_to_entry_type(cls)
1236 out.write("""
1237 %(base_type)s_t elt;
1238 int count = 0;
1239 int rv;
1240""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -07001241
Rich Lanea06d0c32013-03-25 08:52:03 -07001242
1243 sub_classes = type_maps.sub_class_map(base_type, version)
Rich Lane1bd2bae2013-07-09 10:06:07 -07001244 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 -07001245 v_name = loxi_utils.version_to_name(version)
1246
1247 if len(sub_classes) == 0:
1248 entry_count = 2
1249 out.write(" /* No subclasses for %s */\n"% base_type)
1250 out.write(" %s_t *elt_p;\n" % base_type)
1251 out.write("\n elt_p = &elt;\n")
1252 else:
1253 entry_count = 2 * len(sub_classes) # Two of each type appended
1254 out.write(" /* Declare pointers for each subclass */\n")
1255 for instance, subcls in sub_classes:
1256 out.write(" %s_t *%s;\n" % (subcls, instance))
1257 out.write("\n /* Instantiate pointers for each subclass */\n")
1258 for instance, subcls in sub_classes:
1259 out.write(" %s = &elt.%s;\n" % (instance, instance))
1260
1261 out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
1262 if len(sub_classes) == 0: # No inheritance case
1263 if loxi_utils.class_is_var_len(base_type, version):
1264 inst_len = -1
1265 else:
1266 inst_len = loxi_utils.base_type_to_length(base_type, version)
Andreas Wundsam53256162013-05-02 14:05:53 -07001267 check_instance(out, cls, base_type, "elt_p", v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -07001268 version, True)
1269 else:
1270 count = 0
1271 for instance, subcls in sub_classes:
1272 count += 1
1273 if loxi_utils.class_is_var_len(subcls, version):
1274 inst_len = -1
1275 else:
1276 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -07001277 check_instance(out, cls, subcls, instance, v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -07001278 version, count==len(sub_classes))
1279 out.write("""
1280""" % dict(base_type=base_type))
1281
1282 out.write("""
1283 /* Do an iterate to test the iterator */
1284 %(u_cls)s_ITER(list, &elt, rv) {
1285 count += 1;
1286 }
1287
1288 TEST_ASSERT(rv == OF_ERROR_RANGE);
1289 TEST_ASSERT(count == %(entry_count)d);
1290
1291 /* We shoehorn a test of the dup functions here */
1292 {
1293 %(cls)s_t *dup;
1294
1295 TEST_ASSERT((dup = %(cls)s_dup(list)) != NULL);
1296 TEST_ASSERT(dup->length == list->length);
1297 TEST_ASSERT(dup->object_id == list->object_id);
1298 TEST_ASSERT(dup->version == list->version);
1299 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1300 OF_OBJECT_BUFFER_INDEX(list, 0), list->length) == 0);
1301 of_object_delete((of_object_t *)dup);
1302
1303 /* And now for the generic dup function */
1304 TEST_ASSERT((dup = (%(cls)s_t *)
1305 of_object_dup(list)) != NULL);
1306 TEST_ASSERT(dup->length == list->length);
1307 TEST_ASSERT(dup->object_id == list->object_id);
1308 TEST_ASSERT(dup->version == list->version);
1309 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1310 OF_OBJECT_BUFFER_INDEX(list, 0), list->length) == 0);
1311 of_object_delete((of_object_t *)dup);
1312 }
1313
1314 return value;
1315}
1316""" % dict(cls=cls, u_cls=cls.upper(), entry_count=entry_count))
1317
1318
1319def gen_class_setup_check(out, cls, version):
1320 out.write("""
1321/**
1322 * Populate all members of an object of type %(cls)s
1323 * with incrementing values
1324 * @param obj Pointer to an object to populate
1325 * @param value The seed value to use in populating the object
1326 * @returns The value after increments for this object's values
1327 */
1328
1329int
1330%(cls)s_%(v_name)s_populate(
1331 %(cls)s_t *obj, int value)
1332{
1333""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1334 members, member_types = loxi_utils.all_member_types_get(cls, version)
1335 for m_type in member_types:
1336 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1337 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1338 else:
1339 out.write(" %s *%s;\n" % (m_type, var_name_map(m_type)))
1340 out.write("""
1341 /* Run thru accessors after new to ensure okay */
1342""")
1343 for member in members:
1344 m_type = member["m_type"]
1345 m_name = member["name"]
1346 if loxi_utils.skip_member_name(m_name):
1347 continue
1348 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1349 out.write("""\
1350 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1351""" % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
1352 else:
1353 sub_cls = m_type[:-2] # Trim _t
1354 out.write("""\
1355 {
1356 %(sub_cls)s_t sub_cls;
1357
1358 /* Test bind */
1359 %(cls)s_%(m_name)s_bind(obj, &sub_cls);
1360 }
Andreas Wundsam53256162013-05-02 14:05:53 -07001361""" % dict(var_name=var_name_map(m_type), cls=cls,
Rich Lanea06d0c32013-03-25 08:52:03 -07001362 m_name=m_name, sub_cls=sub_cls,
1363 v_name=loxi_utils.version_to_name(version)))
1364
1365 out.write("""
1366 value = %(cls)s_%(v_name)s_populate_scalars(
1367 obj, value);
1368 TEST_ASSERT(value != 0);
1369""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1370
1371 for member in members:
1372 m_type = member["m_type"]
1373 m_name = member["name"]
1374 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1375 continue
1376 if loxi_utils.skip_member_name(m_name):
1377 continue
1378 if m_type == "of_match_t":
1379 out.write("""\
1380 value = of_match_populate(&%(var_name)s, %(v_name)s, value);
1381 TEST_ASSERT(value != 0);
1382 %(cls)s_%(m_name)s_set(
1383 obj, &%(var_name)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001384""" % dict(cls=cls, var_name=var_name_map(m_type),
Rich Lanea06d0c32013-03-25 08:52:03 -07001385 m_name=m_name, v_name=loxi_utils.version_to_name(version)))
1386 elif m_type == "of_octets_t":
1387 out.write("""\
1388 value = of_octets_populate(&%(var_name)s, value);
1389 TEST_ASSERT(value != 0);
1390 %(cls)s_%(m_name)s_set(
1391 obj, &%(var_name)s);
1392 if (octets.bytes) {
1393 FREE(octets.data);
1394 }
1395""" % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
1396 else:
1397 sub_cls = m_type[:-2] # Trim _t
1398 out.write("""
1399 %(var_name)s = %(sub_cls)s_new(%(v_name)s);
1400 TEST_ASSERT(%(var_name)s != NULL);
1401 value = %(sub_cls)s_%(v_name)s_populate(
1402 %(var_name)s, value);
1403 TEST_ASSERT(value != 0);
1404 %(cls)s_%(m_name)s_set(
1405 obj, %(var_name)s);
1406 %(sub_cls)s_delete(%(var_name)s);
1407""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, m_type=m_type,
1408 var_name=var_name_map(m_type),
1409 v_name=loxi_utils.version_to_name(version)))
1410
1411 out.write("""
1412 return value;
1413}
1414""")
1415
1416 out.write("""
1417/**
1418 * Check all members of an object of type %(cls)s
1419 * populated by the above function
1420 * @param obj Pointer to an object to check
1421 * @param value Starting value for checking
1422 * @returns The value after increments for this object's values
1423 */
1424
1425int
1426%(cls)s_%(v_name)s_check(
1427 %(cls)s_t *obj, int value)
1428{
1429""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1430 members, member_types = loxi_utils.all_member_types_get(cls, version)
1431 for m_type in member_types:
1432 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1433 continue
1434 if loxi_utils.type_is_of_object(m_type):
1435 continue
1436 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1437 out.write("""
1438 value = %(cls)s_%(v_name)s_check_scalars(
1439 obj, value);
1440 TEST_ASSERT(value != 0);
1441""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1442
1443 for member in members:
1444 m_type = member["m_type"]
1445 m_name = member["name"]
1446 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1447 continue
1448 if loxi_utils.skip_member_name(m_name):
1449 continue
1450 if m_type == "of_match_t":
1451 out.write("""\
1452 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1453 value = of_match_check(&%(var_name)s, %(v_name)s, value);
1454""" % dict(cls=cls, var_name=var_name_map(m_type), m_name=m_name,
1455 v_name=loxi_utils.version_to_name(version)))
1456 elif m_type == "of_octets_t":
1457 out.write("""\
1458 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1459 value = of_octets_check(&%(var_name)s, value);
1460""" % dict(cls=cls, var_name=var_name_map(m_type), m_name=m_name,
1461 v_name=loxi_utils.version_to_name(version)))
1462 else:
1463 sub_cls = m_type[:-2] # Trim _t
1464 out.write("""
1465 { /* Use get/delete to access on check */
1466 %(m_type)s *%(m_name)s_ptr;
1467
1468 %(m_name)s_ptr = %(cls)s_%(m_name)s_get(obj);
1469 TEST_ASSERT(%(m_name)s_ptr != NULL);
1470 value = %(sub_cls)s_%(v_name)s_check(
1471 %(m_name)s_ptr, value);
1472 TEST_ASSERT(value != 0);
1473 %(sub_cls)s_delete(%(m_name)s_ptr);
1474 }
1475""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, m_type=m_type,
1476 var_name=var_name_map(m_type),
1477 v_name=loxi_utils.version_to_name(version)))
1478
1479 out.write("""
1480 /* We shoehorn a test of the dup functions here */
1481 {
1482 %(cls)s_t *dup;
1483
1484 TEST_ASSERT((dup = %(cls)s_dup(obj)) != NULL);
1485 TEST_ASSERT(dup->length == obj->length);
1486 TEST_ASSERT(dup->object_id == obj->object_id);
1487 TEST_ASSERT(dup->version == obj->version);
1488 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1489 OF_OBJECT_BUFFER_INDEX(obj, 0), obj->length) == 0);
1490 of_object_delete((of_object_t *)dup);
1491
1492 /* And now for the generic dup function */
1493 TEST_ASSERT((dup = (%(cls)s_t *)
1494 of_object_dup(obj)) != NULL);
1495 TEST_ASSERT(dup->length == obj->length);
1496 TEST_ASSERT(dup->object_id == obj->object_id);
1497 TEST_ASSERT(dup->version == obj->version);
1498 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1499 OF_OBJECT_BUFFER_INDEX(obj, 0), obj->length) == 0);
1500 of_object_delete((of_object_t *)dup);
1501 }
1502
1503 return value;
1504}
1505""" % dict(cls=cls))
1506
1507def unified_accessor_test_case(out, cls, version):
1508 """
1509 Generate one test case for the given version and class
1510 """
1511
1512 members, member_types = scalar_member_types_get(cls, version)
Rich Lanef70be942013-07-18 13:33:14 -07001513 length = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
Rich Lanea06d0c32013-03-25 08:52:03 -07001514 v_name = loxi_utils.version_to_name(version)
1515
1516 out.write("""
1517static int
1518test_%(cls)s_%(v_name)s(void)
1519{
1520 %(cls)s_t *obj;
1521 obj = %(cls)s_new(%(v_name)s);
1522 TEST_ASSERT(obj != NULL);
1523 TEST_ASSERT(obj->version == %(v_name)s);
1524 TEST_ASSERT(obj->length == %(length)d);
1525 TEST_ASSERT(obj->parent == NULL);
1526 TEST_ASSERT(obj->object_id == %(u_cls)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001527""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -07001528 v_name=v_name, length=length, version=version))
1529 if (not type_maps.class_is_virtual(cls)) or loxi_utils.class_is_list(cls):
1530 out.write("""
1531 if (obj->wire_length_get != NULL) {
1532 int length;
1533
1534 obj->wire_length_get((of_object_t *)obj, &length);
1535 TEST_ASSERT(length == %(length)d);
1536 }
1537 if (obj->wire_type_get != NULL) {
1538 of_object_id_t obj_id;
1539
1540 obj->wire_type_get((of_object_t *)obj, &obj_id);
1541 TEST_ASSERT(obj_id == %(u_cls)s);
1542 }
1543
1544 /* Set up incrementing values for members */
1545 TEST_ASSERT(%(cls)s_%(v_name)s_populate(
1546 obj, 1) != 0);
1547
1548 /* Check values just set */
1549 TEST_ASSERT(%(cls)s_%(v_name)s_check(
1550 obj, 1) != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -07001551""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -07001552 v_name=v_name, length=length, version=version))
1553
1554 out.write("""
1555 %(cls)s_delete(obj);
1556
1557 /* To do: Check memory */
1558 return TEST_PASS;
1559}
1560""" % dict(cls=cls))
1561
1562
1563def gen_unified_accessor_funs(out):
1564 for version in of_g.of_version_range:
1565 for cls in of_g.standard_class_order:
1566 if not loxi_utils.class_in_version(cls, version):
1567 continue
1568 if cls in type_maps.inheritance_map:
1569 continue
1570 elif loxi_utils.class_is_list(cls):
1571 gen_list_setup_check(out, cls, version)
1572 else:
1573 gen_class_setup_check(out, cls, version)
1574
1575def gen_unified_accessor_tests(out, name):
1576 loxi_utils.gen_c_copy_license(out)
1577 out.write("""
1578/**
1579 *
1580 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1581 *
1582 * Unified simple class instantiation tests for all versions
1583 */
1584
1585#include <locitest/test_common.h>
1586""")
1587 for version in of_g.of_version_range:
1588 for cls in of_g.standard_class_order:
1589 if not loxi_utils.class_in_version(cls, version):
1590 continue
1591 if cls in type_maps.inheritance_map:
1592 continue
1593 unified_accessor_test_case(out, cls, version)
1594
1595 out.write("""
1596int
1597run_unified_accessor_tests(void)
1598{
1599""")
1600 for version in of_g.of_version_range:
1601 v_name = loxi_utils.version_to_name(version)
1602 for cls in of_g.standard_class_order:
1603 if not loxi_utils.class_in_version(cls, version):
1604 continue
1605 if cls in type_maps.inheritance_map:
1606 continue
1607 test_name = "%s_%s" % (cls, v_name)
1608 out.write(" RUN_TEST(%s);\n" % test_name)
1609
1610 out.write(" return TEST_PASS;\n}\n");
1611
1612
1613
1614################################################################
1615#
1616# Object duplication functions
1617#
1618# These exercise the accessors to create duplicate objects.
1619# They are used in the LOCI test shim which sits in an OF
1620# protocol stream.
1621#
1622# TODO
1623# Resolve version stuff
1624# Complete list dup
1625
1626def gen_dup_list(out, cls, version):
1627 ver_name = loxi_utils.version_to_name(version)
1628 elt_type = loxi_utils.list_to_entry_type(cls)
1629 out.write("""
1630/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001631 * Duplicate a list of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001632 * using accessor functions
1633 * @param src Pointer to object to be duplicated
1634 * @returns A new object of type %(cls)s.
1635 *
1636 * The caller is responsible for deleting the returned value
1637 */
1638%(cls)s_t *
1639%(cls)s_%(ver_name)s_dup(
1640 %(cls)s_t *src)
1641{
1642 %(elt_type)s_t src_elt;
1643 %(elt_type)s_t *dst_elt;
1644 int rv;
1645 %(cls)s_t *dst;
1646
1647 if ((dst = %(cls)s_new(src->version)) == NULL) {
1648 return NULL;
1649 }
1650""" % dict(elt_type=elt_type, cls=cls, ver_name=ver_name))
1651
1652 out.write("""
1653 %(u_cls)s_ITER(src, &src_elt, rv) {
1654 if ((dst_elt = %(elt_type)s_%(ver_name)s_dup(&src_elt)) == NULL) {
1655 of_object_delete((of_object_t *)dst);
1656 return NULL;
1657 }
1658 _TRY_FREE(%(cls)s_append(dst, dst_elt),
1659 dst, NULL);
1660 of_object_delete((of_object_t *)dst_elt);
1661 }
1662
1663 return dst;
1664}
1665""" % dict(u_cls=cls.upper(), elt_type=elt_type, cls=cls, ver_name=ver_name))
1666
1667
1668def gen_dup_inheritance(out, cls, version):
1669 ver_name = loxi_utils.version_to_name(version)
1670 out.write("""
1671/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001672 * Duplicate a super class object of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001673 * @param src Pointer to object to be duplicated
1674 * @returns A new object of type %(cls)s.
1675 *
1676 * The caller is responsible for deleting the returned value
1677 */
1678%(cls)s_t *
1679%(cls)s_%(ver_name)s_dup(
1680 %(cls)s_t *src)
1681{
1682""" % dict(cls=cls, ver_name=ver_name))
1683
1684 # For each subclass, check if this is an instance of that subclass
1685 version_classes = type_maps.inheritance_data[cls][version]
1686 for sub_cls in version_classes:
1687 sub_enum = (cls + "_" + sub_cls).upper()
1688 out.write("""
1689 if (src->header.object_id == %(sub_enum)s) {
1690 return (%(cls)s_t *)%(cls)s_%(sub_cls)s_%(ver_name)s_dup(
1691 &src->%(sub_cls)s);
1692 }
1693""" % dict(sub_cls=sub_cls, ver_name=ver_name, sub_enum=sub_enum, cls=cls))
1694
1695 out.write("""
1696 return NULL;
1697}
1698""")
1699
1700
1701def gen_dup_cls(out, cls, version):
1702 """
1703 Generate duplication routine for class cls
1704 """
1705 ver_name = loxi_utils.version_to_name(version)
1706
1707 out.write("""
1708/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001709 * Duplicate an object of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001710 * using accessor functions
1711 * @param src Pointer to object to be duplicated
1712 * @returns A new object of type %(cls)s.
1713 *
1714 * The caller is responsible for deleting the returned value
1715 */
1716%(cls)s_t *
1717%(cls)s_%(ver_name)s_dup(
1718 %(cls)s_t *src)
1719{
1720 %(cls)s_t *dst;
1721""" % dict(cls=cls, ver_name=ver_name))
1722
1723 # Get members and types for the class
1724 members, member_types = loxi_utils.all_member_types_get(cls, version)
1725
1726 # Add declarations for each member type
1727 for m_type in member_types:
1728 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1729 # Declare instance of these
1730 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1731 else:
1732 out.write("""
1733 %(m_type)s src_%(v_name)s;
1734 %(m_type)s *dst_%(v_name)s;
1735""" % dict(m_type=m_type, v_name=var_name_map(m_type)))
1736
1737 out.write("""
1738 if ((dst = %(cls)s_new(src->version)) == NULL) {
1739 return NULL;
1740 }
1741""" % dict(cls=cls))
1742
1743 for member in members:
1744 m_type = member["m_type"]
1745 m_name = member["name"]
1746 if loxi_utils.skip_member_name(m_name):
1747 continue
1748 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1749 out.write("""
1750 %(cls)s_%(m_name)s_get(src, &%(v_name)s);
1751 %(cls)s_%(m_name)s_set(dst, %(v_name)s);
1752""" % dict(cls=cls, m_name=m_name, v_name=var_name_map(m_type)))
1753 elif m_type in ["of_match_t", "of_octets_t"]:
1754 out.write("""
1755 %(cls)s_%(m_name)s_get(src, &%(v_name)s);
1756 %(cls)s_%(m_name)s_set(dst, &%(v_name)s);
1757""" % dict(cls=cls, m_name=m_name, v_name=var_name_map(m_type)))
1758 else:
1759 sub_cls = m_type[:-2] # Trim _t
1760 out.write("""
1761 %(cls)s_%(m_name)s_bind(
1762 src, &src_%(v_name)s);
1763 dst_%(v_name)s = %(sub_cls)s_%(ver_name)s_dup(&src_%(v_name)s);
1764 if (dst_%(v_name)s == NULL) {
1765 %(cls)s_delete(dst);
1766 return NULL;
1767 }
1768 %(cls)s_%(m_name)s_set(dst, dst_%(v_name)s);
1769 %(sub_cls)s_delete(dst_%(v_name)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001770""" % dict(sub_cls=sub_cls, cls=cls, m_name=m_name,
Rich Lanea06d0c32013-03-25 08:52:03 -07001771 v_name=var_name_map(m_type), ver_name=ver_name))
1772
1773 out.write("""
1774 return dst;
1775}
1776""")
1777
1778def gen_version_dup(out=sys.stdout):
1779 """
1780 Generate duplication routines for each object type
1781 """
1782 out.write("""
1783/* Special try macro for duplicating */
1784#define _TRY_FREE(op, obj, rv) do { \\
1785 int _rv; \\
1786 if ((_rv = (op)) < 0) { \\
1787 LOCI_LOG_ERROR("ERROR %d at %s:%d\\n", _rv, __FILE__, __LINE__); \\
1788 of_object_delete((of_object_t *)(obj)); \\
1789 return (rv); \\
1790 } \\
1791 } while (0)
1792""")
1793
1794 for version in of_g.of_version_range:
1795 for cls in of_g.standard_class_order:
1796 if not loxi_utils.class_in_version(cls, version):
1797 continue
1798 if cls in type_maps.inheritance_map:
1799 gen_dup_inheritance(out, cls, version)
1800 elif loxi_utils.class_is_list(cls):
1801 gen_dup_list(out, cls, version)
1802 else:
1803 gen_dup_cls(out, cls, version)
1804
1805def gen_dup(out=sys.stdout):
1806 """
1807 Generate non-version specific duplication routines for each object type
1808 """
1809
1810 for cls in of_g.standard_class_order:
1811 out.write("""
1812%(cls)s_t *
1813%(cls)s_dup(
1814 %(cls)s_t *src)
1815{
1816""" % dict(cls=cls))
1817 for version in of_g.of_version_range:
1818 if not loxi_utils.class_in_version(cls, version):
1819 continue
1820 hdr = "header." if cls in type_maps.inheritance_map else ""
1821
1822 ver_name = loxi_utils.version_to_name(version)
1823 out.write("""
1824 if (src->%(hdr)sversion == %(ver_name)s) {
1825 return %(cls)s_%(ver_name)s_dup(src);
1826 }
1827""" % dict(cls=cls, ver_name=ver_name, hdr=hdr))
1828
1829 out.write("""
1830 /* Class not supported in given version */
1831 return NULL;
1832}
1833""")
1834
1835def dup_c_gen(out, name):
1836 """
1837 Generate the C file for duplication functions
1838 """
1839 loxi_utils.gen_c_copy_license(out)
1840 out.write("""\
1841/*
1842 * Duplication functions for all OF objects
1843 *
1844 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1845 *
1846 * These are test functions for exercising accessors. You can call
1847 * of_object_dup for an efficient duplication.
1848 */
1849
1850#define DISABLE_WARN_UNUSED_RESULT
1851#include "loci_log.h"
1852#include <locitest/of_dup.h>
1853
1854""")
1855
1856 gen_version_dup(out)
1857 gen_dup(out)
1858
1859
1860def dup_h_gen(out, name):
1861 """
1862 Generate the header file for duplication functions
1863 """
1864
1865 loxi_utils.gen_c_copy_license(out)
1866 out.write("""
1867/*
1868 * Duplication function header file
1869 *
1870 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1871 */
1872
1873#if !defined(_OF_DUP_H_)
1874#define _OF_DUP_H_
1875
1876#include <loci/loci.h>
1877""")
1878
1879 for cls in of_g.standard_class_order:
1880 out.write("""
1881extern %(cls)s_t *
1882 %(cls)s_dup(
1883 %(cls)s_t *src);
1884""" % dict(cls=cls))
1885
1886 for version in of_g.of_version_range:
1887 for cls in of_g.standard_class_order:
1888 if not loxi_utils.class_in_version(cls, version):
1889 continue
1890 ver_name = loxi_utils.version_to_name(version)
1891 out.write("""
1892extern %(cls)s_t *
1893 %(cls)s_%(ver_name)s_dup(
1894 %(cls)s_t *src);
1895""" % dict(cls=cls, ver_name=ver_name))
1896
1897 out.write("\n#endif /* _OF_DUP_H_ */\n")
1898
1899def gen_log_test(out):
1900 """
1901 Generate test for obj log calls
1902
1903 Define a trivial handler for object logging; call all obj log fns
1904 """
1905 out.write("""
1906
1907/**
1908 * Test object dump functions
1909 */
1910
1911int
1912test_dump_objs(void)
1913{
1914 of_object_t *obj;
1915
1916 FILE *out = fopen("/dev/null", "w");
1917
1918 /* Call each obj dump function */
1919""")
1920 for version in of_g.of_version_range:
1921 for j, cls in enumerate(of_g.all_class_order):
1922 if not loxi_utils.class_in_version(cls, version):
1923 continue
1924 if cls in type_maps.inheritance_map:
1925 continue
1926 out.write("""
1927 obj = (of_object_t *)%(cls)s_new(%(version)s);
1928 of_object_dump((loci_writer_f)fprintf, out, obj);
1929 of_object_delete(obj);
1930""" % dict(cls=cls, version=of_g.of_version_wire2name[version]))
Andreas Wundsam53256162013-05-02 14:05:53 -07001931
Rich Lanea06d0c32013-03-25 08:52:03 -07001932 out.write("""
1933 fclose(out);
1934 return TEST_PASS;
1935}
1936""")
1937
1938def gen_ident_tests(out):
1939 """
1940 Generate tests for identifiers
1941
1942 For all idents, instantiate, test version supported macros
1943 For flags, set it, test it, clear it, test it.
1944 """
1945 out.write("""
1946/**
1947 * Test cases for all flag accessor macros
1948 * These only test self consistency (and that they compile)
1949 */
1950int
1951test_ident_macros(void)
1952{
1953 int value __attribute__((unused));
1954 uint32_t flags;
1955
1956""")
1957
1958 for ident, info in of_g.identifiers.items():
1959 if not identifiers.defined_versions_agree(of_g.identifiers,
1960 of_g.target_version_list,
1961 ident):
1962 # @fixme
1963 continue
1964 out.write(" value = %s;\n" % ident)
1965 for version in of_g.target_version_list:
1966 if version in info["values_by_version"].keys():
1967 out.write(" TEST_ASSERT(%s_SUPPORTED(%s));\n" %
1968 (ident, of_g.of_version_wire2name[version]))
1969 else:
1970 out.write(" TEST_ASSERT(!%s_SUPPORTED(%s));\n" %
1971 (ident, of_g.of_version_wire2name[version]))
1972 if flags.ident_is_flag(ident):
1973 # Grab first supported version
1974 for version in info["values_by_version"]:
1975 break
1976 out.write("""
1977 flags = 0;
1978 %(ident)s_SET(flags, %(ver_name)s);
1979 TEST_ASSERT(flags == %(ident)s_BY_VERSION(%(ver_name)s));
1980 TEST_ASSERT(%(ident)s_TEST(flags, %(ver_name)s));
1981 %(ident)s_CLEAR(flags, %(ver_name)s);
1982 TEST_ASSERT(flags == 0);
1983 TEST_ASSERT(!%(ident)s_TEST(flags, %(ver_name)s));
1984""" % dict(ident=ident, ver_name=of_g.of_version_wire2name[version]))
1985
1986 out.write("""
1987 return TEST_PASS;
1988}
1989""")
1990
Rich Laneccae0312013-07-21 23:34:13 -07001991def gen_datafiles_tests(out, name):
1992 tests = []
1993 for filename in test_data.list_files():
1994 data = test_data.read(filename)
1995 if not 'c' in data:
1996 continue
1997 name = filename[:-5].replace("/", "_")
1998 tests.append(dict(name=name,
1999 filename=filename,
2000 c=data['c'],
2001 binary=data['binary']))
2002
2003 util.render_template(out, "test_data.c", tests=tests)