Example #1
0
 def test_get_shortest_path(self):
     automata = Automata()
     state0 = State('state0')
     state1 = State('state1')
     state2 = State('state2')
     state3 = State('state3')
     state4 = State('state4')
     state5 = State('state5')
     state6 = State('state6')
     automata.add_state(state0)
     automata.add_state(state1)
     automata.add_state(state2)
     automata.add_state(state3)
     automata.add_state(state4)
     automata.add_state(state5)
     automata.add_state(state6)
     automata.add_edge(state0, state1, Clickable('0-1'))
     automata.add_edge(state0, state2, Clickable('0-2'))
     automata.add_edge(state0, state3, Clickable('0-3'))
     automata.add_edge(state2, state4, Clickable('2-4'))
     automata.add_edge(state4, state5, Clickable('4-5'))
     automata.add_edge(state3, state5, Clickable('3-5'))
     automata.add_edge(state3, state5, Clickable('5-0'))
     automata.add_edge(state5, state6, Clickable('5-6'))
     self.assertEqual(automata.get_shortest_path(state0), [])
     edges = automata.get_shortest_path(state6)
     # 0-3, 3-5, 5-6
     self.assertEqual([int(e[0].get_id()) for e in edges], [0, 3, 5])
Example #2
0
    def test_automata(self):
        dom1 = self.automata.get_current_state().get_dom()
        dom1 += '<custom></custom>'
        dom2 = dom1
        state1 = State(dom1)
        state2 = State(dom2)
        self.automata.add_state(state1)
        state3, is_newly_added = self.automata.add_state(state2)
        self.assertTrue(state3 == state1)
        self.assertFalse(is_newly_added)
        self.assertEqual(len(self.automata.get_states()), 2)

        clickable = self.automata.get_current_state().get_clickables()[0]
        clickable2 = Clickable('', '//html/body/button[3]')
        self.assertEqual(len(self.automata.get_current_state().get_clickables()), 1)
        self.automata.get_current_state().add_clickable(clickable)
        self.automata.get_current_state().add_clickable(clickable2)
        self.automata.get_current_state().add_clickable(clickable2)
        self.assertEqual(len(self.automata.get_current_state().get_clickables()), 2)

        self.automata.add_edge(self.automata.get_current_state(), state1, self.automata.get_current_state().get_clickables()[0])
        self.assertEqual(len(self.automata.get_edges()), 1)

        state1.add_prev_state(self.automata.get_current_state())

        self.assertEqual(self.automata.get_current_state().get_id(), '0')
        self.automata.change_state(state1)
        self.assertEqual(self.automata.get_initial_state().get_id(), '0')
        self.assertEqual(self.automata.get_current_state().get_id(), '1')
        self.assertEqual(self.automata.get_current_state().get_prev_states()[0].get_id(), '0')

        '''
Example #3
0
 def __init__(self, fname=None, load_dom=False):
     self._states = []
     self._edges = []
     self._initial_state = None
     self._current_state = None
     if fname:
         assert os.path.isfile(fname) and os.path.exists(fname)
         t_start = time.time()
         with open(fname) as f:
             data = json.load(f)
             for state in data['state']:
                 if load_dom:
                     with open(
                             os.path.join(
                                 os.path.dirname(os.path.realpath(fname)),
                                 state['dom_path']), 'r') as df:
                         s = State(df.read())
                 else:
                     s = State(state['id'])
                 s.set_id(state['id'])
                 for form in state['form']:
                     f = FormField(form['id'], form['xpath'])
                     for the_input in form['input']:
                         f.add_input(
                             InputField(the_input['id'], the_input['xpath'],
                                        the_input['type'],
                                        the_input['value']))
                     s.add_form(f)
                 for clickable in state['clickable']:
                     c = Clickable(clickable['id'], clickable['xpath'],
                                   clickable['tag'])
                     for form in clickable['form']:
                         f = s.get_form_by_id(form['id'])
                         assert f
                         c.add_form(f)
                     s.add_clickable(c)
                 self.add_state(s)
             for edge in data['edge']:
                 from_state = self.get_state_by_id(edge['from'])
                 to_state = self.get_state_by_id(edge['to'])
                 clickable = from_state.get_clickable_by_id(
                     edge['clickable'])
                 assert from_state and to_state and clickable
                 self.add_edge(from_state, to_state, clickable)
         logger.info('automata loaded. loading time: %f sec',
                     time.time() - t_start)
Example #4
0
 def test_generate_report(self):
     num_clickables = {
         'unexamined': 5,
         'true':  10,
         'false': 30
     }
     form1 = FormField('form1')
     form1.add_input(InputField('username', '//*[@id="username"]', 'castman'))
     form1.add_input(InputField('password', '', 'p@ssw0rd'))
     form_list = [{
         'state': 1,
         'form': form1,
         'execution_seq': [Clickable('exe1', '//html/body/button[1]'), Clickable('exe2', '//html/body/button[1]')],
         'clickable': [Clickable('btn1', '//html/body/button[1]'), Clickable('btn2', '//html/body/button[1]')]
     }]
     inv_violation = [{
         'state': 2,
         'name': '{"name": "file-not-found"}',
         'sequence': [Clickable('inv-btn1', '//html/body/button[1]'), Clickable('inv-btn2', '//html/body/button[1]')]
     }]
     Visualizer.generate_report(
         'web',
         'trace/example-app-4-webide',
         'automata.json',
         3, num_clickables, form_list, inv_violation, 9.987
     )
    def run_arch_test(self,
                      arch=None,
                      arch_agnostic_builder=False,
                      build_cmd=True,
                      restrict_arch_env=None,
                      restrict_arch=None,
                      expect_exception=False):
        config_env = {}
        if restrict_arch_env:
            config_env['CLICKABLE_ARCH'] = restrict_arch_env

        config_json = {}
        if arch_agnostic_builder:
            config_json["builder"] = "pure"
        else:
            config_json["builder"] = "cmake"
        if restrict_arch:
            config_json["restrict_arch"] = restrict_arch

        cli_args = []
        if arch:
            cli_args += ["--arch", arch]

        parser = Clickable.create_parser("Unit Test Call")
        run_args = parser.parse_args(cli_args)

        commands = ['no_command']
        if build_cmd:
            commands.append('build')

        self.setUpConfig(
            expect_exception = expect_exception,
            mock_config_json = config_json,
            mock_config_env = config_env,
            args = run_args,
            commands = commands,
        )

        if arch:
            expected_arch = arch
        elif restrict_arch:
            expected_arch = restrict_arch
        elif arch_agnostic_builder:
            expected_arch = "all"
        elif restrict_arch_env:
            expected_arch = restrict_arch_env
        else:
            expected_arch = "armhf"

        if not expect_exception:
            self.assertEqual(expected_arch, self.config.arch)
Example #6
0
    def setUp(self):
        self.clickable = Clickable()
        self.original_path = os.getcwd()

        self.path = os.path.join(os.path.dirname(__file__), 'tmp')
        self.app_path = os.path.join(self.path, 'appname')

        if os.path.exists(self.path):
            shutil.rmtree(self.path)

        os.makedirs(self.path)
        os.chdir(self.path)

        os.environ['CLICKABLE_DEFAULT'] = 'clean build review'
        os.environ['CLICKABLE_ARCH'] = 'amd64'

        self.config_file = os.path.expanduser(
            '~/.clickable/cookiecutter_config.yaml')
        self.tmp_config_file = '/tmp/cookiecutter_config.yaml'
        self.restore_config = False
        if os.path.exists(self.config_file):
            os.rename(self.config_file, self.tmp_config_file)
            self.restore_config = True
Example #7
0
 def __init__(self, fname=None, load_dom=False):
     self._states = []
     self._edges = []
     self._initial_state = None
     self._current_state = None
     if fname:
         assert os.path.isfile(fname) and os.path.exists(fname)
         t_start = time.time()
         with open(fname) as f:
             data = json.load(f)
             for state in data['state']:
                 if load_dom:
                     with open(os.path.join(os.path.dirname(os.path.realpath(fname)), state['dom_path']), 'r') as df:
                         s = State(df.read())
                 else:
                     s = State(state['id'])
                 s.set_id(state['id'])
                 for form in state['form']:
                     f = FormField(form['id'], form['xpath'])
                     for the_input in form['input']:
                         f.add_input(InputField(the_input['id'], the_input['xpath'], the_input['type'], the_input['value']))
                     s.add_form(f)
                 for clickable in state['clickable']:
                     c = Clickable(clickable['id'], clickable['xpath'], clickable['tag'])
                     for form in clickable['form']:
                         f = s.get_form_by_id(form['id'])
                         assert f
                         c.add_form(f)
                     s.add_clickable(c)
                 self.add_state(s)
             for edge in data['edge']:
                 from_state = self.get_state_by_id(edge['from'])
                 to_state = self.get_state_by_id(edge['to'])
                 clickable = from_state.get_clickable_by_id(edge['clickable'])
                 assert from_state and to_state and clickable
                 self.add_edge(from_state, to_state, clickable)
         logger.info('automata loaded. loading time: %f sec', time.time() - t_start)
 def build_trace(self, data):
     try:
         edges = []
         for edge in data['edges']:
             state_from = edge['from']
             state_to = edge['to']
             c = edge['clickable']
             clickable = Clickable(c['id'], c['name'], c['xpath'], c['tag'])
             inputs = []
             for i in edge['inputs']:
                 inputs.append(
                     InputField(i['id'], i['name'], i['xpath'], i['type'],
                                i['value']))
             selects = []
             for s in edge['selects']:
                 selects.append(
                     SelectField(s['id'], s['name'], s['xpath'], s['value'],
                                 s['selected']))
             checkboxes = []
             for c_field in edge['checkboxes']:
                 c_list = []
                 for c in c_field['checkbox_list']:
                     c_list.append(
                         Checkbox(c['id'], c['name'], c['xpath'],
                                  c['value']))
                 checkboxes.append(
                     CheckboxField(c_list, c_field['checkbox_name'],
                                   c_field['checkbox_selected_list']))
             radios = []
             for r_field in edge['radios']:
                 r_list = []
                 for r in r_field['radio_list']:
                     r_list.append(
                         Radio(r['id'], r['name'], r['xpath'], r['value']))
                 radios.append(
                     RadioField(r_list, r_field['radio_name'],
                                r_field['radio_selected']))
             iframe_list = edge['iframe_list']
             edges.append(
                 Edge(state_from, state_to, clickable, inputs, selects,
                      checkboxes, radios, iframe_list))
         return edges
     except Exception as e:
         logging.error('can not build trace: %s', str(e))
def load_automata(fname):
    t_start = time.time()
    assert os.path.isfile(fname) and os.path.exists(fname)
    automata = Automata()
    with open(fname) as f:
        data = json.load(f)
        for state in data['state']:
            with open(os.path.join(os.path.dirname(os.path.realpath(fname)), state['dom_path']), 'r') as df:
                s = State(df.read())
                s.set_id(state['id'])
                for clickable in state['clickable']:
                    c = Clickable(clickable['id'], clickable['xpath'], clickable['tag'])
                    s.add_clickable(c)
                automata.add_state(s)
        for edge in data['edge']:
            from_state = automata.get_state_by_id(edge['from'])
            to_state = automata.get_state_by_id(edge['to'])
            clickable = from_state.get_clickable_by_id(edge['clickable'])
            assert from_state and to_state and clickable
            automata.add_edge(from_state, to_state, clickable)
    return automata
    def get_clickables(cls, cs, prev_s=None):
        # only return newly discovered clickables, i.e. clickables not in prev_clickables
        cs_candidate_clickables_dict = cs.get_all_candidate_clickables()
        prev_candidate_clickables_dict = prev_s.get_all_candidate_clickables(
        ) if prev_s else None
        clickables_iframe_list = []

        for iframe_path_key in cs_candidate_clickables_dict.keys():
            #find prev_candidate_clickables if prev_s exists and iframe_path_list same
            cs_candidate_clickables = cs_candidate_clickables_dict[
                iframe_path_key]
            prev_candidate_clickables = None
            clickables = []
            if prev_candidate_clickables_dict:
                for prev_i in prev_candidate_clickables_dict.keys():
                    if iframe_path_key == prev_i:
                        prev_candidate_clickables = prev_candidate_clickables_dict[
                            prev_i]
                        break
            for candidate_clickable, clickable_xpath in cs_candidate_clickables:
                #find if candidate_clickable is same in prev
                if not cls._is_same_soup_in_prev( prev_candidate_clickables, candidate_clickable, clickable_xpath ) \
                        and not cls._is_duplicate(clickables, candidate_clickable):
                    clickable_id = cls.make_id(
                        candidate_clickable.get('id') if candidate_clickable.
                        has_attr('id') else None)
                    clickable_name = candidate_clickable.get(
                        'name') if candidate_clickable.has_attr(
                            'name') else clickable_id
                    clickable_xpath = cls._get_xpath(candidate_clickable)
                    clickable_tag = candidate_clickable.name
                    clickables.append(
                        Clickable(clickable_id, clickable_name,
                                  clickable_xpath, clickable_tag))
            clickables_iframe_list.append((clickables, iframe_path_key))
        return clickables_iframe_list
Example #11
0
    def get_clickables(cls, dom, prev_dom=None):
        # only return newly discovered clickables and forms, i.e. clickables not in prev_clickables
        prev_clickables = []
        prev_forms = []
        if prev_dom:
            prev_soup = BeautifulSoup(prev_dom, 'html.parser')
            for tag in cls._clickable_tags:
                if tag.get_attr():
                    for attr, value in tag.get_attr().items():
                        prev_clickables += prev_soup.find_all(
                            tag.get_name(), attrs={attr: value})
                else:
                    prev_clickables += prev_soup.find_all(tag.get_name())
            prev_forms = prev_soup.find_all('form')
        soup = BeautifulSoup(dom, 'html.parser')
        forms = soup.find_all('form')
        clickables = []
        # clickables with forms and inputs attached
        for form in forms:
            if form in prev_forms:
                continue
            form_id = form.get('id')
            if not form_id:
                form_id = cls.serial_prefix + str(cls._serial_num)
                cls._serial_num += 1
            f = FormField(form_id, cls._get_xpath(form))
            for input_type in cls.input_types:
                inputs = form.find_all('input', attrs={'type': input_type})
                for my_input in inputs:
                    data_set = InlineDataBank.get_data(input_type)
                    if data_set:
                        value = random.choice(list(data_set))
                    else:
                        value = ''.join(
                            random.choice(string.lowercase) for i in xrange(8))
                    input_id = my_input.get('id')
                    if not input_id:
                        input_id = cls.serial_prefix + str(cls._serial_num)
                        cls._serial_num += 1
                    f.add_input(
                        InputField(input_id, cls._get_xpath(my_input),
                                   input_type, value))
            for tag in cls._clickable_tags:
                if tag.get_attr():
                    for attr, value in tag.get_attr().items():
                        candidate_clickables = form.find_all(
                            tag.get_name(), attrs={attr: value})
                else:
                    candidate_clickables = form.find_all(tag.get_name())
                for candidate_clickable in candidate_clickables:
                    if candidate_clickable in prev_clickables:
                        continue
                    clickable_id = candidate_clickable.get('id')
                    if not clickable_id:
                        clickable_id = cls.serial_prefix + str(cls._serial_num)
                        cls._serial_num += 1
                    c = Clickable(clickable_id,
                                  cls._get_xpath(candidate_clickable),
                                  tag.get_name())
                    c.add_form(f)
                    clickables.append(c)

        # other clickables
        for tag in cls._clickable_tags:
            if tag.get_attr():
                for attr, value in tag.get_attr().items():
                    candidate_clickables = soup.find_all(tag.get_name(),
                                                         attrs={attr: value})
            else:
                candidate_clickables = soup.find_all(tag.get_name())
            for candidate_clickable in candidate_clickables:
                #print candidate_clickable
                if candidate_clickable in prev_clickables:
                    continue
                if not cls._is_duplicate(clickables, candidate_clickable):
                    clickable_id = candidate_clickable.get('id')
                    if not clickable_id:
                        clickable_id = cls.serial_prefix + str(cls._serial_num)
                        cls._serial_num += 1
                    clickables.append(
                        Clickable(clickable_id,
                                  cls._get_xpath(candidate_clickable),
                                  tag.get_name()))
        return clickables
Example #12
0
 def run_clickable(self, cli_args=[]):
     parser = Clickable.create_parser("Integration Test Call")
     run_args = parser.parse_args(cli_args)
     self.run(run_args.commands, run_args)
Example #13
0
    def get_clickables(cls, dom, prev_dom=None):
        # only return newly discovered clickables and forms, i.e. clickables not in prev_clickables
        prev_clickables = []
        prev_forms = []
        if prev_dom:
            prev_soup = BeautifulSoup(prev_dom, 'html.parser')
            for tag in cls._clickable_tags:
                if tag.get_attr():
                    for attr, value in tag.get_attr().items():
                        prev_clickables += prev_soup.find_all(tag.get_name(), attrs={attr: value})
                else:
                    prev_clickables += prev_soup.find_all(tag.get_name())
            prev_forms = prev_soup.find_all('form')
        soup = BeautifulSoup(dom, 'html.parser')
        forms = soup.find_all('form')
        clickables = []
        # clickables with forms and inputs attached
        for form in forms:
            if form in prev_forms:
                continue
            form_id = form.get('id')
            if not form_id:
                form_id = cls.serial_prefix + str(cls._serial_num)
                cls._serial_num += 1
            f = FormField(form_id, cls._get_xpath(form))
            for input_type in cls.input_types:
                inputs = form.find_all('input', attrs={'type': input_type})
                for my_input in inputs:
                    data_set = InlineDataBank.get_data(input_type)
                    if data_set:
                        value = random.choice(list(data_set))
                    else:
                        value = ''.join(random.choice(string.lowercase) for i in xrange(8))
                    input_id = my_input.get('id')
                    if not input_id:
                        input_id = cls.serial_prefix + str(cls._serial_num)
                        cls._serial_num += 1
                    f.add_input(InputField(input_id, cls._get_xpath(my_input), input_type, value))
            for tag in cls._clickable_tags:
                if tag.get_attr():
                    for attr, value in tag.get_attr().items():
                        candidate_clickables = form.find_all(tag.get_name(), attrs={attr: value})
                else:
                    candidate_clickables = form.find_all(tag.get_name())
                for candidate_clickable in candidate_clickables:
                    if candidate_clickable in prev_clickables:
                        continue
                    clickable_id = candidate_clickable.get('id')
                    if not clickable_id:
                        clickable_id = cls.serial_prefix + str(cls._serial_num)
                        cls._serial_num += 1
                    c = Clickable(clickable_id, cls._get_xpath(candidate_clickable), tag.get_name())
                    c.add_form(f)
                    clickables.append(c)

        # other clickables
        for tag in cls._clickable_tags:
            if tag.get_attr():
                for attr, value in tag.get_attr().items():
                    candidate_clickables = soup.find_all(tag.get_name(), attrs={attr: value})
            else:
                candidate_clickables = soup.find_all(tag.get_name())
            for candidate_clickable in candidate_clickables:
                #print candidate_clickable
                if candidate_clickable in prev_clickables:
                        continue
                if not cls._is_duplicate(clickables, candidate_clickable):
                    clickable_id = candidate_clickable.get('id')
                    if not clickable_id:
                        clickable_id = cls.serial_prefix + str(cls._serial_num)
                        cls._serial_num += 1
                    clickables.append(Clickable(clickable_id, cls._get_xpath(candidate_clickable), tag.get_name()))
        return clickables
Example #14
0
class TestTemplates(TestCase):
    def setUp(self):
        self.clickable = Clickable()
        self.original_path = os.getcwd()

        self.path = os.path.join(os.path.dirname(__file__), 'tmp')
        self.app_path = os.path.join(self.path, 'appname')

        if os.path.exists(self.path):
            shutil.rmtree(self.path)

        os.makedirs(self.path)
        os.chdir(self.path)

        os.environ['CLICKABLE_DEFAULT'] = 'clean build review'
        os.environ['CLICKABLE_ARCH'] = 'amd64'

        self.config_file = os.path.expanduser(
            '~/.clickable/cookiecutter_config.yaml')
        self.tmp_config_file = '/tmp/cookiecutter_config.yaml'
        self.restore_config = False
        if os.path.exists(self.config_file):
            os.rename(self.config_file, self.tmp_config_file)
            self.restore_config = True

    def tearDown(self):
        shutil.rmtree(self.path)
        os.chdir(self.original_path)

        os.environ['CLICKABLE_DEFAULT'] = ''
        os.environ['CLICKABLE_ARCH'] = ''

        if self.restore_config:
            os.rename(self.tmp_config_file, self.config_file)

    def create_and_run(self, template):
        config = ConfigMock()
        config.container = Container(config)
        command = CreateCommand(config)

        command.run(path_arg=template, no_input=True)

        os.chdir(self.app_path)
        self.clickable.run(['clean', 'build'])

    def assertClickExists(self, arch):
        click = os.path.join(
            self.app_path,
            'build/x86_64-linux-gnu/app/appname.yourname_1.0.0_amd64.click')
        if arch == 'all':
            click = os.path.join(
                self.app_path,
                'build/all/app/appname.yourname_1.0.0_all.click')

        self.assertTrue(os.path.exists(click))

    def test_qml_only(self):
        self.create_and_run('QML Only')
        self.assertClickExists('all')

    def test_cpp_plugin(self):
        self.create_and_run('C++ (Plugin)')
        self.assertClickExists('amd64')

    def test_cpp_binary(self):
        self.create_and_run('C++ (Binary)')
        self.assertClickExists('amd64')

    def test_python(self):
        self.create_and_run('Python')
        self.assertClickExists('all')

    def test_html(self):
        self.create_and_run('HTML')
        self.assertClickExists('all')

    # TODO enable this once the go qt library is fixed
    '''
    def test_go(self):
        self.create_and_run('Go')
        self.assertClickExists('amd64')
    '''

    def test_rust(self):
        # TODO see if the rust template can support automatically changing the arch in the manifest

        config = ConfigMock()
        config.container = Container(config)
        command = CreateCommand(config)

        command.run(path_arg='Rust', no_input=True)

        manifest_path = os.path.join(self.app_path, 'manifest.json')
        with open(manifest_path, 'r') as manifest_reader:
            manifest = json.load(manifest_reader)
            manifest['architecture'] = 'amd64'

            with open(manifest_path, 'w') as manifest_writer:
                json.dump(manifest, manifest_writer, indent=4)

        os.chdir(self.app_path)
        self.clickable.run(['clean', 'build'])

        self.assertClickExists('amd64')
Example #15
0
    def setUp(self):
        dom1 = '''
            <!DOCTYPE html>
            <html lang="en">
            <head> <meta charset="UTF-8"> <title></title> </head>
            <body>dom1</body>
            </html>
        '''
        state = State(dom1)
        self.automata = Automata()
        self.automata.add_state(state)
        self.assertEqual(len(self.automata.get_states()), 1)
        self.assertEqual(self.automata.get_initial_state().get_id(), self.automata.get_current_state().get_id())
        self.assertEqual(self.automata.get_current_state().get_id(), '0')

        # test adding and removing inputs and forms
        form1 = FormField('form1')
        form1.add_input(InputField('username', '//*[@id="username"]', 'castman'))
        form1.add_input(InputField('password', '', 'p@ssw0rd'))
        form1.add_input(InputField('password', '', 'p@ssw0rd'))
        self.assertEqual(len(form1.get_inputs()), 2)
        form1.remove_input(InputField('username', '//*[@id="username"]', 'castman'))
        self.assertEqual(len(form1.get_inputs()), 1)

        form2 = FormField('', '//*[@id="lst-ib"]')
        clickable = Clickable('', '//*[@id="btn1"]')
        clickable.add_form(form1)
        clickable.add_form(FormField('form1'))
        clickable.add_form(form2)
        self.assertEqual(len(clickable.get_forms()), 2)
        clickable.remove_form(FormField('', '//*[@id="lst-ib"]'))
        self.assertEqual(len(clickable.get_forms()), 1)

        # add the clickable into state 0
        self.automata.get_current_state().add_clickable(clickable)