Example #1
0
    def test_equivalence(
            self, fsm: Union[DFA, MealyMachine]) -> Tuple[bool, Iterable]:
        print("[info] Starting equivalence test")
        # Don't bother with the distinguishing set for now
        W = get_distinguishing_set(fsm)

        P = get_state_cover_set(fsm)
        print("[info] Got state cover set")
        A = sorted([(x, ) for x in fsm.get_alphabet()])

        equivalent = True
        counterexample = None

        for access_sequence in sorted(P, key=len, reverse=self.longest_first):
            #print("[info] Trying access sequence:", access_sequence)
            to_visit = deque()
            to_visit.extend(A)

            while len(to_visit) > 0:
                cur = to_visit.popleft()
                #print(cur)
                # Check cache if this is invalid input
                if access_sequence + cur in self.sul.invalid_cache:
                    continue

                # Check cache if this is a known error
                prefix, value = self.sul.error_cache.shortest_prefix(" ".join(
                    [str(x) for x in access_sequence + cur]))
                if prefix is not None:
                    # Do check it tho
                    equivalent, counterexample = self._are_equivalent(
                        fsm, access_sequence + cur)
                    if not equivalent:
                        return equivalent, counterexample
                    continue

                # If the test is of sufficient length, execute it
                #if len(cur) == self.m:
                #print("[Testing]", access_sequence + cur)
                for w in [tuple()] + list(W):
                    equivalent, counterexample = self._are_equivalent(
                        fsm, access_sequence + cur + w)
                    if not equivalent:
                        return equivalent, counterexample

                # If not, keep building
                #else:
                if len(cur) < self.m:
                    for a in A:
                        if access_sequence + cur + a not in self.sul.invalid_cache:
                            to_visit.append(cur + a)

        return equivalent, counterexample
Example #2
0
    def test_equivalence(self, test_sul: SUL) -> Tuple[bool, Iterable]:
        P = get_state_cover_set(test_sul)
        W = get_distinguishing_set(test_sul, check=False)

        equivalent = True
        counterexample = None

        for acc_seq in P:
            equivalent, counterexample = self.blockcopy(acc_seq, test_sul, W)
            if not equivalent:
                return equivalent, counterexample

        return equivalent, counterexample
    def _update_afl_queue(self, fsm: Union[DFA, MealyMachine]):
        # Make sure we have a folder to put our stuff in
        queuepath = self.afl_dir.joinpath(f'output/{self.name}/queue')
        queuepath.mkdir(exist_ok=True, parents=True)

        state_cover = get_state_cover_set(fsm)

        for acc_seq in state_cover:
            acc_seq = tuple(acc_seq)

            if acc_seq not in self.feedback_seqs:
                filename = f'id:{str(len(self.feedback_seqs)).rjust(6, "0")}'
                with open(queuepath.joinpath(filename), 'wb') as file:
                    for a in acc_seq:
                        file.write(bytes([int(a)]))
                self.feedback_seqs.add(acc_seq)
Example #4
0
    def test_equivalence(
            self, fsm: Union[DFA, MealyMachine]) -> Tuple[bool, Iterable]:
        print("Starting EQ test")

        n = len(fsm.get_states())
        m = self.m

        assert m >= n, "hypothesis has more states than w-method bound"

        depth = m - n

        print('Attempting to determine distinguishing set')
        W = get_distinguishing_set(fsm)
        if len(W) < 1:
            W.add(tuple())

        print('distinguishing:', W)
        P = get_state_cover_set(fsm)
        print('state cover:', P)
        X = fsm.get_alphabet()  #set([(x,) for x in fsm.get_alphabet()])

        equivalent = True
        counterexample = None

        order = sorted(range(1, depth + 1), reverse=self.longest_first)

        for i in order:
            print(i, '/', depth)
            for p in P:
                for x in product(X, repeat=i):
                    for w in W:
                        test_sequence = p + x + w
                        print(test_sequence)
                        equivalent, counterexample = self._are_equivalent(
                            fsm, test_sequence)
                        print("Test sequence: ", test_sequence)
                        if not equivalent:
                            print("COUNTEREXAMPLE:", counterexample)
                            return equivalent, counterexample

        return equivalent, None
    def _update_afl_queue(self, fsm: Union[DFA, MealyMachine]):
        # Make sure we have a folder to put our stuff in
        queuepath = Path(self.afl_out_dir).joinpath('learner01/queue')
        queuepath.mkdir(exist_ok=True, parents=True)

        state_cover = get_state_cover_set(fsm)
        for acc_seq in state_cover:
            fsm.reset()
            fsm.process_input(acc_seq)
            statename = fsm.state.name

            if statename in self.state_id:
                filename = self.state_id[statename]
            else:
                filename = f'id:{statename.rjust(6, "0")}'
                self.state_id[statename] = filename

            with open(queuepath.joinpath(filename), 'w') as file:
                for a in acc_seq:
                    file.write(f'{a} ')
                file.write('0 \n')
Example #6
0
    def test_equivalence(
            self, fsm: Union[DFA, MealyMachine]) -> Tuple[bool, Iterable]:
        print("[info] Starting equivalence test")
        if self.m is not None:
            n = len(fsm.get_states())
            m = self.m
            assert m >= n, "hypothesis has more states than w-method bound"
            depth = m - n
        else:
            depth = self.horizon

        print("Depth:", depth)

        print("[info] Calculating distinguishing set")
        W = get_distinguishing_set(fsm, check=False)

        P = get_state_cover_set(fsm)
        print("[info] Got state cover set")

        # Ensure all access sequences have a counter
        for p in P:
            if p not in self.acc_seq_ce_counter:
                self.acc_seq_ce_counter[p] = 0

        A = sorted([(x, ) for x in fsm.get_alphabet()])

        equivalent = True
        counterexample = None

        for access_sequence in self.acc_seq_order(P):
            print("[info] Trying access sequence:", access_sequence)
            to_visit = deque()
            to_visit.extend(A)

            while len(to_visit) > 0:
                cur = to_visit.popleft()

                # Grow the testing tree where possible
                self.sul.reset()
                sul_output_pre = self.sul.process_input(access_sequence + cur)
                if sul_output_pre in self.stop_on or any([
                        sul_output_pre.startswith(x)
                        for x in self.stop_on_startswith
                ]):
                    self.stopping_set.add(access_sequence + cur)
                    #continue
                elif len(cur) <= depth:
                    for a in A:
                        if access_sequence + cur + a not in self.stopping_set\
                                and access_sequence + cur + a not in P:
                            to_visit.append(cur + a)

                # Perform the standard W-method tests
                for w in W:
                    equivalent, counterexample = self._are_equivalent(
                        fsm, access_sequence + cur + w)
                    if not equivalent:

                        # find longest access sequence which overlaps with the current query
                        longest_acc_seq = None
                        cur_query = access_sequence + cur + w
                        for acc_seq in P:
                            if cur_query[0:len(acc_seq)] == acc_seq:
                                if longest_acc_seq is None or len(
                                        acc_seq) > len(longest_acc_seq):
                                    longest_acc_seq = acc_seq

                        print("Counterexample:", counterexample)
                        print("Longest acc seq:", longest_acc_seq)

                        self.acc_seq_ce_counter[longest_acc_seq] += 1
                        return equivalent, counterexample

            # Nothing found for this access sequence:
            self.acc_seq_ce_counter[access_sequence] = min(
                0, self.acc_seq_ce_counter[access_sequence])
            self.acc_seq_ce_counter[access_sequence] -= 1

        return equivalent, counterexample
Example #7
0
    def test_equivalence(
            self, fsm: Union[DFA, MealyMachine]) -> Tuple[bool, Iterable]:
        print("[info] Starting equivalence test")
        if self.m is not None:
            n = len(fsm.get_states())
            m = self.m
            assert m >= n, "hypothesis has more states than w-method bound"
            depth = m - n
        else:
            depth = self.horizon

        print("Depth:", depth)

        print("[info] Calculating distinguishing set")
        W = get_distinguishing_set(fsm, check=False)

        P = get_state_cover_set(fsm)
        print("[info] Got state cover set")

        A = sorted([(x, ) for x in fsm.get_alphabet()])

        equivalent = True
        counterexample = None

        acc_seq_tasks = deque(
            zip(self.acc_seq_order(P), [
                deque([a for a in A if a not in self.stopping_set])
                for x in range(len(P))
            ]))

        while len(acc_seq_tasks) > 0:
            access_sequence, to_visit = acc_seq_tasks.popleft()
            # bprint("[info] Trying access sequence:", access_sequence)
            assert len(to_visit) > 0

            cur = to_visit.popleft()

            # Test without distinguishing sequence, important for early stopping
            equivalent, counterexample = self._are_equivalent(
                fsm, access_sequence + cur)
            if not equivalent:
                return equivalent, counterexample

            if access_sequence + cur not in self.stopping_set:
                # Basically the usual W-method tests:
                for w in W:
                    equivalent, counterexample = self._are_equivalent(
                        fsm, access_sequence + cur + w)
                    if not equivalent:
                        return equivalent, counterexample

                # If not, keep building
                if len(cur) <= depth:
                    for a in A:
                        if access_sequence + cur + a not in self.stopping_set:
                            to_visit.append(cur + a)

            if len(to_visit) > 0:
                acc_seq_tasks.append((access_sequence, to_visit))
            #else:
            #print(access_sequence)

        return equivalent, counterexample
Example #8
0
    def test_equivalence(
            self, fsm: Union[DFA, MealyMachine]) -> Tuple[bool, Iterable]:
        print("[info] Starting equivalence test")
        if self.m is not None:
            n = len(fsm.get_states())
            m = self.m
            assert m >= n, "hypothesis has more states than w-method bound"
            depth = m - n
        else:
            depth = self.horizon

        print("Depth:", depth)

        print("[info] Calculating distinguishing set")
        W = get_distinguishing_set(fsm, check=False)

        P = get_state_cover_set(fsm)
        print("[info] Got state cover set")

        # Ensure all access sequences have a counter
        for p in P:
            if p not in self.acc_seq_ce_counter:
                self.acc_seq_ce_counter[p] = 0

        A = sorted([(x, ) for x in fsm.get_alphabet()])

        equivalent = True
        counterexample = None

        for access_sequence in self.acc_seq_order(P):
            print("[info] Trying access sequence:", access_sequence)
            to_visit = deque()
            to_visit.extend(A)

            while len(to_visit) > 0:
                cur = to_visit.popleft()

                # Basically the usual W-method tests:
                for w in W:
                    equivalent, counterexample = self._are_equivalent(
                        fsm, access_sequence + cur + w)
                    if not equivalent:
                        self.acc_seq_ce_counter[access_sequence] += 1
                        return equivalent, counterexample

                # Also test without distinguishing sequence, important for early stopping
                equivalent, counterexample = self._are_equivalent(
                    fsm, access_sequence + cur)
                if not equivalent:
                    self.acc_seq_ce_counter[access_sequence] += 1
                    return equivalent, counterexample

                # Cut this branch short?
                if access_sequence + cur in self.stopping_set:
                    continue

                # If not, keep building
                #else:
                if len(cur) <= depth:
                    for a in A:
                        if access_sequence + cur + a not in self.stopping_set:
                            to_visit.append(cur + a)

            # Nothing found for this access sequence:
            self.acc_seq_ce_counter[access_sequence] = min(
                0, self.acc_seq_ce_counter[access_sequence])
            self.acc_seq_ce_counter[access_sequence] -= 1

        return equivalent, counterexample