summaryrefslogtreecommitdiffstats
path: root/java/com/google/gerrit/testing/InMemoryTestEnvironment.java
blob: cebd139612ead189a7c66e111f074a582d14bc93 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Copyright (C) 2017 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.testing;

import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.reviewdb.client.Account;
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.schema.SchemaCreator;
import com.google.gerrit.server.util.RequestContext;
import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.gwtorm.server.SchemaFactory;
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 org.eclipse.jgit.lib.Config;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;

/**
 * An in-memory test environment for integration tests.
 *
 * <p>This test environment emulates the internals of a Gerrit server without starting a Gerrit
 * site. ReviewDb as well as NoteDb are represented by in-memory representations.
 *
 * <p>Each test is executed with a fresh and clean test environment. Hence, modifications applied in
 * one test don't carry over to subsequent ones.
 */
public final class InMemoryTestEnvironment implements MethodRule {
  private final Provider<Config> configProvider;

  @Inject private AccountManager accountManager;
  @Inject private IdentifiedUser.GenericFactory userFactory;
  @Inject private SchemaFactory<ReviewDb> schemaFactory;
  @Inject private SchemaCreator schemaCreator;
  @Inject private ThreadLocalRequestContext requestContext;
  // Only for use in setting up/tearing down injector.
  @Inject private InMemoryDatabase inMemoryDatabase;

  private ReviewDb db;
  private LifecycleManager lifecycle;

  /** Create a test environment using an empty base config. */
  public InMemoryTestEnvironment() {
    this(Config::new);
  }

  /**
   * Create a test environment using the specified base config.
   *
   * <p>The config is passed as a provider so it can be lazily initialized after this rule is
   * instantiated, for example using {@link ConfigSuite}.
   *
   * @param configProvider possibly-lazy provider for the base config.
   */
  public InMemoryTestEnvironment(Provider<Config> configProvider) {
    this.configProvider = configProvider;
  }

  @Override
  public Statement apply(Statement base, FrameworkMethod method, Object target) {
    return new Statement() {
      @Override
      public void evaluate() throws Throwable {
        try {
          setUp(target);
          base.evaluate();
        } finally {
          tearDown();
        }
      }
    };
  }

  public void setApiUser(Account.Id id) {
    IdentifiedUser user = userFactory.create(id);
    requestContext.setContext(
        new RequestContext() {
          @Override
          public CurrentUser getUser() {
            return user;
          }

          @Override
          public Provider<ReviewDb> getReviewDbProvider() {
            return Providers.of(db);
          }
        });
  }

  private void setUp(Object target) throws Exception {
    Config cfg = configProvider.get();
    InMemoryModule.setDefaults(cfg);

    Injector injector =
        Guice.createInjector(new InMemoryModule(cfg, NoteDbMode.newNotesMigrationFromEnv()));
    injector.injectMembers(this);
    lifecycle = new LifecycleManager();
    lifecycle.add(injector);
    lifecycle.start();

    try (ReviewDb underlyingDb = inMemoryDatabase.getDatabase().open()) {
      schemaCreator.create(underlyingDb);
    }
    db = schemaFactory.open();

    // The first user is added to the "Administrators" group. See AccountManager#create().
    setApiUser(accountManager.authenticate(AuthRequest.forUser("admin")).getAccountId());

    // Inject target members after setting API user, so it can @Inject a ReviewDb if it wants.
    injector.injectMembers(target);
  }

  private void tearDown() {
    if (lifecycle != null) {
      lifecycle.stop();
    }
    if (requestContext != null) {
      requestContext.setContext(null);
    }
    if (db != null) {
      db.close();
    }
    InMemoryDatabase.drop(inMemoryDatabase);
  }
}