Untitled
Anonymous
plain_text
02/08/2026 10:16 PM
23.3 KB
14
Indexable
import java.io.IOException;
import student.TestCase;
/**
* Test suite for the Songs database project.
*
* Exercises the SongsDB, Hash, and MemManager classes using
* the public Songs interface, plus direct unit tests where
* allowed, to validate behavior and output formatting.
*
* @author Leguejou Awunganyi
* @author Ishita Punna
* @version 2026-02-08
*/
public class SongsTest extends TestCase {
/**
* Shared Songs reference used by several tests.
* It is reset or re-created inside each test as needed.
*/
private Songs it;
/**
* Set up method run before each test. No shared
* fixture is required, so this method is empty.
*/
public void setUp() {
// Nothing to initialize globally for these tests.
}
/**
* Memory manager edge-case: start with very small pool size,
* force an expansion on insert, and verify strings are still
* stored and printed correctly via SongsDB.
*
* @throws IOException
* if an I/O error occurs (not expected here)
*/
public void testMemManEdge1() throws IOException {
SongsDB db = new SongsDB();
db.create(1, 8); // very small memory to trigger expansion quickly
// Insert a song that fits
db.insert("A", "S1");
// Insert a song that is larger than the remaining pool
String out = db.insert("B", "LONG_SONG_NAME");
// This should trigger memory pool expansion
assertTrue(out.contains("Memory pool expanded"));
// Check that both artist and song tables reflect the inserts
String artistPrint = db.print("artist");
String songPrint = db.print("song");
assertTrue(artistPrint.contains("A"));
assertTrue(artistPrint.contains("B"));
assertTrue(songPrint.contains("S1"));
assertTrue(songPrint.contains("LONG_SONG_NAME"));
}
/**
* Hash function coverage: insert artists/songs with different
* length names to exercise both branches of the sfold hash
* multiplier logic, then verify all songs are present.
*
* @throws IOException
* if an I/O error occurs (not expected here)
*/
public void testHashFunctionCollisions() throws IOException {
SongsDB db = new SongsDB();
db.create(8, 64);
// Insert strings of different lengths to hit different branches in h()
db.insert("abcd", "Song1"); // length 4
db.insert("abcdefgh", "Song2"); // length 8
db.insert("ijklmnop", "Song3"); // length 8
// Print songs and check if inserted strings exist
String allSongs = db.print("song");
assertTrue(allSongs.contains("Song1"));
assertTrue(allSongs.contains("Song2"));
assertTrue(allSongs.contains("Song3"));
}
/**
* Verify that create() rejects an invalid initial hash size.
*/
public void testInvalidHash() {
Songs invalidDB = new SongsDB();
assertFuzzyEquals("Initial hash table size must be positive",
invalidDB.create(-1, 4));
}
/**
* Verify that create() rejects an invalid initial memory size.
*/
public void testInvalidMemory() {
Songs invalidMemMan = new SongsDB();
assertFuzzyEquals("Initial memory manager size must be positive",
invalidMemMan.create(10, -10));
}
/**
* Verify that insert() reports an error when called before
* the database has been initialized with create().
*
* @throws IOException
* if an I/O error occurs (not expected here)
*/
public void testInvalidInsert() throws IOException {
Songs invalidDB = new SongsDB();
assertFuzzyEquals("Database not initialized",
invalidDB.insert("Ish", "Punna"));
}
/**
* Verify that printing artists right after a valid create()
* reports the correct empty-artist summary line.
*
* @throws IOException
* if an I/O error occurs (not expected here)
*/
public void testInvalidArtist() throws IOException {
Songs invalidDB = new SongsDB();
invalidDB.create(1, 4);
assertFuzzyEquals("total artists: 0", invalidDB.print("artist"));
}
/**
* Verify that print() reports the correct message when given
* an empty string as the print type parameter.
*
* @throws IOException
* if an I/O error occurs (not expected here)
*/
public void testInvalidPrint() throws IOException {
Songs invalidDB = new SongsDB();
invalidDB.create(1, 4);
assertFuzzyEquals("Input strings cannot be null or empty",
invalidDB.print(""));
}
/**
* Validate create() for invalid hash size and invalid memory
* size, using the SongsDB implementation directly.
*/
public void testCreateInvalidInputs() {
SongsDB db = new SongsDB();
String msg;
// invalid hash table size
msg = db.create(0, 8);
assertEquals("Initial hash table size must be positive", msg);
// invalid memory manager size
msg = db.create(8, 0);
assertEquals("Initial memory manager size must be positive", msg);
}
/**
* Validate that create() correctly rejects a non-power-of-two
* memory manager size, and accepts a proper power of two.
*/
public void testCreateNonPowerOfTwoMem() {
SongsDB db = new SongsDB();
// Non-power-of-2 mem size triggers error
String msg = db.create(10, 3);
assertEquals("Initial memory manager size must be a power of 2", msg);
// Positive power-of-2 works
msg = db.create(10, 8);
assertEquals("", msg);
}
/**
* Test various bad inputs for create, insert, remove, and print,
* including uninitialized database state and invalid parameters.
*
* @throws Exception
* if an unexpected error occurs
*/
public void testBadInput() throws Exception {
it = new SongsDB();
// Not been initialized yet
assertFalse(it.clear());
assertFuzzyEquals(
"Initial hash table size must be positive",
it.create(-1, 32));
assertFuzzyEquals(
"Initial memory manager size must be positive",
it.create(10, 0));
assertFuzzyEquals(
"Initial memory manager size must be a power of 2",
it.create(10, 3));
assertFuzzyEquals(
"Database not initialized",
it.insert("a", "b"));
assertFuzzyEquals(
"Database not initialized",
it.remove("song", "a"));
assertFuzzyEquals(
"Database not initialized",
it.print("blocks"));
it.create(32, 32);
assertFuzzyEquals(
"Bad print parameter",
it.print("dum"));
assertFuzzyEquals(
"Bad type value |Dum| on remove",
it.remove("Dum", "Dum"));
assertFuzzyEquals(
"Input strings cannot be null or empty",
it.print(""));
assertFuzzyEquals(
"Input strings cannot be null or empty",
it.print(null));
assertFuzzyEquals(
"Input strings cannot be null or empty",
it.insert("", "b"));
assertFuzzyEquals(
"Input strings cannot be null or empty",
it.insert(null, "b"));
assertFuzzyEquals(
"Input strings cannot be null or empty",
it.insert("a", ""));
assertFuzzyEquals(
"Input strings cannot be null or empty",
it.insert("a", null));
assertFuzzyEquals(
"Input strings cannot be null or empty",
it.remove("song", ""));
assertFuzzyEquals(
"Input strings cannot be null or empty",
it.remove("song", null));
assertFuzzyEquals(
"Input strings cannot be null or empty",
it.remove("", "a"));
assertFuzzyEquals(
"Input strings cannot be null or empty",
it.remove(null, "a"));
}
/**
* Test behavior on an otherwise empty database after create():
* printing tables, inserting one record, and then checking
* block printing and failed removes.
*
* @throws Exception
* if an unexpected error occurs
*/
public void testEmpty() throws Exception {
it = new SongsDB();
it.create(10, 32);
assertFuzzyEquals(
"total artists: 0",
it.print("artist"));
assertFuzzyEquals(
"total songs: 0",
it.print("song"));
it.insert("Hello World", "Hello World2");
assertFuzzyEquals(
"No free blocks are available.",
it.print("blocks"));
assertFuzzyEquals(
"|Dum| does not exist in the Artist database",
it.remove("artist", "Dum"));
assertFuzzyEquals(
"|Dum| does not exist in the song database",
it.remove("song", "Dum"));
}
/**
* Verify that clear() succeeds after a valid create()
* and that subsequent artist printing matches the empty
* summary output.
*
* @throws IOException
* if an I/O error occurs (not expected here)
*/
public void testClearWorks() throws IOException {
SongsDB db = new SongsDB();
db.create(4, 32);
assertTrue(db.clear());
assertFuzzyEquals("total artists: 0", db.print("artist"));
}
/**
* Verify the error message when remove() is called with an
* invalid table type parameter.
*
* @throws Exception
* if an unexpected error occurs
*/
public void testRemoveBadTypeMessage() throws Exception {
SongsDB db = new SongsDB();
db.create(4, 32);
String out = db.remove("bad", "x");
assertTrue(out.contains("Bad type value"));
}
/**
* Exact-output test for inserting artist and song pairs,
* including a duplicate artist insertion, using newline
* formatting as specified by the project sample.
*
* @throws IOException
* if an I/O error occurs (not expected here)
*/
public void testInsertArtistAndSongExactOutput() throws IOException {
SongsDB db = new SongsDB();
db.create(4, 32);
String out1 = db.insert("A", "S");
assertFuzzyEquals("|A| is added to the Artist database\n"
+ "|S| is added to the Song database", out1);
String out2 = db.insert("A", "S2");
assertFuzzyEquals("|A| duplicates a record already in the Artist database\n"
+ "|S2| is added to the Song database", out2);
}
/**
* Verify that tombstone slots in the artist hash table
* can be reused by new inserts without producing a
* duplicate-record error.
*
* @throws IOException
* if an I/O error occurs (not expected here)
*/
public void testTombstoneReuse() throws IOException {
SongsDB db = new SongsDB();
db.create(4, 32);
db.insert("A", "S1");
db.insert("B", "S2");
db.remove("artist", "A");
String out = db.insert("A", "S3");
assertFalse(out.contains("duplicates"));
}
/**
* Verify that the blocks printing functionality can be reached
* via SongsDB.print(\"blocks\") and returns a non-empty formatted
* string once some data have been inserted.
*
* @throws Exception
* if an unexpected error occurs
*/
public void testBlocksPrintViaSongsDB() throws Exception {
SongsDB db = new SongsDB();
db.create(4, 32);
db.insert("A", "This song name is very long");
String out = db.print("blocks");
assertTrue(out.contains(":"));
}
/**
* Full sample-input test from the project specification.
* Checks that the sequence of operations produces the
* exact output formatting in the sample.
*
* @throws Exception
* if an unexpected error occurs
*/
public void testSampleInput() throws Exception {
it = new SongsDB();
it.create(10, 32);
assertFuzzyEquals(
"|When Summer's Through| does not exist in the Song database",
it.remove("song", "When Summer's Through"));
assertFuzzyEquals(
"|Blind Lemon Jefferson| is added to the Artist database\r\n"
+ "Memory pool expanded to be 64 bytes\r\n"
+ "|Long Lonesome Blues| is added to the Song database",
it.insert("Blind Lemon Jefferson", "Long Lonesome Blues"));
assertFuzzyEquals(
"Memory pool expanded to be 128 bytes\r\n"
+ "|Ma Rainey| is added to the Artist database\r\n"
+ "|Ma Rainey's Black Bottom| is added to the Song database",
it.insert("Ma Rainey", "Ma Rainey's Black Bottom"));
assertFuzzyEquals(
"|Charley Patton| is added to the Artist database\r\n"
+ "Memory pool expanded to be 256 bytes\r\n"
+ "|Mississippi Boweavil Blues| is added to the Song database",
it.insert("Charley Patton", "Mississippi Boweavil Blues"));
assertFuzzyEquals(
"|Sleepy John Estes| is added to the Artist database\r\n"
+ "|Street Car Blues| is added to the Song database",
it.insert("Sleepy John Estes", "Street Car Blues"));
assertFuzzyEquals(
"|Bukka White| is added to the Artist database\r\n"
+ "|Fixin' To Die Blues| is added to the Song database",
it.insert("Bukka White", "Fixin' To Die Blues"));
assertFuzzyEquals(
"0: |Blind Lemon Jefferson|\r\n"
+ "1: |Sleepy John Estes|\r\n"
+ "4: |Charley Patton|\r\n"
+ "5: |Bukka White|\r\n"
+ "7: |Ma Rainey|\r\n"
+ "total artists: 5",
it.print("artist"));
assertFuzzyEquals(
"1: |Fixin' To Die Blues|\r\n"
+ "2: |Mississippi Boweavil Blues|\r\n"
+ "5: |Long Lonesome Blues|\r\n"
+ "6: |Ma Rainey's Black Bottom|\r\n"
+ "9: |Street Car Blues|\r\n"
+ "total songs: 5",
it.print("song"));
assertFuzzyEquals(
"Memory pool expanded to be 512 bytes\r\n"
+ "Artist hash table size doubled\r\n"
+ "|Guitar Slim| is added to the Artist database\r\n"
+ "Song hash table size doubled\r\n"
+ "|The Things That I Used To Do| is added to the Song database",
it.insert("Guitar Slim", "The Things That I Used To Do"));
assertFuzzyEquals(
"|Style Council| does not exist in the Artist database",
it.remove("artist", "Style Council"));
assertFuzzyEquals(
"|Ma Rainey| is removed from the Artist database",
it.remove("artist", "Ma Rainey"));
assertFuzzyEquals(
"|Mississippi Boweavil Blues| is removed from the Song database",
it.remove("song", "Mississippi Boweavil Blues"));
assertFuzzyEquals(
"|(The Best Part Of) Breakin' Up| does not exist in the Song database",
it.remove("song", "(The Best Part Of) Breakin' Up"));
assertFuzzyEquals(
"16: 64 272\r\n"
+ "32: 128\r\n"
+ "64: 320\r\n"
+ "128: 384",
it.print("blocks"));
assertFuzzyEquals(
"|Blind Lemon Jefferson| duplicates a record already in the Artist database\r\n"
+ "|Got The Blues| is added to the Song database",
it.insert("Blind Lemon Jefferson", "Got The Blues"));
assertFuzzyEquals(
"|Little Eva| is added to the Artist database\r\n"
+ "|The Loco-Motion| is added to the Song database",
it.insert("Little Eva", "The Loco-Motion"));
assertFuzzyEquals(
"0: |Blind Lemon Jefferson|\r\n"
+ "4: |Bukka White|\r\n"
+ "7: TOMBSTONE\r\n"
+ "10: |Sleepy John Estes|\r\n"
+ "12: |Guitar Slim|\r\n"
+ "14: |Charley Patton|\r\n"
+ "18: |Little Eva|\r\n"
+ "total artists: 6",
it.print("artist"));
assertFuzzyEquals(
"1: |Fixin' To Die Blues|\r\n"
+ "2: TOMBSTONE\r\n"
+ "5: |Street Car Blues|\r\n"
+ "8: |Got The Blues|\r\n"
+ "15: |Long Lonesome Blues|\r\n"
+ "16: |Ma Rainey's Black Bottom|\r\n"
+ "17: |The Things That I Used To Do|\r\n"
+ "18: |The Loco-Motion|\r\n"
+ "total songs: 7",
it.print("song"));
assertFuzzyEquals(
"|Jim Reeves| is added to the Artist database\r\n"
+ "|Jingle Bells| is added to the Song database",
it.insert("Jim Reeves", "Jingle Bells"));
assertFuzzyEquals(
"|Mongo Santamaria| is added to the Artist database\r\n"
+ "|Watermelon Man| is added to the Song database",
it.insert("Mongo Santamaria", "Watermelon Man"));
assertFuzzyEquals(
"16: 368\r\n"
+ "128: 384",
it.print("blocks"));
}
}
Editor is loading...
Leave a Comment