From 42fb155291f96b130ab3f3cee15038a02d1b3996 Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Fri, 1 Aug 2014 20:46:36 +0100 Subject: [PATCH] More work on the verification suite. Fully working with the initial test case now. --- firmware/tools/verification/tc/times_two.py | 25 +- firmware/tools/verification/verification.py | 75 +- firmware/tools/verification/verification_tc.c | 8 +- .../tools/verification/verification_tc.py | 694 ++++++++++++++++++ 4 files changed, 779 insertions(+), 23 deletions(-) create mode 100644 firmware/tools/verification/verification_tc.py diff --git a/firmware/tools/verification/tc/times_two.py b/firmware/tools/verification/tc/times_two.py index a260627..6ae2cd6 100644 --- a/firmware/tools/verification/tc/times_two.py +++ b/firmware/tools/verification/tc/times_two.py @@ -6,31 +6,44 @@ import os import sys + sys.path.append("./tools/verification") from verification import * import verification_tc +from random import randint + # ------------------------------------------------------------------------------ # Test Script # ------------------------------------------------------------------------------ class times_two_tc: - def __init__(self, tester): + def __init__(self): self.name = self.__class__.__name__ + self.iterations = 20 - tester.print_header(self.__class__.__name__) + def get_test(self): + """Returns some suitable test parameters""" params = verification_tc.struct_times_two_tc_params() - params.input = 4 + params.input = randint(0, 10000) - result = tester.run_tc(self.name, params) + return params - tester.print_info(str(result)) + def is_correct(self, params, result): + """Returns if a result is correct for the given parameters""" + + print_info("%d * 2 = %d"%(params.input, result['result'])) + + if (params.input * 2 == result['result']): + return True + else: + return False # ------------------------------------------------------------------------------ # Run test # ------------------------------------------------------------------------------ tester = samd20_test() -times_two_tc(tester) +tester.run_test_case(times_two_tc()) del tester diff --git a/firmware/tools/verification/verification.py b/firmware/tools/verification/verification.py index ca0875a..f6eaf80 100644 --- a/firmware/tools/verification/verification.py +++ b/firmware/tools/verification/verification.py @@ -28,29 +28,53 @@ import sys from time import * from colorama import * +LINE_LENGTH = 80 + +##### Public Print utilities def printf(string): + """All writes go to stderr""" print (string, file=sys.stderr) -LINE_LENGTH = 80 +def print_info(string): + """Prints an info line""" + printf("") + printf(Fore.CYAN + "INFO " + Fore.RESET + string) + +##### Tester class samd20_test: - # Prints something in the centre of the line def print_centre(self, string): + """Prints something in the centre of the line""" count = (LINE_LENGTH - len(string)) / 2 printf ((" " * count) + string) - # Prints a pretty header - def print_header(self, string): - printf (Fore.YELLOW) - printf (("*" * LINE_LENGTH) + Fore.RESET) - self.print_centre(string) + def print_header_line(self): + """Prints a yellow line. Yo""" printf (Fore.YELLOW + ("*" * LINE_LENGTH) + Fore.RESET) - def print_info(self, string): - """Prints an info line""" - printf(Fore.CYAN + "\nINFO " + Fore.RESET + string + "\n\n") + def print_header(self, string): + """Prints a pretty header""" + printf ("") + self.print_header_line() + self.print_centre(string) + self.print_header_line() + + def print_pass(self, tc_name, time): + """Nice green pass notice""" + offset = (LINE_LENGTH / 2) - len(tc_name) + + printf("") + printf(Fore.GREEN + " " + tc_name + " - PASS" \ + + (" " * offset) + str(time) + Fore.RESET) + + def print_fail(self, tc_name, time): + """Evil red pass notice""" + + printf("") + printf(Fore.RED + " " + tc_name + "- FAIL" \ + + str(time) + Fore.RESET) #### GDB @@ -69,19 +93,19 @@ class samd20_test: gdb.execute("c") def __del__(self): - self.print_info("quit") + print_info("quit") gdb.execute("quit") - def run_tc(self, tc_name, parameters): - """Runs a test case""" + def hw_run_tc(self, tc_name, parameters): + """Runs a test case on hardware""" # Write the parameters self.write_varible(tc_name+"_params", parameters) # Presuming there"s a breakpoint at the top of tc_main - gdb.execute("set $lr=$pc") - gdb.execute("set $pc="+tc_name) + #gdb.execute("set $lr=tc_main") + gdb.execute("set tc_ptr="+tc_name+"+1") gdb.execute("c") # Test case done. Return results @@ -96,3 +120,24 @@ class samd20_test: def write_varible(self, name, value): pvar = self.read_variable(name) self.inferior.write_memory(pvar.address, value) + + #### Test Case + + def run_test_case(self, test_case): + tc_name = test_case.__class__.__name__ + self.print_header(tc_name) + fail = False + + if test_case.iterations: + for i in range(test_case.iterations): + params = test_case.get_test() + result = self.hw_run_tc(tc_name, params) + + if not test_case.is_correct(params, result): + fail = True + break + + if not fail: + self.print_pass(tc_name, 0) + else: + self.print_fail(tc_name, 0) diff --git a/firmware/tools/verification/verification_tc.c b/firmware/tools/verification/verification_tc.c index e5650c5..6a990d1 100644 --- a/firmware/tools/verification/verification_tc.c +++ b/firmware/tools/verification/verification_tc.c @@ -69,12 +69,16 @@ __verification__ void times_two_tc(void) { /*******************************//* tc_main *//********************************/ +typedef void (*tc_ptr_type)(void); +volatile tc_ptr_type tc_ptr; + /** * Called at the start of the test case run */ __verification__ void tc_main(void) { - /* Test enviroment initialisation */ /* Wait forever while test cases execute */ - while (1); + while (1) { + (*tc_ptr)(); + } } diff --git a/firmware/tools/verification/verification_tc.py b/firmware/tools/verification/verification_tc.py new file mode 100644 index 0000000..bff1473 --- /dev/null +++ b/firmware/tools/verification/verification_tc.py @@ -0,0 +1,694 @@ +'''Wrapper for verification_tc.c + +Generated with: +ctypes/ctypesgen.py -o verification_tc.py --cpp=gcc -E -DCTYPESGEN verification_tc.c + +Do not modify this file. +''' + +__docformat__ = 'restructuredtext' + +# Begin preamble + +import ctypes, os, sys +from ctypes import * + +_int_types = (c_int16, c_int32) +if hasattr(ctypes, 'c_int64'): + # Some builds of ctypes apparently do not have c_int64 + # defined; it's a pretty good bet that these builds do not + # have 64-bit pointers. + _int_types += (c_int64,) +for t in _int_types: + if sizeof(t) == sizeof(c_size_t): + c_ptrdiff_t = t +del t +del _int_types + +class c_void(Structure): + # c_void_p is a buggy return type, converting to int, so + # POINTER(None) == c_void_p is actually written as + # POINTER(c_void), so it can be treated as a real pointer. + _fields_ = [('dummy', c_int)] + +def POINTER(obj): + p = ctypes.POINTER(obj) + + # Convert None to a real NULL pointer to work around bugs + # in how ctypes handles None on 64-bit platforms + if not isinstance(p.from_param, classmethod): + def from_param(cls, x): + if x is None: + return cls() + else: + return x + p.from_param = classmethod(from_param) + + return p + +class UserString: + def __init__(self, seq): + if isinstance(seq, basestring): + self.data = seq + elif isinstance(seq, UserString): + self.data = seq.data[:] + else: + self.data = str(seq) + def __str__(self): return str(self.data) + def __repr__(self): return repr(self.data) + def __int__(self): return int(self.data) + def __long__(self): return long(self.data) + def __float__(self): return float(self.data) + def __complex__(self): return complex(self.data) + def __hash__(self): return hash(self.data) + + def __cmp__(self, string): + if isinstance(string, UserString): + return cmp(self.data, string.data) + else: + return cmp(self.data, string) + def __contains__(self, char): + return char in self.data + + def __len__(self): return len(self.data) + def __getitem__(self, index): return self.__class__(self.data[index]) + def __getslice__(self, start, end): + start = max(start, 0); end = max(end, 0) + return self.__class__(self.data[start:end]) + + def __add__(self, other): + if isinstance(other, UserString): + return self.__class__(self.data + other.data) + elif isinstance(other, basestring): + return self.__class__(self.data + other) + else: + return self.__class__(self.data + str(other)) + def __radd__(self, other): + if isinstance(other, basestring): + return self.__class__(other + self.data) + else: + return self.__class__(str(other) + self.data) + def __mul__(self, n): + return self.__class__(self.data*n) + __rmul__ = __mul__ + def __mod__(self, args): + return self.__class__(self.data % args) + + # the following methods are defined in alphabetical order: + def capitalize(self): return self.__class__(self.data.capitalize()) + def center(self, width, *args): + return self.__class__(self.data.center(width, *args)) + def count(self, sub, start=0, end=sys.maxint): + return self.data.count(sub, start, end) + def decode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.decode(encoding, errors)) + else: + return self.__class__(self.data.decode(encoding)) + else: + return self.__class__(self.data.decode()) + def encode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.encode(encoding, errors)) + else: + return self.__class__(self.data.encode(encoding)) + else: + return self.__class__(self.data.encode()) + def endswith(self, suffix, start=0, end=sys.maxint): + return self.data.endswith(suffix, start, end) + def expandtabs(self, tabsize=8): + return self.__class__(self.data.expandtabs(tabsize)) + def find(self, sub, start=0, end=sys.maxint): + return self.data.find(sub, start, end) + def index(self, sub, start=0, end=sys.maxint): + return self.data.index(sub, start, end) + def isalpha(self): return self.data.isalpha() + def isalnum(self): return self.data.isalnum() + def isdecimal(self): return self.data.isdecimal() + def isdigit(self): return self.data.isdigit() + def islower(self): return self.data.islower() + def isnumeric(self): return self.data.isnumeric() + def isspace(self): return self.data.isspace() + def istitle(self): return self.data.istitle() + def isupper(self): return self.data.isupper() + def join(self, seq): return self.data.join(seq) + def ljust(self, width, *args): + return self.__class__(self.data.ljust(width, *args)) + def lower(self): return self.__class__(self.data.lower()) + def lstrip(self, chars=None): return self.__class__(self.data.lstrip(chars)) + def partition(self, sep): + return self.data.partition(sep) + def replace(self, old, new, maxsplit=-1): + return self.__class__(self.data.replace(old, new, maxsplit)) + def rfind(self, sub, start=0, end=sys.maxint): + return self.data.rfind(sub, start, end) + def rindex(self, sub, start=0, end=sys.maxint): + return self.data.rindex(sub, start, end) + def rjust(self, width, *args): + return self.__class__(self.data.rjust(width, *args)) + def rpartition(self, sep): + return self.data.rpartition(sep) + def rstrip(self, chars=None): return self.__class__(self.data.rstrip(chars)) + def split(self, sep=None, maxsplit=-1): + return self.data.split(sep, maxsplit) + def rsplit(self, sep=None, maxsplit=-1): + return self.data.rsplit(sep, maxsplit) + def splitlines(self, keepends=0): return self.data.splitlines(keepends) + def startswith(self, prefix, start=0, end=sys.maxint): + return self.data.startswith(prefix, start, end) + def strip(self, chars=None): return self.__class__(self.data.strip(chars)) + def swapcase(self): return self.__class__(self.data.swapcase()) + def title(self): return self.__class__(self.data.title()) + def translate(self, *args): + return self.__class__(self.data.translate(*args)) + def upper(self): return self.__class__(self.data.upper()) + def zfill(self, width): return self.__class__(self.data.zfill(width)) + +class MutableString(UserString): + """mutable string objects + + Python strings are immutable objects. This has the advantage, that + strings may be used as dictionary keys. If this property isn't needed + and you insist on changing string values in place instead, you may cheat + and use MutableString. + + But the purpose of this class is an educational one: to prevent + people from inventing their own mutable string class derived + from UserString and than forget thereby to remove (override) the + __hash__ method inherited from UserString. This would lead to + errors that would be very hard to track down. + + A faster and better solution is to rewrite your program using lists.""" + def __init__(self, string=""): + self.data = string + def __hash__(self): + raise TypeError("unhashable type (it is mutable)") + def __setitem__(self, index, sub): + if index < 0: + index += len(self.data) + if index < 0 or index >= len(self.data): raise IndexError + self.data = self.data[:index] + sub + self.data[index+1:] + def __delitem__(self, index): + if index < 0: + index += len(self.data) + if index < 0 or index >= len(self.data): raise IndexError + self.data = self.data[:index] + self.data[index+1:] + def __setslice__(self, start, end, sub): + start = max(start, 0); end = max(end, 0) + if isinstance(sub, UserString): + self.data = self.data[:start]+sub.data+self.data[end:] + elif isinstance(sub, basestring): + self.data = self.data[:start]+sub+self.data[end:] + else: + self.data = self.data[:start]+str(sub)+self.data[end:] + def __delslice__(self, start, end): + start = max(start, 0); end = max(end, 0) + self.data = self.data[:start] + self.data[end:] + def immutable(self): + return UserString(self.data) + def __iadd__(self, other): + if isinstance(other, UserString): + self.data += other.data + elif isinstance(other, basestring): + self.data += other + else: + self.data += str(other) + return self + def __imul__(self, n): + self.data *= n + return self + +class String(MutableString, Union): + + _fields_ = [('raw', POINTER(c_char)), + ('data', c_char_p)] + + def __init__(self, obj=""): + if isinstance(obj, (str, unicode, UserString)): + self.data = str(obj) + else: + self.raw = obj + + def __len__(self): + return self.data and len(self.data) or 0 + + def from_param(cls, obj): + # Convert None or 0 + if obj is None or obj == 0: + return cls(POINTER(c_char)()) + + # Convert from String + elif isinstance(obj, String): + return obj + + # Convert from str + elif isinstance(obj, str): + return cls(obj) + + # Convert from c_char_p + elif isinstance(obj, c_char_p): + return obj + + # Convert from POINTER(c_char) + elif isinstance(obj, POINTER(c_char)): + return obj + + # Convert from raw pointer + elif isinstance(obj, int): + return cls(cast(obj, POINTER(c_char))) + + # Convert from object + else: + return String.from_param(obj._as_parameter_) + from_param = classmethod(from_param) + +def ReturnString(obj, func=None, arguments=None): + return String.from_param(obj) + +# As of ctypes 1.0, ctypes does not support custom error-checking +# functions on callbacks, nor does it support custom datatypes on +# callbacks, so we must ensure that all callbacks return +# primitive datatypes. +# +# Non-primitive return values wrapped with UNCHECKED won't be +# typechecked, and will be converted to c_void_p. +def UNCHECKED(type): + if (hasattr(type, "_type_") and isinstance(type._type_, str) + and type._type_ != "P"): + return type + else: + return c_void_p + +# ctypes doesn't have direct support for variadic functions, so we have to write +# our own wrapper class +class _variadic_function(object): + def __init__(self,func,restype,argtypes): + self.func=func + self.func.restype=restype + self.argtypes=argtypes + def _as_parameter_(self): + # So we can pass this variadic function as a function pointer + return self.func + def __call__(self,*args): + fixed_args=[] + i=0 + for argtype in self.argtypes: + # Typecheck what we can + fixed_args.append(argtype.from_param(args[i])) + i+=1 + return self.func(*fixed_args+list(args[i:])) + +# End preamble + +_libs = {} +_libdirs = [] + +# Begin loader + +# ---------------------------------------------------------------------------- +# Copyright (c) 2008 David James +# Copyright (c) 2006-2008 Alex Holkner +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of pyglet nor the names of its +# contributors may be used to endorse or promote products +# derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# ---------------------------------------------------------------------------- + +import os.path, re, sys, glob +import platform +import ctypes +import ctypes.util + +def _environ_path(name): + if name in os.environ: + return os.environ[name].split(":") + else: + return [] + +class LibraryLoader(object): + def __init__(self): + self.other_dirs=[] + + def load_library(self,libname): + """Given the name of a library, load it.""" + paths = self.getpaths(libname) + + for path in paths: + if os.path.exists(path): + return self.load(path) + + raise ImportError("%s not found." % libname) + + def load(self,path): + """Given a path to a library, load it.""" + try: + # Darwin requires dlopen to be called with mode RTLD_GLOBAL instead + # of the default RTLD_LOCAL. Without this, you end up with + # libraries not being loadable, resulting in "Symbol not found" + # errors + if sys.platform == 'darwin': + return ctypes.CDLL(path, ctypes.RTLD_GLOBAL) + else: + return ctypes.cdll.LoadLibrary(path) + except OSError,e: + raise ImportError(e) + + def getpaths(self,libname): + """Return a list of paths where the library might be found.""" + if os.path.isabs(libname): + yield libname + else: + # FIXME / TODO return '.' and os.path.dirname(__file__) + for path in self.getplatformpaths(libname): + yield path + + path = ctypes.util.find_library(libname) + if path: yield path + + def getplatformpaths(self, libname): + return [] + +# Darwin (Mac OS X) + +class DarwinLibraryLoader(LibraryLoader): + name_formats = ["lib%s.dylib", "lib%s.so", "lib%s.bundle", "%s.dylib", + "%s.so", "%s.bundle", "%s"] + + def getplatformpaths(self,libname): + if os.path.pathsep in libname: + names = [libname] + else: + names = [format % libname for format in self.name_formats] + + for dir in self.getdirs(libname): + for name in names: + yield os.path.join(dir,name) + + def getdirs(self,libname): + '''Implements the dylib search as specified in Apple documentation: + + http://developer.apple.com/documentation/DeveloperTools/Conceptual/ + DynamicLibraries/Articles/DynamicLibraryUsageGuidelines.html + + Before commencing the standard search, the method first checks + the bundle's ``Frameworks`` directory if the application is running + within a bundle (OS X .app). + ''' + + dyld_fallback_library_path = _environ_path("DYLD_FALLBACK_LIBRARY_PATH") + if not dyld_fallback_library_path: + dyld_fallback_library_path = [os.path.expanduser('~/lib'), + '/usr/local/lib', '/usr/lib'] + + dirs = [] + + if '/' in libname: + dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) + else: + dirs.extend(_environ_path("LD_LIBRARY_PATH")) + dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) + + dirs.extend(self.other_dirs) + dirs.append(".") + dirs.append(os.path.dirname(__file__)) + + if hasattr(sys, 'frozen') and sys.frozen == 'macosx_app': + dirs.append(os.path.join( + os.environ['RESOURCEPATH'], + '..', + 'Frameworks')) + + dirs.extend(dyld_fallback_library_path) + + return dirs + +# Posix + +class PosixLibraryLoader(LibraryLoader): + _ld_so_cache = None + + def _create_ld_so_cache(self): + # Recreate search path followed by ld.so. This is going to be + # slow to build, and incorrect (ld.so uses ld.so.cache, which may + # not be up-to-date). Used only as fallback for distros without + # /sbin/ldconfig. + # + # We assume the DT_RPATH and DT_RUNPATH binary sections are omitted. + + directories = [] + for name in ("LD_LIBRARY_PATH", + "SHLIB_PATH", # HPUX + "LIBPATH", # OS/2, AIX + "LIBRARY_PATH", # BE/OS + ): + if name in os.environ: + directories.extend(os.environ[name].split(os.pathsep)) + directories.extend(self.other_dirs) + directories.append(".") + directories.append(os.path.dirname(__file__)) + + try: directories.extend([dir.strip() for dir in open('/etc/ld.so.conf')]) + except IOError: pass + + unix_lib_dirs_list = ['/lib', '/usr/lib', '/lib64', '/usr/lib64'] + if sys.platform.startswith('linux'): + # Try and support multiarch work in Ubuntu + # https://wiki.ubuntu.com/MultiarchSpec + bitage = platform.architecture()[0] + if bitage.startswith('32'): + # Assume Intel/AMD x86 compat + unix_lib_dirs_list += ['/lib/i386-linux-gnu', '/usr/lib/i386-linux-gnu'] + elif bitage.startswith('64'): + # Assume Intel/AMD x86 compat + unix_lib_dirs_list += ['/lib/x86_64-linux-gnu', '/usr/lib/x86_64-linux-gnu'] + else: + # guess... + unix_lib_dirs_list += glob.glob('/lib/*linux-gnu') + directories.extend(unix_lib_dirs_list) + + cache = {} + lib_re = re.compile(r'lib(.*)\.s[ol]') + ext_re = re.compile(r'\.s[ol]$') + for dir in directories: + try: + for path in glob.glob("%s/*.s[ol]*" % dir): + file = os.path.basename(path) + + # Index by filename + if file not in cache: + cache[file] = path + + # Index by library name + match = lib_re.match(file) + if match: + library = match.group(1) + if library not in cache: + cache[library] = path + except OSError: + pass + + self._ld_so_cache = cache + + def getplatformpaths(self, libname): + if self._ld_so_cache is None: + self._create_ld_so_cache() + + result = self._ld_so_cache.get(libname) + if result: yield result + + path = ctypes.util.find_library(libname) + if path: yield os.path.join("/lib",path) + +# Windows + +class _WindowsLibrary(object): + def __init__(self, path): + self.cdll = ctypes.cdll.LoadLibrary(path) + self.windll = ctypes.windll.LoadLibrary(path) + + def __getattr__(self, name): + try: return getattr(self.cdll,name) + except AttributeError: + try: return getattr(self.windll,name) + except AttributeError: + raise + +class WindowsLibraryLoader(LibraryLoader): + name_formats = ["%s.dll", "lib%s.dll", "%slib.dll"] + + def load_library(self, libname): + try: + result = LibraryLoader.load_library(self, libname) + except ImportError: + result = None + if os.path.sep not in libname: + for name in self.name_formats: + try: + result = getattr(ctypes.cdll, name % libname) + if result: + break + except WindowsError: + result = None + if result is None: + try: + result = getattr(ctypes.cdll, libname) + except WindowsError: + result = None + if result is None: + raise ImportError("%s not found." % libname) + return result + + def load(self, path): + return _WindowsLibrary(path) + + def getplatformpaths(self, libname): + if os.path.sep not in libname: + for name in self.name_formats: + dll_in_current_dir = os.path.abspath(name % libname) + if os.path.exists(dll_in_current_dir): + yield dll_in_current_dir + path = ctypes.util.find_library(name % libname) + if path: + yield path + +# Platform switching + +# If your value of sys.platform does not appear in this dict, please contact +# the Ctypesgen maintainers. + +loaderclass = { + "darwin": DarwinLibraryLoader, + "cygwin": WindowsLibraryLoader, + "win32": WindowsLibraryLoader +} + +loader = loaderclass.get(sys.platform, PosixLibraryLoader)() + +def add_library_search_dirs(other_dirs): + loader.other_dirs = other_dirs + +load_library = loader.load_library + +del loaderclass + +# End loader + +add_library_search_dirs([]) + +# No libraries + +# No modules + +# /richard/_longshot/firmware/tools/verification/verification_tc.c: 42 +class struct_nmea_decode_tc_params(Structure): + pass + +struct_nmea_decode_tc_params.__slots__ = [ + '_in', +] +struct_nmea_decode_tc_params._fields_ = [ + ('_in', c_int), +] + +# /richard/_longshot/firmware/tools/verification/verification_tc.c: 42 +for _lib in _libs.values(): + try: + nmea_decode_tc_params = (struct_nmea_decode_tc_params).in_dll(_lib, 'nmea_decode_tc_params') + break + except: + pass + +# /richard/_longshot/firmware/tools/verification/verification_tc.c: 46 +class struct_nmea_decode_tc_results(Structure): + pass + +struct_nmea_decode_tc_results.__slots__ = [ + 'result', +] +struct_nmea_decode_tc_results._fields_ = [ + ('result', c_int), +] + +# /richard/_longshot/firmware/tools/verification/verification_tc.c: 46 +for _lib in _libs.values(): + try: + nmea_decode_tc_results = (struct_nmea_decode_tc_results).in_dll(_lib, 'nmea_decode_tc_results') + break + except: + pass + +# /richard/_longshot/firmware/tools/verification/verification_tc.c: 59 +class struct_times_two_tc_params(Structure): + pass + +struct_times_two_tc_params.__slots__ = [ + 'input', +] +struct_times_two_tc_params._fields_ = [ + ('input', c_int), +] + +# /richard/_longshot/firmware/tools/verification/verification_tc.c: 59 +for _lib in _libs.values(): + try: + times_two_tc_params = (struct_times_two_tc_params).in_dll(_lib, 'times_two_tc_params') + break + except: + pass + +# /richard/_longshot/firmware/tools/verification/verification_tc.c: 63 +class struct_times_two_tc_results(Structure): + pass + +struct_times_two_tc_results.__slots__ = [ + 'result', +] +struct_times_two_tc_results._fields_ = [ + ('result', c_int), +] + +# /richard/_longshot/firmware/tools/verification/verification_tc.c: 63 +for _lib in _libs.values(): + try: + times_two_tc_results = (struct_times_two_tc_results).in_dll(_lib, 'times_two_tc_results') + break + except: + pass + +nmea_decode_tc_params = struct_nmea_decode_tc_params # /richard/_longshot/firmware/tools/verification/verification_tc.c: 42 + +nmea_decode_tc_results = struct_nmea_decode_tc_results # /richard/_longshot/firmware/tools/verification/verification_tc.c: 46 + +times_two_tc_params = struct_times_two_tc_params # /richard/_longshot/firmware/tools/verification/verification_tc.c: 59 + +times_two_tc_results = struct_times_two_tc_results # /richard/_longshot/firmware/tools/verification/verification_tc.c: 63 + +# No inserted files +