diff --git a/pom.xml b/pom.xml
index cf720a9f..fe07ba7e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,12 @@
4.12
test
+
+ nl.jqno.equalsverifier
+ equalsverifier
+ 2.3.2
+ test
+
diff --git a/src/main/java/com/mpatric/mp3agic/FileInputSource.java b/src/main/java/com/mpatric/mp3agic/FileInputSource.java
new file mode 100644
index 00000000..80c2b192
--- /dev/null
+++ b/src/main/java/com/mpatric/mp3agic/FileInputSource.java
@@ -0,0 +1,43 @@
+package com.mpatric.mp3agic;
+
+import java.io.IOException;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.file.Files;
+import java.nio.file.OpenOption;
+import java.nio.file.Path;
+import java.util.concurrent.TimeUnit;
+
+public class FileInputSource implements InputSource {
+
+ private final Path path;
+
+ public FileInputSource(Path path) {
+ this.path = path;
+ }
+
+ @Override
+ public String getResourceName() {
+ return path.toString();
+ }
+
+ @Override
+ public boolean isReadable() {
+ return Files.exists(path) && Files.isReadable(path);
+ }
+
+ @Override
+ public long getLastModified() throws IOException {
+ return Files.getLastModifiedTime(path).to(TimeUnit.MILLISECONDS);
+ }
+
+ @Override
+ public long getLength() throws IOException {
+ return Files.size(path);
+ }
+
+ @Override
+ public SeekableByteChannel openChannel(OpenOption... options) throws IOException {
+ return Files.newByteChannel(path, options);
+ }
+
+}
diff --git a/src/main/java/com/mpatric/mp3agic/FileWrapper.java b/src/main/java/com/mpatric/mp3agic/FileWrapper.java
index 11d15236..f12fa404 100644
--- a/src/main/java/com/mpatric/mp3agic/FileWrapper.java
+++ b/src/main/java/com/mpatric/mp3agic/FileWrapper.java
@@ -3,53 +3,57 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
+import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.TimeUnit;
public class FileWrapper {
- protected Path path;
- protected long length;
+ protected InputSource inputSource;
protected long lastModified;
protected FileWrapper() {
}
public FileWrapper(String filename) throws IOException {
- this.path = Paths.get(filename);
+ if (filename == null) throw new IllegalArgumentException("filename must not be null");
+ this.inputSource = new FileInputSource(Paths.get(filename));
init();
}
public FileWrapper(File file) throws IOException {
- if (file == null) throw new NullPointerException();
- this.path = Paths.get(file.getPath());
+ if (file == null) throw new IllegalArgumentException("file must not be null");
+ this.inputSource = new FileInputSource(Paths.get(file.getPath()));
init();
}
public FileWrapper(Path path) throws IOException {
- if (path == null) throw new NullPointerException();
- this.path = path;
+ if (path == null) throw new IllegalArgumentException("path must not be null");
+ this.inputSource = new FileInputSource(path);
init();
}
- private void init() throws IOException {
- if (!Files.exists(path)) throw new FileNotFoundException("File not found " + path);
- if (!Files.isReadable(path)) throw new IOException("File not readable");
- length = Files.size(path);
- lastModified = Files.getLastModifiedTime(path).to(TimeUnit.MILLISECONDS);
+ public FileWrapper(InputSource inputSource) throws IOException {
+ if (inputSource == null) throw new IllegalArgumentException("inputSource must not be null");
+ this.inputSource = inputSource;
+ init();
}
- public String getFilename() {
- return path.toString();
+ private void init() throws IOException {
+ if (!inputSource.isReadable()) throw new FileNotFoundException("File could not be found or is not readable " +
+ inputSource.getResourceName());
+ lastModified = inputSource.getLastModified();
}
- public long getLength() {
- return length;
+ public String getFilename() {
+ return inputSource.getResourceName();
}
public long getLastModified() {
return lastModified;
}
+
}
diff --git a/src/main/java/com/mpatric/mp3agic/ID3v1Tag.java b/src/main/java/com/mpatric/mp3agic/ID3v1Tag.java
index 0818c199..e5fa244a 100644
--- a/src/main/java/com/mpatric/mp3agic/ID3v1Tag.java
+++ b/src/main/java/com/mpatric/mp3agic/ID3v1Tag.java
@@ -2,6 +2,7 @@
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
+import java.util.Objects;
public class ID3v1Tag implements ID3v1 {
@@ -227,16 +228,7 @@ public void setComment(String comment) {
@Override
public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((album == null) ? 0 : album.hashCode());
- result = prime * result + ((artist == null) ? 0 : artist.hashCode());
- result = prime * result + ((comment == null) ? 0 : comment.hashCode());
- result = prime * result + genre;
- result = prime * result + ((title == null) ? 0 : title.hashCode());
- result = prime * result + ((track == null) ? 0 : track.hashCode());
- result = prime * result + ((year == null) ? 0 : year.hashCode());
- return result;
+ return Objects.hash(album, artist, comment, genre, title, track, year);
}
@Override
@@ -247,39 +239,14 @@ public boolean equals(Object obj) {
return false;
if (getClass() != obj.getClass())
return false;
- ID3v1Tag other = (ID3v1Tag) obj;
- if (album == null) {
- if (other.album != null)
- return false;
- } else if (!album.equals(other.album))
- return false;
- if (artist == null) {
- if (other.artist != null)
- return false;
- } else if (!artist.equals(other.artist))
- return false;
- if (comment == null) {
- if (other.comment != null)
- return false;
- } else if (!comment.equals(other.comment))
- return false;
- if (genre != other.genre)
- return false;
- if (title == null) {
- if (other.title != null)
- return false;
- } else if (!title.equals(other.title))
- return false;
- if (track == null) {
- if (other.track != null)
- return false;
- } else if (!track.equals(other.track))
- return false;
- if (year == null) {
- if (other.year != null)
- return false;
- } else if (!year.equals(other.year))
- return false;
- return true;
+ final ID3v1Tag other = (ID3v1Tag) obj;
+ return
+ Objects.equals(album, other.album) &&
+ Objects.equals(artist, other.artist) &&
+ Objects.equals(comment, other.comment) &&
+ Objects.equals(genre, other.genre) &&
+ Objects.equals(title, other.title) &&
+ Objects.equals(track, other.track) &&
+ Objects.equals(year, other.year);
}
}
diff --git a/src/main/java/com/mpatric/mp3agic/InputSource.java b/src/main/java/com/mpatric/mp3agic/InputSource.java
new file mode 100644
index 00000000..9dc9e342
--- /dev/null
+++ b/src/main/java/com/mpatric/mp3agic/InputSource.java
@@ -0,0 +1,35 @@
+package com.mpatric.mp3agic;
+
+import java.io.IOException;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.file.OpenOption;
+
+public interface InputSource {
+
+ /**
+ * Retrieves a value that identifies this resource.
+ * Can be a URL or a file name, for example.
+ */
+ String getResourceName();
+
+ /**
+ * Tells if the resource is valid and readable.
+ */
+ boolean isReadable();
+
+ /**
+ * Retrieves the last modification time of the resource.
+ */
+ long getLastModified() throws IOException;
+
+ /**
+ * Retrieves the length of the resource in bytes.
+ */
+ long getLength() throws IOException;
+
+ /**
+ * Opens a channel to read the resource.
+ */
+ SeekableByteChannel openChannel(OpenOption... options) throws IOException;
+
+}
diff --git a/src/main/java/com/mpatric/mp3agic/Mp3File.java b/src/main/java/com/mpatric/mp3agic/Mp3File.java
index 9b858458..b5428c26 100644
--- a/src/main/java/com/mpatric/mp3agic/Mp3File.java
+++ b/src/main/java/com/mpatric/mp3agic/Mp3File.java
@@ -84,13 +84,18 @@ public Mp3File(Path path, int bufferLength, boolean scanFile) throws IOException
init(bufferLength, scanFile);
}
+ public Mp3File(InputSource inputSource, int bufferLength, boolean scanFile) throws IOException, UnsupportedTagException, InvalidDataException {
+ super(inputSource);
+ init(bufferLength, scanFile);
+ }
+
private void init(int bufferLength, boolean scanFile) throws IOException, UnsupportedTagException, InvalidDataException {
if (bufferLength < MINIMUM_BUFFER_LENGTH + 1) throw new IllegalArgumentException("Buffer too small");
this.bufferLength = bufferLength;
this.scanFile = scanFile;
- try (SeekableByteChannel seekableByteChannel = Files.newByteChannel(path, StandardOpenOption.READ)) {
+ try (SeekableByteChannel seekableByteChannel = inputSource.openChannel(StandardOpenOption.READ)) {
initId3v1Tag(seekableByteChannel);
scanFile(seekableByteChannel);
if (startOffset < 0) {
@@ -146,7 +151,7 @@ private void scanFile(SeekableByteChannel seekableByteChannel) throws IOExceptio
}
lastOffset = startOffset;
}
- offset = scanBlock(bytes, bytesRead, fileOffset, offset);
+ offset = scanBlock(bytes, bytesRead, fileOffset, offset, seekableByteChannel.size());
fileOffset += offset;
seekableByteChannel.position(fileOffset);
break;
@@ -204,12 +209,12 @@ private int scanBlockForStart(byte[] bytes, int bytesRead, int absoluteOffset, i
return offset;
}
- private int scanBlock(byte[] bytes, int bytesRead, int absoluteOffset, int offset) throws InvalidDataException {
+ private int scanBlock(byte[] bytes, int bytesRead, int absoluteOffset, int offset, long size) throws InvalidDataException {
while (offset < bytesRead - MINIMUM_BUFFER_LENGTH) {
MpegFrame frame = new MpegFrame(bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3]);
- sanityCheckFrame(frame, absoluteOffset + offset);
+ sanityCheckFrame(frame, absoluteOffset + offset, size);
int newEndOffset = absoluteOffset + offset + frame.getLengthInBytes() - 1;
- if (newEndOffset < maxEndOffset()) {
+ if (newEndOffset < maxEndOffset(size)) {
endOffset = absoluteOffset + offset + frame.getLengthInBytes() - 1;
frameCount++;
addBitrate(frame.getBitrate());
@@ -221,8 +226,8 @@ private int scanBlock(byte[] bytes, int bytesRead, int absoluteOffset, int offse
return offset;
}
- private int maxEndOffset() {
- int maxEndOffset = (int) getLength();
+ private int maxEndOffset(long size) {
+ int maxEndOffset = (int) size;
if (hasId3v1Tag()) maxEndOffset -= ID3v1Tag.TAG_LENGTH;
return maxEndOffset;
}
@@ -249,11 +254,11 @@ private boolean isXingFrame(byte[] bytes, int offset) {
return false;
}
- private void sanityCheckFrame(MpegFrame frame, int offset) throws InvalidDataException {
+ private void sanityCheckFrame(MpegFrame frame, int offset, long size) throws InvalidDataException {
if (sampleRate != frame.getSampleRate()) throw new InvalidDataException("Inconsistent frame header");
if (!layer.equals(frame.getLayer())) throw new InvalidDataException("Inconsistent frame header");
if (!version.equals(frame.getVersion())) throw new InvalidDataException("Inconsistent frame header");
- if (offset + frame.getLengthInBytes() > getLength())
+ if (offset + frame.getLengthInBytes() > size)
throw new InvalidDataException("Frame would extend beyond end of file");
}
@@ -270,7 +275,7 @@ private void addBitrate(int bitrate) {
private void initId3v1Tag(SeekableByteChannel seekableByteChannel) throws IOException {
ByteBuffer byteBuffer = ByteBuffer.allocate(ID3v1Tag.TAG_LENGTH);
- seekableByteChannel.position(getLength() - ID3v1Tag.TAG_LENGTH);
+ seekableByteChannel.position(seekableByteChannel.size() - ID3v1Tag.TAG_LENGTH);
byteBuffer.clear();
int bytesRead = seekableByteChannel.read(byteBuffer);
if (bytesRead < ID3v1Tag.TAG_LENGTH) throw new IOException("Not enough bytes read");
@@ -302,7 +307,7 @@ private void initId3v2Tag(SeekableByteChannel seekableByteChannel) throws IOExce
}
private void initCustomTag(SeekableByteChannel seekableByteChannel) throws IOException {
- int bufferLength = (int) (getLength() - (endOffset + 1));
+ int bufferLength = (int) (seekableByteChannel.size() - (endOffset + 1));
if (hasId3v1Tag()) bufferLength -= ID3v1Tag.TAG_LENGTH;
if (bufferLength <= 0) {
customTag = null;
@@ -442,10 +447,13 @@ public void removeCustomTag() {
}
public void save(String newFilename) throws IOException, NotSupportedException {
- if (path.toAbsolutePath().compareTo(Paths.get(newFilename).toAbsolutePath()) == 0) {
+ final Path originalPath = Paths.get(inputSource.getResourceName()).toAbsolutePath();
+ final Path newPath = Paths.get(newFilename).toAbsolutePath();
+ if (originalPath.compareTo(newPath) == 0) {
throw new IllegalArgumentException("Save filename same as source filename");
}
- try (SeekableByteChannel saveFile = Files.newByteChannel(Paths.get(newFilename), EnumSet.of(StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE))) {
+ try (SeekableByteChannel saveFile = Files.newByteChannel(newPath,
+ EnumSet.of(StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE))) {
if (hasId3v2Tag()) {
ByteBuffer byteBuffer = ByteBuffer.wrap(id3v2Tag.toBytes());
byteBuffer.rewind();
@@ -471,9 +479,8 @@ private void saveMpegFrames(SeekableByteChannel saveFile) throws IOException {
if (filePos < 0) filePos = startOffset;
if (filePos < 0) return;
if (endOffset < filePos) return;
- SeekableByteChannel seekableByteChannel = Files.newByteChannel(path, StandardOpenOption.READ);
ByteBuffer byteBuffer = ByteBuffer.allocate(bufferLength);
- try {
+ try (SeekableByteChannel seekableByteChannel = inputSource.openChannel(StandardOpenOption.READ)) {
seekableByteChannel.position(filePos);
while (true) {
byteBuffer.clear();
@@ -489,8 +496,6 @@ private void saveMpegFrames(SeekableByteChannel saveFile) throws IOException {
break;
}
}
- } finally {
- seekableByteChannel.close();
}
}
}
diff --git a/src/main/java/com/mpatric/mp3agic/MutableInteger.java b/src/main/java/com/mpatric/mp3agic/MutableInteger.java
index d2c8b6fe..7c4f1163 100644
--- a/src/main/java/com/mpatric/mp3agic/MutableInteger.java
+++ b/src/main/java/com/mpatric/mp3agic/MutableInteger.java
@@ -1,5 +1,7 @@
package com.mpatric.mp3agic;
+import java.util.Objects;
+
public class MutableInteger {
private int value;
@@ -22,10 +24,7 @@ public void setValue(int value) {
@Override
public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + value;
- return result;
+ return Objects.hash(value);
}
@Override
@@ -36,9 +35,7 @@ public boolean equals(Object obj) {
return false;
if (getClass() != obj.getClass())
return false;
- MutableInteger other = (MutableInteger) obj;
- if (value != other.value)
- return false;
- return true;
+ final MutableInteger other = (MutableInteger) obj;
+ return Objects.equals(value, other.value);
}
}
diff --git a/src/test/java/com/mpatric/mp3agic/FileWrapperTest.java b/src/test/java/com/mpatric/mp3agic/FileWrapperTest.java
index 15f66994..47c9dd33 100644
--- a/src/test/java/com/mpatric/mp3agic/FileWrapperTest.java
+++ b/src/test/java/com/mpatric/mp3agic/FileWrapperTest.java
@@ -24,7 +24,7 @@ public void shouldReadValidFilename() throws IOException {
System.out.println(VALID_FILENAME);
assertEquals(fileWrapper.getFilename(), VALID_FILENAME);
assertTrue(fileWrapper.getLastModified() > 0);
- assertEquals(fileWrapper.getLength(), VALID_FILE_LENGTH);
+ assertEquals(fileWrapper.inputSource.getLength(), VALID_FILE_LENGTH);
}
@Test
@@ -34,7 +34,7 @@ public void shouldReadValidFile() throws IOException {
System.out.println(VALID_FILENAME);
assertEquals(fileWrapper.getFilename(), VALID_FILENAME);
assertTrue(fileWrapper.getLastModified() > 0);
- assertEquals(fileWrapper.getLength(), VALID_FILE_LENGTH);
+ assertEquals(fileWrapper.inputSource.getLength(), VALID_FILE_LENGTH);
}
@Test
@@ -44,7 +44,7 @@ public void shouldReadValidPath() throws IOException {
System.out.println(VALID_FILENAME);
assertEquals(fileWrapper.getFilename(), VALID_FILENAME);
assertTrue(fileWrapper.getLastModified() > 0);
- assertEquals(fileWrapper.getLength(), VALID_FILE_LENGTH);
+ assertEquals(fileWrapper.inputSource.getLength(), VALID_FILE_LENGTH);
}
@Test(expected = FileNotFoundException.class)
@@ -57,18 +57,23 @@ public void shouldFailForMalformedFilename() throws IOException {
new FileWrapper(MALFORMED_FILENAME);
}
- @Test(expected = NullPointerException.class)
+ @Test(expected = IllegalArgumentException.class)
public void shouldFailForNullFilename() throws IOException {
new FileWrapper((String) null);
}
- @Test(expected = NullPointerException.class)
+ @Test(expected = IllegalArgumentException.class)
public void shouldFailForNullFilenameFile() throws IOException {
new FileWrapper((java.io.File) null);
}
- @Test(expected = NullPointerException.class)
+ @Test(expected = IllegalArgumentException.class)
public void shouldFailForNullPath() throws IOException {
new FileWrapper((java.nio.file.Path) null);
}
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldFailForNullInputSource() throws IOException {
+ new FileWrapper((InputSource) null);
+ }
}
diff --git a/src/test/java/com/mpatric/mp3agic/ID3v1TagTest.java b/src/test/java/com/mpatric/mp3agic/ID3v1TagTest.java
index e2fbba13..07ee932a 100644
--- a/src/test/java/com/mpatric/mp3agic/ID3v1TagTest.java
+++ b/src/test/java/com/mpatric/mp3agic/ID3v1TagTest.java
@@ -1,5 +1,7 @@
package com.mpatric.mp3agic;
+import nl.jqno.equalsverifier.EqualsVerifier;
+import nl.jqno.equalsverifier.Warning;
import org.junit.Test;
import static org.junit.Assert.*;
@@ -161,4 +163,37 @@ public void shouldReturnEmptyTrackIfNotSetOn11Tag() throws Exception {
ID3v1 id3tag = new ID3v1Tag(tagBuffer);
assertEquals("", id3tag.getTrack());
}
+
+ @Test
+ public void shouldReturnCorrectGenreDescription() throws Exception {
+ for (int genre = 0; genre < ID3v1Genres.GENRES.length; ++genre) {
+ final ID3v1 id3tag = new ID3v1Tag();
+ id3tag.setGenre(genre);
+ assertEquals(ID3v1Genres.GENRES[genre], id3tag.getGenreDescription());
+ }
+ }
+
+ @Test
+ public void shouldReturnUnknownGenreDescriptionForOutOfRangeGenre() throws Exception {
+ final ID3v1 id3tag = new ID3v1Tag();
+ id3tag.setGenre(Integer.MAX_VALUE);
+ assertEquals("Unknown", id3tag.getGenreDescription());
+ }
+
+ @Test
+ public void shouldReturnCorrectVersion() throws Exception {
+ final ID3v1 id3tag1 = new ID3v1Tag();
+ assertEquals("0", id3tag1.getVersion());
+ final ID3v1 id3tag2 = new ID3v1Tag();
+ id3tag2.setTrack("1");
+ assertEquals("1", id3tag2.getVersion());
+ }
+
+ @Test
+ public void shouldCorrectlyImplementHashCodeAndEquals() throws Exception {
+ EqualsVerifier.forClass(ID3v1Tag.class)
+ .usingGetClass()
+ .suppress(Warning.NONFINAL_FIELDS)
+ .verify();
+ }
}
diff --git a/src/test/java/com/mpatric/mp3agic/Mp3FileTest.java b/src/test/java/com/mpatric/mp3agic/Mp3FileTest.java
index f8657b8d..1cd90dd9 100644
--- a/src/test/java/com/mpatric/mp3agic/Mp3FileTest.java
+++ b/src/test/java/com/mpatric/mp3agic/Mp3FileTest.java
@@ -5,9 +5,11 @@
import java.io.File;
import java.io.IOException;
import java.nio.channels.SeekableByteChannel;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
+import java.util.Arrays;
import static junit.framework.TestCase.assertFalse;
import static org.junit.Assert.*;
@@ -204,6 +206,29 @@ private void testShouldInitialiseProperlyWhenNotScanningFile(Mp3File mp3File) th
assertTrue(mp3File.hasId3v2Tag());
}
+ @Test
+ public void shouldSetId3v1Tag() throws Exception {
+ final Mp3File mp3File = new Mp3File(MP3_WITH_NO_TAGS);
+ final ID3v1 id3tag = new ID3v1Tag();
+ id3tag.setTrack("5");
+ id3tag.setArtist("ARTIST");
+ id3tag.setTitle("TITLE");
+ id3tag.setAlbum("ALBUM");
+ id3tag.setYear("1997");
+ id3tag.setGenre(13);
+ id3tag.setComment("");
+ String saveFilename = mp3File.getFilename() + ".copy";
+ try {
+ mp3File.setId3v1Tag(id3tag);
+ mp3File.save(saveFilename);
+ Mp3File newMp3File = new Mp3File(saveFilename);
+ assertTrue(newMp3File.hasId3v1Tag());
+ assertEquals(id3tag, newMp3File.getId3v1Tag());
+ } finally {
+ TestHelper.deleteFile(saveFilename);
+ }
+ }
+
@Test
public void shouldRemoveId3v1Tag() throws Exception {
String filename = MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS;
@@ -230,6 +255,27 @@ private void testShouldRemoveId3v1Tag(Mp3File mp3File) throws Exception {
}
}
+ @Test
+ public void shouldSetId3v2Tag() throws Exception {
+ final Mp3File mp3File = new Mp3File(MP3_WITH_NO_TAGS);
+ final ID3v2 id3tag = new ID3v24Tag();
+ id3tag.setArtist("ARTIST");
+ id3tag.setTitle("TITLE");
+ id3tag.setAlbum("ALBUM");
+ id3tag.setYear("1954");
+ id3tag.setGenre(0x0d);
+ String saveFilename = mp3File.getFilename() + ".copy";
+ try {
+ mp3File.setId3v2Tag(id3tag);
+ mp3File.save(saveFilename);
+ Mp3File newMp3File = new Mp3File(saveFilename);
+ assertTrue(newMp3File.hasId3v2Tag());
+ assertEquals(id3tag, newMp3File.getId3v2Tag());
+ } finally {
+ TestHelper.deleteFile(saveFilename);
+ }
+ }
+
@Test
public void shouldRemoveId3v2Tag() throws Exception {
String filename = MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS;
@@ -256,6 +302,22 @@ private void testShouldRemoveId3v2Tag(Mp3File mp3File) throws Exception {
}
}
+ @Test
+ public void shouldSetCustomTag() throws Exception {
+ final Mp3File mp3File = new Mp3File(MP3_WITH_NO_TAGS);
+ final byte[] customTag = "CUSTOM_TAG".getBytes(StandardCharsets.UTF_8);
+ String saveFilename = mp3File.getFilename() + ".copy";
+ try {
+ mp3File.setCustomTag(customTag);
+ mp3File.save(saveFilename);
+ Mp3File newMp3File = new Mp3File(saveFilename);
+ assertTrue(newMp3File.hasCustomTag());
+ assertTrue(Arrays.equals(newMp3File.getCustomTag(), customTag));
+ } finally {
+ TestHelper.deleteFile(saveFilename);
+ }
+ }
+
@Test
public void shouldRemoveCustomTag() throws Exception {
String filename = MP3_WITH_ID3V1_AND_ID3V23_AND_CUSTOM_TAGS;
@@ -294,6 +356,18 @@ public void shouldRemoveId3v1AndId3v2AndCustomTagsForFileConstructor() throws Ex
testShouldRemoveId3v1AndId3v2AndCustomTags(new Mp3File(filename));
}
+ @Test
+ public void shouldReturnCorrectLengthInSeconds() throws Exception {
+ final Mp3File mp3File = new Mp3File(MP3_WITH_ID3V1_AND_ID3V23_TAGS);
+ assertEquals(0, mp3File.getLengthInSeconds());
+ }
+
+ @Test
+ public void shouldCorrectlyIdentifyIfVBR() throws Exception {
+ final Mp3File mp3File = new Mp3File(MP3_WITH_ID3V1_AND_ID3V23_TAGS);
+ assertTrue(mp3File.isVbr());
+ }
+
private void testShouldRemoveId3v1AndId3v2AndCustomTags(Mp3File mp3File) throws Exception {
String saveFilename = mp3File.getFilename() + ".copy";
try {
diff --git a/src/test/java/com/mpatric/mp3agic/MutableIntegerTest.java b/src/test/java/com/mpatric/mp3agic/MutableIntegerTest.java
index 46679d39..a67198cb 100644
--- a/src/test/java/com/mpatric/mp3agic/MutableIntegerTest.java
+++ b/src/test/java/com/mpatric/mp3agic/MutableIntegerTest.java
@@ -1,5 +1,7 @@
package com.mpatric.mp3agic;
+import nl.jqno.equalsverifier.EqualsVerifier;
+import nl.jqno.equalsverifier.Warning;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
@@ -28,47 +30,10 @@ public void setsValue() {
}
@Test
- public void equalsItself() {
- MutableInteger integer = new MutableInteger(8);
- assertEquals(integer, integer);
- }
-
- @Test
- public void equalIfValueEqual() {
- MutableInteger eight = new MutableInteger(8);
- MutableInteger eightAgain = new MutableInteger(8);
- assertEquals(eight, eightAgain);
- }
-
- @Test
- public void notEqualToNull() {
- MutableInteger integer = new MutableInteger(8);
- assertFalse(integer.equals(null));
- }
-
- @Test
- public void notEqualToDifferentClass() {
- MutableInteger integer = new MutableInteger(8);
- assertFalse(integer.equals("8"));
- }
-
- @Test
- public void notEqualIfValueNotEqual() {
- MutableInteger eight = new MutableInteger(8);
- MutableInteger nine = new MutableInteger(9);
- assertNotEquals(eight, nine);
- }
-
- @Test
- public void hashCodeIsConsistent() {
- MutableInteger integer = new MutableInteger(8);
- assertEquals(integer.hashCode(), integer.hashCode());
- }
-
- @Test
- public void equalObjectsHaveSameHashCode() {
- MutableInteger eight = new MutableInteger(8);
- MutableInteger eightAgain = new MutableInteger(8);
- assertEquals(eight.hashCode(), eightAgain.hashCode());
+ public void shouldCorrectlyImplementHashCodeAndEquals() throws Exception {
+ EqualsVerifier.forClass(MutableInteger.class)
+ .usingGetClass()
+ .suppress(Warning.NONFINAL_FIELDS)
+ .verify();
}
}