Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
github-classroom[bot] authored Feb 13, 2024
0 parents commit afe60d0
Show file tree
Hide file tree
Showing 11 changed files with 614 additions and 0 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/java-sbt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Java sbt CI

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Run tests
run: sbt jacoco
46 changes: 46 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# built application files
*.apk
*.ap_

# files for the dex VM
*.dex

# Java class files
*.class

# generated files
bin/
gen/
logs/
proguard_cache/
target/
tmp/

# Local configuration file (sdk path, etc)
local.properties
.cache/
.classpath
.project
.settings/
*.iml
.idea/
local.sbt
.bsp/
.bloop/
.metals/
.vscode/
project/.bloop/
project/metals.sbt
project/project/
.jqwik-database

# Emacs files
*~
\#*\#

# Mac files
.DS_Store

# SBT configuration files
# remove if specific version of SBT is required
project/build.properties
10 changes: 10 additions & 0 deletions .gitpod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This configuration file was automatically generated by Gitpod.
# Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file)
# and commit this file to your remote git repository to share the goodness with others.

tasks:
- init: |
echo "sdkman_auto_answer=true" >> $HOME/.sdkman/etc/config
sdk install java 17.0.10-tem
sdk install sbt
sbt "Test / compile"
70 changes: 70 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Stateful unit testing using Jqwik actions: fixed-size circular queue

In this project, we'll implement and thoroughly test our own array-based data structure, a fixed-size circular queue!

## Objectives

An understanding of the following concepts and techniques:

- ADT implementation perspective
- queue ADT (see also [java.util.Queue](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Queue.html))
- implementing queue as a circular array
- queues with fixed versus growing capacity
- algorithms based on the queue's FIFO policy
- interface-based testing
- stateful property-based testing
- initial exposure to concurrency

## Instructions

In this project, you will have the opportunity to implement a generic queue as a circular array and use this implementation in the context of a typical queue-based application.

Specifically:

1. Complete the TODO items in the `FixedArrayQueue` implementation until the tests in `TestSimpleQueue` pass.
1. Complete the main class `SingleQueueService`, which reads successive input lines until EOF and
puts them on a queue that the background consumer activity processes.
1. When running the main class, note that the consumer is set to serve customers at a fixed rate.
By entering customers' names at different rates, try to create scenarios where customers arrive infrequently enough for the queue to remain empty, or in such quick succession that the queue becomes full (by pasting several of them at once).
1. Complete the TODO items in the `TestSimpleQueueJqwik` test suite until it reflects the stated pre- and postconditions of the `SimpleQueue` methods.
1. Answer the following questions in a separate file `Answers.md`:
- Why does `FixedArrayQueue` require an explicit constructor?
- What happens when you offer an item to a full `FixedArrayQueue`?
- What happens when you poll an empty `FixedArrayQueue`?
- What is the time and (extra) space complexity of each of the `FixedArrayQueue` methods?
- How exhaustively does the `TestSimpleQueue` test suite test the implementation, both conceptually and in terms of actual coverage?
- How exhaustively does the `TestSimpleQueueJqwik` test suite test the implementation, both conceptually and in terms of actual coverage?
- What kind of test cases does the `simpleQueueActions` method generate?

## Running the code

To run the tests:

sbt jacoco

To run the main program:

sbt run

## Grading (total 10 points)

- 3.5 completion of items marked TODO in `FixedArrayQueue` and tests passing
- 1 completion of `SingleQueueService` and correct behavior
- 3.5 completion of items marked TODO in `TestSimpleQueueJqwik` and working
- 2 written part
- 1.5 responses to the questions above
- 0.5 grammar, style, formatting

## Extra credit

Clearly indicate in your `Answers.md` file any extra credit attempted.

- 0.5 apply `checkSimpleQueue` property to different queue capacities
- 1 add a `clear` method, which removes all elements in the queue, to interface, impmlementation, and tests

## References

- [java.util.Queue interface](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Queue.html)
- [Introduction and Array Implementation of Circular Queue](https://www.geeksforgeeks.org/introduction-and-array-implementation-of-circular-queue)
- [Zombies testing](https://hackernoon.com/zombie-testing-one-behavior-at-a-time-9s2m3zjo)
- [Zombies testing with circular queue/buffer example](http://blog.wingman-sw.com/tdd-guided-by-zombies)
30 changes: 30 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name := "arrayqueue-jqwik-java-sbt"

version := "0.4"

compile / javacOptions += "-Xlint:all"

javaOptions += "-enableassertions"

ThisBuild / libraryDependencies ++= Seq(
"net.aichler" % "jupiter-interface" % "0.11.1" % Test,
"net.jqwik" % "jqwik" % "1.8.2" % Test
)

Test / parallelExecution := false

jacocoReportSettings := JacocoReportSettings()
.withThresholds(
JacocoThresholds(
instruction = 80,
method = 100,
branch = 100,
complexity = 100,
line = 90,
clazz = 100)
)
.withFormats(JacocoReportFormats.HTML)

jacocoExcludes := Seq("**.SingleQueueService*")

enablePlugins(JavaAppPackaging)
4 changes: 4 additions & 0 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.9.16")
addSbtPlugin("net.aichler" % "sbt-jupiter-interface" % "0.11.1")
addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.4.0")
addSbtPlugin("com.lightbend.sbt" % "sbt-java-formatter" % "0.8.0")
81 changes: 81 additions & 0 deletions src/main/java/edu/luc/cs271/arrayqueue/FixedArrayQueue.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package edu.luc.cs271.arrayqueue;

import java.util.ArrayList;
import java.util.List;

public class FixedArrayQueue<E> implements SimpleQueue<E> {

private final int capacity;

private int size;

private int front;

private int rear;

private final E[] data;

// TODO why do we need an explicit constructor?

@SuppressWarnings("unchecked")
public FixedArrayQueue(final int capacity) {
// TODO check argument validity

this.capacity = capacity;
this.data = (E[]) new Object[capacity];
this.size = 0;
this.front = 0;
this.rear = capacity - 1;
}

@Override
public boolean offer(final E obj) {
// TODO

return false;
}

@Override
public E peek() {
// TODO

return null;
}

@Override
public E poll() {
// TODO

return null;
}

@Override
public boolean isEmpty() {
// TODO
return true;
}

@Override
public boolean isFull() {
// TODO
return false;
}

@Override
public int size() {
return size;
}

@Override
public int capacity() {
return capacity;
}

@Override
public List<E> asList() {
// TODO implement using an ArrayList preallocated with the right size
final ArrayList<E> result = null;

return result;
}
}
88 changes: 88 additions & 0 deletions src/main/java/edu/luc/cs271/arrayqueue/SimpleQueue.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package edu.luc.cs271.arrayqueue;

import java.util.List;

/**
* Generic interface for a first-in-first-out (FIFO) data structure where objects are inserted into
* and removed from opposeite ends.
*
* <p>Based on Koffman & Wolfgang, Data Structures 3rd ed, Wiley 2015.
*
* @param <E> The element type
*/
public interface SimpleQueue<E> {
/**
* Adds an item to the end of the queue and returns a boolean to indicate whether the attempt
* succeded.
*
* @pre True.
* @post The queue is nonempty and one item larger than before.
* @param obj The object to be inserted
* @return true if the object has been inserted, false otherwise
*/
boolean offer(E obj);

/**
* Returns the object at the front of the queue without removing it.
*
* @pre True.
* @post The queue remains unchanged.
* @return The object at the front of the queue if one exists, null otherwise
*/
E peek();

/**
* Returns the object at the front of the queue and removes it.
*
* @pre True.
* @post The queue is one item smaller than before.
* @return The object at the front of the queue if one exists, null otherwise
*/
E poll();

/**
* Returns true if the queue is empty; otherwise, returns false.
*
* @pre True.
* @post The queue remains unchanged.
* @return true if the queue is empty, false otherwise
*/
boolean isEmpty();

/**
* Returns true if the queue is full; otherwise, returns false.
*
* @pre True.
* @post The queue remains unchanged.
* @return true if the queue is full, false otherwise
*/
boolean isFull();

/**
* Returns the size of the queue.
*
* @pre True.
* @post The queue remains unchanged.
* @return the size of the queue
*/
int size();

/**
* Returns the capacity (maximum size) of the queue.
*
* @pre True.
* @post The queue remains unchanged.
* @return the capacity of the queue
*/
int capacity();

/**
* Returns a Java list containing the items currently in the queue. The item at the front of the
* queue is the first item of the list (at index 0).
*
* @pre True.
* @post The queue remains unchanged.
* @return The list containing the items in the queue
*/
List<E> asList();
}
Loading

0 comments on commit afe60d0

Please sign in to comment.