In-memory tests for searching changes

Use InMemoryModule to inject everything needed to manually insert
commits into a repo and changes into a database, then query the
results.

Change-Id: I22f6d663039039dd4d3f2189e587dbd22f11252b
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java
index fca63b1..9debd5d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java
@@ -924,7 +924,7 @@
     Boolean mergeable;
 
     String _sortkey;
-    int _number;
+    public int _number;
 
     AccountInfo owner;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java
index c5217c9..0d4f336 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java
@@ -42,8 +42,8 @@
 import java.util.List;
 
 @RequiresCapability(GlobalCapability.CREATE_PROJECT)
-class CreateProject implements RestModifyView<TopLevelResource, Input> {
-  static class Input {
+public class CreateProject implements RestModifyView<TopLevelResource, Input> {
+  public static class Input {
     String name;
     String parent;
     String description;
@@ -59,7 +59,7 @@
     String maxObjectSizeLimit;
   }
 
-  static interface Factory {
+  public static interface Factory {
     CreateProject create(String name);
   }
 
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/query/change/QueryChangesTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/query/change/QueryChangesTest.java
new file mode 100644
index 0000000..ad24c2c
--- /dev/null
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/query/change/QueryChangesTest.java
@@ -0,0 +1,166 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// 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 com.google.gerrit.server.git;
+
+package com.google.gerrit.server.query.change;
+
+import com.google.gerrit.extensions.restapi.TopLevelResource;
+import com.google.gerrit.lifecycle.LifecycleManager;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.account.AccountManager;
+import com.google.gerrit.server.account.AuthRequest;
+import com.google.gerrit.server.change.ChangeInserter;
+import com.google.gerrit.server.change.ChangeJson.ChangeInfo;
+import com.google.gerrit.server.project.CreateProject;
+import com.google.gerrit.server.project.NoSuchProjectException;
+import com.google.gerrit.server.project.ProjectControl;
+import com.google.gerrit.server.project.RefControl;
+import com.google.gerrit.server.schema.SchemaCreator;
+import com.google.gerrit.server.util.RequestContext;
+import com.google.gerrit.server.util.ThreadLocalRequestContext;
+import com.google.gerrit.testutil.InMemoryDatabase;
+import com.google.gerrit.testutil.InMemoryModule;
+import com.google.gerrit.testutil.InMemoryRepositoryManager;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Provider;
+import com.google.inject.util.Providers;
+
+import junit.framework.TestCase;
+
+import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+import java.io.IOException;
+import java.util.List;
+
+public class QueryChangesTest extends TestCase {
+  @Inject private AccountManager accountManager;
+  @Inject private ChangeInserter.Factory changeFactory;
+  @Inject private CreateProject.Factory projectFactory;
+  @Inject private IdentifiedUser.RequestFactory userFactory;
+  @Inject private InMemoryDatabase schemaFactory;
+  @Inject private InMemoryRepositoryManager repoManager;
+  @Inject private ProjectControl.GenericFactory projectControlFactory;
+  @Inject private Provider<QueryChanges> queryProvider;
+  @Inject private SchemaCreator schemaCreator;
+  @Inject private ThreadLocalRequestContext requestContext;
+
+  private LifecycleManager lifecycle;
+  private ReviewDb db;
+  private Account.Id user;
+
+  @Override
+  public void setUp() throws Exception {
+    Config cfg = InMemoryModule.newDefaultConfig();
+    cfg.setString("index", null, "type", "lucene");
+    cfg.setBoolean("index", "lucene", "testInmemory", true);
+    cfg.setInt("index", "lucene", "testVersion", 2);
+
+    Injector injector = Guice.createInjector(new InMemoryModule(cfg));
+    injector.injectMembers(this);
+    lifecycle = new LifecycleManager();
+    lifecycle.add(injector);
+    lifecycle.start();
+
+    db = schemaFactory.open();
+    schemaCreator.create(db);
+    user = accountManager.authenticate(AuthRequest.forUser("user"))
+        .getAccountId();
+
+    requestContext.setContext(new RequestContext() {
+      @Override
+      public CurrentUser getCurrentUser() {
+        return userFactory.create(user);
+      }
+
+      @Override
+      public Provider<ReviewDb> getReviewDbProvider() {
+        return Providers.of(db);
+      }
+    });
+  }
+
+  @Override
+  public void tearDown() {
+    lifecycle.stop();
+    requestContext.setContext(null);
+    db.close();
+    InMemoryDatabase.drop(schemaFactory);
+  }
+
+
+  public void testInjectionSetup() {
+    assertNotNull(changeFactory);
+    assertNotNull(repoManager);
+  }
+
+  public void testQueryById() throws Exception {
+    TestRepository<InMemoryRepository> repo = createProject("repo");
+    RevCommit commit = repo.parseBody(repo.commit().message("message").create());
+    Change change = new Change(
+        new Change.Key("I1234567890123456789012345678901234567890"),
+        new Change.Id(db.nextChangeId()),
+        user,
+        new Branch.NameKey(new Project.NameKey("repo"), "refs/heads/master"));
+    ChangeInserter ins = changeFactory.create(
+        refControl("repo", change),
+        change,
+        commit);
+    ins.insert();
+
+    int id = change.getId().get();
+    ChangeInfo result = queryOne(Integer.toString(id));
+    assertEquals(id, result._number);
+  }
+
+  private TestRepository<InMemoryRepository> createProject(String name)
+      throws Exception {
+    CreateProject create = projectFactory.create(name);
+    create.apply(TopLevelResource.INSTANCE, new CreateProject.Input());
+    return new TestRepository<InMemoryRepository>(
+        repoManager.openRepository(new Project.NameKey(name)));
+  }
+
+  private RefControl refControl(String repo, Change change) throws NoSuchProjectException, IOException {
+    return projectControlFactory.controlFor(
+        new Project.NameKey(repo),
+        userFactory.create(user)).controlFor(change).getRefControl();
+  }
+
+  private ChangeInfo queryOne(String query) throws Exception {
+    QueryChanges q = queryProvider.get();
+    q.addQuery(query);
+    Object result = q.apply(TopLevelResource.INSTANCE);
+    assertTrue(String.format("expected List<ChangeInfo>, found %s", result),
+        result instanceof List);
+    @SuppressWarnings("rawtypes")
+    List results = (List) result;
+    assertTrue(String.format(
+        "expected singleton List<ChangeInfo>, found %s", result),
+        results.size() == 1);
+    Object ci = results.get(0);
+    assertTrue(String.format("expected ChangeInfo, found %s", result),
+        ci instanceof ChangeInfo);
+    return (ChangeInfo) ci;
+  }
+}