1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4#
5# Copyright 2017, Data61
6# Commonwealth Scientific and Industrial Research Organisation (CSIRO)
7# ABN 41 687 119 230.
8#
9# This software may be distributed and modified according to the terms of
10# the BSD 2-Clause license. Note that NO WARRANTY is provided.
11# See "LICENSE_BSD2.txt" for details.
12#
13# @TAG(DATA61_BSD)
14#
15
16'''
17Tests for input from good/ subdirectory, that are intended to be legitimate
18CAmkES input.
19'''
20
21from __future__ import absolute_import, division, print_function, \
22    unicode_literals
23
24import functools, os, re, sys, unittest
25
26ME = os.path.abspath(__file__)
27
28# Make CAmkES importable
29sys.path.append(os.path.join(os.path.dirname(ME), '../../..'))
30
31from camkes.ast import ASTError
32from camkes.internal.tests.utils import CAmkESTest, cpp_available
33from camkes.parser import ParseError
34from camkes.parser.stage0 import CPP, Reader
35from camkes.parser.stage1 import Parse1
36from camkes.parser.stage2 import Parse2
37from camkes.parser.stage3 import Parse3
38from camkes.parser.stage4 import Parse4
39from camkes.parser.stage5 import Parse5
40from camkes.parser.stage6 import Parse6
41from camkes.parser.stage7 import Parse7
42from camkes.parser.stage8 import Parse8
43from camkes.parser.stage9 import Parse9
44from camkes.parser.stage10 import Parse10
45from camkes.parser.query import QueryParseStage
46from camkes.parser.fdtQueryEngine import DtbMatchQuery
47
48PARSERS = ('reader', 'cpp', 's1', 's2', 's3', 's4', 's5', 's6', 's7', 's71', 's8', 's9', 's10')
49
50class TestExamples(CAmkESTest):
51    def setUp(self):
52        super(TestExamples, self).setUp()
53        self.reader = Reader()
54        self.cpp = CPP()
55        self.s1 = Parse1(self.cpp)
56        self.s2 = Parse2(self.s1)
57        self.s3 = Parse3(self.s2)
58        self.s4 = Parse4(self.s3)
59        self.s5 = Parse5(self.s4)
60        self.s6 = Parse6(self.s5)
61        self.s7 = Parse7(self.s6)
62
63        # initialise a dtb query parser
64        dtbQuery = DtbMatchQuery()
65        dtbQuery.parse_args(['--dtb', os.path.join(os.path.dirname(ME), "test.dtb")])
66        dtbQuery.check_options()
67
68        self.s71 = QueryParseStage(self.s7, {dtbQuery.get_query_name() : dtbQuery})
69        self.s8 = Parse8(self.s71)
70        self.s9 = Parse9(self.s8)
71        self.s10 = Parse10(self.s9)
72        assert all([hasattr(self, p) for p in PARSERS])
73
74# Locate all the test files in good/*.camkes and add each as a separate test
75# case for each parser.
76added_good = False
77for eg in os.listdir(os.path.join(os.path.dirname(ME), 'good')):
78    if re.match(r'.*\.camkes$', eg) is not None:
79        path = os.path.join(os.path.dirname(ME), 'good', eg)
80        for parser in PARSERS:
81            test_name = 'test_good_%s_%s' % (parser, re.sub(r'[^\w]', '_', eg))
82            setattr(TestExamples, test_name,
83                lambda self, f=path, p=parser: getattr(self, p).parse_file(f))
84        added_good = True
85if not added_good:
86    # We didn't find any valid tests.
87    def no_good(self):
88        self.fail('no good example input found')
89    TestExamples.test_no_good = no_good
90
91def _check_until(tester, filename, limit):
92    for p in PARSERS:
93        if p == limit:
94            with tester.assertRaises((ASTError, ParseError)):
95                getattr(tester, p).parse_file(filename)
96            break
97        else:
98            getattr(tester, p).parse_file(filename)
99
100# Locate all the files in bad-at-*/*.camkes and add each as a separate test
101# case, failing at the specific parser level.
102for p in PARSERS:
103    dirname = os.path.join(os.path.dirname(ME), 'bad-at-%s' % p)
104    if not os.path.exists(dirname):
105        continue
106    for eg in os.listdir(dirname):
107        if re.match(r'.*\.camkes$', eg) is not None:
108            path = os.path.join(dirname, eg)
109            test_name = 'test_bad_at_%s_%s' % (p, re.sub(r'[^\w]', '_', eg))
110            setattr(TestExamples, test_name,
111                lambda self, f=path, limit=p: _check_until(self, f, limit))
112
113if __name__ == '__main__':
114    unittest.main()
115