/******************************************************************************* * 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.avrdude; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.osgi.service.prefs.BackingStoreException; import de.innot.avreclipse.TestHelper; import de.innot.avreclipse.core.properties.AVRDudeProperties; import de.innot.avreclipse.core.properties.AVRProjectProperties; import de.innot.avreclipse.core.toolinfo.fuses.ByteValues; import de.innot.avreclipse.core.toolinfo.fuses.FuseType; /** * @author Thomas Holland * */ public class FuseBytePropertiesTest { private IEclipsePreferences fPrefs; private AVRDudeProperties fAVRDudeProps; // The name and the byte values of the fuses file '/TestData/test01.fuses' private final static String TEST01_FILE = "/TestData/test01.fuses"; private final static int[] TEST01_VALUES = new int[] { 0x83, 0x83, 0xfd }; /** * @throws java.lang.Exception */ @Before public void setUp() throws Exception { fPrefs = new InstanceScope().getNode("de.innot.avreclipse.tests"); AVRProjectProperties projectProps = new AVRProjectProperties(fPrefs); fAVRDudeProps = new AVRDudeProperties(fPrefs, projectProps); } @After public void tearDown() throws Exception { // clear the preferences // fPrefs.removeNode(); // fPrefs.flush(); } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.FuseBytesProperties#FuseBytesProperties(org.osgi.service.prefs.Preferences, de.innot.avreclipse.core.properties.AVRDudeProperties)} * . */ @Test public void testFuseBytesPropertiesPreferencesAVRDudeProperties() { FuseBytesProperties props = new FuseBytesProperties(fPrefs, fAVRDudeProps); assertNotNull("Null FuseBytesProperties Object", props); } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.FuseBytesProperties#FuseBytesProperties(org.osgi.service.prefs.Preferences, de.innot.avreclipse.core.properties.AVRDudeProperties, de.innot.avreclipse.core.avrdude.FuseBytesProperties)} * . */ @Test public void testFuseBytesPropertiesPreferencesAVRDudePropertiesFuseBytesProperties() { int[] testvalues = new int[] { 11, 22, 33 }; FuseBytesProperties props = new FuseBytesProperties(fPrefs, fAVRDudeProps); // remember original values boolean oldusefile = props.getUseFile(); boolean oldwrite = props.getWrite(); // and change the values props.setMCUId("atmega128"); props.setUseFile(!oldusefile); props.setWrite(!oldwrite); props.setValues(testvalues); props.setFileName("foobar"); // Make the copy and check that the values transfered FuseBytesProperties cloneprops = new FuseBytesProperties(fPrefs, fAVRDudeProps, props); assertNotNull("Clone Constructor failed", cloneprops); assertEquals("UseFile flag was not cloned", !oldusefile, cloneprops .getUseFile()); assertEquals("Write flag was not cloned", !oldwrite, cloneprops .getWrite()); assertEquals("Filename was not cloned", "foobar", cloneprops .getFileName()); // We need to reset the 'use file' flag so that the mcuid is returned // correctly cloneprops.setUseFile(false); assertEquals("MCU ID was not cloned", "atmega128", cloneprops .getMCUId()); assertArrayEquals("ByteValues were not cloned", testvalues, cloneprops .getByteValues().getValues()); } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#getMCUId()}. * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#setMCUId(java.lang.String)} * . * * @throws CoreException * @throws IOException */ @Test public void testMCUId() throws IOException, CoreException { FuseBytesProperties props = new FuseBytesProperties(fPrefs, fAVRDudeProps); props.setUseFile(false); // don't use file as it would override // setMCUId() String defaultID = props.getMCUId(); props.setMCUId(defaultID); assertFalse("setMCUId(previousID) changed dirty state", props.isDirty()); assertEquals("get/set MCUId() failed", defaultID, props.getMCUId()); props.setMCUId("foobar"); assertTrue("setMCUId() did not change dirty state", props.isDirty()); assertEquals("get/set MCUId() failed", "foobar", props.getMCUId()); // Test with a non-existing file: returns null props.setUseFile(true); props.setFileName("foo/bar"); assertNull(props.getMCUId()); // Test with a real file IFile file = TestHelper.getPluginIFile(TEST01_FILE); String filename = file.getLocation().toOSString(); props.setFileName(filename); assertEquals("atmega2560", props.getMCUId()); } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#getWrite()}. * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#setWrite(boolean)} * . */ @Test public void testWrite() { FuseBytesProperties props = new FuseBytesProperties(fPrefs, fAVRDudeProps); boolean oldvalue = props.getWrite(); props.setWrite(oldvalue); assertFalse("setWrite(oldvalue) changed dirty state", props.isDirty()); assertEquals("get/setWrite() failed", oldvalue, props.getWrite()); props.setWrite(!oldvalue); assertTrue("setWrite(!oldvalue) did not change dirty state", props .isDirty()); assertEquals("get/setWrite() failed", !oldvalue, props.getWrite()); } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#getUseFile()} * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#setUseFile(boolean)} * . */ @Test public void testGetUseFile() { FuseBytesProperties props = new FuseBytesProperties(fPrefs, fAVRDudeProps); boolean oldvalue = props.getUseFile(); props.setUseFile(oldvalue); assertFalse("setUseFile(oldvalue) changed dirty state", props.isDirty()); assertEquals("get/setUseFile() failed", oldvalue, props.getUseFile()); props.setUseFile(!oldvalue); assertTrue("setUseFile(!oldvalue) did not change dirty state", props .isDirty()); assertEquals("get/setUseFile() failed", !oldvalue, props.getUseFile()); } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#getFileNameResolved()} * . */ @Test public void testGetFileNameResolved() { // Testing this method requires a build configuration, which in turn // requires a AVR project. So we test it at a higher level. // TODO: write high level tests } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#setBuildConfig(org.eclipse.cdt.managedbuilder.core.IConfiguration)} * . */ @Test public void testSetBuildConfig() { // Testing this method requires a build configuration, which in turn // requires a AVR project. So we test it at a higher level. // TODO: write high level tests } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#getFileName()} * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#setFileName(java.lang.String)} * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#getFileNameResolved()} * . */ @Test public void testFileName() { FuseBytesProperties props = new FuseBytesProperties(fPrefs, fAVRDudeProps); // Low level tests only (without an actual file) String testname = "foo/bar/baz"; props.setFileName(testname); assertEquals("set/getFilename() failed", testname, props.getFileName()); // without a build config the getFilenameResolved() method will return // the unchanged filename. assertEquals("getFilenameResolved() failed", testname, props .getFileNameResolved()); } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#getByteValues()} * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#setByteValues(de.innot.avreclipse.core.toolinfo.fuses.ByteValues)} * . */ @Test public void testByteValues() { FuseBytesProperties props = new FuseBytesProperties(fPrefs, fAVRDudeProps); String mcuidprops = "atmega128"; String mcuidnew = "atmega32"; int[] testvalues = new int[] { 11, 22 }; props.setMCUId(mcuidprops); props.setUseFile(false); // setByteValues() not yet implemented for // files ByteValues testbv = new ByteValues(FuseType.FUSE, mcuidnew); testbv.setValues(testvalues); props.setByteValues(testbv); // Check that all values from the new ByteValues were copied assertEquals("MCU not taken from new ByteValues", mcuidnew, props .getMCUId()); assertArrayEquals(testvalues, props.getValues()); assertTrue("Dirty flag not set", props.isDirty()); // Test wrong type of byte values ByteValues wrongvalues = new ByteValues(FuseType.LOCKBITS, mcuidnew); try { props.setByteValues(wrongvalues); fail("setByteValues(LockbitValues) did not cause an Exception"); } catch (IllegalArgumentException iae) { // continue } catch (Exception e) { fail("setByteValues(LockbitValues) caused an unexpected Exception"); } // Test with non-existing file: returns null props.setUseFile(true); props.setFileName("foo/bar"); assertNull(props.getByteValues()); } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#clearValues()} * . */ @Test public void testClearValues() { FuseBytesProperties props = new FuseBytesProperties(fPrefs, fAVRDudeProps); props.setUseFile(false); // setByteValues() not yet implemented for // files // set some random value and clear them again for (int c = 0; c < props.getValues().length; c++) { props.setValue(c, 0xaa); assertEquals(0xaa, props.getValue(c)); } props.clearValues(); for (int c = 0; c < props.getValues().length; c++) { assertEquals(-1, props.getValue(c)); } } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#setDefaultValues()} * . */ @Test public void testSetDefaultValues() { FuseBytesProperties props = new FuseBytesProperties(fPrefs, fAVRDudeProps); props.setUseFile(false); // setByteValues() not yet implemented for // files String mcuidprops = props.getMCUId(); ByteValues testvalues = new ByteValues(FuseType.FUSE, mcuidprops); testvalues.setDefaultValues(); props.clearValues(); props.setDefaultValues(); assertArrayEquals(testvalues.getValues(), props.getValues()); assertTrue("Dirty flag not set", props.isDirty()); } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#getByteValuesFromFile()} * . * * @throws CoreException * @throws IOException */ @Test public void testGetByteValuesFromFile() throws CoreException, IOException { // Get the testfilename IFile file = TestHelper.getPluginIFile(TEST01_FILE); String filename = file.getLocation().toOSString(); FuseBytesProperties props = new FuseBytesProperties(fPrefs, fAVRDudeProps); props.clearValues(); // Clear the immediate values props.setUseFile(true); props.setFileName(filename); ByteValues testvalues = props.getByteValuesFromFile(); assertArrayEquals(TEST01_VALUES, testvalues.getValues()); assertEquals("Test Fusefile for regression tests", testvalues .getComment()); // Should get same result from getValues() assertArrayEquals(TEST01_VALUES, props.getValues()); // Test failures // Non-Existing file props.setFileName("foo/bar"); try { testvalues = props.getByteValuesFromFile(); fail("No CoreException thrown for an invalid filename"); } catch (Exception e) { assertEquals(CoreException.class, e.getClass()); } // Empty filename --> CoreException props.setFileName(""); try { testvalues = props.getByteValuesFromFile(); fail("No CoreException thrown for an empty filename"); } catch (Exception e) { assertEquals(CoreException.class, e.getClass()); } // Invalid file (missing MCU field)--> CoreException IFile invalidfile = TestHelper .getPluginIFile("/TestData/invalid.fuses"); filename = invalidfile.getLocation().toOSString(); props.setFileName(filename); try { testvalues = props.getByteValuesFromFile(); fail("No CoreException thrown for an invalid file"); } catch (Exception e) { assertEquals(CoreException.class, e.getClass()); } // Invalid file (Locks file)--> CoreException invalidfile = TestHelper.getPluginIFile("/TestData/test01.locks"); filename = invalidfile.getLocation().toOSString(); props.setFileName(filename); try { testvalues = props.getByteValuesFromFile(); fail("No CoreException thrown for an invalid file"); } catch (Exception e) { assertEquals(CoreException.class, e.getClass()); } } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#setValues(int[])} * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#getValues()}. * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#setValue(int, int)} * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#getValue(int)} */ @Test public void testSetGetValues() { FuseBytesProperties props = new FuseBytesProperties(fPrefs, fAVRDudeProps); // Set MCUid to atmega2560, which has three fuse bytes props.setMCUId("atmega2560"); int FUSES = 3; // make sure that Atmel did not change the fusecount assertEquals(FUSES, props.getByteValues().getByteCount()); // Simple tests int[] testvalues1 = new int[] { 0x11, 0x22, 0x33 }; props.setValues(testvalues1); assertArrayEquals(testvalues1, props.getValues()); int[] testvalues2 = new int[] { -1, -1, -1 }; props.setValues(testvalues2); assertArrayEquals(testvalues2, props.getValues()); // Excess Bytes are ignored int[] testvalues3 = new int[] { 0x11, 0x22, 0x33, 0x44, 0x55 }; props.setValues(testvalues3); assertEquals(FUSES, props.getValues().length); assertArrayEquals(testvalues1, props.getValues()); // Test invalid values try { props.setValues(new int[] { 256 }); fail("Invalid value 256 did not throw IllegalArgumentException"); } catch (Exception e) { assertEquals(IllegalArgumentException.class, e.getClass()); } try { props.setValues(new int[] { -2 }); fail("Invalid value -2 did not throw IllegalArgumentException"); } catch (Exception e) { assertEquals(IllegalArgumentException.class, e.getClass()); } // Test the index version for (int i = 0; i < testvalues1.length; i++) { props.setValue(i, i); } for (int i = 0; i < testvalues2.length; i++) { assertEquals(i, props.getValue(i)); } // setValue() with invalid index does nothing props.setValue(testvalues1.length, 0xdd); // getValue() with invalid index returns -1 assertEquals(-1, props.getValue(testvalues1.length)); } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#getValuesFromFile()} * . * * @throws CoreException * @throws IOException */ @Test public void testGetValuesFromFile() throws IOException, CoreException { IFile file = TestHelper.getPluginIFile(TEST01_FILE); String filename = file.getLocation().toOSString(); FuseBytesProperties props = new FuseBytesProperties(fPrefs, fAVRDudeProps); props.setFileName(filename); // Don't use file. getValues() should return the immediate values (all // -1) props.setUseFile(false); props.clearValues(); // Clear the immediate values int[] immvalues = props.getValues(); for (int v : immvalues) { assertEquals(-1, v); } // getValuesFromFile() must return the values from the file, // regardless of the useFile flag assertArrayEquals(TEST01_VALUES, props.getValuesFromFile()); // Check for non-existing file --> returns empty array props.setFileName("foo/bar"); assertEquals(0, props.getValuesFromFile().length); } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#getValuesFromImmediate()} * . * * @throws CoreException * @throws IOException */ @Test public void testGetValuesFromImmediate() throws IOException, CoreException { IFile file = TestHelper.getPluginIFile(TEST01_FILE); String filename = file.getLocation().toOSString(); FuseBytesProperties props = new FuseBytesProperties(fPrefs, fAVRDudeProps); props.setFileName(filename); // Use file. getValues() should return the file values props.setUseFile(true); props.clearValues(); // Clear the immediate values assertArrayEquals(TEST01_VALUES, props.getValues()); // But the immediate Values are still all at -1 int[] immvalues = props.getValuesFromImmediate(); for (int v : immvalues) { assertEquals(-1, v); } } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#syncFromFile()} * . * * @throws CoreException * @throws IOException */ @Test public void testSyncFromFile() throws IOException, CoreException { IFile file = TestHelper.getPluginIFile(TEST01_FILE); String filename = file.getLocation().toOSString(); FuseBytesProperties props = new FuseBytesProperties(fPrefs, fAVRDudeProps); props.setFileName(filename); // Use Immediate mode and set all values different than the file props.setUseFile(false); props.setMCUId("atmega32"); props.setDefaultValues(); // Now Sync and all properties should be the same as the file props.syncFromFile(); assertFalse(props.getUseFile()); // Still using immediate mode assertEquals("atmega2560", props.getMCUId()); assertArrayEquals(TEST01_VALUES, props.getValues()); assertArrayEquals(TEST01_VALUES, props.getValuesFromImmediate()); } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#save()}. * * @throws BackingStoreException */ @Test public void testSave() throws BackingStoreException { FuseBytesProperties props1 = new FuseBytesProperties(fPrefs, fAVRDudeProps); props1.setMCUId("atmega2560"); props1.setValues(TEST01_VALUES); props1.setWrite(true); props1.save(); assertFalse(props1.isDirty()); // changes after save() should not be stored props1.setFileName("foo/bar"); assertTrue(props1.isDirty()); // get a new Properties object. As it is derived from the same // preference store, it should have the values we just saved. FuseBytesProperties props2 = new FuseBytesProperties(fPrefs, fAVRDudeProps); assertEquals("atmega2560", props2.getMCUId()); assertArrayEquals(TEST01_VALUES, props2.getValues()); assertTrue(props2.getWrite()); assertEquals("", props2.getFileName()); assertFalse(props2.isDirty()); } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#isCompatibleWith(java.lang.String)} * . * * @throws CoreException * @throws IOException */ @Test public void testIsCompatibleWith() throws IOException, CoreException { FuseBytesProperties props = new FuseBytesProperties(fPrefs, fAVRDudeProps); props.setMCUId("atmega16"); // Compatible with itself assertTrue(props.isCompatibleWith("atmega16")); assertTrue(props.isCompatibleWith("atmega16a")); assertFalse(props.isCompatibleWith("atmega64")); assertFalse(props.isCompatibleWith("foobar")); // Check with a file IFile file = TestHelper.getPluginIFile(TEST01_FILE); String filename = file.getLocation().toOSString(); props.setFileName(filename); props.setUseFile(true); assertTrue(props.isCompatibleWith("atmega2561")); assertFalse(props.isCompatibleWith("atmega16")); } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.BaseBytesProperties#convertTo(java.lang.String, de.innot.avreclipse.core.toolinfo.fuses.ConversionResults)} * . */ @Test @Ignore public void testConvertTo() { fail("Not yet implemented"); } /** * Test method for * {@link de.innot.avreclipse.core.avrdude.FuseBytesProperties#getArguments(java.lang.String)} * . */ @Test @Ignore public void testGetArguments() { fail("Not yet implemented"); } }