Переглянути джерело

SONAR-11302 Increase size of organization's key and name

As login can be automatically generated from name, size of the personal organization key might be higher than current value (32)
tags/7.5
Julien Lancelot 5 роки тому
джерело
коміт
f5a9eedb6a
17 змінених файлів з 204 додано та 237 видалено
  1. 2
    2
      server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl
  2. 0
    43
      server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationCount.java
  3. 18
    2
      server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationDto.java
  4. 1
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74.java
  5. 56
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLength.java
  6. 1
    1
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74Test.java
  7. 55
    0
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLengthTest.java
  8. 20
    0
      server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLengthTest/organizations.sql
  9. 4
    4
      server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidation.java
  10. 1
    2
      server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidationImpl.java
  11. 7
    2
      server/sonar-server/src/main/java/org/sonar/server/organization/ws/CreateAction.java
  12. 3
    2
      server/sonar-server/src/main/java/org/sonar/server/organization/ws/OrganizationsWsSupport.java
  13. 3
    1
      server/sonar-server/src/main/java/org/sonar/server/organization/ws/UpdateAction.java
  14. 2
    51
      server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java
  15. 22
    35
      server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationValidationImplTest.java
  16. 7
    71
      server/sonar-server/src/test/java/org/sonar/server/organization/ws/CreateActionTest.java
  17. 2
    21
      server/sonar-server/src/test/java/org/sonar/server/organization/ws/UpdateActionTest.java

+ 2
- 2
server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl Переглянути файл

@@ -1,7 +1,7 @@
CREATE TABLE "ORGANIZATIONS" (
"UUID" VARCHAR(40) NOT NULL,
"KEE" VARCHAR(32) NOT NULL,
"NAME" VARCHAR(64) NOT NULL,
"KEE" VARCHAR(300) NOT NULL,
"NAME" VARCHAR(300) NOT NULL,
"DESCRIPTION" VARCHAR(256),
"URL" VARCHAR(256),
"AVATAR_URL" VARCHAR(256),

+ 0
- 43
server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationCount.java Переглянути файл

@@ -1,43 +0,0 @@
/*
* 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.sonar.db.organization;

public class OrganizationCount {
private String organizationUuid;
private int memberCount;

public String getOrganizationUuid() {
return organizationUuid;
}

public OrganizationCount setOrganizationUuid(String organizationUuid) {
this.organizationUuid = organizationUuid;
return this;
}

public int getMemberCount() {
return memberCount;
}

public OrganizationCount setMemberCount(int memberCount) {
this.memberCount = memberCount;
return this;
}
}

+ 18
- 2
server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationDto.java Переглянути файл

@@ -22,6 +22,7 @@ package org.sonar.db.organization;
import java.util.Objects;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.api.server.authentication.UserIdentity;

public class OrganizationDto {

@@ -44,10 +45,25 @@ public class OrganizationDto {

/** Technical unique identifier, can't be null */
private String uuid;
/** Functional unique identifier, can't be null */

/**
* Functional unique identifier, can't be null.
*
* On personal organization (created the first time the user authenticates), the key can have the following format :
* - When {@link UserIdentity#getLogin()} is not null, it's a slug of the login
* - When {@link UserIdentity#getLogin()} is null, it's a slug of the name appended to a random number
*
* Length is set to 300 (As login length is 255, the size must be higher than 255).
*/
private String key;
/** Name, can't be null */

/**
* Name, can't be null.
*
* Length is set to 300, as it's generated from the key when no name is provided.
*/
private String name;

/** description can't be null */
private String description;
/** url can be null */

+ 1
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74.java Переглянути файл

@@ -41,6 +41,7 @@ public class DbVersion74 implements DbVersion {
.add(2318, "Finalize CE_QUEUE.MAIN_COMPONENT_UUID 3/3", FinalizeMainComponentUuidColumnsToCeActivity.class)
.add(2319, "Finalize CE_ACTIVITY.MAIN_COMPONENT_UUID 3/3", FinalizeMainComponentUuidColumnsToCeQueue.class)
.add(2320, "Finalize CE_ACTIVITY.MAIN_LAST_KEY 3/3", FinalizeMainLastKeyColumnsToCeActivity.class)
.add(2321, "Increase organization key and name length", IncreaseOrganizationsKeeAndNameLength.class)
;
}
}

+ 56
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLength.java Переглянути файл

@@ -0,0 +1,56 @@
/*
* 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.sonar.server.platform.db.migration.version.v74;

import java.sql.SQLException;
import org.sonar.db.Database;
import org.sonar.server.platform.db.migration.SupportsBlueGreen;
import org.sonar.server.platform.db.migration.sql.AlterColumnsBuilder;
import org.sonar.server.platform.db.migration.step.DdlChange;

import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;

@SupportsBlueGreen
public class IncreaseOrganizationsKeeAndNameLength extends DdlChange {

public static final String ORGANIZATIONS_TABLE = "organizations";

public IncreaseOrganizationsKeeAndNameLength(Database db) {
super(db);
}

@Override
public void execute(Context context) throws SQLException {
context.execute(new AlterColumnsBuilder(getDialect(), ORGANIZATIONS_TABLE)
.updateColumn(newVarcharColumnDefBuilder()
.setColumnName("kee")
.setLimit(300)
.setIsNullable(false)
.build())
.build());
context.execute(new AlterColumnsBuilder(getDialect(), ORGANIZATIONS_TABLE)
.updateColumn(newVarcharColumnDefBuilder()
.setColumnName("name")
.setLimit(300)
.setIsNullable(false)
.build())
.build());
}
}

+ 1
- 1
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74Test.java Переглянути файл

@@ -35,6 +35,6 @@ public class DbVersion74Test {

@Test
public void verify_migration_count() {
verifyMigrationCount(underTest, 14);
verifyMigrationCount(underTest, 15);
}
}

+ 55
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLengthTest.java Переглянути файл

@@ -0,0 +1,55 @@
/*
* 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.sonar.server.platform.db.migration.version.v74;

import java.sql.SQLException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.db.CoreDbTester;

import static java.sql.Types.VARCHAR;

public class IncreaseOrganizationsKeeAndNameLengthTest {

@Rule
public final CoreDbTester db = CoreDbTester.createForSchema(IncreaseOrganizationsKeeAndNameLengthTest.class, "organizations.sql");

@Rule
public ExpectedException expectedException = ExpectedException.none();

private IncreaseOrganizationsKeeAndNameLength underTest = new IncreaseOrganizationsKeeAndNameLength(db.database());

@Test
public void column_is_updated() throws SQLException {
underTest.execute();

db.assertColumnDefinition("organizations", "kee", VARCHAR, 300, false);
db.assertColumnDefinition("organizations", "name", VARCHAR, 300, false);
}

@Test
public void migration_is_reentrant() throws SQLException {
underTest.execute();

underTest.execute();
}

}

+ 20
- 0
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLengthTest/organizations.sql Переглянути файл

@@ -0,0 +1,20 @@
CREATE TABLE "ORGANIZATIONS" (
"UUID" VARCHAR(40) NOT NULL,
"KEE" VARCHAR(32) NOT NULL,
"NAME" VARCHAR(64) NOT NULL,
"DESCRIPTION" VARCHAR(256),
"URL" VARCHAR(256),
"AVATAR_URL" VARCHAR(256),
"GUARDED" BOOLEAN NOT NULL,
"DEFAULT_PERM_TEMPLATE_PROJECT" VARCHAR(40),
"DEFAULT_PERM_TEMPLATE_VIEW" VARCHAR(40),
"DEFAULT_GROUP_ID" INTEGER,
"DEFAULT_QUALITY_GATE_UUID" VARCHAR(40) NOT NULL,
"NEW_PROJECT_PRIVATE" BOOLEAN NOT NULL,
"SUBSCRIPTION" VARCHAR(40) NOT NULL,
"CREATED_AT" BIGINT NOT NULL,
"UPDATED_AT" BIGINT NOT NULL,

CONSTRAINT "PK_ORGANIZATIONS" PRIMARY KEY ("UUID")
);
CREATE UNIQUE INDEX "ORGANIZATION_KEY" ON "ORGANIZATIONS" ("KEE");

+ 4
- 4
server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidation.java Переглянути файл

@@ -24,16 +24,16 @@ import javax.annotation.Nullable;

public interface OrganizationValidation {
int KEY_MIN_LENGTH = 1;
int KEY_MAX_LENGTH = 32;
int KEY_MAX_LENGTH = 300;
int NAME_MIN_LENGTH = 1;
int NAME_MAX_LENGTH = 64;
int NAME_MAX_LENGTH = 300;
int DESCRIPTION_MAX_LENGTH = 256;
int URL_MAX_LENGTH = 256;

/**
* Ensures the specified argument is a valid key by failing with an exception if it is not so.
* <p>
* A valid key is non null and its length is between {@link #KEY_MIN_LENGTH 2} and {@link #KEY_MAX_LENGTH 32}.
* A valid key is non null and its length is between {@link #KEY_MIN_LENGTH} and {@link #KEY_MAX_LENGTH}.
* </p>
*
* @return the argument
@@ -46,7 +46,7 @@ public interface OrganizationValidation {
/**
* Ensures the specified argument is a valid name by failing with an exception if it is not so.
* <p>
* A valid name is non null and its length is between {@link #NAME_MIN_LENGTH 2} and {@link #NAME_MAX_LENGTH 64}.
* A valid name is non null and its length is between {@link #NAME_MIN_LENGTH} and {@link #NAME_MAX_LENGTH}.
* </p>
*
* @return the argument

+ 1
- 2
server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidationImpl.java Переглянути файл

@@ -23,7 +23,6 @@ import javax.annotation.CheckForNull;
import javax.annotation.Nullable;

import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.Math.min;
import static java.util.Objects.requireNonNull;
import static org.sonar.core.util.Slug.slugify;

@@ -79,6 +78,6 @@ public class OrganizationValidationImpl implements OrganizationValidation {

@Override
public String generateKeyFrom(String source) {
return slugify(source.substring(0, min(source.length(), KEY_MAX_LENGTH)));
return slugify(source);
}
}

+ 7
- 2
server/sonar-server/src/main/java/org/sonar/server/organization/ws/CreateAction.java Переглянути файл

@@ -40,6 +40,7 @@ import org.sonarqube.ws.Organizations.CreateWsResponse;
import static com.google.common.base.Preconditions.checkArgument;
import static org.sonar.server.organization.OrganizationUpdater.NewOrganization.newOrganizationBuilder;
import static org.sonar.server.organization.OrganizationValidation.KEY_MAX_LENGTH;
import static org.sonar.server.organization.OrganizationValidation.KEY_MIN_LENGTH;
import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_KEY;
import static org.sonar.server.ws.WsUtils.writeProtobuf;

@@ -74,16 +75,20 @@ public class CreateAction implements OrganizationsWsAction {
.setResponseExample(getClass().getResource("create-example.json"))
.setInternal(true)
.setSince("6.2")
.setChangelog(new Change("7.2", "Minimal number of character of name and key is one character"))
.setChangelog(
new Change("7.4", "Maximal number of character of name and key is 300 characters"),
new Change("7.2", "Minimal number of character of name and key is one character")
)
.setHandler(this);

action.createParam(PARAM_KEY)
.setRequired(false)
.setMinimumLength(KEY_MIN_LENGTH)
.setMaximumLength(KEY_MAX_LENGTH)
.setDescription("Key of the organization. <br />" +
"The key is unique to the whole SonarQube. <br/>" +
"When not specified, the key is computed from the name. <br />" +
"Otherwise, it must be between 1 and 32 chars long. All chars must be lower-case letters (a to z), digits or dash (but dash can neither be trailing nor heading)")
"All chars must be lower-case letters (a to z), digits or dash (but dash can neither be trailing nor heading)")
.setExampleValue("foo-company");

wsSupport.addOrganizationDetailsParams(action, true);

+ 3
- 2
server/sonar-server/src/main/java/org/sonar/server/organization/ws/OrganizationsWsSupport.java Переглянути файл

@@ -29,6 +29,7 @@ import org.sonarqube.ws.Organizations.Organization;
import static org.sonar.core.util.Protobuf.setNullable;
import static org.sonar.server.organization.OrganizationValidation.DESCRIPTION_MAX_LENGTH;
import static org.sonar.server.organization.OrganizationValidation.NAME_MAX_LENGTH;
import static org.sonar.server.organization.OrganizationValidation.NAME_MIN_LENGTH;
import static org.sonar.server.organization.OrganizationValidation.URL_MAX_LENGTH;

/**
@@ -83,9 +84,9 @@ public class OrganizationsWsSupport {
void addOrganizationDetailsParams(WebService.NewAction action, boolean isNameRequired) {
action.createParam(PARAM_NAME)
.setRequired(isNameRequired)
.setMinimumLength(NAME_MIN_LENGTH)
.setMaximumLength(NAME_MAX_LENGTH)
.setDescription("Name of the organization. <br />" +
"It must be between 2 and 64 chars longs.")
.setDescription("Name of the organization")
.setExampleValue("Foo Company");

action.createParam(PARAM_DESCRIPTION)

+ 3
- 1
server/sonar-server/src/main/java/org/sonar/server/organization/ws/UpdateAction.java Переглянути файл

@@ -22,6 +22,7 @@ package org.sonar.server.organization.ws;
import java.util.Optional;
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;
import org.sonar.api.server.ws.WebService;
@@ -34,12 +35,12 @@ import org.sonar.server.user.UserSession;
import org.sonarqube.ws.Organizations;

import static java.lang.String.format;
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_AVATAR_URL;
import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_DESCRIPTION;
import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_KEY;
import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_NAME;
import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_URL;
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
import static org.sonar.server.ws.WsUtils.writeProtobuf;

public class UpdateAction implements OrganizationsWsAction {
@@ -66,6 +67,7 @@ public class UpdateAction implements OrganizationsWsAction {
"Require 'Administer System' permission. Organization support must be enabled.")
.setInternal(true)
.setSince("6.2")
.setChangelog(new Change("7.4", "Maximal number of character of name is 300 characters"))
.setHandler(this);

action.createParam(PARAM_KEY)

+ 2
- 51
server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java Переглянути файл

@@ -73,7 +73,6 @@ public class OrganizationUpdaterImplTest {
private static final long A_DATE = 12893434L;
private static final String A_LOGIN = "a-login";
private static final String SLUG_OF_A_LOGIN = "slug-of-a-login";
private static final String STRING_64_CHARS = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
private static final String A_NAME = "a name";

private OrganizationUpdater.NewOrganization FULL_POPULATED_NEW_ORGANIZATION = newOrganizationBuilder()
@@ -191,7 +190,8 @@ public class OrganizationUpdaterImplTest {
assertThat(dbClient.permissionTemplateDao().selectGroupPermissionsByTemplateId(dbSession, defaultTemplate.getId()))
.extracting(PermissionTemplateGroupDto::getGroupId, PermissionTemplateGroupDto::getPermission)
.containsOnly(
tuple(ownersGroup.getId(), UserRole.ADMIN), tuple(ownersGroup.getId(), UserRole.ISSUE_ADMIN), tuple(ownersGroup.getId(), UserRole.SECURITYHOTSPOT_ADMIN), tuple(ownersGroup.getId(), GlobalPermissions.SCAN_EXECUTION),
tuple(ownersGroup.getId(), UserRole.ADMIN), tuple(ownersGroup.getId(), UserRole.ISSUE_ADMIN), tuple(ownersGroup.getId(), UserRole.SECURITYHOTSPOT_ADMIN),
tuple(ownersGroup.getId(), GlobalPermissions.SCAN_EXECUTION),
tuple(defaultGroupId, UserRole.USER), tuple(defaultGroupId, UserRole.CODEVIEWER));
}

@@ -425,54 +425,6 @@ public class OrganizationUpdaterImplTest {
assertThat(dbClient.organizationMemberDao().select(dbSession, organization.getUuid(), user.getId())).isPresent();
}

@Test
public void createForUser_does_not_fail_if_name_is_too_long_for_an_organization_name() {
String nameTooLong = STRING_64_CHARS + "b";
UserDto user = db.users().insertUser(dto -> dto.setName(nameTooLong).setLogin(A_LOGIN));
when(organizationValidation.generateKeyFrom(A_LOGIN)).thenReturn(SLUG_OF_A_LOGIN);
enableCreatePersonalOrg(true);
builtInQProfileRepositoryRule.initialize();
db.qualityGates().insertBuiltInQualityGate();

underTest.createForUser(dbSession, user);

OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, SLUG_OF_A_LOGIN).get();
assertThat(organization.getName()).isEqualTo(STRING_64_CHARS);
assertThat(organization.getDescription()).isEqualTo(nameTooLong + "'s personal organization");
}

@Test
public void createForUser_does_not_fail_if_name_is_empty_and_login_is_too_long_for_an_organization_name() {
String login = STRING_64_CHARS + "b";
UserDto user = db.users().insertUser(dto -> dto.setName("").setLogin(login));
when(organizationValidation.generateKeyFrom(login)).thenReturn(SLUG_OF_A_LOGIN);
enableCreatePersonalOrg(true);
builtInQProfileRepositoryRule.initialize();
db.qualityGates().insertBuiltInQualityGate();

underTest.createForUser(dbSession, user);

OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, SLUG_OF_A_LOGIN).get();
assertThat(organization.getName()).isEqualTo(STRING_64_CHARS);
assertThat(organization.getDescription()).isEqualTo(login + "'s personal organization");
}

@Test
public void createForUser_does_not_fail_if_name_is_null_and_login_is_too_long_for_an_organization_name() {
String login = STRING_64_CHARS + "b";
UserDto user = db.users().insertUser(dto -> dto.setName(null).setLogin(login));
when(organizationValidation.generateKeyFrom(login)).thenReturn(SLUG_OF_A_LOGIN);
enableCreatePersonalOrg(true);
builtInQProfileRepositoryRule.initialize();
db.qualityGates().insertBuiltInQualityGate();

underTest.createForUser(dbSession, user);

OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, SLUG_OF_A_LOGIN).get();
assertThat(organization.getName()).isEqualTo(STRING_64_CHARS);
assertThat(organization.getDescription()).isEqualTo(login + "'s personal organization");
}

@Test
public void createForUser_associates_to_built_in_quality_profiles() {
UserDto user = db.users().insertUser(A_LOGIN);
@@ -536,7 +488,6 @@ public class OrganizationUpdaterImplTest {
assertThat(db.countRowsOfTable("perm_templates_groups")).isEqualTo(0);
}


@Test
public void update_personal_organization() {
OrganizationDto organization = db.organizations().insert(o -> o.setKey("old login"));

+ 22
- 35
server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationValidationImplTest.java Переглянути файл

@@ -19,6 +19,7 @@
*/
package org.sonar.server.organization;

import com.google.common.base.Strings;
import java.util.Random;
import org.junit.Rule;
import org.junit.Test;
@@ -32,6 +33,8 @@ public class OrganizationValidationImplTest {
private static final String STRING_64_CHARS = STRING_32_CHARS + STRING_32_CHARS;
private static final String STRING_256_CHARS = STRING_64_CHARS + STRING_64_CHARS + STRING_64_CHARS + STRING_64_CHARS;

private static final String STRING_300_CHARS = Strings.repeat("a", 300);

@Rule
public ExpectedException expectedException = ExpectedException.none();

@@ -62,27 +65,22 @@ public class OrganizationValidationImplTest {
}

@Test
public void checkValidKey_does_not_fail_if_arg_is_2_to_32_chars_long() {
String str = "aa";
for (int i = 0; i < 31; i++) {
public void checkValidKey_does_not_fail_if_arg_is_1_to_300_chars_long() {
String str = "a";
for (int i = 0; i < 299; i++) {
underTest.checkKey(str);
str += "a";
}
}

@Test
public void checkValidKey_throws_IAE_if_arg_is_33_or_more_chars_long() {
String str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
underTest.checkKey(str);
for (int i = 0; i < 5 + Math.abs(new Random().nextInt(10)); i++) {
str += "c";
try {
underTest.checkKey(str);
fail("A IllegalArgumentException should have been thrown");
} catch (IllegalArgumentException e) {
assertThat(e).hasMessage("Key '" + str + "' must be at most 32 chars long");
}
}
public void checkValidKey_throws_IAE_when_more_than_300_characters() {
String key = STRING_300_CHARS + "b";

expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Key '" + key + "' must be at most 300 chars long");

underTest.checkKey(key);
}

@Test
@@ -117,27 +115,22 @@ public class OrganizationValidationImplTest {
}

@Test
public void checkValidName_does_not_fail_if_arg_is_2_to_32_chars_long() {
String str = "aa";
for (int i = 0; i < 63; i++) {
public void checkValidName_does_not_fail_if_arg_is_1_to_300_chars_long() {
String str = "a";
for (int i = 0; i < 299; i++) {
underTest.checkName(str);
str += "a";
}
}

@Test
public void checkValidName_throws_IAE_if_arg_is_65_or_more_chars_long() {
String str = STRING_64_CHARS;
public void checkValidName_throws_IAE_when_more_than_300_characters() {
String str = STRING_300_CHARS + "b";

expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Name '" + str + "' must be at most 300 chars long");

underTest.checkName(str);
for (int i = 0; i < 5 + Math.abs(new Random().nextInt(10)); i++) {
str += "c";
try {
underTest.checkName(str);
fail("A IllegalArgumentException should have been thrown");
} catch (IllegalArgumentException e) {
assertThat(e).hasMessage("Name '" + str + "' must be at most 64 chars long");
}
}
}

@Test
@@ -244,10 +237,4 @@ public class OrganizationValidationImplTest {
assertThat(underTest.generateKeyFrom("<\"foo:\">")).isEqualTo("foo");
}

@Test
public void generateKeyFrom_truncate_arg_to_32_chars() {
assertThat(underTest.generateKeyFrom(STRING_64_CHARS))
.isEqualTo(underTest.generateKeyFrom(STRING_256_CHARS))
.isEqualTo(underTest.generateKeyFrom(STRING_32_CHARS));
}
}

+ 7
- 71
server/sonar-server/src/test/java/org/sonar/server/organization/ws/CreateActionTest.java Переглянути файл

@@ -69,7 +69,6 @@ import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.mockito.Mockito.mock;
import static org.sonar.core.config.CorePropertyDefinitions.ORGANIZATIONS_ANYONE_CAN_CREATE;
import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_KEY;
import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_NAME;
import static org.sonar.server.organization.ws.OrganizationsWsTestSupport.STRING_257_CHARS_LONG;
import static org.sonar.server.organization.ws.OrganizationsWsTestSupport.STRING_65_CHARS_LONG;
@@ -280,16 +279,6 @@ public class CreateActionTest {
verifyResponseAndDb(executeRequest("ab"), "ab", "ab", NOW);
}

@Test
public void request_succeeds_if_name_is_64_char_long() {
createUserAndLogInAsSystemAdministrator();
db.qualityGates().insertBuiltInQualityGate();

String name = STRING_65_CHARS_LONG.substring(0, 64);

verifyResponseAndDb(executeRequest(name), name, name.substring(0, 32), NOW);
}

@Test
public void request_succeeds_if_key_is_2_chars_long() {
createUserAndLogInAsSystemAdministrator();
@@ -327,17 +316,6 @@ public class CreateActionTest {
verifyResponseAndDb(response, "foo", "bar", "moo", "doo", "boo", NOW);
}

@Test
public void request_succeeds_to_generate_key_from_name_more_then_32_chars_long() {
createUserAndLogInAsSystemAdministrator();
db.qualityGates().insertBuiltInQualityGate();

String name = STRING_65_CHARS_LONG.substring(0, 33);

CreateWsResponse response = executeRequest(name);
verifyResponseAndDb(response, name, name.substring(0, 32), NOW);
}

@Test
public void request_generates_key_ignoring_multiple_following_spaces() {
createUserAndLogInAsSystemAdministrator();
@@ -389,40 +367,6 @@ public class CreateActionTest {
executeRequest(null);
}

@Test
public void request_fails_if_name_is_empty() {
createUserAndLogInAsSystemAdministrator();

expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Name must not be empty");

wsTester.newRequest()
.setParam(PARAM_NAME, "")
.execute();
}

@Test
public void request_fails_if_name_is_65_chars_long() {
createUserAndLogInAsSystemAdministrator();

expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("'name' length (65) is longer than the maximum authorized (64)");

executeRequest(STRING_65_CHARS_LONG);
}

@Test
public void request_fails_if_key_is_33_chars_long() {
createUserAndLogInAsSystemAdministrator();

String key = STRING_65_CHARS_LONG.substring(0, 33);

expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("'key' length (33) is longer than the maximum authorized (32)");

executeRequest("foo", key);
}

@Test
public void requests_fails_if_key_contains_non_ascii_chars_but_dash() {
createUserAndLogInAsSystemAdministrator();
@@ -463,19 +407,6 @@ public class CreateActionTest {
executeRequest("foo", "a b");
}

@Test
public void request_fails_if_key_is_empty() {
createUserAndLogInAsSystemAdministrator();

expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Key must not be empty");

wsTester.newRequest()
.setParam(PARAM_KEY, "")
.setParam(PARAM_NAME, "foo")
.execute();
}

@Test
public void request_fails_if_key_is_specified_and_already_exists_in_DB() {
createUserAndLogInAsSystemAdministrator();
@@ -490,9 +421,9 @@ public class CreateActionTest {
@Test
public void request_fails_if_key_computed_from_name_already_exists_in_DB() {
createUserAndLogInAsSystemAdministrator();
String key = STRING_65_CHARS_LONG.substring(0, 32);
String key = "key";
db.organizations().insert(o -> o.setKey(key));
String name = STRING_65_CHARS_LONG.substring(0, 64);
String name = "Key";

expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Key '" + key + "' generated from name '" + name + "' is already used. Specify one.");
@@ -584,13 +515,18 @@ public class CreateActionTest {
assertThat(action.handler()).isNotNull();
assertThat(action.params()).hasSize(5);
assertThat(action.responseExample()).isEqualTo(getClass().getResource("create-example.json"));

assertThat(action.param("name"))
.matches(WebService.Param::isRequired)
.matches(param -> "Foo Company".equals(param.exampleValue()))
.matches(param -> param.minimumLength().equals(1))
.matches(param -> param.maximumLength().equals(300))
.matches(param -> param.description() != null);
assertThat(action.param("key"))
.matches(param -> !param.isRequired())
.matches(param -> "foo-company".equals(param.exampleValue()))
.matches(param -> param.minimumLength().equals(1))
.matches(param -> param.maximumLength().equals(300))
.matches(param -> param.description() != null);
assertThat(action.param("description"))
.matches(param -> !param.isRequired())

+ 2
- 21
server/sonar-server/src/test/java/org/sonar/server/organization/ws/UpdateActionTest.java Переглянути файл

@@ -82,6 +82,8 @@ public class UpdateActionTest {
assertThat(action.param("name"))
.matches(param -> !param.isRequired())
.matches(param -> "Foo Company".equals(param.exampleValue()))
.matches(param -> param.minimumLength().equals(1))
.matches(param -> param.maximumLength().equals(300))
.matches(param -> param.description() != null);
assertThat(action.param("description"))
.matches(param -> !param.isRequired())
@@ -172,16 +174,6 @@ public class UpdateActionTest {
verifyResponseAndDb(executeKeyRequest(org.getKey(), null), org, org.getName(), DATE_2);
}

@Test
public void request_fails_if_name_is_empty() {
userSession.logIn();

expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Name must not be empty");

executeKeyRequest(SOME_KEY, "");
}

@Test
public void request_succeeds_if_name_is_two_chars_long() {
OrganizationDto org = mockForSuccessfulUpdate(DATE_1, DATE_2);
@@ -190,17 +182,6 @@ public class UpdateActionTest {
verifyResponseAndDb(executeKeyRequest(org.getKey(), "ab"), org, "ab", DATE_2);
}

@Test
public void request_fails_if_name_is_65_chars_long() {
userSession.logIn();

expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("'name' length (65) is longer than the maximum authorized (64)");


executeKeyRequest(SOME_KEY, STRING_65_CHARS_LONG);
}

@Test
public void request_succeeds_if_name_is_64_char_long() {
OrganizationDto org = mockForSuccessfulUpdate(DATE_1, DATE_2);

Завантаження…
Відмінити
Зберегти