package de.persosim.simulator.tlv;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import mockit.Deencapsulation;
import org.junit.Test;
import de.persosim.simulator.exception.ISO7816Exception;
import de.persosim.simulator.utils.Utils;
public class ConstructedTlvDataObjectTest {
/**
* Positive test case: Extract constructed TLV data object from a range
* being larger than the minimum range required
*/
@Test
public void testConstructorByteArrayIntIntConstructedTlvDataObjectLargerRangeLargerArray() {
/* arbitrary but valid constructed TLV data object */
byte[] tlvExpected = new byte[] { (byte) 0x21, (byte) 0x08,
(byte) 0x01, (byte) 0x02, (byte) 0xFF, (byte) 0xFF,
(byte) 0x02, (byte) 0x02, (byte) 0xEE, (byte) 0xEE };
/* dummy data to prepend */
byte[] byteArrayPre = new byte[] { (byte) 0xFF, (byte) 0xFF };
/* dummy data to append */
byte[] byteArrayPost = new byte[] { (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF };
/* build actual byte array */
byte[] byteArray = Utils.concatByteArrays(byteArrayPre, tlvExpected,
byteArrayPost);
ConstructedTlvDataObject tlvObject = new ConstructedTlvDataObject(
byteArray, byteArrayPre.length, byteArray.length);
assertArrayEquals("Equals expected byte array representation",
tlvObject.toByteArray(), tlvExpected);
}
/**
* Positive test case: Extract constructed TLV data object from a range
* being exactly of the same size as the minimum range required
*/
@Test
public void testConstructorByteArrayIntIntMinRangeLargerArray() {
/* arbitrary but valid constructed TLV data object */
byte[] tlvExpected = new byte[] { (byte) 0x21, (byte) 0x08,
(byte) 0x01, (byte) 0x02, (byte) 0xFF, (byte) 0xFF,
(byte) 0x02, (byte) 0x02, (byte) 0xEE, (byte) 0xEE };
/* dummy data to prepend */
byte[] byteArrayPre = new byte[] { (byte) 0xFF, (byte) 0xFF };
/* dummy data to append */
byte[] byteArrayPost = new byte[] { (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF };
/* build actual byte array */
byte[] byteArray = Utils.concatByteArrays(byteArrayPre, tlvExpected,
byteArrayPost);
ConstructedTlvDataObject tlvObject = new ConstructedTlvDataObject(
byteArray, byteArrayPre.length, byteArray.length
- byteArrayPost.length);
assertArrayEquals("Equals expected byte array representation",
tlvObject.toByteArray(), tlvExpected);
}
/**
* Negative test case: Extract constructed TLV data object from a range
* being 1 byte smaller than the minimum range required
*/
@Test(expected = ISO7816Exception.class)
public void testConstructorByteArrayIntIntSmallerRangeLargerArray() {
/* arbitrary but valid constructed TLV data object */
byte[] tlvExpected = new byte[] { (byte) 0x21, (byte) 0x08,
(byte) 0x01, (byte) 0x02, (byte) 0xFF, (byte) 0xFF,
(byte) 0x02, (byte) 0x02, (byte) 0xEE, (byte) 0xEE };
/* dummy data to prepend */
byte[] byteArrayPre = new byte[] { (byte) 0xFF, (byte) 0xFF };
/* dummy data to append */
byte[] byteArrayPost = new byte[] { (byte) 0xFF, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF };
/* build actual byte array */
byte[] byteArray = Utils.concatByteArrays(byteArrayPre, tlvExpected,
byteArrayPost);
new ConstructedTlvDataObject(byteArray, byteArrayPre.length,
byteArray.length - byteArrayPost.length - 1);
}
/**
* Positive test case: Construct constructed TLV data object from basic
* T-L-V elements
*/
@Test
public void testConstructorTagLengthValueTlvTagTlvLengthTlvValue() {
/* set arbitrary but valid constructed tag */
byte[] tagExpected = new byte[] { (byte) 0x21 };
/* set arbitrary but valid length matching actual length of value */
byte[] lengthExpected = new byte[] { (byte) 0x08 };
/* set arbitrary value consisting of valid chained TLV data objects */
byte[] valueExpected = new byte[] { (byte) 0x01, (byte) 0x02,
(byte) 0xFF, (byte) 0xFF, (byte) 0x02, (byte) 0x02,
(byte) 0xEE, (byte) 0xEE };
byte[] tlvExpected = Utils.concatByteArrays(tagExpected,
lengthExpected, valueExpected);
TlvTag tag = new TlvTag(tagExpected);
TlvLength length = new TlvLength(lengthExpected);
TlvDataObjectContainer value = new TlvDataObjectContainer(valueExpected);
ConstructedTlvDataObject tlvObject = new ConstructedTlvDataObject(tag,
length, value);
assertArrayEquals("Equals expected byte array representation",
tlvObject.toByteArray(), tlvExpected);
}
/**
* Negative test case: Construct constructed TLV data object from basic
* T-L-V elements, V not matching L
*/
@Test(expected = IllegalArgumentException.class)
public void testConstructorTagLengthValueLengthNotMatchingValue() {
/* set arbitrary but valid constructed tag */
byte[] tagExpected = new byte[] { (byte) 0x21 };
/* set arbitrary but valid length smaller than actual length of value */
byte[] lengthExpected = new byte[] { (byte) 0x07 };
/* set arbitrary value consisting of valid chained TLV data objects */
byte[] valueExpected = new byte[] { (byte) 0x01, (byte) 0x02,
(byte) 0xFF, (byte) 0xFF, (byte) 0x02, (byte) 0x02,
(byte) 0xEE, (byte) 0xEE };
byte[] tlvExpected = Utils.concatByteArrays(tagExpected,
lengthExpected, valueExpected);
TlvTag tag = new TlvTag(tagExpected);
TlvLength length = new TlvLength(lengthExpected);
TlvDataObjectContainer value = new TlvDataObjectContainer(valueExpected);
ConstructedTlvDataObject tlvObject = new ConstructedTlvDataObject(tag,
length, value);
assertArrayEquals("Equals expected byte array representation",
tlvObject.toByteArray(), tlvExpected);
}
/**
* Negative test case: Construct constructed TLV data object from basic
* T-L-V elements, T indicates primitive encoding
*/
@Test(expected = IllegalArgumentException.class)
public void testConstructorTagLengthValueWithPrimitiveTag() {
/* set arbitrary but "valid" primitive tag */
byte[] tagExpected = new byte[] { (byte) 0x01 };
/* set arbitrary but valid length matching actual length of value */
byte[] lengthExpected = new byte[] { (byte) 0x08 };
/* set arbitrary value consisting of valid chained TLV data objects */
byte[] valueExpected = new byte[] { (byte) 0x01, (byte) 0x02,
(byte) 0xFF, (byte) 0xFF, (byte) 0x02, (byte) 0x02,
(byte) 0xEE, (byte) 0xEE };
TlvTag tag = new TlvTag(tagExpected);
TlvLength length = new TlvLength(lengthExpected);
TlvDataObjectContainer value = new TlvDataObjectContainer(valueExpected);
new ConstructedTlvDataObject(tag, length, value);
}
/**
* Positive test case: Construct constructed TLV data object from basic
* T-L-V elements; returned T must not be the same object as provided T
*/
@Test
public void testConstructorTagLengthValueTagNotSameWhenRetrieved() {
/* set arbitrary but valid constructed tag */
byte[] tagExpected = new byte[] { (byte) 0x21 };
/* set arbitrary but valid length matching actual length of value */
byte[] lengthExpected = new byte[] { (byte) 0x08 };
/* set arbitrary value consisting of valid chained TLV data objects */
byte[] valueExpected = new byte[] { (byte) 0x01, (byte) 0x02,
(byte) 0xFF, (byte) 0xFF, (byte) 0x02, (byte) 0x02,
(byte) 0xEE, (byte) 0xEE };
TlvTag tag = new TlvTag(tagExpected);
TlvLength length = new TlvLength(lengthExpected);
TlvDataObjectContainer value = new TlvDataObjectContainer(valueExpected);
ConstructedTlvDataObject tlvObject = new ConstructedTlvDataObject(tag,
length, value);
boolean isSame = tag == tlvObject.getTlvTag();
assertEquals("Provided tag must mismatch retrieved", isSame, false);
}
/**
* Positive test case: Construct constructed TLV data object from basic
* T-L-V elements; stored T must not be the same object as provided T
*/
@Test
public void testConstructorTagLengthValueStoredTNotSameAsProvided() {
/* set arbitrary but valid constructed tag */
byte[] tagExpected = new byte[] { (byte) 0x21 };
/* set arbitrary but valid length matching actual length of value */
byte[] lengthExpected = new byte[] { (byte) 0x08 };
/* set arbitrary value consisting of valid chained TLV data objects */
byte[] valueExpected = new byte[] { (byte) 0x01, (byte) 0x02,
(byte) 0xFF, (byte) 0xFF, (byte) 0x02, (byte) 0x02,
(byte) 0xEE, (byte) 0xEE };
TlvTag tag = new TlvTag(tagExpected);
TlvLength length = new TlvLength(lengthExpected);
TlvDataObjectContainer value = new TlvDataObjectContainer(valueExpected);
ConstructedTlvDataObject tlvObject = new ConstructedTlvDataObject(tag,
length, value);
/* set arbitrary but valid constructed tag different from the one defined before */
byte[] tagExpected2 = new byte[] { (byte) 0x24 };
Deencapsulation.setField(tag, "tagField", tagExpected2);
boolean isEqual = tag.equals(tlvObject.getTlvTag());
assertEquals("Provided tag must not be imported directly", isEqual,
false);
}
/**
* Positive test case:
* Construct constructed TLV data object from basic T-L-V elements; returned T must not be the same object as stored T
*/
@Test
public void testConstructorTagLengthValueReturnedTNotSameAsStored() {
/* set arbitrary but valid constructed tag */
byte[] tagExpected = new byte[] { (byte) 0x21 };
/* set arbitrary but valid length matching actual length of value */
byte[] lengthExpected = new byte[] { (byte) 0x08 };
/* set arbitrary value consisting of valid chained TLV data objects */
byte[] valueExpected = new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0xFF, (byte) 0xFF,
(byte) 0x02, (byte) 0x02, (byte) 0xEE, (byte) 0xEE };
TlvTag tag = new TlvTag(tagExpected);
TlvLength length = new TlvLength(lengthExpected);
TlvDataObjectContainer value = new TlvDataObjectContainer(valueExpected);
ConstructedTlvDataObject tlvObject = new ConstructedTlvDataObject(tag, length, value);
/* set arbitrary but valid constructed tag different from the one defined before */
byte[] tagExpected2 = new byte[] { (byte) 0x24 };
TlvTag tagMod = tlvObject.getTlvTag();
Deencapsulation.setField(tagMod, "tagField", tagExpected2);
boolean isEqual = tagMod.equals(tlvObject.getTlvTag());
assertEquals("Stored tag must not be returned directly", isEqual, false);
}
/**
* Positive test case:
* Construct constructed TLV data object from basic T only
*/
@Test
public void testConstructorTag() {
/* set arbitrary but valid constructed tag */
byte[] tagExpected = new byte[] { (byte) 0x21 };
TlvTag tag = new TlvTag(tagExpected);
ConstructedTlvDataObject tlvObject = new ConstructedTlvDataObject(tag);
/* set arbitrary but valid length matching actual length of value (0) */
byte[] lengthExpected = new byte[] { (byte) 0x00 };
byte[] tlvExpected = Utils.concatByteArrays(tagExpected,
lengthExpected);
assertArrayEquals("Equals expected byte array representation", tlvObject.toByteArray(), tlvExpected);
}
/**
* Positive test case:
* Add primitive tag
*/
@Test
public void testAddTlvDataObjectTlvDataObjectPrimitiveTag() {
/* set arbitrary but valid constructed tag */
byte[] tagExpected = new byte[] { (byte) 0x21 };
TlvTag tag = new TlvTag(tagExpected);
ConstructedTlvDataObject tlvObject = new ConstructedTlvDataObject(tag);
/* set arbitrary but valid primitive TLV data object */
byte[] tlvExpected2 = new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0xFF, (byte) 0xFF };
PrimitiveTlvDataObject tlvObject2 = new PrimitiveTlvDataObject(tlvExpected2);
tlvObject.addTlvDataObject(tlvObject2);
/* set arbitrary but valid length matching actual length of value */
byte[] lengthExpected3 = new byte[] { (byte) 0x04 };
byte[] tlvExpected3 = Utils.concatByteArrays(tagExpected, lengthExpected3, tlvExpected2);
assertArrayEquals("Equals expected byte array representation", tlvObject.toByteArray(), tlvExpected3);
}
/**
* Positive test case: Add nested constructed tags
*/
@Test
public void testAddTlvDataObjectTlvDataObjectNestedConstructedTlvDataObject() {
/* set arbitrary but valid constructed tag */
byte[] tagExpected = new byte[] { (byte) 0x21 };
TlvTag tag = new TlvTag(tagExpected);
ConstructedTlvDataObject tlvObject1 = new ConstructedTlvDataObject(tag);
/* set arbitrary but valid primitive TLV data object */
byte[] tlvExpected2 = new byte[] { (byte) 0x01, (byte) 0x02,
(byte) 0xFF, (byte) 0xFF };
PrimitiveTlvDataObject tlvObject11 = new PrimitiveTlvDataObject(
tlvExpected2);
tlvObject1.addTlvDataObject(tlvObject11);
ConstructedTlvDataObject tlvObject12 = new ConstructedTlvDataObject(tag);
PrimitiveTlvDataObject tlvObject121 = new PrimitiveTlvDataObject(
tlvExpected2);
PrimitiveTlvDataObject tlvObject122 = new PrimitiveTlvDataObject(
tlvExpected2);
tlvObject12.addTlvDataObject(tlvObject121);
tlvObject12.addTlvDataObject(tlvObject122);
tlvObject1.addTlvDataObject(tlvObject12);
ConstructedTlvDataObject tlvObject13 = new ConstructedTlvDataObject(tag);
tlvObject1.addTlvDataObject(tlvObject13);
byte[] lengthExpected12 = TlvLength
.getLengthEncoding(2 * tlvExpected2.length);
byte[] lengthExpected13 = TlvLength.getLengthEncoding(0);
byte[] lengthExpected1 = TlvLength.getLengthEncoding(tlvObject11
.getLength()
+ tlvObject12.getTlvTag().getLength()
+ lengthExpected12.length
+ (2 * tlvExpected2.length)
+ tagExpected.length + 1 + 0);
byte[] tlvExpectedX = Utils.concatByteArrays(tagExpected,
lengthExpected1, tlvExpected2, tagExpected, lengthExpected12,
tlvExpected2, tlvExpected2, tagExpected, lengthExpected13);
assertArrayEquals("Equals expected byte array representation",
tlvObject1.toByteArray(), tlvExpectedX);
}
/**
* Positive test case: Get no of elements in nested constructed TLV data
* object
*/
@Test
public void testGetNoOfElementsNestedConstructedTlvDataObject() {
/* set arbitrary but valid constructed tag */
byte[] tagExpected = new byte[] { (byte) 0x21 };
TlvTag tag = new TlvTag(tagExpected);
ConstructedTlvDataObject tlvObject1 = new ConstructedTlvDataObject(tag);
assertEquals("Is expected no of elements",
tlvObject1.getNoOfElements(), 0);
/* set arbitrary but valid primitive TLV data object */
byte[] tlvExpected2 = new byte[] { (byte) 0x01, (byte) 0x02,
(byte) 0xFF, (byte) 0xFF };
PrimitiveTlvDataObject tlvObject11 = new PrimitiveTlvDataObject(
tlvExpected2);
tlvObject1.addTlvDataObject(tlvObject11);
assertEquals("Is expected no of elements",
tlvObject1.getNoOfElements(), 1);
ConstructedTlvDataObject tlvObject12 = new ConstructedTlvDataObject(tag);
PrimitiveTlvDataObject tlvObject121 = new PrimitiveTlvDataObject(
tlvExpected2);
PrimitiveTlvDataObject tlvObject122 = new PrimitiveTlvDataObject(
tlvExpected2);
tlvObject12.addTlvDataObject(tlvObject121);
tlvObject12.addTlvDataObject(tlvObject122);
tlvObject1.addTlvDataObject(tlvObject12);
assertEquals("Is expected no of elements",
tlvObject1.getNoOfElements(), 2);
ConstructedTlvDataObject tlvObject13 = new ConstructedTlvDataObject(tag);
tlvObject1.addTlvDataObject(tlvObject13);
assertEquals("Is expected no of elements",
tlvObject1.getNoOfElements(), 3);
}
/**
* Positive test case: Get recursive no of elements in nested constructed
* TLV data object
*/
@Test
public void testGetNoOfElementsNestedConstructedTlvDataObjectRecursive() {
/* set arbitrary but valid constructed tag */
byte[] tagExpected = new byte[] { (byte) 0x21 };
TlvTag tag = new TlvTag(tagExpected);
ConstructedTlvDataObject tlvObject1 = new ConstructedTlvDataObject(tag);
assertEquals("Is expected no of elements",
tlvObject1.getNoOfElements(true), 0);
/* set arbitrary but valid primitive TLV data object */
byte[] tlvExpected2 = new byte[] { (byte) 0x01, (byte) 0x02,
(byte) 0xFF, (byte) 0xFF };
PrimitiveTlvDataObject tlvObject11 = new PrimitiveTlvDataObject(
tlvExpected2);
tlvObject1.addTlvDataObject(tlvObject11);
assertEquals("Is expected no of elements",
tlvObject1.getNoOfElements(true), 1);
ConstructedTlvDataObject tlvObject12 = new ConstructedTlvDataObject(tag);
PrimitiveTlvDataObject tlvObject121 = new PrimitiveTlvDataObject(
tlvExpected2);
PrimitiveTlvDataObject tlvObject122 = new PrimitiveTlvDataObject(
tlvExpected2);
tlvObject12.addTlvDataObject(tlvObject121);
tlvObject12.addTlvDataObject(tlvObject122);
tlvObject1.addTlvDataObject(tlvObject12);
assertEquals("Is expected no of elements",
tlvObject1.getNoOfElements(true), 4);
ConstructedTlvDataObject tlvObject13 = new ConstructedTlvDataObject(tag);
tlvObject1.addTlvDataObject(tlvObject13);
assertEquals("Is expected no of elements",
tlvObject1.getNoOfElements(true), 5);
}
/**
* Positive test case: Get path of tag from nested constructed TLV data
* object
*/
@Test
public void testGetTagFieldTlvPathNestedConstructedTlvDataObject() {
/* set arbitrary but valid primitive tags with ascending numbers */
TlvTag tagP1 = new TlvTag((byte) 0x01);
TlvTag tagP2 = new TlvTag((byte) 0x02);
TlvTag tagP3 = new TlvTag((byte) 0x03);
/* set arbitrary but valid constructed tags with ascending numbers */
TlvTag tagC1 = new TlvTag((byte) 0x21);
TlvTag tagC2 = new TlvTag((byte) 0x22);
TlvTag tagC3 = new TlvTag((byte) 0x23);
TlvTag tagC4 = new TlvTag((byte) 0x24);
ConstructedTlvDataObject tlvObject1 = new ConstructedTlvDataObject(
tagC1);
ConstructedTlvDataObject tlvObject11 = new ConstructedTlvDataObject(
tagC2);
ConstructedTlvDataObject tlvObject111 = new ConstructedTlvDataObject(
tagC3);
ConstructedTlvDataObject tlvObject1111 = new ConstructedTlvDataObject(
tagC4);
PrimitiveTlvDataObject tlvObject11111 = new PrimitiveTlvDataObject(
tagP1);
PrimitiveTlvDataObject tlvObject11112 = new PrimitiveTlvDataObject(
tagP2);
PrimitiveTlvDataObject tlvObject11113 = new PrimitiveTlvDataObject(
tagP3);
tlvObject1111.addTlvDataObject(tlvObject11111);
tlvObject1111.addTlvDataObject(tlvObject11112);
tlvObject1111.addTlvDataObject(tlvObject11113);
tlvObject111.addTlvDataObject(tlvObject1111);
tlvObject11.addTlvDataObject(tlvObject111);
tlvObject1.addTlvDataObject(tlvObject11);
TlvPath path = new TlvPath();
path.add(tagC2);
path.add(tagC3);
path.add(tagC4);
path.add(tagP2);
assertEquals("Is expected path", tlvObject1.getTlvDataObject(path),
tlvObject11112);
}
/**
* Positive test case: Adds a TLV data object to a certain path within a
* nested constructed TLV data object
*/
@Test
public void testAddTlvDataObjectTlvPathTlvDataObjectNestedConstructedTlvDataObject() {
/* set arbitrary but valid primitive tags with ascending numbers */
TlvTag tagP1 = new TlvTag((byte) 0x01);
TlvTag tagP2 = new TlvTag((byte) 0x02);
TlvTag tagP3 = new TlvTag((byte) 0x03);
/* set arbitrary but valid constructed tags with ascending numbers */
TlvTag tagC1 = new TlvTag((byte) 0x21);
TlvTag tagC2 = new TlvTag((byte) 0x22);
TlvTag tagC3 = new TlvTag((byte) 0x23);
TlvTag tagC4 = new TlvTag((byte) 0x24);
ConstructedTlvDataObject tlvObject1 = new ConstructedTlvDataObject(
tagC1);
ConstructedTlvDataObject tlvObject11 = new ConstructedTlvDataObject(
tagC2);
ConstructedTlvDataObject tlvObject111 = new ConstructedTlvDataObject(
tagC3);
ConstructedTlvDataObject tlvObject1111 = new ConstructedTlvDataObject(
tagC4);
PrimitiveTlvDataObject tlvObject11111 = new PrimitiveTlvDataObject(
tagP1);
PrimitiveTlvDataObject tlvObject11112 = new PrimitiveTlvDataObject(
tagP2);
PrimitiveTlvDataObject tlvObject11113 = new PrimitiveTlvDataObject(
tagP3);
tlvObject1111.addTlvDataObject(tlvObject11111);
tlvObject1111.addTlvDataObject(tlvObject11112);
tlvObject111.addTlvDataObject(tlvObject1111);
tlvObject11.addTlvDataObject(tlvObject111);
tlvObject1.addTlvDataObject(tlvObject11);
TlvPath path = new TlvPath();
path.add(tagC2);
path.add(tagC3);
path.add(tagC4);
tlvObject1.addTlvDataObject(path, tlvObject11113);
path.add(tagP3);
assertEquals("Is expected path", tlvObject1.getTlvDataObject(path),
tlvObject11113);
}
/**
* Negative test case: Adds a TLV data object to a certain non-existing path
* within a nested constructed TLV data object
*/
@Test
public void testAddTlvDataObjectTlvPathTlvDataObjectNonExistingPath() {
/* set arbitrary but valid primitive tags with ascending numbers */
TlvTag tagP1 = new TlvTag((byte) 0x01);
TlvTag tagP2 = new TlvTag((byte) 0x02);
TlvTag tagP3 = new TlvTag((byte) 0x03);
/* set arbitrary but valid constructed tags with ascending numbers */
TlvTag tagC1 = new TlvTag((byte) 0x21);
TlvTag tagC2 = new TlvTag((byte) 0x22);
TlvTag tagC3 = new TlvTag((byte) 0x23);
TlvTag tagC4 = new TlvTag((byte) 0x24);
ConstructedTlvDataObject tlvObject1 = new ConstructedTlvDataObject(
tagC1);
ConstructedTlvDataObject tlvObject11 = new ConstructedTlvDataObject(
tagC2);
ConstructedTlvDataObject tlvObject111 = new ConstructedTlvDataObject(
tagC3);
ConstructedTlvDataObject tlvObject1111 = new ConstructedTlvDataObject(
tagC4);
PrimitiveTlvDataObject tlvObject11111 = new PrimitiveTlvDataObject(
tagP1);
PrimitiveTlvDataObject tlvObject11112 = new PrimitiveTlvDataObject(
tagP2);
PrimitiveTlvDataObject tlvObject11113 = new PrimitiveTlvDataObject(
tagP3);
tlvObject1111.addTlvDataObject(tlvObject11111);
tlvObject1111.addTlvDataObject(tlvObject11112);
tlvObject111.addTlvDataObject(tlvObject1111);
tlvObject11.addTlvDataObject(tlvObject111);
tlvObject1.addTlvDataObject(tlvObject11);
TlvPath path = new TlvPath();
path.add(tagC2);
path.add(tagC4);
path.add(tagC3);
tlvObject1.addTlvDataObject(path, tlvObject11113);
assertEquals("Is expected no of elements",
tlvObject1.getNoOfElements(), 1);
assertEquals("Is expected no of elements",
tlvObject11.getNoOfElements(), 1);
assertEquals("Is expected no of elements",
tlvObject111.getNoOfElements(), 1);
assertEquals("Is expected no of elements",
tlvObject1111.getNoOfElements(), 2);
}
/**
* Positive test case: Remove a TLV data object from a certain path within a
* nested constructed TLV data object
*/
@Test
public void testRemoveTlvDataObjectTlvPath() {
/* set arbitrary but valid primitive tags with ascending numbers */
TlvTag tagP1 = new TlvTag((byte) 0x01);
TlvTag tagP2 = new TlvTag((byte) 0x02);
TlvTag tagP3 = new TlvTag((byte) 0x03);
/* set arbitrary but valid constructed tags with ascending numbers */
TlvTag tagC1 = new TlvTag((byte) 0x21);
TlvTag tagC2 = new TlvTag((byte) 0x22);
TlvTag tagC3 = new TlvTag((byte) 0x23);
TlvTag tagC4 = new TlvTag((byte) 0x24);
ConstructedTlvDataObject tlvObject1 = new ConstructedTlvDataObject(
tagC1);
ConstructedTlvDataObject tlvObject11 = new ConstructedTlvDataObject(
tagC2);
ConstructedTlvDataObject tlvObject111 = new ConstructedTlvDataObject(
tagC3);
ConstructedTlvDataObject tlvObject1111 = new ConstructedTlvDataObject(
tagC4);
PrimitiveTlvDataObject tlvObject11111 = new PrimitiveTlvDataObject(
tagP1);
PrimitiveTlvDataObject tlvObject11112 = new PrimitiveTlvDataObject(
tagP2);
PrimitiveTlvDataObject tlvObject11113 = new PrimitiveTlvDataObject(
tagP3);
tlvObject1111.addTlvDataObject(tlvObject11111);
tlvObject1111.addTlvDataObject(tlvObject11112);
tlvObject1111.addTlvDataObject(tlvObject11113);
tlvObject111.addTlvDataObject(tlvObject1111);
tlvObject11.addTlvDataObject(tlvObject111);
tlvObject1.addTlvDataObject(tlvObject11);
TlvPath path = new TlvPath();
path.add(tagC2);
path.add(tagC3);
path.add(tagC4);
path.add(tagP2);
tlvObject1.removeTlvDataObject(path);
assertEquals("Is expected path", tlvObject1111.getNoOfElements(), 2);
}
/**
* Negative test case: Remove a non-existing TLV data object from a certain
* path within a nested constructed TLV data object
*/
@Test
public void testRemoveTlvDataObjectTlvPathNonExistingTlvDataObject() {
/* set arbitrary but valid primitive tags with ascending numbers */
TlvTag tagP1 = new TlvTag((byte) 0x01);
TlvTag tagP2 = new TlvTag((byte) 0x02);
TlvTag tagP3 = new TlvTag((byte) 0x03);
/* set arbitrary but valid constructed tags with ascending numbers */
TlvTag tagC1 = new TlvTag((byte) 0x21);
TlvTag tagC2 = new TlvTag((byte) 0x22);
TlvTag tagC3 = new TlvTag((byte) 0x23);
TlvTag tagC4 = new TlvTag((byte) 0x24);
ConstructedTlvDataObject tlvObject1 = new ConstructedTlvDataObject(
tagC1);
ConstructedTlvDataObject tlvObject11 = new ConstructedTlvDataObject(
tagC2);
ConstructedTlvDataObject tlvObject111 = new ConstructedTlvDataObject(
tagC3);
ConstructedTlvDataObject tlvObject1111 = new ConstructedTlvDataObject(
tagC4);
PrimitiveTlvDataObject tlvObject11111 = new PrimitiveTlvDataObject(
tagP1);
PrimitiveTlvDataObject tlvObject11112 = new PrimitiveTlvDataObject(
tagP2);
tlvObject1111.addTlvDataObject(tlvObject11111);
tlvObject1111.addTlvDataObject(tlvObject11112);
tlvObject111.addTlvDataObject(tlvObject1111);
tlvObject11.addTlvDataObject(tlvObject111);
tlvObject1.addTlvDataObject(tlvObject11);
TlvPath path = new TlvPath();
path.add(tagC2);
path.add(tagC3);
path.add(tagC4);
path.add(tagP3);
tlvObject1.removeTlvDataObject(path);
assertEquals("Is expected path", tlvObject1111.getNoOfElements(), 2);
}
/**
* Positive test case: Sorts a constructed TLV data object according to DER
* encoding rules
*/
@Test
public void testSortComparatorDer() {
/*
* set arbitrary but valid pairs of tags with different tag numbers
* representing all combinations of class and encoding
*/
TlvTag tagP1 = new TlvTag((byte) 0x01);
TlvTag tagP2 = new TlvTag((byte) 0x02);
TlvTag tagP3 = new TlvTag((byte) 0x41);
TlvTag tagP4 = new TlvTag((byte) 0x42);
TlvTag tagP5 = new TlvTag((byte) 0x81);
TlvTag tagP6 = new TlvTag((byte) 0x82);
TlvTag tagP7 = new TlvTag((byte) 0xC1);
TlvTag tagP8 = new TlvTag((byte) 0xC2);
TlvTag tagC1 = new TlvTag((byte) 0x21);
ConstructedTlvDataObject tlvObjectC1 = new ConstructedTlvDataObject(
tagC1);
ConstructedTlvDataObject tlvObjectC2 = new ConstructedTlvDataObject(
tagC1);
PrimitiveTlvDataObject tlvObjectP1 = new PrimitiveTlvDataObject(tagP1);
PrimitiveTlvDataObject tlvObjectP2 = new PrimitiveTlvDataObject(tagP2);
PrimitiveTlvDataObject tlvObjectP3 = new PrimitiveTlvDataObject(tagP3);
PrimitiveTlvDataObject tlvObjectP4 = new PrimitiveTlvDataObject(tagP4);
PrimitiveTlvDataObject tlvObjectP5 = new PrimitiveTlvDataObject(tagP5);
PrimitiveTlvDataObject tlvObjectP6 = new PrimitiveTlvDataObject(tagP6);
PrimitiveTlvDataObject tlvObjectP7 = new PrimitiveTlvDataObject(tagP7);
PrimitiveTlvDataObject tlvObjectP8 = new PrimitiveTlvDataObject(tagP8);
tlvObjectC1.addTlvDataObject(tlvObjectP8);
tlvObjectC1.addTlvDataObject(tlvObjectP5);
tlvObjectC1.addTlvDataObject(tlvObjectP3);
tlvObjectC1.addTlvDataObject(tlvObjectP7);
tlvObjectC1.addTlvDataObject(tlvObjectP6);
tlvObjectC1.addTlvDataObject(tlvObjectP1);
tlvObjectC1.addTlvDataObject(tlvObjectP4);
tlvObjectC1.addTlvDataObject(tlvObjectP2);
tlvObjectC2.addTlvDataObject(tlvObjectP1);
tlvObjectC2.addTlvDataObject(tlvObjectP2);
tlvObjectC2.addTlvDataObject(tlvObjectP3);
tlvObjectC2.addTlvDataObject(tlvObjectP4);
tlvObjectC2.addTlvDataObject(tlvObjectP5);
tlvObjectC2.addTlvDataObject(tlvObjectP6);
tlvObjectC2.addTlvDataObject(tlvObjectP7);
tlvObjectC2.addTlvDataObject(tlvObjectP8);
tlvObjectC1.sort(new TlvDataObjectComparatorDer());
assertArrayEquals("Is expected order of elements",
tlvObjectC1.toByteArray(), tlvObjectC2.toByteArray());
}
/**
* Positive test case: Test DER encoding validity check on constructed TLV
* data object with unsorted but otherwise correctly encoded sub elements.
*/
@Test
public void testIsValidDerEncodingSorting() {
/*
* set arbitrary but valid pairs of tags with different tag numbers
* representing all combinations of class and encoding
*/
TlvTag tagP1 = new TlvTag((byte) 0x01);
TlvTag tagP2 = new TlvTag((byte) 0x02);
TlvTag tagP3 = new TlvTag((byte) 0x41);
TlvTag tagP4 = new TlvTag((byte) 0x42);
TlvTag tagP5 = new TlvTag((byte) 0x81);
TlvTag tagP6 = new TlvTag((byte) 0x82);
TlvTag tagP7 = new TlvTag((byte) 0xC1);
TlvTag tagP8 = new TlvTag((byte) 0xC2);
TlvTag tagC1 = new TlvTag((byte) 0x21);
ConstructedTlvDataObject tlvObjectC1 = new ConstructedTlvDataObject(
tagC1);
PrimitiveTlvDataObject tlvObjectP1 = new PrimitiveTlvDataObject(tagP1);
PrimitiveTlvDataObject tlvObjectP2 = new PrimitiveTlvDataObject(tagP2);
PrimitiveTlvDataObject tlvObjectP3 = new PrimitiveTlvDataObject(tagP3);
PrimitiveTlvDataObject tlvObjectP4 = new PrimitiveTlvDataObject(tagP4);
PrimitiveTlvDataObject tlvObjectP5 = new PrimitiveTlvDataObject(tagP5);
PrimitiveTlvDataObject tlvObjectP6 = new PrimitiveTlvDataObject(tagP6);
PrimitiveTlvDataObject tlvObjectP7 = new PrimitiveTlvDataObject(tagP7);
PrimitiveTlvDataObject tlvObjectP8 = new PrimitiveTlvDataObject(tagP8);
tlvObjectC1.addTlvDataObject(tlvObjectP8);
tlvObjectC1.addTlvDataObject(tlvObjectP5);
tlvObjectC1.addTlvDataObject(tlvObjectP3);
tlvObjectC1.addTlvDataObject(tlvObjectP7);
tlvObjectC1.addTlvDataObject(tlvObjectP6);
tlvObjectC1.addTlvDataObject(tlvObjectP1);
tlvObjectC1.addTlvDataObject(tlvObjectP4);
tlvObjectC1.addTlvDataObject(tlvObjectP2);
assertEquals("Is expected order of elements",
tlvObjectC1.isValidDerEncoding(), false);
tlvObjectC1.sort(new TlvDataObjectComparatorDer());
assertEquals("Is expected order of elements",
tlvObjectC1.isValidDerEncoding(), true);
}
/**
* Positive test case: Construct constructed TLV data object from basic
* T-L-V elements with L being BER but non-DER encoded. Add another TLV data
* object and check for validity of DER encoding, i.e. whether L has been
* updated and is DER encoded.
*/
@Test
public void testIsValidDerEncodingImplicitlyModifiedLength() {
/* set arbitrary but valid constructed tag */
byte[] tagExpected = new byte[] { (byte) 0x21 };
/* set arbitrary but valid BER but non-DER length matching actual length of value */
byte[] lengthExpected = new byte[] { (byte) 0x81, (byte) 0x08 };
/* set arbitrary value consisting of valid chained TLV data objects */
byte[] valueExpected = new byte[] { (byte) 0x01, (byte) 0x02,
(byte) 0xFF, (byte) 0xFF, (byte) 0x02, (byte) 0x02,
(byte) 0xEE, (byte) 0xEE };
TlvTag tag = new TlvTag(tagExpected);
TlvLength length = new TlvLength(lengthExpected);
TlvDataObjectContainer value = new TlvDataObjectContainer(valueExpected);
ConstructedTlvDataObject tlvObject1 = new ConstructedTlvDataObject(tag,
length, value);
TlvTag tag2 = new TlvTag((byte) 0x03);
PrimitiveTlvDataObject tlvObject2 = new PrimitiveTlvDataObject(tag2);
tlvObject1.addTlvDataObject(tlvObject2);
assertEquals("Is valid DER encoding",
tlvObject1.isValidDerEncoding(), true);
}
/**
* Positive test case: Construct constructed TLV data object from basic
* T-L-V elements with L being BER but non-DER encoded and check for
* validity of DER encoding.
*/
@Test
public void testIsValidDerEncodingBerNonDerLength() {
/* set arbitrary but valid constructed tag */
byte[] tagExpected = new byte[] { (byte) 0x21 };
/* set arbitrary but valid BER but non-DER length matching actual length of value */
byte[] lengthExpected = new byte[] { (byte) 0x81, (byte) 0x08 };
/* set arbitrary value consisting of valid chained TLV data objects */
byte[] valueExpected = new byte[] { (byte) 0x01, (byte) 0x02,
(byte) 0xFF, (byte) 0xFF, (byte) 0x02, (byte) 0x02,
(byte) 0xEE, (byte) 0xEE };
TlvTag tag = new TlvTag(tagExpected);
TlvLength length = new TlvLength(lengthExpected);
TlvDataObjectContainer value = new TlvDataObjectContainer(valueExpected);
ConstructedTlvDataObject tlvObject1 = new ConstructedTlvDataObject(tag,
length, value);
assertEquals("Is valid DER encoding",
tlvObject1.isValidDerEncoding(), false);
}
/**
* Negative test case: Set tag with a primitive tag
*/
@Test(expected = IllegalArgumentException.class)
public void testSetTagTagPrimitiveTag() {
/* set arbitrary but valid constructed tag */
byte[] tagExpected = new byte[] { (byte) 0x21 };
/* set arbitrary but valid length matching actual length of value */
byte[] lengthExpected = new byte[] { (byte) 0x08 };
/* set arbitrary value consisting of valid chained TLV data objects */
byte[] valueExpected = new byte[] { (byte) 0x01, (byte) 0x02,
(byte) 0xFF, (byte) 0xFF, (byte) 0x02, (byte) 0x02,
(byte) 0xEE, (byte) 0xEE };
TlvTag tag = new TlvTag(tagExpected);
TlvLength length = new TlvLength(lengthExpected);
TlvDataObjectContainer value = new TlvDataObjectContainer(valueExpected);
ConstructedTlvDataObject tlvObject = new ConstructedTlvDataObject(tag,
length, value);
/* set arbitrary but "valid" primitive tag */
byte[] tagExpected2 = new byte[] { (byte) 0x01 };
TlvTag tag2 = new TlvTag(tagExpected2);
tlvObject.setTag(tag2);
}
/**
* Negative test case: Forced primitive tag fails
*/
@Test(expected = IllegalArgumentException.class)
public void testForceTagTlvTagPrimitiveTag() {
/* set arbitrary but valid constructed tag */
byte[] tagExpected = new byte[] { (byte) 0x21 };
/* set arbitrary but valid length matching actual length of value */
byte[] lengthExpected = new byte[] { (byte) 0x08 };
/* set arbitrary value consisting of valid chained TLV data objects */
byte[] valueExpected = new byte[] { (byte) 0x01, (byte) 0x02,
(byte) 0xFF, (byte) 0xFF, (byte) 0x02, (byte) 0x02,
(byte) 0xEE, (byte) 0xEE };
TlvTag tag = new TlvTag(tagExpected);
TlvLength length = new TlvLength(lengthExpected);
TlvDataObjectContainer value = new TlvDataObjectContainer(valueExpected);
ConstructedTlvDataObject tlvObject = new ConstructedTlvDataObject(tag,
length, value);
/* set arbitrary but "valid" primitive tag */
byte[] tagExpected2 = new byte[] { (byte) 0x01 };
TlvTag tag2 = new TlvTag(tagExpected2);
tlvObject.setTag(tag2, false);
}
/**
* Positive test case: TLV data objects equals itself and other objects
* generated with the same constructor arguments
*/
@Test
public void testEqualsSameAndSameConstructorArguments() {
/* set arbitrary but valid constructed tag */
byte[] tagExpected = new byte[] { (byte) 0x21 };
/* set arbitrary but valid length matching actual length of value */
byte[] lengthExpected = new byte[] { (byte) 0x08 };
/* set arbitrary value consisting of valid chained TLV data objects */
byte[] valueExpected = new byte[] { (byte) 0x01, (byte) 0x02,
(byte) 0xFF, (byte) 0xFF, (byte) 0x02, (byte) 0x02,
(byte) 0xEE, (byte) 0xEE };
TlvTag tag = new TlvTag(tagExpected);
TlvLength length = new TlvLength(lengthExpected);
TlvDataObjectContainer value = new TlvDataObjectContainer(valueExpected);
ConstructedTlvDataObject tlvObject1 = new ConstructedTlvDataObject(tag,
length, value);
ConstructedTlvDataObject tlvObject2 = new ConstructedTlvDataObject(tag,
length, value);
assertEquals("Equals self", tlvObject1, tlvObject1);
assertEquals("Equals same constructor arguments", tlvObject1,
tlvObject2);
}
/**
* Positive test case: step by step add nested constructed tags and check
* for correct computation of length
*/
@Test
public void testAddTlvDataObjectTlvDataObjectLengthCheckForNestedConstructedTlvDataObject() {
/* set arbitrary but valid constructed tag */
byte[] tagExpected = new byte[] { (byte) 0x21 };
TlvTag tag = new TlvTag(tagExpected);
ConstructedTlvDataObject tlvObject1 = new ConstructedTlvDataObject(tag);
assertEquals("Equals expected length", tlvObject1.getLengthValue(), 0);
/* set arbitrary but valid primitive TLV data object */
byte[] tlvExpected2 = new byte[] { (byte) 0x01, (byte) 0x02,
(byte) 0xFF, (byte) 0xFF };
PrimitiveTlvDataObject tlvObject11 = new PrimitiveTlvDataObject(
tlvExpected2);
tlvObject1.addTlvDataObject(tlvObject11);
assertEquals("Equals expected length", tlvObject1.getLengthValue(),
tlvObject11.getLength());
ConstructedTlvDataObject tlvObject12 = new ConstructedTlvDataObject(tag);
assertEquals("Equals expected length", tlvObject12.getLengthValue(), 0);
PrimitiveTlvDataObject tlvObject121 = new PrimitiveTlvDataObject(
tlvExpected2);
PrimitiveTlvDataObject tlvObject122 = new PrimitiveTlvDataObject(
tlvExpected2);
tlvObject12.addTlvDataObject(tlvObject121);
tlvObject12.addTlvDataObject(tlvObject122);
assertEquals("Equals expected length", tlvObject12.getLengthValue(),
2 * (tlvObject121.getLength()));
tlvObject1.addTlvDataObject(tlvObject12);
assertEquals("Equals expected length", tlvObject1.getLengthValue(),
tlvObject11.getLength() + tlvObject12.getLength());
ConstructedTlvDataObject tlvObject13 = new ConstructedTlvDataObject(tag);
tlvObject1.addTlvDataObject(tlvObject13);
assertEquals(
"Equals expected length",
tlvObject1.getLengthValue(),
tlvObject11.getLength() + tlvObject12.getLength()
+ tlvObject13.getLength());
}
/**
* Negative test case: the method setValue is getting the tlvDataObjectContainerInput, which is null.
*/
@Test(expected=NullPointerException.class)
public void testSetValue_tlvDataObject_ContainerInput_Is_Null()
{
ConstructedTlvDataObject tlvObject = (ConstructedTlvDataObject) TlvDataObjectFactory.createTLVDataObject("21080102FFFF0202EEEE");
tlvObject.setValue(null);
}
/**
* Negative test case: the method setTag is getting the tlvTagInput, which is null.
*/
@Test(expected=NullPointerException.class)
public void testSetTag_TlvTag_Input_Is_Null()
{
ConstructedTlvDataObject tlvObject = (ConstructedTlvDataObject) TlvDataObjectFactory.createTLVDataObject("21080102FFFF0202EEEE");
tlvObject.setTag(null, true);
}
//TODO missing tests
// modification of child values / update of length field
// expected methods like testGetLength_ChildLenghtIncreased and testGetLength_ChildLengthDecreased
// maybe methods like testGetLength_ChildAdded and testGetLength_ChildRemoved, these can be marked with @Ignore and linked in Javadoc to similar methods like testAddTlvDataObject...
}