1# Copyright (C) 2016 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15'''Module that contains the test TestCallApiFuns.'''
16
17from __future__ import absolute_import
18
19import re
20import string
21
22from harness.test_base_remote import TestBaseRemote
23from harness import RS_funs
24from harness.decorators import (
25    wimpy,
26    ordered_test,
27    cpp_only_test,
28)
29
30
31class _APIFunsExprTestsMeta(type):
32    """
33    Generate unique, standalone test methods from a list of lldb expressions.
34    The lldb expression evaluation engine for calling RenderScript
35    builtins need to be tested thoroughly; rather than manually
36    write the 1000s of individual test cases, we automatically generate them
37    and their variants to add to the test class. This is done from a list
38    of expressions that are all tested in the same way.
39    """
40    def __new__(self, name, bases, class_dict):
41        func_name_sub = re.compile(r'[%s\s]+' % string.punctuation)
42
43        for count, line in enumerate(RS_funs.FUNC_LIST):
44            def make_test(line):
45                """
46                We use an extra level of indirection here to properly
47                close over the *value* of the loop variable, `line`
48                """
49                @ordered_test(count)
50                def test(self):
51                    # build the expression
52                    ret, expr = RS_funs.build_expr(line)
53                    try:
54                        # evaluate the expression with expected return value
55                        self.try_command(expr, [], [RS_funs.TYPE_MAP[ret]])
56                    except KeyError:
57                        # or just check the return type if no return value
58                        # specified
59                        self.try_command(expr, '(%s)' % ret)
60                return test
61
62            # Make a pretty python method that adheres to the testcase standard
63            # Use the `count` parameter to ensure the name is unique in the class
64            test_name = 'test_%s_%s' % (re.sub(func_name_sub, '_', line), count)
65            test = make_test(line)
66            test.func_name = test_name
67            # We mark every 10th test case as runnable in wimpy mode
68            class_dict[test_name] = wimpy(test) if count % 10 == 0 else test
69
70        return type(name, bases, class_dict)
71
72
73class TestCallApiFuns(TestBaseRemote):
74    '''Tests calling of some RS API functions. This tests that JITing works.'''
75
76    __metaclass__ = _APIFunsExprTestsMeta
77
78    bundle_target = {
79        'java': "KernelVariables",
80        'jni': "JNIKernelVariables",
81        'cpp': "CppKernelVariables"
82    }
83
84    @wimpy
85    @ordered_test(-2)
86    def test_setup(self):
87        self.try_command('language renderscript status',
88                         ['Runtime Library discovered',
89                          'Runtime Driver discovered'])
90
91        self.try_command('b -f simple.rs -l 145', [])
92
93        self.try_command('process continue',
94                         ['resuming',
95                          'stopped',
96                          'stop reason = breakpoint'])
97
98    @wimpy
99    @ordered_test(-1)
100    def test_call_api_funs_atomic(self):
101        # Test the atomics separately because we want to check the output
102        # AtomicAdd(1234, 2)
103        self.try_command('expr rsAtomicAdd(&int_global, 2)',
104                         ['1234'],
105                         [r'\(int(32_t)?\)'])
106
107        self.try_command('expr int_global',
108                         ['(int)',
109                          '1236'])
110
111        # AtomicAnd(2345, 333)
112        self.try_command('expr rsAtomicAnd(&uint_global, 333)',
113                         ['2345'],
114                         [r'\(int(32_t)?\)'])
115
116        self.try_command('expr uint_global',
117                         ['(uint)',
118                          '265'])
119
120        # AtomicCas(1236, 1236, 2345)
121        self.try_command('expr rsAtomicCas(&int_global, 1236, 2345)',
122                         ['1236'],
123                         [r'\(int(32_t)?\)'])
124
125        self.try_command('expr int_global',
126                         ['(int)',
127                          '2345'])
128
129        # AtomicDec(265)
130        self.try_command('expr rsAtomicDec(&uint_global)',
131                         ['265'],
132                         [r'\(int(32_t)?\)'])
133
134        self.try_command('expr uint_global',
135                         ['(uint)',
136                          '264'])
137
138        # AtomicInc(2345)
139        self.try_command('expr rsAtomicInc(&int_global)',
140                         ['2345'],
141                         [r'\(int(32_t)?\)'])
142
143        self.try_command('expr int_global',
144                         ['(int)',
145                          '2346'])
146
147        # AtomicMax(264, 3456)
148        self.try_command('expr rsAtomicMax(&uint_global, 3456)',
149                         ['264'],
150                         [r'\(uint(32_t)?\)'])
151
152        self.try_command('expr uint_global',
153                         ['(uint)',
154                          '3456'])
155
156        # AtomicMin(2346, 3)
157        self.try_command('expr rsAtomicMin(&int_global, 3)',
158                         ['2346'],
159                         [r'\(int(32_t)?\)'])
160
161        self.try_command('expr int_global',
162                         ['(int)',
163                          '3'])
164
165        # AtomicOr(3, 456)
166        self.try_command('expr rsAtomicOr(&int_global, 456)',
167                         ['3'],
168                         [r'\(int(32_t)?\)'])
169
170        self.try_command('expr int_global',
171                         ['(int)',
172                          '459'])
173
174        # AtomicSub(3456, 7)
175        self.try_command('expr rsAtomicSub(&uint_global, 7)',
176                         ['3456'],
177                         [r'\(int(32_t)?\)'])
178
179        self.try_command('expr uint_global',
180                         ['(uint)',
181                          '3449'])
182
183        # AtomicXor(459, 89)
184        self.try_command('expr rsAtomicXor(&int_global, 89)',
185                         ['459'],
186                         [r'\(int(32_t)?\)'])
187
188        self.try_command('expr int_global',
189                         ['(int)',
190                          '402'])
191
192    @ordered_test('last')
193    @cpp_only_test()
194    def test_cpp_cleanup(self):
195        self.try_command('breakpoint delete 1', ['1 breakpoints deleted'])
196
197        self.try_command('process continue', ['exited with status = 0'])
198