]> source.dussan.org Git - sonarqube.git/commitdiff
use testFixtures instead of test configuration of server-common
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 29 Aug 2019 11:47:54 +0000 (13:47 +0200)
committerSonarTech <sonartech@sonarsource.com>
Mon, 2 Sep 2019 18:21:04 +0000 (20:21 +0200)
39 files changed:
server/sonar-ce-common/build.gradle
server/sonar-ce-task-projectanalysis/build.gradle
server/sonar-server-common/build.gradle
server/sonar-server-common/src/test/java/org/elasticsearch/transport/MockTcpTransport.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/es/EsTester.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/es/FakeDoc.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/es/TestProjectIndexers.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/es/newindex/FakeIndexDefinition.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/es/textsearch/ComponentTextSearchFeatureRule.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/issue/IssueDocTesting.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/IssuesChangesNotificationBuilderTesting.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/l18n/I18nRule.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/organization/TestDefaultOrganizationProvider.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/organization/TestOrganizationFlags.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/platform/monitoring/SystemInfoTesting.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/platform/monitoring/cluster/TestGlobalSystemInfoSection.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/platform/monitoring/cluster/TestSystemInfoSection.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/source/index/FileSourceTesting.java [deleted file]
server/sonar-server-common/src/testFixtures/java/org/elasticsearch/transport/MockTcpTransport.java [new file with mode: 0644]
server/sonar-server-common/src/testFixtures/java/org/sonar/server/es/EsTester.java [new file with mode: 0644]
server/sonar-server-common/src/testFixtures/java/org/sonar/server/es/FakeDoc.java [new file with mode: 0644]
server/sonar-server-common/src/testFixtures/java/org/sonar/server/es/TestProjectIndexers.java [new file with mode: 0644]
server/sonar-server-common/src/testFixtures/java/org/sonar/server/es/newindex/FakeIndexDefinition.java [new file with mode: 0644]
server/sonar-server-common/src/testFixtures/java/org/sonar/server/es/textsearch/ComponentTextSearchFeatureRule.java [new file with mode: 0644]
server/sonar-server-common/src/testFixtures/java/org/sonar/server/issue/IssueDocTesting.java [new file with mode: 0644]
server/sonar-server-common/src/testFixtures/java/org/sonar/server/issue/notification/IssuesChangesNotificationBuilderTesting.java [new file with mode: 0644]
server/sonar-server-common/src/testFixtures/java/org/sonar/server/l18n/I18nRule.java [new file with mode: 0644]
server/sonar-server-common/src/testFixtures/java/org/sonar/server/organization/TestDefaultOrganizationProvider.java [new file with mode: 0644]
server/sonar-server-common/src/testFixtures/java/org/sonar/server/organization/TestOrganizationFlags.java [new file with mode: 0644]
server/sonar-server-common/src/testFixtures/java/org/sonar/server/platform/monitoring/SystemInfoTesting.java [new file with mode: 0644]
server/sonar-server-common/src/testFixtures/java/org/sonar/server/platform/monitoring/cluster/TestGlobalSystemInfoSection.java [new file with mode: 0644]
server/sonar-server-common/src/testFixtures/java/org/sonar/server/platform/monitoring/cluster/TestSystemInfoSection.java [new file with mode: 0644]
server/sonar-server-common/src/testFixtures/java/org/sonar/server/source/index/FileSourceTesting.java [new file with mode: 0644]
server/sonar-webserver-api/build.gradle
server/sonar-webserver-auth/build.gradle
server/sonar-webserver-core/build.gradle
server/sonar-webserver-es/build.gradle
server/sonar-webserver-webapi/build.gradle
server/sonar-webserver/build.gradle

index c10f7b688e090b73d1c0463834d0456869237159..800286bde41406ee193d1569696297dcfbec3914 100644 (file)
@@ -51,6 +51,5 @@ dependencies {
   testCompile 'org.assertj:assertj-guava'
   testCompile 'org.hamcrest:hamcrest-all'
   testCompile project(':sonar-plugin-api-impl')
-  testCompile testFixtures(project(':server:sonar-db-dao'))
-  testCompile project(path: ":server:sonar-server-common", configuration: "tests")
+  testCompile testFixtures(project(':server:sonar-server-common'))
 }
index 47e0a9999dd2a0f143d6a3d8ad751370449fe8a8..e9eca578474cc29ed9674855068c843ecaab6bac 100644 (file)
@@ -50,17 +50,15 @@ dependencies {
 
   testCompile 'com.google.code.findbugs:jsr305'
   testCompile 'com.tngtech.java:junit-dataprovider'
-  testCompile 'junit:junit'
   testCompile 'org.apache.logging.log4j:log4j-api'
   testCompile 'org.apache.logging.log4j:log4j-core'
   testCompile 'org.assertj:assertj-core'
   testCompile 'org.assertj:assertj-guava'
   testCompile 'org.mockito:mockito-core'
   testCompile 'org.reflections:reflections'
-  testCompile testFixtures(project(':server:sonar-db-dao'))
   testCompile project(':sonar-testing-harness')
   testCompile project(path: ":server:sonar-ce-task", configuration: "tests")
-  testCompile project(path: ":server:sonar-server-common", configuration: "tests")
+  testCompile testFixtures(project(':server:sonar-server-common'))
 }
 
 task testJar(type: Jar) {
index 284828db542006b51bae11680db2633ce225778d..5e027f8187836a918971b212f75fe9dd4fe058ea 100644 (file)
@@ -6,12 +6,6 @@ sonarqube {
   }
 }
 
-configurations {
-  tests
-
-  testCompile.extendsFrom tests
-}
-
 dependencies {
   // please keep the list grouped by configuration and ordered by name
 
@@ -32,10 +26,6 @@ dependencies {
 
   compileOnly 'com.google.code.findbugs:jsr305'
 
-  // "tests" dependencies are pulled by other modules which depends on "tests" configuration, "testCompile" are not pulled
-  tests 'org.codelibs.elasticsearch.module:analysis-common'
-  tests 'org.elasticsearch:mocksocket'
-
   testCompile 'ch.qos.logback:logback-core'
   testCompile 'com.google.code.findbugs:jsr305'
   testCompile 'com.squareup.okhttp3:mockwebserver'
@@ -51,13 +41,12 @@ dependencies {
   testCompile project(path: ':sonar-plugin-api', configuration: 'shadow')
   testCompile project(':sonar-plugin-api-impl')
   testCompile project(':sonar-testing-harness')
-}
+    
+  testFixturesApi 'junit:junit'
+  testFixturesApi testFixtures(project(':server:sonar-db-dao'))
 
-task testJar(type: Jar) {
-  classifier = 'tests'
-  from sourceSets.test.output
-}
+  testFixturesCompileOnly 'com.google.code.findbugs:jsr305'
 
-artifacts {
-  tests testJar
+  testFixturesImplementation 'org.codelibs.elasticsearch.module:analysis-common'
+  testFixturesImplementation 'org.elasticsearch:mocksocket'
 }
diff --git a/server/sonar-server-common/src/test/java/org/elasticsearch/transport/MockTcpTransport.java b/server/sonar-server-common/src/test/java/org/elasticsearch/transport/MockTcpTransport.java
deleted file mode 100644 (file)
index b5d89ef..0000000
+++ /dev/null
@@ -1,495 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.elasticsearch.transport;
-
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you 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.
- */
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.Closeable;
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketException;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.elasticsearch.Version;
-import org.elasticsearch.action.ActionListener;
-import org.elasticsearch.cli.SuppressForbidden;
-import org.elasticsearch.cluster.node.DiscoveryNode;
-import org.elasticsearch.common.bytes.BytesArray;
-import org.elasticsearch.common.bytes.BytesReference;
-import org.elasticsearch.common.concurrent.CompletableContext;
-import org.elasticsearch.common.io.stream.BytesStreamOutput;
-import org.elasticsearch.common.io.stream.InputStreamStreamInput;
-import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
-import org.elasticsearch.common.io.stream.ReleasableBytesStreamOutput;
-import org.elasticsearch.common.io.stream.StreamInput;
-import org.elasticsearch.common.network.NetworkService;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.common.unit.ByteSizeValue;
-import org.elasticsearch.common.util.BigArrays;
-import org.elasticsearch.common.util.CancellableThreads;
-import org.elasticsearch.common.util.PageCacheRecycler;
-import org.elasticsearch.common.util.concurrent.AbstractRunnable;
-import org.elasticsearch.common.util.concurrent.EsExecutors;
-import org.elasticsearch.core.internal.io.IOUtils;
-import org.elasticsearch.indices.breaker.CircuitBreakerService;
-import org.elasticsearch.mocksocket.MockServerSocket;
-import org.elasticsearch.mocksocket.MockSocket;
-import org.elasticsearch.threadpool.ThreadPool;
-
-/**
- * This is a socket based blocking TcpTransport implementation that is used for tests
- * that need real networking. This implementation is a test only implementation that implements
- * the networking layer in the worst possible way since it blocks and uses a thread per request model.
- */
-public class MockTcpTransport extends TcpTransport {
-  private static final Logger logger = LogManager.getLogger(MockTcpTransport.class);
-
-  /**
-   * A pre-built light connection profile that shares a single connection across all
-   * types.
-   */
-  static final ConnectionProfile LIGHT_PROFILE;
-
-  private final Set<MockChannel> openChannels = new HashSet<>();
-
-  static {
-    ConnectionProfile.Builder builder = new ConnectionProfile.Builder();
-    builder.addConnections(1,
-      TransportRequestOptions.Type.BULK,
-      TransportRequestOptions.Type.PING,
-      TransportRequestOptions.Type.RECOVERY,
-      TransportRequestOptions.Type.REG,
-      TransportRequestOptions.Type.STATE);
-    LIGHT_PROFILE = builder.build();
-  }
-
-  private final ExecutorService executor;
-
-  public MockTcpTransport(Settings settings, ThreadPool threadPool, BigArrays bigArrays,
-                          CircuitBreakerService circuitBreakerService, NamedWriteableRegistry namedWriteableRegistry,
-                          NetworkService networkService) {
-    this(settings, threadPool, bigArrays, circuitBreakerService, namedWriteableRegistry, networkService, Version.CURRENT);
-  }
-
-  public MockTcpTransport(Settings settings, ThreadPool threadPool, BigArrays bigArrays,
-                          CircuitBreakerService circuitBreakerService, NamedWriteableRegistry namedWriteableRegistry,
-                          NetworkService networkService, Version mockVersion) {
-    super("mock-tcp-transport", settings, mockVersion, threadPool, PageCacheRecycler.NON_RECYCLING_INSTANCE, circuitBreakerService,
-      namedWriteableRegistry, networkService);
-    // we have our own crazy cached threadpool this one is not bounded at all...
-    // using the ES thread factory here is crucial for tests otherwise disruption tests won't block that thread
-    executor = Executors.newCachedThreadPool(EsExecutors.daemonThreadFactory(settings, Transports.TEST_MOCK_TRANSPORT_THREAD_PREFIX));
-  }
-
-  @Override
-  protected MockChannel bind(final String name, InetSocketAddress address) throws IOException {
-    MockServerSocket socket = new MockServerSocket();
-    socket.setReuseAddress(TransportSettings.TCP_REUSE_ADDRESS.get(settings));
-    ByteSizeValue tcpReceiveBufferSize = TransportSettings.TCP_RECEIVE_BUFFER_SIZE.get(settings);
-    if (tcpReceiveBufferSize.getBytes() > 0) {
-      socket.setReceiveBufferSize(tcpReceiveBufferSize.bytesAsInt());
-    }
-    socket.bind(address);
-    MockChannel serverMockChannel = new MockChannel(socket, name);
-    CountDownLatch started = new CountDownLatch(1);
-    executor.execute(new AbstractRunnable() {
-      @Override
-      public void onFailure(Exception e) {
-        onException(serverMockChannel, e);
-      }
-
-      @Override
-      protected void doRun() throws Exception {
-        started.countDown();
-        serverMockChannel.accept(executor);
-      }
-    });
-    try {
-      started.await();
-    } catch (InterruptedException e) {
-      Thread.currentThread().interrupt();
-    }
-    return serverMockChannel;
-  }
-
-  private void readMessage(MockChannel mockChannel, StreamInput input) throws IOException {
-    Socket socket = mockChannel.activeChannel;
-    byte[] minimalHeader = new byte[TcpHeader.MARKER_BYTES_SIZE + TcpHeader.MESSAGE_LENGTH_SIZE];
-    try {
-      input.readFully(minimalHeader);
-    } catch (EOFException eof) {
-      throw new IOException("Connection reset by peer");
-    }
-
-    // Read message length will throw stream corrupted exception if the marker bytes incorrect
-    int msgSize = TcpTransport.readMessageLength(new BytesArray(minimalHeader));
-    if (msgSize == -1) {
-      socket.getOutputStream().flush();
-    } else {
-      final byte[] buffer = new byte[msgSize];
-      input.readFully(buffer);
-      int expectedSize = TcpHeader.MARKER_BYTES_SIZE + TcpHeader.MESSAGE_LENGTH_SIZE + msgSize;
-      try (BytesStreamOutput output = new ReleasableBytesStreamOutput(expectedSize, bigArrays)) {
-        output.write(minimalHeader);
-        output.write(buffer);
-        consumeNetworkReads(mockChannel, output.bytes());
-      }
-    }
-  }
-
-  @Override
-  @SuppressForbidden(reason = "real socket for mocking remote connections")
-  protected MockChannel initiateChannel(DiscoveryNode node) throws IOException {
-    InetSocketAddress address = node.getAddress().address();
-    final MockSocket socket = new MockSocket();
-    final MockChannel channel = new MockChannel(socket, address, false, "none");
-
-    boolean success = false;
-    try {
-      configureSocket(socket);
-      success = true;
-    } finally {
-      if (success == false) {
-        IOUtils.close(socket);
-      }
-    }
-
-    executor.submit(() -> {
-      try {
-        socket.connect(address);
-        socket.setSoLinger(false, 0);
-        channel.connectFuture.complete(null);
-        channel.loopRead(executor);
-      } catch (Exception ex) {
-        channel.connectFuture.completeExceptionally(ex);
-      }
-    });
-
-    return channel;
-  }
-
-  @Override
-  protected ConnectionProfile maybeOverrideConnectionProfile(ConnectionProfile connectionProfile) {
-    ConnectionProfile.Builder builder = new ConnectionProfile.Builder();
-    Set<TransportRequestOptions.Type> allTypesWithConnection = new HashSet<>();
-    Set<TransportRequestOptions.Type> allTypesWithoutConnection = new HashSet<>();
-    for (ConnectionProfile.ConnectionTypeHandle handle : connectionProfile.getHandles()) {
-      Set<TransportRequestOptions.Type> types = handle.getTypes();
-      if (handle.length > 0) {
-        allTypesWithConnection.addAll(types);
-      } else {
-        allTypesWithoutConnection.addAll(types);
-      }
-    }
-    // make sure we maintain at least the types that are supported by this profile even if we only use a single channel for them.
-    builder.addConnections(1, allTypesWithConnection.toArray(new TransportRequestOptions.Type[0]));
-    if (allTypesWithoutConnection.isEmpty() == false) {
-      builder.addConnections(0, allTypesWithoutConnection.toArray(new TransportRequestOptions.Type[0]));
-    }
-    builder.setHandshakeTimeout(connectionProfile.getHandshakeTimeout());
-    builder.setConnectTimeout(connectionProfile.getConnectTimeout());
-    builder.setPingInterval(connectionProfile.getPingInterval());
-    builder.setCompressionEnabled(connectionProfile.getCompressionEnabled());
-    return builder.build();
-  }
-
-  private void configureSocket(Socket socket) throws SocketException {
-    socket.setTcpNoDelay(TransportSettings.TCP_NO_DELAY.get(settings));
-    ByteSizeValue tcpSendBufferSize = TransportSettings.TCP_SEND_BUFFER_SIZE.get(settings);
-    if (tcpSendBufferSize.getBytes() > 0) {
-      socket.setSendBufferSize(tcpSendBufferSize.bytesAsInt());
-    }
-    ByteSizeValue tcpReceiveBufferSize = TransportSettings.TCP_RECEIVE_BUFFER_SIZE.get(settings);
-    if (tcpReceiveBufferSize.getBytes() > 0) {
-      socket.setReceiveBufferSize(tcpReceiveBufferSize.bytesAsInt());
-    }
-    socket.setReuseAddress(TransportSettings.TCP_REUSE_ADDRESS.get(settings));
-  }
-
-  public final class MockChannel implements Closeable, TcpChannel, TcpServerChannel {
-    private final AtomicBoolean isOpen = new AtomicBoolean(true);
-    private final InetSocketAddress localAddress;
-    private final ServerSocket serverSocket;
-    private final Set<MockChannel> workerChannels = Collections.newSetFromMap(new ConcurrentHashMap<>());
-    private final Socket activeChannel;
-    private final boolean isServer;
-    private final String profile;
-    private final CancellableThreads cancellableThreads = new CancellableThreads();
-    private final CompletableContext<Void> closeFuture = new CompletableContext<>();
-    private final CompletableContext<Void> connectFuture = new CompletableContext<>();
-    private final ChannelStats stats = new ChannelStats();
-
-    /**
-     * Constructs a new MockChannel instance intended for handling the actual incoming / outgoing traffic.
-     *
-     * @param socket The client socket. Mut not be null.
-     * @param localAddress Address associated with the corresponding local server socket. Must not be null.
-     * @param profile The associated profile name.
-     */
-    MockChannel(Socket socket, InetSocketAddress localAddress, boolean isServer, String profile) {
-      this.localAddress = localAddress;
-      this.activeChannel = socket;
-      this.isServer = isServer;
-      this.serverSocket = null;
-      this.profile = profile;
-      synchronized (openChannels) {
-        openChannels.add(this);
-      }
-    }
-
-    /**
-     * Constructs a new MockChannel instance intended for accepting requests.
-     *
-     * @param serverSocket The associated server socket. Must not be null.
-     * @param profile The associated profile name.
-     */
-    MockChannel(ServerSocket serverSocket, String profile) {
-      this.localAddress = (InetSocketAddress) serverSocket.getLocalSocketAddress();
-      this.serverSocket = serverSocket;
-      this.profile = profile;
-      this.isServer = false;
-      this.activeChannel = null;
-      synchronized (openChannels) {
-        openChannels.add(this);
-      }
-    }
-
-    public void accept(Executor executor) throws IOException {
-      while (isOpen.get()) {
-        Socket incomingSocket = serverSocket.accept();
-        MockChannel incomingChannel = null;
-        try {
-          configureSocket(incomingSocket);
-          synchronized (this) {
-            if (isOpen.get()) {
-              InetSocketAddress localAddress = new InetSocketAddress(incomingSocket.getLocalAddress(),
-                incomingSocket.getPort());
-              incomingChannel = new MockChannel(incomingSocket, localAddress, true, profile);
-              MockChannel finalIncomingChannel = incomingChannel;
-              incomingChannel.addCloseListener(new ActionListener<Void>() {
-                @Override
-                public void onResponse(Void aVoid) {
-                  workerChannels.remove(finalIncomingChannel);
-                }
-
-                @Override
-                public void onFailure(Exception e) {
-                  workerChannels.remove(finalIncomingChannel);
-                }
-              });
-              serverAcceptedChannel(incomingChannel);
-              //establish a happens-before edge between closing and accepting a new connection
-              workerChannels.add(incomingChannel);
-
-              // this spawns a new thread immediately, so OK under lock
-              incomingChannel.loopRead(executor);
-              // the channel is properly registered and will be cleared by the close code.
-              incomingSocket = null;
-              incomingChannel = null;
-            }
-          }
-        } finally {
-          // ensure we don't leak sockets and channels in the failure case. Note that we null both
-          // if there are no exceptions so this becomes a no op.
-          IOUtils.closeWhileHandlingException(incomingSocket, incomingChannel);
-        }
-      }
-    }
-
-    void loopRead(Executor executor) {
-      executor.execute(new AbstractRunnable() {
-        @Override
-        public void onFailure(Exception e) {
-          if (isOpen.get()) {
-            try {
-              onException(MockChannel.this, e);
-            } catch (Exception ex) {
-              logger.warn("failed on handling exception", ex);
-              IOUtils.closeWhileHandlingException(MockChannel.this); // pure paranoia
-            }
-          }
-        }
-
-        @Override
-        protected void doRun() throws Exception {
-          StreamInput input = new InputStreamStreamInput(new BufferedInputStream(activeChannel.getInputStream()));
-          // There is a (slim) chance that we get interrupted right after a loop iteration, so check explicitly
-          while (isOpen.get() && !Thread.currentThread().isInterrupted()) {
-            cancellableThreads.executeIO(() -> readMessage(MockChannel.this, input));
-          }
-        }
-      });
-    }
-
-    synchronized void close0() throws IOException {
-      // establish a happens-before edge between closing and accepting a new connection
-      // we have to sync this entire block to ensure that our openChannels checks work correctly.
-      // The close block below will close all worker channels but if one of the worker channels runs into an exception
-      // for instance due to a disconnect the handling of this exception might be executed concurrently.
-      // now if we are in-turn concurrently call close we might not wait for the actual close to happen and that will, down the road
-      // make the assertion trip that not all channels are closed.
-      if (isOpen.compareAndSet(true, false)) {
-        final boolean removedChannel;
-        synchronized (openChannels) {
-          removedChannel = openChannels.remove(this);
-        }
-        IOUtils.close(serverSocket, activeChannel, () -> IOUtils.close(workerChannels),
-          () -> cancellableThreads.cancel("channel closed"));
-        assert removedChannel: "Channel was not removed or removed twice?";
-      }
-    }
-
-    @Override
-    public String toString() {
-      return "MockChannel{" +
-        "profile='" + profile + '\'' +
-        ", isOpen=" + isOpen +
-        ", localAddress=" + localAddress +
-        ", isServerSocket=" + (serverSocket != null) +
-        '}';
-    }
-
-    @Override
-    public void close() {
-      try {
-        close0();
-        closeFuture.complete(null);
-      } catch (IOException e) {
-        closeFuture.completeExceptionally(e);
-      }
-    }
-
-    @Override
-    public String getProfile() {
-      return profile;
-    }
-
-    @Override
-    public boolean isServerChannel() {
-      return isServer;
-    }
-
-    @Override
-    public void addCloseListener(ActionListener<Void> listener) {
-      closeFuture.addListener(ActionListener.toBiConsumer(listener));
-    }
-
-    @Override
-    public void addConnectListener(ActionListener<Void> listener) {
-      connectFuture.addListener(ActionListener.toBiConsumer(listener));
-    }
-
-    @Override
-    public ChannelStats getChannelStats() {
-      return stats;
-    }
-
-    @Override
-    public boolean isOpen() {
-      return isOpen.get();
-    }
-
-    @Override
-    public InetSocketAddress getLocalAddress() {
-      return localAddress;
-    }
-
-    @Override
-    public InetSocketAddress getRemoteAddress() {
-      return (InetSocketAddress) activeChannel.getRemoteSocketAddress();
-    }
-
-    @Override
-    public void sendMessage(BytesReference reference, ActionListener<Void> listener) {
-      try {
-        synchronized (this) {
-          OutputStream outputStream = new BufferedOutputStream(activeChannel.getOutputStream());
-          reference.writeTo(outputStream);
-          outputStream.flush();
-        }
-        listener.onResponse(null);
-      } catch (IOException e) {
-        listener.onFailure(e);
-        onException(this, e);
-      }
-    }
-  }
-
-
-  @Override
-  protected void doStart() {
-    boolean success = false;
-    try {
-      if (NetworkService.NETWORK_SERVER.get(settings)) {
-        // loop through all profiles and start them up, special handling for default one
-        for (ProfileSettings profileSettings : profileSettings) {
-          bindServer(profileSettings);
-        }
-      }
-      super.doStart();
-      success = true;
-    } finally {
-      if (success == false) {
-        doStop();
-      }
-    }
-  }
-
-  @Override
-  protected void stopInternal() {
-    ThreadPool.terminate(executor, 10, TimeUnit.SECONDS);
-    synchronized (openChannels) {
-      assert openChannels.isEmpty() : "there are still open channels: " + openChannels;
-    }
-  }
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/es/EsTester.java b/server/sonar-server-common/src/test/java/org/sonar/server/es/EsTester.java
deleted file mode 100644 (file)
index 9d69c04..0000000
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.es;
-
-import com.google.common.base.Throwables;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import org.apache.commons.lang.reflect.ConstructorUtils;
-import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
-import org.elasticsearch.action.bulk.BulkRequestBuilder;
-import org.elasticsearch.action.bulk.BulkResponse;
-import org.elasticsearch.action.index.IndexRequest;
-import org.elasticsearch.action.search.SearchRequestBuilder;
-import org.elasticsearch.action.search.SearchResponse;
-import org.elasticsearch.action.support.master.AcknowledgedResponse;
-import org.elasticsearch.analysis.common.CommonAnalysisPlugin;
-import org.elasticsearch.cluster.health.ClusterHealthStatus;
-import org.elasticsearch.cluster.routing.allocation.DiskThresholdSettings;
-import org.elasticsearch.common.Strings;
-import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
-import org.elasticsearch.common.network.NetworkModule;
-import org.elasticsearch.common.network.NetworkService;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.common.unit.TimeValue;
-import org.elasticsearch.common.util.BigArrays;
-import org.elasticsearch.common.util.PageCacheRecycler;
-import org.elasticsearch.discovery.DiscoveryModule;
-import org.elasticsearch.env.Environment;
-import org.elasticsearch.env.NodeEnvironment;
-import org.elasticsearch.index.IndexNotFoundException;
-import org.elasticsearch.index.query.QueryBuilder;
-import org.elasticsearch.index.query.TermQueryBuilder;
-import org.elasticsearch.indices.breaker.CircuitBreakerService;
-import org.elasticsearch.indices.recovery.RecoverySettings;
-import org.elasticsearch.join.ParentJoinPlugin;
-import org.elasticsearch.node.InternalSettingsPreparer;
-import org.elasticsearch.node.Node;
-import org.elasticsearch.plugins.NetworkPlugin;
-import org.elasticsearch.plugins.Plugin;
-import org.elasticsearch.search.SearchHit;
-import org.elasticsearch.threadpool.ThreadPool;
-import org.elasticsearch.transport.MockTcpTransport;
-import org.elasticsearch.transport.Transport;
-import org.junit.rules.ExternalResource;
-import org.sonar.server.component.index.ComponentIndexDefinition;
-import org.sonar.server.es.IndexDefinition.IndexDefinitionContext;
-import org.sonar.server.es.IndexType.IndexRelationType;
-import org.sonar.server.es.newindex.BuiltIndex;
-import org.sonar.server.es.newindex.NewIndex;
-import org.sonar.server.issue.index.IssueIndexDefinition;
-import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition;
-import org.sonar.server.rule.index.RuleIndexDefinition;
-import org.sonar.server.user.index.UserIndexDefinition;
-import org.sonar.server.view.index.ViewIndexDefinition;
-
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Lists.newArrayList;
-import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
-import static org.sonar.server.es.Index.ALL_INDICES;
-import static org.sonar.server.es.IndexType.FIELD_INDEX_TYPE;
-import static org.sonar.server.es.newindex.DefaultIndexSettings.REFRESH_IMMEDIATE;
-
-public class EsTester extends ExternalResource {
-
-  static {
-    System.setProperty("log4j.shutdownHookEnabled", "false");
-    // we can not shutdown logging when tests are running or the next test that runs within the
-    // same JVM will try to initialize logging after a security manager has been installed and
-    // this will fail
-    System.setProperty("es.log4j.shutdownEnabled", "false");
-    System.setProperty("log4j2.disable.jmx", "true");
-    System.setProperty("log4j.skipJansi", "true"); // jython has this crazy shaded Jansi version that log4j2 tries to load
-
-    if (!Strings.hasLength(System.getProperty("tests.es.logger.level"))) {
-      System.setProperty("tests.es.logger.level", "WARN");
-    }
-  }
-
-  private static final Node SHARED_NODE = createNode();
-  private static final AtomicBoolean CORE_INDICES_CREATED = new AtomicBoolean(false);
-  private static final Set<String> CORE_INDICES_NAMES = new HashSet<>();
-
-  private final boolean isCustom;
-
-  private EsTester(boolean isCustom) {
-    this.isCustom = isCustom;
-  }
-
-  /**
-   * New instance which contains the core indices (rules, issues, ...).
-   */
-  public static EsTester create() {
-    if (!CORE_INDICES_CREATED.get()) {
-      List<BuiltIndex> createdIndices = createIndices(
-        ComponentIndexDefinition.createForTest(),
-        IssueIndexDefinition.createForTest(),
-        ProjectMeasuresIndexDefinition.createForTest(),
-        RuleIndexDefinition.createForTest(),
-        UserIndexDefinition.createForTest(),
-        ViewIndexDefinition.createForTest());
-
-      CORE_INDICES_CREATED.set(true);
-      createdIndices.stream().map(t -> t.getMainType().getIndex().getName()).forEach(CORE_INDICES_NAMES::add);
-    }
-    return new EsTester(false);
-  }
-
-  /**
-   * New instance which contains the specified indices. Note that
-   * core indices may exist.
-   */
-  public static EsTester createCustom(IndexDefinition... definitions) {
-    createIndices(definitions);
-    return new EsTester(true);
-  }
-
-  @Override
-  protected void after() {
-    if (isCustom) {
-      // delete non-core indices
-      String[] existingIndices = SHARED_NODE.client().admin().indices().prepareGetIndex().get().getIndices();
-      Stream.of(existingIndices)
-        .filter(i -> !CORE_INDICES_NAMES.contains(i))
-        .forEach(EsTester::deleteIndexIfExists);
-    }
-    BulkIndexer.delete(client(), IndexType.main(ALL_INDICES, "dummy"), client().prepareSearch(ALL_INDICES).setQuery(matchAllQuery()));
-  }
-
-  public EsClient client() {
-    return new EsClient(SHARED_NODE.client());
-  }
-
-  public void putDocuments(IndexType indexType, BaseDoc... docs) {
-    try {
-      BulkRequestBuilder bulk = SHARED_NODE.client().prepareBulk()
-        .setRefreshPolicy(REFRESH_IMMEDIATE);
-      for (BaseDoc doc : docs) {
-        bulk.add(doc.toIndexRequest());
-      }
-      BulkResponse bulkResponse = bulk.get();
-      if (bulkResponse.hasFailures()) {
-        throw new IllegalStateException(bulkResponse.buildFailureMessage());
-      }
-    } catch (Exception e) {
-      throw Throwables.propagate(e);
-    }
-  }
-
-  public void putDocuments(IndexType indexType, Map<String, Object>... docs) {
-    try {
-      BulkRequestBuilder bulk = SHARED_NODE.client().prepareBulk()
-        .setRefreshPolicy(REFRESH_IMMEDIATE);
-      for (Map<String, Object> doc : docs) {
-        IndexType.IndexMainType mainType = indexType.getMainType();
-        bulk.add(new IndexRequest(mainType.getIndex().getName(), mainType.getType())
-          .source(doc));
-      }
-      BulkResponse bulkResponse = bulk.get();
-      if (bulkResponse.hasFailures()) {
-        throw new IllegalStateException(bulkResponse.buildFailureMessage());
-      }
-    } catch (Exception e) {
-      throw Throwables.propagate(e);
-    }
-  }
-
-  public long countDocuments(Index index) {
-    return client().prepareSearch(index)
-      .setQuery(matchAllQuery())
-      .setSize(0).get().getHits().getTotalHits();
-  }
-
-  public long countDocuments(IndexType indexType) {
-    return client().prepareSearch(indexType.getMainType())
-      .setQuery(getDocumentsQuery(indexType))
-      .setSize(0).get().getHits().getTotalHits();
-  }
-
-  /**
-   * Get all the indexed documents (no paginated results). Results are converted to BaseDoc objects.
-   * Results are not sorted.
-   */
-  public <E extends BaseDoc> List<E> getDocuments(IndexType indexType, final Class<E> docClass) {
-    List<SearchHit> hits = getDocuments(indexType);
-    return new ArrayList<>(Collections2.transform(hits, input -> {
-      try {
-        return (E) ConstructorUtils.invokeConstructor(docClass, input.getSourceAsMap());
-      } catch (Exception e) {
-        throw Throwables.propagate(e);
-      }
-    }));
-  }
-
-  /**
-   * Get all the indexed documents (no paginated results) in the specified index, whatever their type. Results are not sorted.
-   */
-  public List<SearchHit> getDocuments(Index index) {
-    SearchRequestBuilder req = SHARED_NODE.client()
-      .prepareSearch(index.getName())
-      .setQuery(matchAllQuery());
-    return getDocuments(req);
-  }
-
-  /**
-   * Get all the indexed documents (no paginated results) of the specified type. Results are not sorted.
-   */
-  public List<SearchHit> getDocuments(IndexType indexType) {
-    IndexType.IndexMainType mainType = indexType.getMainType();
-    SearchRequestBuilder req = SHARED_NODE.client()
-      .prepareSearch(mainType.getIndex().getName())
-      .setQuery(getDocumentsQuery(indexType));
-    return getDocuments(req);
-  }
-
-  private List<SearchHit> getDocuments(SearchRequestBuilder req) {
-    EsUtils.optimizeScrollRequest(req);
-    req.setScroll(new TimeValue(60000))
-      .setSize(100);
-
-    SearchResponse response = req.get();
-    List<SearchHit> result = newArrayList();
-    while (true) {
-      Iterables.addAll(result, response.getHits());
-      response = SHARED_NODE.client().prepareSearchScroll(response.getScrollId()).setScroll(new TimeValue(600000)).execute().actionGet();
-      // Break condition: No hits are returned
-      if (response.getHits().getHits().length == 0) {
-        break;
-      }
-    }
-    return result;
-  }
-
-  private QueryBuilder getDocumentsQuery(IndexType indexType) {
-    if (!indexType.getMainType().getIndex().acceptsRelations()) {
-      return matchAllQuery();
-    }
-
-    if (indexType instanceof IndexRelationType) {
-      return new TermQueryBuilder(FIELD_INDEX_TYPE, ((IndexRelationType) indexType).getName());
-    }
-    if (indexType instanceof IndexType.IndexMainType) {
-      return new TermQueryBuilder(FIELD_INDEX_TYPE, ((IndexType.IndexMainType) indexType).getType());
-    }
-    throw new IllegalArgumentException("Unsupported IndexType " + indexType.getClass());
-  }
-
-  /**
-   * Get a list of a specific field from all indexed documents.
-   */
-  public <T> List<T> getDocumentFieldValues(IndexType indexType, final String fieldNameToReturn) {
-    return getDocuments(indexType)
-      .stream()
-      .map(input -> (T) input.getSourceAsMap().get(fieldNameToReturn))
-      .collect(Collectors.toList());
-  }
-
-  public List<String> getIds(IndexType indexType) {
-    return getDocuments(indexType).stream().map(SearchHit::getId).collect(Collectors.toList());
-  }
-
-  public void lockWrites(IndexType index) {
-    setIndexSettings(index.getMainType().getIndex().getName(), ImmutableMap.of("index.blocks.write", "true"));
-  }
-
-  public void unlockWrites(IndexType index) {
-    setIndexSettings(index.getMainType().getIndex().getName(), ImmutableMap.of("index.blocks.write", "false"));
-  }
-
-  private void setIndexSettings(String index, Map<String, Object> settings) {
-    AcknowledgedResponse response = SHARED_NODE.client().admin().indices()
-      .prepareUpdateSettings(index)
-      .setSettings(settings)
-      .get();
-    checkState(response.isAcknowledged());
-  }
-
-  private static void deleteIndexIfExists(String name) {
-    try {
-      AcknowledgedResponse response = SHARED_NODE.client().admin().indices().prepareDelete(name).get();
-      checkState(response.isAcknowledged(), "Fail to drop the index " + name);
-    } catch (IndexNotFoundException e) {
-      // ignore
-    }
-  }
-
-  private static List<BuiltIndex> createIndices(IndexDefinition... definitions) {
-    IndexDefinitionContext context = new IndexDefinitionContext();
-    Stream.of(definitions).forEach(d -> d.define(context));
-
-    List<BuiltIndex> result = new ArrayList<>();
-    for (NewIndex newIndex : context.getIndices().values()) {
-      BuiltIndex index = newIndex.build();
-
-      String indexName = index.getMainType().getIndex().getName();
-      deleteIndexIfExists(indexName);
-
-      // create index
-      Settings.Builder settings = Settings.builder();
-      settings.put(index.getSettings());
-      CreateIndexResponse indexResponse = SHARED_NODE.client().admin().indices()
-        .prepareCreate(indexName)
-        .setSettings(settings)
-        .get();
-      if (!indexResponse.isAcknowledged()) {
-        throw new IllegalStateException("Failed to create index " + indexName);
-      }
-      SHARED_NODE.client().admin().cluster().prepareHealth(indexName).setWaitForStatus(ClusterHealthStatus.YELLOW).get();
-
-      // create types
-      String typeName = index.getMainType().getType();
-      AcknowledgedResponse mappingResponse = SHARED_NODE.client().admin().indices().preparePutMapping(indexName)
-        .setType(typeName)
-        .setSource(index.getAttributes())
-        .get();
-      if (!mappingResponse.isAcknowledged()) {
-        throw new IllegalStateException("Failed to create type " + typeName);
-      }
-      SHARED_NODE.client().admin().cluster().prepareHealth(indexName).setWaitForStatus(ClusterHealthStatus.YELLOW).get();
-      result.add(index);
-    }
-    return result;
-  }
-
-  private static Node createNode() {
-    try {
-      Path tempDir = Files.createTempDirectory("EsTester");
-      tempDir.toFile().deleteOnExit();
-      Settings settings = Settings.builder()
-        .put(Environment.PATH_HOME_SETTING.getKey(), tempDir)
-        .put("node.name", "EsTester")
-        .put(NodeEnvironment.MAX_LOCAL_STORAGE_NODES_SETTING.getKey(), Integer.MAX_VALUE)
-        .put("logger.level", "INFO")
-        .put("action.auto_create_index", false)
-        // Default the watermarks to absurdly low to prevent the tests
-        // from failing on nodes without enough disk space
-        .put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "1b")
-        .put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "1b")
-        .put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(), "1b")
-        // always reduce this - it can make tests really slow
-        .put(RecoverySettings.INDICES_RECOVERY_RETRY_DELAY_STATE_SYNC_SETTING.getKey(), TimeValue.timeValueMillis(20))
-        .put(NetworkModule.TRANSPORT_TYPE_KEY, "local")
-        .put(NetworkModule.HTTP_ENABLED.getKey(), false)
-        .put(DiscoveryModule.DISCOVERY_TYPE_SETTING.getKey(), "single-node")
-        .build();
-      Node node = new Node(InternalSettingsPreparer.prepareEnvironment(settings, null),
-        ImmutableList.of(
-          CommonAnalysisPlugin.class,
-          // mock local transport plugin
-          MockTcpTransportPlugin.class,
-          // install ParentJoin plugin required to create field of type "join"
-          ParentJoinPlugin.class),
-        true) {
-        @Override
-        protected void registerDerivedNodeNameWithLogger(String nodeName) {
-          // nothing to do
-        }
-      };
-      return node.start();
-    } catch (Exception e) {
-      throw new IllegalStateException("Fail to start embedded Elasticsearch", e);
-    }
-  }
-
-  public static final class MockTcpTransportPlugin extends Plugin implements NetworkPlugin {
-    @Override
-    public Map<String, Supplier<Transport>> getTransports(Settings settings, ThreadPool threadPool, PageCacheRecycler pageCacheRecycler,
-      CircuitBreakerService circuitBreakerService, NamedWriteableRegistry namedWriteableRegistry, NetworkService networkService) {
-      return Collections.singletonMap(
-        "local",
-        () -> new MockTcpTransport(settings, threadPool, BigArrays.NON_RECYCLING_INSTANCE, circuitBreakerService, namedWriteableRegistry, networkService));
-    }
-  }
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/es/FakeDoc.java b/server/sonar-server-common/src/test/java/org/sonar/server/es/FakeDoc.java
deleted file mode 100644 (file)
index d199ed9..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.es;
-
-import com.google.common.collect.Maps;
-
-import static org.sonar.server.es.newindex.FakeIndexDefinition.INT_FIELD;
-import static org.sonar.server.es.newindex.FakeIndexDefinition.TYPE_FAKE;
-
-public class FakeDoc extends BaseDoc {
-  public FakeDoc() {
-    super(TYPE_FAKE, Maps.newHashMap());
-  }
-
-  @Override
-  public String getId() {
-    return null;
-  }
-
-  public int getInt() {
-    return getField(INT_FIELD);
-  }
-
-  public FakeDoc setInt(int i) {
-    setField(INT_FIELD, i);
-    return this;
-  }
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/es/TestProjectIndexers.java b/server/sonar-server-common/src/test/java/org/sonar/server/es/TestProjectIndexers.java
deleted file mode 100644 (file)
index fb85891..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.es;
-
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.ListMultimap;
-import java.util.Collection;
-import org.sonar.db.DbSession;
-
-public class TestProjectIndexers implements ProjectIndexers {
-
-  private final ListMultimap<String, ProjectIndexer.Cause> calls = ArrayListMultimap.create();
-
-  @Override
-  public void commitAndIndexByProjectUuids(DbSession dbSession, Collection<String> projectUuids, ProjectIndexer.Cause cause) {
-    dbSession.commit();
-    projectUuids.forEach(projectUuid -> calls.put(projectUuid, cause));
-
-  }
-
-  public boolean hasBeenCalled(String projectUuid, ProjectIndexer.Cause expectedCause) {
-    return calls.get(projectUuid).contains(expectedCause);
-  }
-
-  public boolean hasBeenCalled(String projectUuid) {
-    return calls.containsKey(projectUuid);
-  }
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/es/newindex/FakeIndexDefinition.java b/server/sonar-server-common/src/test/java/org/sonar/server/es/newindex/FakeIndexDefinition.java
deleted file mode 100644 (file)
index d6dfd76..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.es.newindex;
-
-import org.elasticsearch.cluster.metadata.IndexMetaData;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.server.es.FakeDoc;
-import org.sonar.server.es.Index;
-import org.sonar.server.es.IndexDefinition;
-import org.sonar.server.es.IndexType;
-import org.sonar.server.es.IndexType.IndexMainType;
-
-import static org.sonar.server.es.newindex.SettingsConfiguration.newBuilder;
-
-public class FakeIndexDefinition implements IndexDefinition {
-
-  public static final String INDEX = "fakes";
-  public static final String TYPE = "fake";
-  public static final Index DESCRIPTOR = Index.simple(INDEX);
-  public static final IndexMainType TYPE_FAKE = IndexType.main(DESCRIPTOR, TYPE);
-  public static final String INT_FIELD = "intField";
-
-  private int replicas = 0;
-
-  public FakeIndexDefinition setReplicas(int replicas) {
-    this.replicas = replicas;
-    return this;
-  }
-
-  @Override
-  public void define(IndexDefinitionContext context) {
-    NewIndex index = context.create(DESCRIPTOR, newBuilder(new MapSettings().asConfig()).build());
-    index.getSettings().put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, replicas);
-    index.getSettings().put("index.refresh_interval", "-1");
-    index.createTypeMapping(TYPE_FAKE)
-      .createIntegerField(INT_FIELD);
-  }
-
-  public static FakeDoc newDoc(int value) {
-    return new FakeDoc().setInt(value);
-  }
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/es/textsearch/ComponentTextSearchFeatureRule.java b/server/sonar-server-common/src/test/java/org/sonar/server/es/textsearch/ComponentTextSearchFeatureRule.java
deleted file mode 100644 (file)
index 60ddbdb..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.es.textsearch;
-
-import org.junit.rules.ExternalResource;
-
-public class ComponentTextSearchFeatureRule extends ExternalResource {
-
-  private ComponentTextSearchFeature[] features;
-
-  @Override
-  protected void before() {
-    features = ComponentTextSearchFeatureRepertoire.values();
-  }
-
-  public ComponentTextSearchFeature[] get() {
-    return features;
-  }
-
-  public void set(ComponentTextSearchFeature... features) {
-    this.features = features;
-  }
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/IssueDocTesting.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/IssueDocTesting.java
deleted file mode 100644 (file)
index c63f12e..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.issue;
-
-import com.google.common.collect.Maps;
-import java.util.Date;
-import org.sonar.api.resources.Scopes;
-import org.sonar.api.rule.Severity;
-import org.sonar.api.rules.RuleType;
-import org.sonar.core.util.Uuids;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.server.issue.index.IssueDoc;
-
-import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
-import static org.apache.commons.lang.math.RandomUtils.nextInt;
-import static org.sonar.api.issue.Issue.STATUS_OPEN;
-
-public class IssueDocTesting {
-
-  public static IssueDoc newDoc(ComponentDto componentDto) {
-    return newDoc(Uuids.createFast(), componentDto);
-  }
-
-  public static IssueDoc newDoc(String key, ComponentDto componentDto) {
-    String mainBranchProjectUuid = componentDto.getMainBranchProjectUuid();
-    return newDoc()
-      .setKey(key)
-      .setBranchUuid(componentDto.projectUuid())
-      .setComponentUuid(componentDto.uuid())
-      .setModuleUuid(!componentDto.scope().equals(Scopes.PROJECT) ? componentDto.moduleUuid() : componentDto.uuid())
-      .setModuleUuidPath(componentDto.moduleUuidPath())
-      .setProjectUuid(mainBranchProjectUuid == null ? componentDto.projectUuid() : mainBranchProjectUuid)
-      .setOrganizationUuid(componentDto.getOrganizationUuid())
-      // File path make no sens on modules and projects
-      .setFilePath(!componentDto.scope().equals(Scopes.PROJECT) ? componentDto.path() : null)
-      .setIsMainBranch(mainBranchProjectUuid == null);
-  }
-
-  public static IssueDoc newDoc() {
-    IssueDoc doc = new IssueDoc(Maps.newHashMap());
-    doc.setKey(Uuids.createFast());
-    doc.setRuleId(nextInt(1000));
-    doc.setType(RuleType.CODE_SMELL);
-    doc.setAssigneeUuid("assignee_uuid_" + randomAlphabetic(26));
-    doc.setAuthorLogin("author_" + randomAlphabetic(5));
-    doc.setLanguage("language_" + randomAlphabetic(5));
-    doc.setComponentUuid(Uuids.createFast());
-    doc.setFilePath("filePath_" + randomAlphabetic(5));
-    doc.setDirectoryPath("directory_" + randomAlphabetic(5));
-    doc.setModuleUuid(Uuids.createFast());
-    doc.setModuleUuidPath(Uuids.createFast());
-    doc.setProjectUuid(Uuids.createFast());
-    doc.setLine(nextInt(1_000) + 1);
-    doc.setStatus(STATUS_OPEN);
-    doc.setResolution(null);
-    doc.setSeverity(Severity.ALL.get(nextInt(Severity.ALL.size())));
-    doc.setEffort((long) nextInt(10));
-    doc.setFuncCreationDate(new Date(System.currentTimeMillis() - 2_000));
-    doc.setFuncUpdateDate(new Date(System.currentTimeMillis() - 1_000));
-    doc.setFuncCloseDate(null);
-    return doc;
-  }
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/IssuesChangesNotificationBuilderTesting.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/IssuesChangesNotificationBuilderTesting.java
deleted file mode 100644 (file)
index 43f5cbf..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.issue.notification;
-
-import java.util.Random;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.db.DbTester;
-import org.sonar.db.component.BranchDto;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.rule.RuleDefinitionDto;
-import org.sonar.db.rule.RuleDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.AnalysisChange;
-import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.ChangedIssue;
-import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.Project;
-import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.Rule;
-import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.User;
-import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.UserChange;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
-
-public class IssuesChangesNotificationBuilderTesting {
-
-  public static Rule ruleOf(RuleDto rule) {
-    return new Rule(rule.getKey(), rule.getName());
-  }
-
-  public static Rule ruleOf(RuleDefinitionDto rule) {
-    return new Rule(rule.getKey(), rule.getName());
-  }
-
-  public static User userOf(UserDto changeAuthor) {
-    return new User(changeAuthor.getUuid(), changeAuthor.getLogin(), changeAuthor.getName());
-  }
-
-  public static Project projectBranchOf(DbTester db, ComponentDto branch) {
-    BranchDto branchDto = db.getDbClient().branchDao().selectByUuid(db.getSession(), branch.uuid()).get();
-    checkArgument(!branchDto.isMain(), "should be a branch");
-    return new Project.Builder(branch.uuid())
-      .setKey(branch.getKey())
-      .setProjectName(branch.name())
-      .setBranchName(branchDto.getKey())
-      .build();
-  }
-
-  public static Project projectOf(ComponentDto project) {
-    return new Project.Builder(project.uuid())
-      .setKey(project.getKey())
-      .setProjectName(project.name())
-      .build();
-  }
-
-  static ChangedIssue newChangedIssue(String key, Project project, Rule rule) {
-    return new ChangedIssue.Builder(key)
-      .setNewStatus(randomAlphabetic(19))
-      .setProject(project)
-      .setRule(rule)
-      .build();
-  }
-
-  static ChangedIssue newChangedIssue(String key, String status, Project project, String ruleName) {
-    return newChangedIssue(key, status, project, newRule(ruleName));
-  }
-
-  static ChangedIssue newChangedIssue(String key, String status, Project project, Rule rule) {
-    return new ChangedIssue.Builder(key)
-      .setNewStatus(status)
-      .setProject(project)
-      .setRule(rule)
-      .build();
-  }
-
-  static Rule newRule(String ruleName) {
-    return new Rule(RuleKey.of(randomAlphabetic(6), randomAlphabetic(7)), ruleName);
-  }
-
-  static Project newProject(String uuid) {
-    return new Project.Builder(uuid).setProjectName(uuid + "_name").setKey(uuid + "_key").build();
-  }
-
-  static Project newBranch(String uuid, String branchName) {
-    return new Project.Builder(uuid).setProjectName(uuid + "_name").setKey(uuid + "_key").setBranchName(branchName).build();
-  }
-
-  static UserChange newUserChange() {
-    return new UserChange(new Random().nextLong(), new User(randomAlphabetic(4), randomAlphabetic(5), randomAlphabetic(6)));
-  }
-
-  static AnalysisChange newAnalysisChange() {
-    return new AnalysisChange(new Random().nextLong());
-  }
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/l18n/I18nRule.java b/server/sonar-server-common/src/test/java/org/sonar/server/l18n/I18nRule.java
deleted file mode 100644 (file)
index f81a2f0..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.l18n;
-
-import java.text.MessageFormat;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-import org.sonar.core.i18n.I18n;
-
-public class I18nRule implements TestRule, I18n {
-  private final Map<String, String> messages = new HashMap<>();
-
-  public I18nRule put(String key, String value) {
-    messages.put(key, value);
-    return this;
-  }
-
-  @Override
-  public Statement apply(final Statement statement, Description description) {
-    return new Statement() {
-      @Override
-      public void evaluate() throws Throwable {
-        try {
-          statement.evaluate();
-        } finally {
-          messages.clear();
-        }
-      }
-    };
-  }
-
-  public void setProjectPermissions() {
-    put("projects_role.admin", "Administer");
-    put("projects_role.admin.desc", "Ability to access project settings and perform administration tasks. " +
-      "(Users will also need \"Browse\" permission)");
-    put("projects_role.issueadmin", "Administer Issues");
-    put("projects_role.issueadmin.desc", "Grants the permission to perform advanced editing on issues: marking an issue " +
-      "False Positive / Won't Fix or changing an Issue's severity. (Users will also need \"Browse\" permission)");
-    put("projects_role.securityhotspotadmin", "Administer Security Hotspots");
-    put("projects_role.securityhotspotadmin.desc", "Detect a Vulnerability from a \"Security Hotspot\". Reject, clear, accept, reopen a \"Security Hotspot\" (users also need \"Browse\" permissions).");
-    put("projects_role.applicationcreator", "Create Applications");
-    put("projects_role.applicationcreator.desc", "Allow to create applications for non system administrator.");
-    put("projects_role.portfoliocreator", "Create Portfolios");
-    put("projects_role.portfoliocreator.desc", "Allow to create portfolios for non system administrator.");
-    put("projects_role.user", "Browse");
-    put("projects_role.user.desc", "Ability to access a project, browse its measures, and create/edit issues for it.");
-    put("projects_role.codeviewer", "See Source Code");
-    put("projects_role.codeviewer.desc", "Ability to view the project's source code. (Users will also need \"Browse\" permission)");
-    put("projects_role.scan", "Execute Analysis");
-    put("projects_role.scan.desc",
-      "Ability to execute analyses, and to get all settings required to perform the analysis, even the secured ones like the scm account password, the jira account password, and so on.");
-  }
-
-  @Override
-  public String message(Locale locale, String key, @Nullable String defaultValue, Object... parameters) {
-    String messageInMap = messages.get(key);
-    String message = messageInMap != null ? messageInMap : defaultValue;
-    return formatMessage(message, parameters);
-  }
-
-  @CheckForNull
-  private static String formatMessage(@Nullable String message, Object... parameters) {
-    if (message == null || parameters.length == 0) {
-      return message;
-    }
-    return MessageFormat.format(message.replaceAll("'", "''"), parameters);
-  }
-
-  @Override
-  public String age(Locale locale, long durationInMillis) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public String age(Locale locale, Date fromDate, Date toDate) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public String ageFromNow(Locale locale, Date date) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public String formatDateTime(Locale locale, Date date) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public String formatDate(Locale locale, Date date) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public String formatDouble(Locale locale, Double value) {
-    return String.valueOf(value);
-  }
-
-  @Override
-  public String formatInteger(Locale locale, Integer value) {
-    return String.valueOf(value);
-  }
-
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/organization/TestDefaultOrganizationProvider.java b/server/sonar-server-common/src/test/java/org/sonar/server/organization/TestDefaultOrganizationProvider.java
deleted file mode 100644 (file)
index a5b5231..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.organization;
-
-import java.util.Date;
-import org.sonar.db.DbTester;
-import org.sonar.db.organization.OrganizationDto;
-
-public class TestDefaultOrganizationProvider implements DefaultOrganizationProvider {
-
-  private final DefaultOrganizationProvider delegate;
-
-  private TestDefaultOrganizationProvider(DefaultOrganizationProvider delegate) {
-    this.delegate = delegate;
-  }
-
-  public static TestDefaultOrganizationProvider from(DbTester dbTester) {
-    return new TestDefaultOrganizationProvider(new DbTesterDefaultOrganizationProvider(dbTester));
-  }
-
-  public static TestDefaultOrganizationProvider fromUuid(String uuid) {
-    long createdAt = new Date().getTime();
-    return new TestDefaultOrganizationProvider(
-      new ImmutableDefaultOrganizationProvider(
-        DefaultOrganization.newBuilder()
-          .setUuid(uuid)
-          .setKey("key_" + uuid)
-          .setName("name_" + uuid)
-          .setCreatedAt(createdAt)
-          .setUpdatedAt(createdAt)
-          .build()));
-  }
-
-  @Override
-  public DefaultOrganization get() {
-    return delegate.get();
-  }
-
-  private static final class ImmutableDefaultOrganizationProvider implements DefaultOrganizationProvider {
-    private final DefaultOrganization defaultOrganization;
-
-    private ImmutableDefaultOrganizationProvider(DefaultOrganization defaultOrganization) {
-      this.defaultOrganization = defaultOrganization;
-    }
-
-    @Override
-    public DefaultOrganization get() {
-      return defaultOrganization;
-    }
-  }
-
-  private static final class DbTesterDefaultOrganizationProvider implements DefaultOrganizationProvider {
-    private final DbTester dbTester;
-    private DefaultOrganization defaultOrganization = null;
-
-    private DbTesterDefaultOrganizationProvider(DbTester dbTester) {
-      this.dbTester = dbTester;
-    }
-
-    @Override
-    public DefaultOrganization get() {
-      if (defaultOrganization == null) {
-        defaultOrganization = toDefaultOrganization(dbTester.getDefaultOrganization());
-      }
-      return defaultOrganization;
-    }
-
-    private static DefaultOrganization toDefaultOrganization(OrganizationDto organizationDto) {
-      return DefaultOrganization.newBuilder()
-        .setUuid(organizationDto.getUuid())
-        .setKey(organizationDto.getKey())
-        .setName(organizationDto.getName())
-        .setCreatedAt(organizationDto.getCreatedAt())
-        .setUpdatedAt(organizationDto.getUpdatedAt())
-        .build();
-    }
-  }
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/organization/TestOrganizationFlags.java b/server/sonar-server-common/src/test/java/org/sonar/server/organization/TestOrganizationFlags.java
deleted file mode 100644 (file)
index f5a6d71..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.organization;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.sonar.db.DbSession;
-
-import static org.sonar.server.organization.OrganizationFlagsImpl.FAILURE_MESSAGE_DISABLED;
-import static org.sonar.server.organization.OrganizationFlagsImpl.FAILURE_MESSAGE_ENABLED;
-
-public class TestOrganizationFlags implements OrganizationFlags {
-
-  private final AtomicBoolean enabled = new AtomicBoolean(false);
-
-  private TestOrganizationFlags() {
-  }
-
-  @Override
-  public boolean isEnabled(DbSession dbSession) {
-    return enabled.get();
-  }
-
-  public TestOrganizationFlags setEnabled(boolean b) {
-    this.enabled.set(b);
-    return this;
-  }
-
-  @Override
-  public void enable(DbSession dbSession) {
-    setEnabled(true);
-  }
-
-  @Override
-  public void checkEnabled(DbSession dbSession) {
-    if (!isEnabled(dbSession)) {
-      throw new IllegalStateException(FAILURE_MESSAGE_DISABLED);
-    }
-  }
-
-  @Override
-  public void checkDisabled(DbSession dbSession) {
-    if (isEnabled(dbSession)) {
-      throw new IllegalStateException(FAILURE_MESSAGE_ENABLED);
-    }
-  }
-
-  /**
-   * By default Organization support is disabled
-   */
-  public static TestOrganizationFlags standalone() {
-    return new TestOrganizationFlags();
-  }
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/platform/monitoring/SystemInfoTesting.java b/server/sonar-server-common/src/test/java/org/sonar/server/platform/monitoring/SystemInfoTesting.java
deleted file mode 100644 (file)
index a438af7..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.platform.monitoring;
-
-import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.process.systeminfo.SystemInfoUtils.attribute;
-
-public class SystemInfoTesting {
-
-  private SystemInfoTesting() {
-    // do not instantiate
-  }
-
-  public static void assertThatAttributeIs(ProtobufSystemInfo.Section section, String key, String expectedValue) {
-    ProtobufSystemInfo.Attribute value = attribute(section, key);
-    assertThat(value).as(key).isNotNull();
-    assertThat(value.getStringValue()).isEqualTo(expectedValue);
-  }
-
-  public static void assertThatAttributeIs(ProtobufSystemInfo.Section section, String key, boolean expectedValue) {
-    ProtobufSystemInfo.Attribute value = attribute(section, key);
-    assertThat(value).as(key).isNotNull();
-    assertThat(value.getBooleanValue()).isEqualTo(expectedValue);
-  }
-
-  public static void assertThatAttributeIs(ProtobufSystemInfo.Section section, String key, long expectedValue) {
-    ProtobufSystemInfo.Attribute value = attribute(section, key);
-    assertThat(value).as(key).isNotNull();
-    assertThat(value.getLongValue()).isEqualTo(expectedValue);
-  }
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/platform/monitoring/cluster/TestGlobalSystemInfoSection.java b/server/sonar-server-common/src/test/java/org/sonar/server/platform/monitoring/cluster/TestGlobalSystemInfoSection.java
deleted file mode 100644 (file)
index 534c0f5..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.platform.monitoring.cluster;
-
-import org.sonar.process.systeminfo.Global;
-import org.sonar.process.systeminfo.SystemInfoSection;
-import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
-
-class TestGlobalSystemInfoSection implements SystemInfoSection, Global {
-  private final String name;
-
-  TestGlobalSystemInfoSection(String name) {
-    this.name = name;
-  }
-
-  @Override
-  public ProtobufSystemInfo.Section toProtobuf() {
-    return ProtobufSystemInfo.Section.newBuilder().setName(name).build();
-  }
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/platform/monitoring/cluster/TestSystemInfoSection.java b/server/sonar-server-common/src/test/java/org/sonar/server/platform/monitoring/cluster/TestSystemInfoSection.java
deleted file mode 100644 (file)
index 0ae8b3a..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.platform.monitoring.cluster;
-
-import org.sonar.process.systeminfo.SystemInfoSection;
-import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
-
-class TestSystemInfoSection implements SystemInfoSection {
-  private final String name;
-
-  TestSystemInfoSection(String name) {
-    this.name = name;
-  }
-
-  @Override
-  public ProtobufSystemInfo.Section toProtobuf() {
-    return ProtobufSystemInfo.Section.newBuilder().setName(name).build();
-  }
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/source/index/FileSourceTesting.java b/server/sonar-server-common/src/test/java/org/sonar/server/source/index/FileSourceTesting.java
deleted file mode 100644 (file)
index 8662438..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.source.index;
-
-import java.util.Arrays;
-import org.sonar.db.protobuf.DbFileSources;
-
-public class FileSourceTesting {
-
-  private FileSourceTesting() {
-    // only static stuff
-  }
-
-  /**
-   * Generate predefined fake data. Result is mutable.
-   */
-  public static DbFileSources.Data.Builder newFakeData(int numberOfLines) {
-    DbFileSources.Data.Builder dataBuilder = DbFileSources.Data.newBuilder();
-    for (int i = 1; i <= numberOfLines; i++) {
-      dataBuilder.addLinesBuilder()
-        .setLine(i)
-        .setScmRevision("REVISION_" + i)
-        .setScmAuthor("AUTHOR_" + i)
-        .setScmDate(1_500_000_000_00L + i)
-        .setSource("SOURCE_" + i)
-        .setLineHits(i)
-        .setConditions(i + 1)
-        .setCoveredConditions(i + 2)
-        .setHighlighting("HIGHLIGHTING_" + i)
-        .setSymbols("SYMBOLS_" + i)
-        .addAllDuplication(Arrays.asList(i))
-        .setIsNewLine(true)
-        .build();
-    }
-    return dataBuilder;
-  }
-
-}
diff --git a/server/sonar-server-common/src/testFixtures/java/org/elasticsearch/transport/MockTcpTransport.java b/server/sonar-server-common/src/testFixtures/java/org/elasticsearch/transport/MockTcpTransport.java
new file mode 100644 (file)
index 0000000..b5d89ef
--- /dev/null
@@ -0,0 +1,495 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.elasticsearch.transport;
+
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you 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.
+ */
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.Closeable;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.elasticsearch.Version;
+import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.cli.SuppressForbidden;
+import org.elasticsearch.cluster.node.DiscoveryNode;
+import org.elasticsearch.common.bytes.BytesArray;
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.concurrent.CompletableContext;
+import org.elasticsearch.common.io.stream.BytesStreamOutput;
+import org.elasticsearch.common.io.stream.InputStreamStreamInput;
+import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
+import org.elasticsearch.common.io.stream.ReleasableBytesStreamOutput;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.network.NetworkService;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.unit.ByteSizeValue;
+import org.elasticsearch.common.util.BigArrays;
+import org.elasticsearch.common.util.CancellableThreads;
+import org.elasticsearch.common.util.PageCacheRecycler;
+import org.elasticsearch.common.util.concurrent.AbstractRunnable;
+import org.elasticsearch.common.util.concurrent.EsExecutors;
+import org.elasticsearch.core.internal.io.IOUtils;
+import org.elasticsearch.indices.breaker.CircuitBreakerService;
+import org.elasticsearch.mocksocket.MockServerSocket;
+import org.elasticsearch.mocksocket.MockSocket;
+import org.elasticsearch.threadpool.ThreadPool;
+
+/**
+ * This is a socket based blocking TcpTransport implementation that is used for tests
+ * that need real networking. This implementation is a test only implementation that implements
+ * the networking layer in the worst possible way since it blocks and uses a thread per request model.
+ */
+public class MockTcpTransport extends TcpTransport {
+  private static final Logger logger = LogManager.getLogger(MockTcpTransport.class);
+
+  /**
+   * A pre-built light connection profile that shares a single connection across all
+   * types.
+   */
+  static final ConnectionProfile LIGHT_PROFILE;
+
+  private final Set<MockChannel> openChannels = new HashSet<>();
+
+  static {
+    ConnectionProfile.Builder builder = new ConnectionProfile.Builder();
+    builder.addConnections(1,
+      TransportRequestOptions.Type.BULK,
+      TransportRequestOptions.Type.PING,
+      TransportRequestOptions.Type.RECOVERY,
+      TransportRequestOptions.Type.REG,
+      TransportRequestOptions.Type.STATE);
+    LIGHT_PROFILE = builder.build();
+  }
+
+  private final ExecutorService executor;
+
+  public MockTcpTransport(Settings settings, ThreadPool threadPool, BigArrays bigArrays,
+                          CircuitBreakerService circuitBreakerService, NamedWriteableRegistry namedWriteableRegistry,
+                          NetworkService networkService) {
+    this(settings, threadPool, bigArrays, circuitBreakerService, namedWriteableRegistry, networkService, Version.CURRENT);
+  }
+
+  public MockTcpTransport(Settings settings, ThreadPool threadPool, BigArrays bigArrays,
+                          CircuitBreakerService circuitBreakerService, NamedWriteableRegistry namedWriteableRegistry,
+                          NetworkService networkService, Version mockVersion) {
+    super("mock-tcp-transport", settings, mockVersion, threadPool, PageCacheRecycler.NON_RECYCLING_INSTANCE, circuitBreakerService,
+      namedWriteableRegistry, networkService);
+    // we have our own crazy cached threadpool this one is not bounded at all...
+    // using the ES thread factory here is crucial for tests otherwise disruption tests won't block that thread
+    executor = Executors.newCachedThreadPool(EsExecutors.daemonThreadFactory(settings, Transports.TEST_MOCK_TRANSPORT_THREAD_PREFIX));
+  }
+
+  @Override
+  protected MockChannel bind(final String name, InetSocketAddress address) throws IOException {
+    MockServerSocket socket = new MockServerSocket();
+    socket.setReuseAddress(TransportSettings.TCP_REUSE_ADDRESS.get(settings));
+    ByteSizeValue tcpReceiveBufferSize = TransportSettings.TCP_RECEIVE_BUFFER_SIZE.get(settings);
+    if (tcpReceiveBufferSize.getBytes() > 0) {
+      socket.setReceiveBufferSize(tcpReceiveBufferSize.bytesAsInt());
+    }
+    socket.bind(address);
+    MockChannel serverMockChannel = new MockChannel(socket, name);
+    CountDownLatch started = new CountDownLatch(1);
+    executor.execute(new AbstractRunnable() {
+      @Override
+      public void onFailure(Exception e) {
+        onException(serverMockChannel, e);
+      }
+
+      @Override
+      protected void doRun() throws Exception {
+        started.countDown();
+        serverMockChannel.accept(executor);
+      }
+    });
+    try {
+      started.await();
+    } catch (InterruptedException e) {
+      Thread.currentThread().interrupt();
+    }
+    return serverMockChannel;
+  }
+
+  private void readMessage(MockChannel mockChannel, StreamInput input) throws IOException {
+    Socket socket = mockChannel.activeChannel;
+    byte[] minimalHeader = new byte[TcpHeader.MARKER_BYTES_SIZE + TcpHeader.MESSAGE_LENGTH_SIZE];
+    try {
+      input.readFully(minimalHeader);
+    } catch (EOFException eof) {
+      throw new IOException("Connection reset by peer");
+    }
+
+    // Read message length will throw stream corrupted exception if the marker bytes incorrect
+    int msgSize = TcpTransport.readMessageLength(new BytesArray(minimalHeader));
+    if (msgSize == -1) {
+      socket.getOutputStream().flush();
+    } else {
+      final byte[] buffer = new byte[msgSize];
+      input.readFully(buffer);
+      int expectedSize = TcpHeader.MARKER_BYTES_SIZE + TcpHeader.MESSAGE_LENGTH_SIZE + msgSize;
+      try (BytesStreamOutput output = new ReleasableBytesStreamOutput(expectedSize, bigArrays)) {
+        output.write(minimalHeader);
+        output.write(buffer);
+        consumeNetworkReads(mockChannel, output.bytes());
+      }
+    }
+  }
+
+  @Override
+  @SuppressForbidden(reason = "real socket for mocking remote connections")
+  protected MockChannel initiateChannel(DiscoveryNode node) throws IOException {
+    InetSocketAddress address = node.getAddress().address();
+    final MockSocket socket = new MockSocket();
+    final MockChannel channel = new MockChannel(socket, address, false, "none");
+
+    boolean success = false;
+    try {
+      configureSocket(socket);
+      success = true;
+    } finally {
+      if (success == false) {
+        IOUtils.close(socket);
+      }
+    }
+
+    executor.submit(() -> {
+      try {
+        socket.connect(address);
+        socket.setSoLinger(false, 0);
+        channel.connectFuture.complete(null);
+        channel.loopRead(executor);
+      } catch (Exception ex) {
+        channel.connectFuture.completeExceptionally(ex);
+      }
+    });
+
+    return channel;
+  }
+
+  @Override
+  protected ConnectionProfile maybeOverrideConnectionProfile(ConnectionProfile connectionProfile) {
+    ConnectionProfile.Builder builder = new ConnectionProfile.Builder();
+    Set<TransportRequestOptions.Type> allTypesWithConnection = new HashSet<>();
+    Set<TransportRequestOptions.Type> allTypesWithoutConnection = new HashSet<>();
+    for (ConnectionProfile.ConnectionTypeHandle handle : connectionProfile.getHandles()) {
+      Set<TransportRequestOptions.Type> types = handle.getTypes();
+      if (handle.length > 0) {
+        allTypesWithConnection.addAll(types);
+      } else {
+        allTypesWithoutConnection.addAll(types);
+      }
+    }
+    // make sure we maintain at least the types that are supported by this profile even if we only use a single channel for them.
+    builder.addConnections(1, allTypesWithConnection.toArray(new TransportRequestOptions.Type[0]));
+    if (allTypesWithoutConnection.isEmpty() == false) {
+      builder.addConnections(0, allTypesWithoutConnection.toArray(new TransportRequestOptions.Type[0]));
+    }
+    builder.setHandshakeTimeout(connectionProfile.getHandshakeTimeout());
+    builder.setConnectTimeout(connectionProfile.getConnectTimeout());
+    builder.setPingInterval(connectionProfile.getPingInterval());
+    builder.setCompressionEnabled(connectionProfile.getCompressionEnabled());
+    return builder.build();
+  }
+
+  private void configureSocket(Socket socket) throws SocketException {
+    socket.setTcpNoDelay(TransportSettings.TCP_NO_DELAY.get(settings));
+    ByteSizeValue tcpSendBufferSize = TransportSettings.TCP_SEND_BUFFER_SIZE.get(settings);
+    if (tcpSendBufferSize.getBytes() > 0) {
+      socket.setSendBufferSize(tcpSendBufferSize.bytesAsInt());
+    }
+    ByteSizeValue tcpReceiveBufferSize = TransportSettings.TCP_RECEIVE_BUFFER_SIZE.get(settings);
+    if (tcpReceiveBufferSize.getBytes() > 0) {
+      socket.setReceiveBufferSize(tcpReceiveBufferSize.bytesAsInt());
+    }
+    socket.setReuseAddress(TransportSettings.TCP_REUSE_ADDRESS.get(settings));
+  }
+
+  public final class MockChannel implements Closeable, TcpChannel, TcpServerChannel {
+    private final AtomicBoolean isOpen = new AtomicBoolean(true);
+    private final InetSocketAddress localAddress;
+    private final ServerSocket serverSocket;
+    private final Set<MockChannel> workerChannels = Collections.newSetFromMap(new ConcurrentHashMap<>());
+    private final Socket activeChannel;
+    private final boolean isServer;
+    private final String profile;
+    private final CancellableThreads cancellableThreads = new CancellableThreads();
+    private final CompletableContext<Void> closeFuture = new CompletableContext<>();
+    private final CompletableContext<Void> connectFuture = new CompletableContext<>();
+    private final ChannelStats stats = new ChannelStats();
+
+    /**
+     * Constructs a new MockChannel instance intended for handling the actual incoming / outgoing traffic.
+     *
+     * @param socket The client socket. Mut not be null.
+     * @param localAddress Address associated with the corresponding local server socket. Must not be null.
+     * @param profile The associated profile name.
+     */
+    MockChannel(Socket socket, InetSocketAddress localAddress, boolean isServer, String profile) {
+      this.localAddress = localAddress;
+      this.activeChannel = socket;
+      this.isServer = isServer;
+      this.serverSocket = null;
+      this.profile = profile;
+      synchronized (openChannels) {
+        openChannels.add(this);
+      }
+    }
+
+    /**
+     * Constructs a new MockChannel instance intended for accepting requests.
+     *
+     * @param serverSocket The associated server socket. Must not be null.
+     * @param profile The associated profile name.
+     */
+    MockChannel(ServerSocket serverSocket, String profile) {
+      this.localAddress = (InetSocketAddress) serverSocket.getLocalSocketAddress();
+      this.serverSocket = serverSocket;
+      this.profile = profile;
+      this.isServer = false;
+      this.activeChannel = null;
+      synchronized (openChannels) {
+        openChannels.add(this);
+      }
+    }
+
+    public void accept(Executor executor) throws IOException {
+      while (isOpen.get()) {
+        Socket incomingSocket = serverSocket.accept();
+        MockChannel incomingChannel = null;
+        try {
+          configureSocket(incomingSocket);
+          synchronized (this) {
+            if (isOpen.get()) {
+              InetSocketAddress localAddress = new InetSocketAddress(incomingSocket.getLocalAddress(),
+                incomingSocket.getPort());
+              incomingChannel = new MockChannel(incomingSocket, localAddress, true, profile);
+              MockChannel finalIncomingChannel = incomingChannel;
+              incomingChannel.addCloseListener(new ActionListener<Void>() {
+                @Override
+                public void onResponse(Void aVoid) {
+                  workerChannels.remove(finalIncomingChannel);
+                }
+
+                @Override
+                public void onFailure(Exception e) {
+                  workerChannels.remove(finalIncomingChannel);
+                }
+              });
+              serverAcceptedChannel(incomingChannel);
+              //establish a happens-before edge between closing and accepting a new connection
+              workerChannels.add(incomingChannel);
+
+              // this spawns a new thread immediately, so OK under lock
+              incomingChannel.loopRead(executor);
+              // the channel is properly registered and will be cleared by the close code.
+              incomingSocket = null;
+              incomingChannel = null;
+            }
+          }
+        } finally {
+          // ensure we don't leak sockets and channels in the failure case. Note that we null both
+          // if there are no exceptions so this becomes a no op.
+          IOUtils.closeWhileHandlingException(incomingSocket, incomingChannel);
+        }
+      }
+    }
+
+    void loopRead(Executor executor) {
+      executor.execute(new AbstractRunnable() {
+        @Override
+        public void onFailure(Exception e) {
+          if (isOpen.get()) {
+            try {
+              onException(MockChannel.this, e);
+            } catch (Exception ex) {
+              logger.warn("failed on handling exception", ex);
+              IOUtils.closeWhileHandlingException(MockChannel.this); // pure paranoia
+            }
+          }
+        }
+
+        @Override
+        protected void doRun() throws Exception {
+          StreamInput input = new InputStreamStreamInput(new BufferedInputStream(activeChannel.getInputStream()));
+          // There is a (slim) chance that we get interrupted right after a loop iteration, so check explicitly
+          while (isOpen.get() && !Thread.currentThread().isInterrupted()) {
+            cancellableThreads.executeIO(() -> readMessage(MockChannel.this, input));
+          }
+        }
+      });
+    }
+
+    synchronized void close0() throws IOException {
+      // establish a happens-before edge between closing and accepting a new connection
+      // we have to sync this entire block to ensure that our openChannels checks work correctly.
+      // The close block below will close all worker channels but if one of the worker channels runs into an exception
+      // for instance due to a disconnect the handling of this exception might be executed concurrently.
+      // now if we are in-turn concurrently call close we might not wait for the actual close to happen and that will, down the road
+      // make the assertion trip that not all channels are closed.
+      if (isOpen.compareAndSet(true, false)) {
+        final boolean removedChannel;
+        synchronized (openChannels) {
+          removedChannel = openChannels.remove(this);
+        }
+        IOUtils.close(serverSocket, activeChannel, () -> IOUtils.close(workerChannels),
+          () -> cancellableThreads.cancel("channel closed"));
+        assert removedChannel: "Channel was not removed or removed twice?";
+      }
+    }
+
+    @Override
+    public String toString() {
+      return "MockChannel{" +
+        "profile='" + profile + '\'' +
+        ", isOpen=" + isOpen +
+        ", localAddress=" + localAddress +
+        ", isServerSocket=" + (serverSocket != null) +
+        '}';
+    }
+
+    @Override
+    public void close() {
+      try {
+        close0();
+        closeFuture.complete(null);
+      } catch (IOException e) {
+        closeFuture.completeExceptionally(e);
+      }
+    }
+
+    @Override
+    public String getProfile() {
+      return profile;
+    }
+
+    @Override
+    public boolean isServerChannel() {
+      return isServer;
+    }
+
+    @Override
+    public void addCloseListener(ActionListener<Void> listener) {
+      closeFuture.addListener(ActionListener.toBiConsumer(listener));
+    }
+
+    @Override
+    public void addConnectListener(ActionListener<Void> listener) {
+      connectFuture.addListener(ActionListener.toBiConsumer(listener));
+    }
+
+    @Override
+    public ChannelStats getChannelStats() {
+      return stats;
+    }
+
+    @Override
+    public boolean isOpen() {
+      return isOpen.get();
+    }
+
+    @Override
+    public InetSocketAddress getLocalAddress() {
+      return localAddress;
+    }
+
+    @Override
+    public InetSocketAddress getRemoteAddress() {
+      return (InetSocketAddress) activeChannel.getRemoteSocketAddress();
+    }
+
+    @Override
+    public void sendMessage(BytesReference reference, ActionListener<Void> listener) {
+      try {
+        synchronized (this) {
+          OutputStream outputStream = new BufferedOutputStream(activeChannel.getOutputStream());
+          reference.writeTo(outputStream);
+          outputStream.flush();
+        }
+        listener.onResponse(null);
+      } catch (IOException e) {
+        listener.onFailure(e);
+        onException(this, e);
+      }
+    }
+  }
+
+
+  @Override
+  protected void doStart() {
+    boolean success = false;
+    try {
+      if (NetworkService.NETWORK_SERVER.get(settings)) {
+        // loop through all profiles and start them up, special handling for default one
+        for (ProfileSettings profileSettings : profileSettings) {
+          bindServer(profileSettings);
+        }
+      }
+      super.doStart();
+      success = true;
+    } finally {
+      if (success == false) {
+        doStop();
+      }
+    }
+  }
+
+  @Override
+  protected void stopInternal() {
+    ThreadPool.terminate(executor, 10, TimeUnit.SECONDS);
+    synchronized (openChannels) {
+      assert openChannels.isEmpty() : "there are still open channels: " + openChannels;
+    }
+  }
+}
diff --git a/server/sonar-server-common/src/testFixtures/java/org/sonar/server/es/EsTester.java b/server/sonar-server-common/src/testFixtures/java/org/sonar/server/es/EsTester.java
new file mode 100644 (file)
index 0000000..9d69c04
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.es;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.commons.lang.reflect.ConstructorUtils;
+import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
+import org.elasticsearch.action.bulk.BulkRequestBuilder;
+import org.elasticsearch.action.bulk.BulkResponse;
+import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.action.search.SearchRequestBuilder;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
+import org.elasticsearch.analysis.common.CommonAnalysisPlugin;
+import org.elasticsearch.cluster.health.ClusterHealthStatus;
+import org.elasticsearch.cluster.routing.allocation.DiskThresholdSettings;
+import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
+import org.elasticsearch.common.network.NetworkModule;
+import org.elasticsearch.common.network.NetworkService;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.common.util.BigArrays;
+import org.elasticsearch.common.util.PageCacheRecycler;
+import org.elasticsearch.discovery.DiscoveryModule;
+import org.elasticsearch.env.Environment;
+import org.elasticsearch.env.NodeEnvironment;
+import org.elasticsearch.index.IndexNotFoundException;
+import org.elasticsearch.index.query.QueryBuilder;
+import org.elasticsearch.index.query.TermQueryBuilder;
+import org.elasticsearch.indices.breaker.CircuitBreakerService;
+import org.elasticsearch.indices.recovery.RecoverySettings;
+import org.elasticsearch.join.ParentJoinPlugin;
+import org.elasticsearch.node.InternalSettingsPreparer;
+import org.elasticsearch.node.Node;
+import org.elasticsearch.plugins.NetworkPlugin;
+import org.elasticsearch.plugins.Plugin;
+import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.threadpool.ThreadPool;
+import org.elasticsearch.transport.MockTcpTransport;
+import org.elasticsearch.transport.Transport;
+import org.junit.rules.ExternalResource;
+import org.sonar.server.component.index.ComponentIndexDefinition;
+import org.sonar.server.es.IndexDefinition.IndexDefinitionContext;
+import org.sonar.server.es.IndexType.IndexRelationType;
+import org.sonar.server.es.newindex.BuiltIndex;
+import org.sonar.server.es.newindex.NewIndex;
+import org.sonar.server.issue.index.IssueIndexDefinition;
+import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition;
+import org.sonar.server.rule.index.RuleIndexDefinition;
+import org.sonar.server.user.index.UserIndexDefinition;
+import org.sonar.server.view.index.ViewIndexDefinition;
+
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Lists.newArrayList;
+import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
+import static org.sonar.server.es.Index.ALL_INDICES;
+import static org.sonar.server.es.IndexType.FIELD_INDEX_TYPE;
+import static org.sonar.server.es.newindex.DefaultIndexSettings.REFRESH_IMMEDIATE;
+
+public class EsTester extends ExternalResource {
+
+  static {
+    System.setProperty("log4j.shutdownHookEnabled", "false");
+    // we can not shutdown logging when tests are running or the next test that runs within the
+    // same JVM will try to initialize logging after a security manager has been installed and
+    // this will fail
+    System.setProperty("es.log4j.shutdownEnabled", "false");
+    System.setProperty("log4j2.disable.jmx", "true");
+    System.setProperty("log4j.skipJansi", "true"); // jython has this crazy shaded Jansi version that log4j2 tries to load
+
+    if (!Strings.hasLength(System.getProperty("tests.es.logger.level"))) {
+      System.setProperty("tests.es.logger.level", "WARN");
+    }
+  }
+
+  private static final Node SHARED_NODE = createNode();
+  private static final AtomicBoolean CORE_INDICES_CREATED = new AtomicBoolean(false);
+  private static final Set<String> CORE_INDICES_NAMES = new HashSet<>();
+
+  private final boolean isCustom;
+
+  private EsTester(boolean isCustom) {
+    this.isCustom = isCustom;
+  }
+
+  /**
+   * New instance which contains the core indices (rules, issues, ...).
+   */
+  public static EsTester create() {
+    if (!CORE_INDICES_CREATED.get()) {
+      List<BuiltIndex> createdIndices = createIndices(
+        ComponentIndexDefinition.createForTest(),
+        IssueIndexDefinition.createForTest(),
+        ProjectMeasuresIndexDefinition.createForTest(),
+        RuleIndexDefinition.createForTest(),
+        UserIndexDefinition.createForTest(),
+        ViewIndexDefinition.createForTest());
+
+      CORE_INDICES_CREATED.set(true);
+      createdIndices.stream().map(t -> t.getMainType().getIndex().getName()).forEach(CORE_INDICES_NAMES::add);
+    }
+    return new EsTester(false);
+  }
+
+  /**
+   * New instance which contains the specified indices. Note that
+   * core indices may exist.
+   */
+  public static EsTester createCustom(IndexDefinition... definitions) {
+    createIndices(definitions);
+    return new EsTester(true);
+  }
+
+  @Override
+  protected void after() {
+    if (isCustom) {
+      // delete non-core indices
+      String[] existingIndices = SHARED_NODE.client().admin().indices().prepareGetIndex().get().getIndices();
+      Stream.of(existingIndices)
+        .filter(i -> !CORE_INDICES_NAMES.contains(i))
+        .forEach(EsTester::deleteIndexIfExists);
+    }
+    BulkIndexer.delete(client(), IndexType.main(ALL_INDICES, "dummy"), client().prepareSearch(ALL_INDICES).setQuery(matchAllQuery()));
+  }
+
+  public EsClient client() {
+    return new EsClient(SHARED_NODE.client());
+  }
+
+  public void putDocuments(IndexType indexType, BaseDoc... docs) {
+    try {
+      BulkRequestBuilder bulk = SHARED_NODE.client().prepareBulk()
+        .setRefreshPolicy(REFRESH_IMMEDIATE);
+      for (BaseDoc doc : docs) {
+        bulk.add(doc.toIndexRequest());
+      }
+      BulkResponse bulkResponse = bulk.get();
+      if (bulkResponse.hasFailures()) {
+        throw new IllegalStateException(bulkResponse.buildFailureMessage());
+      }
+    } catch (Exception e) {
+      throw Throwables.propagate(e);
+    }
+  }
+
+  public void putDocuments(IndexType indexType, Map<String, Object>... docs) {
+    try {
+      BulkRequestBuilder bulk = SHARED_NODE.client().prepareBulk()
+        .setRefreshPolicy(REFRESH_IMMEDIATE);
+      for (Map<String, Object> doc : docs) {
+        IndexType.IndexMainType mainType = indexType.getMainType();
+        bulk.add(new IndexRequest(mainType.getIndex().getName(), mainType.getType())
+          .source(doc));
+      }
+      BulkResponse bulkResponse = bulk.get();
+      if (bulkResponse.hasFailures()) {
+        throw new IllegalStateException(bulkResponse.buildFailureMessage());
+      }
+    } catch (Exception e) {
+      throw Throwables.propagate(e);
+    }
+  }
+
+  public long countDocuments(Index index) {
+    return client().prepareSearch(index)
+      .setQuery(matchAllQuery())
+      .setSize(0).get().getHits().getTotalHits();
+  }
+
+  public long countDocuments(IndexType indexType) {
+    return client().prepareSearch(indexType.getMainType())
+      .setQuery(getDocumentsQuery(indexType))
+      .setSize(0).get().getHits().getTotalHits();
+  }
+
+  /**
+   * Get all the indexed documents (no paginated results). Results are converted to BaseDoc objects.
+   * Results are not sorted.
+   */
+  public <E extends BaseDoc> List<E> getDocuments(IndexType indexType, final Class<E> docClass) {
+    List<SearchHit> hits = getDocuments(indexType);
+    return new ArrayList<>(Collections2.transform(hits, input -> {
+      try {
+        return (E) ConstructorUtils.invokeConstructor(docClass, input.getSourceAsMap());
+      } catch (Exception e) {
+        throw Throwables.propagate(e);
+      }
+    }));
+  }
+
+  /**
+   * Get all the indexed documents (no paginated results) in the specified index, whatever their type. Results are not sorted.
+   */
+  public List<SearchHit> getDocuments(Index index) {
+    SearchRequestBuilder req = SHARED_NODE.client()
+      .prepareSearch(index.getName())
+      .setQuery(matchAllQuery());
+    return getDocuments(req);
+  }
+
+  /**
+   * Get all the indexed documents (no paginated results) of the specified type. Results are not sorted.
+   */
+  public List<SearchHit> getDocuments(IndexType indexType) {
+    IndexType.IndexMainType mainType = indexType.getMainType();
+    SearchRequestBuilder req = SHARED_NODE.client()
+      .prepareSearch(mainType.getIndex().getName())
+      .setQuery(getDocumentsQuery(indexType));
+    return getDocuments(req);
+  }
+
+  private List<SearchHit> getDocuments(SearchRequestBuilder req) {
+    EsUtils.optimizeScrollRequest(req);
+    req.setScroll(new TimeValue(60000))
+      .setSize(100);
+
+    SearchResponse response = req.get();
+    List<SearchHit> result = newArrayList();
+    while (true) {
+      Iterables.addAll(result, response.getHits());
+      response = SHARED_NODE.client().prepareSearchScroll(response.getScrollId()).setScroll(new TimeValue(600000)).execute().actionGet();
+      // Break condition: No hits are returned
+      if (response.getHits().getHits().length == 0) {
+        break;
+      }
+    }
+    return result;
+  }
+
+  private QueryBuilder getDocumentsQuery(IndexType indexType) {
+    if (!indexType.getMainType().getIndex().acceptsRelations()) {
+      return matchAllQuery();
+    }
+
+    if (indexType instanceof IndexRelationType) {
+      return new TermQueryBuilder(FIELD_INDEX_TYPE, ((IndexRelationType) indexType).getName());
+    }
+    if (indexType instanceof IndexType.IndexMainType) {
+      return new TermQueryBuilder(FIELD_INDEX_TYPE, ((IndexType.IndexMainType) indexType).getType());
+    }
+    throw new IllegalArgumentException("Unsupported IndexType " + indexType.getClass());
+  }
+
+  /**
+   * Get a list of a specific field from all indexed documents.
+   */
+  public <T> List<T> getDocumentFieldValues(IndexType indexType, final String fieldNameToReturn) {
+    return getDocuments(indexType)
+      .stream()
+      .map(input -> (T) input.getSourceAsMap().get(fieldNameToReturn))
+      .collect(Collectors.toList());
+  }
+
+  public List<String> getIds(IndexType indexType) {
+    return getDocuments(indexType).stream().map(SearchHit::getId).collect(Collectors.toList());
+  }
+
+  public void lockWrites(IndexType index) {
+    setIndexSettings(index.getMainType().getIndex().getName(), ImmutableMap.of("index.blocks.write", "true"));
+  }
+
+  public void unlockWrites(IndexType index) {
+    setIndexSettings(index.getMainType().getIndex().getName(), ImmutableMap.of("index.blocks.write", "false"));
+  }
+
+  private void setIndexSettings(String index, Map<String, Object> settings) {
+    AcknowledgedResponse response = SHARED_NODE.client().admin().indices()
+      .prepareUpdateSettings(index)
+      .setSettings(settings)
+      .get();
+    checkState(response.isAcknowledged());
+  }
+
+  private static void deleteIndexIfExists(String name) {
+    try {
+      AcknowledgedResponse response = SHARED_NODE.client().admin().indices().prepareDelete(name).get();
+      checkState(response.isAcknowledged(), "Fail to drop the index " + name);
+    } catch (IndexNotFoundException e) {
+      // ignore
+    }
+  }
+
+  private static List<BuiltIndex> createIndices(IndexDefinition... definitions) {
+    IndexDefinitionContext context = new IndexDefinitionContext();
+    Stream.of(definitions).forEach(d -> d.define(context));
+
+    List<BuiltIndex> result = new ArrayList<>();
+    for (NewIndex newIndex : context.getIndices().values()) {
+      BuiltIndex index = newIndex.build();
+
+      String indexName = index.getMainType().getIndex().getName();
+      deleteIndexIfExists(indexName);
+
+      // create index
+      Settings.Builder settings = Settings.builder();
+      settings.put(index.getSettings());
+      CreateIndexResponse indexResponse = SHARED_NODE.client().admin().indices()
+        .prepareCreate(indexName)
+        .setSettings(settings)
+        .get();
+      if (!indexResponse.isAcknowledged()) {
+        throw new IllegalStateException("Failed to create index " + indexName);
+      }
+      SHARED_NODE.client().admin().cluster().prepareHealth(indexName).setWaitForStatus(ClusterHealthStatus.YELLOW).get();
+
+      // create types
+      String typeName = index.getMainType().getType();
+      AcknowledgedResponse mappingResponse = SHARED_NODE.client().admin().indices().preparePutMapping(indexName)
+        .setType(typeName)
+        .setSource(index.getAttributes())
+        .get();
+      if (!mappingResponse.isAcknowledged()) {
+        throw new IllegalStateException("Failed to create type " + typeName);
+      }
+      SHARED_NODE.client().admin().cluster().prepareHealth(indexName).setWaitForStatus(ClusterHealthStatus.YELLOW).get();
+      result.add(index);
+    }
+    return result;
+  }
+
+  private static Node createNode() {
+    try {
+      Path tempDir = Files.createTempDirectory("EsTester");
+      tempDir.toFile().deleteOnExit();
+      Settings settings = Settings.builder()
+        .put(Environment.PATH_HOME_SETTING.getKey(), tempDir)
+        .put("node.name", "EsTester")
+        .put(NodeEnvironment.MAX_LOCAL_STORAGE_NODES_SETTING.getKey(), Integer.MAX_VALUE)
+        .put("logger.level", "INFO")
+        .put("action.auto_create_index", false)
+        // Default the watermarks to absurdly low to prevent the tests
+        // from failing on nodes without enough disk space
+        .put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), "1b")
+        .put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), "1b")
+        .put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(), "1b")
+        // always reduce this - it can make tests really slow
+        .put(RecoverySettings.INDICES_RECOVERY_RETRY_DELAY_STATE_SYNC_SETTING.getKey(), TimeValue.timeValueMillis(20))
+        .put(NetworkModule.TRANSPORT_TYPE_KEY, "local")
+        .put(NetworkModule.HTTP_ENABLED.getKey(), false)
+        .put(DiscoveryModule.DISCOVERY_TYPE_SETTING.getKey(), "single-node")
+        .build();
+      Node node = new Node(InternalSettingsPreparer.prepareEnvironment(settings, null),
+        ImmutableList.of(
+          CommonAnalysisPlugin.class,
+          // mock local transport plugin
+          MockTcpTransportPlugin.class,
+          // install ParentJoin plugin required to create field of type "join"
+          ParentJoinPlugin.class),
+        true) {
+        @Override
+        protected void registerDerivedNodeNameWithLogger(String nodeName) {
+          // nothing to do
+        }
+      };
+      return node.start();
+    } catch (Exception e) {
+      throw new IllegalStateException("Fail to start embedded Elasticsearch", e);
+    }
+  }
+
+  public static final class MockTcpTransportPlugin extends Plugin implements NetworkPlugin {
+    @Override
+    public Map<String, Supplier<Transport>> getTransports(Settings settings, ThreadPool threadPool, PageCacheRecycler pageCacheRecycler,
+      CircuitBreakerService circuitBreakerService, NamedWriteableRegistry namedWriteableRegistry, NetworkService networkService) {
+      return Collections.singletonMap(
+        "local",
+        () -> new MockTcpTransport(settings, threadPool, BigArrays.NON_RECYCLING_INSTANCE, circuitBreakerService, namedWriteableRegistry, networkService));
+    }
+  }
+}
diff --git a/server/sonar-server-common/src/testFixtures/java/org/sonar/server/es/FakeDoc.java b/server/sonar-server-common/src/testFixtures/java/org/sonar/server/es/FakeDoc.java
new file mode 100644 (file)
index 0000000..d199ed9
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.es;
+
+import com.google.common.collect.Maps;
+
+import static org.sonar.server.es.newindex.FakeIndexDefinition.INT_FIELD;
+import static org.sonar.server.es.newindex.FakeIndexDefinition.TYPE_FAKE;
+
+public class FakeDoc extends BaseDoc {
+  public FakeDoc() {
+    super(TYPE_FAKE, Maps.newHashMap());
+  }
+
+  @Override
+  public String getId() {
+    return null;
+  }
+
+  public int getInt() {
+    return getField(INT_FIELD);
+  }
+
+  public FakeDoc setInt(int i) {
+    setField(INT_FIELD, i);
+    return this;
+  }
+}
diff --git a/server/sonar-server-common/src/testFixtures/java/org/sonar/server/es/TestProjectIndexers.java b/server/sonar-server-common/src/testFixtures/java/org/sonar/server/es/TestProjectIndexers.java
new file mode 100644 (file)
index 0000000..fb85891
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.es;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ListMultimap;
+import java.util.Collection;
+import org.sonar.db.DbSession;
+
+public class TestProjectIndexers implements ProjectIndexers {
+
+  private final ListMultimap<String, ProjectIndexer.Cause> calls = ArrayListMultimap.create();
+
+  @Override
+  public void commitAndIndexByProjectUuids(DbSession dbSession, Collection<String> projectUuids, ProjectIndexer.Cause cause) {
+    dbSession.commit();
+    projectUuids.forEach(projectUuid -> calls.put(projectUuid, cause));
+
+  }
+
+  public boolean hasBeenCalled(String projectUuid, ProjectIndexer.Cause expectedCause) {
+    return calls.get(projectUuid).contains(expectedCause);
+  }
+
+  public boolean hasBeenCalled(String projectUuid) {
+    return calls.containsKey(projectUuid);
+  }
+}
diff --git a/server/sonar-server-common/src/testFixtures/java/org/sonar/server/es/newindex/FakeIndexDefinition.java b/server/sonar-server-common/src/testFixtures/java/org/sonar/server/es/newindex/FakeIndexDefinition.java
new file mode 100644 (file)
index 0000000..d6dfd76
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.es.newindex;
+
+import org.elasticsearch.cluster.metadata.IndexMetaData;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.server.es.FakeDoc;
+import org.sonar.server.es.Index;
+import org.sonar.server.es.IndexDefinition;
+import org.sonar.server.es.IndexType;
+import org.sonar.server.es.IndexType.IndexMainType;
+
+import static org.sonar.server.es.newindex.SettingsConfiguration.newBuilder;
+
+public class FakeIndexDefinition implements IndexDefinition {
+
+  public static final String INDEX = "fakes";
+  public static final String TYPE = "fake";
+  public static final Index DESCRIPTOR = Index.simple(INDEX);
+  public static final IndexMainType TYPE_FAKE = IndexType.main(DESCRIPTOR, TYPE);
+  public static final String INT_FIELD = "intField";
+
+  private int replicas = 0;
+
+  public FakeIndexDefinition setReplicas(int replicas) {
+    this.replicas = replicas;
+    return this;
+  }
+
+  @Override
+  public void define(IndexDefinitionContext context) {
+    NewIndex index = context.create(DESCRIPTOR, newBuilder(new MapSettings().asConfig()).build());
+    index.getSettings().put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, replicas);
+    index.getSettings().put("index.refresh_interval", "-1");
+    index.createTypeMapping(TYPE_FAKE)
+      .createIntegerField(INT_FIELD);
+  }
+
+  public static FakeDoc newDoc(int value) {
+    return new FakeDoc().setInt(value);
+  }
+}
diff --git a/server/sonar-server-common/src/testFixtures/java/org/sonar/server/es/textsearch/ComponentTextSearchFeatureRule.java b/server/sonar-server-common/src/testFixtures/java/org/sonar/server/es/textsearch/ComponentTextSearchFeatureRule.java
new file mode 100644 (file)
index 0000000..60ddbdb
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.es.textsearch;
+
+import org.junit.rules.ExternalResource;
+
+public class ComponentTextSearchFeatureRule extends ExternalResource {
+
+  private ComponentTextSearchFeature[] features;
+
+  @Override
+  protected void before() {
+    features = ComponentTextSearchFeatureRepertoire.values();
+  }
+
+  public ComponentTextSearchFeature[] get() {
+    return features;
+  }
+
+  public void set(ComponentTextSearchFeature... features) {
+    this.features = features;
+  }
+}
diff --git a/server/sonar-server-common/src/testFixtures/java/org/sonar/server/issue/IssueDocTesting.java b/server/sonar-server-common/src/testFixtures/java/org/sonar/server/issue/IssueDocTesting.java
new file mode 100644 (file)
index 0000000..c63f12e
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.issue;
+
+import com.google.common.collect.Maps;
+import java.util.Date;
+import org.sonar.api.resources.Scopes;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.RuleType;
+import org.sonar.core.util.Uuids;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.server.issue.index.IssueDoc;
+
+import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
+import static org.apache.commons.lang.math.RandomUtils.nextInt;
+import static org.sonar.api.issue.Issue.STATUS_OPEN;
+
+public class IssueDocTesting {
+
+  public static IssueDoc newDoc(ComponentDto componentDto) {
+    return newDoc(Uuids.createFast(), componentDto);
+  }
+
+  public static IssueDoc newDoc(String key, ComponentDto componentDto) {
+    String mainBranchProjectUuid = componentDto.getMainBranchProjectUuid();
+    return newDoc()
+      .setKey(key)
+      .setBranchUuid(componentDto.projectUuid())
+      .setComponentUuid(componentDto.uuid())
+      .setModuleUuid(!componentDto.scope().equals(Scopes.PROJECT) ? componentDto.moduleUuid() : componentDto.uuid())
+      .setModuleUuidPath(componentDto.moduleUuidPath())
+      .setProjectUuid(mainBranchProjectUuid == null ? componentDto.projectUuid() : mainBranchProjectUuid)
+      .setOrganizationUuid(componentDto.getOrganizationUuid())
+      // File path make no sens on modules and projects
+      .setFilePath(!componentDto.scope().equals(Scopes.PROJECT) ? componentDto.path() : null)
+      .setIsMainBranch(mainBranchProjectUuid == null);
+  }
+
+  public static IssueDoc newDoc() {
+    IssueDoc doc = new IssueDoc(Maps.newHashMap());
+    doc.setKey(Uuids.createFast());
+    doc.setRuleId(nextInt(1000));
+    doc.setType(RuleType.CODE_SMELL);
+    doc.setAssigneeUuid("assignee_uuid_" + randomAlphabetic(26));
+    doc.setAuthorLogin("author_" + randomAlphabetic(5));
+    doc.setLanguage("language_" + randomAlphabetic(5));
+    doc.setComponentUuid(Uuids.createFast());
+    doc.setFilePath("filePath_" + randomAlphabetic(5));
+    doc.setDirectoryPath("directory_" + randomAlphabetic(5));
+    doc.setModuleUuid(Uuids.createFast());
+    doc.setModuleUuidPath(Uuids.createFast());
+    doc.setProjectUuid(Uuids.createFast());
+    doc.setLine(nextInt(1_000) + 1);
+    doc.setStatus(STATUS_OPEN);
+    doc.setResolution(null);
+    doc.setSeverity(Severity.ALL.get(nextInt(Severity.ALL.size())));
+    doc.setEffort((long) nextInt(10));
+    doc.setFuncCreationDate(new Date(System.currentTimeMillis() - 2_000));
+    doc.setFuncUpdateDate(new Date(System.currentTimeMillis() - 1_000));
+    doc.setFuncCloseDate(null);
+    return doc;
+  }
+}
diff --git a/server/sonar-server-common/src/testFixtures/java/org/sonar/server/issue/notification/IssuesChangesNotificationBuilderTesting.java b/server/sonar-server-common/src/testFixtures/java/org/sonar/server/issue/notification/IssuesChangesNotificationBuilderTesting.java
new file mode 100644 (file)
index 0000000..43f5cbf
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.issue.notification;
+
+import java.util.Random;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.BranchDto;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.rule.RuleDefinitionDto;
+import org.sonar.db.rule.RuleDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.AnalysisChange;
+import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.ChangedIssue;
+import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.Project;
+import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.Rule;
+import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.User;
+import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.UserChange;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
+
+public class IssuesChangesNotificationBuilderTesting {
+
+  public static Rule ruleOf(RuleDto rule) {
+    return new Rule(rule.getKey(), rule.getName());
+  }
+
+  public static Rule ruleOf(RuleDefinitionDto rule) {
+    return new Rule(rule.getKey(), rule.getName());
+  }
+
+  public static User userOf(UserDto changeAuthor) {
+    return new User(changeAuthor.getUuid(), changeAuthor.getLogin(), changeAuthor.getName());
+  }
+
+  public static Project projectBranchOf(DbTester db, ComponentDto branch) {
+    BranchDto branchDto = db.getDbClient().branchDao().selectByUuid(db.getSession(), branch.uuid()).get();
+    checkArgument(!branchDto.isMain(), "should be a branch");
+    return new Project.Builder(branch.uuid())
+      .setKey(branch.getKey())
+      .setProjectName(branch.name())
+      .setBranchName(branchDto.getKey())
+      .build();
+  }
+
+  public static Project projectOf(ComponentDto project) {
+    return new Project.Builder(project.uuid())
+      .setKey(project.getKey())
+      .setProjectName(project.name())
+      .build();
+  }
+
+  static ChangedIssue newChangedIssue(String key, Project project, Rule rule) {
+    return new ChangedIssue.Builder(key)
+      .setNewStatus(randomAlphabetic(19))
+      .setProject(project)
+      .setRule(rule)
+      .build();
+  }
+
+  static ChangedIssue newChangedIssue(String key, String status, Project project, String ruleName) {
+    return newChangedIssue(key, status, project, newRule(ruleName));
+  }
+
+  static ChangedIssue newChangedIssue(String key, String status, Project project, Rule rule) {
+    return new ChangedIssue.Builder(key)
+      .setNewStatus(status)
+      .setProject(project)
+      .setRule(rule)
+      .build();
+  }
+
+  static Rule newRule(String ruleName) {
+    return new Rule(RuleKey.of(randomAlphabetic(6), randomAlphabetic(7)), ruleName);
+  }
+
+  static Project newProject(String uuid) {
+    return new Project.Builder(uuid).setProjectName(uuid + "_name").setKey(uuid + "_key").build();
+  }
+
+  static Project newBranch(String uuid, String branchName) {
+    return new Project.Builder(uuid).setProjectName(uuid + "_name").setKey(uuid + "_key").setBranchName(branchName).build();
+  }
+
+  static UserChange newUserChange() {
+    return new UserChange(new Random().nextLong(), new User(randomAlphabetic(4), randomAlphabetic(5), randomAlphabetic(6)));
+  }
+
+  static AnalysisChange newAnalysisChange() {
+    return new AnalysisChange(new Random().nextLong());
+  }
+}
diff --git a/server/sonar-server-common/src/testFixtures/java/org/sonar/server/l18n/I18nRule.java b/server/sonar-server-common/src/testFixtures/java/org/sonar/server/l18n/I18nRule.java
new file mode 100644 (file)
index 0000000..f81a2f0
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.l18n;
+
+import java.text.MessageFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import org.sonar.core.i18n.I18n;
+
+public class I18nRule implements TestRule, I18n {
+  private final Map<String, String> messages = new HashMap<>();
+
+  public I18nRule put(String key, String value) {
+    messages.put(key, value);
+    return this;
+  }
+
+  @Override
+  public Statement apply(final Statement statement, Description description) {
+    return new Statement() {
+      @Override
+      public void evaluate() throws Throwable {
+        try {
+          statement.evaluate();
+        } finally {
+          messages.clear();
+        }
+      }
+    };
+  }
+
+  public void setProjectPermissions() {
+    put("projects_role.admin", "Administer");
+    put("projects_role.admin.desc", "Ability to access project settings and perform administration tasks. " +
+      "(Users will also need \"Browse\" permission)");
+    put("projects_role.issueadmin", "Administer Issues");
+    put("projects_role.issueadmin.desc", "Grants the permission to perform advanced editing on issues: marking an issue " +
+      "False Positive / Won't Fix or changing an Issue's severity. (Users will also need \"Browse\" permission)");
+    put("projects_role.securityhotspotadmin", "Administer Security Hotspots");
+    put("projects_role.securityhotspotadmin.desc", "Detect a Vulnerability from a \"Security Hotspot\". Reject, clear, accept, reopen a \"Security Hotspot\" (users also need \"Browse\" permissions).");
+    put("projects_role.applicationcreator", "Create Applications");
+    put("projects_role.applicationcreator.desc", "Allow to create applications for non system administrator.");
+    put("projects_role.portfoliocreator", "Create Portfolios");
+    put("projects_role.portfoliocreator.desc", "Allow to create portfolios for non system administrator.");
+    put("projects_role.user", "Browse");
+    put("projects_role.user.desc", "Ability to access a project, browse its measures, and create/edit issues for it.");
+    put("projects_role.codeviewer", "See Source Code");
+    put("projects_role.codeviewer.desc", "Ability to view the project's source code. (Users will also need \"Browse\" permission)");
+    put("projects_role.scan", "Execute Analysis");
+    put("projects_role.scan.desc",
+      "Ability to execute analyses, and to get all settings required to perform the analysis, even the secured ones like the scm account password, the jira account password, and so on.");
+  }
+
+  @Override
+  public String message(Locale locale, String key, @Nullable String defaultValue, Object... parameters) {
+    String messageInMap = messages.get(key);
+    String message = messageInMap != null ? messageInMap : defaultValue;
+    return formatMessage(message, parameters);
+  }
+
+  @CheckForNull
+  private static String formatMessage(@Nullable String message, Object... parameters) {
+    if (message == null || parameters.length == 0) {
+      return message;
+    }
+    return MessageFormat.format(message.replaceAll("'", "''"), parameters);
+  }
+
+  @Override
+  public String age(Locale locale, long durationInMillis) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public String age(Locale locale, Date fromDate, Date toDate) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public String ageFromNow(Locale locale, Date date) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public String formatDateTime(Locale locale, Date date) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public String formatDate(Locale locale, Date date) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public String formatDouble(Locale locale, Double value) {
+    return String.valueOf(value);
+  }
+
+  @Override
+  public String formatInteger(Locale locale, Integer value) {
+    return String.valueOf(value);
+  }
+
+}
diff --git a/server/sonar-server-common/src/testFixtures/java/org/sonar/server/organization/TestDefaultOrganizationProvider.java b/server/sonar-server-common/src/testFixtures/java/org/sonar/server/organization/TestDefaultOrganizationProvider.java
new file mode 100644 (file)
index 0000000..a5b5231
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.organization;
+
+import java.util.Date;
+import org.sonar.db.DbTester;
+import org.sonar.db.organization.OrganizationDto;
+
+public class TestDefaultOrganizationProvider implements DefaultOrganizationProvider {
+
+  private final DefaultOrganizationProvider delegate;
+
+  private TestDefaultOrganizationProvider(DefaultOrganizationProvider delegate) {
+    this.delegate = delegate;
+  }
+
+  public static TestDefaultOrganizationProvider from(DbTester dbTester) {
+    return new TestDefaultOrganizationProvider(new DbTesterDefaultOrganizationProvider(dbTester));
+  }
+
+  public static TestDefaultOrganizationProvider fromUuid(String uuid) {
+    long createdAt = new Date().getTime();
+    return new TestDefaultOrganizationProvider(
+      new ImmutableDefaultOrganizationProvider(
+        DefaultOrganization.newBuilder()
+          .setUuid(uuid)
+          .setKey("key_" + uuid)
+          .setName("name_" + uuid)
+          .setCreatedAt(createdAt)
+          .setUpdatedAt(createdAt)
+          .build()));
+  }
+
+  @Override
+  public DefaultOrganization get() {
+    return delegate.get();
+  }
+
+  private static final class ImmutableDefaultOrganizationProvider implements DefaultOrganizationProvider {
+    private final DefaultOrganization defaultOrganization;
+
+    private ImmutableDefaultOrganizationProvider(DefaultOrganization defaultOrganization) {
+      this.defaultOrganization = defaultOrganization;
+    }
+
+    @Override
+    public DefaultOrganization get() {
+      return defaultOrganization;
+    }
+  }
+
+  private static final class DbTesterDefaultOrganizationProvider implements DefaultOrganizationProvider {
+    private final DbTester dbTester;
+    private DefaultOrganization defaultOrganization = null;
+
+    private DbTesterDefaultOrganizationProvider(DbTester dbTester) {
+      this.dbTester = dbTester;
+    }
+
+    @Override
+    public DefaultOrganization get() {
+      if (defaultOrganization == null) {
+        defaultOrganization = toDefaultOrganization(dbTester.getDefaultOrganization());
+      }
+      return defaultOrganization;
+    }
+
+    private static DefaultOrganization toDefaultOrganization(OrganizationDto organizationDto) {
+      return DefaultOrganization.newBuilder()
+        .setUuid(organizationDto.getUuid())
+        .setKey(organizationDto.getKey())
+        .setName(organizationDto.getName())
+        .setCreatedAt(organizationDto.getCreatedAt())
+        .setUpdatedAt(organizationDto.getUpdatedAt())
+        .build();
+    }
+  }
+}
diff --git a/server/sonar-server-common/src/testFixtures/java/org/sonar/server/organization/TestOrganizationFlags.java b/server/sonar-server-common/src/testFixtures/java/org/sonar/server/organization/TestOrganizationFlags.java
new file mode 100644 (file)
index 0000000..f5a6d71
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.organization;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.sonar.db.DbSession;
+
+import static org.sonar.server.organization.OrganizationFlagsImpl.FAILURE_MESSAGE_DISABLED;
+import static org.sonar.server.organization.OrganizationFlagsImpl.FAILURE_MESSAGE_ENABLED;
+
+public class TestOrganizationFlags implements OrganizationFlags {
+
+  private final AtomicBoolean enabled = new AtomicBoolean(false);
+
+  private TestOrganizationFlags() {
+  }
+
+  @Override
+  public boolean isEnabled(DbSession dbSession) {
+    return enabled.get();
+  }
+
+  public TestOrganizationFlags setEnabled(boolean b) {
+    this.enabled.set(b);
+    return this;
+  }
+
+  @Override
+  public void enable(DbSession dbSession) {
+    setEnabled(true);
+  }
+
+  @Override
+  public void checkEnabled(DbSession dbSession) {
+    if (!isEnabled(dbSession)) {
+      throw new IllegalStateException(FAILURE_MESSAGE_DISABLED);
+    }
+  }
+
+  @Override
+  public void checkDisabled(DbSession dbSession) {
+    if (isEnabled(dbSession)) {
+      throw new IllegalStateException(FAILURE_MESSAGE_ENABLED);
+    }
+  }
+
+  /**
+   * By default Organization support is disabled
+   */
+  public static TestOrganizationFlags standalone() {
+    return new TestOrganizationFlags();
+  }
+}
diff --git a/server/sonar-server-common/src/testFixtures/java/org/sonar/server/platform/monitoring/SystemInfoTesting.java b/server/sonar-server-common/src/testFixtures/java/org/sonar/server/platform/monitoring/SystemInfoTesting.java
new file mode 100644 (file)
index 0000000..a438af7
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.platform.monitoring;
+
+import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.process.systeminfo.SystemInfoUtils.attribute;
+
+public class SystemInfoTesting {
+
+  private SystemInfoTesting() {
+    // do not instantiate
+  }
+
+  public static void assertThatAttributeIs(ProtobufSystemInfo.Section section, String key, String expectedValue) {
+    ProtobufSystemInfo.Attribute value = attribute(section, key);
+    assertThat(value).as(key).isNotNull();
+    assertThat(value.getStringValue()).isEqualTo(expectedValue);
+  }
+
+  public static void assertThatAttributeIs(ProtobufSystemInfo.Section section, String key, boolean expectedValue) {
+    ProtobufSystemInfo.Attribute value = attribute(section, key);
+    assertThat(value).as(key).isNotNull();
+    assertThat(value.getBooleanValue()).isEqualTo(expectedValue);
+  }
+
+  public static void assertThatAttributeIs(ProtobufSystemInfo.Section section, String key, long expectedValue) {
+    ProtobufSystemInfo.Attribute value = attribute(section, key);
+    assertThat(value).as(key).isNotNull();
+    assertThat(value.getLongValue()).isEqualTo(expectedValue);
+  }
+}
diff --git a/server/sonar-server-common/src/testFixtures/java/org/sonar/server/platform/monitoring/cluster/TestGlobalSystemInfoSection.java b/server/sonar-server-common/src/testFixtures/java/org/sonar/server/platform/monitoring/cluster/TestGlobalSystemInfoSection.java
new file mode 100644 (file)
index 0000000..534c0f5
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.platform.monitoring.cluster;
+
+import org.sonar.process.systeminfo.Global;
+import org.sonar.process.systeminfo.SystemInfoSection;
+import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
+
+class TestGlobalSystemInfoSection implements SystemInfoSection, Global {
+  private final String name;
+
+  TestGlobalSystemInfoSection(String name) {
+    this.name = name;
+  }
+
+  @Override
+  public ProtobufSystemInfo.Section toProtobuf() {
+    return ProtobufSystemInfo.Section.newBuilder().setName(name).build();
+  }
+}
diff --git a/server/sonar-server-common/src/testFixtures/java/org/sonar/server/platform/monitoring/cluster/TestSystemInfoSection.java b/server/sonar-server-common/src/testFixtures/java/org/sonar/server/platform/monitoring/cluster/TestSystemInfoSection.java
new file mode 100644 (file)
index 0000000..0ae8b3a
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.platform.monitoring.cluster;
+
+import org.sonar.process.systeminfo.SystemInfoSection;
+import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
+
+class TestSystemInfoSection implements SystemInfoSection {
+  private final String name;
+
+  TestSystemInfoSection(String name) {
+    this.name = name;
+  }
+
+  @Override
+  public ProtobufSystemInfo.Section toProtobuf() {
+    return ProtobufSystemInfo.Section.newBuilder().setName(name).build();
+  }
+}
diff --git a/server/sonar-server-common/src/testFixtures/java/org/sonar/server/source/index/FileSourceTesting.java b/server/sonar-server-common/src/testFixtures/java/org/sonar/server/source/index/FileSourceTesting.java
new file mode 100644 (file)
index 0000000..8662438
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.source.index;
+
+import java.util.Arrays;
+import org.sonar.db.protobuf.DbFileSources;
+
+public class FileSourceTesting {
+
+  private FileSourceTesting() {
+    // only static stuff
+  }
+
+  /**
+   * Generate predefined fake data. Result is mutable.
+   */
+  public static DbFileSources.Data.Builder newFakeData(int numberOfLines) {
+    DbFileSources.Data.Builder dataBuilder = DbFileSources.Data.newBuilder();
+    for (int i = 1; i <= numberOfLines; i++) {
+      dataBuilder.addLinesBuilder()
+        .setLine(i)
+        .setScmRevision("REVISION_" + i)
+        .setScmAuthor("AUTHOR_" + i)
+        .setScmDate(1_500_000_000_00L + i)
+        .setSource("SOURCE_" + i)
+        .setLineHits(i)
+        .setConditions(i + 1)
+        .setCoveredConditions(i + 2)
+        .setHighlighting("HIGHLIGHTING_" + i)
+        .setSymbols("SYMBOLS_" + i)
+        .addAllDuplication(Arrays.asList(i))
+        .setIsNewLine(true)
+        .build();
+    }
+    return dataBuilder;
+  }
+
+}
index 93b373805f75f2602f8c6edfad79d8f91ae09788..561fd3957d5f40471be9c403a4ac3a1453e1e9e5 100644 (file)
@@ -35,7 +35,6 @@ dependencies {
   testCompile 'com.tngtech.java:junit-dataprovider'
   testCompile 'javax.servlet:javax.servlet-api'
   testCompile 'org.mockito:mockito-core'
-  testCompile testFixtures(project(':server:sonar-db-dao'))
-  testCompile project(path: ":server:sonar-server-common", configuration: "tests")
+  testCompile testFixtures(project(':server:sonar-server-common'))
   testCompile project(':sonar-testing-harness')
 }
index cba572bb3ba980f745ad41520640c7c7b058dab6..2882242d7fc060b1c4381073db235dc66f5e265f 100644 (file)
@@ -35,8 +35,7 @@ dependencies {
   testCompile 'org.apache.logging.log4j:log4j-core'
   testCompile 'org.assertj:assertj-guava'
   testCompile 'org.mockito:mockito-core'
-  testCompile testFixtures(project(':server:sonar-db-dao'))
-  testCompile project(path: ":server:sonar-server-common", configuration: "tests")
+  testCompile testFixtures(project(':server:sonar-server-common'))
   testCompile project(':sonar-testing-harness')
 
   runtime 'io.jsonwebtoken:jjwt-jackson'
index 46fd497fa9fbbad7e5cdf1f96361201a71ed13cf..824739f42c7bd80223e012c6a144e5401029f389 100644 (file)
@@ -61,7 +61,6 @@ dependencies {
   testCompile 'com.h2database:h2'
   testCompile 'com.squareup.okhttp3:mockwebserver'
   testCompile 'com.tngtech.java:junit-dataprovider'
-  testCompile 'junit:junit'
   testCompile 'org.apache.logging.log4j:log4j-api'
   testCompile 'org.apache.logging.log4j:log4j-core'
   testCompile 'org.assertj:assertj-core'
@@ -71,8 +70,7 @@ dependencies {
   testCompile 'org.hamcrest:hamcrest-all'
   testCompile 'org.mockito:mockito-core'
   testCompile 'org.subethamail:subethasmtp'
-  testCompile testFixtures(project(':server:sonar-db-dao'))
-  testCompile project(path: ":server:sonar-server-common", configuration: "tests")
+  testCompile testFixtures(project(':server:sonar-server-common'))
   testCompile project(path: ":server:sonar-webserver-auth", configuration: "tests")
   testCompile project(path: ":server:sonar-webserver-es", configuration: "tests")
   testCompile testFixtures(project(':server:sonar-webserver-ws'))
index cea503301be8e71ce08045e6314396280b93fe38..d69e85e01aa58d9729b7b8f3e67317015157ff77 100644 (file)
@@ -27,9 +27,8 @@ dependencies {
   testCompile 'com.google.code.findbugs:jsr305'
   testCompile 'com.tngtech.java:junit-dataprovider'
   testCompile 'org.mockito:mockito-core'
-  testCompile testFixtures(project(':server:sonar-db-dao'))
   testCompile project(path: ":server:sonar-webserver-auth", configuration: "tests")
-  testCompile project(path: ":server:sonar-server-common", configuration: "tests")
+  testCompile testFixtures(project(':server:sonar-server-common'))
   testCompile project(':sonar-testing-harness')
 }
 
index 2d3a2c1772f8c19e36969ec1f633bff37a9298fb..d9501e61847d6ded6999df8c0189ca5a0621784a 100644 (file)
@@ -33,8 +33,7 @@ dependencies {
   testCompile 'com.squareup.okhttp3:mockwebserver'
   testCompile 'javax.servlet:javax.servlet-api'
   testCompile 'org.mockito:mockito-core'
-  testCompile testFixtures(project(':server:sonar-db-dao'))
-  testCompile project(path: ":server:sonar-server-common", configuration: "tests")
+  testCompile testFixtures(project(':server:sonar-server-common'))
   testCompile project(path: ":server:sonar-webserver-auth", configuration: "tests")
   testCompile project(path: ":server:sonar-webserver-es", configuration: "tests")
   testCompile testFixtures(project(':server:sonar-webserver-ws'))
index cd4e3185417217534794fd22e0204acd74e3d45b..758f76bca3c023473bb0a13345c1897f989991a2 100644 (file)
@@ -26,8 +26,7 @@ dependencies {
   testCompile 'org.mockito:mockito-core'
   testCompile 'org.eclipse.jetty:jetty-server'
   testCompile 'org.eclipse.jetty:jetty-servlet'
-  testCompile testFixtures(project(':server:sonar-db-dao'))
-  testCompile project(path: ":server:sonar-server-common", configuration: "tests")
+  testCompile testFixtures(project(':server:sonar-server-common'))
   testCompile project(path: ":server:sonar-webserver-auth", configuration: "tests")
   testCompile project(path: ":server:sonar-webserver-es", configuration: "tests")
   testCompile project(':sonar-testing-harness')