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