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