]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10597 Update MANUAL_MEASURES#USER_LOGIN to USER_UUID
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Fri, 11 May 2018 07:24:33 +0000 (09:24 +0200)
committerSonarTech <sonartech@sonarsource.com>
Wed, 23 May 2018 18:20:47 +0000 (20:20 +0200)
* SONAR-10597 Update MANUAL_MEASURES#USER_LOGIN to USER_UUD in DB

* SONAR-10597 Update api/custom_measures/create to use user uuid

* SONAR-10597 Update api/custom_measures/update to use user uuid

* SONAR-10597 Remove CustomMeasureDao#selectOrFail

* SONAR-10597 Update api/custom_measures/search to use user uuid

* SONAR-10597 Clean up no more needed code

* SONAR-10597 Add ITs to check manual measure after login update

29 files changed:
server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl
server/sonar-db-dao/src/main/java/org/sonar/db/measure/custom/CustomMeasureDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/measure/custom/CustomMeasureDto.java
server/sonar-db-dao/src/main/java/org/sonar/db/metric/MetricDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/user/UserDao.java
server/sonar-db-dao/src/main/resources/org/sonar/db/measure/custom/CustomMeasureMapper.xml
server/sonar-db-dao/src/test/java/org/sonar/db/measure/MeasureDbTester.java
server/sonar-db-dao/src/test/java/org/sonar/db/measure/custom/CustomMeasureDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/measure/custom/CustomMeasureTesting.java
server/sonar-db-dao/src/test/java/org/sonar/db/metric/MetricDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java
server/sonar-db-dao/src/test/resources/org/sonar/db/measure/custom/CustomMeasureDaoTest/select_by_metric_key_and_text_value.xml [deleted file]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/DbVersion72.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasures.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/DbVersion72Test.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasuresTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasuresTest/manual_measures.sql [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CreateAction.java
server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CustomMeasureJsonWriter.java
server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/DeleteAction.java
server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/UpdateAction.java
server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/CreateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/DeleteActionTest.java
server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/SearchActionTest.java
server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/UpdateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/user/ws/ChangePasswordActionTest.java
server/sonar-server/src/test/resources/org/sonar/server/measure/custom/ws/CreateActionTest/custom-measure.json [deleted file]
tests/src/test/java/org/sonarqube/tests/user/SonarCloudUpdateLoginDuringAuthenticationTest.java

index 3c5de10a498184fa2a83bed52e1afcf0c1b7ef27..4f8a73a1ff45f84b122c78f02a29655af68e0ca5 100644 (file)
@@ -404,7 +404,7 @@ CREATE TABLE "MANUAL_MEASURES" (
   "COMPONENT_UUID" VARCHAR(50) NOT NULL,
   "VALUE" DOUBLE,
   "TEXT_VALUE" VARCHAR(4000),
-  "USER_LOGIN" VARCHAR(255),
+  "USER_UUID" VARCHAR(255),
   "DESCRIPTION" VARCHAR(4000),
   "CREATED_AT" BIGINT,
   "UPDATED_AT" BIGINT
index 0f0aa3887d114994e694947f5b11d21f246397da..0530d537580db8e93db4b3a37e7709514d44f502 100644 (file)
@@ -25,7 +25,6 @@ import org.apache.ibatis.session.RowBounds;
 import org.sonar.db.Dao;
 import org.sonar.db.DatabaseUtils;
 import org.sonar.db.DbSession;
-import org.sonar.db.RowNotFoundException;
 
 public class CustomMeasureDao implements Dao {
   public void insert(DbSession session, CustomMeasureDto customMeasureDto) {
@@ -49,14 +48,6 @@ public class CustomMeasureDao implements Dao {
     return mapper(session).selectById(id);
   }
 
-  public CustomMeasureDto selectOrFail(DbSession session, long id) {
-    CustomMeasureDto customMeasure = selectById(session, id);
-    if (customMeasure == null) {
-      throw new RowNotFoundException(String.format("Custom measure '%d' not found.", id));
-    }
-    return customMeasure;
-  }
-
   public List<CustomMeasureDto> selectByMetricId(DbSession session, int metricId) {
     return mapper(session).selectByMetricId(metricId);
   }
index 0282bce1a26d9f5f172450e6de0f14f2457fa61d..4cf4d0f41a8d1fe933cb6ed6605f89ce30fec3ae 100644 (file)
@@ -29,26 +29,27 @@ public class CustomMeasureDto {
   private String componentUuid;
   private double value;
   private String textValue;
-  private String userLogin;
+  private String userUuid;
   private String description;
   private long createdAt;
   private long updatedAt;
 
+  @CheckForNull
   public String getDescription() {
     return description;
   }
 
-  public CustomMeasureDto setDescription(String description) {
+  public CustomMeasureDto setDescription(@Nullable String description) {
     this.description = description;
     return this;
   }
 
-  public String getUserLogin() {
-    return userLogin;
+  public String getUserUuid() {
+    return userUuid;
   }
 
-  public CustomMeasureDto setUserLogin(String userLogin) {
-    this.userLogin = userLogin;
+  public CustomMeasureDto setUserUuid(String userUuid) {
+    this.userUuid = userUuid;
     return this;
   }
 
index 0f27ac2bae9b9ac6817d0cc2c972e5022f7f66c9..344cbb6e1643a1a95ad516296b70eaba596aef10 100644 (file)
@@ -141,11 +141,4 @@ public class MetricDao implements Dao {
     return mapper(session).selectById(id);
   }
 
-  public MetricDto selectOrFailById(DbSession session, long id) {
-    MetricDto metric = mapper(session).selectById(id);
-    if (metric == null) {
-      throw new RowNotFoundException(String.format("Metric id '%d' not found", id));
-    }
-    return metric;
-  }
 }
index 4bd8de97b522514f602f1848840eef23b25cfb65..79318d4d02a6811977803babc3fa9610a054da95 100644 (file)
@@ -35,7 +35,6 @@ import org.sonar.api.utils.System2;
 import org.sonar.core.util.UuidFactory;
 import org.sonar.db.Dao;
 import org.sonar.db.DbSession;
-import org.sonar.db.RowNotFoundException;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
 
@@ -153,14 +152,6 @@ public class UserDao implements Dao {
     return mapper(session).selectByLogin(login);
   }
 
-  public UserDto selectOrFailByLogin(DbSession session, String login) {
-    UserDto user = selectByLogin(session, login);
-    if (user == null) {
-      throw new RowNotFoundException(String.format("User with login '%s' has not been found", login));
-    }
-    return user;
-  }
-
   public List<UserDto> selectByScmAccountOrLoginOrEmail(DbSession session, String scmAccountOrLoginOrEmail) {
     String like = new StringBuilder().append("%")
       .append(UserDto.SCM_ACCOUNTS_SEPARATOR).append(scmAccountOrLoginOrEmail)
index 8735cb8dea5da5db7230340c6bcff8736ee85f87..ef334040b4282e8f709036c0cef967d4a81ae5eb 100644 (file)
@@ -8,7 +8,7 @@
     m.component_uuid as componentUuid,
     m.value,
     m.text_value as textValue,
-    m.user_login as userLogin,
+    m.user_uuid as userUuid,
     m.description,
     m.created_at as createdAt,
     m.updated_at as updatedAt
 
   <insert id="insert" parameterType="CustomMeasure" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
     INSERT INTO manual_measures (
-    metric_id, component_uuid, value, text_value, user_login, description, created_at, updated_at
+    metric_id, component_uuid, value, text_value, user_uuid, description, created_at, updated_at
     )
     VALUES (
     #{metricId, jdbcType=INTEGER}, #{componentUuid, jdbcType=VARCHAR},
-    #{value, jdbcType=DOUBLE}, #{textValue, jdbcType=VARCHAR}, #{userLogin, jdbcType=VARCHAR},
+    #{value, jdbcType=DOUBLE}, #{textValue, jdbcType=VARCHAR}, #{userUuid, jdbcType=VARCHAR},
     #{description, jdbcType=VARCHAR}, #{createdAt, jdbcType=BIGINT}, #{updatedAt, jdbcType=BIGINT}
     )
   </insert>
@@ -61,7 +61,7 @@
     set value = #{value, jdbcType=DOUBLE},
     text_value = #{textValue, jdbcType=VARCHAR},
     description = #{description, jdbcType=VARCHAR},
-    user_login = #{userLogin, jdbcType=VARCHAR},
+    user_uuid = #{userUuid, jdbcType=VARCHAR},
     updated_at = #{updatedAt, jdbcType=BIGINT}
     where id = #{id}
   </update>
index dd5289151b37cd3524b0af6a8af31108473b3a8b..597fdddc18ca87a8f237b837f5cb7da36f1c3069 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.db.measure;
 
+import com.google.common.base.Preconditions;
 import java.util.Arrays;
 import java.util.function.Consumer;
 import org.sonar.db.DbClient;
@@ -26,10 +27,13 @@ import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.measure.custom.CustomMeasureDto;
 import org.sonar.db.metric.MetricDto;
+import org.sonar.db.user.UserDto;
 
 import static org.sonar.db.measure.MeasureTesting.newLiveMeasure;
 import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
+import static org.sonar.db.measure.custom.CustomMeasureTesting.newCustomMeasureDto;
 import static org.sonar.db.metric.MetricTesting.newMetricDto;
 
 public class MeasureDbTester {
@@ -42,7 +46,7 @@ public class MeasureDbTester {
   }
 
   @SafeVarargs
-  public final MeasureDto insertMeasure(ComponentDto component, SnapshotDto analysis, MetricDto metricDto, Consumer<MeasureDto>... consumers){
+  public final MeasureDto insertMeasure(ComponentDto component, SnapshotDto analysis, MetricDto metricDto, Consumer<MeasureDto>... consumers) {
     MeasureDto measureDto = newMeasureDto(metricDto, component, analysis);
     Arrays.stream(consumers).forEach(c -> c.accept(measureDto));
     dbClient.measureDao().insert(dbSession, measureDto);
@@ -51,7 +55,7 @@ public class MeasureDbTester {
   }
 
   @SafeVarargs
-  public final LiveMeasureDto insertLiveMeasure(ComponentDto component, MetricDto metric, Consumer<LiveMeasureDto>... consumers){
+  public final LiveMeasureDto insertLiveMeasure(ComponentDto component, MetricDto metric, Consumer<LiveMeasureDto>... consumers) {
     LiveMeasureDto dto = newLiveMeasure(component, metric);
     Arrays.stream(consumers).forEach(c -> c.accept(dto));
     dbClient.liveMeasureDao().insert(dbSession, dto);
@@ -60,7 +64,17 @@ public class MeasureDbTester {
   }
 
   @SafeVarargs
-  public final MetricDto insertMetric(Consumer<MetricDto>... consumers){
+  public final CustomMeasureDto insertCustomMeasure(UserDto user, ComponentDto component, MetricDto metricDto, Consumer<CustomMeasureDto>... consumers) {
+    Preconditions.checkArgument(metricDto.isUserManaged(),"Custom measure must be created from a custom metric");
+    CustomMeasureDto dto = newCustomMeasureDto().setUserUuid(user.getUuid()).setComponentUuid(component.uuid()).setMetricId(metricDto.getId());
+    Arrays.stream(consumers).forEach(c -> c.accept(dto));
+    dbClient.customMeasureDao().insert(dbSession, dto);
+    dbSession.commit();
+    return dto;
+  }
+
+  @SafeVarargs
+  public final MetricDto insertMetric(Consumer<MetricDto>... consumers) {
     MetricDto metricDto = newMetricDto();
     Arrays.stream(consumers).forEach(c -> c.accept(metricDto));
     dbClient.metricDao().insert(dbSession, metricDto);
index 4f4adcac167729953146e78cf449ac0cf914dcce..ef24c3fbb3b299800207600faf170be414f86cd8 100644 (file)
  */
 package org.sonar.db.measure.custom;
 
-import java.util.Arrays;
 import java.util.List;
-import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
-import org.sonar.db.RowNotFoundException;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.metric.MetricDto;
+import org.sonar.db.user.UserDto;
 
+import static java.util.Collections.singletonList;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.offset;
+import static org.assertj.core.api.Assertions.tuple;
 import static org.sonar.db.measure.custom.CustomMeasureTesting.newCustomMeasureDto;
 
-
 public class CustomMeasureDaoTest {
   @Rule
   public DbTester db = DbTester.create(System2.INSTANCE);
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
 
-  CustomMeasureDao underTest;
-  DbSession session;
+  private DbSession session = db.getSession();
 
-  @Before
-  public void setUp() {
-    session = db.getSession();
-    underTest = new CustomMeasureDao();
-  }
+  private CustomMeasureDao underTest = new CustomMeasureDao();
 
   @Test
   public void insert() {
-    CustomMeasureDto measure = newCustomMeasureDto();
+    UserDto user = db.users().insertUser();
+    ComponentDto project = db.components().insertPrivateProject();
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true));
+    CustomMeasureDto measure = newCustomMeasureDto()
+      .setComponentUuid(project.uuid())
+      .setMetricId(metric.getId())
+      .setUserUuid(user.getUuid());
 
     underTest.insert(session, measure);
 
-    CustomMeasureDto result = underTest.selectOrFail(session, measure.getId());
+    CustomMeasureDto result = underTest.selectById(session, measure.getId());
     assertThat(result.getId()).isEqualTo(measure.getId());
-    assertThat(result.getMetricId()).isEqualTo(measure.getMetricId());
-    assertThat(result.getComponentUuid()).isEqualTo(measure.getComponentUuid());
+    assertThat(result.getMetricId()).isEqualTo(metric.getId());
+    assertThat(result.getComponentUuid()).isEqualTo(project.uuid());
+    assertThat(result.getUserUuid()).isEqualTo(user.getUuid());
     assertThat(result.getDescription()).isEqualTo(measure.getDescription());
-    assertThat(result.getUserLogin()).isEqualTo(measure.getUserLogin());
     assertThat(result.getTextValue()).isEqualTo(measure.getTextValue());
     assertThat(result.getValue()).isCloseTo(measure.getValue(), offset(0.001d));
     assertThat(result.getCreatedAt()).isEqualTo(measure.getCreatedAt());
@@ -70,60 +69,76 @@ public class CustomMeasureDaoTest {
 
   @Test
   public void delete_by_metric_id() {
-    CustomMeasureDto measure = newCustomMeasureDto();
-    underTest.insert(session, measure);
-    assertThat(underTest.selectById(session, measure.getId())).isNotNull();
+    UserDto user = db.users().insertUser();
+    ComponentDto project = db.components().insertPrivateProject();
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true));
+    CustomMeasureDto measure = db.measures().insertCustomMeasure(user, project, metric);
 
-    underTest.deleteByMetricIds(session, Arrays.asList(measure.getMetricId()));
+    underTest.deleteByMetricIds(session, singletonList(measure.getMetricId()));
 
     assertThat(underTest.selectById(session, measure.getId())).isNull();
   }
 
   @Test
   public void update() {
-    CustomMeasureDto measure = newCustomMeasureDto().setDescription("old-description");
-    underTest.insert(session, measure);
-    measure.setDescription("new-description");
+    UserDto user = db.users().insertUser();
+    ComponentDto project = db.components().insertPrivateProject();
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true));
+    CustomMeasureDto measure = db.measures().insertCustomMeasure(user, project, metric, m -> m.setDescription("old-description"));
 
-    underTest.update(session, measure);
+    underTest.update(session, measure.setDescription("new-description"));
 
     assertThat(underTest.selectById(session, measure.getId()).getDescription()).isEqualTo("new-description");
   }
 
   @Test
   public void delete() {
-    CustomMeasureDto measure = newCustomMeasureDto();
-    underTest.insert(session, measure);
+    UserDto user = db.users().insertUser();
+    ComponentDto project = db.components().insertPrivateProject();
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true));
+    CustomMeasureDto measure = db.measures().insertCustomMeasure(user, project, metric);
 
     underTest.delete(session, measure.getId());
+
     assertThat(underTest.selectById(session, measure.getId())).isNull();
   }
 
   @Test
   public void select_by_component_uuid() {
-    underTest.insert(session, newCustomMeasureDto().setComponentUuid("u1"));
-    underTest.insert(session, newCustomMeasureDto().setComponentUuid("u1"));
-    underTest.insert(session, newCustomMeasureDto().setComponentUuid("u2"));
-    session.commit();
-
-    List<CustomMeasureDto> result = underTest.selectByComponentUuid(session, "u1");
-
-    assertThat(result).hasSize(2);
-    assertThat(result).extracting("componentUuid").containsOnly("u1");
-    assertThat(underTest.countByComponentUuid(session, "u1")).isEqualTo(2);
+    UserDto user = db.users().insertUser();
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true));
+    ComponentDto project1 = db.components().insertPrivateProject();
+    CustomMeasureDto measure1 = db.measures().insertCustomMeasure(user, project1, metric);
+    CustomMeasureDto measure2 = db.measures().insertCustomMeasure(user, project1, metric);
+    ComponentDto project2 = db.components().insertPrivateProject();
+    CustomMeasureDto measure3 = db.measures().insertCustomMeasure(user, project2, metric);
+
+    assertThat(underTest.selectByComponentUuid(session, project1.uuid()))
+      .extracting(CustomMeasureDto::getId, CustomMeasureDto::getComponentUuid)
+      .containsOnly(
+        tuple(measure1.getId(), project1.uuid()),
+        tuple(measure2.getId(), project1.uuid()))
+      .doesNotContain(tuple(measure3.getId(), project2.uuid()));
+
+    assertThat(underTest.countByComponentUuid(session, project1.uuid())).isEqualTo(2);
   }
 
   @Test
   public void select_by_component_uuid_with_options() {
-    underTest.insert(session, newCustomMeasureDto().setComponentUuid("u1"));
-    underTest.insert(session, newCustomMeasureDto().setComponentUuid("u1"));
-    underTest.insert(session, newCustomMeasureDto().setComponentUuid("u2"));
-    session.commit();
-
-    List<CustomMeasureDto> result = underTest.selectByComponentUuid(session, "u1", 0, 100);
-
-    assertThat(result).hasSize(2);
-    assertThat(result).extracting("componentUuid").containsOnly("u1");
+    UserDto user = db.users().insertUser();
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true));
+    ComponentDto project1 = db.components().insertPrivateProject();
+    CustomMeasureDto measure1 = db.measures().insertCustomMeasure(user, project1, metric);
+    CustomMeasureDto measure2 = db.measures().insertCustomMeasure(user, project1, metric);
+    ComponentDto project2 = db.components().insertPrivateProject();
+    CustomMeasureDto measure3 = db.measures().insertCustomMeasure(user, project2, metric);
+
+    assertThat(underTest.selectByComponentUuid(session, project1.uuid(), 0, 100))
+      .extracting(CustomMeasureDto::getId, CustomMeasureDto::getComponentUuid)
+      .containsOnly(
+        tuple(measure1.getId(), project1.uuid()),
+        tuple(measure2.getId(), project1.uuid()))
+      .doesNotContain(tuple(measure3.getId(), project2.uuid()));
   }
 
   @Test
@@ -146,22 +161,21 @@ public class CustomMeasureDaoTest {
     assertThat(count).isEqualTo(2);
   }
 
-  @Test
-  public void select_by_id_fail_if_no_measure_found() {
-    expectedException.expect(RowNotFoundException.class);
-
-    underTest.selectOrFail(session, 42L);
-  }
-
   @Test
   public void select_by_metric_key_and_text_value() {
-    db.prepareDbUnit(getClass(), "select_by_metric_key_and_text_value.xml");
-
-    List<CustomMeasureDto> result = underTest.selectByMetricKeyAndTextValue(session, "customKey", "value1");
-
-    assertThat(result).extracting("id").containsOnly(20L, 21L);
-
-    assertThat(underTest.selectByMetricKeyAndTextValue(session, "customKey", "unknown")).isEmpty();
-    assertThat(underTest.selectByMetricKeyAndTextValue(session, "unknown", "value1")).isEmpty();
+    UserDto user = db.users().insertUser();
+    ComponentDto project = db.components().insertPrivateProject();
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true));
+    CustomMeasureDto customMeasure1 = db.measures().insertCustomMeasure(user, project, metric, m -> m.setTextValue("value"));
+    CustomMeasureDto customMeasure2 = db.measures().insertCustomMeasure(user, project, metric, m -> m.setTextValue("value"));
+    CustomMeasureDto customMeasure3 = db.measures().insertCustomMeasure(user, project, metric, m -> m.setTextValue("other value"));
+
+    assertThat(underTest.selectByMetricKeyAndTextValue(session, metric.getKey(), "value"))
+      .extracting(CustomMeasureDto::getId)
+      .containsExactlyInAnyOrder(customMeasure1.getId(), customMeasure2.getId())
+      .doesNotContain(customMeasure3.getId());
+
+    assertThat(underTest.selectByMetricKeyAndTextValue(session, metric.getKey(), "unknown")).isEmpty();
+    assertThat(underTest.selectByMetricKeyAndTextValue(session, "unknown", "value")).isEmpty();
   }
 }
index 90dd2db8b806bb14b49b397d69087ba83ebb8dfe..4e812989b8d875c0a0d1e526115f0dc6a7ff89dc 100644 (file)
@@ -32,7 +32,7 @@ public class CustomMeasureTesting {
     return new CustomMeasureDto()
       .setDescription(RandomStringUtils.randomAlphanumeric(255))
       .setTextValue(RandomStringUtils.randomAlphanumeric(255))
-      .setUserLogin(RandomStringUtils.randomAlphanumeric(255))
+      .setUserUuid("userUuid" + RandomStringUtils.randomAlphanumeric(100))
       .setValue(RandomUtils.nextDouble())
       .setMetricId(RandomUtils.nextInt())
       .setComponentUuid(RandomStringUtils.randomAlphanumeric(50))
index 34dbc169e36e2d59636197bd614178befd9a79da..6e56af068edfea072fd46c5214026a45e20dbb25 100644 (file)
@@ -197,22 +197,6 @@ public class MetricDaoTest {
     assertThat(result).isNotNull();
   }
 
-  @Test
-  public void selectOrFailById() {
-    MetricDto metric = underTest.insert(dbSession, newMetricDto());
-
-    MetricDto result = underTest.selectOrFailById(dbSession, metric.getId());
-
-    assertThat(result).isNotNull();
-  }
-
-  @Test
-  public void fail_when_no_id_selectOrFailById() {
-    expectedException.expect(RowNotFoundException.class);
-
-    underTest.selectOrFailById(dbSession, 42L);
-  }
-
   @Test
   public void selectByIds() {
     MetricDto metric1 = underTest.insert(dbSession, newMetricDto());
index 7a725cf13be839399536d4664d8b8a4f3247f0c2..1ca0e6a9c01420cab03affa7bea96ae3325a60df 100644 (file)
@@ -26,7 +26,6 @@ import java.util.List;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 import org.sonar.api.user.UserQuery;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.System2;
@@ -34,7 +33,6 @@ import org.sonar.db.DatabaseUtils;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
-import org.sonar.db.RowNotFoundException;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
 
@@ -43,7 +41,6 @@ import static java.util.Collections.emptyList;
 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.groups.Tuple.tuple;
-import static org.junit.Assert.fail;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.sonar.db.user.GroupTesting.newGroupDto;
@@ -54,8 +51,6 @@ public class UserDaoTest {
 
   private System2 system2 = mock(System2.class);
 
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
   @Rule
   public DbTester db = DbTester.create(system2);
 
@@ -509,7 +504,7 @@ public class UserDaoTest {
     underTest.insert(session, user);
     session.commit();
 
-    underTest.cleanHomepage(session,user);
+    underTest.cleanHomepage(session, user);
 
     UserDto reloaded = underTest.selectUserById(session, user.getId());
     assertThat(reloaded.getUpdatedAt()).isEqualTo(NOW);
@@ -538,7 +533,7 @@ public class UserDaoTest {
     UserDto user2 = db.users().insertUser();
     underTest.setRoot(session, user2.getLogin(), true);
 
-    UserDto dto = underTest.selectOrFailByLogin(session, user1.getLogin());
+    UserDto dto = underTest.selectByLogin(session, user1.getLogin());
     assertThat(dto.getId()).isEqualTo(user1.getId());
     assertThat(dto.getLogin()).isEqualTo("marius");
     assertThat(dto.getName()).isEqualTo("Marius");
@@ -553,7 +548,7 @@ public class UserDaoTest {
     assertThat(dto.getHomepageType()).isEqualTo("project");
     assertThat(dto.getHomepageParameter()).isEqualTo("OB1");
 
-    dto = underTest.selectOrFailByLogin(session, user2.getLogin());
+    dto = underTest.selectByLogin(session, user2.getLogin());
     assertThat(dto.isRoot()).isTrue();
   }
 
@@ -579,16 +574,6 @@ public class UserDaoTest {
     assertThat(results).hasSize(2);
   }
 
-  @Test
-  public void select_by_login_with_unknown_login() {
-    try {
-      underTest.selectOrFailByLogin(session, "unknown");
-      fail();
-    } catch (Exception e) {
-      assertThat(e).isInstanceOf(RowNotFoundException.class).hasMessage("User with login 'unknown' has not been found");
-    }
-  }
-
   @Test
   public void select_nullable_by_login() {
     db.users().insertUser(user -> user.setLogin("marius"));
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/measure/custom/CustomMeasureDaoTest/select_by_metric_key_and_text_value.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/measure/custom/CustomMeasureDaoTest/select_by_metric_key_and_text_value.xml
deleted file mode 100644 (file)
index ff00f75..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<dataset>
-
-  <metrics id="10" name="ncloc"/>
-  <metrics id="11" name="customKey"/>
-
-  <manual_measures id="20" metric_id="11" component_uuid="ABCD" value="[null]" text_value="value1"
-                  user_login="seb" description="" created_at="123456789" updated_at="123456789" />
-  <manual_measures id="21" metric_id="11" component_uuid="BCDE" value="[null]" text_value="value1"
-                  user_login="seb" description="" created_at="123456789" updated_at="123456789" />
-  <manual_measures id="22" metric_id="11" component_uuid="CDEF" value="[null]" text_value="value2"
-                  user_login="seb" description="" created_at="123456789" updated_at="123456789" />
-
-
-</dataset>
index c8cf8a2fbb1375cf4c0ec0af54f68bd7e010d4ef..20d40419ebe02e9bf66c11e62fe216d309d593a2 100644 (file)
@@ -47,6 +47,7 @@ public class DbVersion72 implements DbVersion {
       .add(2117, "Drop USER_ID from table organizations", DropUserIdFromOrganizations.class)
       .add(2118, "Rename USER_LOGIN TO USER_UUID on table QPROFILE_CHANGES", RenameUserLoginToUserUuidOnTableQProfileChanges.class)
       .add(2119, "Rename LOGIN TO USER_UUID on table USER_TOKENS", RenameLoginToUserUuidOnTableUserTokens.class)
+      .add(2120, "Rename USER_LOGIN TO USER_UUID on table MANUAL_MEASURES", RenameUserLoginToUserUuidOnTableManualMeasures.class);
     ;
   }
 }
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasures.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasures.java
new file mode 100644 (file)
index 0000000..924ab02
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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.v72;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.sql.RenameColumnsBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class RenameUserLoginToUserUuidOnTableManualMeasures extends DdlChange {
+
+  private static final String TABLE = "manual_measures";
+
+  public RenameUserLoginToUserUuidOnTableManualMeasures(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(new RenameColumnsBuilder(getDialect(), TABLE)
+      .renameColumn("user_login",
+        newVarcharColumnDefBuilder()
+          .setColumnName("user_uuid")
+          .setLimit(255)
+          .setIsNullable(true)
+          .build())
+      .build());
+  }
+}
index 4cd2886c5681839362d9f5fc6d9cffa3a6586bfa..87922b1bf3944e944b417558e10e8e6f003fbf12 100644 (file)
@@ -34,7 +34,7 @@ public class DbVersion72Test {
 
   @Test
   public void verify_migration_count() {
-    verifyMigrationCount(underTest, 20);
+    verifyMigrationCount(underTest, 21);
   }
 
 }
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasuresTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasuresTest.java
new file mode 100644 (file)
index 0000000..2ab573a
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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.v72;
+
+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 RenameUserLoginToUserUuidOnTableManualMeasuresTest {
+
+  @Rule
+  public final CoreDbTester db = CoreDbTester.createForSchema(RenameUserLoginToUserUuidOnTableManualMeasuresTest.class, "manual_measures.sql");
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private RenameUserLoginToUserUuidOnTableManualMeasures underTest = new RenameUserLoginToUserUuidOnTableManualMeasures(db.database());
+
+  @Test
+  public void rename_column() throws SQLException {
+    underTest.execute();
+
+    db.assertColumnDefinition("manual_measures", "user_uuid", VARCHAR, 255, true);
+    db.assertColumnDoesNotExist("manual_measures", "user_login");
+  }
+
+  public void migration_is_not_reentrant() throws SQLException {
+    underTest.execute();
+
+    expectedException.expect(IllegalStateException.class);
+
+    underTest.execute();
+  }
+
+}
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasuresTest/manual_measures.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v72/RenameUserLoginToUserUuidOnTableManualMeasuresTest/manual_measures.sql
new file mode 100644 (file)
index 0000000..598cb68
--- /dev/null
@@ -0,0 +1,12 @@
+CREATE TABLE "MANUAL_MEASURES" (
+  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "METRIC_ID" INTEGER NOT NULL,
+  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+  "VALUE" DOUBLE,
+  "TEXT_VALUE" VARCHAR(4000),
+  "USER_LOGIN" VARCHAR(255),
+  "DESCRIPTION" VARCHAR(4000),
+  "CREATED_AT" BIGINT,
+  "UPDATED_AT" BIGINT
+);
+CREATE INDEX "MANUAL_MEASURES_COMPONENT_UUID" ON "MANUAL_MEASURES" ("COMPONENT_UUID");
\ No newline at end of file
index 658c23167db1a5f4150e0830876ae8b1f0da06d2..69dbbe4e213718bc322d563ce2cd81be9a9f3304 100644 (file)
@@ -35,6 +35,8 @@ import org.sonar.server.component.ComponentFinder;
 import org.sonar.server.user.UserSession;
 
 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.sonar.server.component.ComponentFinder.ParamNames.PROJECT_ID_AND_KEY;
 import static org.sonar.server.measure.custom.ws.CustomMeasureValidator.checkPermissions;
 import static org.sonar.server.measure.custom.ws.CustomMeasureValueDescription.measureValueDescription;
@@ -115,12 +117,14 @@ public class CreateAction implements CustomMeasuresWsAction {
       checkPermissions(userSession, component);
       checkIsProjectOrModule(component);
       checkMeasureDoesNotExistAlready(dbSession, component, metric);
-      UserDto user = dbClient.userDao().selectOrFailByLogin(dbSession, userSession.getLogin());
+      String userUuid = requireNonNull(userSession.getUuid(), "User uuid should not be null");
+      UserDto user = dbClient.userDao().selectByUuid(dbSession, userUuid);
+      checkState(user != null, "User with uuid '%s' does not exist", userUuid);
       CustomMeasureDto measure = new CustomMeasureDto()
         .setComponentUuid(component.uuid())
         .setMetricId(metric.getId())
         .setDescription(description)
-        .setUserLogin(user.getLogin())
+        .setUserUuid(user.getUuid())
         .setCreatedAt(now)
         .setUpdatedAt(now);
       validator.setMeasureValue(measure, valueAsString, metric);
@@ -134,14 +138,14 @@ public class CreateAction implements CustomMeasuresWsAction {
   }
 
   private static void checkIsProjectOrModule(ComponentDto component) {
-    checkRequest(Scopes.PROJECT.equals(component.scope()), "Component '%s' (id: %s) must be a project or a module.", component.getDbKey(), component.uuid());
+    checkRequest(Scopes.PROJECT.equals(component.scope()), "Component '%s' must be a project or a module.", component.getDbKey());
   }
 
   private void checkMeasureDoesNotExistAlready(DbSession dbSession, ComponentDto component, MetricDto metric) {
     int nbMeasuresOnSameMetricAndMeasure = dbClient.customMeasureDao().countByComponentIdAndMetricId(dbSession, component.uuid(), metric.getId());
     checkRequest(nbMeasuresOnSameMetricAndMeasure == 0,
-      "A measure already exists for project '%s' (id: %s) and metric '%s' (id: '%d')",
-      component.getDbKey(), component.uuid(), metric.getKey(), metric.getId());
+      "A measure already exists for project '%s' and metric '%s'",
+      component.getDbKey(), metric.getKey());
   }
 
   private MetricDto searchMetric(DbSession dbSession, Request request) {
@@ -149,10 +153,13 @@ public class CreateAction implements CustomMeasuresWsAction {
     String metricKey = request.param(PARAM_METRIC_KEY);
     checkArgument(metricId != null ^ metricKey != null, "Either the metric id or the metric key must be provided");
 
-    if (metricId != null) {
-      return dbClient.metricDao().selectOrFailById(dbSession, metricId);
+    if (metricId == null) {
+      MetricDto metric = dbClient.metricDao().selectByKey(dbSession, metricKey);
+      checkArgument(metric != null, "Metric with key '%s' does not exist", metricKey);
+      return metric;
     }
-
-    return dbClient.metricDao().selectOrFailByKey(dbSession, metricKey);
+    MetricDto metric = dbClient.metricDao().selectById(dbSession, metricId);
+    checkArgument(metric != null, "Metric with id '%s' does not exist", metricId);
+    return metric;
   }
 }
index 117570c2a95c7269d241b09782574cbfaaa44639..c686e3ab0932e0a2844604c0ad01c45bbd135613 100644 (file)
@@ -22,8 +22,6 @@ package org.sonar.server.measure.custom.ws;
 import com.google.common.collect.ImmutableSet;
 import java.util.Collection;
 import java.util.Date;
-import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import javax.annotation.Nullable;
 import org.sonar.api.measures.Metric;
@@ -59,7 +57,8 @@ public class CustomMeasureJsonWriter {
     this.userJsonWriter = userJsonWriter;
   }
 
-  public void write(JsonWriter json, CustomMeasureDto measure, MetricDto metric, ComponentDto component, UserDto user, boolean isPending, Collection<String> fieldsToReturn) {
+  public void write(JsonWriter json, CustomMeasureDto measure, MetricDto metric, ComponentDto component, UserDto user, boolean isPending,
+    @Nullable Collection<String> fieldsToReturn) {
     json.beginObject();
     json.prop(FIELD_ID, String.valueOf(measure.getId()));
     writeIfNeeded(json, measureValue(measure, metric), FIELD_VALUE, fieldsToReturn);
@@ -109,14 +108,4 @@ public class CustomMeasureJsonWriter {
     }
   }
 
-  public void write(JsonWriter json, List<CustomMeasureDto> customMeasures, ComponentDto project, Map<Integer, MetricDto> metricsById, Map<String, UserDto> usersByLogin,
-    @Nullable Long lastAnalysisTimestamp, Collection<String> fieldsToReturn) {
-    json.name("customMeasures");
-    json.beginArray();
-    for (CustomMeasureDto customMeasure : customMeasures) {
-      boolean pending = lastAnalysisTimestamp == null || lastAnalysisTimestamp < customMeasure.getUpdatedAt();
-      write(json, customMeasure, metricsById.get(customMeasure.getMetricId()), project, usersByLogin.get(customMeasure.getUserLogin()), pending, fieldsToReturn);
-    }
-    json.endArray();
-  }
 }
index 2ab63b636280092d5598f1d2d5fb0b35eb526b68..e9130a9d4afdf00df0eee1d6d289f647d716824c 100644 (file)
@@ -29,6 +29,8 @@ import org.sonar.db.component.ComponentDto;
 import org.sonar.db.measure.custom.CustomMeasureDto;
 import org.sonar.server.user.UserSession;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 public class DeleteAction implements CustomMeasuresWsAction {
 
   private static final String ACTION = "delete";
@@ -61,7 +63,8 @@ public class DeleteAction implements CustomMeasuresWsAction {
     long id = request.mandatoryParamAsLong(PARAM_ID);
 
     try (DbSession dbSession = dbClient.openSession(false)) {
-      CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectOrFail(dbSession, id);
+      CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectById(dbSession, id);
+      checkArgument(customMeasure != null, "Custom measure with id '%s' does not exist", id);
       checkPermission(dbSession, customMeasure);
       dbClient.customMeasureDao().delete(dbSession, id);
       dbSession.commit();
index f6aa74f6be835eae8f852426aeebd544e2082fb6..14af7c1a21ce0cb3c29a7fd1f056e75a4a05f383 100644 (file)
 package org.sonar.server.measure.custom.ws;
 
 import com.google.common.base.Function;
-import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -33,6 +34,7 @@ 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.utils.text.JsonWriter;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -103,10 +105,10 @@ public class SearchAction implements CustomMeasuresWsAction {
       Long lastAnalysisDateMs = searchLastSnapshotDate(dbSession, component);
       List<CustomMeasureDto> customMeasures = searchCustomMeasures(dbSession, component, searchOptions);
       int nbCustomMeasures = countTotalOfCustomMeasures(dbSession, component);
-      Map<String, UserDto> usersByLogin = usersByLogin(dbSession, customMeasures);
+      Map<String, UserDto> usersByUuid = usersByUuid(dbSession, customMeasures);
       Map<Integer, MetricDto> metricsById = metricsById(dbSession, customMeasures);
 
-      writeResponse(response, customMeasures, nbCustomMeasures, component, metricsById, usersByLogin, lastAnalysisDateMs, searchOptions, fieldsToReturn);
+      writeResponse(response, customMeasures, nbCustomMeasures, component, metricsById, usersByUuid, lastAnalysisDateMs, searchOptions, fieldsToReturn);
     }
   }
 
@@ -126,44 +128,36 @@ public class SearchAction implements CustomMeasuresWsAction {
   }
 
   private void writeResponse(Response response, List<CustomMeasureDto> customMeasures, int nbCustomMeasures, ComponentDto project, Map<Integer, MetricDto> metricsById,
-    Map<String, UserDto> usersByLogin, @Nullable Long lastAnalysisDate, SearchOptions searchOptions, List<String> fieldsToReturn) {
+    Map<String, UserDto> usersByUuid, @Nullable Long lastAnalysisDate, SearchOptions searchOptions, @Nullable List<String> fieldsToReturn) {
     JsonWriter json = response.newJsonWriter();
     json.beginObject();
-    customMeasureJsonWriter.write(json, customMeasures, project, metricsById, usersByLogin, lastAnalysisDate, fieldsToReturn);
+    writeUsers(json, customMeasures, project, metricsById, usersByUuid, lastAnalysisDate, fieldsToReturn);
     searchOptions.writeJson(json, nbCustomMeasures);
     json.endObject();
     json.close();
   }
 
+  private void writeUsers(JsonWriter json, List<CustomMeasureDto> customMeasures, ComponentDto project, Map<Integer, MetricDto> metricsById, Map<String, UserDto> usersByUuids,
+    @Nullable Long lastAnalysisTimestamp, @Nullable Collection<String> fieldsToReturn) {
+    json.name("customMeasures");
+    json.beginArray();
+    for (CustomMeasureDto customMeasure : customMeasures) {
+      boolean pending = lastAnalysisTimestamp == null || lastAnalysisTimestamp < customMeasure.getUpdatedAt();
+      customMeasureJsonWriter.write(json, customMeasure, metricsById.get(customMeasure.getMetricId()), project, usersByUuids.get(customMeasure.getUserUuid()), pending,
+        fieldsToReturn);
+    }
+    json.endArray();
+  }
+
   private Map<Integer, MetricDto> metricsById(DbSession dbSession, List<CustomMeasureDto> customMeasures) {
     List<MetricDto> metrics = dbClient.metricDao().selectByIds(dbSession, newHashSet(Lists.transform(customMeasures, CustomMeasureToMetricIdFunction.INSTANCE)));
     return Maps.uniqueIndex(metrics, MetricToIdFunction.INSTANCE);
   }
 
-  private Map<String, UserDto> usersByLogin(DbSession dbSession, List<CustomMeasureDto> customMeasures) {
-    List<String> logins = FluentIterable.from(customMeasures)
-      .transform(CustomMeasureToUserLoginFunction.INSTANCE)
-      .toList();
-    List<UserDto> userDtos = dbClient.userDao().selectByLogins(dbSession, logins);
-    return FluentIterable.from(userDtos).uniqueIndex(UserDtoToLogin.INSTANCE);
-  }
-
-  private enum CustomMeasureToUserLoginFunction implements Function<CustomMeasureDto, String> {
-    INSTANCE;
-
-    @Override
-    public String apply(@Nonnull CustomMeasureDto customMeasure) {
-      return customMeasure.getUserLogin();
-    }
-  }
-
-  private enum UserDtoToLogin implements Function<UserDto, String> {
-    INSTANCE;
-
-    @Override
-    public String apply(@Nonnull UserDto input) {
-      return input.getLogin();
-    }
+  private Map<String, UserDto> usersByUuid(DbSession dbSession, List<CustomMeasureDto> customMeasures) {
+    Set<String> userUuids = customMeasures.stream().map(CustomMeasureDto::getUserUuid).collect(MoreCollectors.toSet());
+    List<UserDto> users = dbClient.userDao().selectByUuids(dbSession, userUuids);
+    return users.stream().collect(MoreCollectors.uniqueIndex(UserDto::getUuid));
   }
 
   private enum CustomMeasureToMetricIdFunction implements Function<CustomMeasureDto, Integer> {
index 09d8d8ca8420a00f2b5c2a77e6f6392fc2b7317a..7e83e7a02e189ea03d426651e57084005ff4a745 100644 (file)
@@ -33,6 +33,9 @@ import org.sonar.db.metric.MetricDto;
 import org.sonar.db.user.UserDto;
 import org.sonar.server.user.UserSession;
 
+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.sonar.server.measure.custom.ws.CustomMeasureValidator.checkPermissions;
 import static org.sonar.server.measure.custom.ws.CustomMeasureValueDescription.measureValueDescription;
 
@@ -86,15 +89,20 @@ public class UpdateAction implements CustomMeasuresWsAction {
     checkParameters(value, description);
 
     try (DbSession dbSession = dbClient.openSession(true)) {
-      CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectOrFail(dbSession, id);
-      MetricDto metric = dbClient.metricDao().selectOrFailById(dbSession, customMeasure.getMetricId());
+      CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectById(dbSession, id);
+      checkArgument(customMeasure != null, "Custom measure with id '%s' does not exist", id);
+      int customMetricId = customMeasure.getMetricId();
+      MetricDto metric = dbClient.metricDao().selectById(dbSession, customMetricId);
+      checkState(metric != null, "Metric with id '%s' does not exist", customMetricId);
       ComponentDto component = dbClient.componentDao().selectOrFailByUuid(dbSession, customMeasure.getComponentUuid());
       checkPermissions(userSession, component);
-      UserDto user = dbClient.userDao().selectOrFailByLogin(dbSession, userSession.getLogin());
+      String userUuid = requireNonNull(userSession.getUuid(), "User uuid should not be null");
+      UserDto user = dbClient.userDao().selectByUuid(dbSession, userUuid);
+      checkState(user != null, "User with uuid '%s' does not exist", userUuid);
 
       setValue(customMeasure, value, metric);
       setDescription(customMeasure, description);
-      customMeasure.setUserLogin(user.getLogin());
+      customMeasure.setUserUuid(user.getUuid());
       customMeasure.setUpdatedAt(system.now());
       dbClient.customMeasureDao().update(dbSession, customMeasure);
       dbSession.commit();
index 1b8ef114ca7603576a8e665c9a4d6ac8a5169494..9c06cb624c6f3aa9891b1313e0776a376b663966 100644 (file)
  */
 package org.sonar.server.measure.custom.ws;
 
-import java.util.List;
-import org.assertj.core.data.Offset;
-import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.Metric.ValueType;
 import org.sonar.api.utils.System2;
-import org.sonar.api.web.UserRole;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
-import org.sonar.db.RowNotFoundException;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentTesting;
 import org.sonar.db.measure.custom.CustomMeasureDto;
 import org.sonar.db.metric.MetricDto;
-import org.sonar.db.metric.MetricTesting;
 import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.permission.OrganizationPermission;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.component.TestComponentFinder;
 import org.sonar.server.es.EsTester;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.exceptions.ServerException;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.user.ws.UserJsonWriter;
-import org.sonar.server.ws.WsTester;
+import org.sonar.server.ws.WsActionTester;
 
+import static java.lang.String.format;
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.data.Offset.offset;
+import static org.assertj.core.api.Assertions.tuple;
 import static org.sonar.api.measures.Metric.ValueType.BOOL;
 import static org.sonar.api.measures.Metric.ValueType.FLOAT;
 import static org.sonar.api.measures.Metric.ValueType.INT;
 import static org.sonar.api.measures.Metric.ValueType.LEVEL;
 import static org.sonar.api.measures.Metric.ValueType.STRING;
 import static org.sonar.api.measures.Metric.ValueType.WORK_DUR;
+import static org.sonar.api.web.UserRole.ADMIN;
+import static org.sonar.db.component.ComponentTesting.newModuleDto;
 import static org.sonar.server.util.TypeValidationsTesting.newFullTypeValidations;
+import static org.sonar.test.JsonAssert.assertJson;
 
 public class CreateActionTest {
 
-  private static final String DEFAULT_PROJECT_UUID = "project-uuid";
-  private static final String DEFAULT_PROJECT_KEY = "project-key";
-
   @Rule
   public UserSessionRule userSession = UserSessionRule.standalone();
   @Rule
@@ -74,284 +65,311 @@ public class CreateActionTest {
   @Rule
   public EsTester es = EsTester.create();
 
-  private DbClient dbClient = db.getDbClient();
-  private ComponentDto project;
-  private final DbSession dbSession = db.getSession();
-  private WsTester ws;
-
-  @Before
-  public void setUp() {
-    ws = new WsTester(new CustomMeasuresWs(new CreateAction(dbClient, userSession, System2.INSTANCE, new CustomMeasureValidator(newFullTypeValidations()),
-      new CustomMeasureJsonWriter(new UserJsonWriter(userSession)), TestComponentFinder.from(db))));
-
-    db.users().insertUser(u -> u.setLogin("login")
-      .setName("Login")
-      .setEmail("login@login.com")
-      .setActive(true));
-
-    OrganizationDto organizationDto = db.organizations().insert();
-    project = ComponentTesting.newPrivateProjectDto(organizationDto, DEFAULT_PROJECT_UUID).setDbKey(DEFAULT_PROJECT_KEY);
-    dbClient.componentDao().insert(dbSession, project);
-    dbSession.commit();
-    userSession.logIn("login").addProjectPermission(UserRole.ADMIN, project);
-  }
+  private WsActionTester ws = new WsActionTester(
+    new CreateAction(db.getDbClient(), userSession, System2.INSTANCE, new CustomMeasureValidator(newFullTypeValidations()),
+      new CustomMeasureJsonWriter(new UserJsonWriter(userSession)), TestComponentFinder.from(db)));
 
   @Test
-  public void create_boolean_custom_measure_in_db() throws Exception {
-    MetricDto metric = insertMetric(BOOL);
-
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
-      .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
+  public void create_boolean_custom_measure_in_db() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(BOOL.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid())
+      .setParam(CreateAction.PARAM_METRIC_ID, Integer.toString(metric.getId()))
       .setParam(CreateAction.PARAM_DESCRIPTION, "custom-measure-description")
       .setParam(CreateAction.PARAM_VALUE, "true")
       .execute();
 
-    List<CustomMeasureDto> customMeasures = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId());
-    CustomMeasureDto customMeasure = customMeasures.get(0);
-    assertThat(customMeasures).hasSize(1);
-    assertThat(customMeasure.getDescription()).isEqualTo("custom-measure-description");
-    assertThat(customMeasure.getTextValue()).isNullOrEmpty();
-    assertThat(customMeasure.getValue()).isCloseTo(1.0d, offset(0.01d));
-    assertThat(customMeasure.getComponentUuid()).isEqualTo(DEFAULT_PROJECT_UUID);
+    assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()))
+      .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid)
+      .containsExactlyInAnyOrder(tuple("custom-measure-description", null, 1d, project.uuid()));
   }
 
   @Test
-  public void create_int_custom_measure_in_db() throws Exception {
-    MetricDto metric = insertMetric(INT);
-
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
+  public void create_int_custom_measure_in_db() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(INT.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid())
       .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
       .setParam(CreateAction.PARAM_VALUE, "42")
       .execute();
 
-    CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0);
-    assertThat(customMeasure.getTextValue()).isNullOrEmpty();
-    assertThat(customMeasure.getValue()).isCloseTo(42.0d, offset(0.01d));
-  }
-
-  @Test
-  public void create_text_custom_measure_in_db() throws Exception {
-    MetricDto metric = insertMetric(STRING);
-
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
-      .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
-      .setParam(CreateAction.PARAM_VALUE, "custom-measure-free-text")
-      .execute();
-
-    CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0);
-    assertThat(customMeasure.getTextValue()).isEqualTo("custom-measure-free-text");
+    assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()))
+      .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid)
+      .containsExactlyInAnyOrder(tuple(null, null, 42d, project.uuid()));
   }
 
   @Test
-  public void create_text_custom_measure_as_project_admin() throws Exception {
-    MetricDto metric = insertMetric(STRING);
-    userSession.logIn("login").addProjectPermission(UserRole.ADMIN, project);
-
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
+  public void create_text_custom_measure_in_db() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid())
       .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
       .setParam(CreateAction.PARAM_VALUE, "custom-measure-free-text")
       .execute();
 
-    CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0);
-    assertThat(customMeasure).isNotNull();
+    assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()))
+      .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid)
+      .containsExactlyInAnyOrder(tuple(null, "custom-measure-free-text", 0d, project.uuid()));
   }
 
   @Test
-  public void create_text_custom_measure_with_metric_key() throws Exception {
-    MetricDto metric = insertMetric(STRING);
-
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
+  public void create_text_custom_measure_with_metric_key() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid())
       .setParam(CreateAction.PARAM_METRIC_KEY, metric.getKey())
       .setParam(CreateAction.PARAM_VALUE, "whatever-value")
       .execute();
 
-    CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0);
-    assertThat(customMeasure).isNotNull();
+    assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()))
+      .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid)
+      .containsExactlyInAnyOrder(tuple(null, "whatever-value", 0d, project.uuid()));
   }
 
   @Test
-  public void create_text_custom_measure_with_project_key() throws Exception {
-    MetricDto metric = insertMetric(STRING);
-
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY)
+  public void create_text_custom_measure_with_project_key() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_KEY, project.getKey())
       .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
       .setParam(CreateAction.PARAM_VALUE, "whatever-value")
       .execute();
 
-    CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0);
-    assertThat(customMeasure).isNotNull();
+    assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()))
+      .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid)
+      .containsExactlyInAnyOrder(tuple(null, "whatever-value", 0d, project.uuid()));
   }
 
   @Test
-  public void create_float_custom_measure_in_db() throws Exception {
-    MetricDto metric = insertMetric(FLOAT);
-
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
+  public void create_float_custom_measure_in_db() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(FLOAT.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid())
       .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
       .setParam(CreateAction.PARAM_VALUE, "4.2")
       .execute();
 
-    CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0);
-    assertThat(customMeasure.getValue()).isCloseTo(4.2d, Offset.offset(0.01d));
-    assertThat(customMeasure.getTextValue()).isNullOrEmpty();
+    assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()))
+      .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid)
+      .containsExactlyInAnyOrder(tuple(null, null, 4.2d, project.uuid()));
   }
 
   @Test
-  public void create_work_duration_custom_measure_in_db() throws Exception {
-    MetricDto metric = insertMetric(WORK_DUR);
-
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
+  public void create_work_duration_custom_measure_in_db() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(WORK_DUR.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid())
       .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
       .setParam(CreateAction.PARAM_VALUE, "253")
       .execute();
 
-    CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0);
-    assertThat(customMeasure.getTextValue()).isNullOrEmpty();
-    assertThat(customMeasure.getValue()).isCloseTo(253, offset(0.01d));
+    assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()))
+      .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid)
+      .containsExactlyInAnyOrder(tuple(null, null, 253d, project.uuid()));
   }
 
   @Test
-  public void create_level_type_custom_measure_in_db() throws Exception {
-    MetricDto metric = insertMetric(LEVEL);
-
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
+  public void create_level_type_custom_measure_in_db() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(LEVEL.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid())
       .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
       .setParam(CreateAction.PARAM_VALUE, Metric.Level.WARN.name())
       .execute();
 
-    CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0);
-    assertThat(customMeasure.getTextValue()).isEqualTo(Metric.Level.WARN.name());
+    assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()))
+      .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid)
+      .containsExactlyInAnyOrder(tuple(null, Metric.Level.WARN.name(), 0d, project.uuid()));
   }
 
   @Test
-  public void response_with_object_and_id() throws Exception {
-    MetricDto metric = insertMetric(STRING);
-
-    WsTester.Result response = newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
+  public void response_with_object_and_id() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
+    String response = ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid())
       .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
       .setParam(CreateAction.PARAM_DESCRIPTION, "custom-measure-description")
       .setParam(CreateAction.PARAM_VALUE, "custom-measure-free-text")
-      .execute();
-
-    CustomMeasureDto customMeasure = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId()).get(0);
-    response.assertJson(getClass(), "custom-measure.json");
-    assertThat(response.outputAsString()).matches(String.format(".*\"id\"\\s*:\\s*\"%d\".*", customMeasure.getId()));
-    assertThat(response.outputAsString()).matches(String.format(".*\"id\"\\s*:\\s*\"%d\".*", metric.getId()));
+      .execute()
+      .getInput();
+
+    CustomMeasureDto customMeasure = db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()).get(0);
+    assertJson(response).isSimilarTo("{\n" +
+      "  \"id\": \"" + customMeasure.getId() + "\",\n" +
+      "  \"value\": \"custom-measure-free-text\",\n" +
+      "  \"description\": \"custom-measure-description\",\n" +
+      "  \"metric\": {\n" +
+      "    \"id\": \"" + metric.getId() + "\",\n" +
+      "    \"key\": \"" + metric.getKey() + "\",\n" +
+      "    \"type\": \"" + metric.getValueType() + "\",\n" +
+      "    \"name\": \"" + metric.getShortName() + "\",\n" +
+      "    \"domain\": \"" + metric.getDomain() + "\"\n" +
+      "  },\n" +
+      "  \"projectId\": \"" + project.uuid() + "\",\n" +
+      "  \"projectKey\": \"" + project.getKey() + "\",\n" +
+      "  \"pending\": true\n" +
+      "}");
   }
 
   @Test
-  public void create_custom_measure_on_a_view() throws Exception {
-    String viewUuid = "VIEW_UUID";
-    ComponentDto view = ComponentTesting.newView(db.organizations().insert(), viewUuid);
-    dbClient.componentDao().insert(dbSession, view);
-    dbSession.commit();
-    MetricDto metric = insertMetric(BOOL);
-    userSession.logIn("login").addProjectPermission(UserRole.ADMIN, view);
-
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, viewUuid)
-      .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
+  public void create_custom_measure_on_module() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(BOOL.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    ComponentDto module = db.components().insertComponent(newModuleDto(project));
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, module.uuid())
+      .setParam(CreateAction.PARAM_METRIC_ID, Integer.toString(metric.getId()))
       .setParam(CreateAction.PARAM_DESCRIPTION, "custom-measure-description")
       .setParam(CreateAction.PARAM_VALUE, "true")
       .execute();
 
-    List<CustomMeasureDto> customMeasures = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId());
-    CustomMeasureDto customMeasure = customMeasures.get(0);
-    assertThat(customMeasures).hasSize(1);
-    assertThat(customMeasure.getComponentUuid()).isEqualTo(viewUuid);
+    assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()))
+      .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid)
+      .containsExactlyInAnyOrder(tuple("custom-measure-description", null, 1d, module.uuid()));
   }
 
   @Test
-  public void create_custom_measure_on_a_sub_view() throws Exception {
-    String subViewUuid = "SUB_VIEW_UUID";
-
-    ComponentDto view = ComponentTesting.newView(db.organizations().insert());
-    dbClient.componentDao().insert(dbSession, view);
-    dbClient.componentDao().insert(dbSession, ComponentTesting.newSubView(view, subViewUuid, "SUB_VIEW_KEY"));
-    dbSession.commit();
-    MetricDto metric = insertMetric(BOOL);
-    userSession.logIn("login").addProjectPermission(UserRole.ADMIN, view);
-
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, subViewUuid)
+  public void create_custom_measure_on_a_view() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(BOOL.name()));
+    OrganizationDto organization = db.organizations().insert();
+    ComponentDto view = db.components().insertPrivatePortfolio(organization);
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, view);
+
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, view.uuid())
       .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
       .setParam(CreateAction.PARAM_DESCRIPTION, "custom-measure-description")
       .setParam(CreateAction.PARAM_VALUE, "true")
       .execute();
 
-    List<CustomMeasureDto> customMeasures = dbClient.customMeasureDao().selectByMetricId(dbSession, metric.getId());
-    CustomMeasureDto customMeasure = customMeasures.get(0);
-    assertThat(customMeasures).hasSize(1);
-    assertThat(customMeasure.getComponentUuid()).isEqualTo(subViewUuid);
+    assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()))
+      .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid)
+      .containsExactlyInAnyOrder(tuple("custom-measure-description", null, 1d, view.uuid()));
   }
 
   @Test
-  public void fail_when_get_request() throws Exception {
-    expectedException.expect(ServerException.class);
-
-    ws.newGetRequest(CustomMeasuresWs.ENDPOINT, CreateAction.ACTION)
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
-      .setParam(CreateAction.PARAM_METRIC_ID, "whatever-id")
-      .setParam(CreateAction.PARAM_VALUE, "custom-measure-free-text")
+  public void create_custom_measure_on_a_sub_view() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(BOOL.name()));
+    OrganizationDto organization = db.organizations().insert();
+    ComponentDto view = db.components().insertPrivatePortfolio(organization);
+    ComponentDto subView = db.components().insertSubView(view);
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, view);
+
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, subView.uuid())
+      .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
+      .setParam(CreateAction.PARAM_DESCRIPTION, "custom-measure-description")
+      .setParam(CreateAction.PARAM_VALUE, "true")
       .execute();
+
+    assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()))
+      .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getComponentUuid)
+      .containsExactlyInAnyOrder(tuple("custom-measure-description", null, 1d, subView.uuid()));
   }
 
   @Test
-  public void fail_when_project_id_nor_project_key_provided() throws Exception {
+  public void fail_when_project_id_nor_project_key_provided() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
     expectedException.expect(IllegalArgumentException.class);
     expectedException.expectMessage("Either 'projectId' or 'projectKey' must be provided");
-    MetricDto metric = insertMetric(STRING);
 
-    newRequest()
+    ws.newRequest()
       .setParam(CreateAction.PARAM_METRIC_ID, "whatever-id")
       .setParam(CreateAction.PARAM_VALUE, metric.getId().toString())
       .execute();
   }
 
   @Test
-  public void fail_when_project_id_and_project_key_are_provided() throws Exception {
+  public void fail_when_project_id_and_project_key_are_provided() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
     expectedException.expect(IllegalArgumentException.class);
     expectedException.expectMessage("Either 'projectId' or 'projectKey' must be provided");
-    MetricDto metric = insertMetric(STRING);
 
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
-      .setParam(CreateAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY)
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid())
+      .setParam(CreateAction.PARAM_PROJECT_KEY, project.getKey())
       .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
       .setParam(CreateAction.PARAM_VALUE, "whatever-value")
       .execute();
   }
 
   @Test
-  public void fail_when_project_key_does_not_exist_in_db() throws Exception {
+  public void fail_when_project_key_does_not_exist_in_db() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
     expectedException.expect(NotFoundException.class);
     expectedException.expectMessage("Component key 'another-project-key' not found");
-    insertMetric(STRING);
 
-    newRequest()
+    ws.newRequest()
       .setParam(CreateAction.PARAM_PROJECT_KEY, "another-project-key")
-      .setParam(CreateAction.PARAM_METRIC_ID, "whatever-id")
+      .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
       .setParam(CreateAction.PARAM_VALUE, "whatever-value")
       .execute();
   }
 
   @Test
-  public void fail_when_project_id_does_not_exist_in_db() throws Exception {
+  public void fail_when_project_id_does_not_exist_in_db() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
     expectedException.expect(NotFoundException.class);
     expectedException.expectMessage("Component id 'another-project-uuid' not found");
-    MetricDto metric = insertMetric(STRING);
 
-    newRequest()
+    ws.newRequest()
       .setParam(CreateAction.PARAM_PROJECT_ID, "another-project-uuid")
       .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
       .setParam(CreateAction.PARAM_VALUE, "whatever-value")
@@ -359,25 +377,32 @@ public class CreateActionTest {
   }
 
   @Test
-  public void fail_when_metric_id_nor_metric_key_is_provided() throws Exception {
+  public void fail_when_metric_id_nor_metric_key_is_provided() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
     expectedException.expect(IllegalArgumentException.class);
     expectedException.expectMessage("Either the metric id or the metric key must be provided");
-    insertMetric(STRING);
 
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid())
       .setParam(CreateAction.PARAM_VALUE, "whatever-value")
       .execute();
   }
 
   @Test
-  public void fail_when_metric_id_and_metric_key_are_provided() throws Exception {
+  public void fail_when_metric_id_and_metric_key_are_provided() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
     expectedException.expect(IllegalArgumentException.class);
     expectedException.expectMessage("Either the metric id or the metric key must be provided");
-    MetricDto metric = insertMetric(STRING);
 
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid())
       .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
       .setParam(CreateAction.PARAM_METRIC_KEY, metric.getKey())
       .setParam(CreateAction.PARAM_VALUE, "whatever-value")
@@ -385,89 +410,104 @@ public class CreateActionTest {
   }
 
   @Test
-  public void fail_when_metric_is_not_found_in_db() throws Exception {
-    expectedException.expect(RowNotFoundException.class);
-    expectedException.expectMessage("Metric id '42' not found");
+  public void fail_when_metric_key_is_not_found_in_db() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
 
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
-      .setParam(CreateAction.PARAM_METRIC_ID, "42")
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Metric with key 'unknown' does not exist");
+
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid())
+      .setParam(CreateAction.PARAM_METRIC_KEY, "unknown")
       .setParam(CreateAction.PARAM_VALUE, "whatever-value")
       .execute();
   }
 
   @Test
-  public void fail_when_measure_already_exists_on_same_project_and_same_metric() throws Exception {
-    MetricDto metric = insertMetric(STRING);
+  public void fail_when_metric_id_is_not_found_in_db() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
 
-    expectedException.expect(ServerException.class);
-    expectedException.expectMessage(String.format("A measure already exists for project 'project-key' (id: project-uuid) and metric 'metric-key' (id: '%d')", metric.getId()));
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Metric with id '42' does not exist");
 
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
-      .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid())
+      .setParam(CreateAction.PARAM_METRIC_ID, "42")
       .setParam(CreateAction.PARAM_VALUE, "whatever-value")
       .execute();
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
+  }
+
+  @Test
+  public void fail_when_measure_already_exists_on_same_project_and_same_metric() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto userMeasureCreator = db.users().insertUser();
+    db.measures().insertCustomMeasure(userMeasureCreator, project, metric);
+    UserDto userAuthenticated = db.users().insertUser();
+    userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project);
+
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage(format("A measure already exists for project '%s' and metric '%s'", project.getKey(), metric.getKey()));
+
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid())
       .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
       .setParam(CreateAction.PARAM_VALUE, "whatever-value")
       .execute();
   }
 
   @Test
-  public void fail_when_value_is_not_well_formatted() throws Exception {
-    MetricDto metric = insertMetric(BOOL);
+  public void fail_when_value_is_not_well_formatted() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(BOOL.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
 
     expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("Value 'non-correct-boolean-value' must be one of \"true\" or \"false\"");
 
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid())
       .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
       .setParam(CreateAction.PARAM_VALUE, "non-correct-boolean-value")
       .execute();
   }
 
   @Test
-  public void fail_when_system_administrator() throws Exception {
-    userSession.logIn().setSystemAdministrator().addPermission(OrganizationPermission.ADMINISTER, db.getDefaultOrganization());
-    MetricDto metric = insertMetric(STRING);
+  public void fail_when_system_administrator() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(BOOL.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).setSystemAdministrator();
 
     expectedException.expect(ForbiddenException.class);
 
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, project.uuid())
       .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
       .setParam(CreateAction.PARAM_VALUE, "whatever-value")
       .execute();
   }
 
   @Test
-  public void fail_when_not_a_project() throws Exception {
-    MetricDto metric = MetricTesting.newMetricDto().setEnabled(true).setValueType(STRING.name()).setKey("metric-key");
-    dbClient.metricDao().insert(dbSession, metric);
-    dbClient.componentDao().insert(dbSession, ComponentTesting.newDirectory(project, "directory-uuid", "path/to/directory").setDbKey("directory-key"));
-    dbSession.commit();
+  public void fail_when_not_a_project() {
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(BOOL.name()));
+    ComponentDto project = db.components().insertPrivateProject();
+    ComponentDto directory = db.components().insertComponent(ComponentTesting.newDirectory(project, "dir"));
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
 
-    expectedException.expect(ServerException.class);
-    expectedException.expectMessage("Component 'directory-key' (id: directory-uuid) must be a project or a module.");
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage(format("Component '%s' must be a project or a module.", directory.getKey()));
 
-    newRequest()
-      .setParam(CreateAction.PARAM_PROJECT_ID, "directory-uuid")
+    ws.newRequest()
+      .setParam(CreateAction.PARAM_PROJECT_ID, directory.uuid())
       .setParam(CreateAction.PARAM_METRIC_ID, metric.getId().toString())
       .setParam(CreateAction.PARAM_VALUE, "whatever-value")
       .execute();
   }
-
-  private WsTester.TestRequest newRequest() {
-    return ws.newPostRequest(CustomMeasuresWs.ENDPOINT, CreateAction.ACTION);
-  }
-
-  private MetricDto insertMetric(ValueType metricType) {
-    MetricDto metric = MetricTesting.newMetricDto().setEnabled(true).setValueType(metricType.name()).setKey("metric-key");
-    dbClient.metricDao().insert(dbSession, metric);
-    dbSession.commit();
-    return metric;
-  }
-
 }
index cb7c51d6e7657b0be83902ceb2c7a441c696ab64..4863fac7dd3b41464c06dd7443c9b2b53b1ee889 100644 (file)
@@ -28,7 +28,6 @@ import org.sonar.api.web.UserRole;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
-import org.sonar.db.RowNotFoundException;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.measure.custom.CustomMeasureDto;
 import org.sonar.server.exceptions.ForbiddenException;
@@ -74,7 +73,8 @@ public class DeleteActionTest {
 
   @Test
   public void throw_RowNotFoundException_if_id_does_not_exist() throws Exception {
-    expectedException.expect(RowNotFoundException.class);
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Custom measure with id '42' does not exist");
 
     newRequest().setParam(PARAM_ID, "42").execute();
   }
index adff6e1b9339ffc2d9b4444a03fb774eb1c0a063..40a61870a0e256ac819173cab2a3483421af15b7 100644 (file)
  */
 package org.sonar.server.measure.custom.ws;
 
+import java.util.ArrayList;
 import java.util.Date;
-import org.apache.commons.lang.StringUtils;
-import org.junit.Before;
+import java.util.List;
+import java.util.stream.IntStream;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.measures.Metric.ValueType;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.System2;
-import org.sonar.api.web.UserRole;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentTesting;
-import org.sonar.db.component.SnapshotTesting;
 import org.sonar.db.measure.custom.CustomMeasureDto;
 import org.sonar.db.metric.MetricDto;
+import org.sonar.db.user.UserDto;
 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.tester.UserSessionRule;
 import org.sonar.server.user.ws.UserJsonWriter;
-import org.sonar.server.ws.WsTester;
+import org.sonar.server.ws.WsActionTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.db.measure.custom.CustomMeasureTesting.newCustomMeasureDto;
-import static org.sonar.db.metric.MetricTesting.newMetricDto;
+import static org.sonar.api.measures.Metric.ValueType.STRING;
+import static org.sonar.api.web.UserRole.ADMIN;
+import static org.sonar.api.web.UserRole.USER;
+import static org.sonar.test.JsonAssert.assertJson;
 
 public class SearchActionTest {
 
-  private static final String DEFAULT_PROJECT_UUID = "project-uuid";
-  private static final String DEFAULT_PROJECT_KEY = "project-key";
-  private static final String METRIC_KEY_PREFIX = "metric-key-";
-
   @Rule
   public ExpectedException expectedException = ExpectedException.none();
   @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+  public UserSessionRule userSession = UserSessionRule.standalone();
   @Rule
   public DbTester db = DbTester.create(System2.INSTANCE);
   @Rule
   public EsTester es = EsTester.create();
 
-  private WsTester ws;
-  private DbClient dbClient = db.getDbClient();
-  private DbSession dbSession = db.getSession();
-  private ComponentDto defaultProject;
-
-  @Before
-  public void setUp() {
-    CustomMeasureJsonWriter customMeasureJsonWriter = new CustomMeasureJsonWriter(new UserJsonWriter(userSessionRule));
-    ws = new WsTester(new CustomMeasuresWs(new SearchAction(dbClient, customMeasureJsonWriter, userSessionRule, TestComponentFinder.from(db))));
-    defaultProject = insertDefaultProject();
-    userSessionRule.logIn().addProjectPermission(UserRole.ADMIN, defaultProject);
-    db.users().insertUser(u -> u.setLogin("login")
-      .setName("Login")
-      .setEmail("login@login.com")
-      .setActive(true));
-  }
+  private WsActionTester ws = new WsActionTester(
+    new SearchAction(db.getDbClient(), new CustomMeasureJsonWriter(new UserJsonWriter(userSession)), userSession, TestComponentFinder.from(db)));
 
   @Test
-  public void json_well_formatted() throws Exception {
-    MetricDto metric1 = insertCustomMetric(1);
-    MetricDto metric2 = insertCustomMetric(2);
-    MetricDto metric3 = insertCustomMetric(3);
-    CustomMeasureDto customMeasure1 = insertCustomMeasure(1, metric1);
-    CustomMeasureDto customMeasure2 = insertCustomMeasure(2, metric2);
-    CustomMeasureDto customMeasure3 = insertCustomMeasure(3, metric3);
-
-    WsTester.Result response = newRequest()
-      .setParam(SearchAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
-      .execute();
+  public void json_well_formatted() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto userAuthenticated = db.users().insertUser();
+    userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project);
+    UserDto userMeasureCreator = db.users().insertUser();
+    MetricDto metric1 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    MetricDto metric2 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    MetricDto metric3 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    CustomMeasureDto customMeasure1 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric1, m -> m.setValue(0d));
+    CustomMeasureDto customMeasure2 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric2, m -> m.setValue(0d));
+    CustomMeasureDto customMeasure3 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric3, m -> m.setValue(0d));
+
+    String response = ws.newRequest()
+      .setParam(SearchAction.PARAM_PROJECT_ID, project.uuid())
+      .execute()
+      .getInput();
+
+    assertJson(response).isSimilarTo("{\n" +
+      "  \"customMeasures\": [\n" +
+      "    {\n" +
+      "      \"id\": \"" + customMeasure1.getId() + "\",\n" +
+      "      \"value\": \"" + customMeasure1.getTextValue() + "\",\n" +
+      "      \"description\": \"" + customMeasure1.getDescription() + "\",\n" +
+      "      \"metric\": {\n" +
+      "        \"id\": \"" + metric1.getId() + "\",\n" +
+      "        \"key\": \"" + metric1.getKey() + "\",\n" +
+      "        \"type\": \"" + metric1.getValueType() + "\",\n" +
+      "        \"name\": \"" + metric1.getShortName() + "\",\n" +
+      "        \"domain\": \"" + metric1.getDomain() + "\"\n" +
+      "      },\n" +
+      "      \"projectId\": \"" + project.uuid() + "\",\n" +
+      "      \"projectKey\": \"" + project.getKey() + "\",\n" +
+      "      \"pending\": true,\n" +
+      "    },\n" +
+      "    {\n" +
+      "      \"id\": \"" + customMeasure2.getId() + "\",\n" +
+      "      \"value\": \"" + customMeasure2.getTextValue() + "\",\n" +
+      "      \"description\": \"" + customMeasure2.getDescription() + "\",\n" +
+      "      \"metric\": {\n" +
+      "        \"id\": \"" + metric2.getId() + "\",\n" +
+      "        \"key\": \"" + metric2.getKey() + "\",\n" +
+      "        \"type\": \"" + metric2.getValueType() + "\",\n" +
+      "        \"name\": \"" + metric2.getShortName() + "\",\n" +
+      "        \"domain\": \"" + metric2.getDomain() + "\"\n" +
+      "      },\n" +
+      "      \"projectId\": \"" + project.uuid() + "\",\n" +
+      "      \"projectKey\": \"" + project.getKey() + "\",\n" +
+      "      \"pending\": true,\n" +
+      "    },\n" +
+      "    {\n" +
+      "      \"id\": \"" + customMeasure3.getId() + "\",\n" +
+      "      \"value\": \"" + customMeasure3.getTextValue() + "\",\n" +
+      "      \"description\": \"" + customMeasure3.getDescription() + "\",\n" +
+      "      \"metric\": {\n" +
+      "        \"id\": \"" + metric3.getId() + "\",\n" +
+      "        \"key\": \"" + metric3.getKey() + "\",\n" +
+      "        \"type\": \"" + metric3.getValueType() + "\",\n" +
+      "        \"name\": \"" + metric3.getShortName() + "\",\n" +
+      "        \"domain\": \"" + metric3.getDomain() + "\"\n" +
+      "      },\n" +
+      "      \"projectId\": \"" + project.uuid() + "\",\n" +
+      "      \"projectKey\": \"" + project.getKey() + "\",\n" +
+      "      \"pending\": true,\n" +
+      "    }\n" +
+      "  ],\n" +
+      "  \"total\": 3,\n" +
+      "  \"p\": 1,\n" +
+      "  \"ps\": 100\n" +
+      "}");
+  }
 
-    response.assertJson(getClass(), "custom-measures.json");
-    String responseAsString = response.outputAsString();
-    assertThat(responseAsString).matches(nameStringValuePattern("id", metric1.getId().toString()));
-    assertThat(responseAsString).matches(nameStringValuePattern("id", metric2.getId().toString()));
-    assertThat(responseAsString).matches(nameStringValuePattern("id", metric3.getId().toString()));
-    assertThat(responseAsString).matches(nameStringValuePattern("id", String.valueOf(customMeasure1.getId())));
-    assertThat(responseAsString).matches(nameStringValuePattern("id", String.valueOf(customMeasure2.getId())));
-    assertThat(responseAsString).matches(nameStringValuePattern("id", String.valueOf(customMeasure3.getId())));
-    assertThat(responseAsString).contains("createdAt", "updatedAt");
+  @Test
+  public void return_users() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto userAuthenticated = db.users().insertUser();
+    userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project);
+    UserDto user1 = db.users().insertUser();
+    UserDto user2 = db.users().insertUser();
+    MetricDto metric1 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    MetricDto metric2 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    MetricDto metric3 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    CustomMeasureDto customMeasure1 = db.measures().insertCustomMeasure(user1, project, metric1, m -> m.setValue(0d));
+    CustomMeasureDto customMeasure2 = db.measures().insertCustomMeasure(user1, project, metric2, m -> m.setValue(0d));
+    CustomMeasureDto customMeasure3 = db.measures().insertCustomMeasure(user2, project, metric3, m -> m.setValue(0d));
+
+    String response = ws.newRequest()
+      .setParam(SearchAction.PARAM_PROJECT_ID, project.uuid())
+      .execute()
+      .getInput();
+
+    assertJson(response).isSimilarTo("{\n" +
+      "  \"customMeasures\": [\n" +
+      "    {\n" +
+      "      \"id\": \"" + customMeasure1.getId() + "\",\n" +
+      "      \"user\": {\n" +
+      "        \"login\": \"" + user1.getLogin() +"\",\n" +
+      "        \"name\": \"" + user1.getName() +"\",\n" +
+      "        \"email\": \"" + user1.getEmail() +"\",\n" +
+      "        \"active\": true\n" +
+      "      }" +
+      "    },\n" +
+      "    {\n" +
+      "      \"id\": \"" + customMeasure2.getId() + "\",\n" +
+      "      \"user\": {\n" +
+      "        \"login\": \"" + user1.getLogin() +"\",\n" +
+      "        \"name\": \"" + user1.getName() +"\",\n" +
+      "        \"email\": \"" + user1.getEmail() +"\",\n" +
+      "        \"active\": true\n" +
+      "      }" +
+      "    },\n" +
+      "    {\n" +
+      "      \"id\": \"" + customMeasure3.getId() + "\",\n" +
+      "      \"user\": {\n" +
+      "        \"login\": \"" + user2.getLogin() +"\",\n" +
+      "        \"name\": \"" + user2.getName() +"\",\n" +
+      "        \"email\": \"" + user2.getEmail() +"\",\n" +
+      "        \"active\": true\n" +
+      "      }" +
+      "    }\n" +
+      "  ]\n" +
+      "}");
   }
 
   @Test
-  public void search_by_project_uuid() throws Exception {
-    MetricDto metric1 = insertCustomMetric(1);
-    MetricDto metric2 = insertCustomMetric(2);
-    MetricDto metric3 = insertCustomMetric(3);
-    insertCustomMeasure(1, metric1);
-    insertCustomMeasure(2, metric2);
-    insertCustomMeasure(3, metric3);
-
-    String response = newRequest()
-      .setParam(SearchAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
-      .execute().outputAsString();
-
-    assertThat(response).contains("text-value-1", "text-value-2", "text-value-3");
+  public void search_by_project_uuid() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto userAuthenticated = db.users().insertUser();
+    userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project);
+    UserDto userMeasureCreator = db.users().insertUser();
+    MetricDto metric1 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    MetricDto metric2 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    MetricDto metric3 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    CustomMeasureDto customMeasure1 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric1, m -> m.setValue(0d));
+    CustomMeasureDto customMeasure2 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric2, m -> m.setValue(0d));
+    CustomMeasureDto customMeasure3 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric3, m -> m.setValue(0d));
+
+    String response = ws.newRequest()
+      .setParam(SearchAction.PARAM_PROJECT_ID, project.uuid())
+      .execute()
+      .getInput();
+
+    assertJson(response).isSimilarTo("{\n" +
+      "  \"customMeasures\": [\n" +
+      "    {\n" +
+      "      \"id\": \"" + customMeasure1.getId() + "\",\n" +
+      "      \"value\": \"" + customMeasure1.getTextValue() + "\"\n" +
+      "    },\n" +
+      "    {\n" +
+      "      \"id\": \"" + customMeasure2.getId() + "\",\n" +
+      "      \"value\": \"" + customMeasure2.getTextValue() + "\"\n" +
+      "    },\n" +
+      "    {\n" +
+      "      \"id\": \"" + customMeasure3.getId() + "\",\n" +
+      "      \"value\": \"" + customMeasure3.getTextValue() + "\"\n" +
+      "    }\n" +
+      "  ],\n" +
+      "  \"total\": 3,\n" +
+      "  \"p\": 1,\n" +
+      "  \"ps\": 100\n" +
+      "}");
   }
 
   @Test
-  public void search_by_project_key() throws Exception {
-    MetricDto metric1 = insertCustomMetric(1);
-    MetricDto metric2 = insertCustomMetric(2);
-    MetricDto metric3 = insertCustomMetric(3);
-    insertCustomMeasure(1, metric1);
-    insertCustomMeasure(2, metric2);
-    insertCustomMeasure(3, metric3);
-
-    String response = newRequest()
-      .setParam(SearchAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY)
-      .execute().outputAsString();
-
-    assertThat(response).contains("text-value-1", "text-value-2", "text-value-3");
+  public void search_by_project_key() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto userAuthenticated = db.users().insertUser();
+    userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project);
+    UserDto userMeasureCreator = db.users().insertUser();
+    MetricDto metric1 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    MetricDto metric2 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    MetricDto metric3 = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    CustomMeasureDto customMeasure1 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric1, m -> m.setValue(0d));
+    CustomMeasureDto customMeasure2 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric2, m -> m.setValue(0d));
+    CustomMeasureDto customMeasure3 = db.measures().insertCustomMeasure(userMeasureCreator, project, metric3, m -> m.setValue(0d));
+
+    String response = ws.newRequest()
+      .setParam(SearchAction.PARAM_PROJECT_KEY, project.getKey())
+      .execute()
+      .getInput();
+
+    assertJson(response).isSimilarTo("{\n" +
+      "  \"customMeasures\": [\n" +
+      "    {\n" +
+      "      \"id\": \"" + customMeasure1.getId() + "\",\n" +
+      "      \"value\": \"" + customMeasure1.getTextValue() + "\"\n" +
+      "    },\n" +
+      "    {\n" +
+      "      \"id\": \"" + customMeasure2.getId() + "\",\n" +
+      "      \"value\": \"" + customMeasure2.getTextValue() + "\"\n" +
+      "    },\n" +
+      "    {\n" +
+      "      \"id\": \"" + customMeasure3.getId() + "\",\n" +
+      "      \"value\": \"" + customMeasure3.getTextValue() + "\"\n" +
+      "    }\n" +
+      "  ],\n" +
+      "  \"total\": 3,\n" +
+      "  \"p\": 1,\n" +
+      "  \"ps\": 100\n" +
+      "}");
   }
 
   @Test
-  public void search_with_pagination() throws Exception {
-    for (int i = 0; i < 10; i++) {
-      MetricDto metric = insertCustomMetric(i);
-      insertCustomMeasure(i, metric);
-    }
-
-    String response = newRequest()
-      .setParam(SearchAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY)
+  public void search_with_pagination() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto userAuthenticated = db.users().insertUser();
+    userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project);
+    UserDto userMeasureCreator = db.users().insertUser();
+    List<CustomMeasureDto> measureById = new ArrayList<>();
+    IntStream.range(0, 10).forEach(i -> {
+      MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true));
+      CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(userMeasureCreator, project, metric);
+      measureById.add(customMeasure);
+    });
+
+    String response = ws.newRequest()
+      .setParam(SearchAction.PARAM_PROJECT_KEY, project.getKey())
       .setParam(WebService.Param.PAGE, "3")
       .setParam(WebService.Param.PAGE_SIZE, "4")
-      .execute().outputAsString();
-
-    assertThat(StringUtils.countMatches(response, "text-value")).isEqualTo(2);
+      .execute()
+      .getInput();
+
+    assertJson(response).isSimilarTo("{\n" +
+      "  \"customMeasures\": [\n" +
+      "    {\n" +
+      "      \"id\": \"" + measureById.get(8).getId() + "\",\n" +
+      "    },\n" +
+      "    {\n" +
+      "      \"id\": \"" + measureById.get(9).getId() + "\",\n" +
+      "    },\n" +
+      "  ],\n" +
+      "  \"total\": 10,\n" +
+      "  \"p\": 3,\n" +
+      "  \"ps\": 4\n" +
+      "}");
   }
 
   @Test
-  public void search_with_selectable_fields() throws Exception {
-    MetricDto metric = insertCustomMetric(1);
-    insertCustomMeasure(1, metric);
-
-    String response = newRequest()
-      .setParam(SearchAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY)
+  public void search_with_selectable_fields() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto userAuthenticated = db.users().insertUser();
+    userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project);
+    UserDto userMeasureCreator = db.users().insertUser();
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    db.measures().insertCustomMeasure(userMeasureCreator, project, metric, m -> m.setValue(0d));
+
+    String response = ws.newRequest()
+      .setParam(SearchAction.PARAM_PROJECT_KEY, project.getKey())
       .setParam(WebService.Param.FIELDS, "value, description")
-      .execute().outputAsString();
+      .execute()
+      .getInput();
 
     assertThat(response).contains("id", "value", "description")
       .doesNotContain("createdAt")
@@ -172,137 +322,99 @@ public class SearchActionTest {
   }
 
   @Test
-  public void search_with_more_recent_analysis() throws Exception {
+  public void search_with_more_recent_analysis() {
     long yesterday = DateUtils.addDays(new Date(), -1).getTime();
-    MetricDto metric = insertCustomMetric(1);
-    dbClient.customMeasureDao().insert(dbSession, newCustomMeasure(1, metric)
-      .setCreatedAt(yesterday)
-      .setUpdatedAt(yesterday));
-    dbClient.snapshotDao().insert(dbSession, SnapshotTesting.newAnalysis(defaultProject));
-    dbSession.commit();
-
-    String response = newRequest()
-      .setParam(SearchAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
-      .execute().outputAsString();
-
-    assertThat(response).matches(nameValuePattern("pending", "false"));
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto userAuthenticated = db.users().insertUser();
+    userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project);
+    UserDto userMeasureCreator = db.users().insertUser();
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(userMeasureCreator, project, metric, m -> m.setCreatedAt(yesterday).setUpdatedAt(yesterday));
+    db.components().insertSnapshot(project);
+
+    String response = ws.newRequest()
+      .setParam(SearchAction.PARAM_PROJECT_ID, project.uuid())
+      .execute()
+      .getInput();
+
+    assertJson(response).isSimilarTo("{\n" +
+      "  \"customMeasures\": [\n" +
+      "    {\n" +
+      "      \"id\": \"" + customMeasure.getId() + "\",\n" +
+      "      \"value\": \"" + customMeasure.getTextValue() + "\",\n" +
+      "      \"pending\": false\n" +
+      "    },\n" +
+      "  ]\n" +
+      "}");
   }
 
   @Test
-  public void search_as_project_admin() throws Exception {
-    userSessionRule.logIn("login").addProjectPermission(UserRole.ADMIN, defaultProject);
-    MetricDto metric1 = insertCustomMetric(1);
-    insertCustomMeasure(1, metric1);
-
-    String response = newRequest()
-      .setParam(SearchAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
-      .execute().outputAsString();
-
-    assertThat(response).contains("text-value-1");
+  public void empty_json_when_no_measure() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto userAuthenticated = db.users().insertUser();
+    userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project);
+
+    String response = ws.newRequest()
+      .setParam(SearchAction.PARAM_PROJECT_KEY, project.getKey())
+      .execute()
+      .getInput();
+
+    assertJson(response).isSimilarTo("{\n" +
+      "  \"customMeasures\": [],\n" +
+      "  \"total\": 0,\n" +
+      "  \"p\": 1,\n" +
+      "  \"ps\": 100\n" +
+      "}");
   }
 
   @Test
-  public void empty_json_when_no_measure() throws Exception {
-    WsTester.Result response = newRequest()
-      .setParam(SearchAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY)
-      .execute();
-
-    response.assertJson(getClass(), "empty.json");
-  }
+  public void fail_when_project_id_and_project_key_provided() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto userAuthenticated = db.users().insertUser();
+    userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project);
 
-  @Test
-  public void fail_when_project_id_and_project_key_provided() throws Exception {
     expectedException.expect(IllegalArgumentException.class);
     expectedException.expectMessage("Either 'projectId' or 'projectKey' must be provided");
 
-    newRequest()
-      .setParam(SearchAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
-      .setParam(SearchAction.PARAM_PROJECT_KEY, DEFAULT_PROJECT_KEY)
+    ws.newRequest()
+      .setParam(SearchAction.PARAM_PROJECT_ID, project.uuid())
+      .setParam(SearchAction.PARAM_PROJECT_KEY, project.getKey())
       .execute();
   }
 
   @Test
-  public void fail_when_project_id_nor_project_key_provided() throws Exception {
+  public void fail_when_project_id_nor_project_key_provided() {
     expectedException.expect(IllegalArgumentException.class);
     expectedException.expectMessage("Either 'projectId' or 'projectKey' must be provided");
-    newRequest().execute();
+
+    ws.newRequest()
+      .execute();
   }
 
   @Test
-  public void fail_when_project_not_found_in_db() throws Exception {
+  public void fail_when_project_not_found_in_db() {
     expectedException.expect(NotFoundException.class);
     expectedException.expectMessage("Component id 'wrong-project-uuid' not found");
 
-    newRequest().setParam(SearchAction.PARAM_PROJECT_ID, "wrong-project-uuid").execute();
+    ws.newRequest()
+      .setParam(SearchAction.PARAM_PROJECT_ID, "wrong-project-uuid")
+      .execute();
   }
 
   @Test
-  public void fail_when_not_enough_privileges() throws Exception {
+  public void fail_when_not_enough_privileges() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto userAuthenticated = db.users().insertUser();
+    userSession.logIn(userAuthenticated).addProjectPermission(USER, project);
+
     expectedException.expect(ForbiddenException.class);
-    userSessionRule.logIn("login");
-    MetricDto metric1 = insertCustomMetric(1);
-    insertCustomMeasure(1, metric1);
 
-    String response = newRequest()
-      .setParam(SearchAction.PARAM_PROJECT_ID, DEFAULT_PROJECT_UUID)
-      .execute().outputAsString();
+    String response = ws.newRequest()
+      .setParam(SearchAction.PARAM_PROJECT_ID, project.uuid())
+      .execute()
+      .getInput();
 
     assertThat(response).contains("text-value-1");
   }
 
-  private ComponentDto insertDefaultProject() {
-    return insertProject(DEFAULT_PROJECT_UUID, DEFAULT_PROJECT_KEY);
-  }
-
-  private ComponentDto insertProject(String projectUuid, String projectKey) {
-    ComponentDto project = ComponentTesting.newPrivateProjectDto(db.organizations().insert(), projectUuid)
-      .setDbKey(projectKey);
-    dbClient.componentDao().insert(dbSession, project);
-    dbSession.commit();
-
-    return project;
-  }
-
-  private MetricDto insertCustomMetric(int id) {
-    MetricDto metric = newCustomMetric(METRIC_KEY_PREFIX + id);
-    dbClient.metricDao().insert(dbSession, metric);
-    dbSession.commit();
-
-    return metric;
-  }
-
-  private static MetricDto newCustomMetric(String metricKey) {
-    return newMetricDto().setEnabled(true).setUserManaged(true).setKey(metricKey).setDomain(metricKey + "-domain").setShortName(metricKey + "-name")
-      .setValueType(ValueType.STRING.name());
-  }
-
-  private CustomMeasureDto insertCustomMeasure(int id, MetricDto metric) {
-    CustomMeasureDto customMeasure = newCustomMeasure(id, metric);
-    dbClient.customMeasureDao().insert(dbSession, customMeasure);
-    dbSession.commit();
-
-    return customMeasure;
-  }
-
-  private CustomMeasureDto newCustomMeasure(int id, MetricDto metric) {
-    return newCustomMeasureDto()
-      .setUserLogin("login")
-      .setValue(id)
-      .setTextValue("text-value-" + id)
-      .setDescription("description-" + id)
-      .setMetricId(metric.getId())
-      .setComponentUuid(defaultProject.uuid());
-  }
-
-  private WsTester.TestRequest newRequest() {
-    return ws.newGetRequest(CustomMeasuresWs.ENDPOINT, SearchAction.ACTION);
-  }
-
-  private static String nameStringValuePattern(String name, String value) {
-    return String.format(".*\"%s\"\\s*:\\s*\"%s\".*", name, value);
-  }
-
-  private static String nameValuePattern(String name, String value) {
-    return String.format(".*\"%s\"\\s*:\\s*%s.*", name, value);
-  }
 }
index f1d0adf3e03f41b80d36fb8ab69af7da2bba5c9e..0691f196468532ba6b773b2d47b460d42fff7e98 100644 (file)
  */
 package org.sonar.server.measure.custom.ws;
 
-import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.measures.Metric.ValueType;
 import org.sonar.api.utils.System2;
-import org.sonar.api.web.UserRole;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
+import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.db.DbTester;
-import org.sonar.db.RowNotFoundException;
 import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentTesting;
 import org.sonar.db.measure.custom.CustomMeasureDto;
 import org.sonar.db.metric.MetricDto;
-import org.sonar.db.metric.MetricTesting;
-import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.es.EsTester;
 import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.ServerException;
 import org.sonar.server.exceptions.UnauthorizedException;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.user.ws.UserJsonWriter;
-import org.sonar.server.ws.WsTester;
+import org.sonar.server.ws.WsActionTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.data.Offset.offset;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.db.measure.custom.CustomMeasureTesting.newCustomMeasureDto;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.sonar.api.measures.Metric.ValueType.INT;
+import static org.sonar.api.measures.Metric.ValueType.STRING;
+import static org.sonar.api.web.UserRole.ADMIN;
+import static org.sonar.api.web.UserRole.USER;
 import static org.sonar.server.measure.custom.ws.UpdateAction.PARAM_DESCRIPTION;
 import static org.sonar.server.measure.custom.ws.UpdateAction.PARAM_ID;
 import static org.sonar.server.measure.custom.ws.UpdateAction.PARAM_VALUE;
 import static org.sonar.server.util.TypeValidationsTesting.newFullTypeValidations;
+import static org.sonar.test.JsonAssert.assertJson;
 
 public class UpdateActionTest {
+
+  private static final long NOW = 10_000_000_000L;
+
+  private System2 system = new TestSystem2().setNow(NOW);
+
   @Rule
   public ExpectedException expectedException = ExpectedException.none();
   @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+  public UserSessionRule userSession = UserSessionRule.standalone();
   @Rule
-  public DbTester db = DbTester.create(System2.INSTANCE);
+  public DbTester db = DbTester.create();
   @Rule
   public EsTester es = EsTester.create();
 
-  private DbClient dbClient = db.getDbClient();
-  private DbSession dbSession = db.getSession();
-  private System2 system = mock(System2.class);
-  private WsTester ws;
-
-  @Before
-  public void setUp() {
-    CustomMeasureValidator validator = new CustomMeasureValidator(newFullTypeValidations());
-
-    ws = new WsTester(new CustomMeasuresWs(new UpdateAction(dbClient, userSessionRule, system, validator, new CustomMeasureJsonWriter(new UserJsonWriter(userSessionRule)))));
-
-    db.users().insertUser(u -> u.setLogin("login")
-      .setName("Login")
-      .setEmail("login@login.com")
-      .setActive(true)
-      );
-    dbSession.commit();
-  }
+  private WsActionTester ws = new WsActionTester(new UpdateAction(db.getDbClient(), userSession, system, new CustomMeasureValidator(newFullTypeValidations()),
+    new CustomMeasureJsonWriter(new UserJsonWriter(userSession))));
 
   @Test
-  public void update_text_value_and_description_in_db() throws Exception {
-    MetricDto metric = insertNewMetric(ValueType.STRING);
-    ComponentDto component = db.components().insertPrivateProject(db.getDefaultOrganization(), "project-uuid");
-    CustomMeasureDto customMeasure = newCustomMeasure(component, metric)
-      .setDescription("custom-measure-description")
-      .setTextValue("text-measure-value");
-    dbClient.customMeasureDao().insert(dbSession, customMeasure);
-    dbSession.commit();
-    when(system.now()).thenReturn(123_456_789L);
-    logInAsProjectAdministrator(component);
-
-    ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION)
+  public void update_text_value_and_description_in_db() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto userAuthenticated = db.users().insertUser();
+    userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project);
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    UserDto userMeasureCreator = db.users().insertUser();
+    CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(userMeasureCreator, project, metric, m -> m.setValue(0d));
+
+    ws.newRequest()
       .setParam(PARAM_ID, String.valueOf(customMeasure.getId()))
       .setParam(PARAM_DESCRIPTION, "new-custom-measure-description")
       .setParam(PARAM_VALUE, "new-text-measure-value")
       .execute();
-    logInAsProjectAdministrator(component);
 
-    CustomMeasureDto updatedCustomMeasure = dbClient.customMeasureDao().selectOrFail(dbSession, customMeasure.getId());
-    assertThat(updatedCustomMeasure.getTextValue()).isEqualTo("new-text-measure-value");
-    assertThat(updatedCustomMeasure.getDescription()).isEqualTo("new-custom-measure-description");
-    assertThat(updatedCustomMeasure.getUpdatedAt()).isEqualTo(123_456_789L);
-    assertThat(customMeasure.getCreatedAt()).isEqualTo(updatedCustomMeasure.getCreatedAt());
+    assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()))
+      .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getUserUuid, CustomMeasureDto::getComponentUuid,
+        CustomMeasureDto::getCreatedAt, CustomMeasureDto::getUpdatedAt)
+      .containsExactlyInAnyOrder(
+        tuple("new-custom-measure-description", "new-text-measure-value", 0d, userAuthenticated.getUuid(), project.uuid(), customMeasure.getCreatedAt(), NOW));
   }
 
   @Test
-  public void update_double_value_and_description_in_db() throws Exception {
-    MetricDto metric = insertNewMetric(ValueType.INT);
-    OrganizationDto organizationDto = db.organizations().insert();
-    ComponentDto component = db.components().insertPrivateProject(organizationDto, "project-uuid");
-    CustomMeasureDto customMeasure = newCustomMeasure(component, metric)
-      .setDescription("custom-measure-description")
-      .setValue(42d);
-    dbClient.customMeasureDao().insert(dbSession, customMeasure);
-    dbSession.commit();
-    logInAsProjectAdministrator(component);
-
-    ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION)
+  public void update_int_value_and_description_in_db() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto userAuthenticated = db.users().insertUser();
+    userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project);
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(INT.name()));
+    UserDto userMeasureCreator = db.users().insertUser();
+    CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(userMeasureCreator, project, metric, m -> m.setValue(42d).setTextValue(null));
+
+    ws.newRequest()
       .setParam(PARAM_ID, String.valueOf(customMeasure.getId()))
       .setParam(PARAM_DESCRIPTION, "new-custom-measure-description")
       .setParam(PARAM_VALUE, "1984")
       .execute();
 
-    CustomMeasureDto updatedCustomMeasure = dbClient.customMeasureDao().selectOrFail(dbSession, customMeasure.getId());
-    assertThat(updatedCustomMeasure.getValue()).isCloseTo(1984d, offset(0.01d));
-    assertThat(updatedCustomMeasure.getDescription()).isEqualTo("new-custom-measure-description");
-    assertThat(customMeasure.getCreatedAt()).isEqualTo(updatedCustomMeasure.getCreatedAt());
+    assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()))
+      .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue, CustomMeasureDto::getUserUuid, CustomMeasureDto::getComponentUuid,
+        CustomMeasureDto::getCreatedAt, CustomMeasureDto::getUpdatedAt)
+      .containsExactlyInAnyOrder(
+        tuple("new-custom-measure-description", null, 1984d, userAuthenticated.getUuid(), project.uuid(), customMeasure.getCreatedAt(), NOW));
   }
 
   @Test
-  public void returns_full_object_in_response() throws Exception {
-    MetricDto metric = MetricTesting.newMetricDto().setEnabled(true)
-      .setValueType(ValueType.STRING.name())
-      .setKey("metric-key");
-    dbClient.metricDao().insert(dbSession, metric);
-    OrganizationDto organizationDto = db.organizations().insert();
-    ComponentDto component = ComponentTesting.newPrivateProjectDto(organizationDto, "project-uuid").setDbKey("project-key");
-    dbClient.componentDao().insert(dbSession, component);
-    CustomMeasureDto customMeasure = newCustomMeasure(component, metric)
-      .setCreatedAt(100_000_000L)
-      .setDescription("custom-measure-description")
-      .setTextValue("text-measure-value");
-    dbClient.customMeasureDao().insert(dbSession, customMeasure);
-    dbSession.commit();
-    when(system.now()).thenReturn(123_456_789L);
-    logInAsProjectAdministrator(component);
-
-    WsTester.Result response = ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION)
+  public void returns_full_object_in_response() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto userAuthenticated = db.users().insertUser();
+    userSession.logIn(userAuthenticated).addProjectPermission(ADMIN, project);
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    UserDto userMeasureCreator = db.users().insertUser();
+    CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(userMeasureCreator, project, metric, m -> m.setValue(0d).setCreatedAt(100_000_000L));
+
+    String response = ws.newRequest()
       .setParam(PARAM_ID, String.valueOf(customMeasure.getId()))
       .setParam(PARAM_DESCRIPTION, "new-custom-measure-description")
       .setParam(PARAM_VALUE, "new-text-measure-value")
-      .execute();
-
-    response.assertJson(getClass(), "custom-measure.json");
-    String responseAsString = response.outputAsString();
-    assertThat(responseAsString).matches(String.format(".*\"id\"\\s*:\\s*\"%s\".*", customMeasure.getId()));
-    assertThat(responseAsString).matches(String.format(".*\"id\"\\s*:\\s*\"%s\".*", metric.getId()));
-    assertThat(responseAsString).matches(".*createdAt.*updatedAt.*");
+      .execute()
+      .getInput();
+
+    assertJson(response).isSimilarTo("{\n" +
+      "  \"id\": \"" + customMeasure.getId() + "\",\n" +
+      "  \"value\": \"new-text-measure-value\",\n" +
+      "  \"description\": \"new-custom-measure-description\",\n" +
+      "  \"metric\": {\n" +
+      "    \"id\": \"" + metric.getId() + "\",\n" +
+      "    \"key\": \"" + metric.getKey() + "\",\n" +
+      "    \"type\": \"" + metric.getValueType() + "\",\n" +
+      "    \"name\": \"" + metric.getShortName() + "\",\n" +
+      "    \"domain\": \"" + metric.getDomain() + "\"\n" +
+      "  },\n" +
+      "  \"projectId\": \"" + project.uuid() + "\",\n" +
+      "  \"projectKey\": \"" + project.getKey() + "\",\n" +
+      "}");
   }
 
   @Test
-  public void update_value_only() throws Exception {
-    MetricDto metric = insertNewMetric(ValueType.STRING);
-    ComponentDto component = db.components().insertPrivateProject(db.getDefaultOrganization(), "project-uuid");
-    CustomMeasureDto customMeasure = newCustomMeasure(component, metric)
-      .setDescription("custom-measure-description")
-      .setTextValue("text-measure-value");
-    dbClient.customMeasureDao().insert(dbSession, customMeasure);
-    dbSession.commit();
-    when(system.now()).thenReturn(123_456_789L);
-    logInAsProjectAdministrator(component);
-
-    ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION)
+  public void update_description_only() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(user, project, metric);
+
+    ws.newRequest()
       .setParam(PARAM_ID, String.valueOf(customMeasure.getId()))
       .setParam(PARAM_DESCRIPTION, "new-custom-measure-description")
       .execute();
-    logInAsProjectAdministrator(component);
 
-    CustomMeasureDto updatedCustomMeasure = dbClient.customMeasureDao().selectOrFail(dbSession, customMeasure.getId());
-    assertThat(updatedCustomMeasure.getTextValue()).isEqualTo("text-measure-value");
-    assertThat(updatedCustomMeasure.getDescription()).isEqualTo("new-custom-measure-description");
-    assertThat(updatedCustomMeasure.getUpdatedAt()).isEqualTo(123_456_789L);
-    assertThat(customMeasure.getCreatedAt()).isEqualTo(updatedCustomMeasure.getCreatedAt());
+    assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()))
+      .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue)
+      .containsExactlyInAnyOrder(
+        tuple("new-custom-measure-description", customMeasure.getTextValue(), customMeasure.getValue()));
   }
 
   @Test
-  public void update_description_only() throws Exception {
-    MetricDto metric = insertNewMetric(ValueType.STRING);
-    OrganizationDto organizationDto = db.organizations().insert();
-    ComponentDto component = db.components().insertPrivateProject(organizationDto, "project-uuid");
-    CustomMeasureDto customMeasure = newCustomMeasure(component, metric)
-      .setMetricId(metric.getId())
-      .setComponentUuid(component.uuid())
-      .setCreatedAt(system.now())
-      .setDescription("custom-measure-description")
-      .setTextValue("text-measure-value");
-    dbClient.customMeasureDao().insert(dbSession, customMeasure);
-    dbSession.commit();
-    when(system.now()).thenReturn(123_456_789L);
-    logInAsProjectAdministrator(component);
-
-    ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION)
+  public void update_value_only() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(user, project, metric);
+
+    ws.newRequest()
       .setParam(PARAM_ID, String.valueOf(customMeasure.getId()))
       .setParam(PARAM_VALUE, "new-text-measure-value")
       .execute();
 
-    CustomMeasureDto updatedCustomMeasure = dbClient.customMeasureDao().selectOrFail(dbSession, customMeasure.getId());
-    assertThat(updatedCustomMeasure.getTextValue()).isEqualTo("new-text-measure-value");
-    assertThat(updatedCustomMeasure.getDescription()).isEqualTo("custom-measure-description");
-    assertThat(updatedCustomMeasure.getUpdatedAt()).isEqualTo(123_456_789L);
-    assertThat(customMeasure.getCreatedAt()).isEqualTo(updatedCustomMeasure.getCreatedAt());
+    assertThat(db.getDbClient().customMeasureDao().selectByMetricId(db.getSession(), metric.getId()))
+      .extracting(CustomMeasureDto::getDescription, CustomMeasureDto::getTextValue, CustomMeasureDto::getValue)
+      .containsExactlyInAnyOrder(
+        tuple(customMeasure.getDescription(), "new-text-measure-value", customMeasure.getValue()));
   }
 
   @Test
-  public void fail_if_get_request() throws Exception {
-    expectedException.expect(ServerException.class);
-
-    ws.newGetRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION)
-      .setParam(PARAM_ID, "42")
-      .setParam(PARAM_DESCRIPTION, "new-custom-measure-description")
-      .setParam(PARAM_VALUE, "1984")
-      .execute();
-  }
+  public void fail_if_measure_is_not_in_db() {
+    ComponentDto project = db.components().insertPrivateProject();
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    UserDto user = db.users().insertUser();
+    db.measures().insertCustomMeasure(user, project, metric);
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
 
-  @Test
-  public void fail_if_not_in_db() throws Exception {
-    expectedException.expect(RowNotFoundException.class);
-    expectedException.expectMessage("Custom measure '42' not found.");
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Custom measure with id '0' does not exist");
 
-    ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION)
-      .setParam(PARAM_ID, "42")
+    ws.newRequest()
+      .setParam(PARAM_ID, "0")
       .setParam(PARAM_DESCRIPTION, "new-custom-measure-description")
       .setParam(PARAM_VALUE, "1984")
       .execute();
   }
 
   @Test
-  public void fail_if_insufficient_privileges() throws Exception {
-    userSessionRule.logIn();
-    MetricDto metric = MetricTesting.newMetricDto().setEnabled(true).setValueType(ValueType.STRING.name());
-    dbClient.metricDao().insert(dbSession, metric);
-    ComponentDto component = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization(), "project-uuid");
-    dbClient.componentDao().insert(dbSession, component);
-    CustomMeasureDto customMeasure = newCustomMeasureDto()
-      .setMetricId(metric.getId())
-      .setComponentUuid(component.uuid())
-      .setCreatedAt(system.now())
-      .setDescription("custom-measure-description")
-      .setTextValue("text-measure-value");
-    dbClient.customMeasureDao().insert(dbSession, customMeasure);
-    dbSession.commit();
+  public void fail_if_insufficient_privileges() {
+    ComponentDto project = db.components().insertPrivateProject();
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    UserDto user = db.users().insertUser();
+    CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(user, project, metric);
+    userSession.logIn(user).addProjectPermission(USER, project);
 
     expectedException.expect(ForbiddenException.class);
 
-    ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION)
+    ws.newRequest()
       .setParam(PARAM_ID, String.valueOf(customMeasure.getId()))
       .setParam(PARAM_DESCRIPTION, "new-custom-measure-description")
       .setParam(PARAM_VALUE, "1984")
@@ -266,24 +216,16 @@ public class UpdateActionTest {
   }
 
   @Test
-  public void fail_if_not_logged_in() throws Exception {
-    userSessionRule.anonymous();
+  public void fail_if_not_logged_in() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    CustomMeasureDto customMeasure = db.measures().insertCustomMeasure(user, project, metric);
+    userSession.anonymous();
+
     expectedException.expect(UnauthorizedException.class);
-    MetricDto metric = MetricTesting.newMetricDto().setEnabled(true).setValueType(ValueType.STRING.name());
-    dbClient.metricDao().insert(dbSession, metric);
-    OrganizationDto organizationDto = db.organizations().insert();
-    ComponentDto component = ComponentTesting.newPrivateProjectDto(organizationDto, "project-uuid");
-    dbClient.componentDao().insert(dbSession, component);
-    CustomMeasureDto customMeasure = newCustomMeasureDto()
-      .setMetricId(metric.getId())
-      .setComponentUuid(component.uuid())
-      .setCreatedAt(system.now())
-      .setDescription("custom-measure-description")
-      .setTextValue("text-measure-value");
-    dbClient.customMeasureDao().insert(dbSession, customMeasure);
-    dbSession.commit();
-
-    ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION)
+
+    ws.newRequest()
       .setParam(PARAM_ID, String.valueOf(customMeasure.getId()))
       .setParam(PARAM_DESCRIPTION, "new-custom-measure-description")
       .setParam(PARAM_VALUE, "1984")
@@ -291,39 +233,36 @@ public class UpdateActionTest {
   }
 
   @Test
-  public void fail_if_custom_measure_id_is_missing_in_request() throws Exception {
+  public void fail_if_custom_measure_id_is_missing_in_request() {
+    ComponentDto project = db.components().insertPrivateProject();
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    UserDto user = db.users().insertUser();
+    db.measures().insertCustomMeasure(user, project, metric);
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
     expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("The 'id' parameter is missing");
 
-    ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION)
+    ws.newRequest()
       .setParam(PARAM_DESCRIPTION, "new-custom-measure-description")
       .setParam(PARAM_VALUE, "1984")
       .execute();
   }
 
   @Test
-  public void fail_if_custom_measure_value_and_description_are_missing_in_request() throws Exception {
+  public void fail_if_custom_measure_value_and_description_are_missing_in_request() {
+    ComponentDto project = db.components().insertPrivateProject();
+    MetricDto metric = db.measures().insertMetric(m -> m.setUserManaged(true).setValueType(STRING.name()));
+    UserDto user = db.users().insertUser();
+    db.measures().insertCustomMeasure(user, project, metric);
+    userSession.logIn(user).addProjectPermission(ADMIN, project);
+
     expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Value or description must be provided.");
 
-    ws.newPostRequest(CustomMeasuresWs.ENDPOINT, UpdateAction.ACTION)
+    ws.newRequest()
       .setParam(PARAM_ID, "42")
       .execute();
   }
 
-  private MetricDto insertNewMetric(ValueType metricType) {
-    MetricDto metric = MetricTesting.newMetricDto().setEnabled(true).setValueType(metricType.name());
-    dbClient.metricDao().insert(dbSession, metric);
-
-    return metric;
-  }
-
-  private CustomMeasureDto newCustomMeasure(ComponentDto project, MetricDto metric) {
-    return newCustomMeasureDto()
-      .setMetricId(metric.getId())
-      .setComponentUuid(project.uuid())
-      .setCreatedAt(system.now());
-  }
-
-  private void logInAsProjectAdministrator(ComponentDto component) {
-    userSessionRule.logIn("login").addProjectPermission(UserRole.ADMIN, component);
-  }
 }
index c8f99ed0895845f41d1820a0930c9ac801c93800..df6242d80f1da7b2a6fc3fe46b290a5b0a9d717c 100644 (file)
@@ -84,7 +84,7 @@ public class ChangePasswordActionTest {
       .setPassword("Valar Dohaeris")
       .build(), u -> {
     });
-    String oldCryptedPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword();
+    String oldCryptedPassword = db.getDbClient().userDao().selectByLogin(db.getSession(), "john").getCryptedPassword();
     userSessionRule.logIn("john");
 
     TestResponse response = tester.newRequest()
@@ -94,7 +94,7 @@ public class ChangePasswordActionTest {
       .execute();
 
     assertThat(response.getStatus()).isEqualTo(204);
-    String newCryptedPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword();
+    String newCryptedPassword = db.getDbClient().userDao().selectByLogin(db.getSession(), "john").getCryptedPassword();
     assertThat(newCryptedPassword).isNotEqualTo(oldCryptedPassword);
   }
 
@@ -102,14 +102,14 @@ public class ChangePasswordActionTest {
   public void system_administrator_can_update_password_of_user() {
     userSessionRule.logIn().setSystemAdministrator();
     createLocalUser();
-    String originalPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword();
+    String originalPassword = db.getDbClient().userDao().selectByLogin(db.getSession(), "john").getCryptedPassword();
 
     tester.newRequest()
       .setParam("login", "john")
       .setParam("password", "Valar Morghulis")
       .execute();
 
-    String newPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword();
+    String newPassword = db.getDbClient().userDao().selectByLogin(db.getSession(), "john").getCryptedPassword();
     assertThat(newPassword).isNotEqualTo(originalPassword);
   }
 
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/measure/custom/ws/CreateActionTest/custom-measure.json b/server/sonar-server/src/test/resources/org/sonar/server/measure/custom/ws/CreateActionTest/custom-measure.json
deleted file mode 100644 (file)
index 939b57e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-  "projectId": "project-uuid",
-  "projectKey": "project-key",
-  "metric": {
-    "key": "metric-key",
-    "type": "STRING"
-  },
-  "value": "custom-measure-free-text",
-  "description": "custom-measure-description",
-  "pending":true,
-  "user": {
-    "active": true,
-    "email": "login@login.com",
-    "login": "login",
-    "name": "Login"
-  }
-}
index 6278ab11cbc6faae2ad269458f6932a99fb301cd..e6c6e0eb62f2832aecd47fff69bb78762ab30d01 100644 (file)
@@ -34,21 +34,25 @@ import org.sonarqube.ws.Issues;
 import org.sonarqube.ws.Issues.Issue;
 import org.sonarqube.ws.Organizations.Organization;
 import org.sonarqube.ws.Projects;
+import org.sonarqube.ws.Projects.CreateWsResponse.Project;
 import org.sonarqube.ws.Qualityprofiles;
 import org.sonarqube.ws.Settings;
 import org.sonarqube.ws.UserTokens;
 import org.sonarqube.ws.Users;
 import org.sonarqube.ws.client.GetRequest;
 import org.sonarqube.ws.client.WsClient;
+import org.sonarqube.ws.client.custommeasures.CreateRequest;
 import org.sonarqube.ws.client.issues.AssignRequest;
 import org.sonarqube.ws.client.organizations.AddMemberRequest;
 import org.sonarqube.ws.client.organizations.SearchRequest;
+import org.sonarqube.ws.client.permissions.AddUserRequest;
 import org.sonarqube.ws.client.qualityprofiles.ChangelogRequest;
 import org.sonarqube.ws.client.settings.SetRequest;
 import org.sonarqube.ws.client.settings.ValuesRequest;
 import org.sonarqube.ws.client.usertokens.GenerateRequest;
 
 import static java.util.Collections.singletonList;
+import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.skyscreamer.jsonassert.JSONAssert.assertEquals;
 import static util.ItUtils.projectDir;
@@ -262,6 +266,66 @@ public class SonarCloudUpdateLoginDuringAuthenticationTest {
       .contains("token1", "token2");
   }
 
+  @Test
+  public void manual_measure_after_login_update() throws JSONException {
+    tester.settings().setGlobalSettings("sonar.organizations.anyoneCanCreate", "true");
+    String providerId = tester.users().generateProviderId();
+    String oldLogin = tester.users().generateLogin();
+
+    // Create user using authentication
+    authenticate(oldLogin, providerId);
+    String userToken = tester.wsClient().userTokens().generate(new GenerateRequest().setLogin(oldLogin).setName("token")).getToken();
+    WsClient userWsClient = tester.as(userToken, null).wsClient();
+
+    // Grant user the admin permission on a project
+    Organization organization = tester.organizations().generate();
+    Project project = tester.projects().provision(organization);
+    tester.organizations().service().addMember(new AddMemberRequest().setOrganization(organization.getKey()).setLogin(oldLogin));
+    String customMetricKey = randomAlphanumeric(50);
+    tester.wsClient().metrics().create(new org.sonarqube.ws.client.metrics.CreateRequest().setKey(customMetricKey).setName("custom").setType("INT"));
+    tester.wsClient().permissions().addUser(new AddUserRequest().setLogin(oldLogin).setProjectKey(project.getKey()).setPermission("admin"));
+
+    // Create a manual metric and a manual measure on it
+    userWsClient.customMeasures().create(new CreateRequest().setMetricKey(customMetricKey).setProjectKey(project.getKey()).setValue("50"));
+    String manualMeasures = tester.wsClient().customMeasures().search(new org.sonarqube.ws.client.custommeasures.SearchRequest().setProjectKey(project.getKey()));
+    assertEquals(
+      "{\n" +
+        "  \"customMeasures\": [\n" +
+        "    {\n" +
+        "      \"projectKey\": \"" + project.getKey() + "\",\n" +
+        "      \"user\": {\n" +
+        "        \"login\": \"" + oldLogin + "\",\n" +
+        "        \"name\": \"John\",\n" +
+        "        \"email\": \"john@email.com\",\n" +
+        "        \"active\": true\n" +
+        "      }" +
+        "    }" +
+        "  ]\n" +
+        "}",
+      manualMeasures,
+      false);
+
+    // Update login during authentication, check manual measure contains new user login
+    String newLogin = tester.users().generateLogin();
+    authenticate(newLogin, providerId);
+    assertEquals(
+      "{\n" +
+        "  \"customMeasures\": [\n" +
+        "    {\n" +
+        "      \"projectKey\": \"" + project.getKey() + "\",\n" +
+        "      \"user\": {\n" +
+        "        \"login\": \"" + newLogin + "\",\n" +
+        "        \"name\": \"John\",\n" +
+        "        \"email\": \"john@email.com\",\n" +
+        "        \"active\": true\n" +
+        "      }" +
+        "    }" +
+        "  ]\n" +
+        "}",
+      tester.wsClient().customMeasures().search(new org.sonarqube.ws.client.custommeasures.SearchRequest().setProjectKey(project.getKey())),
+      false);
+  }
+
   private void authenticate(String login, String providerId) {
     tester.settings().setGlobalSettings("sonar.auth.fake-base-id-provider.user", login + "," + providerId + ",fake-" + login + ",John,john@email.com");
     tester.wsClient().wsConnector().call(