]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-11632 Remove api/tests WS
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 17 Jan 2019 15:03:25 +0000 (16:03 +0100)
committerSonarTech <sonartech@sonarsource.com>
Thu, 17 Jan 2019 19:21:00 +0000 (20:21 +0100)
- Drop api/tests WS
- Drop persistance of tests and coverage details from compute engine
- Drop tests and coverage details from scanner report

82 files changed:
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/batch/BatchReportReader.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/batch/BatchReportReaderImpl.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/purge/IndexPurgeListener.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/scm/ScmInfoDbLoader.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/PersistFileSourcesStep.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistTestsStep.java [deleted file]
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/batch/BatchReportReaderImplTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/batch/BatchReportReaderRule.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCountTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/filemove/FileMoveDetectionStepTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/purge/IndexPurgeListenerTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/PersistFileSourcesStepTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistTestsStepTest.java [deleted file]
server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
server/sonar-db-dao/src/main/java/org/sonar/db/source/FileSourceDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/source/FileSourceDto.java
server/sonar-db-dao/src/main/java/org/sonar/db/source/FileSourceMapper.java
server/sonar-db-dao/src/main/resources/org/sonar/db/source/FileSourceMapper.xml
server/sonar-db-dao/src/test/java/org/sonar/db/component/ScrollForFileMoveComponentDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/source/FileSourceDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/source/FileSourceDtoTest.java
server/sonar-server-common/src/main/java/org/sonar/server/source/index/FileSourcesUpdaterHelper.java [deleted file]
server/sonar-server-common/src/main/java/org/sonar/server/test/index/CoveredFileDoc.java [deleted file]
server/sonar-server-common/src/main/java/org/sonar/server/test/index/TestDoc.java [deleted file]
server/sonar-server-common/src/main/java/org/sonar/server/test/index/TestIndex.java [deleted file]
server/sonar-server-common/src/main/java/org/sonar/server/test/index/TestIndexer.java [deleted file]
server/sonar-server-common/src/main/java/org/sonar/server/test/index/TestResultSetIterator.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/source/index/FileSourceTesting.java
server/sonar-server-common/src/test/java/org/sonar/server/test/db/TestTesting.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/test/index/TestIndexTest.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/test/index/TestIndexerTest.java [deleted file]
server/sonar-server-common/src/test/java/org/sonar/server/test/index/TestResultSetIteratorTest.java [deleted file]
server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P1_F1_T1.json [deleted file]
server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P1_F1_T2.json [deleted file]
server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P1_F2_T1.json [deleted file]
server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P2_F3_T1.json [deleted file]
server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P3_F1_long_message.json [deleted file]
server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P3_F1_long_name.json [deleted file]
server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P3_F1_long_stacktrace.json [deleted file]
server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/db.xml [deleted file]
server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestResultSetIteratorTest/filter_by_project.xml [deleted file]
server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestResultSetIteratorTest/filter_by_project_and_date.xml [deleted file]
server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestResultSetIteratorTest/schema.sql [deleted file]
server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestResultSetIteratorTest/shared.xml [deleted file]
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
server/sonar-server/src/main/java/org/sonar/server/source/SourceService.java
server/sonar-server/src/main/java/org/sonar/server/test/ws/CoveredFilesAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/test/ws/ListAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/test/ws/TestsWs.java
server/sonar-server/src/main/java/org/sonar/server/test/ws/TestsWsAction.java [deleted file]
server/sonar-server/src/main/resources/org/sonar/server/test/ws/tests-example-covered-files.json [deleted file]
server/sonar-server/src/main/resources/org/sonar/server/test/ws/tests-example-list.json [deleted file]
server/sonar-server/src/test/java/org/sonar/server/batch/ProjectDataLoaderTest.java
server/sonar-server/src/test/java/org/sonar/server/source/ws/HashActionTest.java
server/sonar-server/src/test/java/org/sonar/server/test/ws/CoveredFilesActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/test/ws/ListActionTest.java [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/test/ws/CoveredFilesActionTest/tests-covered-files.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/test/ws/ListActionTest/list-main-file.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/test/ws/ListActionTest/list-test-uuid.json [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisResult.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/TestExecutionAndCoveragePublisher.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/tests/CoveragePerTestMediumTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/tests/GenericTestExecutionMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/tests/TestExecutionMediumTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/TestExecutionAndCoveragePublisherTest.java [deleted file]
sonar-scanner-protocol/src/main/java/org/sonar/scanner/protocol/output/FileStructure.java
sonar-scanner-protocol/src/main/java/org/sonar/scanner/protocol/output/ScannerReportReader.java
sonar-scanner-protocol/src/main/java/org/sonar/scanner/protocol/output/ScannerReportWriter.java
sonar-scanner-protocol/src/main/java/org/sonar/scanner/protocol/viewer/ScannerReportViewerApp.java
sonar-scanner-protocol/src/main/protobuf/scanner_report.proto
sonar-scanner-protocol/src/test/java/org/sonar/scanner/protocol/output/ScannerReportReaderTest.java
sonar-scanner-protocol/src/test/java/org/sonar/scanner/protocol/output/ScannerReportWriterTest.java
sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java
sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java
sonar-ws/src/main/java/org/sonarqube/ws/client/tests/CoveredFilesRequest.java [deleted file]
sonar-ws/src/main/java/org/sonarqube/ws/client/tests/ListRequest.java [deleted file]
sonar-ws/src/main/java/org/sonarqube/ws/client/tests/TestsService.java [deleted file]
sonar-ws/src/main/java/org/sonarqube/ws/client/tests/package-info.java [deleted file]

index 9dcc8c5c93563a083ecee4056813b182f51d21dc..87c8adf27cfbee6a2120298c8127978990325422 100644 (file)
@@ -59,10 +59,6 @@ public interface BatchReportReader {
    */
   Optional<CloseableIterator<String>> readFileSource(int fileRef);
 
-  CloseableIterator<ScannerReport.Test> readTests(int testFileRef);
-
-  CloseableIterator<ScannerReport.CoverageDetail> readCoverageDetails(int testFileRef);
-
   CloseableIterator<ScannerReport.ContextProperty> readContextProperties();
 
   Optional<CloseableIterator<ScannerReport.LineSgnificantCode>> readComponentSignificantCode(int fileRef);
index cc1ed72287c0867cfe8776cfe00cdb72f28452c5..353949dffd8ae0c1e7121d94fbe3f0a5eca5ccff 100644 (file)
  */
 package org.sonar.ce.task.projectanalysis.batch;
 
-import com.google.common.base.Throwables;
-import com.google.protobuf.InvalidProtocolBufferException;
-import com.google.protobuf.Parser;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.util.NoSuchElementException;
@@ -92,7 +88,6 @@ public class BatchReportReaderImpl implements BatchReportReader {
     return delegate.readAdHocRules();
   }
 
-
   @Override
   public CloseableIterator<ScannerReport.Measure> readComponentMeasures(int componentRef) {
     ensureInitialized();
@@ -198,76 +193,12 @@ public class BatchReportReaderImpl implements BatchReportReader {
     }
   }
 
-  @Override
-  public CloseableIterator<ScannerReport.Test> readTests(int testFileRef) {
-    ensureInitialized();
-    File file = delegate.readTests(testFileRef);
-    if (file == null) {
-      return CloseableIterator.emptyCloseableIterator();
-    }
-
-    try {
-      return new ParserCloseableIterator<>(ScannerReport.Test.parser(), FileUtils.openInputStream(file));
-    } catch (IOException e) {
-      Throwables.propagate(e);
-      // actually never reached
-      return CloseableIterator.emptyCloseableIterator();
-    }
-  }
-
-  @Override
-  public CloseableIterator<ScannerReport.CoverageDetail> readCoverageDetails(int testFileRef) {
-    ensureInitialized();
-    File file = delegate.readCoverageDetails(testFileRef);
-    if (file == null) {
-      return CloseableIterator.emptyCloseableIterator();
-    }
-
-    try {
-      return new ParserCloseableIterator<>(ScannerReport.CoverageDetail.parser(), FileUtils.openInputStream(file));
-    } catch (IOException e) {
-      Throwables.propagate(e);
-      // actually never reached
-      return CloseableIterator.emptyCloseableIterator();
-    }
-  }
-
   @Override
   public CloseableIterator<ScannerReport.ContextProperty> readContextProperties() {
     ensureInitialized();
     return delegate.readContextProperties();
   }
 
-  private static class ParserCloseableIterator<T> extends CloseableIterator<T> {
-    private final Parser<T> parser;
-    private final FileInputStream fileInputStream;
-
-    public ParserCloseableIterator(Parser<T> parser, FileInputStream fileInputStream) {
-      this.parser = parser;
-      this.fileInputStream = fileInputStream;
-    }
-
-    @Override
-    protected T doNext() {
-      try {
-        return parser.parseDelimitedFrom(fileInputStream);
-      } catch (InvalidProtocolBufferException e) {
-        Throwables.propagate(e);
-        // actually never reached
-        return null;
-      }
-    }
-
-    @Override
-    protected void doClose() throws Exception {
-      fileInputStream.close();
-    }
-  }
-
-  public boolean hasSignificantCode(int fileRef) {
-    return delegate.hasSignificantCode(fileRef);
-  }
-
   @Override
   public Optional<CloseableIterator<LineSgnificantCode>> readComponentSignificantCode(int fileRef) {
     ensureInitialized();
index 237d836a2cb4ad34dc538bf3464179b7836657f4..70ebb5f33e8b5c1639a70eb6c9eec8cef9fe373e 100644 (file)
@@ -25,16 +25,13 @@ import org.sonar.api.server.ServerSide;
 import org.sonar.db.purge.PurgeListener;
 import org.sonar.server.component.index.ComponentIndexer;
 import org.sonar.server.issue.index.IssueIndexer;
-import org.sonar.server.test.index.TestIndexer;
 
 @ServerSide
 public class IndexPurgeListener implements PurgeListener {
-  private final TestIndexer testIndexer;
   private final IssueIndexer issueIndexer;
   private final ComponentIndexer componentIndexer;
 
-  public IndexPurgeListener(TestIndexer testIndexer, IssueIndexer issueIndexer, ComponentIndexer componentIndexer) {
-    this.testIndexer = testIndexer;
+  public IndexPurgeListener(IssueIndexer issueIndexer, ComponentIndexer componentIndexer) {
     this.issueIndexer = issueIndexer;
     this.componentIndexer = componentIndexer;
   }
@@ -42,11 +39,6 @@ public class IndexPurgeListener implements PurgeListener {
   @Override
   public void onComponentsDisabling(String projectUuid, Collection<String> disabledComponentUuids) {
     componentIndexer.delete(projectUuid, disabledComponentUuids);
-    disabledComponentUuids.forEach(this::onComponentDisabling);
-  }
-
-  private void onComponentDisabling(String uuid) {
-    testIndexer.deleteByFile(uuid);
   }
 
   @Override
index 048ad74ea9ad91b5b349d94c0f0b2814fca829a6..6f9b8b5442b9d6ee6acc516a686b98a40ddb6bc2 100644 (file)
@@ -22,13 +22,13 @@ package org.sonar.ce.task.projectanalysis.scm;
 import java.util.Optional;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
+import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
+import org.sonar.ce.task.projectanalysis.analysis.Branch;
 import org.sonar.ce.task.projectanalysis.component.Component;
 import org.sonar.ce.task.projectanalysis.component.MergeBranchComponentUuids;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.source.FileSourceDto;
-import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
-import org.sonar.ce.task.projectanalysis.analysis.Branch;
 
 public class ScmInfoDbLoader {
   private static final Logger LOGGER = Loggers.get(ScmInfoDbLoader.class);
@@ -51,7 +51,7 @@ public class ScmInfoDbLoader {
 
     LOGGER.trace("Reading SCM info from DB for file '{}'", uuid.get());
     try (DbSession dbSession = dbClient.openSession(false)) {
-      FileSourceDto dto = dbClient.fileSourceDao().selectSourceByFileUuid(dbSession, uuid.get());
+      FileSourceDto dto = dbClient.fileSourceDao().selectByFileUuid(dbSession, uuid.get());
       if (dto == null) {
         return Optional.empty();
       }
index 8eac3d6a40bc1b083a810e7b2c123ef8f58fc1e1..4e446cf7c524ca67935cb659a6006446f96b7532 100644 (file)
@@ -39,7 +39,6 @@ import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.protobuf.DbFileSources;
 import org.sonar.db.source.FileSourceDto;
-import org.sonar.db.source.FileSourceDto.Type;
 
 import static org.sonar.ce.task.projectanalysis.component.ComponentVisitor.Order.PRE_ORDER;
 
@@ -87,7 +86,7 @@ public class PersistFileSourcesStep implements ComputationStep {
     @Override
     public void visitProject(Component project) {
       this.projectUuid = project.getUuid();
-      session.select("org.sonar.db.source.FileSourceMapper.selectHashesForProject", ImmutableMap.of("projectUuid", projectUuid, "dataType", Type.SOURCE),
+      session.select("org.sonar.db.source.FileSourceMapper.selectHashesForProject", ImmutableMap.of("projectUuid", projectUuid),
         context -> {
           FileSourceDto dto = (FileSourceDto) context.getResultObject();
           previousFileSourcesByUuid.put(dto.getFileUuid(), dto);
@@ -119,7 +118,6 @@ public class PersistFileSourcesStep implements ComputationStep {
         FileSourceDto dto = new FileSourceDto()
           .setProjectUuid(projectUuid)
           .setFileUuid(file.getUuid())
-          .setDataType(Type.SOURCE)
           .setBinaryData(binaryData)
           .setSrcHash(srcHash)
           .setDataHash(dataHash)
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistTestsStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistTestsStep.java
deleted file mode 100644 (file)
index 8231e05..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.ce.task.projectanalysis.step;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.HashBasedTable;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Table;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.sonar.api.utils.System2;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.ce.task.projectanalysis.batch.BatchReportReader;
-import org.sonar.ce.task.projectanalysis.component.Component;
-import org.sonar.ce.task.projectanalysis.component.ComponentVisitor;
-import org.sonar.ce.task.projectanalysis.component.CrawlerDepthLimit;
-import org.sonar.ce.task.projectanalysis.component.DepthTraversalTypeAwareCrawler;
-import org.sonar.ce.task.projectanalysis.component.TreeRootHolder;
-import org.sonar.ce.task.projectanalysis.component.TypeAwareVisitorAdapter;
-import org.sonar.ce.task.step.ComputationStep;
-import org.sonar.core.util.CloseableIterator;
-import org.sonar.core.util.Uuids;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.protobuf.DbFileSources;
-import org.sonar.db.source.FileSourceDto;
-import org.sonar.db.source.FileSourceDto.Type;
-import org.sonar.scanner.protocol.output.ScannerReport;
-import org.sonar.scanner.protocol.output.ScannerReport.Test.TestStatus;
-
-public class PersistTestsStep implements ComputationStep {
-
-  private static final Logger LOG = Loggers.get(PersistTestsStep.class);
-
-  private final DbClient dbClient;
-  private final System2 system;
-  private final BatchReportReader reportReader;
-  private final TreeRootHolder treeRootHolder;
-
-  public PersistTestsStep(DbClient dbClient, System2 system, BatchReportReader reportReader, TreeRootHolder treeRootHolder) {
-    this.dbClient = dbClient;
-    this.system = system;
-    this.reportReader = reportReader;
-    this.treeRootHolder = treeRootHolder;
-  }
-
-  @Override
-  public void execute(ComputationStep.Context context) {
-    try (DbSession dbSession = dbClient.openSession(true)) {
-      TestDepthTraversalTypeAwareVisitor visitor = new TestDepthTraversalTypeAwareVisitor(dbSession);
-      new DepthTraversalTypeAwareCrawler(visitor).visit(treeRootHolder.getRoot());
-      dbSession.commit();
-      if (visitor.hasUnprocessedCoverageDetails) {
-        LOG.warn("Some coverage tests are not taken into account during analysis of project '{}'", visitor.getProjectKey());
-      }
-    }
-  }
-
-  @Override
-  public String getDescription() {
-    return "Persist tests";
-  }
-
-  private class TestDepthTraversalTypeAwareVisitor extends TypeAwareVisitorAdapter {
-    final DbSession session;
-    final Map<String, FileSourceDto> existingFileSourcesByUuid;
-    final String projectUuid;
-    final String projectKey;
-    boolean hasUnprocessedCoverageDetails = false;
-
-    public TestDepthTraversalTypeAwareVisitor(DbSession session) {
-      super(CrawlerDepthLimit.FILE, ComponentVisitor.Order.PRE_ORDER);
-      this.session = session;
-      this.existingFileSourcesByUuid = new HashMap<>();
-      this.projectUuid = treeRootHolder.getRoot().getUuid();
-      this.projectKey = treeRootHolder.getRoot().getDbKey();
-      session.select("org.sonar.db.source.FileSourceMapper.selectHashesForProject",
-        ImmutableMap.of("projectUuid", treeRootHolder.getRoot().getUuid(), "dataType", Type.TEST),
-        context -> {
-          FileSourceDto dto = (FileSourceDto) context.getResultObject();
-          existingFileSourcesByUuid.put(dto.getFileUuid(), dto);
-        });
-    }
-
-    @Override
-    public void visitFile(Component file) {
-      if (file.getFileAttributes().isUnitTest()) {
-        persistTestResults(file);
-      }
-    }
-
-    private void persistTestResults(Component component) {
-      Multimap<String, DbFileSources.Test.Builder> testsByName = buildDbTests(component.getReportAttributes().getRef());
-      Table<String, String, DbFileSources.Test.CoveredFile.Builder> coveredFilesByName = loadCoverageDetails(component.getReportAttributes().getRef());
-      List<DbFileSources.Test> tests = addCoveredFilesToTests(testsByName, coveredFilesByName);
-      if (checkIfThereAreUnprocessedCoverageDetails(testsByName, coveredFilesByName, component.getDbKey())) {
-        hasUnprocessedCoverageDetails = true;
-      }
-
-      if (tests.isEmpty()) {
-        return;
-      }
-
-      String componentUuid = getUuid(component.getReportAttributes().getRef());
-      FileSourceDto existingDto = existingFileSourcesByUuid.get(componentUuid);
-      long now = system.now();
-      if (existingDto != null) {
-        // update
-        existingDto
-          .setTestData(tests)
-          .setUpdatedAt(now);
-        dbClient.fileSourceDao().update(session, existingDto);
-      } else {
-        // insert
-        FileSourceDto newDto = new FileSourceDto()
-          .setTestData(tests)
-          .setFileUuid(componentUuid)
-          .setProjectUuid(projectUuid)
-          .setDataType(Type.TEST)
-          .setCreatedAt(now)
-          .setUpdatedAt(now);
-        dbClient.fileSourceDao().insert(session, newDto);
-      }
-    }
-
-    private boolean checkIfThereAreUnprocessedCoverageDetails(Multimap<String, DbFileSources.Test.Builder> testsByName,
-                                                              Table<String, String, DbFileSources.Test.CoveredFile.Builder> coveredFilesByName, String componentKey) {
-      Set<String> unprocessedCoverageDetailNames = new HashSet<>(coveredFilesByName.rowKeySet());
-      unprocessedCoverageDetailNames.removeAll(testsByName.keySet());
-      boolean hasUnprocessedCoverage = !unprocessedCoverageDetailNames.isEmpty();
-      if (hasUnprocessedCoverage) {
-        LOG.trace("The following test coverages for file '{}' have not been taken into account: {}", componentKey, Joiner.on(", ").join(unprocessedCoverageDetailNames));
-      }
-      return hasUnprocessedCoverage;
-    }
-
-    private List<DbFileSources.Test> addCoveredFilesToTests(Multimap<String, DbFileSources.Test.Builder> testsByName,
-                                                            Table<String, String, DbFileSources.Test.CoveredFile.Builder> coveredFilesByName) {
-      List<DbFileSources.Test> tests = new ArrayList<>();
-      for (DbFileSources.Test.Builder test : testsByName.values()) {
-        Collection<DbFileSources.Test.CoveredFile.Builder> coveredFiles = coveredFilesByName.row(test.getName()).values();
-        if (!coveredFiles.isEmpty()) {
-          for (DbFileSources.Test.CoveredFile.Builder coveredFile : coveredFiles) {
-            test.addCoveredFile(coveredFile);
-          }
-        }
-        tests.add(test.build());
-      }
-
-      return tests;
-    }
-
-    private Multimap<String, DbFileSources.Test.Builder> buildDbTests(int componentRed) {
-      Multimap<String, DbFileSources.Test.Builder> tests = ArrayListMultimap.create();
-
-      try (CloseableIterator<ScannerReport.Test> testIterator = reportReader.readTests(componentRed)) {
-        while (testIterator.hasNext()) {
-          ScannerReport.Test batchTest = testIterator.next();
-          DbFileSources.Test.Builder dbTest = DbFileSources.Test.newBuilder();
-          dbTest.setUuid(Uuids.create());
-          dbTest.setName(batchTest.getName());
-          if (!batchTest.getStacktrace().isEmpty()) {
-            dbTest.setStacktrace(batchTest.getStacktrace());
-          }
-          if (batchTest.getStatus() != TestStatus.UNSET) {
-            dbTest.setStatus(DbFileSources.Test.TestStatus.valueOf(batchTest.getStatus().name()));
-          }
-          if (!batchTest.getMsg().isEmpty()) {
-            dbTest.setMsg(batchTest.getMsg());
-          }
-          dbTest.setExecutionTimeMs(batchTest.getDurationInMs());
-
-          tests.put(dbTest.getName(), dbTest);
-        }
-      }
-
-      return tests;
-    }
-
-    /**
-     * returns a Table of (test name, main file uuid, covered file)
-     */
-    private Table<String, String, DbFileSources.Test.CoveredFile.Builder> loadCoverageDetails(int testFileRef) {
-      Table<String, String, DbFileSources.Test.CoveredFile.Builder> nameToCoveredFiles = HashBasedTable.create();
-
-      try (CloseableIterator<ScannerReport.CoverageDetail> coverageIterator = reportReader.readCoverageDetails(testFileRef)) {
-        while (coverageIterator.hasNext()) {
-          ScannerReport.CoverageDetail batchCoverageDetail = coverageIterator.next();
-          String testName = batchCoverageDetail.getTestName();
-          for (ScannerReport.CoverageDetail.CoveredFile batchCoveredFile : batchCoverageDetail.getCoveredFileList()) {
-            loadCoverageFile(batchCoveredFile, testName, nameToCoveredFiles);
-          }
-        }
-      }
-      return nameToCoveredFiles;
-    }
-
-    private void loadCoverageFile(ScannerReport.CoverageDetail.CoveredFile batchCoveredFile, String testName, Table<String, String,
-      DbFileSources.Test.CoveredFile.Builder> nameToCoveredFiles) {
-      String mainFileUuid = getUuid(batchCoveredFile.getFileRef());
-      DbFileSources.Test.CoveredFile.Builder existingDbCoveredFile = nameToCoveredFiles.get(testName, mainFileUuid);
-      List<Integer> batchCoveredLines = batchCoveredFile.getCoveredLineList();
-      if (existingDbCoveredFile == null) {
-        DbFileSources.Test.CoveredFile.Builder dbCoveredFile = DbFileSources.Test.CoveredFile.newBuilder()
-          .setFileUuid(getUuid(batchCoveredFile.getFileRef()))
-          .addAllCoveredLine(batchCoveredLines);
-        nameToCoveredFiles.put(testName, mainFileUuid, dbCoveredFile);
-      } else {
-        List<Integer> remainingBatchCoveredLines = new ArrayList<>(batchCoveredLines);
-        remainingBatchCoveredLines.removeAll(existingDbCoveredFile.getCoveredLineList());
-        existingDbCoveredFile.addAllCoveredLine(batchCoveredLines);
-      }
-    }
-
-    private String getUuid(int fileRef) {
-      return treeRootHolder.getComponentByRef(fileRef).getUuid();
-    }
-
-    public String getProjectKey() {
-      return projectKey;
-    }
-  }
-
-}
index 899b5ee014b368a29756e624d18ecb4dad8ff861..e1e6b5b0895f8360b0e2b55ed4af5ca35469c4c6 100644 (file)
@@ -99,7 +99,6 @@ public class ReportComputationSteps extends AbstractComputationSteps {
     PersistProjectLinksStep.class,
     PersistEventsStep.class,
     PersistFileSourcesStep.class,
-    PersistTestsStep.class,
     PersistCrossProjectDuplicationIndexStep.class,
     EnableAnalysisStep.class,
 
index 38736275d4876003ba2af2a91750cec503729941..c2c8b96f421ea484775b2e3cf98ebf8bc57d28ec 100644 (file)
@@ -47,10 +47,6 @@ public class BatchReportReaderImplTest {
   private static final ScannerReport.SyntaxHighlightingRule SYNTAX_HIGHLIGHTING_2 = ScannerReport.SyntaxHighlightingRule.newBuilder().build();
   private static final ScannerReport.LineCoverage COVERAGE_1 = ScannerReport.LineCoverage.newBuilder().build();
   private static final ScannerReport.LineCoverage COVERAGE_2 = ScannerReport.LineCoverage.newBuilder().build();
-  private static final ScannerReport.Test TEST_1 = ScannerReport.Test.newBuilder().setName("1").build();
-  private static final ScannerReport.Test TEST_2 = ScannerReport.Test.newBuilder().setName("2").build();
-  private static final ScannerReport.CoverageDetail COVERAGE_DETAIL_1 = ScannerReport.CoverageDetail.newBuilder().setTestName("1").build();
-  private static final ScannerReport.CoverageDetail COVERAGE_DETAIL_2 = ScannerReport.CoverageDetail.newBuilder().setTestName("2").build();
 
   @Rule
   public JUnitTempFolder tempFolder = new JUnitTempFolder();
@@ -288,34 +284,6 @@ public class BatchReportReaderImplTest {
     res.close();
   }
 
-  @Test
-  public void readTests_returns_empty_CloseableIterator_when_file_does_not_exist() {
-    assertThat(underTest.readTests(COMPONENT_REF)).isEmpty();
-  }
-
-  @Test
-  public void verify_readTests() {
-    writer.writeTests(COMPONENT_REF, of(TEST_1, TEST_2));
-
-    CloseableIterator<ScannerReport.Test> res = underTest.readTests(COMPONENT_REF);
-    assertThat(res).containsExactly(TEST_1, TEST_2);
-    res.close();
-  }
-
-  @Test
-  public void readCoverageDetails_returns_empty_CloseableIterator_when_file_does_not_exist() {
-    assertThat(underTest.readCoverageDetails(COMPONENT_REF)).isEmpty();
-  }
-
-  @Test
-  public void verify_readCoverageDetails() {
-    writer.writeCoverageDetails(COMPONENT_REF, of(COVERAGE_DETAIL_1, COVERAGE_DETAIL_2));
-
-    CloseableIterator<ScannerReport.CoverageDetail> res = underTest.readCoverageDetails(COMPONENT_REF);
-    assertThat(res).containsExactly(COVERAGE_DETAIL_1, COVERAGE_DETAIL_2);
-    res.close();
-  }
-
   @Test
   public void verify_readAnalysisWarnings() {
     ScannerReport.AnalysisWarning warning1 = ScannerReport.AnalysisWarning.newBuilder().setText("warning 1").build();
index 8417e6870a541048d89f596d296843cbd1d34ad1..2f67e6ddfa7affbbeed493091e7f73201f1f4779 100644 (file)
@@ -54,8 +54,6 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
   private Map<Integer, List<ScannerReport.SyntaxHighlightingRule>> syntaxHighlightings = new HashMap<>();
   private Map<Integer, List<ScannerReport.LineCoverage>> coverages = new HashMap<>();
   private Map<Integer, List<String>> fileSources = new HashMap<>();
-  private Map<Integer, List<ScannerReport.Test>> tests = new HashMap<>();
-  private Map<Integer, List<ScannerReport.CoverageDetail>> coverageDetails = new HashMap<>();
   private Map<Integer, List<ScannerReport.LineSgnificantCode>> significantCode = new HashMap<>();
   private Map<Integer, ScannerReport.ChangedLines> changedLines = new HashMap<>();
   private List<ScannerReport.AnalysisWarning> analysisWarnings = Collections.emptyList();
@@ -87,8 +85,6 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     this.syntaxHighlightings.clear();
     this.coverages.clear();
     this.fileSources.clear();
-    this.tests.clear();
-    this.coverageDetails.clear();
     this.significantCode.clear();
   }
 
@@ -308,24 +304,4 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader {
     return this;
   }
 
-  @Override
-  public CloseableIterator<ScannerReport.Test> readTests(int testFileRef) {
-    return closeableIterator(this.tests.get(testFileRef));
-  }
-
-  public BatchReportReaderRule putTests(int testFileRed, List<ScannerReport.Test> tests) {
-    this.tests.put(testFileRed, tests);
-    return this;
-  }
-
-  @Override
-  public CloseableIterator<ScannerReport.CoverageDetail> readCoverageDetails(int testFileRef) {
-    return closeableIterator(this.coverageDetails.get(testFileRef));
-  }
-
-  public BatchReportReaderRule putCoverageDetails(int testFileRef, List<ScannerReport.CoverageDetail> coverageDetails) {
-    this.coverageDetails.put(testFileRef, coverageDetails);
-    return this;
-  }
-
 }
index 059736bcd977173d07f6fefd7062507557f2f09c..791a7b43a5509955a576a25ac58c37b02ac172e5 100644 (file)
@@ -19,9 +19,6 @@
  */
 package org.sonar.ce.task.projectanalysis.dbmigration;
 
-import com.tngtech.java.junit.dataprovider.DataProvider;
-import com.tngtech.java.junit.dataprovider.DataProviderRunner;
-import com.tngtech.java.junit.dataprovider.UseDataProvider;
 import java.sql.SQLException;
 import java.util.Optional;
 import java.util.Random;
@@ -31,11 +28,9 @@ import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
 import org.sonar.api.utils.System2;
 import org.sonar.ce.task.CeTask;
 import org.sonar.db.DbTester;
-import org.sonar.db.source.FileSourceDto;
 
 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
 import static org.assertj.core.api.Assertions.assertThat;
@@ -43,7 +38,6 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.sonar.db.source.FileSourceDto.LINE_COUNT_NOT_POPULATED;
 
-@RunWith(DataProviderRunner.class)
 public class PopulateFileSourceLineCountTest {
 
   @Rule
@@ -65,13 +59,12 @@ public class PopulateFileSourceLineCountTest {
   }
 
   @Test
-  @UseDataProvider("anyType")
-  public void execute_populates_line_count_of_any_type(String type) throws SQLException {
+  public void execute_populates_line_count_of_any_type() throws SQLException {
     String projectUuid = randomAlphanumeric(4);
     String fileUuid = randomAlphanumeric(5);
     when(ceTask.getComponent()).thenReturn(newComponent(projectUuid));
     int lineCount = 1 + random.nextInt(15);
-    insertUnpopulatedFileSource(projectUuid, fileUuid, type, lineCount);
+    insertUnpopulatedFileSource(projectUuid, fileUuid, lineCount);
     assertThat(getLineCountByFileUuid(fileUuid)).isEqualTo(LINE_COUNT_NOT_POPULATED);
 
     underTest.execute();
@@ -80,8 +73,7 @@ public class PopulateFileSourceLineCountTest {
   }
 
   @Test
-  @UseDataProvider("anyType")
-  public void execute_changes_only_file_source_with_LINE_COUNT_NOT_POPULATED_value(String type) throws SQLException {
+  public void execute_changes_only_file_source_with_LINE_COUNT_NOT_POPULATED_value() throws SQLException {
     String projectUuid = randomAlphanumeric(4);
     String fileUuid1 = randomAlphanumeric(5);
     String fileUuid2 = randomAlphanumeric(6);
@@ -91,9 +83,9 @@ public class PopulateFileSourceLineCountTest {
     int lineCountFile3 = 150 + random.nextInt(15);
 
     when(ceTask.getComponent()).thenReturn(newComponent(projectUuid));
-    insertPopulatedFileSource(projectUuid, fileUuid1, type, lineCountFile1);
-    int badLineCountFile2 = insertInconsistentPopulatedFileSource(projectUuid, fileUuid2, type, lineCountFile2);
-    insertUnpopulatedFileSource(projectUuid, fileUuid3, type, lineCountFile3);
+    insertPopulatedFileSource(projectUuid, fileUuid1, lineCountFile1);
+    int badLineCountFile2 = insertInconsistentPopulatedFileSource(projectUuid, fileUuid2, lineCountFile2);
+    insertUnpopulatedFileSource(projectUuid, fileUuid3, lineCountFile3);
     assertThat(getLineCountByFileUuid(fileUuid1)).isEqualTo(lineCountFile1);
     assertThat(getLineCountByFileUuid(fileUuid2)).isEqualTo(badLineCountFile2);
     assertThat(getLineCountByFileUuid(fileUuid3)).isEqualTo(LINE_COUNT_NOT_POPULATED);
@@ -106,8 +98,7 @@ public class PopulateFileSourceLineCountTest {
   }
 
   @Test
-  @UseDataProvider("anyType")
-  public void execute_changes_only_file_source_of_CeTask_component_uuid(String type) throws SQLException {
+  public void execute_changes_only_file_source_of_CeTask_component_uuid() throws SQLException {
     String projectUuid1 = randomAlphanumeric(4);
     String projectUuid2 = randomAlphanumeric(5);
     String fileUuid1 = randomAlphanumeric(6);
@@ -116,8 +107,8 @@ public class PopulateFileSourceLineCountTest {
     int lineCountFile2 = 30 + random.nextInt(15);
 
     when(ceTask.getComponent()).thenReturn(newComponent(projectUuid1));
-    insertUnpopulatedFileSource(projectUuid1, fileUuid1, type, lineCountFile1);
-    insertUnpopulatedFileSource(projectUuid2, fileUuid2, type, lineCountFile2);
+    insertUnpopulatedFileSource(projectUuid1, fileUuid1, lineCountFile1);
+    insertUnpopulatedFileSource(projectUuid2, fileUuid2, lineCountFile2);
 
     underTest.execute();
 
@@ -126,13 +117,12 @@ public class PopulateFileSourceLineCountTest {
   }
 
   @Test
-  @UseDataProvider("anyType")
-  public void execute_set_line_count_to_zero_when_file_source_has_no_line_hashes(String type) throws SQLException {
+  public void execute_set_line_count_to_zero_when_file_source_has_no_line_hashes() throws SQLException {
     String projectUuid = randomAlphanumeric(4);
     String fileUuid1 = randomAlphanumeric(5);
 
     when(ceTask.getComponent()).thenReturn(newComponent(projectUuid));
-    insertFileSource(projectUuid, fileUuid1, type, null, LINE_COUNT_NOT_POPULATED);
+    insertFileSource(projectUuid, fileUuid1, null, LINE_COUNT_NOT_POPULATED);
 
     underTest.execute();
 
@@ -140,52 +130,41 @@ public class PopulateFileSourceLineCountTest {
   }
 
   @Test
-  @UseDataProvider("anyType")
-  public void execute_set_line_count_to_1_when_file_source_has_empty_line_hashes(String type) throws SQLException {
+  public void execute_set_line_count_to_1_when_file_source_has_empty_line_hashes() throws SQLException {
     String projectUuid = randomAlphanumeric(4);
     String fileUuid1 = randomAlphanumeric(5);
 
     when(ceTask.getComponent()).thenReturn(newComponent(projectUuid));
-    insertFileSource(projectUuid, fileUuid1, type, "", LINE_COUNT_NOT_POPULATED);
+    insertFileSource(projectUuid, fileUuid1, "", LINE_COUNT_NOT_POPULATED);
 
     underTest.execute();
 
     assertThat(getLineCountByFileUuid(fileUuid1)).isEqualTo(1);
   }
 
-  @DataProvider
-  public static Object[][] anyType() {
-    return new Object[][] {
-      {FileSourceDto.Type.SOURCE},
-      {FileSourceDto.Type.TEST},
-      {null},
-      {randomAlphanumeric(3)},
-    };
-  }
-
   private int getLineCountByFileUuid(String fileUuid) {
     Long res = (Long) db.selectFirst("select line_count as \"LINE_COUNT\" from file_sources where file_uuid = '" + fileUuid + "'")
       .get("LINE_COUNT");
     return res.intValue();
   }
 
-  private void insertUnpopulatedFileSource(String projectUuid, String fileUuid, @Nullable String dataType, int numberOfHashes) {
+  private void insertUnpopulatedFileSource(String projectUuid, String fileUuid, int numberOfHashes) {
     String lineHashes = generateLineHashes(numberOfHashes);
 
-    insertFileSource(projectUuid, fileUuid, dataType, lineHashes, LINE_COUNT_NOT_POPULATED);
+    insertFileSource(projectUuid, fileUuid, lineHashes, LINE_COUNT_NOT_POPULATED);
   }
 
-  private void insertPopulatedFileSource(String projectUuid, String fileUuid, @Nullable String dataType, int lineCount) {
+  private void insertPopulatedFileSource(String projectUuid, String fileUuid, int lineCount) {
     String lineHashes = generateLineHashes(lineCount);
 
-    insertFileSource(projectUuid, fileUuid, dataType, lineHashes, lineCount);
+    insertFileSource(projectUuid, fileUuid, lineHashes, lineCount);
   }
 
-  private int insertInconsistentPopulatedFileSource(String projectUuid, String fileUuid, @Nullable String dataType, int lineCount) {
+  private int insertInconsistentPopulatedFileSource(String projectUuid, String fileUuid, int lineCount) {
     String lineHashes = generateLineHashes(lineCount);
     int badLineCount = lineCount + random.nextInt(6);
 
-    insertFileSource(projectUuid, fileUuid, dataType, lineHashes, badLineCount);
+    insertFileSource(projectUuid, fileUuid, lineHashes, badLineCount);
 
     return badLineCount;
   }
@@ -196,13 +175,12 @@ public class PopulateFileSourceLineCountTest {
       .collect(Collectors.joining("\n"));
   }
 
-  private void insertFileSource(String projectUuid, String fileUuid, @Nullable String dataType, @Nullable String lineHashes, int lineCount) {
+  private void insertFileSource(String projectUuid, String fileUuid, @Nullable String lineHashes, int lineCount) {
     db.executeInsert(
       "FILE_SOURCES",
       "PROJECT_UUID", projectUuid,
       "FILE_UUID", fileUuid,
       "LINE_HASHES", lineHashes,
-      "DATA_TYPE", dataType,
       "LINE_COUNT", lineCount,
       "CREATED_AT", 1_222_333L,
       "UPDATED_AT", 1_222_333L);
index 97d0f6eb5f457c3be0431564517bbedf5c2ea203..d69681c8cbaa66f3d89f3ef758022438981a2653 100644 (file)
@@ -600,8 +600,7 @@ public class FileMoveDetectionStepTest {
         FileSourceDto fileSourceDto = new FileSourceDto()
           .setFileUuid(file.uuid())
           .setProjectUuid(file.projectUuid())
-          .setLineHashes(linesHashesComputer.getLineHashes())
-          .setDataType(FileSourceDto.Type.SOURCE);
+          .setLineHashes(linesHashesComputer.getLineHashes());
         dbTester.getDbClient().fileSourceDao().insert(dbTester.getSession(), fileSourceDto);
         dbTester.commit();
         return fileSourceDto;
index 7ee5dfe10d67dff0c11024c4fa8144fcd4e2d14f..dd04702247267e8ec90b857b119691e75fcab01c 100644 (file)
@@ -23,7 +23,6 @@ import java.util.List;
 import org.junit.Test;
 import org.sonar.server.component.index.ComponentIndexer;
 import org.sonar.server.issue.index.IssueIndexer;
-import org.sonar.server.test.index.TestIndexer;
 
 import static java.util.Arrays.asList;
 import static java.util.Collections.singletonList;
@@ -32,11 +31,10 @@ import static org.mockito.Mockito.verify;
 
 public class IndexPurgeListenerTest {
 
-  private TestIndexer testIndexer = mock(TestIndexer.class);
   private IssueIndexer issueIndexer = mock(IssueIndexer.class);
   private ComponentIndexer componentIndexer = mock(ComponentIndexer.class);
 
-  private IndexPurgeListener underTest = new IndexPurgeListener(testIndexer, issueIndexer, componentIndexer);
+  private IndexPurgeListener underTest = new IndexPurgeListener(issueIndexer, componentIndexer);
 
   @Test
   public void test_onComponentDisabling() {
@@ -45,7 +43,6 @@ public class IndexPurgeListenerTest {
     List<String> uuids = singletonList(uuid);
     underTest.onComponentsDisabling(projectUuid, uuids);
 
-    verify(testIndexer).deleteByFile(uuid);
     verify(componentIndexer).delete(projectUuid, uuids);
   }
 
index a519bd661b801eea8efb9a529fef45653e78bf31..1806989f94527920c9536bfc1dde76439769e60f 100644 (file)
@@ -43,7 +43,6 @@ import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.protobuf.DbFileSources;
 import org.sonar.db.source.FileSourceDto;
-import org.sonar.db.source.FileSourceDto.Type;
 import org.sonar.db.source.LineHashVersion;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -107,7 +106,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
     underTest.execute(new TestComputationStepContext());
 
     assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
-    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
+    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID);
     assertThat(fileSourceDto.getProjectUuid()).isEqualTo(PROJECT_UUID);
     assertThat(fileSourceDto.getFileUuid()).isEqualTo(FILE1_UUID);
     assertThat(fileSourceDto.getBinaryData()).isNotEmpty();
@@ -135,7 +134,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
     underTest.execute(new TestComputationStepContext());
 
     assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
-    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
+    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID);
     assertThat(fileSourceDto.getLineHashes()).containsExactly("137f72c3708c6bd0de00a0e5a69c699b", "e6251bcf1a7dc3ba5e7933e325bbe605");
     assertThat(fileSourceDto.getSrcHash()).isEqualTo("ee5a58024a155466b43bc559d953e018");
     verify(fileSourceDataWarnings).commitWarnings();
@@ -156,7 +155,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
     underTest.execute(new TestComputationStepContext());
 
     assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
-    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
+    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID);
     assertThat(fileSourceDto.getSourceData()).isEqualTo(dbData);
     verify(fileSourceDataWarnings).commitWarnings();
   }
@@ -179,7 +178,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
     underTest.execute(new TestComputationStepContext());
 
     assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
-    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
+    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID);
     assertThat(fileSourceDto.getSourceData()).isEqualTo(dbData);
     assertThat(fileSourceDto.getRevision()).isNull();
     verify(fileSourceDataWarnings).commitWarnings();
@@ -204,7 +203,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
     underTest.execute(new TestComputationStepContext());
 
     assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
-    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
+    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID);
 
     DbFileSources.Data data = fileSourceDto.getSourceData();
 
@@ -236,7 +235,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
     underTest.execute(new TestComputationStepContext());
 
     assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
-    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
+    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID);
     DbFileSources.Data data = fileSourceDto.getSourceData();
     assertThat(data).isEqualTo(dbData);
     assertThat(data.getLinesList()).hasSize(1);
@@ -260,7 +259,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
     underTest.execute(new TestComputationStepContext());
 
     assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
-    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
+    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID);
     assertThat(fileSourceDto.getSourceData()).isEqualTo(dbData);
     verify(fileSourceDataWarnings).commitWarnings();
   }
@@ -277,7 +276,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
     underTest.execute(new TestComputationStepContext());
 
     assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
-    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
+    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID);
     assertThat(fileSourceDto.getSourceData()).isEqualTo(dbData);
     verify(fileSourceDataWarnings).commitWarnings();
   }
@@ -289,7 +288,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
 
     underTest.execute(new TestComputationStepContext());
 
-    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
+    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID);
     assertThat(fileSourceDto.getRevision()).isEqualTo("rev-1");
     verify(fileSourceDataWarnings).commitWarnings();
   }
@@ -300,7 +299,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
 
     underTest.execute(new TestComputationStepContext());
 
-    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
+    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID);
     assertThat(fileSourceDto.getRevision()).isNull();
     verify(fileSourceDataWarnings).commitWarnings();
   }
@@ -316,7 +315,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
     underTest.execute(new TestComputationStepContext());
 
     assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
-    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
+    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID);
     assertThat(fileSourceDto.getSrcHash()).isEqualTo("sourceHash");
     assertThat(fileSourceDto.getLineHashes()).isEqualTo(Collections.singletonList("lineHash"));
     assertThat(fileSourceDto.getCreatedAt()).isEqualTo(PAST);
@@ -331,7 +330,6 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
     dbClient.fileSourceDao().insert(dbTester.getSession(), new FileSourceDto()
       .setProjectUuid(PROJECT_UUID)
       .setFileUuid(FILE1_UUID)
-      .setDataType(Type.SOURCE)
       .setSrcHash("5b4bd9815cdb17b8ceae19eb1810c34c")
       .setLineHashes(Collections.singletonList("6438c669e0d0de98e6929c2cc0fac474"))
       .setDataHash("6cad150e3d065976c230cddc5a09efaa")
@@ -362,7 +360,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
     underTest.execute(new TestComputationStepContext());
 
     assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
-    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
+    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID);
     assertThat(fileSourceDto.getCreatedAt()).isEqualTo(past);
     assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(NOW);
     assertThat(fileSourceDto.getRevision()).isEqualTo("rev-1");
@@ -380,7 +378,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
     underTest.execute(new TestComputationStepContext());
 
     assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
-    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
+    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID);
     assertThat(fileSourceDto.getCreatedAt()).isEqualTo(PAST);
     assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(NOW);
     assertThat(fileSourceDto.getSrcHash()).isEqualTo("newSourceHash");
@@ -405,7 +403,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
     underTest.execute(new TestComputationStepContext());
 
     assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
-    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
+    FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID);
     assertThat(fileSourceDto.getCreatedAt()).isEqualTo(PAST);
     assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(NOW);
     assertThat(fileSourceDto.getRevision()).isEqualTo("revision");
@@ -425,7 +423,6 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
     FileSourceDto dto = new FileSourceDto()
       .setProjectUuid(PROJECT_UUID)
       .setFileUuid(FILE1_UUID)
-      .setDataType(Type.SOURCE)
       .setSrcHash("sourceHash")
       .setLineHashes(Collections.singletonList("lineHash"))
       .setDataHash(dataHash)
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistTestsStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistTestsStepTest.java
deleted file mode 100644 (file)
index f8baeae..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.ce.task.projectanalysis.step;
-
-import java.util.Arrays;
-import java.util.List;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.utils.System2;
-import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.utils.log.LoggerLevel;
-import org.sonar.ce.task.projectanalysis.batch.BatchReportReaderRule;
-import org.sonar.ce.task.projectanalysis.component.Component;
-import org.sonar.ce.task.projectanalysis.component.FileAttributes;
-import org.sonar.ce.task.projectanalysis.component.ReportComponent;
-import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
-import org.sonar.ce.task.step.ComputationStep;
-import org.sonar.ce.task.step.TestComputationStepContext;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbTester;
-import org.sonar.db.protobuf.DbFileSources;
-import org.sonar.db.source.FileSourceDto;
-import org.sonar.scanner.protocol.output.ScannerReport;
-import org.sonar.scanner.protocol.output.ScannerReport.CoverageDetail;
-import org.sonar.scanner.protocol.output.ScannerReport.Test.TestStatus;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.tuple;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class PersistTestsStepTest extends BaseStepTest {
-
-  private static final String PROJECT_UUID = "PROJECT";
-  private static final String PROJECT_KEY = "PROJECT_KEY";
-  private static final int TEST_FILE_REF_1 = 3;
-  private static final int TEST_FILE_REF_2 = 4;
-  private static final int MAIN_FILE_REF_1 = 5;
-  private static final int MAIN_FILE_REF_2 = 6;
-  private static final String TEST_FILE_UUID_1 = "TEST-FILE-1";
-  private static final String TEST_FILE_UUID_2 = "TEST-FILE-2";
-  private static final String MAIN_FILE_UUID_1 = "MAIN-FILE-1";
-  private static final String MAIN_FILE_UUID_2 = "MAIN-FILE-2";
-
-  @Rule
-  public DbTester db = DbTester.create(System2.INSTANCE);
-
-  @Rule
-  public BatchReportReaderRule reportReader = new BatchReportReaderRule();
-
-  @Rule
-  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
-
-  @Rule
-  public LogTester log = new LogTester();
-
-  DbClient dbClient = db.getDbClient();
-  Component root;
-
-  PersistTestsStep underTest;
-
-  long now = 123456789L;
-
-  @Before
-  public void setup() {
-    System2 system2 = mock(System2.class);
-    when(system2.now()).thenReturn(now);
-
-    underTest = new PersistTestsStep(dbClient, system2, reportReader, treeRootHolder);
-
-    root = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_UUID).setKey(PROJECT_KEY).addChildren(
-      ReportComponent.builder(Component.Type.FILE, 3).setUuid(TEST_FILE_UUID_1).setKey("TEST_FILE1_KEY").setFileAttributes(new FileAttributes(true, null, 1)).build(),
-      ReportComponent.builder(Component.Type.FILE, 4).setUuid(TEST_FILE_UUID_2).setKey("TEST_FILE2_KEY").setFileAttributes(new FileAttributes(true, null, 1)).build(),
-      ReportComponent.builder(Component.Type.FILE, 5).setUuid(MAIN_FILE_UUID_1).setKey("MAIN_FILE1_KEY").build(),
-      ReportComponent.builder(Component.Type.FILE, 6).setUuid(MAIN_FILE_UUID_2).setKey("MAIN_FILE2_KEY").build())
-      .build();
-    treeRootHolder.setRoot(root);
-  }
-
-  @Override
-  protected ComputationStep step() {
-    return underTest;
-  }
-
-  @Test
-  public void no_test_in_database_and_batch_report() {
-    underTest.execute(new TestComputationStepContext());
-
-    assertThat(dbClient.fileSourceDao().selectTestByFileUuid(db.getSession(), TEST_FILE_UUID_1)).isNull();
-    assertThat(log.logs()).isEmpty();
-  }
-
-  @Test
-  public void insert_several_tests_in_a_report() {
-    List<ScannerReport.Test> batchTests = Arrays.asList(
-      newTest(1), newTest(2));
-    reportReader.putTests(TEST_FILE_REF_1, batchTests);
-    List<CoverageDetail> coverageDetails = Arrays.asList(
-      newCoverageDetail(1, MAIN_FILE_REF_1));
-    reportReader.putCoverageDetails(TEST_FILE_REF_1, coverageDetails);
-
-    underTest.execute(new TestComputationStepContext());
-
-    assertThat(db.countRowsOfTable("file_sources")).isEqualTo(1);
-
-    FileSourceDto dto = dbClient.fileSourceDao().selectTestByFileUuid(db.getSession(), TEST_FILE_UUID_1);
-    assertThat(dto.getCreatedAt()).isEqualTo(now);
-    assertThat(dto.getUpdatedAt()).isEqualTo(now);
-    assertThat(dto.getProjectUuid()).isEqualTo(PROJECT_UUID);
-    assertThat(dto.getFileUuid()).isEqualTo(TEST_FILE_UUID_1);
-    assertThat(dto.getTestData()).hasSize(2);
-
-    assertThat(dto.getTestData()).extracting("name", "coveredFileCount").containsOnly(
-      tuple("name#1", 1),
-      tuple("name#2", 0));
-
-    assertThat(log.logs()).isEmpty();
-  }
-
-  @Test
-  public void insert_all_data_of_a_test() {
-    reportReader.putTests(TEST_FILE_REF_1, Arrays.asList(newTest(1)));
-    reportReader.putCoverageDetails(TEST_FILE_REF_1, Arrays.asList(newCoverageDetail(1, MAIN_FILE_REF_1)));
-
-    underTest.execute(new TestComputationStepContext());
-
-    FileSourceDto dto = dbClient.fileSourceDao().selectTestByFileUuid(db.getSession(), TEST_FILE_UUID_1);
-    assertThat(dto.getCreatedAt()).isEqualTo(now);
-    assertThat(dto.getUpdatedAt()).isEqualTo(now);
-    assertThat(dto.getProjectUuid()).isEqualTo(PROJECT_UUID);
-    assertThat(dto.getFileUuid()).isEqualTo(TEST_FILE_UUID_1);
-    assertThat(dto.getTestData()).hasSize(1);
-
-    DbFileSources.Test test1 = dto.getTestData().get(0);
-    assertThat(test1.getUuid()).isNotEmpty();
-    assertThat(test1.getName()).isEqualTo("name#1");
-    assertThat(test1.getMsg()).isEqualTo("message#1");
-    assertThat(test1.getStacktrace()).isEqualTo("stacktrace#1");
-    assertThat(test1.getStatus()).isEqualTo(DbFileSources.Test.TestStatus.FAILURE);
-    assertThat(test1.getExecutionTimeMs()).isEqualTo(1_000);
-    assertThat(test1.getCoveredFileCount()).isEqualTo(1);
-    assertThat(test1.getCoveredFile(0).getCoveredLineList()).containsOnly(1, 2, 3);
-    assertThat(test1.getCoveredFile(0).getFileUuid()).isEqualTo(MAIN_FILE_UUID_1);
-  }
-
-  @Test
-  public void insert_tests_without_coverage_details() {
-    List<ScannerReport.Test> batchTests = Arrays.asList(newTest(1));
-    reportReader.putTests(TEST_FILE_REF_1, batchTests);
-
-    underTest.execute(new TestComputationStepContext());
-
-    FileSourceDto dto = dbClient.fileSourceDao().selectTestByFileUuid(db.getSession(), TEST_FILE_UUID_1);
-    assertThat(dto.getFileUuid()).isEqualTo(TEST_FILE_UUID_1);
-    List<DbFileSources.Test> tests = dto.getTestData();
-    assertThat(tests).hasSize(1);
-    assertThat(tests.get(0).getCoveredFileList()).isEmpty();
-    assertThat(tests.get(0).getMsg()).isEqualTo("message#1");
-  }
-
-  @Test
-  public void insert_coverage_details_not_taken_into_account() {
-    List<ScannerReport.Test> batchTests = Arrays.asList(newTest(1));
-    reportReader.putTests(TEST_FILE_REF_1, batchTests);
-    List<CoverageDetail> coverageDetails = Arrays.asList(newCoverageDetail(1, MAIN_FILE_REF_1), newCoverageDetail(2, MAIN_FILE_REF_2));
-    reportReader.putCoverageDetails(TEST_FILE_REF_1, coverageDetails);
-    reportReader.putCoverageDetails(TEST_FILE_REF_2, coverageDetails);
-
-    underTest.execute(new TestComputationStepContext());
-
-    assertThat(log.logs(LoggerLevel.WARN)).hasSize(1);
-    assertThat(log.logs(LoggerLevel.WARN).get(0)).isEqualTo("Some coverage tests are not taken into account during analysis of project 'PROJECT_KEY'");
-    assertThat(log.logs(LoggerLevel.TRACE)).hasSize(2);
-    assertThat(log.logs(LoggerLevel.TRACE).get(0)).isEqualTo("The following test coverages for file 'TEST_FILE1_KEY' have not been taken into account: name#2");
-    assertThat(log.logs(LoggerLevel.TRACE).get(1)).startsWith("The following test coverages for file 'TEST_FILE2_KEY' have not been taken into account: ");
-    assertThat(log.logs(LoggerLevel.TRACE).get(1)).contains("name#1", "name#2");
-  }
-
-  @Test
-  public void aggregate_coverage_details() {
-    reportReader.putTests(TEST_FILE_REF_1, Arrays.asList(newTest(1)));
-    reportReader.putCoverageDetails(TEST_FILE_REF_1, Arrays.asList(
-      newCoverageDetailWithLines(1, MAIN_FILE_REF_1, 1, 3),
-      newCoverageDetailWithLines(1, MAIN_FILE_REF_1, 2, 4)));
-
-    underTest.execute(new TestComputationStepContext());
-
-    FileSourceDto dto = dbClient.fileSourceDao().selectTestByFileUuid(db.getSession(), TEST_FILE_UUID_1);
-    List<Integer> coveredLines = dto.getTestData().get(0).getCoveredFile(0).getCoveredLineList();
-    assertThat(coveredLines).containsOnly(1, 2, 3, 4);
-  }
-
-  @Test
-  public void update_existing_test() {
-    // ARRANGE
-    dbClient.fileSourceDao().insert(db.getSession(), new FileSourceDto()
-      .setProjectUuid(PROJECT_UUID)
-      .setFileUuid(TEST_FILE_UUID_1)
-      .setTestData(Arrays.asList(DbFileSources.Test.newBuilder()
-        .setUuid("test-uuid-1")
-        .setName("name#1")
-        .setStatus(DbFileSources.Test.TestStatus.ERROR)
-        .setStacktrace("old-stacktrace#1")
-        .setMsg("old-message#1")
-        .setExecutionTimeMs(987_654_321L)
-        .build()))
-      .setCreatedAt(100_000)
-      .setUpdatedAt(100_000));
-    db.getSession().commit();
-    assertThat(dbClient.fileSourceDao().selectTestByFileUuid(db.getSession(), TEST_FILE_UUID_1)).isNotNull();
-
-    ScannerReport.Test newBatchTest = newTest(1);
-    reportReader.putTests(TEST_FILE_REF_1, Arrays.asList(newBatchTest));
-
-    CoverageDetail newCoverageDetail = newCoverageDetail(1, MAIN_FILE_REF_1);
-    reportReader.putCoverageDetails(TEST_FILE_REF_1, Arrays.asList(newCoverageDetail));
-
-    // ACT
-    underTest.execute(new TestComputationStepContext());
-
-    // ASSERT
-    FileSourceDto dto = dbClient.fileSourceDao().selectTestByFileUuid(db.getSession(), TEST_FILE_UUID_1);
-    assertThat(dto.getCreatedAt()).isEqualTo(100_000);
-    assertThat(dto.getUpdatedAt()).isEqualTo(now);
-    assertThat(dto.getTestData()).hasSize(1);
-
-    DbFileSources.Test test = dto.getTestData().get(0);
-    assertThat(test.getUuid()).isNotEqualTo("test-uuid-1");
-    assertThat(test.getName()).isEqualTo("name#1");
-    assertThat(test.getStatus()).isEqualTo(DbFileSources.Test.TestStatus.valueOf(newBatchTest.getStatus().name()));
-    assertThat(test.getMsg()).isEqualTo(newBatchTest.getMsg());
-    assertThat(test.getStacktrace()).isEqualTo(newBatchTest.getStacktrace());
-    assertThat(test.getExecutionTimeMs()).isEqualTo(newBatchTest.getDurationInMs());
-    assertThat(test.getCoveredFileCount()).isEqualTo(1);
-    assertThat(test.getCoveredFile(0).getCoveredLineList()).containsOnly(1, 2, 3);
-    assertThat(test.getCoveredFile(0).getFileUuid()).isEqualTo(MAIN_FILE_UUID_1);
-  }
-
-  private ScannerReport.Test newTest(int id) {
-    return ScannerReport.Test.newBuilder()
-      .setStatus(TestStatus.FAILURE)
-      .setName("name#" + id)
-      .setStacktrace("stacktrace#" + id)
-      .setMsg("message#" + id)
-      .setDurationInMs(1_000)
-      .build();
-  }
-
-  private ScannerReport.CoverageDetail newCoverageDetail(int id, int covered_file_ref) {
-    return newCoverageDetailWithLines(id, covered_file_ref, 1, 2, 3);
-  }
-
-  private ScannerReport.CoverageDetail newCoverageDetailWithLines(int id, int covered_file_ref, Integer... lines) {
-    return CoverageDetail.newBuilder()
-      .setTestName("name#" + id)
-      .addCoveredFile(CoverageDetail.CoveredFile.newBuilder()
-        .addAllCoveredLine(Arrays.asList(lines))
-        .setFileRef(covered_file_ref)
-        .build())
-      .build();
-  }
-}
index c93b3031db7fce2853b241b061ac5ce716a754da..96757cc6f29524029a1e9fe10d22b4dbd3149c65 100644 (file)
@@ -149,7 +149,6 @@ import org.sonar.server.rule.index.RuleIndexer;
 import org.sonar.server.setting.DatabaseSettingLoader;
 import org.sonar.server.setting.DatabaseSettingsEnabler;
 import org.sonar.server.setting.ThreadLocalSettings;
-import org.sonar.server.test.index.TestIndexer;
 import org.sonar.server.user.index.UserIndex;
 import org.sonar.server.user.index.UserIndexer;
 import org.sonar.server.util.OkHttpClientProvider;
@@ -425,9 +424,6 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer {
       EmailNotificationChannel.class,
       ReportAnalysisFailureNotificationModule.class,
 
-      // Tests
-      TestIndexer.class,
-
       // System
       ServerLogging.class,
 
index 2f63230ad85b3801db9acecc38d00c49066c2e96..f50a10319f54db6da0a336491cc908ac55717373 100644 (file)
@@ -97,7 +97,7 @@ public class ComputeEngineContainerImplTest {
       assertThat(picoContainer.getComponentAdapters())
         .hasSize(
           CONTAINER_ITSELF
-            + 70 // level 4
+            + 69 // level 4
             + 6 // content of CeConfigurationModule
             + 4 // content of CeQueueModule
             + 3 // content of CeHttpModule
index b60539e9c9d32b238ebbe90c6b76ad4f6c7b1ce6..3a1567ccb3cd935992c7725ae9825da02f6cfccf 100644 (file)
@@ -35,7 +35,6 @@ import org.apache.commons.io.IOUtils;
 import org.apache.ibatis.session.ResultHandler;
 import org.sonar.db.Dao;
 import org.sonar.db.DbSession;
-import org.sonar.db.source.FileSourceDto.Type;
 
 import static org.sonar.db.DatabaseUtils.toUniqueAndSortedPartitions;
 
@@ -44,18 +43,13 @@ public class FileSourceDao implements Dao {
   private static final Splitter END_OF_LINE_SPLITTER = Splitter.on('\n');
 
   @CheckForNull
-  public FileSourceDto selectSourceByFileUuid(DbSession session, String fileUuid) {
-    return mapper(session).select(fileUuid, Type.SOURCE);
-  }
-
-  @CheckForNull
-  public FileSourceDto selectTestByFileUuid(DbSession dbSession, String fileUuid) {
-    return mapper(dbSession).select(fileUuid, Type.TEST);
+  public FileSourceDto selectByFileUuid(DbSession session, String fileUuid) {
+    return mapper(session).selectByFileUuid(fileUuid);
   }
 
   @CheckForNull
   public LineHashVersion selectLineHashesVersion(DbSession dbSession, String fileUuid) {
-    Integer version = mapper(dbSession).selectLineHashesVersion(fileUuid, Type.SOURCE);
+    Integer version = mapper(dbSession).selectLineHashesVersion(fileUuid);
     return version == null ? LineHashVersion.WITHOUT_SIGNIFICANT_CODE : LineHashVersion.valueOf(version);
   }
 
@@ -65,9 +59,8 @@ public class FileSourceDao implements Dao {
     PreparedStatement pstmt = null;
     ResultSet rs = null;
     try {
-      pstmt = connection.prepareStatement("SELECT line_hashes FROM file_sources WHERE file_uuid=? AND data_type=?");
+      pstmt = connection.prepareStatement("SELECT line_hashes FROM file_sources WHERE file_uuid=? AND data_type='SOURCE'");
       pstmt.setString(1, fileUuid);
-      pstmt.setString(2, Type.SOURCE);
       rs = pstmt.executeQuery();
       if (rs.next()) {
         String string = rs.getString(1);
@@ -100,9 +93,8 @@ public class FileSourceDao implements Dao {
     ResultSet rs = null;
     Reader reader = null;
     try {
-      pstmt = connection.prepareStatement("SELECT line_hashes FROM file_sources WHERE file_uuid=? AND data_type=?");
+      pstmt = connection.prepareStatement("SELECT line_hashes FROM file_sources WHERE file_uuid=? AND data_type='SOURCE'");
       pstmt.setString(1, fileUuid);
-      pstmt.setString(2, Type.SOURCE);
       rs = pstmt.executeQuery();
       if (rs.next()) {
         reader = rs.getCharacterStream(1);
index f22e4d31925fd0510f5db4cdbe8fa34b0fbecf69..44469d67d73c13d84f5c95c51eeef7c181e6ac66 100644 (file)
@@ -26,8 +26,6 @@ import com.google.protobuf.InvalidProtocolBufferException;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import javax.annotation.CheckForNull;
@@ -68,7 +66,6 @@ public class FileSourceDto {
   private int lineCount = LINE_COUNT_NOT_POPULATED;
   private String srcHash;
   private byte[] binaryData = new byte[0];
-  private String dataType;
   private String dataHash;
   private String revision;
   @Nullable
@@ -170,56 +167,6 @@ public class FileSourceDto {
     }
   }
 
-  public static List<DbFileSources.Test> decodeTestData(byte[] binaryData) {
-    // stream is always closed
-    return decodeTestData(new ByteArrayInputStream(binaryData));
-  }
-
-  /**
-   * Decompress and deserialize content of column FILE_SOURCES.BINARY_DATA.
-   * The parameter "input" is always closed by this method.
-   */
-  public static List<DbFileSources.Test> decodeTestData(InputStream binaryInput) {
-    LZ4BlockInputStream lz4Input = null;
-    List<DbFileSources.Test> tests = new ArrayList<>();
-    try {
-      lz4Input = new LZ4BlockInputStream(binaryInput);
-
-      DbFileSources.Test currentTest;
-      do {
-        currentTest = DbFileSources.Test.parseDelimitedFrom(lz4Input);
-        if (currentTest != null) {
-          tests.add(currentTest);
-        }
-      } while (currentTest != null);
-      return tests;
-    } catch (IOException e) {
-      throw new IllegalStateException("Fail to decompress and deserialize source data", e);
-    } finally {
-      IOUtils.closeQuietly(lz4Input);
-    }
-  }
-
-  /**
-   * Serialize and compress protobuf message {@link org.sonar.db.protobuf.DbFileSources.Data}
-   * in the column BINARY_DATA.
-   */
-  public static byte[] encodeTestData(List<DbFileSources.Test> tests) {
-    ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
-    LZ4BlockOutputStream compressedOutput = new LZ4BlockOutputStream(byteOutput);
-    try {
-      for (DbFileSources.Test test : tests) {
-        test.writeDelimitedTo(compressedOutput);
-      }
-      compressedOutput.close();
-      return byteOutput.toByteArray();
-    } catch (IOException e) {
-      throw new IllegalStateException("Fail to serialize and compress source tests", e);
-    } finally {
-      IOUtils.closeQuietly(compressedOutput);
-    }
-  }
-
   /**
    * Compressed value of serialized protobuf message {@link org.sonar.db.protobuf.DbFileSources.Data}
    */
@@ -243,24 +190,10 @@ public class FileSourceDto {
   }
 
   public FileSourceDto setSourceData(DbFileSources.Data data) {
-    this.dataType = Type.SOURCE;
     this.binaryData = encodeSourceData(data);
     return this;
   }
 
-  /**
-   * Compressed value of serialized protobuf message {@link org.sonar.db.protobuf.DbFileSources.Data}
-   */
-  public List<DbFileSources.Test> getTestData() {
-    return decodeTestData(binaryData);
-  }
-
-  public FileSourceDto setTestData(List<DbFileSources.Test> data) {
-    this.dataType = Type.TEST;
-    this.binaryData = encodeTestData(data);
-    return this;
-  }
-
   /** Used by MyBatis */
   public String getRawLineHashes() {
     return lineHashes;
@@ -332,15 +265,6 @@ public class FileSourceDto {
     return this;
   }
 
-  public String getDataType() {
-    return dataType;
-  }
-
-  public FileSourceDto setDataType(String dataType) {
-    this.dataType = dataType;
-    return this;
-  }
-
   public String getRevision() {
     return revision;
   }
@@ -350,12 +274,4 @@ public class FileSourceDto {
     return this;
   }
 
-  public static class Type {
-    public static final String SOURCE = "SOURCE";
-    public static final String TEST = "TEST";
-
-    private Type() {
-      // utility class
-    }
-  }
 }
index 1f3f5a3b22b6cae212fcadc9f451cfdeb3dbdeec..0da4f1980d998d48b79ef45d370d6bbbc4a97021 100644 (file)
@@ -30,12 +30,12 @@ public interface FileSourceMapper {
   List<FileSourceDto> selectHashesForProject(@Param("projectUuid") String projectUuid, @Param("dataType") String dataType);
 
   @CheckForNull
-  FileSourceDto select(@Param("fileUuid") String fileUuid, @Param("dataType") String dataType);
+  FileSourceDto selectByFileUuid(@Param("fileUuid") String fileUuid);
 
   void scrollLineHashes(@Param("fileUuids") Collection<String> fileUuids, ResultHandler<LineHashesWithUuidDto> rowHandler);
 
   @CheckForNull
-  Integer selectLineHashesVersion(@Param("fileUuid") String fileUuid, @Param("dataType") String dataType);
+  Integer selectLineHashesVersion(@Param("fileUuid") String fileUuid);
 
   void insert(FileSourceDto dto);
 
index 1f518f219760c87be3bda8c410b08b4d68798348..b45f1f1f6699ed619542c8c3d69229c1b3d5c1c8 100644 (file)
@@ -4,7 +4,7 @@
 
 <mapper namespace="org.sonar.db.source.FileSourceMapper">
 
-  <select id="select" parameterType="map" resultType="org.sonar.db.source.FileSourceDto">
+  <select id="selectByFileUuid" parameterType="map" resultType="org.sonar.db.source.FileSourceDto">
     select
       id,
       project_uuid as projectUuid,
       line_count as lineCount,
       data_hash as dataHash,
       src_hash as srcHash,
-      data_type as
-      dataType,
       revision
     from
       file_sources
     where
       file_uuid = #{fileUuid,jdbcType=VARCHAR}
-      and data_type = #{dataType,jdbcType=VARCHAR}
+      and data_type = 'SOURCE'
   </select>
 
   <select id="selectHashesForProject" parameterType="map" resultType="org.sonar.db.source.FileSourceDto">
       src_hash as srcHash,
       revision,
       updated_at as updatedAt
-    from
+      from
       file_sources
     where
       project_uuid = #{projectUuid,jdbcType=VARCHAR}
-      and data_type = #{dataType,jdbcType=VARCHAR}
+      and data_type = 'SOURCE'
   </select>
 
   <select id="scrollLineHashes" parameterType="map" resultType="org.sonar.db.source.LineHashesWithUuidDto" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY">
@@ -66,7 +64,7 @@
       file_sources
     WHERE
       file_uuid = #{fileUuid,jdbcType=VARCHAR}
-      and data_type=#{dataType,jdbcType=VARCHAR}
+      and data_type = 'SOURCE'
   </select>
 
   <insert id="insert" parameterType="org.sonar.db.source.FileSourceDto" useGeneratedKeys="false">
@@ -97,7 +95,7 @@
       #{lineCount,jdbcType=INTEGER},
       #{dataHash,jdbcType=VARCHAR},
       #{srcHash,jdbcType=VARCHAR},
-      #{dataType,jdbcType=VARCHAR},
+      'SOURCE',
       #{revision,jdbcType=VARCHAR}
     )
   </insert>
index d9fc779595476720900adc53bcd9332dd042322d..65cab2dfd1c03d6ac699c300900b92f12c7f695b 100644 (file)
@@ -123,26 +123,6 @@ public class ScrollForFileMoveComponentDaoTest {
     verifyFileMoveRowDto(resultHandler, file3);
   }
 
-  @Test
-  public void scrollAllFilesForFileMove_ignores_file_source_of_type_TEST() {
-    OrganizationDto organization = db.organizations().insert();
-    ComponentDto project = random.nextBoolean() ? db.components().insertPrivateProject(organization) : db.components().insertPublicProject(organization);
-    ComponentDto module1 = db.components().insertComponent(ComponentTesting.newModuleDto(project));
-    ComponentDto module2 = db.components().insertComponent(ComponentTesting.newModuleDto(module1));
-    ComponentAndSource file1 = insertFileAndSource(project, FILE);
-    ComponentDto file2 = db.components().insertComponent(ComponentTesting.newFileDto(module1).setQualifier(UNIT_TEST_FILE));
-    db.fileSources().insertFileSource(file2, t -> t.setDataType(UNIT_TEST_FILE));
-    ComponentAndSource file3 = insertFileAndSource(module2, FILE);
-    db.fileSources().insertFileSource(file3.component, t -> t.setDataType(UNIT_TEST_FILE));
-    RecordingResultHandler resultHandler = new RecordingResultHandler();
-
-    underTest.scrollAllFilesForFileMove(dbSession, project.uuid(), resultHandler);
-
-    assertThat(resultHandler.dtos).hasSize(2);
-    verifyFileMoveRowDto(resultHandler, file1);
-    verifyFileMoveRowDto(resultHandler, file3);
-  }
-
   @Test
   public void scrollAllFilesForFileMove_scrolls_large_number_of_files_and_uts() {
     OrganizationDto organization = db.organizations().insert();
@@ -268,5 +248,4 @@ public class ScrollForFileMoveComponentDaoTest {
     assertThat(dto.getLineCount()).isEqualTo(componentAndSource.source.getLineCount());
   }
 
-
 }
index 56b540d2a0b4b0d4eb2fd9faef97014eab0b6a77..b50ecc58b1f7b7dfc90dc944ff886119ec0e65a2 100644 (file)
@@ -214,9 +214,8 @@ public class PurgeDaoTest {
     assertThat(db.countSql("select count(*) from issues where resolution = 'REMOVED'")).isEqualTo(0);
 
     db.fileSources().insertFileSource(srcFile);
-    db.fileSources().insertFileSource(testFile, f -> f.setDataType("TEST"));
     FileSourceDto nonSelectedFileSource = db.fileSources().insertFileSource(nonSelectedFile);
-    assertThat(db.countRowsOfTable("file_sources")).isEqualTo(3);
+    assertThat(db.countRowsOfTable("file_sources")).isEqualTo(2);
 
     MetricDto metric1 = db.measures().insertMetric();
     MetricDto metric2 = db.measures().insertMetric();
@@ -254,11 +253,12 @@ public class PurgeDaoTest {
 
     // delete file sources of selected
     assertThat(db.countRowsOfTable("file_sources")).isEqualTo(1);
-    assertThat(db.getDbClient().fileSourceDao().selectSourceByFileUuid(dbSession, nonSelectedFileSource.getFileUuid())).isNotNull();
+    assertThat(db.getDbClient().fileSourceDao().selectByFileUuid(dbSession, nonSelectedFileSource.getFileUuid())).isNotNull();
 
     // deletes live measure of selected
     assertThat(db.countRowsOfTable("live_measures")).isEqualTo(4);
-    List<LiveMeasureDto> liveMeasureDtos = db.getDbClient().liveMeasureDao().selectByComponentUuidsAndMetricIds(dbSession, ImmutableSet.of(srcFile.uuid(), dir.uuid(), project.uuid(), nonSelectedFile.uuid()), ImmutableSet.of(metric1.getId(), metric2.getId()));
+    List<LiveMeasureDto> liveMeasureDtos = db.getDbClient().liveMeasureDao().selectByComponentUuidsAndMetricIds(dbSession,
+      ImmutableSet.of(srcFile.uuid(), dir.uuid(), project.uuid(), nonSelectedFile.uuid()), ImmutableSet.of(metric1.getId(), metric2.getId()));
     assertThat(liveMeasureDtos)
       .extracting(LiveMeasureDto::getComponentUuid)
       .containsOnly(nonSelectedFile.uuid(), project.uuid());
@@ -275,7 +275,6 @@ public class PurgeDaoTest {
     db.assertDbUnit(getClass(), "shouldDeleteAnalyses-result.xml", "snapshots");
   }
 
-
   @Test
   public void deleteAnalyses_deletes_rows_in_events_and_event_component_changes() {
     ComponentDto project = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
index 5f0d5bc8df68c28c425f0f460594488e1cb066aa..0524b9e7234787222ce2d67fcf948c71efb3e16c 100644 (file)
@@ -41,7 +41,6 @@ import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.source.FileSourceDto.Type;
 
 import static com.google.common.collect.ImmutableList.of;
 import static java.util.Collections.emptyList;
@@ -64,7 +63,7 @@ public class FileSourceDaoTest {
   public void select() {
     dbTester.prepareDbUnit(getClass(), "shared.xml");
 
-    FileSourceDto fileSourceDto = underTest.selectSourceByFileUuid(dbSession, "FILE1_UUID");
+    FileSourceDto fileSourceDto = underTest.selectByFileUuid(dbSession, "FILE1_UUID");
 
     assertThat(fileSourceDto.getBinaryData()).isNotEmpty();
     assertThat(fileSourceDto.getDataHash()).isEqualTo("hash");
@@ -72,7 +71,6 @@ public class FileSourceDaoTest {
     assertThat(fileSourceDto.getFileUuid()).isEqualTo("FILE1_UUID");
     assertThat(fileSourceDto.getCreatedAt()).isEqualTo(1500000000000L);
     assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(1500000000000L);
-    assertThat(fileSourceDto.getDataType()).isEqualTo(Type.SOURCE);
     assertThat(fileSourceDto.getRevision()).isEqualTo("123456789");
     assertThat(fileSourceDto.getLineHashesVersion()).isEqualTo(0);
 
@@ -117,7 +115,6 @@ public class FileSourceDaoTest {
       .setDataHash("FILE2_DATA_HASH")
       .setLineHashes(of("LINE1_HASH", "LINE2_HASH"))
       .setSrcHash("FILE2_HASH")
-      .setDataType(Type.SOURCE)
       .setCreatedAt(1500000000000L)
       .setUpdatedAt(1500000000001L)
       .setLineHashesVersion(1)
@@ -125,7 +122,7 @@ public class FileSourceDaoTest {
     underTest.insert(dbSession, expected);
     dbSession.commit();
 
-    FileSourceDto fileSourceDto = underTest.selectSourceByFileUuid(dbSession, expected.getFileUuid());
+    FileSourceDto fileSourceDto = underTest.selectByFileUuid(dbSession, expected.getFileUuid());
 
     assertThat(fileSourceDto.getProjectUuid()).isEqualTo(expected.getProjectUuid());
     assertThat(fileSourceDto.getFileUuid()).isEqualTo(expected.getFileUuid());
@@ -156,30 +153,12 @@ public class FileSourceDaoTest {
     FileSourceDto fileSourceDto = new FileSourceDto()
       .setProjectUuid("Foo")
       .setFileUuid("Bar")
-      .setDataType(Type.SOURCE)
       .setCreatedAt(1500000000000L)
       .setUpdatedAt(1500000000001L);
     underTest.insert(dbSession, fileSourceDto);
     dbSession.commit();
 
-    FileSourceDto res = underTest.selectSourceByFileUuid(dbSession, fileSourceDto.getFileUuid());
-
-    assertThat(res.getLineCount()).isEqualTo(0);
-    assertThat(res.getLineHashes()).isEmpty();
-  }
-
-  @Test
-  public void selectTest_reads_test_without_line_hashes() {
-    FileSourceDto fileSourceDto = new FileSourceDto()
-      .setProjectUuid("Foo")
-      .setFileUuid("Bar")
-      .setDataType(Type.TEST)
-      .setCreatedAt(1500000000000L)
-      .setUpdatedAt(1500000000001L);
-    underTest.insert(dbSession, fileSourceDto);
-    dbSession.commit();
-
-    FileSourceDto res = underTest.selectTestByFileUuid(dbSession, fileSourceDto.getFileUuid());
+    FileSourceDto res = underTest.selectByFileUuid(dbSession, fileSourceDto.getFileUuid());
 
     assertThat(res.getLineCount()).isEqualTo(0);
     assertThat(res.getLineHashes()).isEmpty();
@@ -195,7 +174,6 @@ public class FileSourceDaoTest {
       .setBinaryData("FILE2_BINARY_DATA".getBytes())
       .setDataHash("FILE2_DATA_HASH")
       .setSrcHash("FILE2_HASH")
-      .setDataType(Type.SOURCE)
       .setCreatedAt(1500000000000L)
       .setUpdatedAt(1500000000001L)
       .setRevision("123456789"));
@@ -213,7 +191,6 @@ public class FileSourceDaoTest {
       .setDataHash("FILE2_DATA_HASH")
       .setLineHashes(singletonList("hashes"))
       .setSrcHash("FILE2_HASH")
-      .setDataType(Type.SOURCE)
       .setCreatedAt(1500000000000L)
       .setUpdatedAt(1500000000001L)
       .setRevision("123456789"));
@@ -231,7 +208,6 @@ public class FileSourceDaoTest {
       .setDataHash("FILE2_DATA_HASH")
       .setLineHashes(singletonList("hashes"))
       .setSrcHash("FILE2_HASH")
-      .setDataType(Type.SOURCE)
       .setCreatedAt(1500000000000L)
       .setUpdatedAt(1500000000001L)
       .setLineHashesVersion(1)
@@ -251,7 +227,6 @@ public class FileSourceDaoTest {
       .setBinaryData("FILE2_BINARY_DATA".getBytes())
       .setDataHash("FILE2_DATA_HASH")
       .setSrcHash("FILE2_HASH")
-      .setDataType(Type.SOURCE)
       .setCreatedAt(1500000000000L)
       .setUpdatedAt(1500000000001L)
       .setRevision("123456789"));
@@ -313,24 +288,6 @@ public class FileSourceDaoTest {
     verifyLinesHashes(handler, file1, fileSource1);
   }
 
-  @Test
-  public void scrollLineHashes_does_not_scroll_hashes_of_component_with_TEST_source() {
-    OrganizationDto organization = dbTester.organizations().insert();
-    ComponentDto project = new Random().nextBoolean() ? dbTester.components().insertPrivateProject(organization) : dbTester.components().insertPublicProject(organization);
-    ComponentDto file1 = dbTester.components().insertComponent(newFileDto(project));
-    FileSourceDto fileSource1 = dbTester.fileSources().insertFileSource(file1);
-    ComponentDto file2 = dbTester.components().insertComponent(newFileDto(project));
-    FileSourceDto fileSource2 = dbTester.fileSources().insertFileSource(file2, t -> t.setDataType(Type.TEST));
-    ComponentDto file3 = dbTester.components().insertComponent(newFileDto(project));
-    FileSourceDto fileSource3 = dbTester.fileSources().insertFileSource(file3, t -> t.setDataType(Type.SOURCE));
-    FileSourceDto testFileSource3 = dbTester.fileSources().insertFileSource(file3, t -> t.setDataType(Type.TEST));
-
-    LineHashesWithKeyDtoHandler handler = scrollLineHashes(file2.uuid(), file1.uuid(), file3.uuid());
-    assertThat(handler.dtos).hasSize(2);
-    verifyLinesHashes(handler, file1, fileSource1);
-    verifyLinesHashes(handler, file3, fileSource3);
-  }
-
   @Test
   public void scrollLineHashes_handles_scrolling_more_than_1000_files() {
     OrganizationDto organization = dbTester.organizations().insert();
@@ -390,14 +347,13 @@ public class FileSourceDaoTest {
       .setDataHash("NEW_DATA_HASH")
       .setSrcHash("NEW_FILE_HASH")
       .setLineHashes(singletonList("NEW_LINE_HASHES"))
-      .setDataType(Type.SOURCE)
       .setUpdatedAt(1500000000002L)
       .setLineHashesVersion(1)
       .setRevision("987654321"));
     dbSession.commit();
 
     dbTester.assertDbUnitTable(getClass(), "update-result.xml", "file_sources", "project_uuid", "file_uuid",
-      "data_hash", "line_hashes", "src_hash", "created_at", "updated_at", "data_type", "revision", "line_hashes_version");
+      "data_hash", "line_hashes", "src_hash", "created_at", "updated_at", "revision", "line_hashes_version");
   }
 
   @Test
@@ -406,14 +362,13 @@ public class FileSourceDaoTest {
     FileSourceDto fileSourceDto = new FileSourceDto()
       .setProjectUuid("Foo")
       .setFileUuid("Bar")
-      .setDataType(Type.SOURCE)
       .setLineHashes(lineHashes)
       .setCreatedAt(1500000000000L)
       .setUpdatedAt(1500000000001L);
     underTest.insert(dbSession, fileSourceDto);
     dbSession.commit();
 
-    FileSourceDto resBefore = underTest.selectSourceByFileUuid(dbSession, fileSourceDto.getFileUuid());
+    FileSourceDto resBefore = underTest.selectByFileUuid(dbSession, fileSourceDto.getFileUuid());
     assertThat(resBefore.getLineCount()).isEqualTo(lineHashes.size());
     assertThat(resBefore.getLineHashes()).isEqualTo(lineHashes);
 
@@ -422,7 +377,7 @@ public class FileSourceDaoTest {
     underTest.update(dbSession, fileSourceDto);
     dbSession.commit();
 
-    FileSourceDto res = underTest.selectSourceByFileUuid(dbSession, fileSourceDto.getFileUuid());
+    FileSourceDto res = underTest.selectByFileUuid(dbSession, fileSourceDto.getFileUuid());
     assertThat(res.getLineHashes()).isEmpty();
     assertThat(res.getLineCount()).isEqualTo(1);
   }
index f8ede3cda8356c8253f5dbbe29ccc76cb790f1dc..c426e4723dfd20f6bd95486141db37941f068b9a 100644 (file)
@@ -20,7 +20,6 @@
 package org.sonar.db.source;
 
 import com.google.common.base.Joiner;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Random;
@@ -43,22 +42,6 @@ public class FileSourceDtoTest {
   @Rule
   public ExpectedException expectedException = ExpectedException.none();
 
-  @Test
-  public void encode_and_decode_test_data() {
-    List<DbFileSources.Test> tests = Arrays.asList(
-      DbFileSources.Test.newBuilder()
-        .setName("name#1")
-        .build(),
-      DbFileSources.Test.newBuilder()
-        .setName("name#2")
-        .build());
-
-    FileSourceDto underTest = new FileSourceDto().setTestData(tests);
-
-    assertThat(underTest.getTestData()).hasSize(2);
-    assertThat(underTest.getTestData().get(0).getName()).isEqualTo("name#1");
-  }
-
   @Test
   public void getSourceData_throws_ISE_with_id_fileUuid_and_projectUuid_in_message_when_data_cant_be_read() {
     long id = 12L;
@@ -98,7 +81,7 @@ public class FileSourceDtoTest {
   }
 
   @Test
-  public void new_FileSourceDto_as_lineCount_0_and_rawLineHashes_to_null()  {
+  public void new_FileSourceDto_as_lineCount_0_and_rawLineHashes_to_null() {
     FileSourceDto underTest = new FileSourceDto();
 
     assertThat(underTest.getLineCount()).isZero();
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/source/index/FileSourcesUpdaterHelper.java b/server/sonar-server-common/src/main/java/org/sonar/server/source/index/FileSourcesUpdaterHelper.java
deleted file mode 100644 (file)
index 19d004b..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.source.index;
-
-import com.google.common.base.Joiner;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.List;
-import javax.annotation.Nullable;
-import org.elasticsearch.action.update.UpdateRequest;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-
-public class FileSourcesUpdaterHelper {
-
-  private static final String SQL_ALL = "SELECT %s FROM file_sources WHERE data_type='%s' ";
-  private static final String PROJECT_FILTER = " AND project_uuid=?";
-
-  private static final String[] FIELDS = {
-    "project_uuid",
-    "file_uuid",
-    "updated_at",
-    "binary_data"
-  };
-  private static final String FIELDS_ONE_LINE = Joiner.on(",").join(FIELDS);
-
-  private FileSourcesUpdaterHelper() {
-    // only static stuff
-  }
-
-  public static PreparedStatement preparedStatementToSelectFileSources(DbClient dbClient, DbSession session, String dataType, @Nullable String projectUuid)
-    throws SQLException {
-    String sql = createSQL(dataType, projectUuid);
-    // rows are big, so they are scrolled once at a time (one row in memory at a time)
-    PreparedStatement stmt = dbClient.getMyBatis().newScrollingSingleRowSelectStatement(session, sql);
-    if (projectUuid != null) {
-      stmt.setString(1, projectUuid);
-    }
-    return stmt;
-  }
-
-  private static String createSQL(String dataType, @Nullable String projectUuid) {
-    StringBuilder sql = new StringBuilder(String.format(SQL_ALL, FIELDS_ONE_LINE, dataType));
-    if (projectUuid != null) {
-      sql.append(PROJECT_FILTER);
-    }
-    return sql.toString();
-  }
-
-  public static class Row {
-    private final String fileUuid;
-    private final String projectUuid;
-    private final long updatedAt;
-    private final List<UpdateRequest> updateRequests = new ArrayList<>();
-
-    public Row(String projectUuid, String fileUuid, long updatedAt) {
-      this.projectUuid = projectUuid;
-      this.fileUuid = fileUuid;
-      this.updatedAt = updatedAt;
-    }
-
-    public String getProjectUuid() {
-      return projectUuid;
-    }
-
-    public String getFileUuid() {
-      return fileUuid;
-    }
-
-    public long getUpdatedAt() {
-      return updatedAt;
-    }
-
-    public List<UpdateRequest> getUpdateRequests() {
-      return updateRequests;
-    }
-  }
-}
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/test/index/CoveredFileDoc.java b/server/sonar-server-common/src/main/java/org/sonar/server/test/index/CoveredFileDoc.java
deleted file mode 100644 (file)
index d07d2d0..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.test.index;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Maps;
-import java.util.List;
-import java.util.Map;
-import org.sonar.server.es.BaseDoc;
-
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILE_LINES;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILE_UUID;
-
-public class CoveredFileDoc extends BaseDoc {
-  public CoveredFileDoc(Map<String, Object> fields) {
-    super(fields);
-  }
-
-  @VisibleForTesting
-  public CoveredFileDoc() {
-    super(Maps.newHashMapWithExpectedSize(2));
-  }
-
-  @Override
-  public String getId() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public String getRouting() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public String getParent() {
-    throw new UnsupportedOperationException();
-  }
-
-  public String fileUuid() {
-    return getField(FIELD_COVERED_FILE_UUID);
-  }
-
-  public CoveredFileDoc setFileUuid(String fileUuid) {
-    setField(FIELD_COVERED_FILE_UUID, fileUuid);
-    return this;
-  }
-
-  public List<Integer> coveredLines() {
-    return getField(FIELD_COVERED_FILE_LINES);
-  }
-
-  public CoveredFileDoc setCoveredLines(List<Integer> coveredLines) {
-    setField(FIELD_COVERED_FILE_LINES, coveredLines);
-    return this;
-  }
-
-}
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/test/index/TestDoc.java b/server/sonar-server-common/src/main/java/org/sonar/server/test/index/TestDoc.java
deleted file mode 100644 (file)
index 33039ff..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.test.index;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Maps;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import javax.annotation.CheckForNull;
-import org.sonar.server.es.BaseDoc;
-
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILES;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_DURATION_IN_MS;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_FILE_UUID;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_MESSAGE;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_NAME;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_PROJECT_UUID;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_STACKTRACE;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_STATUS;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_TEST_UUID;
-
-public class TestDoc extends BaseDoc {
-
-  public TestDoc(Map<String, Object> fields) {
-    super(fields);
-  }
-
-  @VisibleForTesting
-  public TestDoc() {
-    super(Maps.newHashMapWithExpectedSize(10));
-  }
-
-  @Override
-  public String getId() {
-    return testUuid();
-  }
-
-  @Override
-  public String getRouting() {
-    return projectUuid();
-  }
-
-  @Override
-  public String getParent() {
-    return null;
-  }
-
-  public String projectUuid() {
-    return getField(FIELD_PROJECT_UUID);
-  }
-
-  public TestDoc setProjectUuid(String projectUuid) {
-    setField(FIELD_PROJECT_UUID, projectUuid);
-    return this;
-  }
-
-  public String fileUuid() {
-    return getField(FIELD_FILE_UUID);
-  }
-
-  public TestDoc setFileUuid(String fileUuid) {
-    setField(FIELD_FILE_UUID, fileUuid);
-    return this;
-  }
-
-  public String testUuid() {
-    return getField(FIELD_TEST_UUID);
-  }
-
-  public TestDoc setUuid(String testUuid) {
-    setField(FIELD_TEST_UUID, testUuid);
-    return this;
-  }
-
-  public String name() {
-    return getField(FIELD_NAME);
-  }
-
-  public TestDoc setName(String name) {
-    setField(FIELD_NAME, name);
-    return this;
-  }
-
-  public String status() {
-    return getField(FIELD_STATUS);
-  }
-
-  public TestDoc setStatus(String status) {
-    setField(FIELD_STATUS, status);
-    return this;
-  }
-
-  @CheckForNull
-  public String message() {
-    return getNullableField(FIELD_MESSAGE);
-  }
-
-  public TestDoc setMessage(String message) {
-    setField(FIELD_MESSAGE, message);
-    return this;
-  }
-
-  @CheckForNull
-  public String stackTrace() {
-    return getNullableField(FIELD_STACKTRACE);
-  }
-
-  public TestDoc setStackTrace(String stackTrace) {
-    setField(FIELD_STACKTRACE, stackTrace);
-    return this;
-  }
-
-  @CheckForNull
-  public Long durationInMs() {
-    Number number =  getNullableField(FIELD_DURATION_IN_MS);
-    return number == null ? null : number.longValue();
-  }
-
-  public TestDoc setDurationInMs(Long durationInMs) {
-    setField(FIELD_DURATION_IN_MS, durationInMs);
-    return this;
-  }
-
-  public List<CoveredFileDoc> coveredFiles() {
-    List<Map<String, Object>> coveredFilesAsMaps = getNullableField(FIELD_COVERED_FILES);
-    if (coveredFilesAsMaps == null) {
-      return new ArrayList<>();
-    }
-    List<CoveredFileDoc> coveredFiles = new ArrayList<>();
-    for (Map<String, Object> coveredFileMap : coveredFilesAsMaps) {
-      coveredFiles.add(new CoveredFileDoc(coveredFileMap));
-    }
-    return coveredFiles;
-  }
-
-  public TestDoc setCoveredFiles(List<CoveredFileDoc> coveredFiles) {
-    List<Map<String, Object>> coveredFilesAsMaps = new ArrayList<>();
-    for (CoveredFileDoc coveredFile : coveredFiles) {
-      coveredFilesAsMaps.add(coveredFile.getFields());
-    }
-    setField(FIELD_COVERED_FILES, coveredFilesAsMaps);
-    return this;
-  }
-}
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/test/index/TestIndex.java b/server/sonar-server-common/src/main/java/org/sonar/server/test/index/TestIndex.java
deleted file mode 100644 (file)
index c5cd85d..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.test.index;
-
-import com.google.common.base.Optional;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.lucene.search.join.ScoreMode;
-import org.elasticsearch.action.search.SearchRequestBuilder;
-import org.elasticsearch.search.SearchHit;
-import org.sonar.api.utils.System2;
-import org.sonar.server.es.EsClient;
-import org.sonar.server.es.SearchOptions;
-import org.sonar.server.es.SearchResult;
-
-import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
-import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
-import static org.elasticsearch.index.query.QueryBuilders.nestedQuery;
-import static org.elasticsearch.index.query.QueryBuilders.termQuery;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILES;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILE_LINES;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILE_UUID;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_FILE_UUID;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_TEST_UUID;
-
-public class TestIndex {
-  private final EsClient client;
-  private final System2 system2;
-
-  public TestIndex(EsClient client, System2 system2) {
-    this.client = client;
-    this.system2 = system2;
-  }
-
-  public List<CoveredFileDoc> coveredFiles(String testUuid) {
-    List<CoveredFileDoc> coveredFiles = new ArrayList<>();
-
-    for (SearchHit hit : client.prepareSearch(TestIndexDefinition.INDEX_TYPE_TEST)
-      .setSize(1)
-      .setQuery(boolQuery().must(matchAllQuery()).filter(termQuery(FIELD_TEST_UUID, testUuid)))
-      .get().getHits().getHits()) {
-      coveredFiles.addAll(new TestDoc(hit.getSourceAsMap()).coveredFiles());
-    }
-
-    return coveredFiles;
-  }
-
-  public SearchResult<TestDoc> searchByTestFileUuid(String testFileUuid, SearchOptions searchOptions) {
-    SearchRequestBuilder searchRequest = client.prepareSearch(TestIndexDefinition.INDEX_TYPE_TEST)
-      .setSize(searchOptions.getLimit())
-      .setFrom(searchOptions.getOffset())
-      .setQuery(boolQuery().must(matchAllQuery()).filter(termQuery(FIELD_FILE_UUID, testFileUuid)));
-
-    return new SearchResult<>(searchRequest.get(), TestDoc::new, system2.getDefaultTimeZone());
-  }
-
-  public SearchResult<TestDoc> searchBySourceFileUuidAndLineNumber(String sourceFileUuid, int lineNumber, SearchOptions searchOptions) {
-    SearchRequestBuilder searchRequest = client.prepareSearch(TestIndexDefinition.INDEX_TYPE_TEST)
-      .setSize(searchOptions.getLimit())
-      .setFrom(searchOptions.getOffset())
-      .setQuery(nestedQuery(
-        FIELD_COVERED_FILES,
-        boolQuery()
-          .must(termQuery(FIELD_COVERED_FILES + "." + FIELD_COVERED_FILE_UUID, sourceFileUuid))
-          .must(termQuery(FIELD_COVERED_FILES + "." + FIELD_COVERED_FILE_LINES, lineNumber)),
-        ScoreMode.Avg));
-
-    return new SearchResult<>(searchRequest.get(), TestDoc::new, system2.getDefaultTimeZone());
-  }
-
-  public TestDoc getByTestUuid(String testUuid) {
-    Optional<TestDoc> testDoc = getNullableByTestUuid(testUuid);
-    if (testDoc.isPresent()) {
-      return testDoc.get();
-    }
-
-    throw new IllegalStateException(String.format("Test id '%s' not found", testUuid));
-  }
-
-  public Optional<TestDoc> getNullableByTestUuid(String testUuid) {
-    SearchHit[] hits = client.prepareSearch(TestIndexDefinition.INDEX_TYPE_TEST)
-      .setSize(1)
-      .setQuery(boolQuery().must(matchAllQuery()).filter(termQuery(FIELD_TEST_UUID, testUuid)))
-      .get().getHits().getHits();
-    if (hits.length > 0) {
-      return Optional.of(new TestDoc(hits[0].getSourceAsMap()));
-    }
-    return Optional.absent();
-  }
-
-  public SearchResult<TestDoc> searchByTestUuid(String testUuid, SearchOptions searchOptions) {
-    SearchRequestBuilder searchRequest = client.prepareSearch(TestIndexDefinition.INDEX_TYPE_TEST)
-      .setSize(searchOptions.getLimit())
-      .setFrom(searchOptions.getOffset())
-      .setQuery(boolQuery().must(matchAllQuery()).filter(termQuery(FIELD_TEST_UUID, testUuid)));
-
-    return new SearchResult<>(searchRequest.get(), TestDoc::new, system2.getDefaultTimeZone());
-  }
-}
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/test/index/TestIndexer.java b/server/sonar-server-common/src/main/java/org/sonar/server/test/index/TestIndexer.java
deleted file mode 100644 (file)
index f5d820a..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.test.index;
-
-import com.google.common.collect.ImmutableSet;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-import org.elasticsearch.action.search.SearchRequestBuilder;
-import org.elasticsearch.index.query.QueryBuilders;
-import org.sonar.core.util.stream.MoreCollectors;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.es.EsQueueDto;
-import org.sonar.server.es.BulkIndexer;
-import org.sonar.server.es.BulkIndexer.Size;
-import org.sonar.server.es.EsClient;
-import org.sonar.server.es.IndexType;
-import org.sonar.server.es.IndexingListener;
-import org.sonar.server.es.IndexingResult;
-import org.sonar.server.es.OneToManyResilientIndexingListener;
-import org.sonar.server.es.ProjectIndexer;
-import org.sonar.server.source.index.FileSourcesUpdaterHelper;
-
-import static java.util.Collections.emptyList;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_FILE_UUID;
-import static org.sonar.server.test.index.TestIndexDefinition.INDEX_TYPE_TEST;
-
-/**
- * Add to Elasticsearch index {@link TestIndexDefinition} the rows of
- * db table FILE_SOURCES of type TEST that are not indexed yet
- * <p>
- * This indexer is not resilient by itself since it's called by Compute Engine
- */
-public class TestIndexer implements ProjectIndexer {
-
-  private final DbClient dbClient;
-  private final EsClient esClient;
-
-  public TestIndexer(DbClient dbClient, EsClient esClient) {
-    this.dbClient = dbClient;
-    this.esClient = esClient;
-  }
-
-  @Override
-  public Set<IndexType> getIndexTypes() {
-    return ImmutableSet.of(INDEX_TYPE_TEST);
-  }
-
-  @Override
-  public void indexOnStartup(Set<IndexType> uninitializedIndexTypes) {
-    try (DbSession dbSession = dbClient.openSession(false);
-      TestResultSetIterator rowIt = TestResultSetIterator.create(dbClient, dbSession, null)) {
-
-      BulkIndexer bulkIndexer = new BulkIndexer(esClient, INDEX_TYPE_TEST, Size.LARGE);
-      bulkIndexer.start();
-      addTestsToBulkIndexer(rowIt, bulkIndexer);
-      bulkIndexer.stop();
-    }
-  }
-
-  @Override
-  public void indexOnAnalysis(String branchUuid) {
-    BulkIndexer bulkIndexer = new BulkIndexer(esClient, INDEX_TYPE_TEST, Size.REGULAR);
-    bulkIndexer.start();
-    addProjectDeletionToBulkIndexer(bulkIndexer, branchUuid);
-    try (DbSession dbSession = dbClient.openSession(false);
-      TestResultSetIterator rowIt = TestResultSetIterator.create(dbClient, dbSession, branchUuid)) {
-      addTestsToBulkIndexer(rowIt, bulkIndexer);
-    }
-    bulkIndexer.stop();
-  }
-
-  @Override
-  public Collection<EsQueueDto> prepareForRecovery(DbSession dbSession, Collection<String> projectUuids, Cause cause) {
-    switch (cause) {
-      case PROJECT_CREATION:
-        // no tests at that time
-      case MEASURE_CHANGE:
-      case PROJECT_KEY_UPDATE:
-      case PROJECT_TAGS_UPDATE:
-      case PERMISSION_CHANGE:
-        // Measures, project key, tags and permissions are not part of tests/test
-        return emptyList();
-
-      case PROJECT_DELETION:
-        List<EsQueueDto> items = projectUuids.stream()
-          .map(projectUuid -> EsQueueDto.create(INDEX_TYPE_TEST.format(), projectUuid, null, projectUuid))
-          .collect(MoreCollectors.toArrayList(projectUuids.size()));
-        return dbClient.esQueueDao().insert(dbSession, items);
-
-      default:
-        // defensive case
-        throw new IllegalStateException("Unsupported cause: " + cause);
-    }
-  }
-
-  public void deleteByFile(String fileUuid) {
-    SearchRequestBuilder searchRequest = esClient.prepareSearch(INDEX_TYPE_TEST)
-      .setQuery(QueryBuilders.termQuery(FIELD_FILE_UUID, fileUuid));
-    BulkIndexer.delete(esClient, INDEX_TYPE_TEST, searchRequest);
-  }
-
-  @Override
-  public IndexingResult index(DbSession dbSession, Collection<EsQueueDto> items) {
-    // The items are to be deleted
-    if (items.isEmpty()) {
-      return new IndexingResult();
-    }
-
-    IndexingListener listener = new OneToManyResilientIndexingListener(dbClient, dbSession, items);
-    BulkIndexer bulkIndexer = new BulkIndexer(esClient, INDEX_TYPE_TEST, Size.REGULAR, listener);
-    bulkIndexer.start();
-    items.forEach(i -> {
-      String projectUuid = i.getDocId();
-      addProjectDeletionToBulkIndexer(bulkIndexer, projectUuid);
-    });
-
-    return bulkIndexer.stop();
-  }
-
-  private void addProjectDeletionToBulkIndexer(BulkIndexer bulkIndexer, String projectUuid) {
-    SearchRequestBuilder searchRequest = esClient.prepareSearch(INDEX_TYPE_TEST)
-      .setQuery(QueryBuilders.termQuery(TestIndexDefinition.FIELD_PROJECT_UUID, projectUuid));
-    bulkIndexer.addDeletion(searchRequest);
-  }
-
-  private static void addTestsToBulkIndexer(TestResultSetIterator rowIt, BulkIndexer bulkIndexer) {
-    while (rowIt.hasNext()) {
-      FileSourcesUpdaterHelper.Row row = rowIt.next();
-      row.getUpdateRequests().forEach(bulkIndexer::add);
-    }
-  }
-}
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/test/index/TestResultSetIterator.java b/server/sonar-server-common/src/main/java/org/sonar/server/test/index/TestResultSetIterator.java
deleted file mode 100644 (file)
index 6da7d1f..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.test.index;
-
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
-import java.nio.charset.StandardCharsets;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import javax.annotation.Nullable;
-import org.elasticsearch.action.update.UpdateRequest;
-import org.elasticsearch.common.xcontent.XContentType;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.ResultSetIterator;
-import org.sonar.db.protobuf.DbFileSources;
-import org.sonar.db.source.FileSourceDto;
-import org.sonar.server.es.EsUtils;
-import org.sonar.server.source.index.FileSourcesUpdaterHelper.Row;
-
-import static org.sonar.server.source.index.FileSourcesUpdaterHelper.preparedStatementToSelectFileSources;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILES;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILE_LINES;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILE_UUID;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_DURATION_IN_MS;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_FILE_UUID;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_MESSAGE;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_NAME;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_PROJECT_UUID;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_STACKTRACE;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_STATUS;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_TEST_UUID;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_UPDATED_AT;
-import static org.sonar.server.test.index.TestIndexDefinition.INDEX_TYPE_TEST;
-
-/**
- * Scroll over table FILE_SOURCES of test type and directly parse data required to
- * populate the index tests/test
- */
-public class TestResultSetIterator extends ResultSetIterator<Row> {
-
-  private TestResultSetIterator(PreparedStatement stmt) throws SQLException {
-    super(stmt);
-  }
-
-  public static TestResultSetIterator create(DbClient dbClient, DbSession session, @Nullable String projectUuid) {
-    try {
-      return new TestResultSetIterator(preparedStatementToSelectFileSources(dbClient, session, FileSourceDto.Type.TEST, projectUuid));
-    } catch (SQLException e) {
-      throw new IllegalStateException("Fail to prepare SQL request to select all tests", e);
-    }
-  }
-
-  @Override
-  protected Row read(ResultSet rs) throws SQLException {
-    String projectUuid = rs.getString(1);
-    String fileUuid = rs.getString(2);
-    Date updatedAt = new Date(rs.getLong(3));
-    List<DbFileSources.Test> tests = parseData(fileUuid, rs.getBinaryStream(4));
-    return toRow(projectUuid, fileUuid, updatedAt, tests);
-  }
-
-  private static List<DbFileSources.Test> parseData(String fileUuid, @Nullable InputStream dataInput) {
-    List<DbFileSources.Test> tests = Collections.emptyList();
-    if (dataInput != null) {
-      try {
-        tests = FileSourceDto.decodeTestData(dataInput);
-      } catch (Exception e) {
-        Loggers.get(TestResultSetIterator.class).warn(String.format("Invalid file_sources.binary_data on row with file_uuid='%s', test file will be ignored", fileUuid), e);
-      }
-    }
-    return tests;
-  }
-
-  /**
-   * Convert protobuf message to tests required for Elasticsearch indexing
-   */
-  public static Row toRow(String projectUuid, String fileUuid, Date updatedAt, List<DbFileSources.Test> tests) {
-    Row result = new Row(projectUuid, fileUuid, updatedAt.getTime());
-    for (DbFileSources.Test test : tests) {
-      ByteArrayOutputStream bytes = new ByteArrayOutputStream();
-
-      // all the fields must be present, even if value is null
-      try (JsonWriter writer = JsonWriter.of(new OutputStreamWriter(bytes, StandardCharsets.UTF_8)).setSerializeNulls(true)) {
-        writer.beginObject();
-        writer.prop(FIELD_PROJECT_UUID, projectUuid);
-        writer.prop(FIELD_FILE_UUID, fileUuid);
-        writer.prop(FIELD_TEST_UUID, test.getUuid());
-        writer.prop(FIELD_NAME, test.getName());
-        writer.prop(FIELD_STATUS, test.hasStatus() ? test.getStatus().toString() : null);
-        writer.prop(FIELD_DURATION_IN_MS, test.hasExecutionTimeMs() ? test.getExecutionTimeMs() : null);
-        writer.prop(FIELD_MESSAGE, test.hasMsg() ? test.getMsg() : null);
-        writer.prop(FIELD_STACKTRACE, test.hasStacktrace() ? test.getStacktrace() : null);
-        writer.prop(FIELD_UPDATED_AT, EsUtils.formatDateTime(updatedAt));
-        writer.name(FIELD_COVERED_FILES);
-        writer.beginArray();
-        for (DbFileSources.Test.CoveredFile coveredFile : test.getCoveredFileList()) {
-          writer.beginObject();
-          writer.prop(FIELD_COVERED_FILE_UUID, coveredFile.getFileUuid());
-          writer.name(FIELD_COVERED_FILE_LINES).valueObject(coveredFile.getCoveredLineList());
-          writer.endObject();
-        }
-        writer.endArray();
-        writer.endObject();
-      }
-      // This is an optimization to reduce memory consumption and multiple conversions from Map to JSON.
-      // UpdateRequest#doc() and #upsert() take the same parameter values, so:
-      // - passing the same Map would execute two JSON serializations
-      // - Map is a useless temporarily structure: read JDBC result set -> convert to map -> convert to JSON. Generating
-      // directly JSON from result set is more efficient.
-      byte[] jsonDoc = bytes.toByteArray();
-      UpdateRequest updateRequest = new UpdateRequest(INDEX_TYPE_TEST.getIndex(), INDEX_TYPE_TEST.getType(), test.getUuid())
-        .routing(projectUuid)
-        .doc(jsonDoc, XContentType.JSON)
-        .upsert(jsonDoc, XContentType.JSON);
-      result.getUpdateRequests().add(updateRequest);
-    }
-    return result;
-  }
-}
index a794d1d4c8397ffda442ee7b82174c22c4e2d139..86624383dc4e26e07d9c74150f612d97d8fc9092 100644 (file)
  */
 package org.sonar.server.source.index;
 
-import java.io.IOException;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
 import java.util.Arrays;
-import org.apache.commons.lang.RandomStringUtils;
-import org.apache.commons.lang.math.RandomUtils;
 import org.sonar.db.protobuf.DbFileSources;
-import org.sonar.db.source.FileSourceDto;
 
 public class FileSourceTesting {
 
@@ -35,18 +28,6 @@ public class FileSourceTesting {
     // only static stuff
   }
 
-  public static void updateDataColumn(Connection connection, String fileUuid, DbFileSources.Data data) throws SQLException {
-    updateDataColumn(connection, fileUuid, FileSourceDto.encodeSourceData(data));
-  }
-
-  public static void updateDataColumn(Connection connection, String fileUuid, byte[] data) throws SQLException {
-    PreparedStatement stmt = connection.prepareStatement("UPDATE file_sources SET binary_data = ? WHERE file_uuid=? AND data_type='" + FileSourceDto.Type.SOURCE + "'");
-    stmt.setBytes(1, data);
-    stmt.setString(2, fileUuid);
-    stmt.executeUpdate();
-    stmt.close();
-  }
-
   /**
    * Generate predefined fake data. Result is mutable.
    */
@@ -71,26 +52,4 @@ public class FileSourceTesting {
     return dataBuilder;
   }
 
-  /**
-   * Generate random data. Result is mutable.
-   */
-  public static DbFileSources.Data.Builder newRandomData(int numberOfLines) {
-    DbFileSources.Data.Builder dataBuilder = DbFileSources.Data.newBuilder();
-    for (int i = 1; i <= numberOfLines; i++) {
-      dataBuilder.addLinesBuilder()
-        .setLine(i)
-        .setScmRevision(RandomStringUtils.randomAlphanumeric(15))
-        .setScmAuthor(RandomStringUtils.randomAlphanumeric(10))
-        .setScmDate(RandomUtils.nextLong())
-        .setSource(RandomStringUtils.randomAlphanumeric(20))
-        .setLineHits(RandomUtils.nextInt(4))
-        .setConditions(RandomUtils.nextInt(4))
-        .setCoveredConditions(RandomUtils.nextInt(4))
-        .setHighlighting(RandomStringUtils.randomAlphanumeric(40))
-        .setSymbols(RandomStringUtils.randomAlphanumeric(30))
-        .addAllDuplication(Arrays.asList(RandomUtils.nextInt(200), RandomUtils.nextInt(200)))
-        .build();
-    }
-    return dataBuilder;
-  }
 }
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/test/db/TestTesting.java b/server/sonar-server-common/src/test/java/org/sonar/server/test/db/TestTesting.java
deleted file mode 100644 (file)
index cca9604..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.test.db;
-
-import java.io.IOException;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.commons.lang.RandomStringUtils;
-import org.apache.commons.lang.math.RandomUtils;
-import org.sonar.core.util.Uuids;
-import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.protobuf.DbFileSources;
-import org.sonar.db.source.FileSourceDto;
-
-import static java.util.Arrays.asList;
-
-public class TestTesting {
-
-  private TestTesting() {
-    // only static stuff
-  }
-
-  public static void updateDataColumn(DbSession session, String fileUuid, List<DbFileSources.Test> tests) throws SQLException {
-    updateDataColumn(session, fileUuid, FileSourceDto.encodeTestData(tests));
-  }
-
-  public static void updateDataColumn(DbSession session, String fileUuid, byte[] data) throws SQLException {
-    Connection connection = session.getConnection();
-    PreparedStatement stmt = connection.prepareStatement("UPDATE file_sources SET binary_data = ? WHERE file_uuid=? AND data_type='TEST'");
-    stmt.setBytes(1, data);
-    stmt.setString(2, fileUuid);
-    stmt.executeUpdate();
-    stmt.close();
-    connection.commit();
-  }
-
-  /**
-   * Generate random data.
-   */
-  public static List<DbFileSources.Test> newRandomTests(int numberOfTests) {
-    List<DbFileSources.Test> tests = new ArrayList<>();
-    for (int i = 1; i <= numberOfTests; i++) {
-      DbFileSources.Test.Builder test = DbFileSources.Test.newBuilder()
-        .setUuid(Uuids.create())
-        .setName(RandomStringUtils.randomAlphanumeric(20))
-        .setStatus(DbFileSources.Test.TestStatus.FAILURE)
-        .setStacktrace(RandomStringUtils.randomAlphanumeric(50))
-        .setMsg(RandomStringUtils.randomAlphanumeric(30))
-        .setExecutionTimeMs(RandomUtils.nextLong());
-      for (int j = 0; j < numberOfTests; j++) {
-        test.addCoveredFile(
-          DbFileSources.Test.CoveredFile.newBuilder()
-            .setFileUuid(Uuids.create())
-            .addCoveredLine(RandomUtils.nextInt(500)));
-      }
-      tests.add(test.build());
-    }
-    return tests;
-  }
-
-  public static DbFileSources.Test.Builder newTest(ComponentDto mainFile, Integer... coveredLines) {
-    DbFileSources.Test.Builder test = DbFileSources.Test.newBuilder()
-      .setUuid(Uuids.create())
-      .setName(RandomStringUtils.randomAlphanumeric(20))
-      .setStatus(DbFileSources.Test.TestStatus.FAILURE)
-      .setStacktrace(RandomStringUtils.randomAlphanumeric(50))
-      .setMsg(RandomStringUtils.randomAlphanumeric(30))
-      .setExecutionTimeMs(RandomUtils.nextLong());
-    test.addCoveredFile(
-      DbFileSources.Test.CoveredFile.newBuilder()
-        .setFileUuid(mainFile.uuid())
-        .addAllCoveredLine(asList(coveredLines)));
-    return test;
-  }
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/test/index/TestIndexTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/test/index/TestIndexTest.java
deleted file mode 100644 (file)
index 6bb3a45..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.test.index;
-
-import com.google.common.base.Optional;
-import java.util.List;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.utils.System2;
-import org.sonar.server.es.EsTester;
-import org.sonar.server.es.SearchOptions;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.guava.api.Assertions.assertThat;
-import static org.sonar.server.test.index.TestIndexDefinition.INDEX_TYPE_TEST;
-
-public class TestIndexTest {
-  @Rule
-  public EsTester es = EsTester.create();
-
-  private TestIndex underTest = new TestIndex(es.client(), System2.INSTANCE);
-
-  @Test
-  public void coveredFiles() {
-    es.putDocuments(INDEX_TYPE_TEST,
-      newTestDoc("1", "TESTFILE1", newCoveredFileDoc("3"), newCoveredFileDoc("4"), newCoveredFileDoc("5")),
-      newTestDoc("2", "TESTFILE1", newCoveredFileDoc("5"), newCoveredFileDoc("6"), newCoveredFileDoc("7")));
-
-    List<CoveredFileDoc> result = underTest.coveredFiles("1");
-
-    assertThat(result).hasSize(3);
-    assertThat(result).extractingResultOf("fileUuid").containsOnly("main-uuid-3", "main-uuid-4", "main-uuid-5");
-    assertThat(result.get(0).coveredLines()).containsOnly(25, 33, 82);
-  }
-
-  @Test
-  public void searchByTestFileUuid() {
-    es.putDocuments(INDEX_TYPE_TEST,
-      newTestDoc("1", "TESTFILE1", newCoveredFileDoc("3"), newCoveredFileDoc("4"), newCoveredFileDoc("5")),
-      newTestDoc("2", "TESTFILE1", newCoveredFileDoc("5"), newCoveredFileDoc("6"), newCoveredFileDoc("7")),
-      newTestDoc("3", "TESTFILE2", newCoveredFileDoc("5"), newCoveredFileDoc("6"), newCoveredFileDoc("7")));
-
-    List<TestDoc> result = underTest.searchByTestFileUuid("TESTFILE1", searchOptions()).getDocs();
-
-    assertThat(result).hasSize(2);
-    assertThat(result).extractingResultOf("name").containsOnly("name-1", "name-2");
-  }
-
-  @Test
-  public void searchBySourceFileUuidAndLineNumber() {
-    es.putDocuments(INDEX_TYPE_TEST,
-      newTestDoc("1", "TESTFILE1", newCoveredFileDoc("10"), newCoveredFileDoc("11"), newCoveredFileDoc("12")),
-      newTestDoc("2", "TESTFILE1", newCoveredFileDoc("3"), newCoveredFileDoc("4"), newCoveredFileDoc("5")),
-      newTestDoc("3", "TESTFILE1", newCoveredFileDoc("5"), newCoveredFileDoc("6"), newCoveredFileDoc("7")));
-
-    List<TestDoc> result = underTest.searchBySourceFileUuidAndLineNumber("main-uuid-5", 82, searchOptions()).getDocs();
-
-    assertThat(result).hasSize(2);
-    assertThat(result).extractingResultOf("name").containsOnly("name-2", "name-3");
-  }
-
-  @Test
-  public void searchByTestUuid() {
-    es.putDocuments(INDEX_TYPE_TEST,
-      newTestDoc("1", "TESTFILE1", newCoveredFileDoc("3"), newCoveredFileDoc("4"), newCoveredFileDoc("5")),
-      newTestDoc("2", "TESTFILE1", newCoveredFileDoc("5"), newCoveredFileDoc("6"), newCoveredFileDoc("7")));
-
-    TestDoc test = underTest.getByTestUuid("1");
-
-    assertThat(test.testUuid()).isEqualTo("1");
-    assertThat(test.fileUuid()).isEqualTo("TESTFILE1");
-    assertThat(test.name()).isEqualTo("name-1");
-    assertThat(test.durationInMs()).isEqualTo(1L);
-    assertThat(test.status()).isEqualTo("status-1");
-    assertThat(test.message()).isEqualTo("message-1");
-    assertThat(test.coveredFiles()).hasSize(3);
-    assertThat(test.coveredFiles()).extractingResultOf("fileUuid").containsOnly("main-uuid-3", "main-uuid-4", "main-uuid-5");
-  }
-
-  @Test
-  public void getNullableByTestUuid() {
-    es.putDocuments(INDEX_TYPE_TEST,
-      newTestDoc("1", "TESTFILE1", newCoveredFileDoc("3"), newCoveredFileDoc("4"), newCoveredFileDoc("5")),
-      newTestDoc("2", "TESTFILE1", newCoveredFileDoc("5"), newCoveredFileDoc("6"), newCoveredFileDoc("7")));
-
-    Optional<TestDoc> result = underTest.getNullableByTestUuid("1");
-
-    assertThat(result).isPresent();
-    TestDoc test = result.get();
-    assertThat(test.testUuid()).isEqualTo("1");
-    assertThat(test.fileUuid()).isEqualTo("TESTFILE1");
-    assertThat(test.name()).isEqualTo("name-1");
-    assertThat(test.durationInMs()).isEqualTo(1L);
-    assertThat(test.status()).isEqualTo("status-1");
-    assertThat(test.message()).isEqualTo("message-1");
-    assertThat(test.coveredFiles()).hasSize(3);
-    assertThat(test.coveredFiles()).extractingResultOf("fileUuid").containsOnly("main-uuid-3", "main-uuid-4", "main-uuid-5");
-  }
-
-  @Test
-  public void getNullableByTestUuid_with_absent_value() {
-    Optional<TestDoc> result = underTest.getNullableByTestUuid("unknown-uuid");
-
-    assertThat(result).isAbsent();
-  }
-
-  @Test
-  public void searchByTestUuid_with_SearchOptions() {
-    es.putDocuments(INDEX_TYPE_TEST,
-      newTestDoc("1", "TESTFILE1", newCoveredFileDoc("3"), newCoveredFileDoc("4"), newCoveredFileDoc("5")),
-      newTestDoc("2", "TESTFILE1", newCoveredFileDoc("5"), newCoveredFileDoc("6"), newCoveredFileDoc("7")));
-
-    List<TestDoc> result = underTest.searchByTestUuid("1", searchOptions()).getDocs();
-
-    assertThat(result).hasSize(1);
-    assertThat(result.get(0).testUuid()).isEqualTo("1");
-  }
-
-  private CoveredFileDoc newCoveredFileDoc(String id) {
-    return new CoveredFileDoc()
-      .setFileUuid("main-uuid-" + id)
-      .setCoveredLines(asList(25, 33, 82));
-  }
-
-  private TestDoc newTestDoc(String testUuid, String fileUuid, CoveredFileDoc... coveredFiles) {
-    return new TestDoc()
-      .setUuid(testUuid)
-      .setProjectUuid("P1")
-      .setName("name-" + testUuid)
-      .setMessage("message-" + testUuid)
-      .setStackTrace("stacktrace-" + testUuid)
-      .setStatus("status-" + testUuid)
-      .setDurationInMs(Long.valueOf(testUuid))
-      .setFileUuid(fileUuid)
-      .setCoveredFiles(asList(coveredFiles));
-  }
-
-  private SearchOptions searchOptions() {
-    return new SearchOptions()
-      .setLimit(100)
-      .setOffset(0);
-  }
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/test/index/TestIndexerTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/test/index/TestIndexerTest.java
deleted file mode 100644 (file)
index 0e81c75..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.test.index;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-import org.apache.commons.io.IOUtils;
-import org.elasticsearch.common.xcontent.XContentType;
-import org.elasticsearch.search.SearchHit;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbTester;
-import org.sonar.server.es.EsTester;
-import org.sonar.server.test.db.TestTesting;
-
-import static java.lang.String.format;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.sonar.server.es.DefaultIndexSettings.REFRESH_IMMEDIATE;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_FILE_UUID;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_MESSAGE;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_NAME;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_STACKTRACE;
-import static org.sonar.server.test.index.TestIndexDefinition.INDEX_TYPE_TEST;
-
-public class TestIndexerTest {
-
-  private System2 system2 = System2.INSTANCE;
-
-  @Rule
-  public EsTester es = EsTester.create();
-
-  @Rule
-  public DbTester db = DbTester.create(system2);
-
-  private TestIndexer underTest = new TestIndexer(db.getDbClient(), es.client());
-
-  @Test
-  public void index_on_startup() {
-    TestIndexer indexer = spy(underTest);
-    doNothing().when(indexer).indexOnStartup(null);
-    indexer.indexOnStartup(null);
-    verify(indexer).indexOnStartup(null);
-  }
-
-  @Test
-  public void index_tests() throws Exception {
-    db.prepareDbUnit(getClass(), "db.xml");
-    TestTesting.updateDataColumn(db.getSession(), "FILE_UUID", TestTesting.newRandomTests(3));
-
-    underTest.indexOnStartup(null);
-
-    assertThat(countDocuments()).isEqualTo(3);
-  }
-
-  @Test
-  public void index_tests_from_project() throws Exception {
-    db.prepareDbUnit(getClass(), "db.xml");
-
-    TestTesting.updateDataColumn(db.getSession(), "FILE_UUID", TestTesting.newRandomTests(3));
-
-    underTest.indexOnAnalysis("PROJECT_UUID");
-    assertThat(countDocuments()).isEqualTo(3);
-  }
-
-  @Test
-  public void index_nothing_from_unknown_project() throws Exception {
-    db.prepareDbUnit(getClass(), "db.xml");
-
-    TestTesting.updateDataColumn(db.getSession(), "FILE_UUID", TestTesting.newRandomTests(3));
-
-    underTest.indexOnAnalysis("UNKNOWN");
-    assertThat(countDocuments()).isZero();
-  }
-
-  @Test
-  public void delete_file_by_uuid() throws Exception {
-    indexTest("P1", "F1", "T1", "U111");
-    indexTest("P1", "F1", "T2", "U112");
-    indexTest("P1", "F2", "T1", "U121");
-
-    underTest.deleteByFile("F1");
-
-    List<SearchHit> hits = getDocuments();
-    Map<String, Object> document = hits.get(0).getSource();
-    assertThat(hits).hasSize(1);
-    assertThat(document.get(FIELD_NAME)).isEqualTo("NAME_1");
-    assertThat(document.get(FIELD_FILE_UUID)).isEqualTo("F2");
-  }
-
-  @Test
-  public void long_message_can_be_indexed() throws Exception {
-    indexTest("P3", "F1", "long_message", "U111");
-
-    assertThat(countDocuments()).isEqualTo(1);
-
-    List<SearchHit> hits = getDocuments();
-    Map<String, Object> document = hits.get(0).getSource();
-    assertThat(hits).hasSize(1);
-    assertThat(document.get(FIELD_MESSAGE).toString()).hasSize(50000);
-    assertThat(document.get(FIELD_FILE_UUID)).isEqualTo("F1");
-  }
-
-  @Test
-  public void long_stacktrace_can_be_indexed() throws Exception {
-    indexTest("P3", "F1", "long_stacktrace", "U111");
-
-    assertThat(countDocuments()).isEqualTo(1);
-
-    List<SearchHit> hits = getDocuments();
-    Map<String, Object> document = hits.get(0).getSource();
-    assertThat(hits).hasSize(1);
-    assertThat(document.get(FIELD_STACKTRACE).toString()).hasSize(50000);
-    assertThat(document.get(FIELD_FILE_UUID)).isEqualTo("F1");
-  }
-
-  @Test
-  public void long_name_can_be_indexed() throws Exception {
-    indexTest("P3", "F1", "long_name", "U111");
-
-    assertThat(countDocuments()).isEqualTo(1);
-
-    List<SearchHit> hits = getDocuments();
-    Map<String, Object> document = hits.get(0).getSource();
-    assertThat(hits).hasSize(1);
-    assertThat(document.get(FIELD_NAME).toString()).hasSize(50000);
-    assertThat(document.get(FIELD_FILE_UUID)).isEqualTo("F1");
-  }
-
-  private void indexTest(String projectUuid, String fileUuid, String testName, String uuid) throws IOException {
-    String json = IOUtils.toString(getClass().getResource(format("%s/%s_%s_%s.json", getClass().getSimpleName(), projectUuid, fileUuid, testName)));
-    es.client().prepareIndex(INDEX_TYPE_TEST)
-      .setId(uuid)
-      .setRouting(projectUuid)
-      .setSource(json, XContentType.JSON)
-      .setRefreshPolicy(REFRESH_IMMEDIATE)
-      .get();
-  }
-
-  private List<SearchHit> getDocuments() {
-    return es.getDocuments(INDEX_TYPE_TEST);
-  }
-
-  private long countDocuments() {
-    return es.countDocuments(INDEX_TYPE_TEST);
-  }
-}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/test/index/TestResultSetIteratorTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/test/index/TestResultSetIteratorTest.java
deleted file mode 100644 (file)
index 11829e0..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.test.index;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import org.elasticsearch.action.update.UpdateRequest;
-import org.junit.After;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.utils.System2;
-import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.utils.log.LoggerLevel;
-import org.sonar.db.DbTester;
-import org.sonar.db.protobuf.DbFileSources;
-import org.sonar.server.source.index.FileSourcesUpdaterHelper;
-import org.sonar.server.test.db.TestTesting;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.data.MapEntry.entry;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILES;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_DURATION_IN_MS;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_FILE_UUID;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_MESSAGE;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_NAME;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_PROJECT_UUID;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_STACKTRACE;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_STATUS;
-import static org.sonar.server.test.index.TestIndexDefinition.FIELD_TEST_UUID;
-
-
-public class TestResultSetIteratorTest {
-
-  @Rule
-  public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
-  @Rule
-  public LogTester logTester = new LogTester();
-
-  TestResultSetIterator underTest;
-
-  private static List<DbFileSources.Test> newFakeTests(int numberOfTests) {
-    List<DbFileSources.Test> tests = new ArrayList<>();
-    for (int i = 1; i <= numberOfTests; i++) {
-      DbFileSources.Test.Builder test = DbFileSources.Test.newBuilder()
-        .setUuid("TEST_FILE_UUID_" + i)
-        .setName("NAME_" + i)
-        .setStatus(DbFileSources.Test.TestStatus.FAILURE)
-        .setStacktrace("STACKTRACE_" + i)
-        .setMsg("MESSAGE_" + i)
-        .setExecutionTimeMs(i);
-      for (int j = 1; j <= numberOfTests; j++) {
-        test.addCoveredFile(
-          DbFileSources.Test.CoveredFile.newBuilder()
-            .setFileUuid("MAIN_FILE_UUID_" + j)
-            .addCoveredLine(j));
-      }
-      tests.add(test.build());
-    }
-    return tests;
-  }
-
-  @After
-  public void after() {
-    if (underTest != null) {
-      underTest.close();
-    }
-  }
-
-  @Test
-  public void traverse_db() throws Exception {
-    dbTester.prepareDbUnit(getClass(), "shared.xml");
-    TestTesting.updateDataColumn(dbTester.getSession(), "F1", newFakeTests(3));
-    underTest = TestResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), null);
-
-    FileSourcesUpdaterHelper.Row row = underTest.next();
-    assertThat(row.getProjectUuid()).isEqualTo("P1");
-    assertThat(row.getFileUuid()).isEqualTo("F1");
-    assertThat(row.getUpdatedAt()).isEqualTo(1416239042000L);
-    assertThat(row.getUpdateRequests()).hasSize(3);
-
-    UpdateRequest firstRequest = row.getUpdateRequests().get(0);
-    Map<String, Object> doc = firstRequest.doc().sourceAsMap();
-    assertThat(doc).contains(
-      entry(FIELD_PROJECT_UUID, "P1"),
-      entry(FIELD_FILE_UUID, "F1"),
-      entry(FIELD_TEST_UUID, "TEST_FILE_UUID_1"),
-      entry(FIELD_STATUS, "FAILURE"),
-      entry(FIELD_MESSAGE, "MESSAGE_1"),
-      entry(FIELD_DURATION_IN_MS, 1),
-      entry(FIELD_STACKTRACE, "STACKTRACE_1"),
-      entry(FIELD_NAME, "NAME_1"));
-  }
-
-  /**
-   * File with one line. No metadata available on the line.
-   */
-  @Test
-  public void minimal_data() throws Exception {
-    dbTester.prepareDbUnit(getClass(), "shared.xml");
-    List<DbFileSources.Test> tests = Arrays.asList(
-      DbFileSources.Test.newBuilder()
-        .setUuid("U1")
-        .setName("N1")
-        .build());
-    TestTesting.updateDataColumn(dbTester.getSession(), "F1", tests);
-    underTest = TestResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), null);
-
-    FileSourcesUpdaterHelper.Row row = underTest.next();
-
-    assertThat(row.getProjectUuid()).isEqualTo("P1");
-    assertThat(row.getFileUuid()).isEqualTo("F1");
-    assertThat(row.getUpdatedAt()).isEqualTo(1416239042000L);
-    assertThat(row.getUpdateRequests()).hasSize(1);
-    UpdateRequest firstRequest = row.getUpdateRequests().get(0);
-    Map<String, Object> doc = firstRequest.doc().sourceAsMap();
-    assertThat(doc).contains(
-      entry(FIELD_PROJECT_UUID, "P1"),
-      entry(FIELD_FILE_UUID, "F1"),
-      entry(FIELD_TEST_UUID, "U1"),
-      entry(FIELD_NAME, "N1"));
-    // null values
-    assertThat(doc).containsKeys(
-      FIELD_DURATION_IN_MS,
-      FIELD_STACKTRACE,
-      FIELD_MESSAGE,
-      FIELD_STATUS,
-      FIELD_COVERED_FILES);
-  }
-
-  @Test
-  public void filter_by_project() throws Exception {
-    dbTester.prepareDbUnit(getClass(), "filter_by_project.xml");
-    TestTesting.updateDataColumn(dbTester.getSession(), "F1", newFakeTests(1));
-
-    underTest = TestResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), "P1");
-
-    FileSourcesUpdaterHelper.Row row = underTest.next();
-    assertThat(row.getProjectUuid()).isEqualTo("P1");
-    assertThat(row.getFileUuid()).isEqualTo("F1");
-
-    // File from other project P2 is not returned
-    assertThat(underTest.hasNext()).isFalse();
-  }
-
-  @Test
-  public void read_does_not_fail_if_corrupted_data() throws Exception {
-    dbTester.prepareDbUnit(getClass(), "shared.xml");
-
-    TestTesting.updateDataColumn(dbTester.getSession(), "F1", "THIS_IS_NOT_PROTOBUF".getBytes());
-
-    underTest = TestResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), null);
-    FileSourcesUpdaterHelper.Row row = underTest.next();
-    assertThat(row.getFileUuid()).isEqualTo("F1");
-    assertThat(row.getUpdateRequests()).isEmpty();
-    assertThat(underTest.hasNext()).isFalse();
-
-    assertThat(logTester.logs(LoggerLevel.WARN)).contains("Invalid file_sources.binary_data on row with file_uuid='F1', test file will be ignored");
-  }
-
-  @Test
-  public void read_does_not_fail_if_null_data() throws Exception {
-    dbTester.prepareDbUnit(getClass(), "shared.xml");
-    TestTesting.updateDataColumn(dbTester.getSession(), "F1", (byte[])null);
-
-    underTest = TestResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), null);
-
-    FileSourcesUpdaterHelper.Row row = underTest.next();
-    assertThat(row.getFileUuid()).isEqualTo("F1");
-    assertThat(row.getUpdateRequests()).isEmpty();
-    assertThat(underTest.hasNext()).isFalse();
-  }
-}
diff --git a/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P1_F1_T1.json b/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P1_F1_T1.json
deleted file mode 100644 (file)
index 52013fe..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "projectUuid": "P1",
-  "fileUuid": "F1",
-  "testUuid": "U111",
-  "name": "NAME_1",
-  "status": "FAILURE",
-  "durationInMs": 100000,
-  "message": "MESSAGE_1",
-  "stacktrace": "STACKTRACE_1",
-  "updatedAt": "2014-01-01T23:45:01.8+01:00"
-}
diff --git a/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P1_F1_T2.json b/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P1_F1_T2.json
deleted file mode 100644 (file)
index 6a76a80..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "projectUuid": "P1",
-  "fileUuid": "F1",
-  "testUuid": "U112",
-  "name": "NAME_2",
-  "status": "FAILURE",
-  "durationInMs": 100000,
-  "message": "MESSAGE_1",
-  "stacktrace": "STACKTRACE_1",
-  "updatedAt": "2014-01-01T23:45:01.8+01:00"
-}
diff --git a/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P1_F2_T1.json b/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P1_F2_T1.json
deleted file mode 100644 (file)
index 1c2e2b9..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "projectUuid": "P1",
-  "fileUuid": "F2",
-  "testUuid": "U121",
-  "name": "NAME_1",
-  "status": "FAILURE",
-  "durationInMs": 100000,
-  "message": "MESSAGE_1",
-  "stacktrace": "STACKTRACE_1",
-  "updatedAt": "2014-01-01T23:45:01.8+01:00"
-}
diff --git a/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P2_F3_T1.json b/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P2_F3_T1.json
deleted file mode 100644 (file)
index 643e58b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "projectUuid": "P2",
-  "fileUuid": "F3",
-  "testUuid": "U231",
-  "name": "NAME_1",
-  "status": "FAILURE",
-  "durationInMs": 100000,
-  "message": "MESSAGE_1",
-  "stacktrace": "STACKTRACE_1",
-  "updatedAt": "2014-01-01T23:45:01.8+01:00"
-}
diff --git a/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P3_F1_long_message.json b/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P3_F1_long_message.json
deleted file mode 100644 (file)
index b259759..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "projectUuid": "P3",
-  "fileUuid": "F1",
-  "testUuid": "U111",
-  "name": "NAME_1",
-  "status": "FAILURE",
-  "durationInMs": 100000,
-  "message": "1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 ",
-  "stacktrace": "STACKTRACE_1",
-  "updatedAt": "2014-01-01T23:45:01.8+01:00"
-}
diff --git a/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P3_F1_long_name.json b/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P3_F1_long_name.json
deleted file mode 100644 (file)
index 6748fa1..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "projectUuid": "P3",
-  "fileUuid": "F1",
-  "testUuid": "U111",
-  "status": "FAILURE",
-  "durationInMs": 100000,
-  "message": "MESSAGE_1",
-  "name": "1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 ",
-  "stacktrace": "stacktrace",
-  "updatedAt": "2014-01-01T23:45:01.8+01:00"
-}
diff --git a/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P3_F1_long_stacktrace.json b/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/P3_F1_long_stacktrace.json
deleted file mode 100644 (file)
index c41860c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "projectUuid": "P3",
-  "fileUuid": "F1",
-  "testUuid": "U111",
-  "name": "NAME_1",
-  "status": "FAILURE",
-  "durationInMs": 100000,
-  "message": "MESSAGE_1",
-  "stacktrace": "1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 ",
-  "updatedAt": "2014-01-01T23:45:01.8+01:00"
-}
diff --git a/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/db.xml b/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestIndexerTest/db.xml
deleted file mode 100644 (file)
index 5aedd1c..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<dataset>
-
-  <file_sources id="1"
-                project_uuid="PROJECT_UUID"
-                file_uuid="FILE_UUID"
-                line_count="0"
-                created_at="1416238020000"
-                updated_at="1416239042000"
-                binary_data=""
-                data_hash=""
-                data_type="TEST"
-  />
-
-</dataset>
diff --git a/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestResultSetIteratorTest/filter_by_project.xml b/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestResultSetIteratorTest/filter_by_project.xml
deleted file mode 100644 (file)
index 5db8861..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<dataset>
-
-  <file_sources id="1"
-                project_uuid="P1"
-                file_uuid="F1"
-                created_at="1416238020000"
-                updated_at="1416239042000"
-                line_count="0"
-                binary_data=""
-                data_hash=""
-                data_type="TEST"/>
-
-  <file_sources id="2"
-                project_uuid="P2"
-                file_uuid="F2"
-                created_at="1416238020000"
-                updated_at="1416239042000"
-                line_count="0"
-                binary_data=""
-                data_hash=""
-                data_type="TEST"/>
-
-</dataset>
diff --git a/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestResultSetIteratorTest/filter_by_project_and_date.xml b/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestResultSetIteratorTest/filter_by_project_and_date.xml
deleted file mode 100644 (file)
index b40d33f..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<dataset>
-
-  <file_sources id="1"
-                project_uuid="P1"
-                file_uuid="F1"
-                created_at="1416238020000"
-                updated_at="1416239042000"
-                line_count="0"
-                binary_data=""
-                data_hash=""
-                data_type="TEST"/>
-
-  <file_sources id="2"
-                project_uuid="P1"
-                file_uuid="F2"
-                created_at="1416238020000"
-                updated_at="1300000000000"
-                line_count="0"
-                binary_data=""
-                data_hash=""
-                data_type="TEST"/>
-
-</dataset>
diff --git a/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestResultSetIteratorTest/schema.sql b/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestResultSetIteratorTest/schema.sql
deleted file mode 100644 (file)
index 99f823f..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-
-CREATE TABLE "FILE_SOURCES" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "PROJECT_UUID" VARCHAR(50) NOT NULL,
-  "FILE_UUID" VARCHAR(50) NOT NULL,
-  "BINARY_DATA" BINARY(167772150),
-  "DATA_HASH" VARCHAR(50) NOT NULL,
-  "DATA_TYPE" VARCHAR(50),
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL
-);
diff --git a/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestResultSetIteratorTest/shared.xml b/server/sonar-server-common/src/test/resources/org/sonar/server/test/index/TestResultSetIteratorTest/shared.xml
deleted file mode 100644 (file)
index ca4a6e5..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<dataset>
-
-  <file_sources id="1"
-                project_uuid="P1"
-                file_uuid="F1"
-                created_at="1416238020000"
-                updated_at="1416239042000"
-                line_count="0"
-                binary_data=""
-                data_hash=""
-                data_type="TEST"/>
-
-</dataset>
index 3438a614598b39714cfc77389eb14700fbc1f2ae..07edaae0eeaece7d66c4b0e2ec02c5651d559c20 100644 (file)
@@ -199,10 +199,7 @@ import org.sonar.server.startup.LogServerId;
 import org.sonar.server.telemetry.TelemetryClient;
 import org.sonar.server.telemetry.TelemetryDaemon;
 import org.sonar.server.telemetry.TelemetryDataLoader;
-import org.sonar.server.test.index.TestIndex;
 import org.sonar.server.test.index.TestIndexDefinition;
-import org.sonar.server.test.index.TestIndexer;
-import org.sonar.server.test.ws.CoveredFilesAction;
 import org.sonar.server.test.ws.TestsWs;
 import org.sonar.server.text.MacroInterpreter;
 import org.sonar.server.ui.DeprecatedViews;
@@ -479,11 +476,7 @@ public class PlatformLevel4 extends PlatformLevel {
 
       // Tests
       TestsWs.class,
-      CoveredFilesAction.class,
-      org.sonar.server.test.ws.ListAction.class,
       TestIndexDefinition.class,
-      TestIndex.class,
-      TestIndexer.class,
 
       // Settings
       PersistentSettings.class,
index 6c9dbc3111ceed10531b836139b470d67801a5a4..7d166a390ffb35d046b0749887481931876c8615 100644 (file)
@@ -65,7 +65,7 @@ public class SourceService {
   private <E> Optional<Iterable<E>> getLines(DbSession dbSession, String fileUuid, int from, int toInclusive, Function<DbFileSources.Line, E> function) {
     verifyLine(from);
     checkArgument(toInclusive >= from, String.format("Line number must greater than or equal to %d, got %d", from, toInclusive));
-    FileSourceDto dto = dbClient.fileSourceDao().selectSourceByFileUuid(dbSession, fileUuid);
+    FileSourceDto dto = dbClient.fileSourceDao().selectByFileUuid(dbSession, fileUuid);
     if (dto == null) {
       return Optional.empty();
     }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/test/ws/CoveredFilesAction.java b/server/sonar-server/src/main/java/org/sonar/server/test/ws/CoveredFilesAction.java
deleted file mode 100644 (file)
index c457754..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.test.ws;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.io.Resources;
-import java.util.List;
-import java.util.Map;
-import javax.annotation.Nonnull;
-import org.sonar.api.server.ws.Change;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.util.Uuids;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.server.test.index.CoveredFileDoc;
-import org.sonar.server.test.index.TestDoc;
-import org.sonar.server.test.index.TestIndex;
-import org.sonar.server.user.UserSession;
-import org.sonarqube.ws.Tests;
-
-import static org.sonar.core.util.Protobuf.setNullable;
-import static org.sonar.server.ws.WsUtils.checkFoundWithOptional;
-import static org.sonar.server.ws.WsUtils.writeProtobuf;
-
-public class CoveredFilesAction implements TestsWsAction {
-
-  public static final String TEST_ID = "testId";
-
-  private final DbClient dbClient;
-  private final TestIndex index;
-  private final UserSession userSession;
-
-  public CoveredFilesAction(DbClient dbClient, TestIndex index, UserSession userSession) {
-    this.dbClient = dbClient;
-    this.index = index;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller.createAction("covered_files")
-      .setDescription("Get the list of source files covered by a test. Require Browse permission on test file's project")
-      .setSince("4.4")
-      .setResponseExample(Resources.getResource(getClass(), "tests-example-covered-files.json"))
-      .setDeprecatedSince("5.6")
-      .setHandler(this)
-      .setChangelog(new Change("6.6", "\"branch\" field is now returned"))
-      .addPagingParams(100);
-
-    action
-      .createParam(TEST_ID)
-      .setRequired(true)
-      .setDescription("Test ID")
-      .setExampleValue(Uuids.UUID_EXAMPLE_01);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    String testId = request.mandatoryParam(TEST_ID);
-    TestDoc testDoc = checkFoundWithOptional(index.getNullableByTestUuid(testId), "Test with id '%s' is not found", testId);
-    userSession.checkComponentUuidPermission(UserRole.CODEVIEWER, testDoc.fileUuid());
-
-    List<CoveredFileDoc> coveredFiles = index.coveredFiles(testId);
-    Map<String, ComponentDto> componentsByUuid = buildComponentsByUuid(coveredFiles);
-
-    Tests.CoveredFilesResponse.Builder responseBuilder = Tests.CoveredFilesResponse.newBuilder();
-    if (!coveredFiles.isEmpty()) {
-      for (CoveredFileDoc doc : coveredFiles) {
-        Tests.CoveredFilesResponse.CoveredFile.Builder fileBuilder = Tests.CoveredFilesResponse.CoveredFile.newBuilder();
-        fileBuilder.setId(doc.fileUuid());
-        fileBuilder.setCoveredLines(doc.coveredLines().size());
-        ComponentDto component = componentsByUuid.get(doc.fileUuid());
-        if (component != null) {
-          fileBuilder.setKey(component.getKey());
-          fileBuilder.setLongName(component.longName());
-          setNullable(component.getBranch(), fileBuilder::setBranch);
-        }
-
-        responseBuilder.addFiles(fileBuilder);
-      }
-    }
-    writeProtobuf(responseBuilder.build(), request, response);
-  }
-
-  private Map<String, ComponentDto> buildComponentsByUuid(List<CoveredFileDoc> coveredFiles) {
-    List<String> sourceFileUuids = Lists.transform(coveredFiles, new CoveredFileToFileUuidFunction());
-    List<ComponentDto> components;
-    try (DbSession dbSession = dbClient.openSession(false)) {
-      components = dbClient.componentDao().selectByUuids(dbSession, sourceFileUuids);
-    }
-    return Maps.uniqueIndex(components, ComponentDto::uuid);
-  }
-
-  private static class CoveredFileToFileUuidFunction implements Function<CoveredFileDoc, String> {
-    @Override
-    public String apply(@Nonnull CoveredFileDoc coveredFile) {
-      return coveredFile.fileUuid();
-    }
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/test/ws/ListAction.java b/server/sonar-server/src/main/java/org/sonar/server/test/ws/ListAction.java
deleted file mode 100644 (file)
index c1f91f7..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.test.ws;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.io.Resources;
-import java.util.List;
-import java.util.Map;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.server.ws.Change;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.util.Uuids;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.es.SearchOptions;
-import org.sonar.server.es.SearchResult;
-import org.sonar.server.test.index.CoveredFileDoc;
-import org.sonar.server.test.index.TestDoc;
-import org.sonar.server.test.index.TestIndex;
-import org.sonar.server.user.UserSession;
-import org.sonar.server.ws.KeyExamples;
-import org.sonar.server.ws.WsUtils;
-import org.sonarqube.ws.Common;
-import org.sonarqube.ws.Tests;
-
-import static org.sonar.api.server.ws.WebService.Param.PAGE;
-import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
-import static org.sonar.api.web.UserRole.CODEVIEWER;
-import static org.sonar.core.util.Protobuf.setNullable;
-import static org.sonar.server.es.SearchOptions.MAX_LIMIT;
-import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001;
-import static org.sonar.server.ws.KeyExamples.KEY_PULL_REQUEST_EXAMPLE_001;
-import static org.sonar.server.ws.WsUtils.checkFoundWithOptional;
-
-public class ListAction implements TestsWsAction {
-  public static final String TEST_ID = "testId";
-  public static final String TEST_FILE_ID = "testFileId";
-  public static final String TEST_FILE_KEY = "testFileKey";
-  public static final String SOURCE_FILE_ID = "sourceFileId";
-  public static final String SOURCE_FILE_KEY = "sourceFileKey";
-  public static final String SOURCE_FILE_LINE_NUMBER = "sourceFileLineNumber";
-  public static final String PARAM_BRANCH = "branch";
-  public static final String PARAM_PULL_REQUEST = "pullRequest";
-
-  private final DbClient dbClient;
-  private final TestIndex testIndex;
-  private final UserSession userSession;
-  private final ComponentFinder componentFinder;
-
-  public ListAction(DbClient dbClient, TestIndex testIndex, UserSession userSession, ComponentFinder componentFinder) {
-    this.dbClient = dbClient;
-    this.testIndex = testIndex;
-    this.userSession = userSession;
-    this.componentFinder = componentFinder;
-  }
-
-  @Override
-  public void define(WebService.NewController controller) {
-    WebService.NewAction action = controller
-      .createAction("list")
-      .setDescription(String.format(
-        "Get the list of tests either in a test file or that test a given line of source code.<br /> " +
-          "Requires 'Browse' permission on the file's project.<br /> " +
-          "One (and only one) of the following combination of parameters must be provided: " +
-          "<ul>" +
-          "<li>%s - get a specific test</li>" +
-          "<li>%s - get the tests in a test file</li>" +
-          "<li>%s - get the tests in a test file</li>" +
-          "<li>%s and %6$s - get the tests that cover a specific line of code</li>" +
-          "<li>%s and %6$s - get the tests that cover a specific line of code</li>" +
-          "</ul>",
-        TEST_ID, TEST_FILE_ID, TEST_FILE_KEY, SOURCE_FILE_ID, SOURCE_FILE_KEY, SOURCE_FILE_LINE_NUMBER))
-      .setSince("5.2")
-      .setResponseExample(Resources.getResource(getClass(), "tests-example-list.json"))
-      .setDeprecatedSince("5.6")
-      .setHandler(this)
-      .setChangelog(new Change("6.6", "\"fileBranch\" field is now returned"))
-      .setChangelog(new Change("7.1", "\"filePullRequest\" field is now returned"))
-      .addPagingParams(100, MAX_LIMIT);
-
-    action
-      .createParam(TEST_FILE_ID)
-      .setDescription("ID of test file")
-      .setExampleValue(Uuids.UUID_EXAMPLE_01);
-
-    action
-      .createParam(TEST_FILE_KEY)
-      .setDescription("Key of test file")
-      .setExampleValue("MY_PROJECT:src/test/java/foo/BarTest.java");
-
-    action
-      .createParam(TEST_ID)
-      .setDescription("ID of test")
-      .setExampleValue(Uuids.UUID_EXAMPLE_02);
-
-    action
-      .createParam(SOURCE_FILE_ID)
-      .setDescription("ID of source file. Must be provided with the source file line number.")
-      .setExampleValue(Uuids.UUID_EXAMPLE_03);
-
-    action
-      .createParam(SOURCE_FILE_KEY)
-      .setSince("5.4")
-      .setDescription("Key of source file. Must be provided with the source file line number.")
-      .setExampleValue(KeyExamples.KEY_FILE_EXAMPLE_001);
-
-    action
-      .createParam(SOURCE_FILE_LINE_NUMBER)
-      .setDescription("Source file line number. Must be provided with the source file ID or key.")
-      .setExampleValue("10");
-
-    action.createParam(PARAM_BRANCH)
-      .setDescription("Branch key")
-      .setSince("6.6")
-      .setInternal(true)
-      .setExampleValue(KEY_BRANCH_EXAMPLE_001);
-
-    action.createParam(PARAM_PULL_REQUEST)
-      .setDescription("Pull request id")
-      .setSince("7.1")
-      .setInternal(true)
-      .setExampleValue(KEY_PULL_REQUEST_EXAMPLE_001);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    String testUuid = request.param(TEST_ID);
-    String testFileUuid = request.param(TEST_FILE_ID);
-    String testFileKey = request.param(TEST_FILE_KEY);
-    String sourceFileUuid = request.param(SOURCE_FILE_ID);
-    String sourceFileKey = request.param(SOURCE_FILE_KEY);
-    String branch = request.param(PARAM_BRANCH);
-    String pullRequest = request.param(PARAM_PULL_REQUEST);
-    Integer sourceFileLineNumber = request.paramAsInt(SOURCE_FILE_LINE_NUMBER);
-    SearchOptions searchOptions = new SearchOptions().setPage(
-      request.mandatoryParamAsInt(PAGE),
-      request.mandatoryParamAsInt(PAGE_SIZE));
-
-    SearchResult<TestDoc> tests;
-    Map<String, ComponentDto> componentsByTestFileUuid;
-    try (DbSession dbSession = dbClient.openSession(false)) {
-      tests = searchTests(dbSession, testUuid, testFileUuid, testFileKey, sourceFileUuid, sourceFileKey, branch, pullRequest, sourceFileLineNumber, searchOptions);
-      componentsByTestFileUuid = buildComponentsByTestFileUuid(dbSession, tests.getDocs());
-    }
-
-    Tests.ListResponse.Builder responseBuilder = Tests.ListResponse.newBuilder();
-    responseBuilder.setPaging(Common.Paging.newBuilder()
-      .setPageIndex(searchOptions.getPage())
-      .setPageSize(searchOptions.getLimit())
-      .setTotal((int) tests.getTotal())
-      .build());
-
-    for (TestDoc testDoc : tests.getDocs()) {
-      Tests.Test.Builder testBuilder = Tests.Test.newBuilder();
-      testBuilder.setId(testDoc.testUuid());
-      testBuilder.setName(StringUtils.defaultString(testDoc.name()));
-      testBuilder.setFileId(testDoc.fileUuid());
-      ComponentDto component = componentsByTestFileUuid.get(testDoc.fileUuid());
-      if (component != null) {
-        testBuilder.setFileKey(component.getKey());
-        testBuilder.setFileName(component.longName());
-        setNullable(component.getBranch(), testBuilder::setFileBranch);
-        setNullable(component.getPullRequest(), testBuilder::setFilePullRequest);
-      }
-      testBuilder.setStatus(Tests.TestStatus.valueOf(testDoc.status()));
-      if (testDoc.durationInMs() != null) {
-        testBuilder.setDurationInMs(testDoc.durationInMs());
-      }
-      testBuilder.setCoveredLines(coveredLines(testDoc.coveredFiles()));
-      if (testDoc.message() != null) {
-        testBuilder.setMessage(testDoc.message());
-      }
-      if (testDoc.stackTrace() != null) {
-        testBuilder.setStacktrace(testDoc.stackTrace());
-      }
-      responseBuilder.addTests(testBuilder.build());
-    }
-    WsUtils.writeProtobuf(responseBuilder.build(), request, response);
-  }
-
-  private static int coveredLines(List<CoveredFileDoc> coveredFiles) {
-    int numberOfLinesCovered = 0;
-    for (CoveredFileDoc coveredFile : coveredFiles) {
-      numberOfLinesCovered += coveredFile.coveredLines().size();
-    }
-
-    return numberOfLinesCovered;
-  }
-
-  private Map<String, ComponentDto> buildComponentsByTestFileUuid(DbSession dbSession, List<TestDoc> tests) {
-    List<String> fileUuids = Lists.transform(tests, new TestToFileUuidFunction());
-    List<ComponentDto> components = dbClient.componentDao().selectByUuids(dbSession, fileUuids);
-
-    return Maps.uniqueIndex(components, ComponentDto::uuid);
-  }
-
-  private SearchResult<TestDoc> searchTests(DbSession dbSession, @Nullable String testUuid, @Nullable String testFileUuid, @Nullable String testFileKey,
-    @Nullable String sourceFileUuid, @Nullable String sourceFileKey, @Nullable String branch, @Nullable String pullRequest,
-    @Nullable Integer sourceFileLineNumber, SearchOptions searchOptions) {
-    if (testUuid != null) {
-      TestDoc testDoc = checkFoundWithOptional(testIndex.getNullableByTestUuid(testUuid), "Test with id '%s' is not found", testUuid);
-      checkComponentUuidPermission(dbSession, testDoc.fileUuid());
-      return testIndex.searchByTestUuid(testUuid, searchOptions);
-    }
-    if (testFileUuid != null) {
-      checkComponentUuidPermission(dbSession, testFileUuid);
-      return testIndex.searchByTestFileUuid(testFileUuid, searchOptions);
-    }
-    if (testFileKey != null) {
-      ComponentDto testFile = componentFinder.getByKeyAndOptionalBranchOrPullRequest(dbSession, testFileKey, branch, pullRequest);
-      userSession.checkComponentPermission(CODEVIEWER, testFile);
-      return testIndex.searchByTestFileUuid(testFile.uuid(), searchOptions);
-    }
-    if (sourceFileUuid != null && sourceFileLineNumber != null) {
-      ComponentDto sourceFile = componentFinder.getByUuid(dbSession, sourceFileUuid);
-      userSession.checkComponentPermission(CODEVIEWER, sourceFile);
-      return testIndex.searchBySourceFileUuidAndLineNumber(sourceFile.uuid(), sourceFileLineNumber, searchOptions);
-    }
-    if (sourceFileKey != null && sourceFileLineNumber != null) {
-      ComponentDto sourceFile = componentFinder.getByKeyAndOptionalBranchOrPullRequest(dbSession, sourceFileKey, branch, pullRequest);
-      userSession.checkComponentPermission(CODEVIEWER, sourceFile);
-      return testIndex.searchBySourceFileUuidAndLineNumber(sourceFile.uuid(), sourceFileLineNumber, searchOptions);
-    }
-
-    throw new IllegalArgumentException(
-      "One (and only one) of the following combination of parameters must be provided: 1) test UUID. 2) test file UUID. " +
-        "3) test file key. 4) source file ID or key with a source file line number.");
-  }
-
-  private void checkComponentUuidPermission(DbSession dbSession, String componentUuid) {
-    ComponentDto component = componentFinder.getByUuid(dbSession, componentUuid);
-    userSession.checkComponentPermission(CODEVIEWER, component);
-  }
-
-  private static class TestToFileUuidFunction implements Function<TestDoc, String> {
-    @Override
-    public String apply(@Nonnull TestDoc testDoc) {
-      return testDoc.fileUuid();
-    }
-  }
-}
index 61310d2bdd5f40fc4d61d152eec7ffaf8074e551..fb477f7b9dcd805f8add47b5eb9d8801ed55b76d 100644 (file)
  */
 package org.sonar.server.test.ws;
 
+import org.sonar.api.server.ws.Change;
 import org.sonar.api.server.ws.WebService;
+import org.sonar.server.ws.RemovedWebServiceHandler;
 
 public class TestsWs implements WebService {
 
-  private final TestsWsAction[] actions;
-
-  public TestsWs(TestsWsAction... actions) {
-    this.actions = actions;
-  }
-
   @Override
   public void define(Context context) {
     NewController controller = context.createController("api/tests")
       .setSince("4.4")
-      .setDescription("Get details on test files. See also api/sources. Deprecated since 5.6.");
+      .setDescription("Removed in 7.6");
 
-    for (TestsWsAction action : actions) {
-      action.define(controller);
-    }
+    controller.createAction("covered_files")
+      .setDescription("This web API is no longer supported")
+      .setSince("4.4")
+      .setDeprecatedSince("5.6")
+      .setChangelog(new Change("7.6", "This action has been removed"))
+      .setResponseExample(RemovedWebServiceHandler.INSTANCE.getResponseExample())
+      .setHandler(RemovedWebServiceHandler.INSTANCE);
+
+    controller
+      .createAction("list")
+      .setDescription("This web API is no longer supported")
+      .setSince("5.2")
+      .setDeprecatedSince("5.6")
+      .setChangelog(new Change("7.6", "This action has been removed"))
+      .setResponseExample(RemovedWebServiceHandler.INSTANCE.getResponseExample())
+      .setHandler(RemovedWebServiceHandler.INSTANCE);
 
     controller.done();
   }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/test/ws/TestsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/test/ws/TestsWsAction.java
deleted file mode 100644 (file)
index 557160f..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.test.ws;
-
-import org.sonar.server.ws.WsAction;
-
-public interface TestsWsAction extends WsAction {
-  // marker interface
-}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/test/ws/tests-example-covered-files.json b/server/sonar-server/src/main/resources/org/sonar/server/test/ws/tests-example-covered-files.json
deleted file mode 100644 (file)
index ce75518..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "files": [
-    {
-      "key": "org.codehaus.sonar:sonar-server:src/main/java/org/sonar/server/paging/PagedResult.java",
-      "longName": "src/main/java/org/sonar/server/paging/PagedResult.java",
-      "coveredLines": 5
-    },
-    {
-      "key": "org.codehaus.sonar:sonar-server:src/main/java/org/sonar/server/rule/RuleDocumentParser.java",
-      "longName": "src/main/java/org/sonar/server/rule/RuleDocumentParser.java",
-      "coveredLines": 38
-    }
-  ]
-}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/test/ws/tests-example-list.json b/server/sonar-server/src/main/resources/org/sonar/server/test/ws/tests-example-list.json
deleted file mode 100644 (file)
index 5eee2e3..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-{
-  "paging": {
-    "pageIndex": 1,
-    "pageSize": 10,
-    "total": 2
-  },
-  "tests": [
-    {
-      "id": "AU-TpxcB-iU5OvuD2FL7",
-      "name": "find_by_params",
-      "status": "OK",
-      "fileId": "AU-TpxcB-iU5OvuD2Fd8",
-      "fileKey": "org.codehaus.sonar:sonar-server:src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java",
-      "fileName": "src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java",
-      "durationInMs": 10,
-      "coveredLines": 89
-    },
-    {
-      "id": "AU-TpxcB-iU5OvuD2FP9",
-      "name": "find_rules_by_characteristics",
-      "status": "ERROR",
-      "fileId": "AU-TpxcB-iU5OvuD2FR2",
-      "fileKey": "org.codehaus.sonar:sonar-server:src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java",
-      "fileName": "src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java",
-      "durationInMs": 97,
-      "coveredLines": 0,
-      "message": "expected:<true> but was:<false>",
-      "stackTrace": "java.lang.AssertionError: expected:<true> but was:<false>\n\tat org.junit.Assert.fail(Assert.java:91)\n\tat org.junit.Assert.failNotEquals(Assert.java:645)\n\tat org.junit.Assert.assertEquals(Assert.java:126)\n\tat org.junit.Assert.assertEquals(Assert.java:145)\n\tat sonar.samples.testFailures.moduleA.FailTest.testAWithFailure(FailTest.java:12)\n"
-    }
-  ]
-}
index c7efa7745f03890fa9968dedf860499b850e9eb7..92ef28722d5357bcb17a83f0e32dc60c12d56215 100644 (file)
@@ -268,7 +268,6 @@ public class ProjectDataLoaderTest {
       .setLineHashes(of("8d7b3d6b83c0a517eac07e1aac94b773"))
       .setCreatedAt(System.currentTimeMillis())
       .setUpdatedAt(System.currentTimeMillis())
-      .setDataType(FileSourceDto.Type.SOURCE)
       .setRevision("123456789")
       .setSrcHash("123456");
   }
index a8309f2d17af7561140f426bc7519b52585beb53..e0916bddd377109e17468a7afb97e8fe9b404179 100644 (file)
@@ -26,7 +26,6 @@ import org.sonar.api.utils.System2;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.protobuf.DbFileSources;
 import org.sonar.db.source.FileSourceDto;
 import org.sonar.server.component.TestComponentFinder;
 import org.sonar.server.exceptions.ForbiddenException;
@@ -38,7 +37,6 @@ import org.sonar.server.ws.WsActionTester;
 import static java.lang.String.format;
 import static java.util.Collections.singletonList;
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.api.resources.Qualifiers.UNIT_TEST_FILE;
 import static org.sonar.api.web.UserRole.USER;
 import static org.sonar.db.component.ComponentTesting.newFileDto;
 
@@ -66,20 +64,6 @@ public class HashActionTest {
     assertThat(request.execute().getInput()).isEqualTo("ABC");
   }
 
-  @Test
-  public void show_hashes_on_test_file() {
-    OrganizationDto organizationDto = db.organizations().insert();
-    ComponentDto project = db.components().insertPrivateProject(organizationDto);
-    ComponentDto test = db.components().insertComponent(newFileDto(project).setQualifier(UNIT_TEST_FILE));
-    FileSourceDto fileSource = db.fileSources().insertFileSource(test, f -> f.setLineHashes(singletonList("ABC")));
-    FileSourceDto fileTest = db.fileSources().insertFileSource(test, f -> f.setTestData(singletonList(DbFileSources.Test.newBuilder().build())));
-    loginAsProjectViewer(project);
-
-    TestRequest request = tester.newRequest().setParam("key", test.getKey());
-
-    assertThat(request.execute().getInput()).isEqualTo("ABC");
-  }
-
   @Test
   public void hashes_empty_if_no_source() {
     OrganizationDto organizationDto = db.organizations().insert();
diff --git a/server/sonar-server/src/test/java/org/sonar/server/test/ws/CoveredFilesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/test/ws/CoveredFilesActionTest.java
deleted file mode 100644 (file)
index bf1d6d1..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.test.ws;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.System2;
-import org.sonar.core.util.Uuids;
-import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.protobuf.DbFileSources;
-import org.sonar.db.protobuf.DbFileSources.Test.CoveredFile;
-import org.sonar.db.source.FileSourceDto;
-import org.sonar.server.es.EsTester;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.test.index.TestIndex;
-import org.sonar.server.test.index.TestIndexer;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.TestRequest;
-import org.sonar.server.ws.WsActionTester;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.api.resources.Qualifiers.UNIT_TEST_FILE;
-import static org.sonar.api.web.UserRole.CODEVIEWER;
-import static org.sonar.db.component.ComponentTesting.newFileDto;
-import static org.sonar.server.test.ws.CoveredFilesAction.TEST_ID;
-import static org.sonar.test.JsonAssert.assertJson;
-
-public class CoveredFilesActionTest {
-
-  @Rule
-  public UserSessionRule userSession = UserSessionRule.standalone();
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-  @Rule
-  public EsTester es = EsTester.create();
-  @Rule
-  public DbTester db = DbTester.create();
-
-  private TestIndex testIndex = new TestIndex(es.client(), System2.INSTANCE);
-  private TestIndexer testIndexer = new TestIndexer(db.getDbClient(), es.client());
-
-  private WsActionTester ws = new WsActionTester(new CoveredFilesAction(db.getDbClient(), testIndex, userSession));
-
-  @Test
-  public void define_covered_files() {
-    WebService.Action action = ws.getDef();
-    assertThat(action).isNotNull();
-    assertThat(action.isInternal()).isFalse();
-    assertThat(action.isPost()).isFalse();
-    assertThat(action.handler()).isNotNull();
-    assertThat(action.responseExampleAsString()).isNotEmpty();
-    assertThat(action.params()).hasSize(3);
-  }
-
-  @Test
-  public void covered_files() {
-    ComponentDto project = db.components().insertPrivateProject();
-    ComponentDto mainFile1 = db.components().insertComponent(newFileDto(project));
-    ComponentDto mainFile2 = db.components().insertComponent(newFileDto(project));
-    ComponentDto testFile = db.components().insertComponent(newFileDto(project).setQualifier(UNIT_TEST_FILE));
-    userSession.addProjectPermission(CODEVIEWER, project, testFile);
-
-    DbFileSources.Test test = DbFileSources.Test.newBuilder().setUuid(Uuids.create())
-      .addCoveredFile(CoveredFile.newBuilder()
-        .setFileUuid(mainFile1.uuid())
-        .addAllCoveredLine(asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)))
-      .addCoveredFile(CoveredFile.newBuilder()
-        .setFileUuid(mainFile2.uuid())
-        .addAllCoveredLine(asList(1, 2, 3)))
-      .build();
-    insertTests(testFile, test);
-
-    TestRequest request = ws.newRequest().setParam(TEST_ID, test.getUuid());
-
-    assertJson(request.execute().getInput()).isSimilarTo("{\n" +
-      "  \"files\": [\n" +
-      "    {\n" +
-      "      \"id\": \"" + mainFile1.uuid() + "\",\n" +
-      "      \"key\": \"" + mainFile1.getKey() + "\",\n" +
-      "      \"longName\": \"" + mainFile1.longName() + "\",\n" +
-      "      \"coveredLines\": 10\n" +
-      "    },\n" +
-      "    {\n" +
-      "      \"id\": \"" + mainFile2.uuid() + "\",\n" +
-      "      \"key\": \"" + mainFile2.getKey() + "\",\n" +
-      "      \"longName\": \"" + mainFile2.longName() + "\",\n" +
-      "      \"coveredLines\": 3\n" +
-      "    }\n" +
-      "  ]\n" +
-      "}");
-  }
-
-  @Test
-  public void covered_files_on_branch() {
-    ComponentDto project = db.components().insertMainBranch();
-    ComponentDto branch = db.components().insertProjectBranch(project);
-    ComponentDto mainFile = db.components().insertComponent(newFileDto(branch));
-    ComponentDto testFile = db.components().insertComponent(newFileDto(branch).setQualifier(UNIT_TEST_FILE));
-    userSession.addProjectPermission(CODEVIEWER, project, testFile);
-    DbFileSources.Test test = DbFileSources.Test.newBuilder().setUuid(Uuids.create())
-      .addCoveredFile(CoveredFile.newBuilder()
-        .setFileUuid(mainFile.uuid())
-        .addAllCoveredLine(asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)))
-      .build();
-    insertTests(testFile, test);
-
-    TestRequest request = ws.newRequest().setParam(TEST_ID, test.getUuid());
-
-    assertJson(request.execute().getInput()).isSimilarTo("{\n" +
-      "  \"files\": [\n" +
-      "    {\n" +
-      "      \"id\": \"" + mainFile.uuid() + "\",\n" +
-      "      \"key\": \"" + mainFile.getKey() + "\",\n" +
-      "      \"branch\": \"" + mainFile.getBranch() + "\",\n" +
-      "      \"longName\": \"" + mainFile.longName() + "\",\n" +
-      "      \"coveredLines\": 10\n" +
-      "    }\n" +
-      "  ]\n" +
-      "}");
-  }
-
-  @Test
-  public void fail_when_test_uuid_is_unknown() {
-    expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage("Test with id 'unknown' is not found");
-
-    ws.newRequest().setParam(TEST_ID, "unknown").execute();
-  }
-
-  private void insertTests(ComponentDto testFile, DbFileSources.Test... tests) {
-    db.getDbClient().fileSourceDao().insert(db.getSession(), new FileSourceDto()
-      .setProjectUuid(testFile.projectUuid())
-      .setFileUuid(testFile.uuid())
-      .setTestData(asList(tests)));
-    db.commit();
-    testIndexer.indexOnStartup(null);
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/test/ws/ListActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/test/ws/ListActionTest.java
deleted file mode 100644 (file)
index fa31b70..0000000
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.test.ws;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentTesting;
-import org.sonar.db.protobuf.DbFileSources;
-import org.sonar.db.source.FileSourceDto;
-import org.sonar.server.component.TestComponentFinder;
-import org.sonar.server.es.EsTester;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.test.index.TestIndex;
-import org.sonar.server.test.index.TestIndexer;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.TestRequest;
-import org.sonar.server.ws.WsActionTester;
-import org.sonarqube.ws.Tests;
-import org.sonarqube.ws.Tests.ListResponse;
-
-import static java.lang.String.format;
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.tuple;
-import static org.sonar.api.resources.Qualifiers.UNIT_TEST_FILE;
-import static org.sonar.api.web.UserRole.CODEVIEWER;
-import static org.sonar.api.web.UserRole.USER;
-import static org.sonar.db.component.BranchType.PULL_REQUEST;
-import static org.sonar.db.component.ComponentTesting.newFileDto;
-import static org.sonar.db.protobuf.DbFileSources.Test.TestStatus.OK;
-import static org.sonar.server.test.db.TestTesting.newTest;
-import static org.sonar.server.test.ws.ListAction.PARAM_PULL_REQUEST;
-import static org.sonar.server.test.ws.ListAction.SOURCE_FILE_ID;
-import static org.sonar.server.test.ws.ListAction.SOURCE_FILE_KEY;
-import static org.sonar.server.test.ws.ListAction.SOURCE_FILE_LINE_NUMBER;
-import static org.sonar.server.test.ws.ListAction.TEST_FILE_ID;
-import static org.sonar.server.test.ws.ListAction.TEST_FILE_KEY;
-import static org.sonar.server.test.ws.ListAction.TEST_ID;
-
-public class ListActionTest {
-
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-  @Rule
-  public EsTester es = EsTester.create();
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-  @Rule
-  public DbTester db = DbTester.create();
-
-  private DbClient dbClient = db.getDbClient();
-
-  private TestIndex testIndex = new TestIndex(es.client(), System2.INSTANCE);
-  private TestIndexer testIndexer = new TestIndexer(db.getDbClient(), es.client());
-
-  private ComponentDto project;
-  private ComponentDto mainFile;
-  private ComponentDto testFile;
-
-  private WsActionTester ws = new WsActionTester(new ListAction(dbClient, testIndex, userSessionRule, TestComponentFinder.from(db)));
-
-  @Before
-  public void setUp() throws Exception {
-    project = db.components().insertComponent(ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization()));
-    mainFile = db.components().insertComponent(newFileDto(project));
-    testFile = db.components().insertComponent(newFileDto(project).setQualifier(UNIT_TEST_FILE));
-  }
-
-  @Test
-  public void test_definition() {
-    WebService.Action action = ws.getDef();
-    assertThat(action).isNotNull();
-    assertThat(action.isInternal()).isFalse();
-    assertThat(action.isPost()).isFalse();
-    assertThat(action.handler()).isNotNull();
-    assertThat(action.responseExampleAsString()).isNotEmpty();
-    assertThat(action.params()).hasSize(10);
-    assertThat(action.description()).isEqualTo("Get the list of tests either in a test file or that test a given line of source code.<br /> " +
-      "Requires 'Browse' permission on the file's project.<br /> " +
-      "One (and only one) of the following combination of parameters must be provided: " +
-      "<ul>" +
-      "<li>testId - get a specific test</li>" +
-      "<li>testFileId - get the tests in a test file</li>" +
-      "<li>testFileKey - get the tests in a test file</li>" +
-      "<li>sourceFileId and sourceFileLineNumber - get the tests that cover a specific line of code</li>" +
-      "<li>sourceFileKey and sourceFileLineNumber - get the tests that cover a specific line of code</li>" +
-      "</ul>");
-  }
-
-  @Test
-  public void list_tests() {
-    userSessionRule.addProjectPermission(CODEVIEWER, project);
-    DbFileSources.Test test = newTest(mainFile, 10, 11, 12, 20, 21, 25).setStatus(OK).build();
-    insertTests(testFile, test);
-
-    ListResponse request = call(ws.newRequest().setParam(TEST_ID, test.getUuid()));
-
-    assertThat(request.getTestsList()).hasSize(1);
-    Tests.Test result = request.getTests(0);
-    assertThat(result.getId()).isEqualTo(test.getUuid());
-    assertThat(result.getName()).isEqualTo(test.getName());
-    assertThat(result.getStatus()).isEqualTo(Tests.TestStatus.OK);
-    assertThat(result.getFileId()).isEqualTo(testFile.uuid());
-    assertThat(result.getFileKey()).isEqualTo(testFile.getDbKey());
-    assertThat(result.getFileName()).isEqualTo(testFile.path());
-    assertThat(result.getDurationInMs()).isEqualTo(test.getExecutionTimeMs());
-    assertThat(result.getMessage()).isEqualTo(test.getMsg());
-    assertThat(result.getStacktrace()).isEqualTo(test.getStacktrace());
-    assertThat(result.getCoveredLines()).isEqualTo(6);
-  }
-
-  @Test
-  public void list_tests_by_test_uuid() {
-    userSessionRule.addProjectPermission(CODEVIEWER, project);
-    DbFileSources.Test test1 = newTest(mainFile, 10).build();
-    DbFileSources.Test test2 = newTest(mainFile, 11).build();
-    insertTests(testFile, test1, test2);
-
-    ListResponse request = call(ws.newRequest()
-      .setParam(TEST_ID, test1.getUuid()));
-
-    assertThat(request.getTestsList())
-      .extracting(Tests.Test::getId)
-      .containsOnly(test1.getUuid());
-  }
-
-  @Test
-  public void list_tests_by_test_file_uuid() {
-    userSessionRule.addProjectPermission(CODEVIEWER, project);
-    ComponentDto anotherTestFile = db.components().insertComponent(newFileDto(project));
-    DbFileSources.Test test1 = newTest(mainFile, 10).build();
-    DbFileSources.Test test2 = newTest(mainFile, 11).build();
-    DbFileSources.Test test3 = newTest(mainFile, 12).build();
-    insertTests(testFile, test1, test2);
-    insertTests(anotherTestFile, test3);
-
-    ListResponse request = call(ws.newRequest()
-      .setParam(TEST_FILE_ID, testFile.uuid()));
-
-    assertThat(request.getTestsList())
-      .extracting(Tests.Test::getId)
-      .containsOnly(test1.getUuid(), test2.getUuid());
-  }
-
-  @Test
-  public void list_tests_by_test_file_key() {
-    userSessionRule.addProjectPermission(CODEVIEWER, project);
-    ComponentDto anotherTestFile = db.components().insertComponent(newFileDto(project));
-    DbFileSources.Test test1 = newTest(mainFile, 10).build();
-    DbFileSources.Test test2 = newTest(mainFile, 11).build();
-    DbFileSources.Test test3 = newTest(mainFile, 12).build();
-    insertTests(testFile, test1, test2);
-    insertTests(anotherTestFile, test3);
-
-    ListResponse request = call(ws.newRequest()
-      .setParam(TEST_FILE_KEY, testFile.getDbKey()));
-
-    assertThat(request.getTestsList())
-      .extracting(Tests.Test::getId)
-      .containsOnly(test1.getUuid(), test2.getUuid());
-  }
-
-  @Test
-  public void list_tests_by_test_file_key_and_branch() {
-    ComponentDto project = db.components().insertMainBranch();
-    userSessionRule.addProjectPermission(CODEVIEWER, project);
-    ComponentDto branch = db.components().insertProjectBranch(project);
-    ComponentDto mainFile = db.components().insertComponent(newFileDto(branch));
-    ComponentDto testFile = db.components().insertComponent(newFileDto(branch).setQualifier(UNIT_TEST_FILE));
-
-    DbFileSources.Test test1 = newTest(mainFile, 10).build();
-    DbFileSources.Test test2 = newTest(mainFile, 11).build();
-    insertTests(testFile, test1, test2);
-
-    ListResponse request = call(ws.newRequest()
-      .setParam(TEST_FILE_KEY, testFile.getKey())
-      .setParam("branch", testFile.getBranch()));
-
-    assertThat(request.getTestsList())
-      .extracting(Tests.Test::getId, Tests.Test::getFileKey, Tests.Test::getFileBranch)
-      .containsOnly(
-        tuple(test1.getUuid(), testFile.getKey(), testFile.getBranch()),
-        tuple(test2.getUuid(), testFile.getKey(), testFile.getBranch()));
-  }
-
-  @Test
-  public void list_tests_by_test_file_key_and_pull_request() {
-    ComponentDto project = db.components().insertMainBranch();
-    userSessionRule.addProjectPermission(CODEVIEWER, project);
-    ComponentDto pullRequest = db.components().insertProjectBranch(project, b -> b.setBranchType(PULL_REQUEST));
-    ComponentDto mainFile = db.components().insertComponent(newFileDto(pullRequest));
-    ComponentDto testFile = db.components().insertComponent(newFileDto(pullRequest).setQualifier(UNIT_TEST_FILE));
-
-    DbFileSources.Test test1 = newTest(mainFile, 10).build();
-    DbFileSources.Test test2 = newTest(mainFile, 11).build();
-    insertTests(testFile, test1, test2);
-
-    ListResponse request = call(ws.newRequest()
-      .setParam(TEST_FILE_KEY, testFile.getKey())
-      .setParam(PARAM_PULL_REQUEST, testFile.getPullRequest()));
-
-    assertThat(request.getTestsList())
-      .extracting(Tests.Test::getId, Tests.Test::getFileKey, Tests.Test::getFilePullRequest)
-      .containsOnly(
-        tuple(test1.getUuid(), testFile.getKey(), testFile.getPullRequest()),
-        tuple(test2.getUuid(), testFile.getKey(), testFile.getPullRequest()));
-  }
-
-  @Test
-  public void list_tests_by_source_file_uuid_and_line_number() {
-    userSessionRule.addProjectPermission(CODEVIEWER, project);
-    ComponentDto anotherMainFile = db.components().insertComponent(newFileDto(project));
-    DbFileSources.Test test1 = newTest(mainFile, 10, 11, 12).build();
-    DbFileSources.Test test2 = newTest(mainFile, 9, 11).build();
-    DbFileSources.Test test3 = newTest(mainFile, 10, 12).build();
-    DbFileSources.Test test4 = newTest(anotherMainFile, 11).build();
-    insertTests(testFile, test1, test2, test3, test4);
-
-    ListResponse request = call(ws.newRequest()
-      .setParam(SOURCE_FILE_ID, mainFile.uuid())
-      .setParam(SOURCE_FILE_LINE_NUMBER, "11"));
-
-    assertThat(request.getTestsList()).extracting(Tests.Test::getId).containsOnly(test1.getUuid(), test2.getUuid());
-  }
-
-  @Test
-  public void list_tests_by_source_file_key_and_line_number() {
-    userSessionRule.addProjectPermission(CODEVIEWER, project);
-    ComponentDto anotherMainFile = db.components().insertComponent(newFileDto(project));
-    DbFileSources.Test test1 = newTest(mainFile, 10, 11, 12).build();
-    DbFileSources.Test test2 = newTest(mainFile, 9, 11).build();
-    DbFileSources.Test test3 = newTest(mainFile, 10, 12).build();
-    DbFileSources.Test test4 = newTest(anotherMainFile, 11).build();
-    insertTests(testFile, test1, test2, test3, test4);
-
-    ListResponse request = call(ws.newRequest()
-      .setParam(SOURCE_FILE_KEY, mainFile.getDbKey())
-      .setParam(SOURCE_FILE_LINE_NUMBER, "10"));
-
-    assertThat(request.getTestsList())
-      .extracting(Tests.Test::getId)
-      .containsOnly(test1.getUuid(), test3.getUuid());
-  }
-
-  @Test
-  public void list_tests_by_source_file_key_and_branch_and_line_number() {
-    ComponentDto project = db.components().insertMainBranch();
-    userSessionRule.addProjectPermission(CODEVIEWER, project);
-    ComponentDto branch = db.components().insertProjectBranch(project);
-    ComponentDto mainFile = db.components().insertComponent(newFileDto(branch));
-    ComponentDto testFile = db.components().insertComponent(newFileDto(branch).setQualifier(UNIT_TEST_FILE));
-    DbFileSources.Test test1 = newTest(mainFile, 10, 11, 12).build();
-    DbFileSources.Test test2 = newTest(mainFile, 9, 11).build();
-    DbFileSources.Test test3 = newTest(mainFile, 10, 12).build();
-    insertTests(testFile, test1, test2, test3);
-
-    ListResponse request = call(ws.newRequest()
-      .setParam(SOURCE_FILE_KEY, mainFile.getKey())
-      .setParam(SOURCE_FILE_LINE_NUMBER, "10")
-      .setParam("branch", testFile.getBranch()));
-
-    assertThat(request.getTestsList())
-      .extracting(Tests.Test::getId, Tests.Test::getFileKey, Tests.Test::getFileBranch)
-      .containsOnly(
-        tuple(test1.getUuid(), testFile.getKey(), testFile.getBranch()),
-        tuple(test3.getUuid(), testFile.getKey(), testFile.getBranch()));
-  }
-
-  @Test
-  public void tests_are_paginated() {
-    userSessionRule.addProjectPermission(CODEVIEWER, project);
-    insertTests(testFile, newTest(mainFile, 10).build(), newTest(mainFile, 11).build(), newTest(mainFile, 12).build());
-
-    ListResponse request = call(ws.newRequest().setParam(TEST_FILE_ID, testFile.uuid()));
-
-    assertThat(request.getPaging().getPageIndex()).isEqualTo(1);
-    assertThat(request.getPaging().getPageSize()).isEqualTo(100);
-    assertThat(request.getPaging().getTotal()).isEqualTo(3);
-  }
-
-  @Test
-  public void fail_when_no_argument() {
-    userSessionRule.addProjectPermission(CODEVIEWER, project);
-
-    expectedException.expect(IllegalArgumentException.class);
-    call(ws.newRequest());
-  }
-
-  @Test
-  public void fail_when_source_file_uuid_without_line_number() {
-    userSessionRule.addProjectPermission(CODEVIEWER, project);
-
-    expectedException.expect(IllegalArgumentException.class);
-    call(ws.newRequest().setParam(SOURCE_FILE_ID, mainFile.uuid()));
-  }
-
-  @Test
-  public void fail_when_not_enough_privilege_on_test_uuid() {
-    userSessionRule.addProjectPermission(USER, project);
-    DbFileSources.Test test = newTest(mainFile, 10).build();
-    insertTests(testFile, test);
-
-    expectedException.expect(ForbiddenException.class);
-    call(ws.newRequest().setParam(TEST_ID, test.getUuid()));
-  }
-
-  @Test
-  public void fail_when_no_enough_privilege_on_test_file_id() {
-    userSessionRule.addProjectPermission(USER, project);
-    insertTests(testFile, newTest(mainFile, 10).build());
-
-    expectedException.expect(ForbiddenException.class);
-    call(ws.newRequest().setParam(TEST_FILE_ID, testFile.uuid()));
-  }
-
-  @Test
-  public void fail_when_not_enough_privilege_on_test_file_key() {
-    userSessionRule.addProjectPermission(USER, project);
-    insertTests(testFile, newTest(mainFile, 10).build());
-
-    expectedException.expect(ForbiddenException.class);
-    call(ws.newRequest().setParam(TEST_FILE_KEY, testFile.getDbKey()));
-  }
-
-  @Test
-  public void fail_when_not_enough_privilege_on_main_file_uuid() {
-    userSessionRule.addProjectPermission(USER, project);
-    insertTests(testFile, newTest(mainFile, 10).build());
-
-    expectedException.expect(ForbiddenException.class);
-    call(ws.newRequest().setParam(SOURCE_FILE_ID, mainFile.uuid()).setParam(SOURCE_FILE_LINE_NUMBER, "10"));
-  }
-
-  @Test
-  public void fail_when_test_uuid_is_unknown() {
-    expectedException.expect(NotFoundException.class);
-    call(ws.newRequest().setParam(TEST_ID, "unknown"));
-  }
-
-  @Test
-  public void fail_when_test_file_id_is_unknown() {
-    expectedException.expect(NotFoundException.class);
-    call(ws.newRequest().setParam(TEST_FILE_ID, "unknown"));
-  }
-
-  @Test
-  public void fail_when_test_file_key_is_unknown() {
-    expectedException.expect(NotFoundException.class);
-    call(ws.newRequest().setParam(TEST_FILE_KEY, "unknown"));
-  }
-
-  @Test
-  public void fail_when_test_branch_is_unknown() {
-    ComponentDto project = db.components().insertMainBranch();
-    userSessionRule.addProjectPermission(CODEVIEWER, project);
-    ComponentDto branch = db.components().insertProjectBranch(project);
-    ComponentDto testFile = db.components().insertComponent(newFileDto(branch).setQualifier(UNIT_TEST_FILE));
-
-    expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage(format("Component '%s' on branch 'unknown' not found", testFile.getKey()));
-
-    call(ws.newRequest()
-      .setParam(TEST_FILE_KEY, testFile.getKey())
-      .setParam("branch", "unknown"));
-  }
-
-  @Test
-  public void fail_when_source_file_id_is_unknown() {
-    expectedException.expect(NotFoundException.class);
-    call(ws.newRequest().setParam(SOURCE_FILE_ID, "unknown").setParam(SOURCE_FILE_LINE_NUMBER, "10"));
-  }
-
-  @Test
-  public void fail_when_source_file_key_is_unknown() {
-    expectedException.expect(NotFoundException.class);
-    call(ws.newRequest().setParam(SOURCE_FILE_KEY, "unknown").setParam(SOURCE_FILE_LINE_NUMBER, "10"));
-  }
-
-  @Test
-  public void fail_when_source_branch_is_unknown() {
-    ComponentDto project = db.components().insertMainBranch();
-    userSessionRule.addProjectPermission(CODEVIEWER, project);
-    ComponentDto branch = db.components().insertProjectBranch(project);
-    ComponentDto mainFile = db.components().insertComponent(newFileDto(branch));
-
-    expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage(format("Component '%s' on branch 'unknown' not found", mainFile.getKey()));
-
-    call(ws.newRequest()
-      .setParam(SOURCE_FILE_KEY, mainFile.getKey())
-      .setParam("branch", "unknown")
-      .setParam(SOURCE_FILE_LINE_NUMBER, "10"));
-  }
-
-  private void insertTests(ComponentDto testFile, DbFileSources.Test... tests) {
-    db.getDbClient().fileSourceDao().insert(db.getSession(), new FileSourceDto()
-      .setProjectUuid(testFile.projectUuid())
-      .setFileUuid(testFile.uuid())
-      .setTestData(asList(tests)));
-    db.commit();
-    testIndexer.indexOnStartup(null);
-  }
-
-  private static ListResponse call(TestRequest request) {
-    return request
-      .executeProtobuf(ListResponse.class);
-  }
-
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/test/ws/CoveredFilesActionTest/tests-covered-files.json b/server/sonar-server/src/test/resources/org/sonar/server/test/ws/CoveredFilesActionTest/tests-covered-files.json
deleted file mode 100644 (file)
index 9a0dbd4..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "files": [
-    {
-      "id": "FILE1",
-      "key": "org.foo.Bar.java",
-      "longName": "src/main/java/org/foo/Bar.java",
-      "coveredLines": 10
-    },
-    {
-      "id": "FILE2",
-      "key": "org.foo.File.java",
-      "longName": "src/main/java/org/foo/File.java",
-      "coveredLines": 3
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/test/ws/ListActionTest/list-main-file.json b/server/sonar-server/src/test/resources/org/sonar/server/test/ws/ListActionTest/list-main-file.json
deleted file mode 100644 (file)
index d3f146c..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-{
-  "paging": {
-    "pageIndex": 1,
-    "pageSize": 100,
-    "total": 2
-  },
-  "tests": [
-    {
-      "id": "TEST-UUID-1",
-      "name": "test1",
-      "status": "OK",
-      "fileId": "ABCD",
-      "fileKey": "org.foo.BarTest.java",
-      "fileName": "src/test/java/org/foo/BarTest.java",
-      "durationInMs": 10,
-      "coveredLines": 4,
-      "message": "MESSAGE-1",
-      "stacktrace": "STACKTRACE-1"
-    },
-    {
-      "id": "TEST-UUID-2",
-      "name": "test2",
-      "status": "ERROR",
-      "fileId": "BCDE",
-      "fileKey": "org.foo.FileTest.java",
-      "fileName": "src/test/java/org/foo/FileTest.java",
-      "durationInMs": 97,
-      "coveredLines": 4,
-      "message": "MESSAGE-2",
-      "stacktrace": "STACKTRACE-2"
-
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/test/ws/ListActionTest/list-test-uuid.json b/server/sonar-server/src/test/resources/org/sonar/server/test/ws/ListActionTest/list-test-uuid.json
deleted file mode 100644 (file)
index 07b6072..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "tests": [
-    {
-      "id": "TEST-UUID-1",
-      "name": "test1",
-      "status": "OK",
-      "fileId": "ABCD",
-      "fileKey": "org.foo.BarTest.java",
-      "fileName": "src/test/java/org/foo/BarTest.java",
-      "durationInMs": 10,
-      "coveredLines": 4,
-      "message": "MESSAGE-1",
-      "stacktrace": "STACKTRACE-1"
-    }
-  ]
-}
index 5f15ca7bd3192b628ef7fe4ddf28cf9fbfe838e1..202c36149dbcfd15b57f152c8420905e7dd5e34f 100644 (file)
@@ -21,7 +21,6 @@ package org.sonar.scanner.mediumtest;
 
 import com.google.common.collect.Iterators;
 import com.google.common.collect.Lists;
-import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -29,7 +28,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import javax.annotation.CheckForNull;
-import org.apache.commons.io.FileUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.batch.fs.InputComponent;
@@ -254,38 +252,6 @@ public class AnalysisResult implements AnalysisObserver {
     return null;
   }
 
-  public ScannerReport.Test firstTestExecutionForName(InputFile testFile, String testName) {
-    int ref = ((DefaultInputComponent) testFile).scannerId();
-    try (InputStream inputStream = FileUtils.openInputStream(getReportReader().readTests(ref))) {
-      ScannerReport.Test test = ScannerReport.Test.parser().parseDelimitedFrom(inputStream);
-      while (test != null) {
-        if (test.getName().equals(testName)) {
-          return test;
-        }
-        test = ScannerReport.Test.parser().parseDelimitedFrom(inputStream);
-      }
-    } catch (Exception e) {
-      throw new IllegalStateException(e);
-    }
-    return null;
-  }
-
-  public ScannerReport.CoverageDetail coveragePerTestFor(InputFile testFile, String testName) {
-    int ref = ((DefaultInputComponent) testFile).scannerId();
-    try (InputStream inputStream = FileUtils.openInputStream(getReportReader().readCoverageDetails(ref))) {
-      ScannerReport.CoverageDetail details = ScannerReport.CoverageDetail.parser().parseDelimitedFrom(inputStream);
-      while (details != null) {
-        if (details.getTestName().equals(testName)) {
-          return details;
-        }
-        details = ScannerReport.CoverageDetail.parser().parseDelimitedFrom(inputStream);
-      }
-    } catch (Exception e) {
-      throw new IllegalStateException(e);
-    }
-    return null;
-  }
-
   public List<ScannerReport.AdHocRule> adHocRules() {
     List<ScannerReport.AdHocRule> result = new ArrayList<>();
     try (CloseableIterator<ScannerReport.AdHocRule> it = getReportReader().readAdHocRules()) {
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/TestExecutionAndCoveragePublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/TestExecutionAndCoveragePublisher.java
deleted file mode 100644 (file)
index 1b15ec2..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.scanner.report;
-
-import com.google.common.collect.Iterables;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.stream.StreamSupport;
-import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputComponent;
-import org.sonar.api.test.CoverageBlock;
-import org.sonar.api.test.MutableTestCase;
-import org.sonar.api.test.MutableTestPlan;
-import org.sonar.api.test.TestCase;
-import org.sonar.scanner.deprecated.test.DefaultTestable;
-import org.sonar.scanner.deprecated.test.TestPlanBuilder;
-import org.sonar.scanner.protocol.output.ScannerReport;
-import org.sonar.scanner.protocol.output.ScannerReport.CoverageDetail;
-import org.sonar.scanner.protocol.output.ScannerReport.Test;
-import org.sonar.scanner.protocol.output.ScannerReport.Test.TestStatus;
-import org.sonar.scanner.protocol.output.ScannerReportWriter;
-import org.sonar.scanner.scan.branch.BranchConfiguration;
-import org.sonar.scanner.scan.filesystem.InputComponentStore;
-
-import static java.util.stream.Collectors.toList;
-
-public class TestExecutionAndCoveragePublisher implements ReportPublisherStep {
-
-  private final InputComponentStore componentStore;
-  private final TestPlanBuilder testPlanBuilder;
-  private final BranchConfiguration branchConfiguration;
-
-  public TestExecutionAndCoveragePublisher(InputComponentStore componentStore, TestPlanBuilder testPlanBuilder, BranchConfiguration branchConfiguration) {
-    this.componentStore = componentStore;
-    this.testPlanBuilder = testPlanBuilder;
-    this.branchConfiguration = branchConfiguration;
-  }
-
-  @Override
-  public void publish(ScannerReportWriter writer) {
-    if (branchConfiguration.isShortOrPullRequest()) {
-      return;
-    }
-    final ScannerReport.Test.Builder testBuilder = ScannerReport.Test.newBuilder();
-    final ScannerReport.CoverageDetail.Builder builder = ScannerReport.CoverageDetail.newBuilder();
-    final ScannerReport.CoverageDetail.CoveredFile.Builder coveredBuilder = ScannerReport.CoverageDetail.CoveredFile.newBuilder();
-    for (final InputComponent c : componentStore.all()) {
-      DefaultInputComponent component = (DefaultInputComponent) c;
-      final MutableTestPlan testPlan = testPlanBuilder.loadPerspective(MutableTestPlan.class, component);
-      if (testPlan == null || Iterables.isEmpty(testPlan.testCases())) {
-        continue;
-      }
-
-      final Set<String> testNamesWithCoverage = new HashSet<>();
-
-      writer.writeTests(component.scannerId(),
-        StreamSupport.stream(testPlan.testCases().spliterator(), false)
-          .map(testCase -> toProtobufTest(testBuilder, testNamesWithCoverage, testCase))
-          .collect(toList()));
-
-      writer.writeCoverageDetails(component.scannerId(), testNamesWithCoverage.stream()
-        .map(testName -> toProtobufCoverageDetails(builder, coveredBuilder, testPlan, testName))
-        .collect(toList()));
-    }
-  }
-
-  private CoverageDetail toProtobufCoverageDetails(final ScannerReport.CoverageDetail.Builder builder, final ScannerReport.CoverageDetail.CoveredFile.Builder coveredBuilder,
-    final MutableTestPlan testPlan, String testName) {
-    // Take first test with provided name
-    MutableTestCase testCase = testPlan.testCasesByName(testName).iterator().next();
-    builder.clear();
-    builder.setTestName(testName);
-    for (CoverageBlock block : testCase.coverageBlocks()) {
-      coveredBuilder.clear();
-      DefaultInputComponent c = (DefaultInputComponent) componentStore.getByKey(((DefaultTestable) block.testable()).inputFile().key());
-      coveredBuilder.setFileRef(c.scannerId());
-      for (int line : block.lines()) {
-        coveredBuilder.addCoveredLine(line);
-      }
-      builder.addCoveredFile(coveredBuilder.build());
-    }
-    return builder.build();
-  }
-
-  private static Test toProtobufTest(final ScannerReport.Test.Builder testBuilder, final Set<String> testNamesWithCoverage, MutableTestCase testCase) {
-    testBuilder.clear();
-    testBuilder.setName(testCase.name());
-    if (testCase.doesCover()) {
-      testNamesWithCoverage.add(testCase.name());
-    }
-    Long durationInMs = testCase.durationInMs();
-    if (durationInMs != null) {
-      testBuilder.setDurationInMs(durationInMs.longValue());
-    }
-    String msg = testCase.message();
-    if (msg != null) {
-      testBuilder.setMsg(msg);
-    }
-    String stack = testCase.stackTrace();
-    if (stack != null) {
-      testBuilder.setStacktrace(stack);
-    }
-    TestCase.Status status = testCase.status();
-    if (status != null) {
-      testBuilder.setStatus(TestStatus.valueOf(status.name()));
-    }
-    return testBuilder.build();
-  }
-}
index 26b6ffa807952b9979e95919f78e3f1d63ab56ee..049d49cdc04f77a0d26dd661d09301af36c52d8d 100644 (file)
@@ -80,7 +80,6 @@ import org.sonar.scanner.report.MeasuresPublisher;
 import org.sonar.scanner.report.MetadataPublisher;
 import org.sonar.scanner.report.ReportPublisher;
 import org.sonar.scanner.report.SourcePublisher;
-import org.sonar.scanner.report.TestExecutionAndCoveragePublisher;
 import org.sonar.scanner.repository.ContextPropertiesCache;
 import org.sonar.scanner.repository.DefaultProjectRepositoriesLoader;
 import org.sonar.scanner.repository.DefaultQualityProfileLoader;
@@ -294,8 +293,7 @@ public class ProjectScanContainer extends ComponentContainer {
       MeasuresPublisher.class,
       CoveragePublisher.class,
       SourcePublisher.class,
-      ChangedLinesPublisher.class,
-      TestExecutionAndCoveragePublisher.class);
+      ChangedLinesPublisher.class);
   }
 
   private void addIssueTrackingComponents() {
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/tests/CoveragePerTestMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/tests/CoveragePerTestMediumTest.java
deleted file mode 100644 (file)
index 20f5fbc..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.scanner.mediumtest.tests;
-
-import com.google.common.collect.ImmutableMap;
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import org.apache.commons.io.FileUtils;
-import org.hamcrest.Description;
-import org.hamcrest.TypeSafeMatcher;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.scanner.mediumtest.ScannerMediumTester;
-import org.sonar.scanner.mediumtest.AnalysisResult;
-import org.sonar.xoo.XooPlugin;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class CoveragePerTestMediumTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Rule
-  public ExpectedException exception = ExpectedException.none();
-
-  @Rule
-  public ScannerMediumTester tester = new ScannerMediumTester()
-    .registerPlugin("xoo", new XooPlugin())
-    .addDefaultQProfile("xoo", "Sonar Way");
-
-  @Test
-  // SONAR-6183
-  public void invalidCoverage() throws IOException {
-    File baseDir = createTestFiles();
-    File srcDir = new File(baseDir, "src");
-
-    File coverageFile = new File(srcDir, "sample.xoo.coverage");
-    FileUtils.write(coverageFile, "0:2\n", StandardCharsets.UTF_8);
-
-    exception.expect(IllegalStateException.class);
-    exception.expectMessage("Error processing line 1 of file");
-    exception.expectCause(new TypeSafeMatcher<Throwable>() {
-
-      @Override
-      public void describeTo(Description description) {
-        // nothing to do
-      }
-
-      @Override
-      protected boolean matchesSafely(Throwable item) {
-        return item.getMessage().contains("Line number must be strictly positive");
-      }
-    });
-    runTask(baseDir);
-
-  }
-
-  @Test
-  public void coveragePerTestInReport() throws IOException {
-    File baseDir = createTestFiles();
-    File testDir = new File(baseDir, "test");
-
-    File xooTestExecutionFile = new File(testDir, "sampleTest.xoo.test");
-    FileUtils.write(xooTestExecutionFile, "some test:4:::OK:UNIT\n" +
-      "another test:10:::OK:UNIT\n" +
-      "test without coverage:10:::OK:UNIT\n", StandardCharsets.UTF_8);
-
-    File xooCoveragePerTestFile = new File(testDir, "sampleTest.xoo.testcoverage");
-    FileUtils.write(xooCoveragePerTestFile, "some test;src/sample.xoo,10,11;src/sample2.xoo,1,2\n" +
-      "another test;src/sample.xoo,10,20\n", StandardCharsets.UTF_8);
-
-    AnalysisResult result = runTask(baseDir);
-
-    InputFile file = result.inputFile("test/sampleTest.xoo");
-    org.sonar.scanner.protocol.output.ScannerReport.CoverageDetail someTest = result.coveragePerTestFor(file, "some test");
-    assertThat(someTest.getCoveredFileList()).hasSize(2);
-    assertThat(someTest.getCoveredFile(0).getFileRef()).isGreaterThan(0);
-    assertThat(someTest.getCoveredFile(0).getCoveredLineList()).containsExactly(10, 11);
-    assertThat(someTest.getCoveredFile(1).getFileRef()).isGreaterThan(0);
-    assertThat(someTest.getCoveredFile(1).getCoveredLineList()).containsExactly(1, 2);
-
-    org.sonar.scanner.protocol.output.ScannerReport.CoverageDetail anotherTest = result.coveragePerTestFor(file, "another test");
-    assertThat(anotherTest.getCoveredFileList()).hasSize(1);
-    assertThat(anotherTest.getCoveredFile(0).getFileRef()).isGreaterThan(0);
-    assertThat(anotherTest.getCoveredFile(0).getCoveredLineList()).containsExactly(10, 20);
-  }
-
-  private AnalysisResult runTask(File baseDir) {
-    return tester.newAnalysis()
-      .properties(ImmutableMap.<String, String>builder()
-        .put("sonar.task", "scan")
-        .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
-        .put("sonar.projectKey", "com.foo.project")
-        .put("sonar.projectName", "Foo Project")
-        .put("sonar.projectVersion", "1.0-SNAPSHOT")
-        .put("sonar.projectDescription", "Description of Foo Project")
-        .put("sonar.sources", "src")
-        .put("sonar.tests", "test")
-        .build())
-      .execute();
-  }
-
-  private File createTestFiles() throws IOException {
-    File baseDir = temp.getRoot();
-    File srcDir = new File(baseDir, "src");
-    srcDir.mkdir();
-    File testDir = new File(baseDir, "test");
-    testDir.mkdir();
-
-    File xooFile = new File(srcDir, "sample.xoo");
-    FileUtils.write(xooFile, "foo", StandardCharsets.UTF_8);
-
-    File xooFile2 = new File(srcDir, "sample2.xoo");
-    FileUtils.write(xooFile2, "foo", StandardCharsets.UTF_8);
-
-    File xooTestFile = new File(testDir, "sampleTest.xoo");
-    FileUtils.write(xooTestFile, "failure\nerror\nok\nskipped", StandardCharsets.UTF_8);
-
-    File xooTestFile2 = new File(testDir, "sample2Test.xoo");
-    FileUtils.write(xooTestFile2, "test file tests", StandardCharsets.UTF_8);
-
-    return baseDir;
-  }
-
-}
index c2bbe13c732ad17b9de066dfcf574292f3557ede..d19a51ad670c91cad21a2e8dbe5db0535515e2e5 100644 (file)
  */
 package org.sonar.scanner.mediumtest.tests;
 
-import com.google.common.collect.ImmutableMap;
 import java.io.File;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
-import org.apache.commons.io.FileUtils;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.measures.CoreMetrics;
-import org.sonar.scanner.mediumtest.ScannerMediumTester;
 import org.sonar.scanner.mediumtest.AnalysisResult;
-import org.sonar.scanner.protocol.output.ScannerReport;
-import org.sonar.scanner.protocol.output.ScannerReport.Test.TestStatus;
+import org.sonar.scanner.mediumtest.ScannerMediumTester;
 import org.sonar.xoo.XooPlugin;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -43,63 +36,13 @@ import static org.assertj.core.api.Assertions.tuple;
 public class GenericTestExecutionMediumTest {
   private final List<String> logs = new ArrayList<>();
 
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
   @Rule
   public ScannerMediumTester tester = new ScannerMediumTester()
     .registerPlugin("xoo", new XooPlugin())
     .addDefaultQProfile("xoo", "Sonar Way");
 
   @Test
-  public void unitTests() throws IOException {
-
-    File baseDir = temp.getRoot();
-    File srcDir = new File(baseDir, "src");
-    srcDir.mkdir();
-    File testDir = new File(baseDir, "test");
-    testDir.mkdir();
-
-    File xooFile = new File(srcDir, "sample.xoo");
-    FileUtils.write(xooFile, "foo", StandardCharsets.UTF_8);
-
-    File xooTestFile = new File(testDir, "sampleTest.xoo");
-    FileUtils.write(xooTestFile, "failure\nerror\nok\nskipped", StandardCharsets.UTF_8);
-
-    File xooTestExecutionFile = new File(testDir, "sampleTest.xoo.test");
-    FileUtils.write(xooTestExecutionFile, "skipped::::SKIPPED:UNIT\n" +
-      "failure:2:Failure::FAILURE:UNIT\n" +
-      "error:2:Error:The stack:ERROR:UNIT\n" +
-      "success:4:::OK:INTEGRATION", StandardCharsets.UTF_8);
-
-    AnalysisResult result = tester
-      .newAnalysis()
-      .properties(ImmutableMap.<String, String>builder()
-        .put("sonar.task", "scan")
-        .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
-        .put("sonar.projectKey", "com.foo.project")
-        .put("sonar.projectName", "Foo Project")
-        .put("sonar.projectVersion", "1.0-SNAPSHOT")
-        .put("sonar.projectDescription", "Description of Foo Project")
-        .put("sonar.sources", "src")
-        .put("sonar.tests", "test")
-        .build())
-      .execute();
-
-    InputFile file = result.inputFile("test/sampleTest.xoo");
-    org.sonar.scanner.protocol.output.ScannerReport.Test success = result.firstTestExecutionForName(file, "success");
-    assertThat(success.getDurationInMs()).isEqualTo(4);
-    assertThat(success.getStatus()).isEqualTo(TestStatus.OK);
-
-    org.sonar.scanner.protocol.output.ScannerReport.Test error = result.firstTestExecutionForName(file, "error");
-    assertThat(error.getDurationInMs()).isEqualTo(2);
-    assertThat(error.getStatus()).isEqualTo(TestStatus.ERROR);
-    assertThat(error.getMsg()).isEqualTo("Error");
-    assertThat(error.getStacktrace()).isEqualTo("The stack");
-  }
-
-  @Test
-  public void singleReport() throws IOException {
+  public void singleReport() {
 
     File projectDir = new File("test-resources/mediumtest/xoo/sample-generic-test-exec");
 
@@ -110,28 +53,6 @@ public class GenericTestExecutionMediumTest {
       .execute();
 
     InputFile testFile = result.inputFile("testx/ClassOneTest.xoo");
-    ScannerReport.Test success = result.firstTestExecutionForName(testFile, "test1");
-    assertThat(success.getDurationInMs()).isEqualTo(5);
-    assertThat(success.getStatus()).isEqualTo(TestStatus.OK);
-
-    ScannerReport.Test skipped = result.firstTestExecutionForName(testFile, "test2");
-    assertThat(skipped.getDurationInMs()).isEqualTo(500);
-    assertThat(skipped.getStatus()).isEqualTo(TestStatus.SKIPPED);
-    assertThat(skipped.getMsg()).isEqualTo("short message");
-    assertThat(skipped.getStacktrace()).isEqualTo("other");
-
-    ScannerReport.Test failed = result.firstTestExecutionForName(testFile, "test3");
-    assertThat(failed.getDurationInMs()).isEqualTo(100);
-    assertThat(failed.getStatus()).isEqualTo(TestStatus.FAILURE);
-    assertThat(failed.getMsg()).isEqualTo("short");
-    assertThat(failed.getStacktrace()).isEqualTo("stacktrace");
-
-    ScannerReport.Test error = result.firstTestExecutionForName(testFile, "test4");
-    assertThat(error.getDurationInMs()).isEqualTo(500);
-    assertThat(error.getStatus()).isEqualTo(TestStatus.ERROR);
-    assertThat(error.getMsg()).isEqualTo("short");
-    assertThat(error.getStacktrace()).isEqualTo("stacktrace");
-
     assertThat(result.allMeasures().get(testFile.key())).extracting("metricKey", "intValue.value", "longValue.value")
       .containsOnly(
         tuple(CoreMetrics.TESTS_KEY, 3, 0L),
@@ -139,12 +60,12 @@ public class GenericTestExecutionMediumTest {
         tuple(CoreMetrics.TEST_ERRORS_KEY, 1, 0L),
         tuple(CoreMetrics.TEST_EXECUTION_TIME_KEY, 0, 1105L),
         tuple(CoreMetrics.TEST_FAILURES_KEY, 1, 0L));
-    
+
     assertThat(logs).noneMatch(l -> l.contains("Please use 'sonar.testExecutionReportPaths'"));
   }
 
   @Test
-  public void twoReports() throws IOException {
+  public void twoReports() {
 
     File projectDir = new File("test-resources/mediumtest/xoo/sample-generic-test-exec");
 
@@ -155,32 +76,6 @@ public class GenericTestExecutionMediumTest {
       .execute();
 
     InputFile testFile = result.inputFile("testx/ClassOneTest.xoo");
-    ScannerReport.Test success = result.firstTestExecutionForName(testFile, "test1");
-    assertThat(success.getDurationInMs()).isEqualTo(5);
-    assertThat(success.getStatus()).isEqualTo(TestStatus.OK);
-
-    ScannerReport.Test success2 = result.firstTestExecutionForName(testFile, "test1b");
-    assertThat(success2.getDurationInMs()).isEqualTo(5);
-    assertThat(success2.getStatus()).isEqualTo(TestStatus.OK);
-
-    ScannerReport.Test skipped = result.firstTestExecutionForName(testFile, "test2");
-    assertThat(skipped.getDurationInMs()).isEqualTo(500);
-    assertThat(skipped.getStatus()).isEqualTo(TestStatus.SKIPPED);
-    assertThat(skipped.getMsg()).isEqualTo("short message");
-    assertThat(skipped.getStacktrace()).isEqualTo("other");
-
-    ScannerReport.Test failed = result.firstTestExecutionForName(testFile, "test3");
-    assertThat(failed.getDurationInMs()).isEqualTo(100);
-    assertThat(failed.getStatus()).isEqualTo(TestStatus.FAILURE);
-    assertThat(failed.getMsg()).isEqualTo("short");
-    assertThat(failed.getStacktrace()).isEqualTo("stacktrace");
-
-    ScannerReport.Test error = result.firstTestExecutionForName(testFile, "test4");
-    assertThat(error.getDurationInMs()).isEqualTo(500);
-    assertThat(error.getStatus()).isEqualTo(TestStatus.ERROR);
-    assertThat(error.getMsg()).isEqualTo("short");
-    assertThat(error.getStacktrace()).isEqualTo("stacktrace");
-
     assertThat(result.allMeasures().get(testFile.key())).extracting("metricKey", "intValue.value", "longValue.value")
       .containsOnly(
         tuple(CoreMetrics.TESTS_KEY, 4, 0L),
@@ -188,7 +83,7 @@ public class GenericTestExecutionMediumTest {
         tuple(CoreMetrics.TEST_ERRORS_KEY, 1, 0L),
         tuple(CoreMetrics.TEST_EXECUTION_TIME_KEY, 0, 1610L),
         tuple(CoreMetrics.TEST_FAILURES_KEY, 1, 0L));
-    
+
     assertThat(logs).noneMatch(l -> l.contains("Please use 'sonar.testExecutionReportPaths'"));
   }
 
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/tests/TestExecutionMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/tests/TestExecutionMediumTest.java
deleted file mode 100644 (file)
index 1a39263..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.scanner.mediumtest.tests;
-
-import com.google.common.collect.ImmutableMap;
-import java.io.File;
-import java.io.IOException;
-import org.apache.commons.io.FileUtils;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.scanner.mediumtest.ScannerMediumTester;
-import org.sonar.scanner.mediumtest.AnalysisResult;
-import org.sonar.scanner.protocol.output.ScannerReport.Test.TestStatus;
-import org.sonar.xoo.XooPlugin;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class TestExecutionMediumTest {
-
-  @org.junit.Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Rule
-  public ScannerMediumTester tester = new ScannerMediumTester()
-    .registerPlugin("xoo", new XooPlugin())
-    .addDefaultQProfile("xoo", "Sonar Way");
-
-  @Test
-  public void unitTests() throws IOException {
-
-    File baseDir = temp.getRoot();
-    File srcDir = new File(baseDir, "src");
-    srcDir.mkdir();
-    File testDir = new File(baseDir, "test");
-    testDir.mkdir();
-
-    File xooFile = new File(srcDir, "sample.xoo");
-    FileUtils.write(xooFile, "foo");
-
-    File xooTestFile = new File(testDir, "sampleTest.xoo");
-    FileUtils.write(xooTestFile, "failure\nerror\nok\nskipped");
-
-    File xooTestExecutionFile = new File(testDir, "sampleTest.xoo.test");
-    FileUtils.write(xooTestExecutionFile, "skipped::::SKIPPED:UNIT\n" +
-      "failure:2:Failure::FAILURE:UNIT\n" +
-      "error:2:Error:The stack:ERROR:UNIT\n" +
-      "success:4:::OK:INTEGRATION");
-
-    AnalysisResult result = tester.newAnalysis()
-      .properties(ImmutableMap.<String, String>builder()
-        .put("sonar.task", "scan")
-        .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
-        .put("sonar.projectKey", "com.foo.project")
-        .put("sonar.projectName", "Foo Project")
-        .put("sonar.projectVersion", "1.0-SNAPSHOT")
-        .put("sonar.projectDescription", "Description of Foo Project")
-        .put("sonar.sources", "src")
-        .put("sonar.tests", "test")
-        .build())
-      .execute();
-
-    InputFile file = result.inputFile("test/sampleTest.xoo");
-    org.sonar.scanner.protocol.output.ScannerReport.Test success = result.firstTestExecutionForName(file, "success");
-    assertThat(success.getDurationInMs()).isEqualTo(4);
-    assertThat(success.getStatus()).isEqualTo(TestStatus.OK);
-
-    org.sonar.scanner.protocol.output.ScannerReport.Test error = result.firstTestExecutionForName(file, "error");
-    assertThat(error.getDurationInMs()).isEqualTo(2);
-    assertThat(error.getStatus()).isEqualTo(TestStatus.ERROR);
-    assertThat(error.getMsg()).isEqualTo("Error");
-    assertThat(error.getStacktrace()).isEqualTo("The stack");
-  }
-
-}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/TestExecutionAndCoveragePublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/TestExecutionAndCoveragePublisherTest.java
deleted file mode 100644 (file)
index 8415312..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.scanner.report;
-
-import java.io.File;
-import java.io.IOException;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.scanner.protocol.output.ScannerReportWriter;
-import org.sonar.scanner.scan.branch.BranchConfiguration;
-import org.sonar.scanner.scan.filesystem.InputComponentStore;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-
-public class TestExecutionAndCoveragePublisherTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Test
-  public void do_nothing_for_short_living_branches() throws IOException {
-    BranchConfiguration branchConfiguration = mock(BranchConfiguration.class);
-    when(branchConfiguration.isShortOrPullRequest()).thenReturn(true);
-    InputComponentStore componentStore = mock(InputComponentStore.class);
-    TestExecutionAndCoveragePublisher publisher = new TestExecutionAndCoveragePublisher(componentStore, null, branchConfiguration);
-    File outputDir = temp.newFolder();
-    ScannerReportWriter writer = new ScannerReportWriter(outputDir);
-
-    publisher.publish(writer);
-
-    verifyZeroInteractions(componentStore);
-  }
-
-  @Test
-  public void do_nothing_for_pull_requests() throws IOException {
-    BranchConfiguration branchConfiguration = mock(BranchConfiguration.class);
-    when(branchConfiguration.isShortOrPullRequest()).thenReturn(true);
-    InputComponentStore componentStore = mock(InputComponentStore.class);
-    TestExecutionAndCoveragePublisher publisher = new TestExecutionAndCoveragePublisher(componentStore, null, branchConfiguration);
-    File outputDir = temp.newFolder();
-    ScannerReportWriter writer = new ScannerReportWriter(outputDir);
-
-    publisher.publish(writer);
-
-    verifyZeroInteractions(componentStore);
-  }
-
-}
index b03e915b4a35d771d61d6fa069a664f9f077d05e..6e4b419c8432194e8380b470fc0a7cc66905a0b0 100644 (file)
@@ -20,7 +20,6 @@
 package org.sonar.scanner.protocol.output;
 
 import java.io.File;
-
 import javax.annotation.concurrent.Immutable;
 
 /**
@@ -40,8 +39,6 @@ public class FileStructure {
     CHANGESETS("changesets-", Domain.PB),
     SYMBOLS("symbols-", Domain.PB),
     COVERAGES("coverages-", Domain.PB),
-    TESTS("tests-", Domain.PB),
-    COVERAGE_DETAILS("coverage-details-", Domain.PB),
     SOURCE("source-", ".txt"),
     SGNIFICANT_CODE("sgnificant-code-", Domain.PB),
     CHANGED_LINES("changed-lines-", Domain.PB);
index 916adcf62a336d00b8f3b1e0521ebc10b64ae71f..90e6143b9ca87b938d3421d22c1211e8d342c988 100644 (file)
@@ -181,26 +181,6 @@ public class ScannerReportReader {
     return null;
   }
 
-  @CheckForNull
-  public File readTests(int testFileRef) {
-    File file = fileStructure.fileFor(FileStructure.Domain.TESTS, testFileRef);
-    if (fileExists(file)) {
-      return file;
-    }
-
-    return null;
-  }
-
-  @CheckForNull
-  public File readCoverageDetails(int testFileRef) {
-    File file = fileStructure.fileFor(FileStructure.Domain.COVERAGE_DETAILS, testFileRef);
-    if (fileExists(file)) {
-      return file;
-    }
-
-    return null;
-  }
-
   public CloseableIterator<ScannerReport.ContextProperty> readContextProperties() {
     File file = fileStructure.contextProperties();
     if (!fileExists(file)) {
index cfa15c7553f366b72457ac5a2ec93b90ffd1049a..e20e37ff852c5892b9de626f7c0ce5a9bef3926c 100644 (file)
@@ -154,18 +154,6 @@ public class ScannerReportWriter {
     return file;
   }
 
-  public File writeTests(int componentRef, Iterable<ScannerReport.Test> tests) {
-    File file = fileStructure.fileFor(FileStructure.Domain.TESTS, componentRef);
-    Protobuf.writeStream(tests, file, false);
-    return file;
-  }
-
-  public File writeCoverageDetails(int componentRef, Iterable<ScannerReport.CoverageDetail> tests) {
-    File file = fileStructure.fileFor(FileStructure.Domain.COVERAGE_DETAILS, componentRef);
-    Protobuf.writeStream(tests, file, false);
-    return file;
-  }
-
   public File writeContextProperties(Iterable<ScannerReport.ContextProperty> properties) {
     File file = fileStructure.contextProperties();
     Protobuf.writeStream(properties, file, false);
index 0b2f132e1c328dceb44f758eaaeaeedc41338c5c..0260f1fcb2e7268f047d6d9c75ecc4186f2d794e 100644 (file)
@@ -25,7 +25,6 @@ import java.awt.Dimension;
 import java.awt.EventQueue;
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.nio.charset.StandardCharsets;
@@ -256,7 +255,6 @@ public class ScannerReportViewerApp {
     updateSymbols(component);
     updateSource(component);
     updateCoverage(component);
-    updateTests(component);
     updateDuplications(component);
     updateIssues(component);
     updateExternalIssues(component);
@@ -348,23 +346,6 @@ public class ScannerReportViewerApp {
     }
   }
 
-  private void updateTests(Component component) {
-    testsEditor.setText("");
-    File tests = reader.readTests(component.getRef());
-    if (tests == null) {
-      return;
-    }
-    try (InputStream inputStream = FileUtils.openInputStream(tests)) {
-      ScannerReport.Test test = ScannerReport.Test.parser().parseDelimitedFrom(inputStream);
-      while (test != null) {
-        testsEditor.getDocument().insertString(testsEditor.getDocument().getEndPosition().getOffset(), test + "\n", null);
-        test = ScannerReport.Test.parser().parseDelimitedFrom(inputStream);
-      }
-    } catch (Exception e) {
-      throw new IllegalStateException(e);
-    }
-  }
-
   private void updateSource(Component component) {
     File sourceFile = reader.getFileStructure().fileFor(Domain.SOURCE, component.getRef());
     sourceEditor.setText("");
index 57f86f9a73a131987393e9ea74e2d395b92b17e2..92e917a65f1697c4527b6c88395644d5a55479bb 100644 (file)
@@ -321,32 +321,6 @@ message SyntaxHighlightingRule {
   }
 }
 
-message Test {
-  string name = 1;
-  TestStatus status = 2;
-  int64 duration_in_ms = 3;
-  string stacktrace = 4;
-  string msg = 5;
-  
-  enum TestStatus {
-    UNSET = 0;
-    OK = 1;
-    FAILURE = 2;
-    ERROR = 3;
-    SKIPPED = 4;
-  }
-}
-
-message CoverageDetail {
-  string test_name = 1;
-  repeated CoveredFile covered_file = 2;
-
-  message CoveredFile {
-    int32 file_ref = 1;
-    repeated int32 covered_line = 2 [packed = true];
-  }
-}
-
 message AnalysisWarning {
   string text = 1;
   int64 timestamp = 2;
index 68fe5aa71886cc97ab904494311f99939f6514e0..928166b5a312424e399395541d436c73fa3a4ddf 100644 (file)
@@ -32,7 +32,6 @@ import org.junit.rules.TemporaryFolder;
 import org.sonar.core.util.CloseableIterator;
 import org.sonar.scanner.protocol.output.ScannerReport.Measure.StringValue;
 import org.sonar.scanner.protocol.output.ScannerReport.SyntaxHighlightingRule.HighlightingType;
-import org.sonar.scanner.protocol.output.ScannerReport.Test.TestStatus;
 
 import static java.util.Arrays.asList;
 import static java.util.Collections.singletonList;
@@ -45,9 +44,9 @@ public class ScannerReportReaderTest {
   @Rule
   public TemporaryFolder temp = new TemporaryFolder();
 
-  File dir;
+  private File dir;
 
-  ScannerReportReader underTest;
+  private ScannerReportReader underTest;
 
   @Before
   public void setUp() throws Exception {
@@ -211,7 +210,7 @@ public class ScannerReportReaderTest {
   }
 
   @Test
-  public void read_syntax_highlighting() throws Exception {
+  public void read_syntax_highlighting() {
     ScannerReportWriter writer = new ScannerReportWriter(dir);
     writer.writeMetadata(ScannerReport.Metadata.newBuilder()
       .setRootComponentRef(1)
@@ -276,7 +275,7 @@ public class ScannerReportReaderTest {
   }
 
   @Test
-  public void read_coverage() throws Exception {
+  public void read_coverage() {
     ScannerReportWriter writer = new ScannerReportWriter(dir);
     writer.writeMetadata(ScannerReport.Metadata.newBuilder()
       .setRootComponentRef(1)
@@ -323,55 +322,6 @@ public class ScannerReportReaderTest {
     assertThat(sourceFile).isEqualTo(file);
   }
 
-  @Test
-  public void read_tests() throws Exception {
-    ScannerReportWriter writer = new ScannerReportWriter(dir);
-    writer.writeTests(1, asList(
-      ScannerReport.Test.newBuilder()
-        .setDurationInMs(60_000)
-        .setStacktrace("stacktrace")
-        .setMsg("message")
-        .setStatus(TestStatus.OK)
-        .build()));
-
-    try (InputStream inputStream = FileUtils.openInputStream(underTest.readTests(1))) {
-      ScannerReport.Test testResult = ScannerReport.Test.parser().parseDelimitedFrom(inputStream);
-      assertThat(testResult.getDurationInMs()).isEqualTo(60_000);
-      assertThat(testResult.getStacktrace()).isEqualTo("stacktrace");
-      assertThat(testResult.getMsg()).isEqualTo("message");
-      assertThat(testResult.getStatus()).isEqualTo(TestStatus.OK);
-    }
-  }
-
-  @Test
-  public void null_if_no_test_found() {
-    assertThat(underTest.readTests(UNKNOWN_COMPONENT_REF)).isNull();
-  }
-
-  @Test
-  public void read_coverage_details() throws Exception {
-    ScannerReportWriter writer = new ScannerReportWriter(dir);
-    writer.writeCoverageDetails(1, asList(
-      ScannerReport.CoverageDetail.newBuilder()
-        .setTestName("test-name")
-        .addCoveredFile(ScannerReport.CoverageDetail.CoveredFile.newBuilder()
-          .addAllCoveredLine(asList(1, 2, 3, 5, 7))
-          .setFileRef(2))
-        .build()));
-
-    try (InputStream inputStream = FileUtils.openInputStream(underTest.readCoverageDetails(1))) {
-      ScannerReport.CoverageDetail coverageDetail = ScannerReport.CoverageDetail.parser().parseDelimitedFrom(inputStream);
-      assertThat(coverageDetail.getTestName()).isEqualTo("test-name");
-      assertThat(coverageDetail.getCoveredFile(0).getFileRef()).isEqualTo(2);
-      assertThat(coverageDetail.getCoveredFile(0).getCoveredLineList()).containsExactly(1, 2, 3, 5, 7);
-    }
-  }
-
-  @Test
-  public void null_if_no_coverage_detail_found() {
-    assertThat(underTest.readCoverageDetails(UNKNOWN_COMPONENT_REF)).isNull();
-  }
-
   @Test
   public void read_file_source() throws Exception {
     ScannerReportWriter writer = new ScannerReportWriter(dir);
@@ -385,7 +335,7 @@ public class ScannerReportReaderTest {
   }
 
   @Test
-  public void return_null_when_no_file_source() throws Exception {
+  public void return_null_when_no_file_source() {
     assertThat(underTest.readFileSource(UNKNOWN_COMPONENT_REF)).isNull();
   }
 }
index ec33c74d38e5092502bb8f6fb2384d00f697e127..3a6f84961dd742db2779ecef1a10591ad48a5150 100644 (file)
@@ -353,24 +353,4 @@ public class ScannerReportWriterTest {
     assertThat(underTest.hasComponentData(FileStructure.Domain.COVERAGES, 1)).isTrue();
   }
 
-  @Test
-  public void write_tests() {
-    assertThat(underTest.hasComponentData(FileStructure.Domain.TESTS, 1)).isFalse();
-
-    underTest.writeTests(1, asList(
-      ScannerReport.Test.getDefaultInstance()));
-
-    assertThat(underTest.hasComponentData(FileStructure.Domain.TESTS, 1)).isTrue();
-
-  }
-
-  @Test
-  public void write_coverage_details() {
-    assertThat(underTest.hasComponentData(FileStructure.Domain.COVERAGE_DETAILS, 1)).isFalse();
-
-    underTest.writeCoverageDetails(1, asList(
-      ScannerReport.CoverageDetail.getDefaultInstance()));
-
-    assertThat(underTest.hasComponentData(FileStructure.Domain.COVERAGE_DETAILS, 1)).isTrue();
-  }
 }
index ae692ccc111348c1674233e72346e0136286ea97..d83de740725cfbca701953236dd3f6ca8db90e0a 100644 (file)
@@ -65,7 +65,6 @@ import org.sonarqube.ws.client.settings.SettingsService;
 import org.sonarqube.ws.client.sources.SourcesService;
 import org.sonarqube.ws.client.support.SupportService;
 import org.sonarqube.ws.client.system.SystemService;
-import org.sonarqube.ws.client.tests.TestsService;
 import org.sonarqube.ws.client.timemachine.TimemachineService;
 import org.sonarqube.ws.client.updatecenter.UpdatecenterService;
 import org.sonarqube.ws.client.usergroups.UserGroupsService;
@@ -130,7 +129,6 @@ class DefaultWsClient implements WsClient {
   private final SourcesService sourcesService;
   private final SupportService supportService;
   private final SystemService systemService;
-  private final TestsService testsService;
   private final TimemachineService timemachineService;
   private final UpdatecenterService updatecenterService;
   private final UserGroupsService userGroupsService;
@@ -189,7 +187,6 @@ class DefaultWsClient implements WsClient {
     this.sourcesService = new SourcesService(wsConnector);
     this.supportService = new SupportService(wsConnector);
     this.systemService = new SystemService(wsConnector);
-    this.testsService = new TestsService(wsConnector);
     this.timemachineService = new TimemachineService(wsConnector);
     this.updatecenterService = new UpdatecenterService(wsConnector);
     this.userGroupsService = new UserGroupsService(wsConnector);
@@ -424,11 +421,6 @@ class DefaultWsClient implements WsClient {
     return systemService;
   }
 
-  @Override
-  public TestsService tests() {
-    return testsService;
-  }
-
   @Override
   public TimemachineService timemachine() {
     return timemachineService;
index 63e9c82d1156ae06d730b0ce023ba251211534cb..30df290cd004d5f1dc2898f31efda9be8d6979d4 100644 (file)
@@ -65,7 +65,6 @@ import org.sonarqube.ws.client.settings.SettingsService;
 import org.sonarqube.ws.client.sources.SourcesService;
 import org.sonarqube.ws.client.support.SupportService;
 import org.sonarqube.ws.client.system.SystemService;
-import org.sonarqube.ws.client.tests.TestsService;
 import org.sonarqube.ws.client.timemachine.TimemachineService;
 import org.sonarqube.ws.client.updatecenter.UpdatecenterService;
 import org.sonarqube.ws.client.usergroups.UserGroupsService;
@@ -185,8 +184,6 @@ public interface WsClient {
 
   SystemService system();
 
-  TestsService tests();
-
   TimemachineService timemachine();
 
   UpdatecenterService updatecenter();
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/tests/CoveredFilesRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/tests/CoveredFilesRequest.java
deleted file mode 100644 (file)
index 0d92feb..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonarqube.ws.client.tests;
-
-import java.util.List;
-import javax.annotation.Generated;
-
-/**
- * This is part of the internal API.
- * This is a POST request.
- * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/tests/covered_files">Further information about this action online (including a response example)</a>
- * @since 4.4
- */
-@Generated("sonar-ws-generator")
-public class CoveredFilesRequest {
-
-  private String p;
-  private String ps;
-  private String testId;
-
-  /**
-   * Example value: "42"
-   */
-  public CoveredFilesRequest setP(String p) {
-    this.p = p;
-    return this;
-  }
-
-  public String getP() {
-    return p;
-  }
-
-  /**
-   * Example value: "20"
-   */
-  public CoveredFilesRequest setPs(String ps) {
-    this.ps = ps;
-    return this;
-  }
-
-  public String getPs() {
-    return ps;
-  }
-
-  /**
-   * This is a mandatory parameter.
-   * Example value: "AU-Tpxb--iU5OvuD2FLy"
-   */
-  public CoveredFilesRequest setTestId(String testId) {
-    this.testId = testId;
-    return this;
-  }
-
-  public String getTestId() {
-    return testId;
-  }
-}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/tests/ListRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/tests/ListRequest.java
deleted file mode 100644 (file)
index be4cdf9..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonarqube.ws.client.tests;
-
-import java.util.List;
-import javax.annotation.Generated;
-
-/**
- * This is part of the internal API.
- * This is a POST request.
- * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/tests/list">Further information about this action online (including a response example)</a>
- * @since 5.2
- */
-@Generated("sonar-ws-generator")
-public class ListRequest {
-
-  private String branch;
-  private String p;
-  private String ps;
-  private String pullRequest;
-  private String sourceFileId;
-  private String sourceFileKey;
-  private String sourceFileLineNumber;
-  private String testFileId;
-  private String testFileKey;
-  private String testId;
-
-  /**
-   * This is part of the internal API.
-   * Example value: "feature/my_branch"
-   */
-  public ListRequest setBranch(String branch) {
-    this.branch = branch;
-    return this;
-  }
-
-  public String getBranch() {
-    return branch;
-  }
-
-  /**
-   * Example value: "42"
-   */
-  public ListRequest setP(String p) {
-    this.p = p;
-    return this;
-  }
-
-  public String getP() {
-    return p;
-  }
-
-  /**
-   * Example value: "20"
-   */
-  public ListRequest setPs(String ps) {
-    this.ps = ps;
-    return this;
-  }
-
-  public String getPs() {
-    return ps;
-  }
-
-  /**
-   * This is part of the internal API.
-   * Example value: "5461"
-   */
-  public ListRequest setPullRequest(String pullRequest) {
-    this.pullRequest = pullRequest;
-    return this;
-  }
-
-  public String getPullRequest() {
-    return pullRequest;
-  }
-
-  /**
-   * Example value: "AU-TpxcA-iU5OvuD2FL0"
-   */
-  public ListRequest setSourceFileId(String sourceFileId) {
-    this.sourceFileId = sourceFileId;
-    return this;
-  }
-
-  public String getSourceFileId() {
-    return sourceFileId;
-  }
-
-  /**
-   * Example value: "my_project:/src/foo/Bar.php"
-   */
-  public ListRequest setSourceFileKey(String sourceFileKey) {
-    this.sourceFileKey = sourceFileKey;
-    return this;
-  }
-
-  public String getSourceFileKey() {
-    return sourceFileKey;
-  }
-
-  /**
-   * Example value: "10"
-   */
-  public ListRequest setSourceFileLineNumber(String sourceFileLineNumber) {
-    this.sourceFileLineNumber = sourceFileLineNumber;
-    return this;
-  }
-
-  public String getSourceFileLineNumber() {
-    return sourceFileLineNumber;
-  }
-
-  /**
-   * Example value: "AU-Tpxb--iU5OvuD2FLy"
-   */
-  public ListRequest setTestFileId(String testFileId) {
-    this.testFileId = testFileId;
-    return this;
-  }
-
-  public String getTestFileId() {
-    return testFileId;
-  }
-
-  /**
-   * Example value: "MY_PROJECT:src/test/java/foo/BarTest.java"
-   */
-  public ListRequest setTestFileKey(String testFileKey) {
-    this.testFileKey = testFileKey;
-    return this;
-  }
-
-  public String getTestFileKey() {
-    return testFileKey;
-  }
-
-  /**
-   * Example value: "AU-TpxcA-iU5OvuD2FLz"
-   */
-  public ListRequest setTestId(String testId) {
-    this.testId = testId;
-    return this;
-  }
-
-  public String getTestId() {
-    return testId;
-  }
-}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/tests/TestsService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/tests/TestsService.java
deleted file mode 100644 (file)
index f1f4fbd..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonarqube.ws.client.tests;
-
-import java.util.stream.Collectors;
-import javax.annotation.Generated;
-import org.sonarqube.ws.MediaTypes;
-import org.sonarqube.ws.client.BaseService;
-import org.sonarqube.ws.client.GetRequest;
-import org.sonarqube.ws.client.PostRequest;
-import org.sonarqube.ws.client.WsConnector;
-import org.sonarqube.ws.Tests.CoveredFilesResponse;
-import org.sonarqube.ws.Tests.ListResponse;
-
-/**
- * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/tests">Further information about this web service online</a>
- */
-@Generated("sonar-ws-generator")
-public class TestsService extends BaseService {
-
-  public TestsService(WsConnector wsConnector) {
-    super(wsConnector, "api/tests");
-  }
-
-  /**
-   *
-   * This is part of the internal API.
-   * This is a GET request.
-   * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/tests/covered_files">Further information about this action online (including a response example)</a>
-   * @since 4.4
-   * @deprecated since 5.6
-   */
-  @Deprecated
-  public CoveredFilesResponse coveredFiles(CoveredFilesRequest request) {
-    return call(
-      new GetRequest(path("covered_files"))
-        .setParam("p", request.getP())
-        .setParam("ps", request.getPs())
-        .setParam("testId", request.getTestId()),
-      CoveredFilesResponse.parser());
-  }
-
-  /**
-   *
-   * This is part of the internal API.
-   * This is a GET request.
-   * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/tests/list">Further information about this action online (including a response example)</a>
-   * @since 5.2
-   * @deprecated since 5.6
-   */
-  @Deprecated
-  public ListResponse list(ListRequest request) {
-    return call(
-      new GetRequest(path("list"))
-        .setParam("branch", request.getBranch())
-        .setParam("p", request.getP())
-        .setParam("ps", request.getPs())
-        .setParam("pullRequest", request.getPullRequest())
-        .setParam("sourceFileId", request.getSourceFileId())
-        .setParam("sourceFileKey", request.getSourceFileKey())
-        .setParam("sourceFileLineNumber", request.getSourceFileLineNumber())
-        .setParam("testFileId", request.getTestFileId())
-        .setParam("testFileKey", request.getTestFileKey())
-        .setParam("testId", request.getTestId()),
-      ListResponse.parser());
-  }
-}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/tests/package-info.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/tests/package-info.java
deleted file mode 100644 (file)
index 1ece80e..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-@Generated("sonar-ws-generator")
-package org.sonarqube.ws.client.tests;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.Generated;
-