/*******************************************************************************
* Copyright (c) 2008, 2011 Thomas Holland (thomas@innot.de) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Thomas Holland - initial API and implementation
*******************************************************************************/
/**
*
*/
package de.innot.avreclipse.core.toolinfo.fuses;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import de.innot.avreclipse.core.toolinfo.fuses.ConversionResults.ConversionStatus;
/**
* @author U043192
*
*/
public class FuseByteValuesTest {
private ByteValues testvalues;
private final static FuseType FUSE = FuseType.FUSE;
private static int[] values6 = new int[] { 0xDE, 0xAD, 0xBE, 0xEF, 0xAA, 0xBB };
private static int[] values3 = new int[] { 0xAB, 0xAD, -1 };
private static int[] defaults6 = new int[] { -1, -1, -1, -1, -1, -1 };
/**
* @throws java.lang.Exception
*/
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
/**
* @throws java.lang.Exception
*/
@AfterClass
public static void tearDownAfterClass() throws Exception {
}
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
}
/**
* Test method for
* {@link de.innot.avreclipse.core.toolinfo.fuses.FuseByteValues#FuseByteValues(java.lang.String)}
* .
*/
@Test
public void testFuseByteValuesString() {
// Test the constructor with String parameter
// 1. Test a valid mcuid
testvalues = new ByteValues(FUSE, "atmega16");
assertNotNull("FuseByteValue(\"atmega16\") returned null", testvalues);
// 2. Test a null mcu id: This should throw an Assertion error
try {
testvalues = new ByteValues(FUSE, (String) null);
fail("FuseByteValues((String)null) did not throw an error");
} catch (Exception e) {
// test passed
}
}
/**
* Test method for
* {@link de.innot.avreclipse.core.toolinfo.fuses.FuseByteValues#FuseByteValues(de.innot.avreclipse.core.toolinfo.fuses.ByteValues)}
* .
*/
@Test
public void testFuseByteValuesByteValues() {
// Test the clone constructor
// Create source object
ByteValues source = new ByteValues(FUSE, "at90pwm2");
source.setValues(values3);
testvalues = new ByteValues(source);
assertNotNull("FuseByteValue(source) returned null", testvalues);
assertEquals("Cloning did not copy mcu id field", "at90pwm2", testvalues.getMCUId());
assertArrayEquals("Cloning did not copy values", values3, testvalues.getValues());
// Test a null source: This should throw an Assertion error
try {
testvalues = new ByteValues((ByteValues) null);
fail("FuseByteValues((ByteValues)null) did not throw an error");
} catch (Exception e) {
// test passed
}
}
/**
* Test method for {@link de.innot.avreclipse.core.toolinfo.fuses.FuseByteValues#getByteCount()}
* .
*/
@Test
public void testGetByteCount() {
// test 6 fuse byte mcu
testvalues = new ByteValues(FUSE, "atxmega64a1");
assertEquals("Wrong bytecount for atxmega64a1", 6, testvalues.getByteCount());
// test 3 fuse byte mcu
testvalues = new ByteValues(FUSE, "at90pwm2");
assertEquals("Wrong bytecount for at90pwm2", 3, testvalues.getByteCount());
// test 2 fuse byte mcu
testvalues = new ByteValues(FUSE, "atmega323");
assertEquals("Wrong bytecount for atmega323", 2, testvalues.getByteCount());
// test 1 fuse byte mcu
testvalues = new ByteValues(FUSE, "attiny12");
assertEquals("Wrong bytecount for attiny12", 1, testvalues.getByteCount());
// test 0 fuse byte mcu
testvalues = new ByteValues(FUSE, "at86rf401");
assertEquals("Wrong bytecount for at86rf401", 0, testvalues.getByteCount());
}
/**
* Test method for {@link de.innot.avreclipse.core.toolinfo.fuses.ByteValues#getMCUId()}.
*/
@Test
public void testGetMCUId() {
testvalues = new ByteValues(FUSE, "at86rf401");
assertEquals("Wrong MCU id", "at86rf401", testvalues.getMCUId());
testvalues = new ByteValues(FUSE, "atxmega128a1");
assertEquals("Wrong MCU id", "atxmega128a1", testvalues.getMCUId());
}
/**
* Test method for {@link de.innot.avreclipse.core.toolinfo.fuses.ByteValues#setValue(int, int)}
* .
*/
@Test
public void testSetValues() {
// Test setting and getting byte arrays
testvalues = new ByteValues(FUSE, "atxmega128a1");
// Values should now be at the default value (-1)
assertArrayEquals("Wrong default values", defaults6, testvalues.getValues());
// Set new values and test them - all together and each one seperate
testvalues.setValues(values6);
int[] values = testvalues.getValues();
assertEquals("Wrong number of bytes returned", 6, values.length);
assertArrayEquals("Wrong values", values6, values);
for (int i = 0; i < values6.length; i++) {
assertEquals("Wrong value at [" + i + "]", values6[i], testvalues.getValue(i));
}
// Test an values array of a different length
testvalues.setValues(values3);
values = testvalues.getValues();
assertEquals("Wrong number of bytes returned", 6, values.length);
for (int i = 0; i < values3.length; i++) {
assertEquals("Wrong value at [" + i + "]", values3[i], testvalues.getValue(i));
}
// test a longer array (should be truncated)
testvalues = new ByteValues(FUSE, "atmega323");
testvalues.setValues(values6);
values = testvalues.getValues();
assertEquals("Wrong number of bytes returned", 2, values.length);
for (int i = 0; i < values.length; i++) {
assertEquals("Wrong value at [" + i + "]", values6[i], testvalues.getValue(i));
}
}
/**
* Test method for {@link de.innot.avreclipse.core.toolinfo.fuses.ByteValues#setValue(int, int)}
* .
*/
@Test
public void testSetValue() {
// Test setting and getting single bytes
testvalues = new ByteValues(FUSE, "atxmega128a1");
for (int i = 0; i < values6.length; i++) {
testvalues.setValue(i, values6[i]);
}
assertArrayEquals("Wrong values", values6, testvalues.getValues());
// Test illegal index: should throw an exception
try {
testvalues.setValue(-1, 0);
fail("setValue(-1,0) did not throw exception");
} catch (IllegalArgumentException iae) {
}
try {
testvalues.setValue(6, 0);
fail("setValue(6,0) did not throw exception");
} catch (IllegalArgumentException iae) {
}
// Test legal values
testvalues.setValue(0, -1);
testvalues.setValue(1, 0);
testvalues.setValue(2, 255);
assertEquals("getValue() for -1", -1, testvalues.getValue(0));
assertEquals("getValue() for 0", 0, testvalues.getValue(1));
assertEquals("getValue() for 255", 255, testvalues.getValue(2));
// Test illegal values
try {
testvalues.setValue(0, -2);
fail("setValue(0, -2) did not throw exception");
} catch (IllegalArgumentException iae) {
}
try {
testvalues.setValue(0, 256);
fail("setValue(0, 256) did not throw exception");
} catch (IllegalArgumentException iae) {
}
}
/**
* Test method for
* {@link de.innot.avreclipse.core.toolinfo.fuses.ByteValues#setNamedValue(java.lang.String, int)}
* .
*/
@Test
public void testSetNamedValue() {
testvalues = new ByteValues(FUSE, "atmega16");
// Test a single bit without shifting
// BOOTRST = byte 1, bit 0
testvalues.setValue(1, 0xAA); // = 10101010 pattern
// Set to 1
testvalues.setNamedValue("BOOTRST", 0x01);
assertEquals(bin(0xAB), bin(testvalues.getValue(1)));
int value = testvalues.getNamedValue("BOOTRST");
assertEquals("getNamedValue(\"BOOTRST\")", 0x01, value);
// Set to 0
testvalues.setNamedValue("BOOTRST", 0x00);
assertEquals(bin(0xAA), bin(testvalues.getValue(1)));
value = testvalues.getNamedValue("BOOTRST");
assertEquals("getNamedValue(\"BOOTRST\")", 0x00, value);
// Test a single bit with shifting
// BODEN = byte 0, bit 7
testvalues.setValue(0, 0x00);
// Set to 1
testvalues.setNamedValue("BODEN", 0x01);
assertEquals(bin(0x40), bin(testvalues.getValue(0)));
value = testvalues.getNamedValue("BODEN");
assertEquals("getNamedValue(\"BODEN\")", 0x01, value);
// Set to 0
testvalues.setNamedValue("BODEN", 0x00);
assertEquals(bin(0x00), bin(testvalues.getValue(0)));
value = testvalues.getNamedValue("BODEN");
assertEquals("getNamedValue(\"BODEN\")", 0x00, value);
// Test multibit with shifting
// BOOTSZ = byte 1, bit 1-2
testvalues.setValue(1, 0x00);
// Set to 0
testvalues.setNamedValue("BOOTSZ", 0x00);
assertEquals(bin(0x00), bin(testvalues.getValue(1)));
value = testvalues.getNamedValue("BOOTSZ");
assertEquals("getNamedValue(\"BOOTSZ\")", 0x00, value);
// Set to 1
testvalues.setNamedValue("BOOTSZ", 0x01);
assertEquals(bin(0x02), bin(testvalues.getValue(1)));
value = testvalues.getNamedValue("BOOTSZ");
assertEquals("getNamedValue(\"BOOTSZ\")", 0x01, value);
// Set to 2
testvalues.setNamedValue("BOOTSZ", 0x02);
assertEquals(bin(0x04), bin(testvalues.getValue(1)));
value = testvalues.getNamedValue("BOOTSZ");
assertEquals("getNamedValue(\"BOOTSZ\")", 0x02, value);
// Set to 3
testvalues.setNamedValue("BOOTSZ", 0x03);
assertEquals(bin(0x06), bin(testvalues.getValue(1)));
value = testvalues.getNamedValue("BOOTSZ");
assertEquals("getNamedValue(\"BOOTSZ\")", 0x03, value);
// Test Failures
// Illegal values
try {
testvalues.setNamedValue("BOOTSZ", 0x04);
fail("Did not throw with illegal value 0x04");
} catch (IllegalArgumentException iae) {
// Test passed
}
try {
testvalues.setNamedValue("SUT_CKSEL", -1);
fail("Did not throw with illegal value -1");
} catch (IllegalArgumentException iae) {
// Test passed
}
// Illegal names
try {
testvalues.setNamedValue("foobar", 0);
fail("Did not throw with illegal name \"foobar\"");
} catch (IllegalArgumentException iae) {
// Test passed
}
try {
testvalues.setNamedValue("", 0);
fail("Did not throw with illegal empty name");
} catch (IllegalArgumentException iae) {
// Test passed
}
try {
testvalues.setNamedValue(null, 0);
fail("Did not throw with illegal null name");
} catch (IllegalArgumentException iae) {
// Test passed
}
}
/**
* Test method for {@link de.innot.avreclipse.core.toolinfo.fuses.ByteValues#clearValues()}.
*/
@Test
public void testClearValues() {
testvalues = new ByteValues(FUSE, "atxmega64a1");
// Values should now be at the default value (-1)
assertArrayEquals("Wrong default values", defaults6, testvalues.getValues());
// Set new values, clear them and test - all together and each one seperate
testvalues.setValues(values6);
testvalues.clearValues();
assertArrayEquals("Wrong values after clear", defaults6, testvalues.getValues());
for (int i = 0; i < values6.length; i++) {
assertEquals("Wrong value at [" + i + "] after clear", -1, testvalues.getValue(i));
}
}
/**
* Test method for {@link de.innot.avreclipse.core.toolinfo.fuses.ByteValues#convertTo()}.
*/
@Test
public void testConvertTo() {
// First test: convert from ATXmega64 to ATXmega128
// these two have identical fuses,
ConversionResults results = new ConversionResults();
testvalues = new ByteValues(FUSE, "atxmega64a1");
testvalues.setValues(values6);
ByteValues targetvalues = testvalues.convertTo("atxmega128a1", results);
assertEquals("Wrong MCU", "atxmega128a1", targetvalues.getMCUId());
assertEquals("Successrate not as expected", 100, results.getSuccessRate());
// Second test: convert ATmega16 to ATmega32
// They differ by only one bitfield: SUT_CKSEL vs. CKSEL
// But with the fixed description files they have identical fusebytes.
testvalues = new ByteValues(FUSE, "atmega16");
testvalues.setValues(values3);
targetvalues = testvalues.convertTo("atmega32", results);
assertEquals("Wrong MCU", "atmega32", targetvalues.getMCUId());
assertEquals("Successrate not as expected", 100, results.getSuccessRate());
// Third test: convert ATmega16 to ATmega161
// They have only two common BitFields: SPIEN and BOOTRST
// ATmega16 add. fields: OCDEN, JTAGEN, EESAVE, BOOTSZ, CKOPT, BODLEVEL, BODEN, SUT_CKSEL
// ATmega161 add. fields: SUT, CKSEL
targetvalues = testvalues.convertTo("atmega161", results);
assertEquals("Wrong MCU", "atmega161", targetvalues.getMCUId());
assertEquals("SPIEN not successful", ConversionStatus.SUCCESS,
results.getStatusForName("SPIEN"));
assertEquals("BOOTRST not successful", ConversionStatus.SUCCESS,
results.getStatusForName("BOOTRST"));
assertEquals("JTAGEN wrong status", ConversionStatus.NOT_IN_TARGET,
results.getStatusForName("JTAGEN"));
assertEquals("BODLEVEL wrong status", ConversionStatus.NOT_IN_TARGET,
results.getStatusForName("BODLEVEL"));
assertEquals("SUT wrong status", ConversionStatus.NOT_IN_SOURCE,
results.getStatusForName("SUT"));
assertEquals("CKSEL wrong status", ConversionStatus.NOT_IN_SOURCE,
results.getStatusForName("CKSEL"));
assertTrue("SUT_CKSEL illegally converted to CKSEL.",
testvalues.getNamedValue("SUT_CKSEL") != targetvalues.getNamedValue("CKSEL"));
}
/**
* Test method for
* {@link de.innot.avreclipse.core.toolinfo.fuses.ByteValues#addByteValuesChangeListener}.
*/
@Test
public void testListener() {
ByteValueChangeEvent[] fEvents = null;
testvalues = new ByteValues(FUSE, "atmega16");
testvalues.setDefaultValues();
MyByteValuesChangeListener myListener = new MyByteValuesChangeListener();
testvalues.addChangeListener(myListener);
// Changing a single bit for a currently undefined byte will set all bits of that byte to 1
// therefore causing, in this case, 7 change events.
testvalues.setNamedValue("SPIEN", 0x01);
fEvents = myListener.getEvents();
assertNotNull("No Events fired", fEvents);
assertEquals("Wrong number of event objects", 7, fEvents.length);
// Changing the same bit again will cause only a single event
testvalues.setNamedValue("SPIEN", 0x00);
fEvents = myListener.getEvents();
assertNotNull("No Events fired", fEvents);
assertEquals("Wrong number of event objects", 1, fEvents.length);
ByteValueChangeEvent event = fEvents[0];
assertEquals("Wrong BitField in event", "SPIEN", event.name);
assertEquals("Wrong new value in event", 0, event.bitfieldvalue);
assertEquals("Wrong byte index", 1, event.byteindex);
assertEquals("Wrong byte value", 0xDF, event.bytevalue);
// cause multiple BitField change events
final String[] names = new String[] { "BODLEVEL", "BODEN", "SUT_CKSEL" };
testvalues.setValue(0, 0xC1);
fEvents = myListener.getEvents();
assertNotNull("No Events fired", fEvents);
assertEquals("Wrong number of event objects", 3, fEvents.length);
for (int i = 0; i < fEvents.length; i++) {
assertEquals("Wrong byte index in event" + event, 0, fEvents[i].byteindex);
assertEquals("Wrong byte value in event" + event, 0xC1, fEvents[i].bytevalue);
boolean foundname = false;
for (String name : names) {
if (name.equals(fEvents[i].name)) {
foundname = true;
}
}
if (!foundname)
fail("None of the required names in the events");
}
}
private String bin(int value) {
return Integer.toBinaryString(value);
}
@Ignore
private class MyByteValuesChangeListener implements IByteValuesChangeListener {
private ByteValueChangeEvent[] fEvents = null;
public void byteValuesChanged(ByteValueChangeEvent[] events) {
fEvents = events;
}
public ByteValueChangeEvent[] getEvents() {
return fEvents;
}
}
}