]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10567 Compute Engine analysis do not fail if project name or description is...
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Thu, 26 Apr 2018 15:33:08 +0000 (17:33 +0200)
committerSonarTech <sonartech@sonarsource.com>
Fri, 27 Apr 2018 18:20:44 +0000 (20:20 +0200)
15 files changed:
server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDto.java
server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentValidator.java
server/sonar-db-dao/src/main/java/org/sonar/db/component/ResourceDto.java
server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentValidatorTest.java
server/sonar-server/src/main/java/org/sonar/server/ce/ws/SubmitAction.java
server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentImpl.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentTreeBuilder.java
server/sonar-server/src/main/java/org/sonar/server/project/ws/CreateAction.java
server/sonar-server/src/test/java/org/sonar/server/ce/ws/SubmitActionTest.java
server/sonar-server/src/test/java/org/sonar/server/component/NewComponentTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ComponentImplTest.java
server/sonar-server/src/test/java/org/sonar/server/project/ws/CreateActionTest.java
tests/src/test/java/org/sonarqube/tests/project/OrganizationProjectSuite.java
tests/src/test/java/org/sonarqube/tests/project/ProjectInfoTest.java [new file with mode: 0644]

index ef402d4e48fdcd63da0f4e53154d5cea2803abc0..fad8823a8b9c19b95aecee41563dfa8c584aa166 100644 (file)
@@ -36,6 +36,7 @@ import static java.lang.String.format;
 import static org.apache.commons.lang.StringUtils.substringBeforeLast;
 import static org.sonar.db.DaoDatabaseUtils.buildLikeValue;
 import static org.sonar.db.component.ComponentValidator.checkComponentKey;
+import static org.sonar.db.component.ComponentValidator.checkComponentLongName;
 import static org.sonar.db.component.ComponentValidator.checkComponentName;
 import static org.sonar.db.component.DbTagsReader.readDbTags;
 
@@ -338,7 +339,7 @@ public class ComponentDto {
   }
 
   public ComponentDto setLongName(String longName) {
-    this.longName = longName;
+    this.longName = checkComponentLongName(longName);
     return this;
   }
 
index 016842ce800d1c9c10534bff62183c7a5c6bd413..d50213f858a04844e396762dc013c51ab0af2a1b 100644 (file)
  */
 package org.sonar.db.component;
 
+import javax.annotation.Nullable;
+
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Strings.isNullOrEmpty;
 import static org.sonar.core.component.ComponentKeys.MAX_COMPONENT_KEY_LENGTH;
 
 public class ComponentValidator {
-  public static final int MAX_COMPONENT_NAME_LENGTH = 2000;
+  // b_name column is 500 characters wide
+  public static final int MAX_COMPONENT_NAME_LENGTH = 500;
+  public static final int MAX_COMPONENT_DESCRIPTION_LENGTH = 2_000;
+  private static final int MAX_COMPONENT_TAGS_LENGTH = 500;
   private static final int MAX_COMPONENT_QUALIFIER_LENGTH = 10;
 
   private ComponentValidator() {
@@ -38,6 +43,35 @@ public class ComponentValidator {
     return name;
   }
 
+  public static String checkComponentLongName(@Nullable String value) {
+    if (value == null) {
+      return null;
+    }
+    checkArgument(value.length() <= MAX_COMPONENT_NAME_LENGTH, "Component name length (%s) is longer than the maximum authorized (%s). '%s' was provided.",
+      value.length(), MAX_COMPONENT_NAME_LENGTH, value);
+    return value;
+  }
+
+  public static String checkDescription(@Nullable String value) {
+    if (value == null) {
+      return null;
+    }
+
+    checkArgument(value.length() <= MAX_COMPONENT_NAME_LENGTH, "Component description length (%s) is longer than the maximum authorized (%s). '%s' was provided.",
+      value.length(), MAX_COMPONENT_DESCRIPTION_LENGTH, value);
+    return value;
+  }
+
+  public static String checkTags(@Nullable String value) {
+    if (value == null) {
+      return null;
+    }
+
+    checkArgument(value.length() <= MAX_COMPONENT_NAME_LENGTH, "Component tags length (%s) is longer than the maximum authorized (%s). '%s' was provided.",
+      value.length(), MAX_COMPONENT_TAGS_LENGTH, value);
+    return value;
+  }
+
   public static String checkComponentKey(String key) {
     checkArgument(!isNullOrEmpty(key), "Component key can't be empty");
     checkArgument(key.length() <= MAX_COMPONENT_KEY_LENGTH, "Component key length (%s) is longer than the maximum authorized (%s). '%s' was provided.",
index 6a83bea9d37e73e0af17eacaa759b1a7ea95b98a..759d65e753c7956f4204a617aa0301e4f1cb9776 100644 (file)
@@ -24,7 +24,9 @@ import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 
 import static org.sonar.db.component.ComponentValidator.checkComponentKey;
+import static org.sonar.db.component.ComponentValidator.checkComponentLongName;
 import static org.sonar.db.component.ComponentValidator.checkComponentName;
+import static org.sonar.db.component.ComponentValidator.checkDescription;
 
 public class ResourceDto {
 
@@ -142,7 +144,7 @@ public class ResourceDto {
   }
 
   public ResourceDto setLongName(String longName) {
-    this.longName = longName;
+    this.longName = checkComponentLongName(longName);
     return this;
   }
 
@@ -178,7 +180,7 @@ public class ResourceDto {
   }
 
   public ResourceDto setDescription(String description) {
-    this.description = description;
+    this.description = checkDescription(description);
     return this;
   }
 
index 668ca786031bd50f2d87f7efe482d78402b64a17..c1db5835db1473c16ab5df6609e29a2286cfa421 100644 (file)
@@ -33,17 +33,17 @@ public class ComponentValidatorTest {
 
   @Test
   public void check_name() {
-    String name = repeat("a", 2000);
+    String name = repeat("a", 500);
 
     assertThat(ComponentValidator.checkComponentName(name)).isEqualTo(name);
   }
 
   @Test
-  public void fail_when_name_longer_than_2000_characters() {
+  public void fail_when_name_longer_than_500_characters() {
     expectedException.expect(IllegalArgumentException.class);
     expectedException.expectMessage("Component name length");
 
-    ComponentValidator.checkComponentName(repeat("a", 2000 + 1));
+    ComponentValidator.checkComponentName(repeat("a", 500 + 1));
   }
 
   @Test
index d2ddeb33cda7a3bea8836f76e59423be0a5d7ea1..102565e3b14eefcfda0b61d2d77c2f951b8be5ab 100644 (file)
@@ -33,6 +33,8 @@ import org.sonar.server.organization.DefaultOrganizationProvider;
 import org.sonar.server.ws.WsUtils;
 import org.sonarqube.ws.Ce;
 
+import static org.apache.commons.lang.StringUtils.abbreviate;
+import static org.apache.commons.lang.StringUtils.defaultIfBlank;
 import static org.sonar.core.component.ComponentKeys.MAX_COMPONENT_KEY_LENGTH;
 import static org.sonar.db.component.ComponentValidator.MAX_COMPONENT_NAME_LENGTH;
 import static org.sonar.server.ws.WsUtils.checkRequest;
@@ -86,8 +88,7 @@ public class SubmitAction implements CeWsAction {
     action
       .createParam(PARAM_PROJECT_NAME)
       .setRequired(false)
-      .setMaximumLength(MAX_COMPONENT_NAME_LENGTH)
-      .setDescription("Optional name of the project, used only if the project does not exist yet.")
+      .setDescription("Optional name of the project, used only if the project does not exist yet. If name is longer than %d, it is abbreviated.", MAX_COMPONENT_NAME_LENGTH)
       .setExampleValue("My Project");
 
     action
@@ -110,7 +111,7 @@ public class SubmitAction implements CeWsAction {
       .or(defaultOrganizationProvider.get()::getKey);
     String projectKey = wsRequest.mandatoryParam(PARAM_PROJECT_KEY);
     String projectBranch = wsRequest.param(PARAM_PROJECT_BRANCH);
-    String projectName = StringUtils.defaultIfBlank(wsRequest.param(PARAM_PROJECT_NAME), projectKey);
+    String projectName = abbreviate(defaultIfBlank(wsRequest.param(PARAM_PROJECT_NAME), projectKey), MAX_COMPONENT_NAME_LENGTH);
 
     Map<String, String> characteristics = parseTaskCharacteristics(wsRequest);
 
index 22165c43d746905da7b2293e25637f97e3afb44b..f3be61d393c9c107f9004fca20cc0f45ea61e5e5 100644 (file)
@@ -27,7 +27,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.Scopes;
 import org.sonar.api.server.ServerSide;
@@ -52,6 +51,7 @@ import org.sonar.server.user.UserSession;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static java.lang.String.format;
+import static org.apache.commons.lang.StringUtils.defaultIfBlank;
 import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION;
 import static org.sonar.server.component.NewComponent.newComponentBuilder;
 import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
@@ -161,7 +161,7 @@ public class ReportSubmitter {
     NewComponent newProject = newComponentBuilder()
       .setOrganizationUuid(organization.getUuid())
       .setKey(projectKey)
-      .setName(StringUtils.defaultIfBlank(projectName, projectKey))
+      .setName(defaultIfBlank(projectName, projectKey))
       .setBranch(deprecatedBranch)
       .setQualifier(Qualifiers.PROJECT)
       .setPrivate(newProjectPrivate)
index d1bb10c3234c25233d30f7577a264fc8f1a642c3..6bbbd3097810ab3e7b44538b4b80d3f62b260b53 100644 (file)
@@ -29,7 +29,10 @@ import javax.annotation.concurrent.Immutable;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
 import static java.util.Objects.requireNonNull;
+import static org.apache.commons.lang.StringUtils.abbreviate;
 import static org.apache.commons.lang.StringUtils.trimToNull;
+import static org.sonar.db.component.ComponentValidator.MAX_COMPONENT_DESCRIPTION_LENGTH;
+import static org.sonar.db.component.ComponentValidator.MAX_COMPONENT_NAME_LENGTH;
 
 @Immutable
 public class ComponentImpl implements Component {
@@ -186,12 +189,12 @@ public class ComponentImpl implements Component {
     }
 
     public Builder setName(String name) {
-      this.name = requireNonNull(name, NAME_CANNOT_BE_NULL);
+      this.name = abbreviate(requireNonNull(name, NAME_CANNOT_BE_NULL), MAX_COMPONENT_NAME_LENGTH);
       return this;
     }
 
     public Builder setDescription(@Nullable String description) {
-      this.description = trimToNull(description);
+      this.description = abbreviate(trimToNull(description), MAX_COMPONENT_DESCRIPTION_LENGTH);
       return this;
     }
 
index 50cdf2e082a88c72856530e5d88532591f9a0e53..b6964fb1532c03b77de3b6c1a979e0ed15659d76 100644 (file)
@@ -149,7 +149,7 @@ public class ComponentTreeBuilder {
     if (branch.isMain()) {
       builder
         .setName(nameOfProject(component))
-        .setDescription(trimToNull(component.getDescription()));
+        .setDescription(component.getDescription());
     } else {
       builder
         .setName(project.getName())
index de8d06b77cfa26f11e9fef533a627723ea3da276..6df58965ba63dd675d9ee30a58fdb0e7c5c545f2 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.server.project.ws;
 
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
 import org.sonar.api.server.ws.Change;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
@@ -32,9 +34,7 @@ import org.sonar.server.project.Visibility;
 import org.sonar.server.user.UserSession;
 import org.sonarqube.ws.Projects.CreateWsResponse;
 
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
+import static org.apache.commons.lang.StringUtils.abbreviate;
 import static org.sonar.api.resources.Qualifiers.PROJECT;
 import static org.sonar.core.component.ComponentKeys.MAX_COMPONENT_KEY_LENGTH;
 import static org.sonar.db.component.ComponentValidator.MAX_COMPONENT_NAME_LENGTH;
@@ -88,9 +88,8 @@ public class CreateAction implements ProjectsWsAction {
       .setExampleValue(KEY_PROJECT_EXAMPLE_001);
 
     action.createParam(PARAM_NAME)
-      .setDescription("Name of the project")
+      .setDescription("Name of the project. If name is longer than %d, it is abbreviated.", MAX_COMPONENT_NAME_LENGTH)
       .setRequired(true)
-      .setMaximumLength(MAX_COMPONENT_NAME_LENGTH)
       .setExampleValue("SonarQube");
 
     action.createParam(PARAM_BRANCH)
@@ -138,7 +137,7 @@ public class CreateAction implements ProjectsWsAction {
     return CreateRequest.builder()
       .setOrganization(request.param(PARAM_ORGANIZATION))
       .setKey(request.mandatoryParam(PARAM_PROJECT))
-      .setName(request.mandatoryParam(PARAM_NAME))
+      .setName(abbreviate(request.mandatoryParam(PARAM_NAME), MAX_COMPONENT_NAME_LENGTH))
       .setBranch(request.param(PARAM_BRANCH))
       .setVisibility(request.param(PARAM_VISIBILITY))
       .build();
index 969817d88a3ff0980166a23a53d44f4276372f09..c35385b08eacc6ffc196edd854f808163d55efae 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.ce.ws;
 
+import com.google.common.base.Strings;
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.util.Arrays;
@@ -112,6 +113,27 @@ public class SubmitActionTest {
     assertThat(map.getValue()).containsOnly(entry("branch", "branch1"), entry("key", "value1=value2"));
   }
 
+  @Test
+  public void abbreviate_long_name() {
+    String longName = Strings.repeat("a", 1_000);
+    String expectedName = Strings.repeat("a", 497) + "...";
+    when(reportSubmitter.submit(eq(organizationKey), eq("my_project"), isNull(), eq(expectedName),
+      anyMap(), any())).thenReturn(A_CE_TASK);
+
+    Ce.SubmitResponse submitResponse = tester.newRequest()
+      .setParam("projectKey", "my_project")
+      .setParam("projectName", longName)
+      .setPart("report", new ByteArrayInputStream("{binary}".getBytes()), "foo.bar")
+      .setMethod("POST")
+      .executeProtobuf(Ce.SubmitResponse.class);
+
+    verify(reportSubmitter).submit(eq(organizationKey), eq("my_project"), isNull(), eq(expectedName),
+      anyMap(), any());
+
+    assertThat(submitResponse.getTaskId()).isEqualTo("TASK_1");
+    assertThat(submitResponse.getProjectId()).isEqualTo("PROJECT_1");
+  }
+
   @Test
   public void test_example_json_response() {
     when(reportSubmitter.submit(eq(organizationKey), eq("my_project"), isNull(), eq("My Project"),
index 0192fa8a2568e562437826e11b24c8446c47edc0..d17576e251024f57e51d058f58a422ad18bac3d2 100644 (file)
@@ -90,11 +90,11 @@ public class NewComponentTest {
   public void build_fails_with_IAE_when_name_is_longer_than_2000_characters() {
     underTest.setOrganizationUuid(ORGANIZATION_UUID)
       .setKey(KEY)
-      .setName(repeat("a", 2001));
+      .setName(repeat("a", 501));
 
     expectBuildException(
       IllegalArgumentException.class,
-      "Component name length (2001) is longer than the maximum authorized (2000)");
+      "Component name length (501) is longer than the maximum authorized (500)");
   }
 
   @Test
index 1754a9e261a1a190370078fc7bf10e60a7c75dbc..c4921b8e68e9f959af765c0b11fb99768581eca5 100644 (file)
@@ -26,6 +26,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.server.computation.task.projectanalysis.component.Component.Status;
 
+import static com.google.common.base.Strings.repeat;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.fail;
 import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.FILE;
@@ -37,7 +38,7 @@ public class ComponentImplTest {
   static final String UUID = "UUID";
 
   @Rule
-  public ExpectedException thrown = ExpectedException.none();
+  public ExpectedException expectedException = ExpectedException.none();
 
   @Test
   public void verify_key_uuid_and_name() {
@@ -50,21 +51,21 @@ public class ComponentImplTest {
 
   @Test
   public void builder_throws_NPE_if_component_arg_is_Null() {
-    thrown.expect(NullPointerException.class);
+    expectedException.expect(NullPointerException.class);
 
     builder(null);
   }
 
   @Test
   public void builder_throws_NPE_if_status_arg_is_Null() {
-    thrown.expect(NullPointerException.class);
+    expectedException.expect(NullPointerException.class);
 
     builder(FILE).setStatus(null);
   }
 
   @Test
   public void builder_throws_NPE_if_status_is_Null() {
-    thrown.expect(NullPointerException.class);
+    expectedException.expect(NullPointerException.class);
 
     builder(Component.Type.DIRECTORY)
       .setName("DIR")
@@ -76,28 +77,28 @@ public class ComponentImplTest {
 
   @Test
   public void set_key_throws_NPE_if_component_arg_is_Null() {
-    thrown.expect(NullPointerException.class);
+    expectedException.expect(NullPointerException.class);
 
     builder(FILE).setUuid(null);
   }
 
   @Test
   public void set_uuid_throws_NPE_if_component_arg_is_Null() {
-    thrown.expect(NullPointerException.class);
+    expectedException.expect(NullPointerException.class);
 
     builder(FILE).setKey(null);
   }
 
   @Test
   public void build_without_key_throws_NPE_if_component_arg_is_Null() {
-    thrown.expect(NullPointerException.class);
+    expectedException.expect(NullPointerException.class);
 
     builder(FILE).setUuid("ABCD").build();
   }
 
   @Test
   public void build_without_uuid_throws_NPE_if_component_arg_is_Null() {
-    thrown.expect(NullPointerException.class);
+    expectedException.expect(NullPointerException.class);
 
     builder(FILE).setKey(KEY).build();
   }
@@ -169,6 +170,30 @@ public class ComponentImplTest {
     assertThat(component.getFileAttributes().getLanguageKey()).isEqualTo(languageKey);
   }
 
+  @Test
+  public void keep_500_first_characters_of_name() {
+    String veryLongString = repeat("a", 3_000);
+
+    ComponentImpl underTest = buildSimpleComponent(FILE, "file")
+      .setName(veryLongString)
+      .build();
+
+    String expectedName = repeat("a", 500-3) + "...";
+    assertThat(underTest.getName()).isEqualTo(expectedName);
+  }
+
+  @Test
+  public void keep_2000_first_characters_of_description() {
+    String veryLongString = repeat("a", 3_000);
+
+    ComponentImpl underTest = buildSimpleComponent(FILE, "file")
+      .setDescription(veryLongString)
+      .build();
+
+    String expectedDescription = repeat("a", 2_000-3) + "...";
+    assertThat(underTest.getDescription()).isEqualTo(expectedDescription);
+  }
+
   @Test
   public void build_with_child() {
     ComponentImpl child = builder(FILE)
index 31d3936a36c66c8c7160a0c2cd952652c3209979..a2be524f1a63fd3774c3d5567f130f96a4400cda 100644 (file)
@@ -19,7 +19,7 @@
  */
 package org.sonar.server.project.ws;
 
-import org.assertj.core.api.AssertionsForClassTypes;
+import com.google.common.base.Strings;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -212,7 +212,23 @@ public class CreateActionTest {
       .setParam("visibility", "public")
       .executeProtobuf(CreateWsResponse.class);
 
-    AssertionsForClassTypes.assertThat(result.getProject().getVisibility()).isEqualTo("public");
+    assertThat(result.getProject().getVisibility()).isEqualTo("public");
+  }
+
+  @Test
+  public void abbreviate_project_name_if_very_long() {
+    OrganizationDto organization = db.organizations().insert();
+    userSession.addPermission(PROVISION_PROJECTS, organization);
+    String longName = Strings.repeat("a", 1_000);
+
+    ws.newRequest()
+      .setParam("key", DEFAULT_PROJECT_KEY)
+      .setParam("name", longName)
+      .setParam("organization", organization.getKey())
+      .executeProtobuf(CreateWsResponse.class);
+
+    assertThat(db.getDbClient().componentDao().selectByKey(db.getSession(), DEFAULT_PROJECT_KEY).get().name())
+      .isEqualTo(Strings.repeat("a", 497) + "...");
   }
 
   @Test
@@ -335,7 +351,7 @@ public class CreateActionTest {
 
     WebService.Param name = definition.param(PARAM_NAME);
     assertThat(name.isRequired()).isTrue();
-    assertThat(name.maximumLength()).isEqualTo(2000);
+    assertThat(name.description()).isEqualTo("Name of the project. If name is longer than 500, it is abbreviated.");
   }
 
   private CreateWsResponse call(CreateRequest request) {
index c0675b8159f3c9ee926773398a09407af41bcad4..75dc194bac26a74d771249fa158ceb5de99780d5 100644 (file)
@@ -36,6 +36,7 @@ import static util.ItUtils.xooPlugin;
   ProjectBulkDeletionPageTest.class,
   ProjectDeletionTest.class,
   ProjectFilterTest.class,
+  ProjectInfoTest.class,
   ProjectKeyUpdateTest.class,
   ProjectKeyUpdatePageTest.class,
   ProjectLeakPageTest.class,
diff --git a/tests/src/test/java/org/sonarqube/tests/project/ProjectInfoTest.java b/tests/src/test/java/org/sonarqube/tests/project/ProjectInfoTest.java
new file mode 100644 (file)
index 0000000..407acd2
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.tests.project;
+
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.SonarScanner;
+import java.io.File;
+import java.io.IOException;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonarqube.qa.util.Tester;
+import org.sonarqube.ws.Components.Component;
+import org.sonarqube.ws.Organizations;
+import org.sonarqube.ws.client.components.ShowRequest;
+import util.XooProjectBuilder;
+
+import static org.apache.commons.lang.StringUtils.repeat;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ProjectInfoTest {
+
+  @ClassRule
+  public static Orchestrator orchestrator = OrganizationProjectSuite.ORCHESTRATOR;
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+  @Rule
+  public Tester tester = new Tester(orchestrator);
+
+  @Test
+  public void project_name_and_description_should_be_truncated_if_too_long() throws IOException {
+    Organizations.Organization organization = tester.organizations().generate();
+    File projectDir = temp.newFolder();
+    new XooProjectBuilder("sample").setFilesPerModule(0).build(projectDir);
+    String longName = repeat("x", 1_000);
+    String longDescription = repeat("y", 3_000);
+
+    orchestrator.executeBuild(SonarScanner.create(projectDir,
+      "sonar.organization", organization.getKey(),
+      "sonar.login", "admin",
+      "sonar.password", "admin",
+      "sonar.projectDescription", longDescription,
+      "sonar.projectName", longName));
+
+    Component createdProject = tester.wsClient().components().show(new ShowRequest().setComponent("sample")).getComponent();
+    assertThat(createdProject.getName()).isEqualTo(repeat("x", 497) + "...");
+    assertThat(createdProject.getDescription()).isEqualTo(repeat("y", 1_997) + "...");
+  }
+}