From ad4e8009343f9364d764cfd6c2d91a19bab21820 Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Thu, 2 Oct 2014 22:27:40 +0100 Subject: Add robolectric for tests --- .idea/gradle.xml | 1 + .../java/org/connectbot/HostBeanTest.java | 96 ------ .../java/org/connectbot/HostListActivityTest.java | 47 --- .../java/org/connectbot/SelectionAreaTest.java | 141 -------- .../java/org/connectbot/SettingsActivityTest.java | 47 --- .../java/org/connectbot/TerminalBridgeTest.java | 105 ------ .../java/org/connectbot/mock/BeanTestCase.java | 229 ------------- .../java/org/connectbot/mock/NullOutputStream.java | 33 -- .../java/org/connectbot/mock/NullTransport.java | 138 -------- .../java/org/connectbot/util/PubkeyUtilsTest.java | 345 ------------------- robolectric-tests/.gitignore | 1 + robolectric-tests/build.gradle | 48 +++ robolectric-tests/robolectric-tests.iml | 76 +++++ .../src/test/java/org/connectbot/HostBeanTest.java | 102 ++++++ .../java/org/connectbot/SelectionAreaTest.java | 152 +++++++++ .../java/org/connectbot/mock/BeanAssertions.java | 235 +++++++++++++ .../java/org/connectbot/mock/NullOutputStream.java | 33 ++ .../java/org/connectbot/mock/NullTransport.java | 138 ++++++++ .../java/org/connectbot/util/PubkeyUtilsTest.java | 370 +++++++++++++++++++++ settings.gradle | 2 +- 20 files changed, 1157 insertions(+), 1182 deletions(-) delete mode 100644 app/src/androidTest/java/org/connectbot/HostBeanTest.java delete mode 100644 app/src/androidTest/java/org/connectbot/HostListActivityTest.java delete mode 100644 app/src/androidTest/java/org/connectbot/SelectionAreaTest.java delete mode 100644 app/src/androidTest/java/org/connectbot/SettingsActivityTest.java delete mode 100644 app/src/androidTest/java/org/connectbot/TerminalBridgeTest.java delete mode 100644 app/src/androidTest/java/org/connectbot/mock/BeanTestCase.java delete mode 100644 app/src/androidTest/java/org/connectbot/mock/NullOutputStream.java delete mode 100644 app/src/androidTest/java/org/connectbot/mock/NullTransport.java delete mode 100644 app/src/androidTest/java/org/connectbot/util/PubkeyUtilsTest.java create mode 100644 robolectric-tests/.gitignore create mode 100644 robolectric-tests/build.gradle create mode 100644 robolectric-tests/robolectric-tests.iml create mode 100644 robolectric-tests/src/test/java/org/connectbot/HostBeanTest.java create mode 100644 robolectric-tests/src/test/java/org/connectbot/SelectionAreaTest.java create mode 100644 robolectric-tests/src/test/java/org/connectbot/mock/BeanAssertions.java create mode 100644 robolectric-tests/src/test/java/org/connectbot/mock/NullOutputStream.java create mode 100644 robolectric-tests/src/test/java/org/connectbot/mock/NullTransport.java create mode 100644 robolectric-tests/src/test/java/org/connectbot/util/PubkeyUtilsTest.java diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 736c7b5..0228264 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -9,6 +9,7 @@ diff --git a/app/src/androidTest/java/org/connectbot/HostBeanTest.java b/app/src/androidTest/java/org/connectbot/HostBeanTest.java deleted file mode 100644 index a252aca..0000000 --- a/app/src/androidTest/java/org/connectbot/HostBeanTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.connectbot; - -import org.connectbot.bean.HostBean; -import org.connectbot.mock.BeanTestCase; - -import android.test.AndroidTestCase; - -/** - * @author Kenny Root - * - */ -public class HostBeanTest extends AndroidTestCase { - private static final String[] FIELDS = { "nickname", "username", - "hostname", "port" }; - - HostBean host1; - HostBean host2; - - @Override - protected void setUp() throws Exception { - super.setUp(); - - host1 = new HostBean(); - host1.setNickname("Home"); - host1.setUsername("bob"); - host1.setHostname("server.example.com"); - host1.setPort(22); - - host2 = new HostBean(); - host2.setNickname("Home"); - host2.setUsername("bob"); - host2.setHostname("server.example.com"); - host2.setPort(22); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - public void testIdEquality() { - host1.setId(1); - host2.setId(1); - assertTrue(host1.equals(host2)); - assertTrue(host1.hashCode() == host2.hashCode()); - } - - public void testIdInequality() { - host1.setId(1); - host2.setId(2); - // HostBeans shouldn't be equal when their IDs are not the same - assertFalse("HostBeans are equal when their ID is different", host1 - .equals(host2)); - assertFalse("HostBean hash codes are equal when their ID is different", - host1.hashCode() == host2.hashCode()); - } - - public void testIdEquality2() { - host1.setId(1); - host2.setId(1); - host2.setNickname("Work"); - host2.setUsername("alice"); - host2.setHostname("client.example.com"); - assertTrue( - "HostBeans are not equal when their ID is the same but other fields are different!", - host1.equals(host2)); - assertTrue( - "HostBeans hashCodes are not equal when their ID is the same but other fields are different!", - host1.hashCode() == host2.hashCode()); - } - - public void testBeanMeetsEqualsContract() { - BeanTestCase.assertMeetsEqualsContract(HostBean.class, FIELDS); - } - - public void testBeanMeetsHashCodeContract() { - BeanTestCase.assertMeetsHashCodeContract(HostBean.class, FIELDS); - } -} diff --git a/app/src/androidTest/java/org/connectbot/HostListActivityTest.java b/app/src/androidTest/java/org/connectbot/HostListActivityTest.java deleted file mode 100644 index 3962c9a..0000000 --- a/app/src/androidTest/java/org/connectbot/HostListActivityTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.connectbot; - -import android.app.Activity; -import android.test.ActivityInstrumentationTestCase2; - -/** - * This is a simple framework for a test of an Application. See - * {@link android.test.ApplicationTestCase ApplicationTestCase} for more - * information on how to write and extend Application tests. - *

- * To run this test, you can type: adb shell am instrument -w \ -e class - * org.connectbot.HostListActivityTest \ - * org.connectbot.tests/android.test.InstrumentationTestRunner - */ -public class HostListActivityTest extends ActivityInstrumentationTestCase2 { - private Activity mActivity; - - public HostListActivityTest() { - super("org.connectbot", HostListActivity.class); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - - setActivityInitialTouchMode(false); - - mActivity = getActivity(); - } -} diff --git a/app/src/androidTest/java/org/connectbot/SelectionAreaTest.java b/app/src/androidTest/java/org/connectbot/SelectionAreaTest.java deleted file mode 100644 index 93e0293..0000000 --- a/app/src/androidTest/java/org/connectbot/SelectionAreaTest.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.connectbot; - -import org.connectbot.bean.SelectionArea; - -import android.test.AndroidTestCase; - -/** - * @author Kenny Root - * - */ -public class SelectionAreaTest extends AndroidTestCase { - private static final int WIDTH = 80; - private static final int HEIGHT = 24; - - public void testCreate() { - SelectionArea sa = new SelectionArea(); - - assertTrue(sa.getLeft() == 0); - assertTrue(sa.getRight() == 0); - assertTrue(sa.getTop() == 0); - assertTrue(sa.getBottom() == 0); - assertTrue(sa.isSelectingOrigin()); - } - - public void testCheckMovement() { - SelectionArea sa = new SelectionArea(); - - sa.setBounds(WIDTH, HEIGHT); - - sa.incrementColumn(); - - // Should be (1,0) to (1,0) - assertTrue(sa.getLeft() == 1); - assertTrue(sa.getTop() == 0); - assertTrue(sa.getRight() == 1); - assertTrue(sa.getBottom() == 0); - - sa.finishSelectingOrigin(); - assertFalse(sa.isSelectingOrigin()); - - sa.incrementColumn(); - sa.incrementColumn(); - - // Should be (1,0) to (3,0) - assertTrue(sa.getLeft() == 1); - assertTrue(sa.getTop() == 0); - assertTrue(sa.getRight() == 3); - assertTrue(sa.getBottom() == 0); - } - - public void testBounds() { - SelectionArea sa = new SelectionArea(); - - sa.setBounds(WIDTH, HEIGHT); - - for (int i = 0; i <= WIDTH; i++) - sa.decrementColumn(); - assertTrue("Left bound should be 0, but instead is " + sa.getLeft(), - sa.getLeft() == 0); - - for (int i = 0; i <= HEIGHT; i++) - sa.decrementRow(); - assertTrue("Top bound should be 0, but instead is " + sa.getLeft(), - sa.getTop() == 0); - - sa.finishSelectingOrigin(); - - for (int i = 0; i <= WIDTH * 2; i++) - sa.incrementColumn(); - - assertTrue("Left bound should be 0, but instead is " + sa.getLeft(), - sa.getLeft() == 0); - assertTrue("Right bound should be " + (WIDTH - 1) + ", but instead is " + sa.getRight(), - sa.getRight() == (WIDTH - 1)); - - for (int i = 0; i <= HEIGHT * 2; i++) - sa.incrementRow(); - - assertTrue("Bottom bound should be " + (HEIGHT - 1) + ", but instead is " + sa.getBottom(), - sa.getBottom() == (HEIGHT - 1)); - assertTrue("Top bound should be 0, but instead is " + sa.getTop(), - sa.getTop() == 0); - } - - public void testSetThenMove() { - SelectionArea sa = new SelectionArea(); - - sa.setBounds(WIDTH, HEIGHT); - - int targetColumn = WIDTH / 2; - int targetRow = HEIGHT / 2; - - sa.setColumn(targetColumn); - sa.setRow(targetRow); - - sa.incrementRow(); - assertTrue("Row should be " + (targetRow + 1) + ", but instead is " + sa.getTop(), - sa.getTop() == (targetRow + 1)); - - sa.decrementColumn(); - assertTrue("Column shold be " + (targetColumn - 1) + ", but instead is " + sa.getLeft(), - sa.getLeft() == (targetColumn - 1)); - - sa.finishSelectingOrigin(); - - sa.setRow(0); - sa.setColumn(0); - - sa.incrementRow(); - sa.decrementColumn(); - - assertTrue("Top row should be 1, but instead is " + sa.getTop(), - sa.getTop() == 1); - - assertTrue("Left column shold be 0, but instead is " + sa.getLeft(), - sa.getLeft() == 0); - - assertTrue("Bottom row should be " + (targetRow + 1) + ", but instead is " + sa.getBottom(), - sa.getBottom() == (targetRow + 1)); - - assertTrue("Right column shold be " + (targetColumn - 1) + ", but instead is " + sa.getRight(), - sa.getRight() == (targetColumn - 1)); - } -} diff --git a/app/src/androidTest/java/org/connectbot/SettingsActivityTest.java b/app/src/androidTest/java/org/connectbot/SettingsActivityTest.java deleted file mode 100644 index 6b79136..0000000 --- a/app/src/androidTest/java/org/connectbot/SettingsActivityTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.connectbot; - -import android.test.ActivityInstrumentationTestCase2; - -/** - * This is a simple framework for a test of an Application. See - * {@link android.test.ApplicationTestCase ApplicationTestCase} for more - * information on how to write and extend Application tests. - *

- * To run this test, you can type: - * adb shell am instrument -w \ - * -e class org.connectbot.HostListActivityTest \ - * org.connectbot.tests/android.test.InstrumentationTestRunner - */ -public class SettingsActivityTest extends - ActivityInstrumentationTestCase2 { - - public SettingsActivityTest() { - super("org.connectbot", SettingsActivity.class); - } - - public void testOpenMenu() { - SettingsActivity a = getActivity(); - - a.openOptionsMenu(); - - a.closeOptionsMenu(); - } - -} diff --git a/app/src/androidTest/java/org/connectbot/TerminalBridgeTest.java b/app/src/androidTest/java/org/connectbot/TerminalBridgeTest.java deleted file mode 100644 index bfa5e23..0000000 --- a/app/src/androidTest/java/org/connectbot/TerminalBridgeTest.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.connectbot; - -import android.test.AndroidTestCase; - -/** - * @author Kenny Root - * - */ -public class TerminalBridgeTest extends AndroidTestCase { - public void testShiftLock() throws SecurityException, NoSuchFieldException, - IllegalArgumentException, IllegalAccessException { -// TerminalBridge bridge = new TerminalBridge(); -// AbsTransport nullTransport = new NullTransport(); -// -// // Make sure onKey will work when we call it -// Field disconnected = TerminalBridge.class -// .getDeclaredField("disconnected"); -// Field keymode = TerminalBridge.class.getDeclaredField("keymode"); -// Field transport = TerminalBridge.class.getDeclaredField("transport"); -// -// disconnected.setAccessible(true); -// keymode.setAccessible(true); -// transport.setAccessible(true); -// -// disconnected.setBoolean(bridge, false); -// keymode.set(bridge, PreferenceConstants.KEYMODE_RIGHT); -// transport.set(bridge, nullTransport); -// -// // Begin tests -// assertTrue("Meta state is " + bridge.getMetaState() -// + " when it should be 0", bridge.getMetaState() == 0); -// -// KeyEvent shiftDown = new KeyEvent(KeyEvent.ACTION_DOWN, -// KeyEvent.KEYCODE_SHIFT_LEFT); -// bridge.onKey(null, shiftDown.getKeyCode(), shiftDown); -// -// assertTrue("Shift test: after shift press, meta state is " -// + bridge.getMetaState() + " when it should be " -// + TerminalBridge.META_SHIFT_ON, -// bridge.getMetaState() == TerminalBridge.META_SHIFT_ON); -// -// KeyEvent shiftUp = KeyEvent.changeAction(shiftDown, KeyEvent.ACTION_UP); -// bridge.onKey(null, shiftUp.getKeyCode(), shiftUp); -// -// assertTrue("Shift test: after shift release, meta state is " -// + bridge.getMetaState() + " when it should be " -// + TerminalBridge.META_SHIFT_ON, -// bridge.getMetaState() == TerminalBridge.META_SHIFT_ON); -// -// KeyEvent letterAdown = new KeyEvent(KeyEvent.ACTION_DOWN, -// KeyEvent.KEYCODE_A); -// KeyEvent letterAup = KeyEvent.changeAction(letterAdown, -// KeyEvent.ACTION_UP); -// -// bridge.onKey(null, letterAdown.getKeyCode(), letterAdown); -// bridge.onKey(null, letterAup.getKeyCode(), letterAup); -// -// assertTrue("Shift test: after letter press and release, meta state is " -// + bridge.getMetaState() + " when it should be 0", bridge -// .getMetaState() == 0); -// -// bridge.onKey(null, shiftDown.getKeyCode(), shiftDown); -// bridge.onKey(null, shiftUp.getKeyCode(), shiftUp); -// bridge.onKey(null, shiftDown.getKeyCode(), shiftDown); -// bridge.onKey(null, shiftUp.getKeyCode(), shiftUp); -// -// assertTrue("Shift lock test: after two shift presses, meta state is " -// + bridge.getMetaState() + " when it should be " -// + TerminalBridge.META_SHIFT_LOCK, -// bridge.getMetaState() == TerminalBridge.META_SHIFT_LOCK); -// -// bridge.onKey(null, letterAdown.getKeyCode(), letterAdown); -// -// assertTrue( -// "Shift lock test: after letter press, meta state is " -// + bridge.getMetaState() + " when it should be " -// + TerminalBridge.META_SHIFT_LOCK, -// bridge.getMetaState() == TerminalBridge.META_SHIFT_LOCK); -// -// bridge.onKey(null, letterAup.getKeyCode(), letterAup); -// -// assertTrue( -// "Shift lock test: after letter press and release, meta state is " -// + bridge.getMetaState() + " when it should be " -// + TerminalBridge.META_SHIFT_LOCK, -// bridge.getMetaState() == TerminalBridge.META_SHIFT_LOCK); - } -} diff --git a/app/src/androidTest/java/org/connectbot/mock/BeanTestCase.java b/app/src/androidTest/java/org/connectbot/mock/BeanTestCase.java deleted file mode 100644 index 5d13d9f..0000000 --- a/app/src/androidTest/java/org/connectbot/mock/BeanTestCase.java +++ /dev/null @@ -1,229 +0,0 @@ -/** - * Originally from http://www.cornetdesign.com/files/BeanTestCase.java.txt - */ -package org.connectbot.mock; - -import junit.framework.TestCase; - -import java.lang.reflect.Field; - -public class BeanTestCase extends TestCase { - - private static final String TEST_STRING_VAL1 = "Some Value"; - private static final String TEST_STRING_VAL2 = "Some Other Value"; - - public static void assertMeetsEqualsContract(Class classUnderTest, - String[] fieldNames) { - Object o1; - Object o2; - try { - // Get Instances - o1 = classUnderTest.newInstance(); - o2 = classUnderTest.newInstance(); - - assertTrue( - "Instances with default constructor not equal (o1.equals(o2))", - o1.equals(o2)); - assertTrue( - "Instances with default constructor not equal (o2.equals(o1))", - o2.equals(o1)); - - Field[] fields = getFieldsByNameOrAll(classUnderTest, fieldNames); - - for (int i = 0; i < fields.length; i++) { - - // Reset the instances - o1 = classUnderTest.newInstance(); - o2 = classUnderTest.newInstance(); - - Field field = fields[i]; - field.setAccessible(true); - if (field.getType() == String.class) { - field.set(o1, TEST_STRING_VAL1); - } else if (field.getType() == boolean.class) { - field.setBoolean(o1, true); - } else if (field.getType() == short.class) { - field.setShort(o1, (short) 1); - } else if (field.getType() == long.class) { - field.setLong(o1, (long) 1); - } else if (field.getType() == float.class) { - field.setFloat(o1, (float) 1); - } else if (field.getType() == int.class) { - field.setInt(o1, 1); - } else if (field.getType() == byte.class) { - field.setByte(o1, (byte) 1); - } else if (field.getType() == char.class) { - field.setChar(o1, (char) 1); - } else if (field.getType() == double.class) { - field.setDouble(o1, (double) 1); - } else if (field.getType().isEnum()) { - field.set(o1, field.getType().getEnumConstants()[0]); - } else if (Object.class.isAssignableFrom(field.getType())) { - field.set(o1, field.getType().newInstance()); - } else { - fail("Don't know how to set a " + field.getType().getName()); - } - - assertFalse("Instances with o1 having " + field.getName() - + " set and o2 having it not set are equal", o1 - .equals(o2)); - - field.set(o2, field.get(o1)); - - assertTrue( - "After setting o2 with the value of the object in o1, the two objects in the field are not equal", - field.get(o1).equals(field.get(o2))); - - assertTrue( - "Instances with o1 having " - + field.getName() - + " set and o2 having it set to the same object of type " - + field.get(o2).getClass().getName() - + " are not equal", o1.equals(o2)); - - if (field.getType() == String.class) { - field.set(o2, TEST_STRING_VAL2); - } else if (field.getType() == boolean.class) { - field.setBoolean(o2, false); - } else if (field.getType() == short.class) { - field.setShort(o2, (short) 0); - } else if (field.getType() == long.class) { - field.setLong(o2, (long) 0); - } else if (field.getType() == float.class) { - field.setFloat(o2, (float) 0); - } else if (field.getType() == int.class) { - field.setInt(o2, 0); - } else if (field.getType() == byte.class) { - field.setByte(o2, (byte) 0); - } else if (field.getType() == char.class) { - field.setChar(o2, (char) 0); - } else if (field.getType() == double.class) { - field.setDouble(o2, (double) 1); - } else if (field.getType().isEnum()) { - field.set(o2, field.getType().getEnumConstants()[1]); - } else if (Object.class.isAssignableFrom(field.getType())) { - field.set(o2, field.getType().newInstance()); - } else { - fail("Don't know how to set a " + field.getType().getName()); - } - if (field.get(o1).equals(field.get(o2))) { - // Even though we have different instances, they are equal. - // Let's walk one of them - // to see if we can find a field to set - Field[] paramFields = field.get(o1).getClass() - .getDeclaredFields(); - for (int j = 0; j < paramFields.length; j++) { - paramFields[j].setAccessible(true); - if (paramFields[j].getType() == String.class) { - paramFields[j].set(field.get(o1), TEST_STRING_VAL1); - } - } - } - - assertFalse( - "After setting o2 with a different object than what is in o1, the two objects in the field are equal. " - + "This is after an attempt to walk the fields to make them different", - field.get(o1).equals(field.get(o2))); - assertFalse( - "Instances with o1 having " - + field.getName() - + " set and o2 having it set to a different object are equal", - o1.equals(o2)); - } - - } catch (InstantiationException e) { - e.printStackTrace(); - throw new AssertionError( - "Unable to construct an instance of the class under test"); - } catch (IllegalAccessException e) { - e.printStackTrace(); - throw new AssertionError( - "Unable to construct an instance of the class under test"); - } catch (SecurityException e) { - e.printStackTrace(); - throw new AssertionError( - "Unable to read the field from the class under test"); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - throw new AssertionError( - "Unable to find field in the class under test"); - } - } - - /** - * @param classUnderTest - * @param fieldNames - * @return - * @throws NoSuchFieldException - */ - private static Field[] getFieldsByNameOrAll(Class classUnderTest, - String[] fieldNames) throws NoSuchFieldException { - Field fields[]; - if (fieldNames == null) { - fields = classUnderTest.getDeclaredFields(); - } else { - fields = new Field[fieldNames.length]; - for (int i = 0; i < fieldNames.length; i++) - fields[i] = classUnderTest.getDeclaredField(fieldNames[i]); - } - return fields; - } - - public static void assertMeetsHashCodeContract(Class classUnderTest, - String[] fieldNames) { - try { - Field[] fields = getFieldsByNameOrAll(classUnderTest, fieldNames); - - for (int i = 0; i < fields.length; i++) { - Object o1 = classUnderTest.newInstance(); - int initialHashCode = o1.hashCode(); - - Field field = fields[i]; - field.setAccessible(true); - if (field.getType() == String.class) { - field.set(o1, TEST_STRING_VAL1); - } else if (field.getType() == boolean.class) { - field.setBoolean(o1, true); - } else if (field.getType() == short.class) { - field.setShort(o1, (short) 1); - } else if (field.getType() == long.class) { - field.setLong(o1, (long) 1); - } else if (field.getType() == float.class) { - field.setFloat(o1, (float) 1); - } else if (field.getType() == int.class) { - field.setInt(o1, 1); - } else if (field.getType() == byte.class) { - field.setByte(o1, (byte) 1); - } else if (field.getType() == char.class) { - field.setChar(o1, (char) 1); - } else if (field.getType() == double.class) { - field.setDouble(o1, (double) 1); - } else if (field.getType().isEnum()) { - field.set(o1, field.getType().getEnumConstants()[0]); - } else if (Object.class.isAssignableFrom(field.getType())) { - field.set(o1, field.getType().newInstance()); - } else { - fail("Don't know how to set a " + field.getType().getName()); - } - int updatedHashCode = o1.hashCode(); - assertFalse( - "The field " - + field.getName() - + " was not taken into account for the hashCode contract ", - initialHashCode == updatedHashCode); - } - } catch (InstantiationException e) { - e.printStackTrace(); - throw new AssertionError( - "Unable to construct an instance of the class under test"); - } catch (IllegalAccessException e) { - e.printStackTrace(); - throw new AssertionError( - "Unable to construct an instance of the class under test"); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - throw new AssertionError( - "Unable to find field in the class under test"); - } - } -} diff --git a/app/src/androidTest/java/org/connectbot/mock/NullOutputStream.java b/app/src/androidTest/java/org/connectbot/mock/NullOutputStream.java deleted file mode 100644 index 79b8e72..0000000 --- a/app/src/androidTest/java/org/connectbot/mock/NullOutputStream.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.connectbot.mock; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * @author Kenny Root - * - */ -public class NullOutputStream extends OutputStream { - @Override - public void write(int arg0) throws IOException { - // do nothing - } - -} diff --git a/app/src/androidTest/java/org/connectbot/mock/NullTransport.java b/app/src/androidTest/java/org/connectbot/mock/NullTransport.java deleted file mode 100644 index d841e6a..0000000 --- a/app/src/androidTest/java/org/connectbot/mock/NullTransport.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.connectbot.mock; - -import java.io.IOException; -import java.util.Map; - -import org.connectbot.bean.HostBean; -import org.connectbot.service.TerminalBridge; -import org.connectbot.service.TerminalManager; -import org.connectbot.transport.AbsTransport; - -import android.net.Uri; - -/** - * @author kenny - * - */ -public class NullTransport extends AbsTransport { - - /** - * - */ - public NullTransport() { - // TODO Auto-generated constructor stub - } - - /** - * @param host - * @param bridge - * @param manager - */ - public NullTransport(HostBean host, TerminalBridge bridge, - TerminalManager manager) { - super(host, bridge, manager); - // TODO Auto-generated constructor stub - } - - @Override - public void close() { - // TODO Auto-generated method stub - - } - - @Override - public void connect() { - // TODO Auto-generated method stub - - } - - @Override - public HostBean createHost(Uri uri) { - // TODO Auto-generated method stub - return null; - } - - @Override - public void flush() throws IOException { - // TODO Auto-generated method stub - - } - - @Override - public String getDefaultNickname(String username, String hostname, int port) { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getDefaultPort() { - // TODO Auto-generated method stub - return 0; - } - - @Override - public void getSelectionArgs(Uri uri, Map selection) { - // TODO Auto-generated method stub - - } - - @Override - public boolean isConnected() { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isSessionOpen() { - // TODO Auto-generated method stub - return false; - } - - @Override - public int read(byte[] buffer, int offset, int length) throws IOException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public void setDimensions(int columns, int rows, int width, int height) { - // TODO Auto-generated method stub - - } - - @Override - public void write(byte[] buffer) throws IOException { - // TODO Auto-generated method stub - - } - - @Override - public void write(int c) throws IOException { - // TODO Auto-generated method stub - - } - - @Override - public boolean usesNetwork() { - // TODO Auto-generated method stub - return false; - } - -} diff --git a/app/src/androidTest/java/org/connectbot/util/PubkeyUtilsTest.java b/app/src/androidTest/java/org/connectbot/util/PubkeyUtilsTest.java deleted file mode 100644 index 1eb1ee6..0000000 --- a/app/src/androidTest/java/org/connectbot/util/PubkeyUtilsTest.java +++ /dev/null @@ -1,345 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.connectbot.util; - -import java.math.BigInteger; -import java.security.KeyPair; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.interfaces.DSAParams; -import java.security.interfaces.DSAPublicKey; -import java.security.interfaces.ECPublicKey; -import java.security.interfaces.RSAPublicKey; -import java.util.Arrays; - -import android.test.AndroidTestCase; - -/** - * @author Kenny Root - * - */ -public class PubkeyUtilsTest extends AndroidTestCase { - public void testEncodeHex_Null_Failure() throws Exception { - try { - PubkeyUtils.encodeHex(null); - fail("Should throw null pointer exception when argument is null"); - } catch (NullPointerException e) { - // success - } - } - public void testEncodeHex_Success() throws Exception { - byte[] input = {(byte) 0xFF, 0x00, (byte) 0xA5, 0x5A, 0x12, 0x23}; - String expected = "ff00a55a1223"; - - assertEquals("Encoded hex should match expected", - PubkeyUtils.encodeHex(input), expected); - } - - public void testSha256_Empty_Success() throws Exception { - byte[] empty_hashed = new byte[] { - (byte) 0xe3, (byte) 0xb0, (byte) 0xc4, (byte) 0x42, - (byte) 0x98, (byte) 0xfc, (byte) 0x1c, (byte) 0x14, - (byte) 0x9a, (byte) 0xfb, (byte) 0xf4, (byte) 0xc8, - (byte) 0x99, (byte) 0x6f, (byte) 0xb9, (byte) 0x24, - (byte) 0x27, (byte) 0xae, (byte) 0x41, (byte) 0xe4, - (byte) 0x64, (byte) 0x9b, (byte) 0x93, (byte) 0x4c, - (byte) 0xa4, (byte) 0x95, (byte) 0x99, (byte) 0x1b, - (byte) 0x78, (byte) 0x52, (byte) 0xb8, (byte) 0x55, - }; - - final byte[] empty = new byte[] {}; - - assertTrue("Empty string should be equal to known test vector", - Arrays.equals(empty_hashed, PubkeyUtils.sha256(empty))); - } - - /* openssl ecparam -genkey -name prime256v1 -noout | openssl pkcs8 -topk8 -outform d -nocrypt | recode ../x1 | sed 's/0x/(byte) 0x/g' */ - private static final byte[] EC_KEY_PKCS8 = new byte[] { (byte) 0x30, (byte) 0x81, (byte) 0x87, - (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x30, (byte) 0x13, (byte) 0x06, - (byte) 0x07, (byte) 0x2A, (byte) 0x86, (byte) 0x48, (byte) 0xCE, (byte) 0x3D, - (byte) 0x02, (byte) 0x01, (byte) 0x06, (byte) 0x08, (byte) 0x2A, (byte) 0x86, - (byte) 0x48, (byte) 0xCE, (byte) 0x3D, (byte) 0x03, (byte) 0x01, (byte) 0x07, - (byte) 0x04, (byte) 0x6D, (byte) 0x30, (byte) 0x6B, (byte) 0x02, (byte) 0x01, - (byte) 0x01, (byte) 0x04, (byte) 0x20, (byte) 0xC7, (byte) 0x6B, (byte) 0xA5, - (byte) 0xB6, (byte) 0xB7, (byte) 0x4E, (byte) 0x0B, (byte) 0x70, (byte) 0x2E, - (byte) 0xA0, (byte) 0x5D, (byte) 0x8D, (byte) 0x0A, (byte) 0xF5, (byte) 0x43, - (byte) 0xEF, (byte) 0x54, (byte) 0x2F, (byte) 0x05, (byte) 0x5B, (byte) 0x66, - (byte) 0x50, (byte) 0xC5, (byte) 0xB4, (byte) 0xA8, (byte) 0x60, (byte) 0x16, - (byte) 0x8E, (byte) 0x8D, (byte) 0xCD, (byte) 0x11, (byte) 0xFA, (byte) 0xA1, - (byte) 0x44, (byte) 0x03, (byte) 0x42, (byte) 0x00, (byte) 0x04, (byte) 0x12, - (byte) 0xE2, (byte) 0x70, (byte) 0x30, (byte) 0x87, (byte) 0x2F, (byte) 0xDE, - (byte) 0x10, (byte) 0xD9, (byte) 0xC9, (byte) 0x83, (byte) 0xC7, (byte) 0x8D, - (byte) 0xC9, (byte) 0x9B, (byte) 0x94, (byte) 0x24, (byte) 0x50, (byte) 0x5D, - (byte) 0xEC, (byte) 0xF1, (byte) 0x4F, (byte) 0x52, (byte) 0xC6, (byte) 0xE7, - (byte) 0xA3, (byte) 0xD7, (byte) 0xF4, (byte) 0x7C, (byte) 0x09, (byte) 0xA1, - (byte) 0x10, (byte) 0x11, (byte) 0xE4, (byte) 0x9E, (byte) 0x90, (byte) 0xAF, - (byte) 0xF9, (byte) 0x4A, (byte) 0x74, (byte) 0x09, (byte) 0x93, (byte) 0xC7, - (byte) 0x9A, (byte) 0xB3, (byte) 0xE2, (byte) 0xD8, (byte) 0x61, (byte) 0x5F, - (byte) 0x86, (byte) 0x14, (byte) 0x91, (byte) 0x7A, (byte) 0x23, (byte) 0x81, - (byte) 0x42, (byte) 0xA9, (byte) 0x02, (byte) 0x1D, (byte) 0x33, (byte) 0x19, - (byte) 0xC0, (byte) 0x4B, (byte) 0xCE - }; - - private static final BigInteger EC_KEY_priv = new BigInteger("c76ba5b6b74e0b702ea05d8d0af543ef542f055b6650c5b4a860168e8dcd11fa", 16); - private static final BigInteger EC_KEY_pub_x = new BigInteger("12e27030872fde10d9c983c78dc99b9424505decf14f52c6e7a3d7f47c09a110", 16); - private static final BigInteger EC_KEY_pub_y = new BigInteger("11e49e90aff94a740993c79ab3e2d8615f8614917a238142a9021d3319c04bce", 16); - - /* openssl genrsa 512 | openssl pkcs8 -topk8 -outform d -nocrypt | recode ../x1 | sed 's/0x/(byte) 0x/g' */ - private static final byte[] RSA_KEY_PKCS8 = new byte[] { (byte) 0x30, (byte) 0x82, (byte) 0x01, - (byte) 0x55, (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x30, (byte) 0x0D, - (byte) 0x06, (byte) 0x09, (byte) 0x2A, (byte) 0x86, (byte) 0x48, (byte) 0x86, - (byte) 0xF7, (byte) 0x0D, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, - (byte) 0x00, (byte) 0x04, (byte) 0x82, (byte) 0x01, (byte) 0x3F, (byte) 0x30, - (byte) 0x82, (byte) 0x01, (byte) 0x3B, (byte) 0x02, (byte) 0x01, (byte) 0x00, - (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xC6, (byte) 0x00, (byte) 0x79, - (byte) 0x0C, (byte) 0x46, (byte) 0xF9, (byte) 0x03, (byte) 0x15, (byte) 0xBA, - (byte) 0x35, (byte) 0x63, (byte) 0x6C, (byte) 0x97, (byte) 0x3A, (byte) 0x6C, - (byte) 0xC8, (byte) 0x15, (byte) 0x32, (byte) 0x2A, (byte) 0x62, (byte) 0x72, - (byte) 0xBD, (byte) 0x05, (byte) 0x01, (byte) 0xCF, (byte) 0xE6, (byte) 0x49, - (byte) 0xEC, (byte) 0xC9, (byte) 0x8A, (byte) 0x3A, (byte) 0x4E, (byte) 0xB1, - (byte) 0xF2, (byte) 0x3E, (byte) 0x86, (byte) 0x3C, (byte) 0x64, (byte) 0x4A, - (byte) 0x0A, (byte) 0x29, (byte) 0xD6, (byte) 0xFA, (byte) 0xF9, (byte) 0xAC, - (byte) 0xD8, (byte) 0x7B, (byte) 0x9F, (byte) 0x2A, (byte) 0x6B, (byte) 0x13, - (byte) 0x06, (byte) 0x06, (byte) 0xEB, (byte) 0x83, (byte) 0x1B, (byte) 0xB8, - (byte) 0x97, (byte) 0xA3, (byte) 0x91, (byte) 0x95, (byte) 0x60, (byte) 0x15, - (byte) 0xE5, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x01, - (byte) 0x02, (byte) 0x40, (byte) 0x0F, (byte) 0xDA, (byte) 0x33, (byte) 0xD6, - (byte) 0xCE, (byte) 0xCB, (byte) 0xDA, (byte) 0xFA, (byte) 0x5F, (byte) 0x59, - (byte) 0x2C, (byte) 0xE7, (byte) 0xA1, (byte) 0xC7, (byte) 0xF4, (byte) 0xB3, - (byte) 0xA4, (byte) 0x36, (byte) 0xCA, (byte) 0xFB, (byte) 0xEC, (byte) 0xD1, - (byte) 0xC3, (byte) 0x57, (byte) 0xDC, (byte) 0xCC, (byte) 0x44, (byte) 0x38, - (byte) 0xE7, (byte) 0xFD, (byte) 0xE0, (byte) 0x23, (byte) 0x0E, (byte) 0x97, - (byte) 0x87, (byte) 0x55, (byte) 0x80, (byte) 0x2B, (byte) 0xF2, (byte) 0xF4, - (byte) 0x1C, (byte) 0x03, (byte) 0xD2, (byte) 0x3E, (byte) 0x09, (byte) 0x72, - (byte) 0x49, (byte) 0xD8, (byte) 0x9C, (byte) 0xAC, (byte) 0xDA, (byte) 0x65, - (byte) 0x68, (byte) 0x4D, (byte) 0x38, (byte) 0x19, (byte) 0xD8, (byte) 0xB1, - (byte) 0x5B, (byte) 0xB7, (byte) 0x38, (byte) 0xC8, (byte) 0x94, (byte) 0xB5, - (byte) 0x02, (byte) 0x21, (byte) 0x00, (byte) 0xF7, (byte) 0x8E, (byte) 0x20, - (byte) 0xDC, (byte) 0x26, (byte) 0x12, (byte) 0x3A, (byte) 0x85, (byte) 0x91, - (byte) 0x5F, (byte) 0x45, (byte) 0xA6, (byte) 0x95, (byte) 0xE5, (byte) 0x22, - (byte) 0xD0, (byte) 0xC4, (byte) 0xD7, (byte) 0x6A, (byte) 0xF1, (byte) 0x43, - (byte) 0x38, (byte) 0x88, (byte) 0x20, (byte) 0x7D, (byte) 0x80, (byte) 0x73, - (byte) 0x7B, (byte) 0xDC, (byte) 0x73, (byte) 0x51, (byte) 0x3B, (byte) 0x02, - (byte) 0x21, (byte) 0x00, (byte) 0xCC, (byte) 0xC1, (byte) 0x99, (byte) 0xC8, - (byte) 0xC0, (byte) 0x54, (byte) 0xBC, (byte) 0xE9, (byte) 0xFB, (byte) 0x77, - (byte) 0x28, (byte) 0xB8, (byte) 0x26, (byte) 0x02, (byte) 0xC0, (byte) 0x0C, - (byte) 0xDE, (byte) 0xFD, (byte) 0xEA, (byte) 0xD0, (byte) 0x15, (byte) 0x4B, - (byte) 0x3B, (byte) 0xD1, (byte) 0xDD, (byte) 0xFD, (byte) 0x5B, (byte) 0xAC, - (byte) 0xB3, (byte) 0xCF, (byte) 0xC3, (byte) 0x5F, (byte) 0x02, (byte) 0x21, - (byte) 0x00, (byte) 0xCD, (byte) 0x8C, (byte) 0x25, (byte) 0x9C, (byte) 0xA5, - (byte) 0xBF, (byte) 0xDC, (byte) 0xF7, (byte) 0xAA, (byte) 0x8D, (byte) 0x00, - (byte) 0xB8, (byte) 0x21, (byte) 0x1D, (byte) 0xF0, (byte) 0x9A, (byte) 0x87, - (byte) 0xD6, (byte) 0x95, (byte) 0xE5, (byte) 0x5D, (byte) 0x7B, (byte) 0x43, - (byte) 0x0C, (byte) 0x37, (byte) 0x28, (byte) 0xC0, (byte) 0xBA, (byte) 0xC7, - (byte) 0x80, (byte) 0xB8, (byte) 0xA1, (byte) 0x02, (byte) 0x21, (byte) 0x00, - (byte) 0xCC, (byte) 0x26, (byte) 0x6F, (byte) 0xAD, (byte) 0x60, (byte) 0x4E, - (byte) 0x5C, (byte) 0xB9, (byte) 0x32, (byte) 0x57, (byte) 0x61, (byte) 0x8B, - (byte) 0x11, (byte) 0xA3, (byte) 0x06, (byte) 0x57, (byte) 0x0E, (byte) 0xF2, - (byte) 0xBE, (byte) 0x6F, (byte) 0x4F, (byte) 0xFB, (byte) 0xDE, (byte) 0x1D, - (byte) 0xE6, (byte) 0xA7, (byte) 0x19, (byte) 0x03, (byte) 0x7D, (byte) 0x98, - (byte) 0xB6, (byte) 0x23, (byte) 0x02, (byte) 0x20, (byte) 0x24, (byte) 0x80, - (byte) 0x94, (byte) 0xFF, (byte) 0xDD, (byte) 0x7A, (byte) 0x22, (byte) 0x7D, - (byte) 0xC4, (byte) 0x5A, (byte) 0xFD, (byte) 0x84, (byte) 0xC1, (byte) 0xAD, - (byte) 0x8A, (byte) 0x13, (byte) 0x2A, (byte) 0xF9, (byte) 0x5D, (byte) 0xFF, - (byte) 0x0B, (byte) 0x2E, (byte) 0x0F, (byte) 0x61, (byte) 0x42, (byte) 0x88, - (byte) 0x57, (byte) 0xCF, (byte) 0xC1, (byte) 0x71, (byte) 0xC9, (byte) 0xB9 - }; - - private static final BigInteger RSA_KEY_N = new BigInteger("C600790C46F90315BA35636C973A6CC815322A6272BD0501CFE649ECC98A3A4EB1F23E863C644A0A29D6FAF9ACD87B9F2A6B130606EB831BB897A391956015E5", 16); - private static final BigInteger RSA_KEY_E = new BigInteger("010001", 16); - - /* - openssl dsaparam -genkey -text -out dsakey.pem 1024 - openssl dsa -in dsakey.pem -text -noout - openssl pkcs8 -topk8 -in dsakey.pem -outform d -nocrypt | recode ../x1 | sed 's/0x/(byte) 0x/g' - */ - private static final byte[] DSA_KEY_PKCS8 = new byte[] { - (byte) 0x30, (byte) 0x82, (byte) 0x01, (byte) 0x4A, (byte) 0x02, (byte) 0x01, - (byte) 0x00, (byte) 0x30, (byte) 0x82, (byte) 0x01, (byte) 0x2B, (byte) 0x06, - (byte) 0x07, (byte) 0x2A, (byte) 0x86, (byte) 0x48, (byte) 0xCE, (byte) 0x38, - (byte) 0x04, (byte) 0x01, (byte) 0x30, (byte) 0x82, (byte) 0x01, (byte) 0x1E, - (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0xD2, (byte) 0x18, - (byte) 0xDB, (byte) 0x94, (byte) 0x7C, (byte) 0xD6, (byte) 0x2E, (byte) 0xE2, - (byte) 0x07, (byte) 0x38, (byte) 0x42, (byte) 0xC4, (byte) 0x16, (byte) 0x24, - (byte) 0x94, (byte) 0x2F, (byte) 0xC1, (byte) 0x0F, (byte) 0x92, (byte) 0x0A, - (byte) 0x44, (byte) 0x44, (byte) 0x99, (byte) 0xFC, (byte) 0x01, (byte) 0x1B, - (byte) 0xF8, (byte) 0xF3, (byte) 0x82, (byte) 0x57, (byte) 0x01, (byte) 0x8D, - (byte) 0xE6, (byte) 0x22, (byte) 0x70, (byte) 0xA0, (byte) 0xD6, (byte) 0x05, - (byte) 0x0F, (byte) 0xF1, (byte) 0xD0, (byte) 0xF4, (byte) 0x0B, (byte) 0xA2, - (byte) 0xE4, (byte) 0x1E, (byte) 0xD3, (byte) 0x44, (byte) 0x79, (byte) 0x74, - (byte) 0x4C, (byte) 0xC1, (byte) 0xA7, (byte) 0xA5, (byte) 0x84, (byte) 0xD8, - (byte) 0xB9, (byte) 0xDF, (byte) 0xA3, (byte) 0x85, (byte) 0xFA, (byte) 0xF2, - (byte) 0xFD, (byte) 0x44, (byte) 0x0B, (byte) 0xB1, (byte) 0xA5, (byte) 0x82, - (byte) 0x8D, (byte) 0x06, (byte) 0x92, (byte) 0xCA, (byte) 0xB4, (byte) 0xFB, - (byte) 0xDF, (byte) 0xC2, (byte) 0xFD, (byte) 0xA7, (byte) 0xCB, (byte) 0x6F, - (byte) 0x03, (byte) 0xB9, (byte) 0xEF, (byte) 0xFD, (byte) 0x7F, (byte) 0xBC, - (byte) 0xB3, (byte) 0x1D, (byte) 0xA4, (byte) 0xE8, (byte) 0x7D, (byte) 0xA2, - (byte) 0xCF, (byte) 0x62, (byte) 0x35, (byte) 0x06, (byte) 0xC8, (byte) 0xFE, - (byte) 0xE6, (byte) 0xE7, (byte) 0x6E, (byte) 0xAE, (byte) 0x22, (byte) 0xE7, - (byte) 0x82, (byte) 0x38, (byte) 0x54, (byte) 0x82, (byte) 0xCD, (byte) 0xEA, - (byte) 0xD8, (byte) 0x69, (byte) 0xBB, (byte) 0x1C, (byte) 0xD3, (byte) 0x70, - (byte) 0x32, (byte) 0xB1, (byte) 0xFB, (byte) 0x07, (byte) 0x01, (byte) 0x66, - (byte) 0xCC, (byte) 0x24, (byte) 0xD6, (byte) 0x50, (byte) 0x46, (byte) 0x9B, - (byte) 0x02, (byte) 0x15, (byte) 0x00, (byte) 0xD6, (byte) 0xE6, (byte) 0x7E, - (byte) 0x1A, (byte) 0xE5, (byte) 0xCA, (byte) 0x1D, (byte) 0xB6, (byte) 0xAF, - (byte) 0x4E, (byte) 0xD9, (byte) 0x18, (byte) 0xE8, (byte) 0x87, (byte) 0xB1, - (byte) 0xBC, (byte) 0x93, (byte) 0xE1, (byte) 0x80, (byte) 0xF5, (byte) 0x02, - (byte) 0x81, (byte) 0x80, (byte) 0x19, (byte) 0x20, (byte) 0xCC, (byte) 0x18, - (byte) 0xF6, (byte) 0x8F, (byte) 0x73, (byte) 0xFA, (byte) 0x9F, (byte) 0x50, - (byte) 0xC8, (byte) 0x92, (byte) 0xBE, (byte) 0x07, (byte) 0x7C, (byte) 0x34, - (byte) 0xD8, (byte) 0x6F, (byte) 0x63, (byte) 0xC9, (byte) 0x35, (byte) 0x48, - (byte) 0x79, (byte) 0x79, (byte) 0x26, (byte) 0xEF, (byte) 0x1E, (byte) 0x99, - (byte) 0x54, (byte) 0xD7, (byte) 0x30, (byte) 0x2C, (byte) 0x68, (byte) 0xBC, - (byte) 0xFF, (byte) 0xF2, (byte) 0x4C, (byte) 0x6A, (byte) 0xD3, (byte) 0x2D, - (byte) 0x1C, (byte) 0x7A, (byte) 0x06, (byte) 0x11, (byte) 0x72, (byte) 0x92, - (byte) 0x9C, (byte) 0xAA, (byte) 0x95, (byte) 0x0E, (byte) 0x44, (byte) 0x2C, - (byte) 0x5F, (byte) 0x19, (byte) 0x25, (byte) 0xB4, (byte) 0xBF, (byte) 0x21, - (byte) 0x8F, (byte) 0xB7, (byte) 0x7E, (byte) 0x4B, (byte) 0x64, (byte) 0x83, - (byte) 0x59, (byte) 0x20, (byte) 0x20, (byte) 0x36, (byte) 0x84, (byte) 0xA4, - (byte) 0x1D, (byte) 0xB5, (byte) 0xCA, (byte) 0x7F, (byte) 0x10, (byte) 0x4E, - (byte) 0x27, (byte) 0x21, (byte) 0x8E, (byte) 0x2C, (byte) 0xA5, (byte) 0xF8, - (byte) 0xAC, (byte) 0xBD, (byte) 0xF5, (byte) 0xB5, (byte) 0xBA, (byte) 0xEB, - (byte) 0x86, (byte) 0x6F, (byte) 0x7F, (byte) 0xB1, (byte) 0xE0, (byte) 0x90, - (byte) 0x35, (byte) 0xCA, (byte) 0xA8, (byte) 0x64, (byte) 0x6E, (byte) 0x06, - (byte) 0x3D, (byte) 0x02, (byte) 0x3D, (byte) 0x95, (byte) 0x57, (byte) 0xB3, - (byte) 0x8A, (byte) 0xE2, (byte) 0x0B, (byte) 0xD3, (byte) 0x9E, (byte) 0x1C, - (byte) 0x13, (byte) 0xDE, (byte) 0x48, (byte) 0xA3, (byte) 0xC2, (byte) 0x11, - (byte) 0xDA, (byte) 0x75, (byte) 0x09, (byte) 0xF6, (byte) 0x92, (byte) 0x0F, - (byte) 0x0F, (byte) 0xA6, (byte) 0xF3, (byte) 0x3E, (byte) 0x04, (byte) 0x16, - (byte) 0x02, (byte) 0x14, (byte) 0x29, (byte) 0x50, (byte) 0xE4, (byte) 0x77, - (byte) 0x4F, (byte) 0xB2, (byte) 0xFF, (byte) 0xFB, (byte) 0x5D, (byte) 0x33, - (byte) 0xC9, (byte) 0x37, (byte) 0xF0, (byte) 0xB5, (byte) 0x8F, (byte) 0xFB, - (byte) 0x0D, (byte) 0x45, (byte) 0xC2, (byte) 0x00 - }; - - private static final BigInteger DSA_KEY_P = new BigInteger("00d218db947cd62ee2073842c41624942fc10f920a444499fc011bf8f38257018de62270a0d6050ff1d0f40ba2e41ed34479744cc1a7a584d8b9dfa385faf2fd440bb1a5828d0692cab4fbdfc2fda7cb6f03b9effd7fbcb31da4e87da2cf623506c8fee6e76eae22e782385482cdead869bb1cd37032b1fb070166cc24d650469b", 16); - private static final BigInteger DSA_KEY_Q = new BigInteger("00d6e67e1ae5ca1db6af4ed918e887b1bc93e180f5", 16); - private static final BigInteger DSA_KEY_G = new BigInteger("1920cc18f68f73fa9f50c892be077c34d86f63c93548797926ef1e9954d7302c68bcfff24c6ad32d1c7a061172929caa950e442c5f1925b4bf218fb77e4b64835920203684a41db5ca7f104e27218e2ca5f8acbdf5b5baeb866f7fb1e09035caa8646e063d023d9557b38ae20bd39e1c13de48a3c211da7509f6920f0fa6f33e", 16); - - private static final BigInteger DSA_KEY_priv = new BigInteger("2950e4774fb2fffb5d33c937f0b58ffb0d45c200", 16); - private static final BigInteger DSA_KEY_pub = new BigInteger("0087b82cdf3232db3bec0d00e96c8393bc7f5629551ea1a00888961cf56e80a36f2a7b316bc10b1d367a5ea374235c9361a472a9176f6cf61f708b86a52b4fae814abd1f1bdd16eea94aea9281851032b1bad7567624c615d6899ca1c94ad614f14e767e49d2ba5223cd113a0d02b66183653cd346ae76d85843afe66520904274", 16); - - public void testGetOidFromPkcs8Encoded_Ec_NistP256() throws Exception { - assertEquals("1.2.840.10045.2.1", PubkeyUtils.getOidFromPkcs8Encoded(EC_KEY_PKCS8)); - } - - public void testGetOidFromPkcs8Encoded_Rsa() throws Exception { - assertEquals("1.2.840.113549.1.1.1", PubkeyUtils.getOidFromPkcs8Encoded(RSA_KEY_PKCS8)); - } - - public void testGetOidFromPkcs8Encoded_Dsa() throws Exception { - assertEquals("1.2.840.10040.4.1", PubkeyUtils.getOidFromPkcs8Encoded(DSA_KEY_PKCS8)); - } - - public void testGetOidFromPkcs8Encoded_Null_Failure() throws Exception { - try { - PubkeyUtils.getOidFromPkcs8Encoded(null); - fail("Should throw NoSuchAlgorithmException"); - } catch (NoSuchAlgorithmException expected) { - } - } - - public void testGetOidFromPkcs8Encoded_NotCorrectDer_Failure() throws Exception { - try { - PubkeyUtils.getOidFromPkcs8Encoded(new byte[] { 0x30, 0x01, 0x00 }); - fail("Should throw NoSuchAlgorithmException"); - } catch (NoSuchAlgorithmException expected) { - } - } - - public void testGetAlgorithmForOid_Ecdsa() throws Exception { - assertEquals("EC", PubkeyUtils.getAlgorithmForOid("1.2.840.10045.2.1")); - } - - public void testGetAlgorithmForOid_Rsa() throws Exception { - assertEquals("RSA", PubkeyUtils.getAlgorithmForOid("1.2.840.113549.1.1.1")); - } - - public void testGetAlgorithmForOid_Dsa() throws Exception { - assertEquals("DSA", PubkeyUtils.getAlgorithmForOid("1.2.840.10040.4.1")); - } - - public void testGetAlgorithmForOid_NullInput_Failure() throws Exception { - try { - PubkeyUtils.getAlgorithmForOid(null); - fail("Should throw NoSuchAlgorithmException"); - } catch (NoSuchAlgorithmException expected) { - } - } - - public void testGetAlgorithmForOid_UnknownOid_Failure() throws Exception { - try { - PubkeyUtils.getAlgorithmForOid("1.3.66666.2000.4000.1"); - fail("Should throw NoSuchAlgorithmException"); - } catch (NoSuchAlgorithmException expected) { - } - } - - public void testRecoverKeyPair_Dsa() throws Exception { - KeyPair kp = PubkeyUtils.recoverKeyPair(DSA_KEY_PKCS8); - - DSAPublicKey pubKey = (DSAPublicKey) kp.getPublic(); - - assertEquals(DSA_KEY_pub, pubKey.getY()); - - DSAParams params = pubKey.getParams(); - assertEquals(params.getG(), DSA_KEY_G); - assertEquals(params.getP(), DSA_KEY_P); - assertEquals(params.getQ(), DSA_KEY_Q); - } - - public void testRecoverKeyPair_Rsa() throws Exception { - KeyPair kp = PubkeyUtils.recoverKeyPair(RSA_KEY_PKCS8); - - RSAPublicKey pubKey = (RSAPublicKey) kp.getPublic(); - - assertEquals(RSA_KEY_N, pubKey.getModulus()); - assertEquals(RSA_KEY_E, pubKey.getPublicExponent()); - } - - public void testRecoverKeyPair_Ec() throws Exception { - KeyPair kp = PubkeyUtils.recoverKeyPair(EC_KEY_PKCS8); - - ECPublicKey pubKey = (ECPublicKey) kp.getPublic(); - - assertEquals(EC_KEY_pub_x, pubKey.getW().getAffineX()); - assertEquals(EC_KEY_pub_y, pubKey.getW().getAffineY()); - } - - private static class MyPrivateKey implements PrivateKey { - public String getAlgorithm() { - throw new UnsupportedOperationException(); - } - - public byte[] getEncoded() { - throw new UnsupportedOperationException(); - } - - public String getFormat() { - throw new UnsupportedOperationException(); - } - } - - public void testRecoverPublicKey_FakeKey_Failure() throws Exception { - try { - PubkeyUtils.recoverPublicKey(null, new MyPrivateKey()); - fail("Should not accept unknown key types"); - } catch (NoSuchAlgorithmException expected) { - } - } -} diff --git a/robolectric-tests/.gitignore b/robolectric-tests/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/robolectric-tests/.gitignore @@ -0,0 +1 @@ +/build diff --git a/robolectric-tests/build.gradle b/robolectric-tests/build.gradle new file mode 100644 index 0000000..ce644af --- /dev/null +++ b/robolectric-tests/build.gradle @@ -0,0 +1,48 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2014 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +apply plugin: 'java' + +evaluationDependsOn(':app') + +dependencies { + def androidModule = project(':app') + compile androidModule + + testCompile androidModule.android.applicationVariants.toList().first().javaCompile.classpath + testCompile androidModule.android.applicationVariants.toList().first().javaCompile.outputs.files + testCompile files(androidModule.plugins.findPlugin("com.android.application").getBootClasspath()) + + // This gets the location of the SDK's Android Support Repo + androidModule.repositories { + all { ArtifactRepository repo -> + if (repo.url.toString().contains("extras/android/m2repository")) { + project.repositories.maven { url = repo.url } + } + } + } + + testCompile 'junit:junit:4.10' + testCompile 'org.robolectric:robolectric:2.3' +} + +tasks.withType(Test) { + scanForTestClasses = false + include "**/*Should.class" + include "**/*Test.class" + include "**/*Tests.class" +} \ No newline at end of file diff --git a/robolectric-tests/robolectric-tests.iml b/robolectric-tests/robolectric-tests.iml new file mode 100644 index 0000000..7ebd6eb --- /dev/null +++ b/robolectric-tests/robolectric-tests.iml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/robolectric-tests/src/test/java/org/connectbot/HostBeanTest.java b/robolectric-tests/src/test/java/org/connectbot/HostBeanTest.java new file mode 100644 index 0000000..2f8eb2f --- /dev/null +++ b/robolectric-tests/src/test/java/org/connectbot/HostBeanTest.java @@ -0,0 +1,102 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.connectbot; + +import org.connectbot.bean.HostBean; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.connectbot.mock.BeanAssertions.assertMeetsEqualsContract; +import static org.connectbot.mock.BeanAssertions.assertMeetsHashCodeContract; + +/** + * @author Kenny Root + */ +@Config(manifest = "../app/src/main/AndroidManifest.xml", emulateSdk = 16) +@RunWith(RobolectricTestRunner.class) +public class HostBeanTest { + private static final String[] FIELDS = { "nickname", "username", + "hostname", "port" }; + + private HostBean host1; + private HostBean host2; + + @Before + public void setUp() { + host1 = new HostBean(); + host1.setNickname("Home"); + host1.setUsername("bob"); + host1.setHostname("server.example.com"); + host1.setPort(22); + + host2 = new HostBean(); + host2.setNickname("Home"); + host2.setUsername("bob"); + host2.setHostname("server.example.com"); + host2.setPort(22); + } + + @Test + public void id_Equality() { + host1.setId(1); + host2.setId(1); + assertTrue(host1.equals(host2)); + assertTrue(host1.hashCode() == host2.hashCode()); + } + + @Test + public void id_Inequality() { + host1.setId(1); + host2.setId(2); + // HostBeans shouldn't be equal when their IDs are not the same + assertFalse("HostBeans are equal when their ID is different", host1 + .equals(host2)); + assertFalse("HostBean hash codes are equal when their ID is different", + host1.hashCode() == host2.hashCode()); + } + + @Test + public void id_Equality2() { + host1.setId(1); + host2.setId(1); + host2.setNickname("Work"); + host2.setUsername("alice"); + host2.setHostname("client.example.com"); + assertTrue( + "HostBeans are not equal when their ID is the same but other fields are different!", + host1.equals(host2)); + assertTrue( + "HostBeans hashCodes are not equal when their ID is the same but other fields are different!", + host1.hashCode() == host2.hashCode()); + } + + @Test + public void testBeanMeetsEqualsContract() { + assertMeetsEqualsContract(HostBean.class, FIELDS); + } + + @Test + public void testBeanMeetsHashCodeContract() { + assertMeetsHashCodeContract(HostBean.class, FIELDS); + } +} diff --git a/robolectric-tests/src/test/java/org/connectbot/SelectionAreaTest.java b/robolectric-tests/src/test/java/org/connectbot/SelectionAreaTest.java new file mode 100644 index 0000000..6e4134a --- /dev/null +++ b/robolectric-tests/src/test/java/org/connectbot/SelectionAreaTest.java @@ -0,0 +1,152 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.connectbot; + +import org.connectbot.bean.SelectionArea; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * @author Kenny Root + * + */ +@Config(manifest = "../app/src/main/AndroidManifest.xml", emulateSdk = 16) +@RunWith(RobolectricTestRunner.class) +public class SelectionAreaTest { + private static final int WIDTH = 80; + private static final int HEIGHT = 24; + + @Test + public void createSelectionArea() { + SelectionArea sa = new SelectionArea(); + + assertTrue(sa.getLeft() == 0); + assertTrue(sa.getRight() == 0); + assertTrue(sa.getTop() == 0); + assertTrue(sa.getBottom() == 0); + assertTrue(sa.isSelectingOrigin()); + } + + @Test + public void checkMovement() { + SelectionArea sa = new SelectionArea(); + + sa.setBounds(WIDTH, HEIGHT); + + sa.incrementColumn(); + + // Should be (1,0) to (1,0) + assertTrue(sa.getLeft() == 1); + assertTrue(sa.getTop() == 0); + assertTrue(sa.getRight() == 1); + assertTrue(sa.getBottom() == 0); + + sa.finishSelectingOrigin(); + assertFalse(sa.isSelectingOrigin()); + + sa.incrementColumn(); + sa.incrementColumn(); + + // Should be (1,0) to (3,0) + assertTrue(sa.getLeft() == 1); + assertTrue(sa.getTop() == 0); + assertTrue(sa.getRight() == 3); + assertTrue(sa.getBottom() == 0); + } + + @Test + public void boundsAreCorrect() { + SelectionArea sa = new SelectionArea(); + + sa.setBounds(WIDTH, HEIGHT); + + for (int i = 0; i <= WIDTH; i++) + sa.decrementColumn(); + assertTrue("Left bound should be 0, but instead is " + sa.getLeft(), + sa.getLeft() == 0); + + for (int i = 0; i <= HEIGHT; i++) + sa.decrementRow(); + assertTrue("Top bound should be 0, but instead is " + sa.getLeft(), + sa.getTop() == 0); + + sa.finishSelectingOrigin(); + + for (int i = 0; i <= WIDTH * 2; i++) + sa.incrementColumn(); + + assertTrue("Left bound should be 0, but instead is " + sa.getLeft(), + sa.getLeft() == 0); + assertTrue("Right bound should be " + (WIDTH - 1) + ", but instead is " + sa.getRight(), + sa.getRight() == (WIDTH - 1)); + + for (int i = 0; i <= HEIGHT * 2; i++) + sa.incrementRow(); + + assertTrue("Bottom bound should be " + (HEIGHT - 1) + ", but instead is " + sa.getBottom(), + sa.getBottom() == (HEIGHT - 1)); + assertTrue("Top bound should be 0, but instead is " + sa.getTop(), + sa.getTop() == 0); + } + + @Test + public void setThenMove() { + SelectionArea sa = new SelectionArea(); + + sa.setBounds(WIDTH, HEIGHT); + + int targetColumn = WIDTH / 2; + int targetRow = HEIGHT / 2; + + sa.setColumn(targetColumn); + sa.setRow(targetRow); + + sa.incrementRow(); + assertTrue("Row should be " + (targetRow + 1) + ", but instead is " + sa.getTop(), + sa.getTop() == (targetRow + 1)); + + sa.decrementColumn(); + assertTrue("Column shold be " + (targetColumn - 1) + ", but instead is " + sa.getLeft(), + sa.getLeft() == (targetColumn - 1)); + + sa.finishSelectingOrigin(); + + sa.setRow(0); + sa.setColumn(0); + + sa.incrementRow(); + sa.decrementColumn(); + + assertTrue("Top row should be 1, but instead is " + sa.getTop(), + sa.getTop() == 1); + + assertTrue("Left column shold be 0, but instead is " + sa.getLeft(), + sa.getLeft() == 0); + + assertTrue("Bottom row should be " + (targetRow + 1) + ", but instead is " + sa.getBottom(), + sa.getBottom() == (targetRow + 1)); + + assertTrue("Right column shold be " + (targetColumn - 1) + ", but instead is " + sa.getRight(), + sa.getRight() == (targetColumn - 1)); + } +} diff --git a/robolectric-tests/src/test/java/org/connectbot/mock/BeanAssertions.java b/robolectric-tests/src/test/java/org/connectbot/mock/BeanAssertions.java new file mode 100644 index 0000000..cf7b7de --- /dev/null +++ b/robolectric-tests/src/test/java/org/connectbot/mock/BeanAssertions.java @@ -0,0 +1,235 @@ +/** + * Originally from http://www.cornetdesign.com/files/BeanTestCase.java.txt + */ +package org.connectbot.mock; + +import junit.framework.TestCase; + +import java.lang.reflect.Field; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class BeanAssertions { + private static final String TEST_STRING_VAL1 = "Some Value"; + private static final String TEST_STRING_VAL2 = "Some Other Value"; + + private BeanAssertions() { + } + + public static void assertMeetsEqualsContract(Class classUnderTest, + String[] fieldNames) { + Object o1; + Object o2; + try { + // Get Instances + o1 = classUnderTest.newInstance(); + o2 = classUnderTest.newInstance(); + + assertTrue( + "Instances with default constructor not equal (o1.equals(o2))", + o1.equals(o2)); + assertTrue( + "Instances with default constructor not equal (o2.equals(o1))", + o2.equals(o1)); + + Field[] fields = getFieldsByNameOrAll(classUnderTest, fieldNames); + + for (int i = 0; i < fields.length; i++) { + + // Reset the instances + o1 = classUnderTest.newInstance(); + o2 = classUnderTest.newInstance(); + + Field field = fields[i]; + field.setAccessible(true); + if (field.getType() == String.class) { + field.set(o1, TEST_STRING_VAL1); + } else if (field.getType() == boolean.class) { + field.setBoolean(o1, true); + } else if (field.getType() == short.class) { + field.setShort(o1, (short) 1); + } else if (field.getType() == long.class) { + field.setLong(o1, (long) 1); + } else if (field.getType() == float.class) { + field.setFloat(o1, (float) 1); + } else if (field.getType() == int.class) { + field.setInt(o1, 1); + } else if (field.getType() == byte.class) { + field.setByte(o1, (byte) 1); + } else if (field.getType() == char.class) { + field.setChar(o1, (char) 1); + } else if (field.getType() == double.class) { + field.setDouble(o1, (double) 1); + } else if (field.getType().isEnum()) { + field.set(o1, field.getType().getEnumConstants()[0]); + } else if (Object.class.isAssignableFrom(field.getType())) { + field.set(o1, field.getType().newInstance()); + } else { + fail("Don't know how to set a " + field.getType().getName()); + } + + assertFalse("Instances with o1 having " + field.getName() + + " set and o2 having it not set are equal", o1 + .equals(o2)); + + field.set(o2, field.get(o1)); + + assertTrue( + "After setting o2 with the value of the object in o1, the two objects in the field are not equal", + field.get(o1).equals(field.get(o2))); + + assertTrue( + "Instances with o1 having " + + field.getName() + + " set and o2 having it set to the same object of type " + + field.get(o2).getClass().getName() + + " are not equal", o1.equals(o2)); + + if (field.getType() == String.class) { + field.set(o2, TEST_STRING_VAL2); + } else if (field.getType() == boolean.class) { + field.setBoolean(o2, false); + } else if (field.getType() == short.class) { + field.setShort(o2, (short) 0); + } else if (field.getType() == long.class) { + field.setLong(o2, (long) 0); + } else if (field.getType() == float.class) { + field.setFloat(o2, (float) 0); + } else if (field.getType() == int.class) { + field.setInt(o2, 0); + } else if (field.getType() == byte.class) { + field.setByte(o2, (byte) 0); + } else if (field.getType() == char.class) { + field.setChar(o2, (char) 0); + } else if (field.getType() == double.class) { + field.setDouble(o2, (double) 1); + } else if (field.getType().isEnum()) { + field.set(o2, field.getType().getEnumConstants()[1]); + } else if (Object.class.isAssignableFrom(field.getType())) { + field.set(o2, field.getType().newInstance()); + } else { + fail("Don't know how to set a " + field.getType().getName()); + } + if (field.get(o1).equals(field.get(o2))) { + // Even though we have different instances, they are equal. + // Let's walk one of them + // to see if we can find a field to set + Field[] paramFields = field.get(o1).getClass() + .getDeclaredFields(); + for (int j = 0; j < paramFields.length; j++) { + paramFields[j].setAccessible(true); + if (paramFields[j].getType() == String.class) { + paramFields[j].set(field.get(o1), TEST_STRING_VAL1); + } + } + } + + assertFalse( + "After setting o2 with a different object than what is in o1, the two objects in the field are equal. " + + "This is after an attempt to walk the fields to make them different", + field.get(o1).equals(field.get(o2))); + assertFalse( + "Instances with o1 having " + + field.getName() + + " set and o2 having it set to a different object are equal", + o1.equals(o2)); + } + + } catch (InstantiationException e) { + e.printStackTrace(); + throw new AssertionError( + "Unable to construct an instance of the class under test"); + } catch (IllegalAccessException e) { + e.printStackTrace(); + throw new AssertionError( + "Unable to construct an instance of the class under test"); + } catch (SecurityException e) { + e.printStackTrace(); + throw new AssertionError( + "Unable to read the field from the class under test"); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + throw new AssertionError( + "Unable to find field in the class under test"); + } + } + + /** + * @param classUnderTest + * @param fieldNames + * @return + * @throws NoSuchFieldException + */ + private static Field[] getFieldsByNameOrAll(Class classUnderTest, + String[] fieldNames) throws NoSuchFieldException { + Field fields[]; + if (fieldNames == null) { + fields = classUnderTest.getDeclaredFields(); + } else { + fields = new Field[fieldNames.length]; + for (int i = 0; i < fieldNames.length; i++) + fields[i] = classUnderTest.getDeclaredField(fieldNames[i]); + } + return fields; + } + + public static void assertMeetsHashCodeContract(Class classUnderTest, + String[] fieldNames) { + try { + Field[] fields = getFieldsByNameOrAll(classUnderTest, fieldNames); + + for (int i = 0; i < fields.length; i++) { + Object o1 = classUnderTest.newInstance(); + int initialHashCode = o1.hashCode(); + + Field field = fields[i]; + field.setAccessible(true); + if (field.getType() == String.class) { + field.set(o1, TEST_STRING_VAL1); + } else if (field.getType() == boolean.class) { + field.setBoolean(o1, true); + } else if (field.getType() == short.class) { + field.setShort(o1, (short) 1); + } else if (field.getType() == long.class) { + field.setLong(o1, (long) 1); + } else if (field.getType() == float.class) { + field.setFloat(o1, (float) 1); + } else if (field.getType() == int.class) { + field.setInt(o1, 1); + } else if (field.getType() == byte.class) { + field.setByte(o1, (byte) 1); + } else if (field.getType() == char.class) { + field.setChar(o1, (char) 1); + } else if (field.getType() == double.class) { + field.setDouble(o1, (double) 1); + } else if (field.getType().isEnum()) { + field.set(o1, field.getType().getEnumConstants()[0]); + } else if (Object.class.isAssignableFrom(field.getType())) { + field.set(o1, field.getType().newInstance()); + } else { + fail("Don't know how to set a " + field.getType().getName()); + } + int updatedHashCode = o1.hashCode(); + assertFalse( + "The field " + + field.getName() + + " was not taken into account for the hashCode contract ", + initialHashCode == updatedHashCode); + } + } catch (InstantiationException e) { + e.printStackTrace(); + throw new AssertionError( + "Unable to construct an instance of the class under test"); + } catch (IllegalAccessException e) { + e.printStackTrace(); + throw new AssertionError( + "Unable to construct an instance of the class under test"); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + throw new AssertionError( + "Unable to find field in the class under test"); + } + } +} diff --git a/robolectric-tests/src/test/java/org/connectbot/mock/NullOutputStream.java b/robolectric-tests/src/test/java/org/connectbot/mock/NullOutputStream.java new file mode 100644 index 0000000..79b8e72 --- /dev/null +++ b/robolectric-tests/src/test/java/org/connectbot/mock/NullOutputStream.java @@ -0,0 +1,33 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.connectbot.mock; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * @author Kenny Root + * + */ +public class NullOutputStream extends OutputStream { + @Override + public void write(int arg0) throws IOException { + // do nothing + } + +} diff --git a/robolectric-tests/src/test/java/org/connectbot/mock/NullTransport.java b/robolectric-tests/src/test/java/org/connectbot/mock/NullTransport.java new file mode 100644 index 0000000..d841e6a --- /dev/null +++ b/robolectric-tests/src/test/java/org/connectbot/mock/NullTransport.java @@ -0,0 +1,138 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.connectbot.mock; + +import java.io.IOException; +import java.util.Map; + +import org.connectbot.bean.HostBean; +import org.connectbot.service.TerminalBridge; +import org.connectbot.service.TerminalManager; +import org.connectbot.transport.AbsTransport; + +import android.net.Uri; + +/** + * @author kenny + * + */ +public class NullTransport extends AbsTransport { + + /** + * + */ + public NullTransport() { + // TODO Auto-generated constructor stub + } + + /** + * @param host + * @param bridge + * @param manager + */ + public NullTransport(HostBean host, TerminalBridge bridge, + TerminalManager manager) { + super(host, bridge, manager); + // TODO Auto-generated constructor stub + } + + @Override + public void close() { + // TODO Auto-generated method stub + + } + + @Override + public void connect() { + // TODO Auto-generated method stub + + } + + @Override + public HostBean createHost(Uri uri) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void flush() throws IOException { + // TODO Auto-generated method stub + + } + + @Override + public String getDefaultNickname(String username, String hostname, int port) { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getDefaultPort() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public void getSelectionArgs(Uri uri, Map selection) { + // TODO Auto-generated method stub + + } + + @Override + public boolean isConnected() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isSessionOpen() { + // TODO Auto-generated method stub + return false; + } + + @Override + public int read(byte[] buffer, int offset, int length) throws IOException { + // TODO Auto-generated method stub + return 0; + } + + @Override + public void setDimensions(int columns, int rows, int width, int height) { + // TODO Auto-generated method stub + + } + + @Override + public void write(byte[] buffer) throws IOException { + // TODO Auto-generated method stub + + } + + @Override + public void write(int c) throws IOException { + // TODO Auto-generated method stub + + } + + @Override + public boolean usesNetwork() { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/robolectric-tests/src/test/java/org/connectbot/util/PubkeyUtilsTest.java b/robolectric-tests/src/test/java/org/connectbot/util/PubkeyUtilsTest.java new file mode 100644 index 0000000..0843e74 --- /dev/null +++ b/robolectric-tests/src/test/java/org/connectbot/util/PubkeyUtilsTest.java @@ -0,0 +1,370 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.connectbot.util; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.interfaces.DSAParams; +import java.security.interfaces.DSAPublicKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPublicKey; +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * @author Kenny Root + */ +@Config(manifest = "../app/src/main/AndroidManifest.xml", emulateSdk = 16) +@RunWith(RobolectricTestRunner.class) +public class PubkeyUtilsTest { + @Test + public void encodeHex_Null_Failure() throws Exception { + try { + PubkeyUtils.encodeHex(null); + fail("Should throw null pointer exception when argument is null"); + } catch (NullPointerException e) { + // success + } + } + + @Test + public void encodeHex_Success() throws Exception { + byte[] input = {(byte) 0xFF, 0x00, (byte) 0xA5, 0x5A, 0x12, 0x23}; + String expected = "ff00a55a1223"; + + assertEquals("Encoded hex should match expected", + PubkeyUtils.encodeHex(input), expected); + } + + @Test + public void sha256_Empty_Success() throws Exception { + byte[] empty_hashed = new byte[] { + (byte) 0xe3, (byte) 0xb0, (byte) 0xc4, (byte) 0x42, + (byte) 0x98, (byte) 0xfc, (byte) 0x1c, (byte) 0x14, + (byte) 0x9a, (byte) 0xfb, (byte) 0xf4, (byte) 0xc8, + (byte) 0x99, (byte) 0x6f, (byte) 0xb9, (byte) 0x24, + (byte) 0x27, (byte) 0xae, (byte) 0x41, (byte) 0xe4, + (byte) 0x64, (byte) 0x9b, (byte) 0x93, (byte) 0x4c, + (byte) 0xa4, (byte) 0x95, (byte) 0x99, (byte) 0x1b, + (byte) 0x78, (byte) 0x52, (byte) 0xb8, (byte) 0x55, + }; + + final byte[] empty = new byte[] {}; + + assertTrue("Empty string should be equal to known test vector", + Arrays.equals(empty_hashed, PubkeyUtils.sha256(empty))); + } + + /* openssl ecparam -genkey -name prime256v1 -noout | openssl pkcs8 -topk8 -outform d -nocrypt | recode ../x1 | sed 's/0x/(byte) 0x/g' */ + private static final byte[] EC_KEY_PKCS8 = new byte[] { (byte) 0x30, (byte) 0x81, (byte) 0x87, + (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x30, (byte) 0x13, (byte) 0x06, + (byte) 0x07, (byte) 0x2A, (byte) 0x86, (byte) 0x48, (byte) 0xCE, (byte) 0x3D, + (byte) 0x02, (byte) 0x01, (byte) 0x06, (byte) 0x08, (byte) 0x2A, (byte) 0x86, + (byte) 0x48, (byte) 0xCE, (byte) 0x3D, (byte) 0x03, (byte) 0x01, (byte) 0x07, + (byte) 0x04, (byte) 0x6D, (byte) 0x30, (byte) 0x6B, (byte) 0x02, (byte) 0x01, + (byte) 0x01, (byte) 0x04, (byte) 0x20, (byte) 0xC7, (byte) 0x6B, (byte) 0xA5, + (byte) 0xB6, (byte) 0xB7, (byte) 0x4E, (byte) 0x0B, (byte) 0x70, (byte) 0x2E, + (byte) 0xA0, (byte) 0x5D, (byte) 0x8D, (byte) 0x0A, (byte) 0xF5, (byte) 0x43, + (byte) 0xEF, (byte) 0x54, (byte) 0x2F, (byte) 0x05, (byte) 0x5B, (byte) 0x66, + (byte) 0x50, (byte) 0xC5, (byte) 0xB4, (byte) 0xA8, (byte) 0x60, (byte) 0x16, + (byte) 0x8E, (byte) 0x8D, (byte) 0xCD, (byte) 0x11, (byte) 0xFA, (byte) 0xA1, + (byte) 0x44, (byte) 0x03, (byte) 0x42, (byte) 0x00, (byte) 0x04, (byte) 0x12, + (byte) 0xE2, (byte) 0x70, (byte) 0x30, (byte) 0x87, (byte) 0x2F, (byte) 0xDE, + (byte) 0x10, (byte) 0xD9, (byte) 0xC9, (byte) 0x83, (byte) 0xC7, (byte) 0x8D, + (byte) 0xC9, (byte) 0x9B, (byte) 0x94, (byte) 0x24, (byte) 0x50, (byte) 0x5D, + (byte) 0xEC, (byte) 0xF1, (byte) 0x4F, (byte) 0x52, (byte) 0xC6, (byte) 0xE7, + (byte) 0xA3, (byte) 0xD7, (byte) 0xF4, (byte) 0x7C, (byte) 0x09, (byte) 0xA1, + (byte) 0x10, (byte) 0x11, (byte) 0xE4, (byte) 0x9E, (byte) 0x90, (byte) 0xAF, + (byte) 0xF9, (byte) 0x4A, (byte) 0x74, (byte) 0x09, (byte) 0x93, (byte) 0xC7, + (byte) 0x9A, (byte) 0xB3, (byte) 0xE2, (byte) 0xD8, (byte) 0x61, (byte) 0x5F, + (byte) 0x86, (byte) 0x14, (byte) 0x91, (byte) 0x7A, (byte) 0x23, (byte) 0x81, + (byte) 0x42, (byte) 0xA9, (byte) 0x02, (byte) 0x1D, (byte) 0x33, (byte) 0x19, + (byte) 0xC0, (byte) 0x4B, (byte) 0xCE + }; + + private static final BigInteger EC_KEY_priv = new BigInteger("c76ba5b6b74e0b702ea05d8d0af543ef542f055b6650c5b4a860168e8dcd11fa", 16); + private static final BigInteger EC_KEY_pub_x = new BigInteger("12e27030872fde10d9c983c78dc99b9424505decf14f52c6e7a3d7f47c09a110", 16); + private static final BigInteger EC_KEY_pub_y = new BigInteger("11e49e90aff94a740993c79ab3e2d8615f8614917a238142a9021d3319c04bce", 16); + + /* openssl genrsa 512 | openssl pkcs8 -topk8 -outform d -nocrypt | recode ../x1 | sed 's/0x/(byte) 0x/g' */ + private static final byte[] RSA_KEY_PKCS8 = new byte[] { (byte) 0x30, (byte) 0x82, (byte) 0x01, + (byte) 0x55, (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x30, (byte) 0x0D, + (byte) 0x06, (byte) 0x09, (byte) 0x2A, (byte) 0x86, (byte) 0x48, (byte) 0x86, + (byte) 0xF7, (byte) 0x0D, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, + (byte) 0x00, (byte) 0x04, (byte) 0x82, (byte) 0x01, (byte) 0x3F, (byte) 0x30, + (byte) 0x82, (byte) 0x01, (byte) 0x3B, (byte) 0x02, (byte) 0x01, (byte) 0x00, + (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xC6, (byte) 0x00, (byte) 0x79, + (byte) 0x0C, (byte) 0x46, (byte) 0xF9, (byte) 0x03, (byte) 0x15, (byte) 0xBA, + (byte) 0x35, (byte) 0x63, (byte) 0x6C, (byte) 0x97, (byte) 0x3A, (byte) 0x6C, + (byte) 0xC8, (byte) 0x15, (byte) 0x32, (byte) 0x2A, (byte) 0x62, (byte) 0x72, + (byte) 0xBD, (byte) 0x05, (byte) 0x01, (byte) 0xCF, (byte) 0xE6, (byte) 0x49, + (byte) 0xEC, (byte) 0xC9, (byte) 0x8A, (byte) 0x3A, (byte) 0x4E, (byte) 0xB1, + (byte) 0xF2, (byte) 0x3E, (byte) 0x86, (byte) 0x3C, (byte) 0x64, (byte) 0x4A, + (byte) 0x0A, (byte) 0x29, (byte) 0xD6, (byte) 0xFA, (byte) 0xF9, (byte) 0xAC, + (byte) 0xD8, (byte) 0x7B, (byte) 0x9F, (byte) 0x2A, (byte) 0x6B, (byte) 0x13, + (byte) 0x06, (byte) 0x06, (byte) 0xEB, (byte) 0x83, (byte) 0x1B, (byte) 0xB8, + (byte) 0x97, (byte) 0xA3, (byte) 0x91, (byte) 0x95, (byte) 0x60, (byte) 0x15, + (byte) 0xE5, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x01, + (byte) 0x02, (byte) 0x40, (byte) 0x0F, (byte) 0xDA, (byte) 0x33, (byte) 0xD6, + (byte) 0xCE, (byte) 0xCB, (byte) 0xDA, (byte) 0xFA, (byte) 0x5F, (byte) 0x59, + (byte) 0x2C, (byte) 0xE7, (byte) 0xA1, (byte) 0xC7, (byte) 0xF4, (byte) 0xB3, + (byte) 0xA4, (byte) 0x36, (byte) 0xCA, (byte) 0xFB, (byte) 0xEC, (byte) 0xD1, + (byte) 0xC3, (byte) 0x57, (byte) 0xDC, (byte) 0xCC, (byte) 0x44, (byte) 0x38, + (byte) 0xE7, (byte) 0xFD, (byte) 0xE0, (byte) 0x23, (byte) 0x0E, (byte) 0x97, + (byte) 0x87, (byte) 0x55, (byte) 0x80, (byte) 0x2B, (byte) 0xF2, (byte) 0xF4, + (byte) 0x1C, (byte) 0x03, (byte) 0xD2, (byte) 0x3E, (byte) 0x09, (byte) 0x72, + (byte) 0x49, (byte) 0xD8, (byte) 0x9C, (byte) 0xAC, (byte) 0xDA, (byte) 0x65, + (byte) 0x68, (byte) 0x4D, (byte) 0x38, (byte) 0x19, (byte) 0xD8, (byte) 0xB1, + (byte) 0x5B, (byte) 0xB7, (byte) 0x38, (byte) 0xC8, (byte) 0x94, (byte) 0xB5, + (byte) 0x02, (byte) 0x21, (byte) 0x00, (byte) 0xF7, (byte) 0x8E, (byte) 0x20, + (byte) 0xDC, (byte) 0x26, (byte) 0x12, (byte) 0x3A, (byte) 0x85, (byte) 0x91, + (byte) 0x5F, (byte) 0x45, (byte) 0xA6, (byte) 0x95, (byte) 0xE5, (byte) 0x22, + (byte) 0xD0, (byte) 0xC4, (byte) 0xD7, (byte) 0x6A, (byte) 0xF1, (byte) 0x43, + (byte) 0x38, (byte) 0x88, (byte) 0x20, (byte) 0x7D, (byte) 0x80, (byte) 0x73, + (byte) 0x7B, (byte) 0xDC, (byte) 0x73, (byte) 0x51, (byte) 0x3B, (byte) 0x02, + (byte) 0x21, (byte) 0x00, (byte) 0xCC, (byte) 0xC1, (byte) 0x99, (byte) 0xC8, + (byte) 0xC0, (byte) 0x54, (byte) 0xBC, (byte) 0xE9, (byte) 0xFB, (byte) 0x77, + (byte) 0x28, (byte) 0xB8, (byte) 0x26, (byte) 0x02, (byte) 0xC0, (byte) 0x0C, + (byte) 0xDE, (byte) 0xFD, (byte) 0xEA, (byte) 0xD0, (byte) 0x15, (byte) 0x4B, + (byte) 0x3B, (byte) 0xD1, (byte) 0xDD, (byte) 0xFD, (byte) 0x5B, (byte) 0xAC, + (byte) 0xB3, (byte) 0xCF, (byte) 0xC3, (byte) 0x5F, (byte) 0x02, (byte) 0x21, + (byte) 0x00, (byte) 0xCD, (byte) 0x8C, (byte) 0x25, (byte) 0x9C, (byte) 0xA5, + (byte) 0xBF, (byte) 0xDC, (byte) 0xF7, (byte) 0xAA, (byte) 0x8D, (byte) 0x00, + (byte) 0xB8, (byte) 0x21, (byte) 0x1D, (byte) 0xF0, (byte) 0x9A, (byte) 0x87, + (byte) 0xD6, (byte) 0x95, (byte) 0xE5, (byte) 0x5D, (byte) 0x7B, (byte) 0x43, + (byte) 0x0C, (byte) 0x37, (byte) 0x28, (byte) 0xC0, (byte) 0xBA, (byte) 0xC7, + (byte) 0x80, (byte) 0xB8, (byte) 0xA1, (byte) 0x02, (byte) 0x21, (byte) 0x00, + (byte) 0xCC, (byte) 0x26, (byte) 0x6F, (byte) 0xAD, (byte) 0x60, (byte) 0x4E, + (byte) 0x5C, (byte) 0xB9, (byte) 0x32, (byte) 0x57, (byte) 0x61, (byte) 0x8B, + (byte) 0x11, (byte) 0xA3, (byte) 0x06, (byte) 0x57, (byte) 0x0E, (byte) 0xF2, + (byte) 0xBE, (byte) 0x6F, (byte) 0x4F, (byte) 0xFB, (byte) 0xDE, (byte) 0x1D, + (byte) 0xE6, (byte) 0xA7, (byte) 0x19, (byte) 0x03, (byte) 0x7D, (byte) 0x98, + (byte) 0xB6, (byte) 0x23, (byte) 0x02, (byte) 0x20, (byte) 0x24, (byte) 0x80, + (byte) 0x94, (byte) 0xFF, (byte) 0xDD, (byte) 0x7A, (byte) 0x22, (byte) 0x7D, + (byte) 0xC4, (byte) 0x5A, (byte) 0xFD, (byte) 0x84, (byte) 0xC1, (byte) 0xAD, + (byte) 0x8A, (byte) 0x13, (byte) 0x2A, (byte) 0xF9, (byte) 0x5D, (byte) 0xFF, + (byte) 0x0B, (byte) 0x2E, (byte) 0x0F, (byte) 0x61, (byte) 0x42, (byte) 0x88, + (byte) 0x57, (byte) 0xCF, (byte) 0xC1, (byte) 0x71, (byte) 0xC9, (byte) 0xB9 + }; + + private static final BigInteger RSA_KEY_N = new BigInteger("C600790C46F90315BA35636C973A6CC815322A6272BD0501CFE649ECC98A3A4EB1F23E863C644A0A29D6FAF9ACD87B9F2A6B130606EB831BB897A391956015E5", 16); + private static final BigInteger RSA_KEY_E = new BigInteger("010001", 16); + + /* + openssl dsaparam -genkey -text -out dsakey.pem 1024 + openssl dsa -in dsakey.pem -text -noout + openssl pkcs8 -topk8 -in dsakey.pem -outform d -nocrypt | recode ../x1 | sed 's/0x/(byte) 0x/g' + */ + private static final byte[] DSA_KEY_PKCS8 = new byte[] { + (byte) 0x30, (byte) 0x82, (byte) 0x01, (byte) 0x4A, (byte) 0x02, (byte) 0x01, + (byte) 0x00, (byte) 0x30, (byte) 0x82, (byte) 0x01, (byte) 0x2B, (byte) 0x06, + (byte) 0x07, (byte) 0x2A, (byte) 0x86, (byte) 0x48, (byte) 0xCE, (byte) 0x38, + (byte) 0x04, (byte) 0x01, (byte) 0x30, (byte) 0x82, (byte) 0x01, (byte) 0x1E, + (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0xD2, (byte) 0x18, + (byte) 0xDB, (byte) 0x94, (byte) 0x7C, (byte) 0xD6, (byte) 0x2E, (byte) 0xE2, + (byte) 0x07, (byte) 0x38, (byte) 0x42, (byte) 0xC4, (byte) 0x16, (byte) 0x24, + (byte) 0x94, (byte) 0x2F, (byte) 0xC1, (byte) 0x0F, (byte) 0x92, (byte) 0x0A, + (byte) 0x44, (byte) 0x44, (byte) 0x99, (byte) 0xFC, (byte) 0x01, (byte) 0x1B, + (byte) 0xF8, (byte) 0xF3, (byte) 0x82, (byte) 0x57, (byte) 0x01, (byte) 0x8D, + (byte) 0xE6, (byte) 0x22, (byte) 0x70, (byte) 0xA0, (byte) 0xD6, (byte) 0x05, + (byte) 0x0F, (byte) 0xF1, (byte) 0xD0, (byte) 0xF4, (byte) 0x0B, (byte) 0xA2, + (byte) 0xE4, (byte) 0x1E, (byte) 0xD3, (byte) 0x44, (byte) 0x79, (byte) 0x74, + (byte) 0x4C, (byte) 0xC1, (byte) 0xA7, (byte) 0xA5, (byte) 0x84, (byte) 0xD8, + (byte) 0xB9, (byte) 0xDF, (byte) 0xA3, (byte) 0x85, (byte) 0xFA, (byte) 0xF2, + (byte) 0xFD, (byte) 0x44, (byte) 0x0B, (byte) 0xB1, (byte) 0xA5, (byte) 0x82, + (byte) 0x8D, (byte) 0x06, (byte) 0x92, (byte) 0xCA, (byte) 0xB4, (byte) 0xFB, + (byte) 0xDF, (byte) 0xC2, (byte) 0xFD, (byte) 0xA7, (byte) 0xCB, (byte) 0x6F, + (byte) 0x03, (byte) 0xB9, (byte) 0xEF, (byte) 0xFD, (byte) 0x7F, (byte) 0xBC, + (byte) 0xB3, (byte) 0x1D, (byte) 0xA4, (byte) 0xE8, (byte) 0x7D, (byte) 0xA2, + (byte) 0xCF, (byte) 0x62, (byte) 0x35, (byte) 0x06, (byte) 0xC8, (byte) 0xFE, + (byte) 0xE6, (byte) 0xE7, (byte) 0x6E, (byte) 0xAE, (byte) 0x22, (byte) 0xE7, + (byte) 0x82, (byte) 0x38, (byte) 0x54, (byte) 0x82, (byte) 0xCD, (byte) 0xEA, + (byte) 0xD8, (byte) 0x69, (byte) 0xBB, (byte) 0x1C, (byte) 0xD3, (byte) 0x70, + (byte) 0x32, (byte) 0xB1, (byte) 0xFB, (byte) 0x07, (byte) 0x01, (byte) 0x66, + (byte) 0xCC, (byte) 0x24, (byte) 0xD6, (byte) 0x50, (byte) 0x46, (byte) 0x9B, + (byte) 0x02, (byte) 0x15, (byte) 0x00, (byte) 0xD6, (byte) 0xE6, (byte) 0x7E, + (byte) 0x1A, (byte) 0xE5, (byte) 0xCA, (byte) 0x1D, (byte) 0xB6, (byte) 0xAF, + (byte) 0x4E, (byte) 0xD9, (byte) 0x18, (byte) 0xE8, (byte) 0x87, (byte) 0xB1, + (byte) 0xBC, (byte) 0x93, (byte) 0xE1, (byte) 0x80, (byte) 0xF5, (byte) 0x02, + (byte) 0x81, (byte) 0x80, (byte) 0x19, (byte) 0x20, (byte) 0xCC, (byte) 0x18, + (byte) 0xF6, (byte) 0x8F, (byte) 0x73, (byte) 0xFA, (byte) 0x9F, (byte) 0x50, + (byte) 0xC8, (byte) 0x92, (byte) 0xBE, (byte) 0x07, (byte) 0x7C, (byte) 0x34, + (byte) 0xD8, (byte) 0x6F, (byte) 0x63, (byte) 0xC9, (byte) 0x35, (byte) 0x48, + (byte) 0x79, (byte) 0x79, (byte) 0x26, (byte) 0xEF, (byte) 0x1E, (byte) 0x99, + (byte) 0x54, (byte) 0xD7, (byte) 0x30, (byte) 0x2C, (byte) 0x68, (byte) 0xBC, + (byte) 0xFF, (byte) 0xF2, (byte) 0x4C, (byte) 0x6A, (byte) 0xD3, (byte) 0x2D, + (byte) 0x1C, (byte) 0x7A, (byte) 0x06, (byte) 0x11, (byte) 0x72, (byte) 0x92, + (byte) 0x9C, (byte) 0xAA, (byte) 0x95, (byte) 0x0E, (byte) 0x44, (byte) 0x2C, + (byte) 0x5F, (byte) 0x19, (byte) 0x25, (byte) 0xB4, (byte) 0xBF, (byte) 0x21, + (byte) 0x8F, (byte) 0xB7, (byte) 0x7E, (byte) 0x4B, (byte) 0x64, (byte) 0x83, + (byte) 0x59, (byte) 0x20, (byte) 0x20, (byte) 0x36, (byte) 0x84, (byte) 0xA4, + (byte) 0x1D, (byte) 0xB5, (byte) 0xCA, (byte) 0x7F, (byte) 0x10, (byte) 0x4E, + (byte) 0x27, (byte) 0x21, (byte) 0x8E, (byte) 0x2C, (byte) 0xA5, (byte) 0xF8, + (byte) 0xAC, (byte) 0xBD, (byte) 0xF5, (byte) 0xB5, (byte) 0xBA, (byte) 0xEB, + (byte) 0x86, (byte) 0x6F, (byte) 0x7F, (byte) 0xB1, (byte) 0xE0, (byte) 0x90, + (byte) 0x35, (byte) 0xCA, (byte) 0xA8, (byte) 0x64, (byte) 0x6E, (byte) 0x06, + (byte) 0x3D, (byte) 0x02, (byte) 0x3D, (byte) 0x95, (byte) 0x57, (byte) 0xB3, + (byte) 0x8A, (byte) 0xE2, (byte) 0x0B, (byte) 0xD3, (byte) 0x9E, (byte) 0x1C, + (byte) 0x13, (byte) 0xDE, (byte) 0x48, (byte) 0xA3, (byte) 0xC2, (byte) 0x11, + (byte) 0xDA, (byte) 0x75, (byte) 0x09, (byte) 0xF6, (byte) 0x92, (byte) 0x0F, + (byte) 0x0F, (byte) 0xA6, (byte) 0xF3, (byte) 0x3E, (byte) 0x04, (byte) 0x16, + (byte) 0x02, (byte) 0x14, (byte) 0x29, (byte) 0x50, (byte) 0xE4, (byte) 0x77, + (byte) 0x4F, (byte) 0xB2, (byte) 0xFF, (byte) 0xFB, (byte) 0x5D, (byte) 0x33, + (byte) 0xC9, (byte) 0x37, (byte) 0xF0, (byte) 0xB5, (byte) 0x8F, (byte) 0xFB, + (byte) 0x0D, (byte) 0x45, (byte) 0xC2, (byte) 0x00 + }; + + private static final BigInteger DSA_KEY_P = new BigInteger("00d218db947cd62ee2073842c41624942fc10f920a444499fc011bf8f38257018de62270a0d6050ff1d0f40ba2e41ed34479744cc1a7a584d8b9dfa385faf2fd440bb1a5828d0692cab4fbdfc2fda7cb6f03b9effd7fbcb31da4e87da2cf623506c8fee6e76eae22e782385482cdead869bb1cd37032b1fb070166cc24d650469b", 16); + private static final BigInteger DSA_KEY_Q = new BigInteger("00d6e67e1ae5ca1db6af4ed918e887b1bc93e180f5", 16); + private static final BigInteger DSA_KEY_G = new BigInteger("1920cc18f68f73fa9f50c892be077c34d86f63c93548797926ef1e9954d7302c68bcfff24c6ad32d1c7a061172929caa950e442c5f1925b4bf218fb77e4b64835920203684a41db5ca7f104e27218e2ca5f8acbdf5b5baeb866f7fb1e09035caa8646e063d023d9557b38ae20bd39e1c13de48a3c211da7509f6920f0fa6f33e", 16); + + private static final BigInteger DSA_KEY_priv = new BigInteger("2950e4774fb2fffb5d33c937f0b58ffb0d45c200", 16); + private static final BigInteger DSA_KEY_pub = new BigInteger("0087b82cdf3232db3bec0d00e96c8393bc7f5629551ea1a00888961cf56e80a36f2a7b316bc10b1d367a5ea374235c9361a472a9176f6cf61f708b86a52b4fae814abd1f1bdd16eea94aea9281851032b1bad7567624c615d6899ca1c94ad614f14e767e49d2ba5223cd113a0d02b66183653cd346ae76d85843afe66520904274", 16); + + @Test + public void getOidFromPkcs8Encoded_Ec_NistP256() throws Exception { + assertEquals("1.2.840.10045.2.1", PubkeyUtils.getOidFromPkcs8Encoded(EC_KEY_PKCS8)); + } + + @Test + public void getOidFromPkcs8Encoded_Rsa() throws Exception { + assertEquals("1.2.840.113549.1.1.1", PubkeyUtils.getOidFromPkcs8Encoded(RSA_KEY_PKCS8)); + } + + @Test + public void getOidFromPkcs8Encoded_Dsa() throws Exception { + assertEquals("1.2.840.10040.4.1", PubkeyUtils.getOidFromPkcs8Encoded(DSA_KEY_PKCS8)); + } + + @Test + public void getOidFromPkcs8Encoded_Null_Failure() throws Exception { + try { + PubkeyUtils.getOidFromPkcs8Encoded(null); + fail("Should throw NoSuchAlgorithmException"); + } catch (NoSuchAlgorithmException expected) { + } + } + + @Test + public void getOidFromPkcs8Encoded_NotCorrectDer_Failure() throws Exception { + try { + PubkeyUtils.getOidFromPkcs8Encoded(new byte[] { 0x30, 0x01, 0x00 }); + fail("Should throw NoSuchAlgorithmException"); + } catch (NoSuchAlgorithmException expected) { + } + } + + @Test + public void getAlgorithmForOid_Ecdsa() throws Exception { + assertEquals("EC", PubkeyUtils.getAlgorithmForOid("1.2.840.10045.2.1")); + } + + @Test + public void getAlgorithmForOid_Rsa() throws Exception { + assertEquals("RSA", PubkeyUtils.getAlgorithmForOid("1.2.840.113549.1.1.1")); + } + + public void getAlgorithmForOid_Dsa() throws Exception { + assertEquals("DSA", PubkeyUtils.getAlgorithmForOid("1.2.840.10040.4.1")); + } + + @Test + public void getAlgorithmForOid_NullInput_Failure() throws Exception { + try { + PubkeyUtils.getAlgorithmForOid(null); + fail("Should throw NoSuchAlgorithmException"); + } catch (NoSuchAlgorithmException expected) { + } + } + + @Test + public void getAlgorithmForOid_UnknownOid_Failure() throws Exception { + try { + PubkeyUtils.getAlgorithmForOid("1.3.66666.2000.4000.1"); + fail("Should throw NoSuchAlgorithmException"); + } catch (NoSuchAlgorithmException expected) { + } + } + + @Test + public void recoverKeyPair_Dsa() throws Exception { + KeyPair kp = PubkeyUtils.recoverKeyPair(DSA_KEY_PKCS8); + + DSAPublicKey pubKey = (DSAPublicKey) kp.getPublic(); + + assertEquals(DSA_KEY_pub, pubKey.getY()); + + DSAParams params = pubKey.getParams(); + assertEquals(params.getG(), DSA_KEY_G); + assertEquals(params.getP(), DSA_KEY_P); + assertEquals(params.getQ(), DSA_KEY_Q); + } + + @Test + public void recoverKeyPair_Rsa() throws Exception { + KeyPair kp = PubkeyUtils.recoverKeyPair(RSA_KEY_PKCS8); + + RSAPublicKey pubKey = (RSAPublicKey) kp.getPublic(); + + assertEquals(RSA_KEY_N, pubKey.getModulus()); + assertEquals(RSA_KEY_E, pubKey.getPublicExponent()); + } + + @Test + public void recoverKeyPair_Ec() throws Exception { + KeyPair kp = PubkeyUtils.recoverKeyPair(EC_KEY_PKCS8); + + ECPublicKey pubKey = (ECPublicKey) kp.getPublic(); + + assertEquals(EC_KEY_pub_x, pubKey.getW().getAffineX()); + assertEquals(EC_KEY_pub_y, pubKey.getW().getAffineY()); + } + + private static class MyPrivateKey implements PrivateKey { + public String getAlgorithm() { + throw new UnsupportedOperationException(); + } + + public byte[] getEncoded() { + throw new UnsupportedOperationException(); + } + + public String getFormat() { + throw new UnsupportedOperationException(); + } + } + + @Test + public void recoverPublicKey_FakeKey_Failure() throws Exception { + try { + PubkeyUtils.recoverPublicKey(null, new MyPrivateKey()); + fail("Should not accept unknown key types"); + } catch (NoSuchAlgorithmException expected) { + } + } +} diff --git a/settings.gradle b/settings.gradle index e7b4def..61ac55a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':app' +include ':app', ':robolectric-tests' -- cgit v1.2.3