diff --git a/core/java/src/net/i2p/I2PAppContext.java b/core/java/src/net/i2p/I2PAppContext.java
index 12379505b2..ae0138effc 100644
--- a/core/java/src/net/i2p/I2PAppContext.java
+++ b/core/java/src/net/i2p/I2PAppContext.java
@@ -43,7 +43,7 @@ import net.i2p.util.I2PProperties.I2PPropertyCallback;
* using the traditional singleton, where any component can access the component
* in question directly, all of those I2P related singletons are exposed through
* a particular I2PAppContext. This helps not only with understanding their use
- * and the components I2P exposes, but it also allows multiple isolated
+ * and the components I2P exposes, but it also allows multiple isolated
* environments to operate concurrently within the same JVM - particularly useful
* for stubbing out implementations of the rooted components and simulating the
* software's interaction between multiple instances.
@@ -52,13 +52,13 @@ import net.i2p.util.I2PProperties.I2PPropertyCallback;
* access to one of the singletons but doesn't have its own context from which
* to root itself, it binds to the I2PAppContext's globalAppContext(), which is
* the first context that was created within the JVM, or a new one if no context
- * existed already. This functionality is often used within the I2P core for
+ * existed already. This functionality is often used within the I2P core for
* logging - e.g.
* private static final Log _log = new Log(someClass.class);
*
* It is for this reason that applications that care about working with multiple
* contexts should build their own context as soon as possible (within the main(..))
- * so that any referenced components will latch on to that context instead of
+ * so that any referenced components will latch on to that context instead of
* instantiating a new one. However, there are situations in which both can be
* relevant.
*
@@ -66,9 +66,9 @@ import net.i2p.util.I2PProperties.I2PPropertyCallback;
public class I2PAppContext {
/** the context that components without explicit root are bound */
protected static volatile I2PAppContext _globalAppContext;
-
+
protected final I2PProperties _overrideProps;
-
+
private StatManager _statManager;
protected SessionKeyManager _sessionKeyManager;
private NamingService _namingService;
@@ -121,7 +121,7 @@ public class I2PAppContext {
_lock17 = new Object(), _lock18 = new Object(), _lock19 = new Object(), _lock20 = new Object();
/**
- * Pull the default context, creating a new one if necessary, else using
+ * Pull the default context, creating a new one if necessary, else using
* the first one created.
*
* Warning - do not save the returned value, or the value of any methods below,
@@ -129,7 +129,7 @@ public class I2PAppContext {
* started in the same JVM after the first is shut down,
* e.g. on Android.
*/
- public static I2PAppContext getGlobalContext() {
+ public static I2PAppContext getGlobalContext() {
// skip the global lock - _gAC must be volatile
// http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
I2PAppContext rv = _globalAppContext;
@@ -141,12 +141,12 @@ public class I2PAppContext {
_globalAppContext = new I2PAppContext(false, null);
}
}
- return _globalAppContext;
+ return _globalAppContext;
}
-
+
/**
* Sets the default context, unless there is one already.
- * NOT a public API, for use by RouterContext only, NOT for external use.
+ * NOT a public API, for use by RouterContext and TestContext only, NOT for external use.
*
* @param ctx context constructed with doInit = false
* @return success (false if previously set)
@@ -172,10 +172,10 @@ public class I2PAppContext {
* @return context or null
* @since 0.8.2
*/
- public static I2PAppContext getCurrentContext() {
- return _globalAppContext;
+ public static I2PAppContext getCurrentContext() {
+ return _globalAppContext;
}
-
+
/**
* Create a brand new context.
* WARNING: In almost all cases, you should use getGlobalContext() instead,
@@ -186,7 +186,7 @@ public class I2PAppContext {
public I2PAppContext() {
this(true, null);
}
-
+
/**
* Create a brand new context.
* WARNING: In almost all cases, you should use getGlobalContext() instead,
@@ -197,7 +197,7 @@ public class I2PAppContext {
public I2PAppContext(Properties envProps) {
this(true, envProps);
}
-
+
/**
* Create a brand new context.
* WARNING: In almost all cases, you should use getGlobalContext() instead,
@@ -212,14 +212,14 @@ public class I2PAppContext {
* @since protected since 0.9.33, NOT for external use
*/
protected I2PAppContext(boolean doInit, Properties envProps) {
- synchronized (I2PAppContext.class) {
+ synchronized (I2PAppContext.class) {
_overrideProps = new I2PProperties();
if (envProps != null)
_overrideProps.putAll(envProps);
_shutdownTasks = new ConcurrentHashSet(32);
_portMapper = new PortMapper(this);
_appManager = isRouterContext() ? null : new ClientAppManagerImpl(this);
-
+
/*
* Directories. These are all set at instantiation and will not be changed by
* subsequent property changes.
@@ -449,8 +449,8 @@ public class I2PAppContext {
}
/**
- * Access the configuration attributes of this context, using properties
- * provided during the context construction, or falling back on
+ * Access the configuration attributes of this context, using properties
+ * provided during the context construction, or falling back on
* System.getProperty if no properties were provided during construction
* (or the specified prop wasn't included).
*
@@ -465,8 +465,8 @@ public class I2PAppContext {
}
/**
- * Access the configuration attributes of this context, using properties
- * provided during the context construction, or falling back on
+ * Access the configuration attributes of this context, using properties
+ * provided during the context construction, or falling back on
* System.getProperty if no properties were provided during construction
* (or the specified prop wasn't included).
*
@@ -545,7 +545,7 @@ public class I2PAppContext {
}
/**
- * Access the configuration attributes of this context, listing the properties
+ * Access the configuration attributes of this context, listing the properties
* provided during the context construction, as well as the ones included in
* System.getProperties.
*
@@ -555,29 +555,29 @@ public class I2PAppContext {
* @return set of Strings containing the names of defined system properties
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
- public Set getPropertyNames() {
+ public Set getPropertyNames() {
// clone to avoid ConcurrentModificationException
Set names = new HashSet((Set) (Set) ((Properties) System.getProperties().clone()).keySet()); // TODO-Java6: s/keySet()/stringPropertyNames()/
if (_overrideProps != null)
names.addAll((Set) (Set) _overrideProps.keySet()); // TODO-Java6: s/keySet()/stringPropertyNames()/
return names;
}
-
+
/**
- * Access the configuration attributes of this context, listing the properties
+ * Access the configuration attributes of this context, listing the properties
* provided during the context construction, as well as the ones included in
* System.getProperties.
*
* @return new Properties with system and context properties
* @since 0.8.4
*/
- public Properties getProperties() {
+ public Properties getProperties() {
// clone to avoid ConcurrentModificationException
Properties rv = (Properties) System.getProperties().clone();
rv.putAll(_overrideProps);
return rv;
}
-
+
/**
* Add a callback, which will fire upon changes in the property
* given in the specific callback.
@@ -585,12 +585,12 @@ public class I2PAppContext {
* @param callback The implementation of the callback.
*/
public void addPropertyCallback(I2PPropertyCallback callback) {}
-
+
/**
* The statistics component with which we can track various events
* over time.
*/
- public StatManager statManager() {
+ public StatManager statManager() {
if (!_statManagerInitialized)
initializeStatManager();
return _statManager;
@@ -603,10 +603,10 @@ public class I2PAppContext {
_statManagerInitialized = true;
}
}
-
+
/**
* The session key manager which coordinates the sessionKey / sessionTag
- * data. This component allows transparent operation of the
+ * data. This component allows transparent operation of the
* ElGamal/AES+SessionTag algorithm, and contains all of the session tags
* for one particular application.
*
@@ -620,7 +620,7 @@ public class I2PAppContext {
* The dummy SKM does NOT handle session tags.
* Overridden in RouterContext to return the full TransientSessionKeyManager.
*/
- public SessionKeyManager sessionKeyManager() {
+ public SessionKeyManager sessionKeyManager() {
if (!_sessionKeyManagerInitialized)
initializeSessionKeyManager();
return _sessionKeyManager;
@@ -628,19 +628,19 @@ public class I2PAppContext {
protected void initializeSessionKeyManager() {
synchronized (_lock3) {
- if (_sessionKeyManager == null)
+ if (_sessionKeyManager == null)
//_sessionKeyManager = new PersistentSessionKeyManager(this);
_sessionKeyManager = new SessionKeyManager(this);
_sessionKeyManagerInitialized = true;
}
}
-
+
/**
* Pull up the naming service used in this context. The naming service itself
- * works by querying the context's properties, so those props should be
+ * works by querying the context's properties, so those props should be
* specified to customize the naming service exposed.
*/
- public NamingService namingService() {
+ public NamingService namingService() {
if (!_namingServiceInitialized)
initializeNamingService();
return _namingService;
@@ -654,7 +654,7 @@ public class I2PAppContext {
_namingServiceInitialized = true;
}
}
-
+
/**
* This is the ElGamal engine used within this context. While it doesn't
* really have anything substantial that is context specific (the algorithm
@@ -680,7 +680,7 @@ public class I2PAppContext {
/**
* Ok, I'll admit it. there is no good reason for having a context specific
* AES engine. We dont really keep stats on it, since its just too fast to
- * matter. Though for the crazy people out there, we do expose a way to
+ * matter. Though for the crazy people out there, we do expose a way to
* disable it.
*/
public AESEngine aes() {
@@ -697,14 +697,14 @@ public class I2PAppContext {
_AESEngineInitialized = true;
}
}
-
+
/**
* Query the log manager for this context, which may in turn have its own
- * set of configuration settings (loaded from the context's properties).
+ * set of configuration settings (loaded from the context's properties).
* Each context's logManager keeps its own isolated set of Log instances with
* their own log levels, output locations, and rotation configuration.
*/
- public LogManager logManager() {
+ public LogManager logManager() {
if (!_logManagerInitialized)
initializeLogManager();
return _logManager;
@@ -751,12 +751,12 @@ public class I2PAppContext {
_hmac256Initialized = true;
}
}
-
+
/**
* Our SHA256 instance (see the hmac discussion for why its context specific)
*
*/
- public SHA256Generator sha() {
+ public SHA256Generator sha() {
if (!_shaInitialized)
initializeSHA();
return _sha;
@@ -769,12 +769,12 @@ public class I2PAppContext {
_shaInitialized = true;
}
}
-
+
/**
* Our DSA engine (see HMAC and SHA above)
*
*/
- public DSAEngine dsa() {
+ public DSAEngine dsa() {
if (!_dsaInitialized)
initializeDSA();
return _dsa;
@@ -787,7 +787,7 @@ public class I2PAppContext {
_dsaInitialized = true;
}
}
-
+
/**
* Component to generate ElGamal, DSA, and Session keys. For why it is in
* the appContext, see the DSA, HMAC, and SHA comments above.
@@ -805,7 +805,7 @@ public class I2PAppContext {
_keyGeneratorInitialized = true;
}
}
-
+
/**
* The context's synchronized clock, which is kept context specific only to
* enable simulators to play with clock skew among different instances.
@@ -824,11 +824,11 @@ public class I2PAppContext {
_clockInitialized = true;
}
}
-
+
/**
- * Determine how much do we want to mess with the keys to turn them
- * into something we can route. This is context specific because we
- * may want to test out how things react when peers don't agree on
+ * Determine how much do we want to mess with the keys to turn them
+ * into something we can route. This is context specific because we
+ * may want to test out how things react when peers don't agree on
* how to skew.
*
* As of 0.9.16, returns null in I2PAppContext.
@@ -839,7 +839,7 @@ public class I2PAppContext {
public RoutingKeyGenerator routingKeyGenerator() {
return null;
}
-
+
/**
* Basic hash map
*/
@@ -856,7 +856,7 @@ public class I2PAppContext {
_keyRingInitialized = true;
}
}
-
+
/**
* [insert snarky comment here]
*
@@ -886,7 +886,7 @@ public class I2PAppContext {
public void addShutdownTask(Runnable task) {
_shutdownTasks.add(task);
}
-
+
/**
* @return an unmodifiable Set
* @since 0.7.1
@@ -894,7 +894,7 @@ public class I2PAppContext {
public Set getShutdownTasks() {
return Collections.unmodifiableSet(_shutdownTasks);
}
-
+
/**
* Use this instead of context instanceof RouterContext
* @since 0.7.9
@@ -1007,7 +1007,7 @@ public class I2PAppContext {
return _appManager;
}
- /**
+ /**
* How long this router was down before it started, or 0 if unknown.
*
* This may be used for a determination of whether to regenerate keys, for example.
diff --git a/core/java/test/junit/net/i2p/CoreTestBase.java b/core/java/test/junit/net/i2p/CoreTestBase.java
new file mode 100644
index 0000000000..4914072216
--- /dev/null
+++ b/core/java/test/junit/net/i2p/CoreTestBase.java
@@ -0,0 +1,18 @@
+package net.i2p;
+
+import org.junit.BeforeClass;
+
+/**
+ * Base class for JUnit tests that need to use
+ * a TestContext
+ */
+public class CoreTestBase {
+
+ protected static TestContext testContext;
+
+ @BeforeClass
+ public static void setupContext() {
+ testContext = new TestContext();
+ testContext = (TestContext) I2PAppContext.getGlobalContext();
+ }
+}
diff --git a/core/java/test/junit/net/i2p/TestContext.java b/core/java/test/junit/net/i2p/TestContext.java
new file mode 100644
index 0000000000..364a8f5df2
--- /dev/null
+++ b/core/java/test/junit/net/i2p/TestContext.java
@@ -0,0 +1,19 @@
+package net.i2p;
+
+import net.i2p.client.naming.NamingService;
+
+public class TestContext extends I2PAppContext {
+
+ public TestContext() {
+ I2PAppContext.setGlobalContext(this);
+ }
+
+ // add more subsystems here
+ public NamingService namingService;
+
+ // override more subsystem getters here
+ @Override
+ public NamingService namingService() {
+ return namingService;
+ }
+}
diff --git a/core/java/test/junit/net/i2p/util/ConvertToHashMockTest.java b/core/java/test/junit/net/i2p/util/ConvertToHashMockTest.java
new file mode 100644
index 0000000000..b75a49c0a5
--- /dev/null
+++ b/core/java/test/junit/net/i2p/util/ConvertToHashMockTest.java
@@ -0,0 +1,38 @@
+package net.i2p.util;
+
+import net.i2p.CoreTestBase;
+import net.i2p.client.naming.NamingService;
+import net.i2p.data.Destination;
+import net.i2p.data.Hash;
+import org.junit.Before;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static org.mockito.Mockito.*;
+import static org.junit.Assert.*;
+
+public class ConvertToHashMockTest extends CoreTestBase {
+
+ @Mock private NamingService namingService;
+ @Mock private Destination destination;
+ @Mock private Hash hash;
+
+ @Before
+ public void before() {
+ MockitoAnnotations.initMocks(this);
+ testContext.namingService = namingService;
+ }
+
+ @Test
+ public void testMockedDestination() {
+ when(namingService.lookup("zzz.i2p")).thenReturn(destination);
+ when(destination.calculateHash()).thenReturn(hash);
+
+ assertSame(hash, ConvertToHash.getHash("zzz.i2p"));
+
+ verify(namingService).lookup("zzz.i2p");
+ verify(destination).calculateHash();
+ }
+}