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