Total marks on this assignment: 80. This assignment counts 8% of total marks.

Learning goals: by completing this assignment, you’ll get some practical experience with writing
JUnit tests, with porting and debugging Java programs written by others, with developing a notquite-
Trivial Java application using threads, and with exploring the performance of heavily multithreaded
computations on a desktop or laptop computer.

Asking for help. If you become confused by Java syntax or semantics, or if you have difficulty using
your Java development environment, you should look on the internet or ask anyone for help. If you
do not understand the underlying concepts, such as the nature of a “test case”, you should start by
reviewing the assigned readings and lecture slides; but you are welcome to seek assistance from
others on “learning the concepts” after you have done your assigned readings for this course.

Working independently. You are not allowed to have assistance from any other person, or from the
internet, when you are writing your test cases, when you are interpreting your test results, when
you are designing your code, and when you are writing your code. All of this must be your own
work, done independently. If you have difficulty debugging, you may seek assistance from tutors or
lab assistants – they should not be telling you “how to fix your bug”, but they may be able to give
you some helpful and appropriate advice (for example, on what you could do to localise the defect,
or on what topic you should study which might help you figure out how to debug your own
program).

Resource requirements. This assignment can be completed if you are using only the basic javac/java
support provided in any recent SDK for Java. However you may wish take this opportunity to learn
how to use an IDE such as Eclipse -- if you don’t know how to do so already.

1.

In the Assignment 2 resources area of the Knowledge Map of the Cecil-site for CompSci 230,
you will find my transcription of Appendix A of the 2nd edition of Myers’ monograph on The
Art of Software Testing. This is a simple Java program (check4Prime.java) with seven
test cases (check4PrimeTest.java). Myers provides instructions for how to use a
command-line interface to Java in his Appendix A – you should read his instructions

Myers apparently used JUnit 3 and J2SE 1.4 when developing his code. You may use either
JUnit 3 or JUnit 4 to complete this question, and you may use any recent version of SE 1.6 or
SE 1.7.

a. (10 marks)
b. Develop an acceptance test for an import of check4Prime.java into
your development system. Your test should be described informally, but in enough
detail that another person – in particular the person who marks your assignment! –
can understand what you did. Your test should confirm that you are able to compile
and run this 8-year-old code (which was developed for an earlier version of Java) on
your system. Your test should be quite simple – taking at most a minute or two to
run.

Submit two or three items:

i. Your acceptance test: describe what input you presented to your build of
check4Prime.java, what output you expected, whether or not your
test was successful, and whether you observed anything extraordinary
about your development system while running this test.

ii. A description of your Java system, including the version numbers of your
SDK, your operating system, and any other software that might reasonably
be expected to affect the success of your importation.

iii. Submit this only if your acceptance test was unsuccessful: describe what you
did to try to identify the defect. If you were able to successfully import a
modified version of check4Prime.java, describe your modifications.

b. (6 marks) Develop an acceptance test for an import of check4PrimeTest.java
into your development system. Submit either two or three items, as for question 1a
above, depending on whether or not your importation was successful.
c. (9 marks) Develop two new test cases for check4PrimeTest.java.

Submit:
i. Your justification for your new cases, explaining the type(s) of errors you
were hoping to find when you designed these tests.
ii. The JUnit code for your test cases.
iii. A test report, indicating what happened when you ran these tests, anything
extraordinary you noticed while running your tests, and your interpretation
of your test results.

2. (55 marks, in total) In the Assignment 2 resources area of the Knowledge Map of the Cecilsite
for CompSci 230, you will find PrimeRace.jar This is a Java application with six classfiles.
a. (5 marks) Acceptance Testing. Download PrimeRace.jar into your development
area, and run the following tests.
i. The command “java primea2/PrimeRace“ prints a help message;
ii. The command “java primea2/PrimeRace 1000 1 10” runs for
approximately one second and prints approximately 6 lines of output;
iii. The command “javac primea2/*.java” creates a new set of classfiles
which pass tests i. and ii. above.

Submit: Your test report, which should have the following content.
i. A brief description of the relevant aspects of your software configuration,
for example the version number of your Java SDK.
ii. A brief description of your hardware configuration: your operating system,
CPU model, the maximum clock speed of your CPU, and the number of cores
in your CPU. (Note: you are encouraged to ask for help in discovering this
information. Your responsibility is to repeat the information-gathering
process for yourself, after someone has shown you how to do it, and then to
write down the information clearly on your assignment submission.)
iii. Your test results
iv. Your interpretation of your test results.

b. (10 marks) Performance testing. Run the following commands on your
development system.

1) java primea2/PrimeRace 1000 1 10
2) java primea2/PrimeRace 1000 1 10 1 10
3) java primea2/PrimeRace 1000 1 10 1 10 1 10
4) java primea2/PrimeRace 1000 1 10 1 10 1 10 1 10
5) java primea2/PrimeRace 1000 1 10 1 10 1 10 1 10 1 10
6) java primea2/PrimeRace 1000 1 10 1 10 1 10 1 10 1 10 1 10
7) java primea2/PrimeRace 1000 1 10 1 10 1 10 1 10 1 10 1 10 1 10
8) java primea2/PrimeRace 1000 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10
9) java primea2/PrimeRace 1000 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10
10) java primea2/PrimeRace 1000 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10
11) java primea2/PrimeRace 1000 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10 1 10
Note that the last two commands are identical – you’ll be running ten prime number
generators in parallel, when executing these commands. Each command should
take about one second to run. Now extract the following information from the
output of each command: the number of prime number generators being run in
parallel (these are called “primeRunners” in the output), the number of primes
generated by the “fastest” primeRunner, the number of primes generated by the
“slowest” primeRunner, and the lane number(s) of the fastest primeRunner.
Submit:
i. A plot of your results, with the number of primeRunners on the x-axis, and
the number of primes computed on the y-axis. Use “X” marks for data from
the fastest primeRunner, and “+” marks for data from the slowest
primeRunner.
ii. Your interpretation of your plotted data, answering the following questions.
Can you determine, from this data, the number of Java threads that your
computer can run simultaneously? Do you see any pattern or bias (e.g.
toward lane 1 or toward the highest-numbered lane) in your lane-number
data? You should not attempt a statistical analysis, but you should think
carefully about what is likely to happen if there are more primeRunners than
the hardware can run simultaneously. Each primeRunner is on its own
“worker” thread.
c. (10 marks) Code analysis. Inspect PrimeRace.java. You should be able to find the
statements which instantiate the worker threads (called “primeRacers” in the code),
as well as the statements which initialise these worker threads, start them, and join
them with the main thread.
Submit:
i. A greatly-shortened version of PrimeRace.java. This version should include
only statements which instantiate, initialise, start, or join worker threads.
ii. A swimlane diagram of PrimeRace.java, with the main thread in lane 0 (at
the left of your diagram) and two primeRacers in lanes 1 and 2. Use a
dotted vertical line to indicate the segment of time during which main() is
sleeping. Give appropriate labels to arrows on your diagram which indicate
how one thread is affecting another thread.

d. (10 marks) Test development. Develop JUnit test cases for this application, with
coverage similar to the cases in Myers’ testing of his primality-testing algorithm (in
Question 1 of this assignment), with additional cases to cover the TODO comments
in these classfiles. These comments are attached to statements which might throw
an exception or error that is not caught by the application.

Submit your test report, which should include:
i. Your test cases
ii. Your test results
iii. Your interpretation of your test results. If my PrimeRace application failed
any of your tests, your interpretation should include a description of the
defect you have identified and a suggestion for how this defect might be
remedied.
e. (10 marks) Code development. Modify PrimeRace.java, so that all primeRacers are
fully initialised before any worker thread is started. Re-run the tests of question 2b.
Submit:
i. A plot of your results, with the number of primeRunners on the x-axis, and
the number of primes computed on the y-axis. Use “X” marks for data from
the fastest primeRunner, and “+” marks for data from the slowest
primeRunner.
ii. Your interpretation of your plotted data, in comparison with the data you
plotted in question 2b. Your interpretation should answer the following
questions. Do you see any significant difference between these two plots?
Do your best to explain why there is (or isn’t) a major difference – but don’t
write more than a paragraph or two.

f. (10 marks) Performance and correctness of multi-threaded code. In an unmodified
copy of PrimeRace.jar, look for the statement “private volatile static boolean
finished = false;” near the beginning of PrimeRace.java. Replace it with
“private static AtomicBoolean finished = new AtomicBoolean();”. This is
likely to cause compilation errors, because an AtomicBoolean is a class, so it cannot
directly replace a Boolean variable (which is a primitive datatype). Modify the code,
as necessary, so that: 1) an AtomicBoolean instance is initially false; 2) this instance
it is set to true, by main(), when the race is over; and 3) this instance is polled by all
worker threads (“primeRacers”).
Run some tests on this code, either from the command line or using JUnit, to
determine whether this change has made a significant difference to the behaviour of
the code. Your tests should include “java primea2/PrimeRace 1000 2 1” and
“java primea2/PrimeRace 1000 3 1“, on both the original code and on the code
with the AtomicBoolean. These runs will poll the finished flag quite frequently; and
the JavaMath prime number generator (#3) will exercise the garbage collector
thread fairly heavily due to its allocation and de-allocation of BigIntegers during its
primality tests. You should not stress-test the code – none of your tests should run
for more than a minute. The objective is for you to see what you can learn about
this code from a small number of tests, not for you to spend a lot of time testing!

Submit:
i. A test report, describing the tests you ran and your interpretation of these
tests. Your interpretation should address the following questions. Does the
use of an AtomicBoolean, rather than a synchronised boolean, make a
significant difference in performance? Does it affect the correctness of the
computation? (When answering the latter question, you should be doing
some white-box testing and code analysis.)

//Check arguments, entering them into argvec
ArrayList<Integer> argvec = null;
try{
argvec = checkArgs( args );
} catch (Exception e) {
System.out.println("Usage: PrimeRace t n1 b1 n2 b2 ... ni bi");
System.out.println(" -- where t is the time limit, in milliseconds, for this computation;");
System.out.println(" -- ni is the prime number generation method used by the i-th worker thread,");
System.out.println(" ---- ni = 1, for a Sieve of Eratosthenes");
System.out.println(" ---- ni = 2, for a naive algorithm in Goetz's Introduction to Java threads");
System.out.println(" ---- ni = 3, for a probabilistic prime finder in Java.math.BigInteger");
System.out.println(" -- bi is the blocksize: the number of ints to be checked for primality");
System.out.println(" by ni, between its polls of the time-limit flag");
System.out.println(" -- Note that a large bi value makes it more likely that the i-th thread");
System.out.println(" will win the race to generate the most primes, because it will finish");
System.out.println(" checking its current block of ints for primality before terminating.");
System.exit(1);
}

// construct the primeRacers by interpreting the argvec
Iterator<Integer> i = argvec.iterator();

// the first arg is the timeLimit (a class variable)
timeLimit = i.next();

// main() needs to have a list of all racer threads, for the join().
// All racers will be terminated by the time main() prints the results,
// so main() also keeps a list of names
primeRacerThreads.add( t );
primeRacerNames.add( t.pName );

// t is now ready to run -- it's on the "starting block" of our racecourse

// There's no "starting gun"!! primeRacers start as soon as they're ready.
// Nobody said this would be a fair race ;-)
t.start();
}

// initialised is set to true after all threads are initialised
initialised = true;

// All primeRacers have been started. The main thread sleeps until the end of the race.
try {
Thread.sleep( timeLimit );
}
catch (InterruptedException e) {
System.out.println("Interrupted Exception to sleep() was ignored in main()!");
// If the println() above produces any console output, then this fall-through is unsafe.
// But, most likely, the exception was raised by a ^c console input that is terminating the
// entire JVM -- in which case, the println() above will not produce any console output and main()
// will be abnormally terminated very soon.
}

// Time's up! All primeRacers will stop generating primes after they finish their current block
finished = true;

//Check arguments, entering them into argvec
ArrayList<Integer> argvec = null;
try{
argvec = checkArgs( args );
} catch (Exception e) {
System.out.println("Usage: PrimeRace t n1 b1 n2 b2 ... ni bi");
System.out.println(" -- where t is the time limit, in milliseconds, for this computation;");
System.out.println(" -- ni is the prime number generation method used by the i-th worker thread,");
System.out.println(" ---- ni = 1, for a Sieve of Eratosthenes");
System.out.println(" ---- ni = 2, for a naive algorithm in Goetz's Introduction to Java threads");
System.out.println(" ---- ni = 3, for a probabilistic prime finder in Java.math.BigInteger");
System.out.println(" -- bi is the blocksize: the number of ints to be checked for primality");
System.out.println(" by ni, between its polls of the time-limit flag");
System.out.println(" -- Note that a large bi value makes it more likely that the i-th thread");
System.out.println(" will win the race to generate the most primes, because it will finish");
System.out.println(" checking its current block of ints for primality before terminating.");
System.exit(1);
}

// construct the primeRacers by interpreting the argvec
Iterator<Integer> i = argvec.iterator();

// the first arg is the timeLimit (a class variable)
timeLimit = i.next();

// main() needs to have a list of all racer threads, for the join().
// All racers will be terminated by the time main() prints the results,
// so main() also keeps a list of names
primeRacerThreads.add( t );
primeRacerNames.add( t.pName );

// t is now ready to run -- it's on the "starting block" of our racecourse

// There's no "starting gun"!! primeRacers start as soon as they're ready.
// Nobody said this would be a fair race ;-)
t.start();
}

// All primeRacers have been started. The main thread sleeps until the end of the race.
try {
Thread.sleep( timeLimit );
}
catch (InterruptedException e) {
System.out.println("Interrupted Exception to sleep() was ignored in main()!");
// If the println() above produces any console output, then this fall-through is unsafe.
// But, most likely, the exception was raised by a ^c console input that is terminating the
// entire JVM -- in which case, the println() above will not produce any console output and main()
// will be abnormally terminated very soon.
}

// Time's up! All primeRacers will stop generating primes after they finish their current block
finished.set(true);

Well sir I just wanted to know whether there are some flaw in my code? I'm new to jUnit testing and Java. I could not find any option to add attachments therefore I have added complete code.

10-10-2012, 10:06 AM

Tolls

Re: developing a notquite- Trivial Java application using threads

Few, if any, people will look at that much code, even if you managed to wrap it in [code] tags [/code] to retain its formatting.

If you have a problem with your code then ask a question about that problem, posting relevant code and any errors/exceptions in full, highlighting where they occur.
If it's a problem with the result, then you need to say what the result you expected was, and what the result you got was.