From b0b4a85d15a1f62755229721484845eaebc10c1e Mon Sep 17 00:00:00 2001
From: Torsten Grote <t@grobox.de>
Date: Mon, 10 Apr 2017 18:58:46 -0300
Subject: [PATCH] Add integration test for FeedManager

Attention: This factors out a DnsModule to be able to make actual
non-Tor DNS lookups for testing.
---
 .../bramble/test/TestSocksModule.java         |  16 +++
 .../briarproject/briar/BriarCoreModule.java   |   2 +
 .../briarproject/briar/feed/DnsModule.java    |  18 +++
 .../briar/feed/FeedManagerImpl.java           |  20 +--
 .../org/briarproject/briar/feed/NoDns.java    |  28 +++++
 .../feed/FeedManagerIntegrationTest.java      | 119 ++++++++++++++++++
 .../FeedManagerIntegrationTestComponent.java  |  79 ++++++++++++
 .../briar/test/TestDnsModule.java             |  15 +++
 8 files changed, 281 insertions(+), 16 deletions(-)
 create mode 100644 bramble-core/src/test/java/org/briarproject/bramble/test/TestSocksModule.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/feed/DnsModule.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/feed/NoDns.java
 create mode 100644 briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTest.java
 create mode 100644 briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java
 create mode 100644 briar-core/src/test/java/org/briarproject/briar/test/TestDnsModule.java

diff --git a/bramble-core/src/test/java/org/briarproject/bramble/test/TestSocksModule.java b/bramble-core/src/test/java/org/briarproject/bramble/test/TestSocksModule.java
new file mode 100644
index 0000000000..e142a24790
--- /dev/null
+++ b/bramble-core/src/test/java/org/briarproject/bramble/test/TestSocksModule.java
@@ -0,0 +1,16 @@
+package org.briarproject.bramble.test;
+
+import javax.net.SocketFactory;
+
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class TestSocksModule {
+
+	@Provides
+	SocketFactory provideSocketFactory() {
+		return SocketFactory.getDefault();
+	}
+
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/BriarCoreModule.java b/briar-core/src/main/java/org/briarproject/briar/BriarCoreModule.java
index a9a7bfc506..99d5879aa2 100644
--- a/briar-core/src/main/java/org/briarproject/briar/BriarCoreModule.java
+++ b/briar-core/src/main/java/org/briarproject/briar/BriarCoreModule.java
@@ -2,6 +2,7 @@ package org.briarproject.briar;
 
 import org.briarproject.briar.blog.BlogModule;
 import org.briarproject.briar.client.BriarClientModule;
+import org.briarproject.briar.feed.DnsModule;
 import org.briarproject.briar.feed.FeedModule;
 import org.briarproject.briar.forum.ForumModule;
 import org.briarproject.briar.introduction.IntroductionModule;
@@ -16,6 +17,7 @@ import dagger.Module;
 		BlogModule.class,
 		BriarClientModule.class,
 		FeedModule.class,
+		DnsModule.class,
 		ForumModule.class,
 		GroupInvitationModule.class,
 		IntroductionModule.class,
diff --git a/briar-core/src/main/java/org/briarproject/briar/feed/DnsModule.java b/briar-core/src/main/java/org/briarproject/briar/feed/DnsModule.java
new file mode 100644
index 0000000000..dc6cd8a885
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/feed/DnsModule.java
@@ -0,0 +1,18 @@
+package org.briarproject.briar.feed;
+
+import dagger.Module;
+import dagger.Provides;
+import okhttp3.Dns;
+
+/**
+ * This is a dedicated module, so it can be replaced for testing.
+ */
+@Module
+public class DnsModule {
+
+	@Provides
+	Dns provideDns(NoDns noDns) {
+		return noDns;
+	}
+
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/feed/FeedManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/feed/FeedManagerImpl.java
index 969de52a3c..75d8977ea8 100644
--- a/briar-core/src/main/java/org/briarproject/briar/feed/FeedManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/feed/FeedManagerImpl.java
@@ -39,8 +39,6 @@ import org.briarproject.briar.api.feed.FeedManager;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
 import java.security.GeneralSecurityException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -81,7 +79,6 @@ class FeedManagerImpl implements FeedManager, Client, EventListener,
 	private static final Logger LOG =
 			Logger.getLogger(FeedManagerImpl.class.getName());
 
-	private static final byte[] UNSPECIFIED_ADDRESS = new byte[4];
 	private static final int CONNECT_TIMEOUT = 60 * 1000; // Milliseconds
 
 	private final ScheduledExecutorService scheduler;
@@ -94,6 +91,7 @@ class FeedManagerImpl implements FeedManager, Client, EventListener,
 	private final FeedFactory feedFactory;
 	private final SocketFactory torSocketFactory;
 	private final Clock clock;
+	private final Dns noDnsLookups;
 	private final AtomicBoolean fetcherStarted = new AtomicBoolean(false);
 
 	@Inject
@@ -102,7 +100,7 @@ class FeedManagerImpl implements FeedManager, Client, EventListener,
 			ContactGroupFactory contactGroupFactory, ClientHelper clientHelper,
 			BlogManager blogManager, BlogPostFactory blogPostFactory,
 			FeedFactory feedFactory, SocketFactory torSocketFactory,
-			Clock clock) {
+			Clock clock, Dns noDnsLookups) {
 
 		this.scheduler = scheduler;
 		this.ioExecutor = ioExecutor;
@@ -114,6 +112,7 @@ class FeedManagerImpl implements FeedManager, Client, EventListener,
 		this.feedFactory = feedFactory;
 		this.torSocketFactory = torSocketFactory;
 		this.clock = clock;
+		this.noDnsLookups = noDnsLookups;
 	}
 
 	@Override
@@ -374,21 +373,10 @@ class FeedManagerImpl implements FeedManager, Client, EventListener,
 	}
 
 	private InputStream getFeedInputStream(String url) throws IOException {
-		// Don't make local DNS lookups
-		Dns noLookups = new Dns() {
-			@Override
-			public List<InetAddress> lookup(String hostname)
-					throws UnknownHostException {
-				InetAddress unspecified =
-						InetAddress.getByAddress(hostname, UNSPECIFIED_ADDRESS);
-				return Collections.singletonList(unspecified);
-			}
-		};
-
 		// Build HTTP Client
 		OkHttpClient client = new OkHttpClient.Builder()
 				.socketFactory(torSocketFactory)
-				.dns(noLookups)
+				.dns(noDnsLookups) // Don't make local DNS lookups
 				.connectTimeout(CONNECT_TIMEOUT, MILLISECONDS)
 				.build();
 
diff --git a/briar-core/src/main/java/org/briarproject/briar/feed/NoDns.java b/briar-core/src/main/java/org/briarproject/briar/feed/NoDns.java
new file mode 100644
index 0000000000..5f5cc8c44b
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/feed/NoDns.java
@@ -0,0 +1,28 @@
+package org.briarproject.briar.feed;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Collections;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import okhttp3.Dns;
+
+class NoDns implements Dns {
+
+	private static final byte[] UNSPECIFIED_ADDRESS = new byte[4];
+
+	@Inject
+	public NoDns() {
+	}
+
+	@Override
+	public List<InetAddress> lookup(String hostname)
+			throws UnknownHostException {
+		InetAddress unspecified =
+				InetAddress.getByAddress(hostname, UNSPECIFIED_ADDRESS);
+		return Collections.singletonList(unspecified);
+	}
+
+}
diff --git a/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTest.java
new file mode 100644
index 0000000000..25d4992c41
--- /dev/null
+++ b/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTest.java
@@ -0,0 +1,119 @@
+package org.briarproject.briar.feed;
+
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.contact.ContactModule;
+import org.briarproject.bramble.crypto.CryptoModule;
+import org.briarproject.bramble.identity.IdentityModule;
+import org.briarproject.bramble.lifecycle.LifecycleModule;
+import org.briarproject.bramble.sync.SyncModule;
+import org.briarproject.bramble.system.SystemModule;
+import org.briarproject.bramble.test.TestDatabaseModule;
+import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.transport.TransportModule;
+import org.briarproject.briar.api.blog.Blog;
+import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.feed.Feed;
+import org.briarproject.briar.api.feed.FeedManager;
+import org.briarproject.briar.blog.BlogModule;
+import org.briarproject.briar.test.BriarTestCase;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class FeedManagerIntegrationTest extends BriarTestCase {
+
+	private LifecycleManager lifecycleManager;
+	private FeedManager feedManager;
+	private BlogManager blogManager;
+	private final File testDir = TestUtils.getTestDirectory();
+	private final File testFile = new File(testDir, "feedTest");
+
+	@Before
+	public void setUp() throws Exception {
+		assertTrue(testDir.mkdirs());
+		FeedManagerIntegrationTestComponent component =
+				DaggerFeedManagerIntegrationTestComponent.builder()
+						.testDatabaseModule(new TestDatabaseModule(testFile))
+						.build();
+		component.inject(this);
+		injectEagerSingletons(component);
+
+		lifecycleManager = component.getLifecycleManager();
+		lifecycleManager.startServices("feedTest");
+		lifecycleManager.waitForStartup();
+
+		feedManager = component.getFeedManager();
+		blogManager = component.getBlogManager();
+	}
+
+	@Test
+	public void testFeedImportAndRemoval() throws Exception {
+		// initially, there's only the one personal blog
+		Collection<Blog> blogs = blogManager.getBlogs();
+		assertEquals(1, blogs.size());
+		Blog personalBlog = blogs.iterator().next();
+
+		// add feed into a dedicated blog
+		String url = "https://www.schneier.com/blog/atom.xml";
+		feedManager.addFeed(url);
+
+		// then there's the feed's blog now
+		blogs = blogManager.getBlogs();
+		assertEquals(2, blogs.size());
+		Blog feedBlog = null;
+		for (Blog blog : blogs) {
+			if (!blog.equals(personalBlog)) feedBlog = blog;
+		}
+		assertNotNull(feedBlog);
+
+		// check the feed got saved as expected
+		Collection<Feed> feeds = feedManager.getFeeds();
+		assertEquals(1, feeds.size());
+		Feed feed = feeds.iterator().next();
+		assertTrue(feed.getLastEntryTime() > 0);
+		assertTrue(feed.getAdded() > 0);
+		assertTrue(feed.getUpdated() > 0);
+		assertEquals(url, feed.getUrl());
+		assertEquals(feedBlog, feed.getBlog());
+		assertEquals("Schneier on Security", feed.getTitle());
+		assertEquals("A blog covering security and security technology.",
+				feed.getDescription());
+		assertEquals(feed.getTitle(), feed.getBlog().getName());
+		assertEquals(feed.getTitle(), feed.getLocalAuthor().getName());
+
+		// now let's remove the feed's blog again
+		blogManager.removeBlog(feedBlog);
+		blogs = blogManager.getBlogs();
+		assertEquals(1, blogs.size());
+		assertEquals(personalBlog, blogs.iterator().next());
+		assertEquals(0, feedManager.getFeeds().size());
+	}
+
+	@After
+	public void tearDown() throws Exception {
+		lifecycleManager.stopServices();
+		lifecycleManager.waitForShutdown();
+		TestUtils.deleteTestDirectory(testDir);
+	}
+
+	protected void injectEagerSingletons(
+			FeedManagerIntegrationTestComponent component) {
+		component.inject(new FeedModule.EagerSingletons());
+		component.inject(new BlogModule.EagerSingletons());
+		component.inject(new ContactModule.EagerSingletons());
+		component.inject(new CryptoModule.EagerSingletons());
+		component.inject(new IdentityModule.EagerSingletons());
+		component.inject(new LifecycleModule.EagerSingletons());
+		component.inject(new SyncModule.EagerSingletons());
+		component.inject(new SystemModule.EagerSingletons());
+		component.inject(new TransportModule.EagerSingletons());
+	}
+
+}
diff --git a/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java
new file mode 100644
index 0000000000..ce5ec5a00d
--- /dev/null
+++ b/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java
@@ -0,0 +1,79 @@
+package org.briarproject.briar.feed;
+
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.client.ClientModule;
+import org.briarproject.bramble.contact.ContactModule;
+import org.briarproject.bramble.crypto.CryptoModule;
+import org.briarproject.bramble.data.DataModule;
+import org.briarproject.bramble.db.DatabaseModule;
+import org.briarproject.bramble.event.EventModule;
+import org.briarproject.bramble.identity.IdentityModule;
+import org.briarproject.bramble.lifecycle.LifecycleModule;
+import org.briarproject.bramble.sync.SyncModule;
+import org.briarproject.bramble.system.SystemModule;
+import org.briarproject.bramble.test.TestDatabaseModule;
+import org.briarproject.bramble.test.TestPluginConfigModule;
+import org.briarproject.bramble.test.TestSeedProviderModule;
+import org.briarproject.bramble.test.TestSocksModule;
+import org.briarproject.bramble.transport.TransportModule;
+import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.feed.FeedManager;
+import org.briarproject.briar.blog.BlogModule;
+import org.briarproject.briar.client.BriarClientModule;
+import org.briarproject.briar.test.TestDnsModule;
+
+import javax.inject.Singleton;
+
+import dagger.Component;
+
+@Singleton
+@Component(modules = {
+		TestDatabaseModule.class,
+		TestPluginConfigModule.class,
+		TestSeedProviderModule.class,
+		TestSocksModule.class,
+		TestDnsModule.class,
+		LifecycleModule.class,
+		BriarClientModule.class,
+		ClientModule.class,
+		ContactModule.class,
+		CryptoModule.class,
+		BlogModule.class,
+		FeedModule.class,
+		DataModule.class,
+		DatabaseModule.class,
+		EventModule.class,
+		IdentityModule.class,
+		SyncModule.class,
+		SystemModule.class,
+		TransportModule.class
+})
+interface FeedManagerIntegrationTestComponent {
+
+	void inject(FeedManagerIntegrationTest testCase);
+
+	void inject(FeedModule.EagerSingletons init);
+
+	void inject(BlogModule.EagerSingletons init);
+
+	void inject(ContactModule.EagerSingletons init);
+
+	void inject(CryptoModule.EagerSingletons init);
+
+	void inject(IdentityModule.EagerSingletons init);
+
+	void inject(LifecycleModule.EagerSingletons init);
+
+	void inject(SyncModule.EagerSingletons init);
+
+	void inject(SystemModule.EagerSingletons init);
+
+	void inject(TransportModule.EagerSingletons init);
+
+	LifecycleManager getLifecycleManager();
+
+	FeedManager getFeedManager();
+
+	BlogManager getBlogManager();
+
+}
diff --git a/briar-core/src/test/java/org/briarproject/briar/test/TestDnsModule.java b/briar-core/src/test/java/org/briarproject/briar/test/TestDnsModule.java
new file mode 100644
index 0000000000..13323b346f
--- /dev/null
+++ b/briar-core/src/test/java/org/briarproject/briar/test/TestDnsModule.java
@@ -0,0 +1,15 @@
+package org.briarproject.briar.test;
+
+import dagger.Module;
+import dagger.Provides;
+import okhttp3.Dns;
+
+@Module
+public class TestDnsModule {
+
+	@Provides
+	Dns provideDns() {
+		return Dns.SYSTEM;
+	}
+
+}
-- 
GitLab