mirror of
https://github.com/syncthing/syncthing-android.git
synced 2024-11-22 20:31:16 +00:00
Various test enhancements:
- added SyncthingServiceTest - removed permanent notification from SyncthingService (didn't work with unit test) - renamed TestContext to MockContext - added MockRestApi
This commit is contained in:
parent
feaaf4c5da
commit
ffefe46eed
19 changed files with 359 additions and 111 deletions
|
@ -3,11 +3,8 @@ package com.nutomic.syncthingandroid.test;
|
|||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.test.mock.MockContext;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
@ -16,9 +13,7 @@ import java.util.List;
|
|||
/**
|
||||
* Context that saves all received intents, which can be retrieved later by test classes.
|
||||
*/
|
||||
public class TestContext extends MockContext {
|
||||
|
||||
private Context mContext;
|
||||
public class MockContext extends ContextWrapper {
|
||||
|
||||
private ArrayList<Intent> mReceivedIntents = new ArrayList<>();
|
||||
|
||||
|
@ -26,8 +21,8 @@ public class TestContext extends MockContext {
|
|||
* Use the actual context for calls that aren't easily mocked. May be null if those
|
||||
* calls aren't needed.
|
||||
*/
|
||||
public TestContext(Context context) {
|
||||
mContext = context;
|
||||
public MockContext(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,11 +30,6 @@ public class TestContext extends MockContext {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSystemService(String name) {
|
||||
return mContext.getSystemService(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentName startService(Intent intent) {
|
||||
mReceivedIntents.add(intent);
|
||||
|
@ -67,13 +57,9 @@ public class TestContext extends MockContext {
|
|||
|
||||
@Override
|
||||
public File getFilesDir() {
|
||||
File testFilesDir = new File(mContext.getFilesDir(), "test/");
|
||||
File testFilesDir = new File(super.getFilesDir(), "test/");
|
||||
testFilesDir.mkdir();
|
||||
return testFilesDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resources getResources() {
|
||||
return mContext.getResources();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package com.nutomic.syncthingandroid.test;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import com.nutomic.syncthingandroid.syncthing.RestApi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MockRestApi extends RestApi {
|
||||
|
||||
public MockRestApi(Context context, String url, OnApiAvailableListener listener) {
|
||||
super(context, url, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApiKey(String apiKey) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWebGuiAvailable() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(String name, String key) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void setValue(String name, String key, T value, boolean isArray, Activity activity) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getNodes() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getSystemInfo(final OnReceiveSystemInfoListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Repo> getRepos() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getConnections(final OnReceiveConnectionsListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getModel(final String repoId, final OnReceiveModelListener listener) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void editNode(final Node node,
|
||||
final OnNodeIdNormalizedListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteNode(Node node, Context context) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean editRepo(Repo repo, boolean create, Context context) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean deleteRepo(Repo repo, Context context) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void normalizeNodeId(String id, final OnNodeIdNormalizedListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
@TargetApi(11)
|
||||
public void copyNodeId(String id) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package com.nutomic.syncthingandroid.test;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
|
||||
|
@ -8,7 +7,6 @@ import com.nutomic.syncthingandroid.syncthing.RestApi;
|
|||
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class MockSyncthingService extends SyncthingService {
|
||||
|
||||
|
@ -51,7 +49,7 @@ public class MockSyncthingService extends SyncthingService {
|
|||
|
||||
@Override
|
||||
public RestApi getApi() {
|
||||
throw new UnsupportedOperationException();
|
||||
return new MockRestApi(this, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -7,18 +7,18 @@ import android.test.suitebuilder.annotation.MediumTest;
|
|||
import com.nutomic.syncthingandroid.syncthing.BatteryReceiver;
|
||||
import com.nutomic.syncthingandroid.syncthing.DeviceStateHolder;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
||||
import com.nutomic.syncthingandroid.test.TestContext;
|
||||
import com.nutomic.syncthingandroid.test.MockContext;
|
||||
|
||||
public class BatteryReceiverTest extends AndroidTestCase {
|
||||
|
||||
private BatteryReceiver mReceiver;
|
||||
private TestContext mContext;
|
||||
private MockContext mContext;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mReceiver = new BatteryReceiver();
|
||||
mContext = new TestContext(null);
|
||||
mContext = new MockContext(null);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
|
|
|
@ -6,7 +6,7 @@ import android.test.suitebuilder.annotation.MediumTest;
|
|||
|
||||
import com.nutomic.syncthingandroid.syncthing.BootReceiver;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
||||
import com.nutomic.syncthingandroid.test.TestContext;
|
||||
import com.nutomic.syncthingandroid.test.MockContext;
|
||||
|
||||
/**
|
||||
* Tests that {@link com.nutomic.syncthingandroid.syncthing.BootReceiver} starts the right service
|
||||
|
@ -15,13 +15,13 @@ import com.nutomic.syncthingandroid.test.TestContext;
|
|||
public class BootReceiverTest extends AndroidTestCase {
|
||||
|
||||
private BootReceiver mReceiver;
|
||||
private TestContext mContext;
|
||||
private MockContext mContext;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mReceiver = new BootReceiver();
|
||||
mContext = new TestContext(null);
|
||||
mContext = new MockContext(null);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
|
|
|
@ -4,21 +4,20 @@ import android.content.Intent;
|
|||
import android.os.BatteryManager;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
import com.nutomic.syncthingandroid.syncthing.DeviceStateHolder;
|
||||
import com.nutomic.syncthingandroid.test.TestContext;
|
||||
import com.nutomic.syncthingandroid.test.MockContext;
|
||||
|
||||
public class DeviceStateHolderTest extends AndroidTestCase {
|
||||
|
||||
private DeviceStateHolder mReceiver;
|
||||
private TestContext mContext;
|
||||
private MockContext mContext;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mReceiver = new DeviceStateHolder(getContext());
|
||||
mContext = new TestContext(null);
|
||||
mContext = new MockContext(null);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
|
|
|
@ -3,7 +3,6 @@ package com.nutomic.syncthingandroid.test.syncthing;
|
|||
import android.net.Uri;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
import android.util.Log;
|
||||
|
||||
import com.nutomic.syncthingandroid.syncthing.GetTask;
|
||||
import com.nutomic.syncthingandroid.syncthing.RestApi;
|
||||
|
|
|
@ -4,10 +4,10 @@ import android.content.Intent;
|
|||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
|
||||
import com.nutomic.syncthingandroid.syncthing.NetworkReceiver;
|
||||
import com.nutomic.syncthingandroid.syncthing.DeviceStateHolder;
|
||||
import com.nutomic.syncthingandroid.syncthing.NetworkReceiver;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
||||
import com.nutomic.syncthingandroid.test.TestContext;
|
||||
import com.nutomic.syncthingandroid.test.MockContext;
|
||||
|
||||
/**
|
||||
* Tests for correct extras on the Intent sent by
|
||||
|
@ -19,13 +19,13 @@ import com.nutomic.syncthingandroid.test.TestContext;
|
|||
public class NetworkReceiverTest extends AndroidTestCase {
|
||||
|
||||
private NetworkReceiver mReceiver;
|
||||
private TestContext mContext;
|
||||
private MockContext mContext;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mReceiver = new NetworkReceiver();
|
||||
mContext = new TestContext(getContext());
|
||||
mContext = new MockContext(getContext());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
|
|
|
@ -4,10 +4,9 @@ import android.test.AndroidTestCase;
|
|||
|
||||
import com.nutomic.syncthingandroid.syncthing.PollWebGuiAvailableTask;
|
||||
import com.nutomic.syncthingandroid.syncthing.PostTask;
|
||||
import com.nutomic.syncthingandroid.syncthing.RestApi;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingRunnable;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
||||
import com.nutomic.syncthingandroid.test.TestContext;
|
||||
import com.nutomic.syncthingandroid.test.MockContext;
|
||||
import com.nutomic.syncthingandroid.util.ConfigXml;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
@ -23,7 +22,7 @@ public class PollWebGuiAvailableTaskTest extends AndroidTestCase {
|
|||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
mConfig = new ConfigXml(new TestContext(getContext()));
|
||||
mConfig = new ConfigXml(new MockContext(getContext()));
|
||||
mConfig.updateIfNeeded();
|
||||
}
|
||||
|
||||
|
@ -31,11 +30,11 @@ public class PollWebGuiAvailableTaskTest extends AndroidTestCase {
|
|||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
|
||||
ConfigXml.getConfigFile(new TestContext(getContext())).delete();
|
||||
ConfigXml.getConfigFile(new MockContext(getContext())).delete();
|
||||
}
|
||||
|
||||
public void testPolling() throws InterruptedException {
|
||||
mSyncthing = new SyncthingRunnable(new TestContext(null),
|
||||
mSyncthing = new SyncthingRunnable(new MockContext(null),
|
||||
getContext().getApplicationInfo().dataDir + "/" + SyncthingService.BINARY_NAME);
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
|
|
|
@ -3,7 +3,6 @@ package com.nutomic.syncthingandroid.test.syncthing;
|
|||
import android.net.Uri;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
import android.util.Log;
|
||||
|
||||
import com.nutomic.syncthingandroid.syncthing.GetTask;
|
||||
import com.nutomic.syncthingandroid.syncthing.PostTask;
|
||||
|
|
|
@ -10,7 +10,7 @@ import com.nutomic.syncthingandroid.syncthing.PostTask;
|
|||
import com.nutomic.syncthingandroid.syncthing.RestApi;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingRunnable;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
||||
import com.nutomic.syncthingandroid.test.TestContext;
|
||||
import com.nutomic.syncthingandroid.test.MockContext;
|
||||
import com.nutomic.syncthingandroid.util.ConfigXml;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -30,10 +30,10 @@ public class RestApiTest extends AndroidTestCase {
|
|||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
mSyncthing = new SyncthingRunnable(new TestContext(null),
|
||||
mSyncthing = new SyncthingRunnable(new MockContext(null),
|
||||
getContext().getApplicationInfo().dataDir + "/" + SyncthingService.BINARY_NAME);
|
||||
|
||||
mConfig = new ConfigXml(new TestContext(getContext()));
|
||||
mConfig = new ConfigXml(new MockContext(getContext()));
|
||||
mConfig.createCameraRepo();
|
||||
mConfig.updateIfNeeded();
|
||||
|
||||
|
@ -69,7 +69,7 @@ public class RestApiTest extends AndroidTestCase {
|
|||
}
|
||||
}.execute(mConfig.getWebGuiUrl(), PostTask.URI_SHUTDOWN, mSyncthing.getApiKey());
|
||||
latch.await(1, TimeUnit.SECONDS);
|
||||
ConfigXml.getConfigFile(new TestContext(getContext())).delete();
|
||||
ConfigXml.getConfigFile(new MockContext(getContext())).delete();
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
|
|
|
@ -4,7 +4,7 @@ import android.test.AndroidTestCase;
|
|||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingRunnable;
|
||||
import com.nutomic.syncthingandroid.test.TestContext;
|
||||
import com.nutomic.syncthingandroid.test.MockContext;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
@ -12,7 +12,7 @@ public class SyncthingRunnableTest extends AndroidTestCase {
|
|||
|
||||
@SmallTest
|
||||
public void testRunning() throws InterruptedException {
|
||||
TestContext context = new TestContext(getContext());
|
||||
MockContext context = new MockContext(getContext());
|
||||
File testFile = new File(context.getFilesDir(), "was_running");
|
||||
assertFalse(testFile.exists());
|
||||
// Inject a differenct command instead of the syncthing binary for testing.
|
||||
|
@ -23,7 +23,7 @@ public class SyncthingRunnableTest extends AndroidTestCase {
|
|||
|
||||
@SmallTest
|
||||
public void testApiKey() {
|
||||
SyncthingRunnable st = new SyncthingRunnable(new TestContext(getContext()), "ls\n");
|
||||
SyncthingRunnable st = new SyncthingRunnable(new MockContext(getContext()), "ls\n");
|
||||
assertEquals(20, st.getApiKey().length());
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
package com.nutomic.syncthingandroid.test.syncthing;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.test.ServiceTestCase;
|
||||
import android.test.suitebuilder.annotation.LargeTest;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
import com.nutomic.syncthingandroid.syncthing.DeviceStateHolder;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingServiceBinder;
|
||||
import com.nutomic.syncthingandroid.test.MockContext;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* FIXME: There are some problems with shutting down the service after tests. It may be that the
|
||||
* service remains running after short tests. As a workaround, kill the app in Android.
|
||||
* NOTE: It seems that @link #tearDown()} is not executed if a test fails, so the test data folder
|
||||
* is not deleted (which may cause following tests to fail).
|
||||
*/
|
||||
public class SyncthingServiceTest extends ServiceTestCase<SyncthingService> {
|
||||
|
||||
private Context mContext;
|
||||
|
||||
public SyncthingServiceTest() {
|
||||
super(SyncthingService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mContext = new MockContext(getContext());
|
||||
setContext(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
deleteRecursive(getContext().getFilesDir());
|
||||
PreferenceManager.getDefaultSharedPreferences(getContext()).edit().clear().commit();
|
||||
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
private void deleteRecursive(File file) {
|
||||
if (file.isDirectory()) {
|
||||
for (File f : file.listFiles()) {
|
||||
deleteRecursive(f);
|
||||
}
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
|
||||
@LargeTest
|
||||
public void testStartService() throws InterruptedException {
|
||||
startService(new Intent(mContext, SyncthingService.class));
|
||||
final CountDownLatch latch = new CountDownLatch(2);
|
||||
getService().registerOnWebGuiAvailableListener(new SyncthingService.OnWebGuiAvailableListener() {
|
||||
@Override
|
||||
public void onWebGuiAvailable() {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
getService().registerOnApiChangeListener(new SyncthingService.OnApiChangeListener() {
|
||||
@Override
|
||||
public void onApiChange(SyncthingService.State currentState) {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
latch.await(1, TimeUnit.SECONDS);
|
||||
assertNotNull(getService().getApi());
|
||||
assertNotNull(getService().getWebGuiUrl());
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testFirstStart() {
|
||||
startService(new Intent(mContext, SyncthingService.class));
|
||||
assertTrue(getService().isFirstStart());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testNotFirstStart() throws IOException {
|
||||
startService(new Intent(mContext, SyncthingService.class));
|
||||
new File(mContext.getFilesDir(), SyncthingService.PUBLIC_KEY_FILE).createNewFile();
|
||||
assertFalse(getService().isFirstStart());
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testBindService() throws InterruptedException {
|
||||
SyncthingServiceBinder binder = (SyncthingServiceBinder)
|
||||
bindService(new Intent(mContext, SyncthingService.class));
|
||||
SyncthingService service = binder.getService();
|
||||
final CountDownLatch latch = new CountDownLatch(2);
|
||||
getService().registerOnWebGuiAvailableListener(new SyncthingService.OnWebGuiAvailableListener() {
|
||||
@Override
|
||||
public void onWebGuiAvailable() {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
getService().registerOnApiChangeListener(new SyncthingService.OnApiChangeListener() {
|
||||
@Override
|
||||
public void onApiChange(SyncthingService.State currentState) {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
latch.await(1, TimeUnit.SECONDS);
|
||||
assertNotNull(service);
|
||||
}
|
||||
|
||||
private class Listener implements SyncthingService.OnApiChangeListener {
|
||||
|
||||
private SyncthingService.State mLastState;
|
||||
|
||||
@Override
|
||||
public void onApiChange(SyncthingService.State currentState) {
|
||||
mLastState = currentState;
|
||||
}
|
||||
|
||||
public SyncthingService.State getLastState() {
|
||||
return mLastState;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Listener mListener = new Listener();
|
||||
|
||||
@MediumTest
|
||||
public void testStatesAllRequired() throws InterruptedException {
|
||||
setupStatesTest(true, true);
|
||||
|
||||
assertState(true, true, SyncthingService.State.ACTIVE);
|
||||
assertState(true, false, SyncthingService.State.DISABLED);
|
||||
assertState(false, true, SyncthingService.State.DISABLED);
|
||||
assertState(false, false, SyncthingService.State.DISABLED);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testStatesWifiRequired() throws InterruptedException {
|
||||
setupStatesTest(true, false);
|
||||
|
||||
assertState(true, true, SyncthingService.State.ACTIVE);
|
||||
assertState(true, false, SyncthingService.State.DISABLED);
|
||||
assertState(false, true, SyncthingService.State.ACTIVE);
|
||||
assertState(false, false, SyncthingService.State.DISABLED);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testStatesChargingRequired() throws InterruptedException {
|
||||
setupStatesTest(false, true);
|
||||
|
||||
assertState(true, true, SyncthingService.State.ACTIVE);
|
||||
assertState(true, false, SyncthingService.State.ACTIVE);
|
||||
assertState(false, true, SyncthingService.State.DISABLED);
|
||||
assertState(false, false, SyncthingService.State.DISABLED);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testStatesNoneRequired() throws InterruptedException {
|
||||
setupStatesTest(false, false);
|
||||
|
||||
assertState(true, true, SyncthingService.State.ACTIVE);
|
||||
assertState(true, false, SyncthingService.State.ACTIVE);
|
||||
assertState(false, true, SyncthingService.State.ACTIVE);
|
||||
assertState(false, false, SyncthingService.State.ACTIVE);
|
||||
}
|
||||
|
||||
public void assertState(boolean charging, boolean wifi, SyncthingService.State expected)
|
||||
throws InterruptedException {
|
||||
Intent i = new Intent(mContext, SyncthingService.class);
|
||||
i.putExtra(DeviceStateHolder.EXTRA_IS_CHARGING, charging);
|
||||
i.putExtra(DeviceStateHolder.EXTRA_HAS_WIFI, wifi);
|
||||
startService(i);
|
||||
// Wait for service to react to preference change.
|
||||
Thread.sleep(7500);
|
||||
assertEquals(expected, mListener.getLastState());
|
||||
}
|
||||
|
||||
public void setupStatesTest(boolean syncOnlyWifi, boolean syncOnlyCharging)
|
||||
throws InterruptedException {
|
||||
PreferenceManager.getDefaultSharedPreferences(getContext()).edit()
|
||||
.putBoolean(SyncthingService.PREF_SYNC_ONLY_WIFI, syncOnlyWifi)
|
||||
.putBoolean(SyncthingService.PREF_SYNC_ONLY_CHARGING, syncOnlyCharging)
|
||||
.commit();
|
||||
// Wait for service to react to preference change.
|
||||
Thread.sleep(1000);
|
||||
startService(new Intent(getContext(), SyncthingService.class));
|
||||
getService().registerOnApiChangeListener(mListener);
|
||||
assertEquals(SyncthingService.State.INIT, mListener.getLastState());
|
||||
}
|
||||
}
|
|
@ -1,21 +1,15 @@
|
|||
package com.nutomic.syncthingandroid.test.util;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
import com.nutomic.syncthingandroid.syncthing.RestApi;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingRunnable;
|
||||
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
|
||||
import com.nutomic.syncthingandroid.test.TestContext;
|
||||
import com.nutomic.syncthingandroid.test.MockContext;
|
||||
import com.nutomic.syncthingandroid.util.ConfigXml;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ConfigXmlTest extends AndroidTestCase {
|
||||
|
||||
private TestContext mContext;
|
||||
private MockContext mContext;
|
||||
|
||||
private ConfigXml mConfig;
|
||||
|
||||
|
@ -23,7 +17,7 @@ public class ConfigXmlTest extends AndroidTestCase {
|
|||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
mContext = new TestContext(getContext());
|
||||
mContext = new MockContext(getContext());
|
||||
assertFalse(ConfigXml.getConfigFile(mContext).exists());
|
||||
mConfig = new ConfigXml(mContext);
|
||||
assertTrue(ConfigXml.getConfigFile(mContext).exists());
|
||||
|
|
|
@ -7,11 +7,8 @@ import android.widget.TextView;
|
|||
|
||||
import com.nutomic.syncthingandroid.R;
|
||||
import com.nutomic.syncthingandroid.syncthing.RestApi;
|
||||
import com.nutomic.syncthingandroid.test.TestContext;
|
||||
import com.nutomic.syncthingandroid.util.NodesAdapter;
|
||||
import com.nutomic.syncthingandroid.util.ReposAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import android.widget.TextView;
|
|||
|
||||
import com.nutomic.syncthingandroid.R;
|
||||
import com.nutomic.syncthingandroid.syncthing.RestApi;
|
||||
import com.nutomic.syncthingandroid.test.TestContext;
|
||||
import com.nutomic.syncthingandroid.util.ReposAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
|
@ -146,15 +146,13 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener {
|
|||
|
||||
private String mLocalNodeId;
|
||||
|
||||
private final NotificationManager mNotificationManager;
|
||||
|
||||
private boolean mRestartPostponed = false;
|
||||
|
||||
/**
|
||||
* Stores the result of the last successful request to {@link GetTask#URI_CONNECTIONS},
|
||||
* or an empty HashMap.
|
||||
*/
|
||||
private HashMap<String, Connection> mPreviousConnections = new HashMap<String, Connection>();
|
||||
private HashMap<String, Connection> mPreviousConnections = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Stores the timestamp of the last successful request to {@link GetTask#URI_CONNECTIONS}.
|
||||
|
@ -170,8 +168,6 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener {
|
|||
public RestApi(Context context, String url, OnApiAvailableListener listener) {
|
||||
mContext = context;
|
||||
mUrl = url;
|
||||
mNotificationManager = (NotificationManager)
|
||||
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
mOnApiAvailableListener = listener;
|
||||
}
|
||||
|
||||
|
@ -257,7 +253,13 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener {
|
|||
* Stops syncthing. You should probably use SyncthingService.stopService() instead.
|
||||
*/
|
||||
public void shutdown() {
|
||||
mNotificationManager.cancel(NOTIFICATION_RESTART);
|
||||
// Happens in unit tests.
|
||||
if (mContext == null)
|
||||
return;
|
||||
|
||||
NotificationManager nm = (NotificationManager)
|
||||
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
nm.cancel(NOTIFICATION_RESTART);
|
||||
new PostTask().execute(mUrl, PostTask.URI_SHUTDOWN, mApiKey);
|
||||
}
|
||||
|
||||
|
@ -371,7 +373,9 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener {
|
|||
.setContentIntent(pi)
|
||||
.build();
|
||||
n.flags |= Notification.FLAG_ONLY_ALERT_ONCE | Notification.FLAG_AUTO_CANCEL;
|
||||
mNotificationManager.notify(NOTIFICATION_RESTART, n);
|
||||
NotificationManager nm = (NotificationManager)
|
||||
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
nm.notify(NOTIFICATION_RESTART, n);
|
||||
mRestartPostponed = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,6 @@ package com.nutomic.syncthingandroid.syncthing;
|
|||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
|
@ -12,25 +10,14 @@ import android.content.SharedPreferences;
|
|||
import android.os.AsyncTask;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.nutomic.syncthingandroid.R;
|
||||
import com.nutomic.syncthingandroid.activities.MainActivity;
|
||||
import com.nutomic.syncthingandroid.activities.SettingsActivity;
|
||||
import com.nutomic.syncthingandroid.util.ConfigXml;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpHead;
|
||||
import org.apache.http.conn.HttpHostConnectException;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
@ -42,8 +29,6 @@ public class SyncthingService extends Service {
|
|||
|
||||
private static final String TAG = "SyncthingService";
|
||||
|
||||
private static final int NOTIFICATION_RUNNING = 1;
|
||||
|
||||
/**
|
||||
* Intent action to perform a syncthing restart.
|
||||
*/
|
||||
|
@ -57,7 +42,7 @@ public class SyncthingService extends Service {
|
|||
/**
|
||||
* Name of the public key file in the data directory.
|
||||
*/
|
||||
private static final String PUBLIC_KEY_FILE = "cert.pem";
|
||||
public static final String PUBLIC_KEY_FILE = "cert.pem";
|
||||
|
||||
/**
|
||||
* Name of the private key file in the data directory.
|
||||
|
@ -69,6 +54,10 @@ public class SyncthingService extends Service {
|
|||
*/
|
||||
public static final String BINARY_NAME = "lib/libsyncthing.so";
|
||||
|
||||
public static final String PREF_SYNC_ONLY_WIFI = "stop_sync_on_mobile_data";
|
||||
|
||||
public static final String PREF_SYNC_ONLY_CHARGING = "stop_sync_while_not_charging";
|
||||
|
||||
private ConfigXml mConfig;
|
||||
|
||||
private RestApi mApi;
|
||||
|
@ -143,14 +132,14 @@ public class SyncthingService extends Service {
|
|||
/**
|
||||
* Checks according to preferences and charging/wifi state, whether syncthing should be enabled
|
||||
* or not.
|
||||
* <p/>
|
||||
*
|
||||
* Depending on the result, syncthing is started or stopped, and {@link #onApiChange()} is
|
||||
* called.
|
||||
*/
|
||||
public void updateState() {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
boolean prefStopMobileData = prefs.getBoolean("stop_sync_on_mobile_data", true);
|
||||
boolean prefStopNotCharging = prefs.getBoolean("stop_sync_while_not_charging", true);
|
||||
boolean prefStopMobileData = prefs.getBoolean(PREF_SYNC_ONLY_WIFI, true);
|
||||
boolean prefStopNotCharging = prefs.getBoolean(PREF_SYNC_ONLY_CHARGING, true);
|
||||
|
||||
// Start syncthing.
|
||||
if ((mDeviceStateHolder.isCharging() || !prefStopNotCharging) &&
|
||||
|
@ -187,7 +176,7 @@ public class SyncthingService extends Service {
|
|||
|
||||
/**
|
||||
* Move config file, keys, and index files to "official" folder
|
||||
* <p/>
|
||||
*
|
||||
* Intended to bring the file locations in older installs in line with
|
||||
* newer versions.
|
||||
*/
|
||||
|
@ -221,18 +210,6 @@ public class SyncthingService extends Service {
|
|||
*/
|
||||
@Override
|
||||
public void onCreate() {
|
||||
PendingIntent pi = PendingIntent.getActivity(
|
||||
this, 0, new Intent(this, MainActivity.class),
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
Notification n = new NotificationCompat.Builder(this)
|
||||
.setContentTitle(getString(R.string.app_name))
|
||||
.setSmallIcon(R.drawable.ic_launcher)
|
||||
.setContentIntent(pi)
|
||||
.setPriority(NotificationCompat.PRIORITY_MIN)
|
||||
.build();
|
||||
n.flags |= Notification.FLAG_ONGOING_EVENT;
|
||||
startForeground(NOTIFICATION_RUNNING, n);
|
||||
|
||||
mDeviceStateHolder = new DeviceStateHolder(SyncthingService.this);
|
||||
registerReceiver(mDeviceStateHolder, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
new StartupTask().execute();
|
||||
|
@ -240,8 +217,7 @@ public class SyncthingService extends Service {
|
|||
|
||||
/**
|
||||
* Sets up the initial configuration, updates the config when coming from an old
|
||||
* version, and reads syncthing URL and API key (these are passed internally as
|
||||
* {@code Pair<String, String>}. TODO
|
||||
* version, and reads syncthing URL..
|
||||
*/
|
||||
private class StartupTask extends AsyncTask<Void, Void, String> {
|
||||
@Override
|
||||
|
@ -272,7 +248,7 @@ public class SyncthingService extends Service {
|
|||
Log.i(TAG, "Web GUI will be available at " + mConfig.getWebGuiUrl());
|
||||
|
||||
// HACK: Make sure there is no syncthing binary left running from an improper
|
||||
// shutdown (eg Play Store updateIfNeeded).
|
||||
// shutdown (eg Play Store update).
|
||||
// NOTE: This will log an exception if syncthing is not actually running.
|
||||
mApi.shutdown();
|
||||
updateState();
|
||||
|
@ -291,12 +267,14 @@ public class SyncthingService extends Service {
|
|||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
Log.i(TAG, "Shutting down service");
|
||||
mApi.shutdown();
|
||||
if (mApi != null) {
|
||||
mApi.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a listener for the web gui becoming available..
|
||||
* <p/>
|
||||
*
|
||||
* If the web gui is already available, listener will be called immediately.
|
||||
* Listeners are unregistered automatically after being called.
|
||||
*/
|
||||
|
@ -310,7 +288,7 @@ public class SyncthingService extends Service {
|
|||
|
||||
/**
|
||||
* Returns true if this service has not been started before (ie config.xml does not exist).
|
||||
* <p/>
|
||||
*
|
||||
* This will return true until the public key file has been generated.
|
||||
*/
|
||||
public boolean isFirstStart() {
|
||||
|
@ -323,7 +301,7 @@ public class SyncthingService extends Service {
|
|||
|
||||
/**
|
||||
* Register a listener for the syncthing API state changing.
|
||||
* <p/>
|
||||
*
|
||||
* The listener is called immediately with the current state, and again whenever the state
|
||||
* changes.
|
||||
*/
|
||||
|
@ -331,7 +309,7 @@ public class SyncthingService extends Service {
|
|||
// Make sure we don't send an invalid state or syncthing might shwow a "disabled" message
|
||||
// when it's just starting up.
|
||||
listener.onApiChange(mCurrentState);
|
||||
mOnApiChangeListeners.add(new WeakReference<OnApiChangeListener>(listener));
|
||||
mOnApiChangeListeners.add(new WeakReference<>(listener));
|
||||
}
|
||||
|
||||
private class PollWebGuiAvailableTaskImpl extends PollWebGuiAvailableTask {
|
||||
|
|
|
@ -15,7 +15,6 @@ import java.io.File;
|
|||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
|
Loading…
Reference in a new issue