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
15from __future__ import absolute_import
16
17import re
18import itertools
19
20from harness.test_base_remote import TestBaseRemote
21from harness.decorators import (
22    ordered_test,
23    wimpy,
24    skip_conditional,
25)
26from harness.assert_mixins import CoordinateAssertionsMixin
27
28from reduce_common import (
29    REDUCE_SCRIPT,
30    REDUCE_AUTO_COMB_SCRIPT,
31    ReductionMixin,
32)
33
34
35multithreaded = lambda: skip_conditional(
36    lambda self: self.cpu_count == 1,
37    "skipping multithreaded test (1 CPU present)"
38)
39
40
41class TestReduceCombinerMultithreaded(
42        TestBaseRemote, CoordinateAssertionsMixin, ReductionMixin):
43    """
44    RenderScript reduction combiners are currently run only on the output of a
45    parallel reduction step for the CPU reference implementation.  These
46    testcases test LLDB's handling of breakpoints for the combiner function.
47    """
48
49    bundle_target = {
50        'java': 'Reduction',
51    }
52
53    def _delete_breakpoints(self):
54        try:
55            self.do_command('breakpoint delete -f')
56        except self.TestFail:
57            pass
58
59    def setup(self, android):
60        """
61        This test *must* be run on multiple threads, and is skipped if the
62        device does not support multiple threads
63        """
64        cpu_spec = android.shell("cat /sys/devices/system/cpu/online").strip()
65        match = re.search(r'(^0(-\d+)?(,\d+([-]\d*)?)*)$', cpu_spec)
66        if not match or not match.groups():
67            raise self.TestFail(
68                "unable to parse number of available CPUs in %r" % cpu_spec)
69
70        def parse_range(s):
71            r = s.split('-')
72            if len(r) == 1:
73                return 1
74            return int(r[1]) - int(r[0])
75
76        self.cpu_count = sum(map(parse_range, cpu_spec.split(',')))
77        android.push_prop('debug.rs.max-threads', self.cpu_count + 1)
78
79    def teardown(self, android):
80        """Reset the number of RS threads to the previous value."""
81        android.pop_prop('debug.rs.max-threads')
82
83    @multithreaded()
84    @ordered_test(0)
85    @wimpy
86    def test_setup(self):
87        self.try_command('language renderscript status', [])
88        # first point of order: make sure the compiled script is properly
89        # loaded and that we can set a breakpoint on the named reduction
90        self.try_command(
91            'language renderscript reduction breakpoint set find_min_user_type_auto_comb')
92        self.try_command(
93            'process continue',
94            expected_regex=[
95                r'Process \d+ stopped',
96                r'frame #0: (0x[0-9a-fA-F]+ )?librs.reduce_auto_comb.so`'
97            ]
98        )
99
100    @multithreaded()
101    def test_function_role_breakpoints_combinations(self):
102        func_role_combinations = itertools.combinations(
103            ('accumulator', 'outconverter', 'initializer', 'combiner'),
104            r=2
105        )
106        self._test_func_role_combinations(func_role_combinations)
107
108    @multithreaded()
109    def test_reduction_breakpoint_set_single_type_user_comb(self):
110        return self._reduction_breakpoint_set_single_type(
111            'reduce',
112            REDUCE_SCRIPT,
113            'find_min_user_type',
114            (
115                ('find_min_user_type_init', 'initializer'),
116                ('find_min_user_type_accum', 'accumulator'),
117                ('find_min_user_type_comb', 'combiner'),
118                ('find_min_user_type_outc', 'outconverter')
119            )
120        )
121
122    @multithreaded()
123    def test_reduction_breakpoint_set_single_type_auto_comb(self):
124        return self._reduction_breakpoint_set_single_type(
125            'reduce_auto_comb',
126            REDUCE_AUTO_COMB_SCRIPT,
127            'find_min_user_type_auto_comb',
128            (
129                ('find_min_user_type_init', 'initializer'),
130                ('find_min_user_type_accum', 'accumulator'),
131                ('find_min_user_type_accum.combiner', 'combiner'),
132                ('find_min_user_type_outc', 'outconverter')
133            )
134        )
135