Homework 2

Please review the material in Lectures 3 through 5 and the concurrency-related slides at the beginning of lecture 6 to answer the questions below.

  1. There is a statement related to software testing that says Testing can only be used to prove the existence of faults not their absence. Explain what this statement means using the testing terminology that we discussed at the beginning of Lecture 5. (5 points)
  2. What are the elements of a test case when performing black box testing and how do you know if a blackbox test has passed? Write a simple function and then write two blackbox test cases for it. (10 points)
  3. Using the control flow graph from Lecture 5, explain why a test set that achieves statement coverage is not necessarily sufficient to achieve edge coverage. You do not need to prove this assertion in general; keep your remarks to this specific control flow graph first shown on slide 23. (10 points)
  4. What is the difference between how traditional software life cycles measure progress and how agile life cycles measure progress? (5 points)
  5. Consider the following Java program that is split across 6 files:


    Product.java:

    public class Product {
    
      private static int id = 0;
      private String name;
    
      public Product() {
        this.name = "Product<" + id + ">";
        id++;
      }
    
      public String toString() {
        return name;
      }
    
    }


    ProductionLine.java:

    import java.util.LinkedList;
    import java.util.List;
    
    public class ProductionLine {
    
       private List<Product> products;
    
       public ProductionLine() {
         products = new LinkedList<Product>();
       }
    
       public int size() {
         return products.size();
       }
    
       public void append(Product p) {
         products.add(p);
       }
    
       public Product retrieve() {
         return products.remove(0);
       }
    
    }


    Producer.java:

    public class Producer implements Runnable {
    
      private ProductionLine queue;
    
      public Producer(ProductionLine queue) {
        this.queue = queue;
      }
    
      public void run() {
        int count = 0;
        while (count < 20) {
          if (queue.size() < 10) {
            Product p = new Product();
            System.out.println("Produced: " + p);
            queue.append(p);
            count++;
          }
          try {
            Thread.sleep(100);
          } catch (Exception ex) {
          }
        }
      }
    
    }


    Consumer.java:

    public class Consumer implements Runnable {
    
      private ProductionLine queue;
    
      public Consumer(ProductionLine queue) {
        this.queue = queue;
      }
    
      public void run() {
        while (true) {
          if (queue.size() > 0) {
            System.out.println("Consumed: " + queue.retrieve());
          }
          try {
            Thread.sleep(1000);
          } catch (Exception ex) {
          }
        }
      }
    
    }


    Monitor.java:

    public class Monitor implements Runnable {
    
      private ProductionLine queue;
    
      public Monitor(ProductionLine queue) {
        this.queue = queue;
      }
    
      public void run() {
        while (true) {
          int size = queue.size();
          if (size > 10) {
            System.out.println("Too many items in the queue: " + size + "!");
          } else if (size == 0) {
            System.out.println("Queue empty!");
          }
          try {
            Thread.sleep(50);
          } catch (Exception ex) {
          }
        }
      }
    
    }


    Main.java:

    public class Main {
    
      public static void main(String[] args) {
        ProductionLine queue = new ProductionLine();
    
        Thread monitor = new Thread(new Monitor(queue));
    
        monitor.setDaemon(true);
        monitor.start();
    
        Thread[] consumers = new Thread[5];
    
        Thread[] producers = new Thread[10];
    
        for (int i = 0; i < consumers.length; i++) {
          consumers[i] = new Thread(new Consumer(queue));
          consumers[i].setDaemon(true);
          consumers[i].start();
        }
    
        for (int i = 0; i < producers.length; i++) {
          producers[i] = new Thread(new Producer(queue));
          producers[i].start();
        }
    
      }
    
    }


    This program should cause 200 products to be created and consumed but it gets nowhere close to that. Plus the monitor is constantly printing messages saying that the queue size is too big.

    Please describe what is wrong with this program from the standpoint of its use of concurrency and what problem or problems discused in Lecture 4 are at the root of the observed behavior. (5 points)

    Please also describe how you would fix the problem and include in your homework submission a fixed version of the program. (15 points)

This assignment is worth 50 points.

In-Class Students: Please upload a .zip or .tar.gz archive of your submission which will include a PDF file containing the answers to your questions along with the source code of the fixed consumer/producer program to the moodle before the start of Lecture 8 on Thursday, February 9th, and bring a hardcopy of your assignment and source code to Lecture 8.

CAETE Students: Please upload a .zip or .tar.gz archive (as described above) for this assignment to the moodle by 9:30 AM on Thursday, February 9th.


© University of Colorado, Boulder 2011