public CFSM(int numProcesses, List<ChannelId> channelIds) { super(numProcesses, channelIds); fsms = Util.newList(Collections.nCopies(numProcesses, (FSM) null)); unSpecifiedPids = numProcesses; firstSyntheticChIndex = Integer.MAX_VALUE; localEventsChIndex = Integer.MAX_VALUE; invs = Util.newList(); }
@Before public void setUp() throws Exception { super.setUp(); cids = Util.newList(2); cid1 = new ChannelId(1, 2, 0); cid2 = new ChannelId(2, 1, 1); cids.add(cid1); cids.add(cid2); chStates = Util.newList(2); chStates.add(new ChState<DistEventType>(cid1)); chStates.add(new ChState<DistEventType>(cid2)); }
@Test public void createEmpty() { mc = ImmutableMultiChState.fromChannelIds(cids); mc2 = ImmutableMultiChState.fromChannelIds(cids); // Make sure that the two instance pointers are identical, because of // internal caching. assertTrue(mc == mc2); assertTrue(mc.equals(mc2)); assertTrue(mc.hashCode() == mc2.hashCode()); // Now, attempt to create the same mc/mc2 instances, but by building // them from more explicit state instances. mc3 = ImmutableMultiChState.fromChannelStates(chStates); assertTrue(mc == mc3); assertTrue(mc.equals(mc3)); cids = Util.newList(2); cid1 = new ChannelId(1, 2, 0); cid2 = new ChannelId(2, 2, 1); cids.add(cid1); cids.add(cid2); mc3 = ImmutableMultiChState.fromChannelIds(cids); assertFalse(mc == mc3); assertFalse(mc.equals(mc3)); }
/** Returns the bad states for all invariants that augment this CFSM. */ public List<BadState> getBadStates() { assert !invs.isEmpty(); // TODO: Sub-optimality -- we are needlessly creating many lists by // calling getBadState(inv) repeatedly. List<BadState> ret = Util.newList(); for (BinaryInvariant inv : invs) { ret.addAll(getBadStates(inv)); } return ret; }
/** * Returns a set of bad states that correspond to a specific invariant that is augmenting this * CFSM. Each invariant corresponds to (possibly multiple) bad states. A bad states is a * combination of FSM states and a sequence of regular expressions that describe the contents of * each of the queues in the CFSM. For an invariant I, a bad state B has the property that if B is * reachable in the CFSM then I is falsified. That is, the path to reach B is the counter-example * for I. */ public List<BadState> getBadStates(BinaryInvariant inv) { assert invs.contains(inv); // Without invariants there are no bad states. if (invs.isEmpty()) { return Collections.emptyList(); } List<BadState> badStates = Util.newList(); Set<CFSMState> accepts = this.getAcceptStates(); if (accepts.isEmpty()) { assert !accepts.isEmpty(); } List<String> qReList = Util.newList(channelIds.size()); // Set non-synthetic queues reg-exps to accept the empty string. for (int i = 0; i < firstSyntheticChIndex; i++) { qReList.add("_"); } int invIndex = invs.indexOf(inv); // Set the synthetic queue reg-exps. for (int i = firstSyntheticChIndex; i < channelIds.size(); i++) { if (i == firstSyntheticChIndex + invIndex) { // The invariant we care about checking. qReList.add(inv.scmBadStateQRe()); } else if (i == localEventsChIndex) { // Add an RE for the local events queue. Set<String> localEvents = this.alphabet.getLocalEventScmStrings(); if (!localEvents.isEmpty()) { String localEventsQueueRe = "("; for (String eLocal : localEvents) { localEventsQueueRe += eLocal + " | "; } // Remove the last occurrence of the "|" character. localEventsQueueRe = localEventsQueueRe.substring(0, localEventsQueueRe.length() - 3); localEventsQueueRe += ")^*"; qReList.add(localEventsQueueRe); } else { // If there are no local events then the queue RE is the // empty string, since no corresponding local event messages // will be generated. qReList.add("_"); } } else { // Initialize non-inv invariant synthetic queues to accept // everything that their alphabet permits. qReList.add(inv.someSynthEventsQRe()); } } // For each accept, generate a bad state <accept, qReList>. for (CFSMState accept : accepts) { badStates.add(new BadState(accept, qReList)); } return badStates; }