I want to test code that produces byte arrays used to send as UDP packets.
Although I'm not able to reproduce every byte in my test (e.g. random bytes, timestamps), I'd like to test the bytes that I can predetermine.
Is something like the following possible using JUnit 4.8 (and Mockito 1.8)?
Packet packet = new RandomPacket();
byte[] bytes = new byte[] {
0x00, 0x02, 0x05, 0x00, anyByte(), anyByte(), anyByte(), anyByte(), 0x00
};
assertArrayEquals(packet.getBytes(), bytes);
The sample above is of course not working, I'm just searching for a way to use some sort of wildcard in assertArrayEquals().
PS: My only alternative right now is to check each byte individually (and omit random ones). But this is quiet tedious and not really reusable.
Thanks to the answer from JB Nizet I have the following code in place now, working just fine:
private static int any() {
return -1;
}
private static void assertArrayEquals(int[] expected, byte[] actual) {
if(actual.length != expected.length) {
fail(String.format("Arrays differ in size: expected <%d> but was <%d>", expected.length, actual.length));
}
for(int i = 0; i < expected.length; i ++) {
if(expected[i] == -1) {
continue;
}
if((byte) expected[i] != actual[i]) {
fail(String.format("Arrays differ at element %d: expected <%d> but was <%d>", i, expected[i], actual[i]));
}
}
}
You could simply write your expected array as an array of integers, and use a special value (such as -1) to represent the wildcard. It's the same trick as the read methods of the input streams. You would just have to write your custom assertEqualsWithWildCard(int[] expected, byte[] actual).
If you are going to be writing a lot of code like this, I would write a separate class to "decode" the packet into meaningful fields. Then (of course, after testing that the class itself works) you can write sensible tests like
assertEquals(42, packet.length());
assertEquals(0xDEADBEEF, packet.checksum());
etc.
That way, you are not "omitting random bytes", and your code will be much more readable (if a tad more verbose).
Related
I am creating a java Desktop Application. I want to write the data into the register of a device. As per my project document, size of the register is 16-bit long. I am using EasyModbusJava jar to write data into the register. Till now I have written some integer data on the device's register. Now I want to write the ascii of 32 characters at 16 consecutive register(2 Character per Register). But issue is that the available methods for writing on the registers takes int as an argument. If am passing the short(int) array of ascii values then it needs to be typecast which means that it will no longer be acquiring the size of the short data type.
There are two methods are available to write into the registers address.
For Writing at Single Register
public void WriteMultipleRegisters(int startingAddress, int[] values){...}
For Writing at Multiple Register
public void WriteMultipleRegisters(int startingAddress, int[] values){...}
Suggest some way to resolve my issue.
Below is the link of the jar file documentation which I am using in my project.
Docs of Jar File.
I think the easiest thing to do is use a ByteBuffer to manage this byte manipulation. Something like,
char[] arr = "Hello, World".toCharArray();
ByteBuffer bb = ByteBuffer.allocate(arr.length);
for (char ch : arr) {
bb.put((byte) ch);
}
bb.rewind();
// You may need a call to ByteBuffer.order(ByteOrder) here.
for (int i = 0; i < arr.length / 2; i++) {
int v = bb.getShort(); // Reads two bytes and converts to 16-bit short integer
System.out.println(v);
}
I'm working on an iOS app that's supposed to decode a certain type of Aztec barcode (example, PDF). I need the scanner to return the data on a low level, since it's zlib compressed and I need to decompress it afterwards. The built-in barcode scanner using AVCapture works fine for regular string data but fails in my case.
I have turned to Zxing, or rather its Objective C port ZXingObjC, in the hope of being able to access the decoded barcode data before it gets turned into a string. I was half successful. The ZXResult returned does contain a ZXByteArray called rawBytes, but only for QR codes (for Aztec codes it's nil)! I looked inside ZXAztecDecoder.m and sure enough, the byte array is never populated, not even in the original Zxing code in Java.
Someone tried to fix it for the original library (Pull Request, Line 80) by doing
byte[] rawBytes = convertBoolArrayToByteArray(correctedBits);
I'd like to add the same functionality for ZXingObjC, but I'm stuck trying to convert theZXBoolArray to a ZXByteArray. Here is the decode function as I envision it:
- (ZXDecoderResult *)decode:(ZXAztecDetectorResult *)detectorResult error:(NSError **)error {
self.ddata = detectorResult;
ZXBitMatrix *matrix = [detectorResult bits];
ZXBoolArray *rawbits = [self extractBits:matrix];
if (!rawbits) {
if (error) *error = ZXFormatErrorInstance();
return nil;
}
ZXBoolArray *correctedBits = [self correctBits:rawbits error:error];
if (!correctedBits) {
return nil;
}
ZXByteArray *rawBytes = /* somehow turn correctedBits into ZXByteArray */;
NSString *result = [[self class] encodedData:correctedBits];
return [[ZXDecoderResult alloc] initWithRawBytes:rawBytes text:result byteSegments:nil ecLevel:nil];
}
If somebody knows how to do this or has an idea how to go about it, I'd appreciate it. If it works out, I'd like to contribute the code to ZXingObjC, so this won't bug people in the future. Thanks in advance!
It's not actually a solution to the problem, but my persistent nagging helped fix this overdue issue in the original ZXing Github repo. If that change makes it upstream into ZXingObjC at some point, I can close this question for good.
If anybody wants to help translate these Java lines (source) to Objective-C, I'd surely appreciate it.
/**
* Reads a code of length 8 in an array of bits, padding with zeros
*/
private static byte readByte(boolean[] rawbits, int startIndex) {
int n = rawbits.length - startIndex;
if (n >= 8) {
return (byte) readCode(rawbits, startIndex, 8);
}
return (byte) (readCode(rawbits, startIndex, n) << (8 - n));
}
/**
* Packs a bit array into bytes, most significant bit first
*/
static byte[] convertBoolArrayToByteArray(boolean[] boolArr) {
byte[] byteArr = new byte[(boolArr.length + 7) / 8];
for (int i = 0; i < byteArr.length; i++) {
byteArr[i] = readByte(boolArr, 8 * i);
}
return byteArr;
}
Hello boys and girls.
I'm developing a terminal based client application which communicates over TCP/IP to server and sends and receives an arbitary number of raw bytes. Each byte represents a command which I need to parse to Java classes representing these commands, for further use.
My question how I should parse these bytes efficiently. I don't want to end up with bunch of nested ifs and switch-cases.
I have the data classes for these commands ready to go. I just need to figure out the proper way of doing the parsing.
Here's some sample specifications:
Byte stream can be for example in
integers:[1,24,2,65,26,18,3,0,239,19,0,14,0,42,65,110,110,97,32,109,121,121,106,228,42,15,20,5,149,45,87]
First byte is 0x01 which is start of header containing only one byte.
Second one is the length which is the number of bytes in certain
commands, only one byte here also.
The next can be any command where the first byte is the command, 0x02
in this case, and it follows n number of bytes which are included in
the command.
So on. In the end there are checksum related bytes.
Sample class representing the set_cursor command:
/**
* Sets the cursor position.
* Syntax: 0x0E | position
*/
public class SET_CURSOR {
private final int hexCommand = 0x0e;
private int position;
public SET_CURSOR(int position) {
}
public int getPosition() {
return position;
}
public int getHexCommnad() {
return hexCommand;
}
}
When parsing byte streams like this the best Design Pattern to use is the Command Pattern. Each of the different Commands will act as handlers to process the next several bytes in the stream.
interface Command{
//depending on your situation,
//either use InputStream if you don't know
//how many bytes each Command will use
// or the the commands will use an unknown number of bytes
//or a large number of bytes that performance
//would be affected by copying everything.
void execute(InputStream in);
//or you can use an array if the
//if the number of bytes is known and small.
void execute( byte[] data);
}
Then you can have a map containing each Command object for each of the byte "opcodes".
Map<Byte, Command> commands = ...
commands.put(Byte.parseByte("0x0e", 16), new SetCursorCommand() );
...
Then you can parse the message and act on the Commands:
InputStream in = ... //our byte array as inputstream
byte header = (byte)in.read();
int length = in.read();
byte commandKey = (byte)in.read();
byte[] data = new byte[length]
in.read(data);
Command command = commands.get(commandKey);
command.execute(data);
Can you have multiple Commands in the same byte message? If so you could then easily wrap the Command fetching and parsing in a loop until the EOF.
you can try JBBP library for that https://github.com/raydac/java-binary-block-parser
#Bin class Parsed { byte header; byte command; byte [] data; int checksum;}
Parsed parsed = JBBPParser.prepare("byte header; ubyte len; byte command; byte [len] data; int checksum;").parse(theArray).mapTo(Parsed.class);
This is a huge and complex subject.
It depends on the type of the data that you will read.
Is it a looooong stream ?
Is it a lot of small independent structures/objects ?
Do you have some references between structures/objects of your flow ?
I recently wrote a byte serialization/deserialization library for a proprietary software.
I took a visitor-like approach with type conversion, the same way JAXB works.
I define my object as a Java class. Initialize the parser on the class, and then pass it the bytes to unserialize or the Java object to serialize.
The type detection (based on the first byte of your flow) is done forward with a simple case matching mechanism (1 => ClassA, 15 => ClassF, ...).
EDIT: It may be complex or overloaded with code (embedding objects) but keep in mind that nowadays, java optimize this well, it keeps code clear and understandable.
ByteBuffer can be used for parsing byte stream - What is the use of ByteBuffer in Java?:
byte[] bytesArray = {4, 2, 6, 5, 3, 2, 1};
ByteBuffer bb = ByteBuffer.wrap(bytesArray);
int intFromBB = bb.order(ByteOrder.LITTLE_ENDIAN).getInt();
byte byteFromBB = bb.get();
short shortFromBB = bb.getShort();
I've already used javax.smartcardio to read serial number from smart card without much effort. However now I'm assigned to create MF on blank card (without which serial number can't be read).I'm creating APDU command for that as per ISO 7816 guidelines,but unable to create proper APDU command because my hex values are getting converted to wrong bytes.
import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
import javax.smartcardio.TerminalFactory;
class SmartCardAPIs {
public int Create_MF() throws CardException{
//--Variable declaration
int result=0;
Card card=null;
byte[] responseData=null;
ResponseAPDU answer=null;
String SW1=null;
String SW2=null;
int cla, ins, p1, p2;
byte[] data=null;
//---------------------------------------------
//--1--Establish connection with the smart card
TerminalFactory factory = TerminalFactory.getDefault();
List<CardTerminal> terminals = factory.terminals().list();
// Use the first terminal
CardTerminal terminal = terminals.get(0);
// Connect with the card
card = terminal.connect("*");
CardChannel channel = card.getBasicChannel();
//---------------------------------------------
//--2--Create MF
cla=0x00;
ins=0xE0;
p1=0x00;
p2=0x00;
data = new byte[] {
(byte) 0x21,
(byte) 0x62,
(byte) 0x1F,
(byte) 0x82, // **** Getting converted to -126 ****
--
--
--
};
answer = channel.transmit(new CommandAPDU(cla, ins, p1, p2, data));
responseData= answer.getBytes();
if(responseData!=null)
{
if(responseData.length==2)
{
SW1=String.format("%02X ", (responseData[0])).trim();
SW2=String.format("%02X ", (responseData[1])).trim();
}
}
}
}
I've 2 problems
1: data in command APDU is taking a byte which is wrong(marked as *).
2: SW1 and SW2 are returning as 6A 80 which means parameter in data field are incorrect(I guess because of negative value while casting int in hex format to byte,but can not help much as I'm forced to do it).
The partial APDU command which I've placed here is part of full command which I've been supplied ,and the command is 100% OK and tested as I've been successful in creating MF in blank card using smart card tools with the command.I want to do the same in java now.
I assume that problem lies with the way this APDU is being getting created,may be negative value problem(I'm not very expert with java APDU stuffs although I 've created Applet to read serial number from card).
Since you say, you have a working command at hand and surely double-checked its java representation: how sure are you, that the command did not execute successfully in a preceeding attempt? (Obviously only one MF is allowed.) Problem is, that the reported error code contradicts the "correct APDU known" assumption and this is the only resolution I can think of. The java code looks correct, as far as it is given.
Other idea: The command data field of an ISO Create File should start with something like 0x6X for FCI. Possibly your 0x21 is the length of the whole template (supposed to be sent as LC), which java constructs itself from the length of the byte array, so try leaving it out.
The fact, that the 3rd byte is 0x1F, meaning 0x21 minus tag and length, supports that hypothesis.
I have tried this command :
..
..
private static final byte[] Select_App = {(byte)0x00,(byte)0xA4,(byte)0x04,(byte)0x00,(byte)0x04,(byte)0x50,(byte)0x54,(byte)0x4B,(byte)0x65};
..
..
and they worked fine, I got the right respons from the card. But I tried that command on android. So I think that byte casting is right we don't need to convert anything
Well, about java.smartcardio.*; I have the same problem with you, I can't send any command using that librari. But someone said that I have to use some java wrapper to send some commands. Umm... I'm still working on it btw... :-)
You need to convert byte to hex properly by following Methods.
Integer class = StringUtil.parseHex("your class as string");
Class StringUtil
public class StringUtil {
public static Integer parseHex(String iStr) {
int mask = 255;
if (iStr.length() > 2)
mask = 65535;
try {
return Integer.valueOf(Integer.parseInt(iStr, 16) & mask);
} catch (Exception ex) {
}
return null;
}
I have a BitSet and want to write it to a file- I came across a solution to use a ObjectOutputStream using the writeObject method.
I looked at the ObjectOutputStream in the java API and saw that you can write other things (byte, int, short etc)
I tried to check out the class so I tried to write a byte to a file using the following code but the result gives me a file with 7 bytes instead of 1 byte
my question is what are the first 6 bytes in the file? why are they there?
my question is relevant to a BitSet because i don't want to start writing lots of data to a file and realize I have random bytes inserted in the file without knowing what they are.
here is the code:
byte[] bt = new byte[]{'A'};
File outFile = new File("testOut.txt");
FileOutputStream fos = new FileOutputStream(outFile);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.write(bt);
oos.close();
thanks for any help
Avner
The other bytes will be type information.
Basically ObjectOutputStream is a class used to write Serializable objects to some destination (usually a file). It makes more sense if you think about InputObjectStream. It has a readObject() method on it. How does Java know what Object to instantiate? Easy: there is type information in there.
You could be writing any objects out to an ObjectOutputStream, so the stream holds information about the types written as well as the data needed to reconstitute the object.
If you know that the stream will always contain a BitSet, don't use an ObjectOutputStream - and if space is a premium, then convert the BitSet to a set of bytes where each bit corresponds to a bit in the BitSet, then write that directly to the underlying stream (e.g. a FileOutputStream as in your example).
The serialisation format, like many others, includes a header with magic number and version information. When you use DataOutput/OutputStream methods on ObjectOutputStream are placed in the middle of the serialised data (with no type information). This is typically only done in writeObject implementations after a call to defaultWriteObject or use of putFields.
If you only use the saved BitSet in Java, the serialization works fine. However, it's kind of annoying if you want share the bitset across multi platforms. Besides the overhead of Java serialization, the BitSet is stored in units of 8-bytes. This can generate too much overhead if your bitset is small.
We wrote this small class so we can exract byte arrays from BitSet. Depending on your usecase, it might work better than Java serialization for you.
public class ExportableBitSet extends BitSet {
private static final long serialVersionUID = 1L;
public ExportableBitSet() {
super();
}
public ExportableBitSet(int nbits) {
super(nbits);
}
public ExportableBitSet(byte[] bytes) {
this(bytes == null? 0 : bytes.length*8);
for (int i = 0; i < size(); i++) {
if (isBitOn(i, bytes))
set(i);
}
}
public byte[] toByteArray() {
if (size() == 0)
return new byte[0];
// Find highest bit
int hiBit = -1;
for (int i = 0; i < size(); i++) {
if (get(i))
hiBit = i;
}
int n = (hiBit + 8) / 8;
byte[] bytes = new byte[n];
if (n == 0)
return bytes;
Arrays.fill(bytes, (byte)0);
for (int i=0; i<n*8; i++) {
if (get(i))
setBit(i, bytes);
}
return bytes;
}
protected static int BIT_MASK[] =
{0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
protected static boolean isBitOn(int bit, byte[] bytes) {
int size = bytes == null ? 0 : bytes.length*8;
if (bit >= size)
return false;
return (bytes[bit/8] & BIT_MASK[bit%8]) != 0;
}
protected static void setBit(int bit, byte[] bytes) {
int size = bytes == null ? 0 : bytes.length*8;
if (bit >= size)
throw new ArrayIndexOutOfBoundsException("Byte array too small");
bytes[bit/8] |= BIT_MASK[bit%8];
}
}