Removed some unit tests that took a bit of setup to get working; added a helper functions to HeaderBlock (getting filename and data or resource fork) and ThreadRecord (get correct InputStream); most LZW tests now compare to expected results. Not all test issues have been resolved.

This commit is contained in:
Robert Greene 2008-06-27 04:19:21 +00:00
parent ac9626e9c0
commit acb0912244
15 changed files with 136 additions and 127 deletions

Binary file not shown.

Binary file not shown.

View File

@ -36,7 +36,8 @@ public class HeaderBlock {
private byte[] optionListBytes;
private byte[] attribBytes;
private String filename;
private List<ThreadRecord> threads;
private String rawFilename;
private List<ThreadRecord> threads = new ArrayList<ThreadRecord>();
/**
* Create the Header Block. This is done dynamically since
@ -76,7 +77,7 @@ public class HeaderBlock {
// Read the (defunct) filename
int length = bs.readWord();
if (length > 0) {
filename = new String(bs.readBytes(length));
rawFilename = new String(bs.readBytes(length));
}
}
/**
@ -84,11 +85,51 @@ public class HeaderBlock {
* each thread's data is read (per NuFX spec).
*/
public void readThreads(LittleEndianByteInputStream bs) throws IOException {
threads = new ArrayList<ThreadRecord>();
for (long l=0; l<totalThreads; l++) threads.add(new ThreadRecord(bs));
for (ThreadRecord r : threads) r.readThreadData(bs);
}
/**
* Locate the filename and return it. It may have been given in the old
* location, in which case, it is in the String filename. Otherwise it will
* be in the filename thread. If it is in the thread, we shove it in the
* filename variable just so we don't need to search for it later. This
* should not be a problem, because if we write the file, we'll write the
* more current version anyway.
*/
public String getFilename() {
if (filename == null) {
ThreadRecord r = findThreadRecord(ThreadKind.FILENAME);
if (r != null) filename = r.getText();
if (filename == null) filename = rawFilename;
}
return filename;
}
/**
* Get the data fork.
*/
public ThreadRecord getDataForkInputStream() throws IOException {
return findThreadRecord(ThreadKind.DATA_FORK);
}
/**
* Get the resource fork.
*/
public ThreadRecord getResourceForkInputStream() throws IOException {
return findThreadRecord(ThreadKind.RESOURCE_FORK);
}
/**
* Locate a ThreadRecord by it's ThreadKind.
*/
protected ThreadRecord findThreadRecord(ThreadKind tk) {
for (ThreadRecord r : threads) {
if (r.getThreadKind() == tk) return r;
}
return null;
}
// GENERATED CODE
public int getHeaderCrc() {
@ -187,12 +228,12 @@ public class HeaderBlock {
public void setAttribBytes(byte[] attribBytes) {
this.attribBytes = attribBytes;
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public String getRawFilename() {
return rawFilename;
}
public List<ThreadRecord> getThreadRecords() {
return threads;
}

View File

@ -5,6 +5,8 @@ import java.io.IOException;
import java.io.InputStream;
import com.webcodepro.shrinkit.io.LittleEndianByteInputStream;
import com.webcodepro.shrinkit.io.NufxLzw1InputStream;
import com.webcodepro.shrinkit.io.NufxLzw2InputStream;
/**
* This represents a single thread from the Shrinkit archive.
@ -70,6 +72,21 @@ public class ThreadRecord {
public InputStream getRawInputStream() {
return new ByteArrayInputStream(threadData);
}
/**
* Get the appropriate input data stream for this thread to decompress the contents.
*/
public InputStream getInputStream() throws IOException {
switch (threadFormat) {
case UNCOMPRESSED:
return getRawInputStream();
case DYNAMIC_LZW1:
return new NufxLzw1InputStream(new LittleEndianByteInputStream(getRawInputStream()));
case DYNAMIC_LZW2:
return new NufxLzw2InputStream(new LittleEndianByteInputStream(getRawInputStream()));
default:
throw new IOException("The thread format " + threadFormat + " does not have an InputStream associated with it!");
}
}
// GENERATED CODE

View File

@ -141,6 +141,6 @@ public class HeaderBlockTest extends TestCase {
assertEquals(new LittleEndianByteInputStream(new byte[] {0x00,0x11,0x11,0x5e,0x13,0x01,0x00,0x01}).readDate(), b.getModWhen());
assertEquals(new LittleEndianByteInputStream(new byte[] {0x38,0x0c,0x14,0x5f,0x08,0x07,0x00,0x04}).readDate(), b.getArchiveWhen());
assertEquals(0x0000, b.getOptionSize());
assertNull(b.getFilename());
assertNull(b.getRawFilename());
}
}

View File

@ -1,61 +0,0 @@
package com.webcodepro.shrinkit;
import java.io.IOException;
import java.io.InputStream;
import junit.framework.TestCase;
/**
* Not really a JUnit test, but this does verify that NuFX archives can be read.
* We read a couple of samples and dump out the details.
* <p>
* Note that to successfully run this, the classpath must have the samples folder
* added to it.
*
* @author robgreene@users.sourceforge.net
*/
public class NuFileArchiveTest extends TestCase {
public void testReadJoystickShk() throws IOException {
display("/Joystick.SHK");
}
public void testReadSccShk() throws IOException {
display("/Scc.shk");
}
private void display(String archiveName) throws IOException {
System.out.printf("Details for %s\n\n", archiveName);
InputStream is = getClass().getResourceAsStream(archiveName);
if (is == null) {
System.out.printf("*** ERROR: Unable to locate '%s'", archiveName);
fail("Unable to locate archive file");
}
NuFileArchive a = new NuFileArchive(is);
MasterHeaderBlock m = a.getMasterHeaderBlock();
System.out.printf("Master Header Block\n==================\n"
+ "master_crc=$%x\ntotal_records=%d\narchive_create_when=%tc\narchive_mod_when=%tc\n"
+ "master_version=%d\nmaster_eof=$%x\nisValidCrc = %b\n\n",
m.getMasterCrc(), m.getTotalRecords(), m.getArchiveCreateWhen(), m.getArchiveModWhen(),
m.getMasterVersion(), m.getMasterEof(), m.isValidCrc());
for (HeaderBlock b : a.getHeaderBlocks()) {
System.out.printf("\tHeader Block\n\t============\n");
System.out.printf("\theader_crc=$%x\n\tattrib_count=%d\n\tversion_number=%d\n\ttotal_threads=%d\n\t"
+ "file_sys_id=$%x\n\tfile_sys_info=$%x\n\taccess=$%x\n\tfile_type=$%x\n\textra_type=$%x\n\t"
+ "storage_type=$%x\n\tcreate_when=%tc\n\tmod_when=%tc\n\tarchive_when=%tc\n\toption_size=%d\n\t"
+ "filename=%s\n\n",
b.getHeaderCrc(), b.getAttribCount(), b.getVersionNumber(), b.getTotalThreads(), b.getFileSysId(),
b.getFileSysInfo(), b.getAccess(), b.getFileType(), b.getExtraType(), b.getStorageType(),
b.getCreateWhen(), b.getModWhen(), b.getArchiveWhen(), b.getOptionSize(), b.getFilename());
System.out.printf("\t\tThreads\n\t\t=======\n");
for (ThreadRecord r : b.getThreadRecords()) {
System.out.printf("\t\tthread_class=%s\n\t\tthread_format=%s\n\t\tthread_kind=%s\n\t\t"
+ "thread_crc=$%x\n\t\tthread_eof=$%x\n\t\tcompThreadEof=$%x\n",
r.getThreadClass(), r.getThreadFormat(), r.getThreadKind(), r.getThreadCrc(),
r.getThreadEof(), r.getCompThreadEof());
if (r.getThreadKind() == ThreadKind.FILENAME) {
System.out.printf("\t\tFILENAME=%s\n", r.getText());
}
System.out.printf("\n");
}
}
}
}

View File

@ -1,12 +1,6 @@
package com.webcodepro.shrinkit.io;
import java.io.IOException;
import java.util.List;
import com.webcodepro.shrinkit.HeaderBlock;
import com.webcodepro.shrinkit.NuFileArchive;
import com.webcodepro.shrinkit.ThreadKind;
import com.webcodepro.shrinkit.ThreadRecord;
/**
* Test some LZW/1 format streams.
@ -22,26 +16,6 @@ public class NufxLzw1Test extends TestCaseHelper {
assertEquals(expected, actual);
assertTrue(is.isCrcValid());
}
public void testAppleIIShk() throws IOException {
NuFileArchive archive = new NuFileArchive(getClass().getResourceAsStream("APPLE.II-LZW1.SHK"));
List<HeaderBlock> blocks = archive.getHeaderBlocks();
HeaderBlock block = blocks.get(0); // only one file
if (block.getFilename() != null) System.out.printf("\n\n%s\n\n", block.getFilename());
List<ThreadRecord> records = block.getThreadRecords();
for (ThreadRecord record : records) {
if (record.getThreadKind() == ThreadKind.FILENAME) {
System.out.printf("\n\n%s\n\n", record.getText());
}
long bytes = record.getThreadEof();
if (record.getThreadKind() == ThreadKind.DATA_FORK) {
NufxLzw1InputStream is = new NufxLzw1InputStream(new LittleEndianByteInputStream(record.getRawInputStream()));
while ( bytes-- > 0 ) {
System.out.print((char)is.read());
}
}
}
}
private byte[] getTextFileLzw1StreamData() {

View File

@ -1,33 +0,0 @@
package com.webcodepro.shrinkit.io;
import java.io.IOException;
import java.util.List;
import junit.framework.TestCase;
import com.webcodepro.shrinkit.HeaderBlock;
import com.webcodepro.shrinkit.NuFileArchive;
import com.webcodepro.shrinkit.ThreadKind;
import com.webcodepro.shrinkit.ThreadRecord;
public class NufxLzw2Test extends TestCase {
public void testPascalFile() throws IOException {
NuFileArchive archive = new NuFileArchive(getClass().getResourceAsStream("APPLE.II-LZW2.SHK"));
List<HeaderBlock> blocks = archive.getHeaderBlocks();
HeaderBlock block = blocks.get(0);
if (block.getFilename() != null) System.out.printf("\n\n%s\n\n", block.getFilename());
List<ThreadRecord> records = block.getThreadRecords();
for (ThreadRecord record : records) {
if (record.getThreadKind() == ThreadKind.FILENAME) {
System.out.printf("\n\n%s\n\n", record.getText());
}
long bytes = record.getThreadEof();
if (record.getThreadKind() == ThreadKind.DATA_FORK) {
NufxLzw2InputStream is = new NufxLzw2InputStream(new LittleEndianByteInputStream(record.getRawInputStream()));
while ( bytes-- > 0 ) {
System.out.print((char)is.read());
}
}
}
}
}

View File

@ -0,0 +1,71 @@
package com.webcodepro.shrinkit.io;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import junit.framework.TestCase;
import com.webcodepro.shrinkit.HeaderBlock;
import com.webcodepro.shrinkit.NuFileArchive;
import com.webcodepro.shrinkit.ThreadRecord;
/**
* Compare actual decompressed content against the expected content.
* This is a very broad test of the NuFX archive format.
*
* @author robgreene@users.sourceforge.net
*/
public class NufxLzwTest extends TestCase {
public void testNufxLzw1() throws IOException {
check("APPLE.II-LZW1.SHK", "APPLE.II", "APPLE.II.txt");
}
public void testNufxLzw2() throws IOException {
check("APPLE.II-LZW2.SHK", "APPLE.II", "APPLE.II.txt");
}
public void testLargerFilesNufxLzw1() throws IOException {
check("PRODOS.MSTR-LZW1.SHK", "SYSUTIL.SYSTEM", "SYSUTIL.SYSTEM.bin");
check("PRODOS.MSTR-LZW1.SHK", "UTIL.0", "UTIL.0.bin");
check("PRODOS.MSTR-LZW1.SHK", "UTIL.1", "UTIL.1.bin");
check("PRODOS.MSTR-LZW1.SHK", "UTIL.2", "UTIL.2.bin");
}
public void testLargerFilesNufxLzw2() throws IOException {
check("PRODOS.MSTR-LZW2.SHK", "SYSUTIL.SYSTEM", "SYSUTIL.SYSTEM.bin");
check("PRODOS.MSTR-LZW2.SHK", "UTIL.0", "UTIL.0.bin");
check("PRODOS.MSTR-LZW2.SHK", "UTIL.1", "UTIL.1.bin");
check("PRODOS.MSTR-LZW2.SHK", "UTIL.2", "UTIL.2.bin");
}
/**
* Given details about an archive file and it's expected contents, locate that
* file and then check it against the contents.
*/
protected void check(String archiveName, String archiveFile, String expectedContentFile) throws IOException {
NuFileArchive archive = new NuFileArchive(getClass().getResourceAsStream(archiveName));
List<HeaderBlock> headers = archive.getHeaderBlocks();
String actual = null;
for (HeaderBlock header : headers) {
if (archiveFile.equals(header.getFilename())) {
ThreadRecord r = header.getDataForkInputStream();
long bytes = r.getThreadEof();
StringBuffer buf = new StringBuffer();
InputStream is = r.getInputStream();
while ( bytes-- > 0 ) {
buf.append((char)is.read());
}
actual = buf.toString();
is.close();
break;
}
}
InputStream is = getClass().getResourceAsStream(expectedContentFile);
StringBuffer buf = new StringBuffer();
int ch;
while ( (ch = is.read()) != -1 ) {
buf.append((char)ch);
}
String expected = buf.toString();
assertEquals(expected, actual);
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.