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'))
}
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) {
}
}
-configurations {
- tests
-
- testCompile.extendsFrom tests
-}
-
dependencies {
// please keep the list grouped by configuration and ordered by name
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'
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'
}
+++ /dev/null
-/*
- * 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;
- }
- }
-}
+++ /dev/null
-/*
- * 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));
- }
- }
-}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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);
- }
-}
+++ /dev/null
-/*
- * 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);
- }
-}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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());
- }
-}
+++ /dev/null
-/*
- * 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);
- }
-
-}
+++ /dev/null
-/*
- * 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();
- }
- }
-}
+++ /dev/null
-/*
- * 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();
- }
-}
+++ /dev/null
-/*
- * 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);
- }
-}
+++ /dev/null
-/*
- * 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();
- }
-}
+++ /dev/null
-/*
- * 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();
- }
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
--- /dev/null
+/*
+ * 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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));
+ }
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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());
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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();
+ }
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
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')
}
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'
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'
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'))
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')
}
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'))
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')