mirror of
https://github.com/AppleCommander/ShrinkItArchive.git
synced 2024-12-21 11:29:45 +00:00
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:
parent
ac9626e9c0
commit
acb0912244
Binary file not shown.
BIN
samples/Scc.shk
BIN
samples/Scc.shk
Binary file not shown.
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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() {
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
71
test_src/com/webcodepro/shrinkit/io/NufxLzwTest.java
Normal file
71
test_src/com/webcodepro/shrinkit/io/NufxLzwTest.java
Normal 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);
|
||||
}
|
||||
}
|
BIN
test_src/com/webcodepro/shrinkit/io/PRODOS.MSTR-LZW1.SHK
Normal file
BIN
test_src/com/webcodepro/shrinkit/io/PRODOS.MSTR-LZW1.SHK
Normal file
Binary file not shown.
BIN
test_src/com/webcodepro/shrinkit/io/PRODOS.MSTR-LZW2.SHK
Normal file
BIN
test_src/com/webcodepro/shrinkit/io/PRODOS.MSTR-LZW2.SHK
Normal file
Binary file not shown.
BIN
test_src/com/webcodepro/shrinkit/io/SYSUTIL.SYSTEM.bin
Normal file
BIN
test_src/com/webcodepro/shrinkit/io/SYSUTIL.SYSTEM.bin
Normal file
Binary file not shown.
BIN
test_src/com/webcodepro/shrinkit/io/UTIL.0.bin
Normal file
BIN
test_src/com/webcodepro/shrinkit/io/UTIL.0.bin
Normal file
Binary file not shown.
BIN
test_src/com/webcodepro/shrinkit/io/UTIL.1.bin
Normal file
BIN
test_src/com/webcodepro/shrinkit/io/UTIL.1.bin
Normal file
Binary file not shown.
BIN
test_src/com/webcodepro/shrinkit/io/UTIL.2.bin
Normal file
BIN
test_src/com/webcodepro/shrinkit/io/UTIL.2.bin
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user