This is long overdue renaming step to manifest that SQL database is removed from gerrit core. Moreover, client/server package division was needed due to GWT UI that was removed as well in release 3.0. Bug: Issue 11678 Change-Id: Icfd83a309a6affac54141e7284e70f1255537dc4
		
			
				
	
	
		
			202 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			202 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
// Copyright (C) 2019 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.acceptance;
 | 
						|
 | 
						|
import static com.google.common.base.Preconditions.checkArgument;
 | 
						|
import static com.google.common.collect.ImmutableList.toImmutableList;
 | 
						|
import static com.google.common.truth.Truth.assertThat;
 | 
						|
import static java.util.Objects.requireNonNull;
 | 
						|
 | 
						|
import com.google.common.base.MoreObjects;
 | 
						|
import com.google.common.collect.ImmutableListMultimap;
 | 
						|
import com.google.gerrit.common.Nullable;
 | 
						|
import com.google.gerrit.entities.Change;
 | 
						|
import com.google.gerrit.extensions.annotations.Exports;
 | 
						|
import com.google.gerrit.extensions.common.ChangeInfo;
 | 
						|
import com.google.gerrit.extensions.common.PluginDefinedInfo;
 | 
						|
import com.google.gerrit.extensions.registration.DynamicSet;
 | 
						|
import com.google.gerrit.server.DynamicOptions.DynamicBean;
 | 
						|
import com.google.gerrit.server.change.ChangeAttributeFactory;
 | 
						|
import com.google.gerrit.server.restapi.change.GetChange;
 | 
						|
import com.google.gerrit.server.restapi.change.QueryChanges;
 | 
						|
import com.google.gerrit.sshd.commands.Query;
 | 
						|
import com.google.gson.Gson;
 | 
						|
import com.google.gson.reflect.TypeToken;
 | 
						|
import com.google.inject.AbstractModule;
 | 
						|
import com.google.inject.Module;
 | 
						|
import java.util.List;
 | 
						|
import java.util.Objects;
 | 
						|
import org.kohsuke.args4j.Option;
 | 
						|
 | 
						|
public class AbstractPluginFieldsTest extends AbstractDaemonTest {
 | 
						|
  protected static class MyInfo extends PluginDefinedInfo {
 | 
						|
    @Nullable String theAttribute;
 | 
						|
 | 
						|
    public MyInfo(@Nullable String theAttribute) {
 | 
						|
      this.theAttribute = theAttribute;
 | 
						|
    }
 | 
						|
 | 
						|
    MyInfo(String name, @Nullable String theAttribute) {
 | 
						|
      this.name = requireNonNull(name);
 | 
						|
      this.theAttribute = theAttribute;
 | 
						|
    }
 | 
						|
 | 
						|
    @Override
 | 
						|
    public boolean equals(Object o) {
 | 
						|
      if (!(o instanceof MyInfo)) {
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
      MyInfo i = (MyInfo) o;
 | 
						|
      return Objects.equals(name, i.name) && Objects.equals(theAttribute, i.theAttribute);
 | 
						|
    }
 | 
						|
 | 
						|
    @Override
 | 
						|
    public int hashCode() {
 | 
						|
      return Objects.hash(name, theAttribute);
 | 
						|
    }
 | 
						|
 | 
						|
    @Override
 | 
						|
    public String toString() {
 | 
						|
      return MoreObjects.toStringHelper(this)
 | 
						|
          .add("name", name)
 | 
						|
          .add("theAttribute", theAttribute)
 | 
						|
          .toString();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  protected static class NullAttributeModule extends AbstractModule {
 | 
						|
    @Override
 | 
						|
    public void configure() {
 | 
						|
      DynamicSet.bind(binder(), ChangeAttributeFactory.class).toInstance((cd, bp, p) -> null);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  protected static class SimpleAttributeModule extends AbstractModule {
 | 
						|
    @Override
 | 
						|
    public void configure() {
 | 
						|
      DynamicSet.bind(binder(), ChangeAttributeFactory.class)
 | 
						|
          .toInstance((cd, bp, p) -> new MyInfo("change " + cd.getId()));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  private static class MyOptions implements DynamicBean {
 | 
						|
    @Option(name = "--opt")
 | 
						|
    private String opt;
 | 
						|
  }
 | 
						|
 | 
						|
  protected static class OptionAttributeModule extends AbstractModule {
 | 
						|
    @Override
 | 
						|
    public void configure() {
 | 
						|
      DynamicSet.bind(binder(), ChangeAttributeFactory.class)
 | 
						|
          .toInstance(
 | 
						|
              (cd, bp, p) -> {
 | 
						|
                MyOptions opts = (MyOptions) bp.getDynamicBean(p);
 | 
						|
                return opts != null ? new MyInfo("opt " + opts.opt) : null;
 | 
						|
              });
 | 
						|
      bind(DynamicBean.class).annotatedWith(Exports.named(Query.class)).to(MyOptions.class);
 | 
						|
      bind(DynamicBean.class).annotatedWith(Exports.named(QueryChanges.class)).to(MyOptions.class);
 | 
						|
      bind(DynamicBean.class).annotatedWith(Exports.named(GetChange.class)).to(MyOptions.class);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  protected void getChangeWithNullAttribute(PluginInfoGetter getter) throws Exception {
 | 
						|
    Change.Id id = createChange().getChange().getId();
 | 
						|
    assertThat(getter.call(id)).isNull();
 | 
						|
 | 
						|
    try (AutoCloseable ignored = installPlugin("my-plugin", NullAttributeModule.class)) {
 | 
						|
      assertThat(getter.call(id)).isNull();
 | 
						|
    }
 | 
						|
 | 
						|
    assertThat(getter.call(id)).isNull();
 | 
						|
  }
 | 
						|
 | 
						|
  protected void getChangeWithSimpleAttribute(PluginInfoGetter getter) throws Exception {
 | 
						|
    getChangeWithSimpleAttribute(getter, SimpleAttributeModule.class);
 | 
						|
  }
 | 
						|
 | 
						|
  protected void getChangeWithSimpleAttribute(
 | 
						|
      PluginInfoGetter getter, Class<? extends Module> moduleClass) throws Exception {
 | 
						|
    Change.Id id = createChange().getChange().getId();
 | 
						|
    assertThat(getter.call(id)).isNull();
 | 
						|
 | 
						|
    try (AutoCloseable ignored = installPlugin("my-plugin", moduleClass)) {
 | 
						|
      assertThat(getter.call(id)).containsExactly(new MyInfo("my-plugin", "change " + id));
 | 
						|
    }
 | 
						|
 | 
						|
    assertThat(getter.call(id)).isNull();
 | 
						|
  }
 | 
						|
 | 
						|
  protected void getChangeWithOption(
 | 
						|
      PluginInfoGetter getterWithoutOptions, PluginInfoGetterWithOptions getterWithOptions)
 | 
						|
      throws Exception {
 | 
						|
    Change.Id id = createChange().getChange().getId();
 | 
						|
    assertThat(getterWithoutOptions.call(id)).isNull();
 | 
						|
 | 
						|
    try (AutoCloseable ignored = installPlugin("my-plugin", OptionAttributeModule.class)) {
 | 
						|
      assertThat(getterWithoutOptions.call(id))
 | 
						|
          .containsExactly(new MyInfo("my-plugin", "opt null"));
 | 
						|
      assertThat(getterWithOptions.call(id, ImmutableListMultimap.of("my-plugin--opt", "foo")))
 | 
						|
          .containsExactly(new MyInfo("my-plugin", "opt foo"));
 | 
						|
    }
 | 
						|
 | 
						|
    assertThat(getterWithoutOptions.call(id)).isNull();
 | 
						|
  }
 | 
						|
 | 
						|
  protected static List<MyInfo> pluginInfoFromSingletonList(List<ChangeInfo> changeInfos) {
 | 
						|
    assertThat(changeInfos).hasSize(1);
 | 
						|
    return pluginInfoFromChangeInfo(changeInfos.get(0));
 | 
						|
  }
 | 
						|
 | 
						|
  protected static List<MyInfo> pluginInfoFromChangeInfo(ChangeInfo changeInfo) {
 | 
						|
    List<PluginDefinedInfo> pluginInfo = changeInfo.plugins;
 | 
						|
    if (pluginInfo == null) {
 | 
						|
      return null;
 | 
						|
    }
 | 
						|
    return pluginInfo.stream().map(MyInfo.class::cast).collect(toImmutableList());
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Decode {@code MyInfo}s from a raw list of maps returned from Gson.
 | 
						|
   *
 | 
						|
   * <p>This method is used instead of decoding {@code ChangeInfo} or {@code ChangAttribute}, since
 | 
						|
   * Gson would decode the {@code plugins} field as a {@code List<PluginDefinedInfo>}, which would
 | 
						|
   * return the base type and silently ignore any fields that are defined only in the subclass.
 | 
						|
   * Instead, decode the enclosing {@code ChangeInfo} or {@code ChangeAttribute} as a raw {@code
 | 
						|
   * Map<String, Object>}, and pass the {@code "plugins"} value to this method.
 | 
						|
   *
 | 
						|
   * @param gson Gson converter.
 | 
						|
   * @param plugins list of {@code MyInfo} objects, each as a raw map returned from Gson.
 | 
						|
   * @return decoded list of {@code MyInfo}s.
 | 
						|
   */
 | 
						|
  protected static List<MyInfo> decodeRawPluginsList(Gson gson, @Nullable Object plugins) {
 | 
						|
    if (plugins == null) {
 | 
						|
      return null;
 | 
						|
    }
 | 
						|
    checkArgument(plugins instanceof List, "not a list: %s", plugins);
 | 
						|
    return gson.fromJson(gson.toJson(plugins), new TypeToken<List<MyInfo>>() {}.getType());
 | 
						|
  }
 | 
						|
 | 
						|
  @FunctionalInterface
 | 
						|
  protected interface PluginInfoGetter {
 | 
						|
    List<MyInfo> call(Change.Id id) throws Exception;
 | 
						|
  }
 | 
						|
 | 
						|
  @FunctionalInterface
 | 
						|
  protected interface PluginInfoGetterWithOptions {
 | 
						|
    List<MyInfo> call(Change.Id id, ImmutableListMultimap<String, String> pluginOptions)
 | 
						|
        throws Exception;
 | 
						|
  }
 | 
						|
}
 |