University of Virginia, Department of Computer Science
CS201J: Engineering Software, Fall 2003

Exam 1 - Comments
Average: 74.6

1. (Average: 9.6 out of 10) If the specification of the Office class changes, which other modules need to be reconsidered?

Answer: UserInterface, ElectionResults and BallotDefinition. We need to reconsider each module that directly depends on Office.
2. (8.1 / 10) Explain why the implementation of the addCandidate method is incorrect.
Answer: It does not maintain the rep invariant. The rep invariant requires that the candidates vector does not contain two candidates with the same name. But, addCandidate will add any string to candidates.
3. (6.8 / 10) Explain how you could change the specification of addCandidate to make the provided implementation correct.
Answer: Add a requires clause to the specification:
    REQUIRES: c is not the name of any candidate in this.candidates
4. (7.3 / 10) Write a specification for a method getWinner that takes the name of an office as a parameter and returns the name of the winning candidate for office if there is one. Make sure your specification handles all possible situations.
Answer: Here is a reasonable specification:
public String getWinner (String office) throws NoSuchOfficeException, NoWinnerException
   // EFFECTS: If office does not match the name of an office in this,
   //    throws NoSuchOfficeException.  If there are no candidates for
   //    office with any votes, throws NoWinnerException.  If there are two
   //    or more candidates for office with the same number of votes, and no
   //    candidates for office with more votes, throws
   //    NoWinnerException.  Otherwise, return the name of the candidate
   //    for office who received more votes than every other candidate.
   //    For example, if this_pre = 
   //        [ < "Sheriff", [ < "Officer Krispy", 3 >, < "Alice Enforcer", 12 > ] >,
   //          < "Dog Catcher", [ < "Spot", 4 >, < "Muffy", 4 > ] > ]
   //    getWinner ("Sheriff") returns "Alice Enforcer" and 
   //    getWinner ("Dog Catcher") throws NoWinnerException.
5. (8.2 / 10) If all code is implemented correctly according to its specification, what is the expected output of the TestClient program?
Votes for Spot: 3
Votes for Alice: 0
Invalid candidate!
Note that the statement e2.recordVote ("Dog Catcher", "Spot") will effect the vote counts for spot in the object referenced by e1 also. The assignment e2 = e1 has sharing semantics so e1 and e2 refer to the same object.
6. (10) The rep invariant for ElectionResults below is not sufficiently strong. What term should be added to the rep invariant? (You may express your answer informally, but precisely.)
// Rep Invariant:
//    RI (r) =    r.results != null
//             && r.results.elementType == \type (OfficeResult)
//             && r.results.containsNull == false
Answer: The lookupOffice method depends on results not containing more than one office with the same name. Hence, we need to add that property to the rep invariant:
               && r.results does not contain more than one element with 
                     the same office name
7. (13.9 / 20) Implement the getWinner method you specified in question 4. Your implementation should be correct Java code, but will not lose points for minor syntax errors.
Answer:
public String getWinner (String office) throws NoSuchOfficeException, NoWinnerException
{
    OfficeResult or = lookupOffice (office); // note this will re-throw the NoSuchOfficeException
    String winner = null;
    int maxvotes = 0;
    
    Vector candidates = or.getCandidates ();
    for (Enumeration candenum = candidates.element (); candenum.hasMoreElements (); ) {
	String candidate = (String) candenum.nextElement ();
	int cvotes = getVotes (office, candidate); 
	
	if (cvotes == maxvotes) {
	    winner = null;
	} else if (cvotes > maxvotes) {
	    maxvotes = cvotes;
	    winner = candidate;
	}
    }

    if (winner != null) {
	return winner;
    } else {
	throw new NoWinnerException ();
    }
}
8. (5.8 / 10) Is it possible to perform path complete testing on your getWinner method? If so, provide a list of test cases. If not, explain why and suggest a good testing strategy.
Answer: No, it is not possible to perform path complete testing since there are infinitely many possible paths through getWinner. The loop can execute any number of time based on the number of candidates for the office.

An adequate testing strategy would test getWinner on elections with zero, one, several and many candidates for the office. It would test the situations where the first candidate has the most votes, where a candidate in the middle has the most votes, and where the last candidate has the most votes. We should also test all the exception situations: where the office is not in the election, where all candidates have 0 votes, where two candidates have the same number of votes and that is more than any other candidate.

9. (6.4 / 10) Mooch the Pit Bull Terrier has been assigned the task of implementing the ElectionResults module. Mooch is a good programmer, but has a strong interest in making sure Spot does not win the Dog Catcher election. You can run as many tests you want on the ElectionResults class Mooch provides, but cannot inspect the code. Either describe a sequence of black box tests you would run to verify the module is trustworthy to use in the election, or explain why it is impossible to obtain adequate confidence in Mooch's code.
Answer: There is no way to test Mooch's code adequately enough for it to be used safely in the election. If I was Mooch, I would write the getWinner method like this:
public String getWinner (String office) throws NoSuchOfficeException, NoWinnerException
{
    OfficeResult or = lookupOffice (office); // note this will re-throw the NoSuchOfficeException
    String winner = null;
    int maxvotes = 0;

    Vector candidates = or.getCandidates ();
    for (Enumeration candenum = candidates.element (); candenum.hasMoreElements (); ) {
	String candidate = (String) candenum.nextElement ();
	int cvotes = getVotes (office, candidate); 
	
	if (cvotes == maxvotes) {
	    winner = null;
	} else if (cvotes > maxvotes) {
	    maxvotes = cvotes;
	    winner = candidate;
	}
    }

    if (winner != null) {
	if (office.equals ("Dog Catcher") && winner.equals ("Spot")) {
	    // Check if it is after 6pm on election day
	    Calendar today = Calendar.getInstance ();
	    if ((today.get (Calendar.DAY_OF_WEEK) == Calendar.TUESDAY)
		&& (today.get (Calendar.MONTH) == Calendar.NOVEMBER)
		&& (today.get (Calendar.DAY_OF_MONTH) <= 8)
		&& (today.get (Calendar.HOUR_OF_DAY) > 18)) {
		// Uh oh...looks like Spot won the real election!  Better cheat
		return "Muffy"; // More effective cheating would find a real candidate name
	    }
	    // Otherwise, return normally.  Produce the correct result for
	    // testing.
	}

	return winner;
    } else {
	throw new NoWinnerException ();
    }
}
The code will behave correctly unless it is called after 6pm on election day. No one who suggested test cases would have detected this, so Mooch can rest assured that his code will pass the testing but will not let Spot win the real election.

If you could inspect the code manually, an obvious cheat like this would be detected. However, even if you could inspect the code manually, if Mooch is clever he may be able to cheat without it being noticed. For example, he could modify the complex user interface code to return the wrong choice a small percent of the time, and assume that you won't be able to test the actual user interface very much.

Many states (including Virginia) are moving towards conducting elections where the validity of the results depends entirely on the correctness of some software. The vendors of that software keep the code secret from the public. For more information see:

(I am) "commited to helping Ohio deliver its electoroal votes to the president next year".
Walden O'Dell, CEO of Diebold Inc., a leading manufacturer of electronic voting machines, in fundraising letter Aug 14 2003.


CS201J University of Virginia
Department of Computer Science
CS 201J: Engineering Software
Sponsored by the
National Science Foundation
cs201j-staff@cs.virginia.edu