]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7824 Add DB column ACTIVITIES.PROFILE_KEY
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Fri, 24 Jun 2016 14:36:23 +0000 (16:36 +0200)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Wed, 29 Jun 2016 09:06:00 +0000 (11:06 +0200)
20 files changed:
server/sonar-server/src/main/java/org/sonar/server/activity/Activity.java
server/sonar-server/src/main/java/org/sonar/server/activity/ActivityService.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ActiveRuleChange.java
server/sonar-server/src/test/java/org/sonar/server/activity/ActivityServiceTest.java
server/sonar-server/src/test/java/org/sonar/server/activity/index/ActivityResultSetIteratorTest.java
server/sonar-server/src/test/java/org/sonar/server/activity/ws/ActivitiesWsMediumTest.java
server/sonar-server/src/test/resources/org/sonar/server/activity/index/ActivityResultSetIteratorTest/traverse.xml
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1259_add_profile_key_to_activities.rb [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/activity/ActivityDao.java
sonar-db/src/main/java/org/sonar/db/activity/ActivityDto.java
sonar-db/src/main/java/org/sonar/db/version/DatabaseVersion.java
sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java
sonar-db/src/main/java/org/sonar/db/version/v60/AddProfileKeyToActivities.java [new file with mode: 0644]
sonar-db/src/main/resources/org/sonar/db/activity/ActivityMapper.xml
sonar-db/src/main/resources/org/sonar/db/version/schema-h2.ddl
sonar-db/src/test/java/org/sonar/db/activity/ActivityDaoTest.java
sonar-db/src/test/java/org/sonar/db/version/MigrationStepModuleTest.java
sonar-db/src/test/java/org/sonar/db/version/v52/RemoveAnalysisReportsFromActivitiesTest.java
sonar-db/src/test/java/org/sonar/db/version/v60/AddProfileKeyToActivitiesTest.java [new file with mode: 0644]
sonar-db/src/test/resources/org/sonar/db/version/v60/AddProfileKeyToActivitiesTest/activities.sql [new file with mode: 0644]

index f4e8939f933817920dbf921a35ea4b38025f747f..67069330b302f6e1b6dca390469bcadd67d23433 100644 (file)
  */
 package org.sonar.server.activity;
 
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
 import java.util.LinkedHashMap;
 import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
 
 public class Activity {
 
@@ -34,7 +33,8 @@ public class Activity {
   private Type type;
   private String action;
   private String message;
-  private final Map<String,Object> data = new LinkedHashMap<>();
+  private String profileKey;
+  private final Map<String, Object> data = new LinkedHashMap<>();
 
   public Type getType() {
     return type;
@@ -69,4 +69,13 @@ public class Activity {
     this.data.put(key, val);
     return this;
   }
+
+  public String getProfileKey() {
+    return profileKey;
+  }
+
+  public Activity setProfileKey(String profileKey) {
+    this.profileKey = profileKey;
+    return this;
+  }
 }
index 0f1f013b75977b5fe4d24bef11e294370bda20ac..bf3885e353ec9122176a8e39e876385dfa87e06e 100644 (file)
@@ -21,9 +21,10 @@ package org.sonar.server.activity;
 
 import org.sonar.api.utils.KeyValueFormat;
 import org.sonar.core.util.Uuids;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
 import org.sonar.db.activity.ActivityDto;
 import org.sonar.server.activity.index.ActivityIndexer;
-import org.sonar.db.DbClient;
 import org.sonar.server.user.UserSession;
 
 public class ActivityService {
@@ -45,8 +46,15 @@ public class ActivityService {
       .setAction(activity.getAction())
       .setMessage(activity.getMessage())
       .setData(KeyValueFormat.format(activity.getData()))
+      .setProfileKey(activity.getProfileKey())
       .setType(activity.getType().name());
-    dbClient.activityDao().insert(dto);
-    indexer.index();
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      dbClient.activityDao().insert(dbSession, dto);
+      dbSession.commit();
+      indexer.index();
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
   }
 }
index 8c910f5140c7ae8953daf80eb197bd709906d5d5..87350de9d0156baad4ffcfe04a9fa0e936be6372 100644 (file)
@@ -92,6 +92,7 @@ public class ActiveRuleChange {
     Activity activity = new Activity();
     activity.setType(Activity.Type.QPROFILE);
     activity.setAction(type.name());
+    activity.setProfileKey(getKey().qProfile());
     activity.setData("key", getKey().toString());
     activity.setData("ruleKey", getKey().ruleKey().toString());
     activity.setData("profileKey", getKey().qProfile());
index 9904058376c39afcddf2615e33b97b4aec2e9dd0..696189279595b56595fe9ebf3602235a796aaa37 100644 (file)
@@ -71,20 +71,22 @@ public class ActivityServiceTest {
     activity.setAction("THE_ACTION");
     activity.setMessage("THE_MSG");
     activity.setData("foo", "bar");
+    activity.setData("profileKey", "PROFILE_KEY");
+    activity.setProfileKey("PROFILE_KEY");
     service.save(activity);
 
     Map<String, Object> dbMap = db.selectFirst("select log_type as \"type\", log_action as \"action\", log_message as \"msg\", data_field as \"data\" from activities");
     assertThat(dbMap).containsEntry("type", "ANALYSIS_REPORT");
     assertThat(dbMap).containsEntry("action", "THE_ACTION");
     assertThat(dbMap).containsEntry("msg", "THE_MSG");
-    assertThat(dbMap.get("data")).isEqualTo("foo=bar");
+    assertThat(dbMap.get("data")).isEqualTo("foo=bar;profileKey=PROFILE_KEY");
 
     List<ActivityDoc> docs = es.getDocuments("activities", "activity", ActivityDoc.class);
     assertThat(docs).hasSize(1);
     assertThat(docs.get(0).getKey()).isNotEmpty();
     assertThat(docs.get(0).getAction()).isEqualTo("THE_ACTION");
     assertThat(docs.get(0).getMessage()).isEqualTo("THE_MSG");
-    assertThat(docs.get(0).getDetails()).containsOnly(MapEntry.entry("foo", "bar"));
+    assertThat(docs.get(0).getDetails()).containsOnly(MapEntry.entry("foo", "bar"), MapEntry.entry("profileKey", "PROFILE_KEY"));
   }
 
 }
index ee56231d38957fb05b58737873806261112e99d6..7a20cd28de2fbe53a53e2b462afdd509ce8d0cbd 100644 (file)
@@ -30,7 +30,6 @@ import org.sonar.db.DbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-
 public class ActivityResultSetIteratorTest {
 
   @Rule
index 196a6e100c0252bf8707cb10066528c923009d3e..895b3cf233165da90a8589307025be8b7b795de8 100644 (file)
@@ -31,6 +31,7 @@ import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.ws.WsTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.test.JsonAssert.assertJson;
 
 public class ActivitiesWsMediumTest {
 
@@ -68,12 +69,28 @@ public class ActivitiesWsMediumTest {
     activity.setAction("THE_ACTION");
     activity.setMessage("THE_MSG");
     activity.setData("foo", "bar");
-    service.save(activity);
+    activity.setProfileKey("PROFILE_KEY");
 
+    service.save(activity);
     WsTester.TestRequest request = tester.wsTester().newGetRequest("api/activities", "search");
-    WsTester.Result result = request.execute();
-    assertThat(result.outputAsString()).contains("\"total\":1");
-    assertThat(result.outputAsString()).contains("\"type\":\"ANALYSIS_REPORT\"");
-    assertThat(result.outputAsString()).contains("\"details\":{\"foo\":\"bar\"}");
+
+    String result = request.execute().outputAsString();
+    assertJson(result).isSimilarTo(
+      "{" +
+        "  \"total\": 1," +
+        "  \"p\": 1," +
+        "  \"ps\": 10," +
+        "  \"logs\": [" +
+        "    {" +
+        "      \"type\": \"ANALYSIS_REPORT\"," +
+        "      \"action\": \"THE_ACTION\"," +
+        "      \"message\": \"THE_MSG\"," +
+        "      \"details\": {" +
+        "        \"profileKey\": \"PROFILE_KEY\"," +
+        "        \"foo\": \"bar\"" +
+        "      }" +
+        "    }" +
+        "  ]" +
+        "}");
   }
 }
index f92f767837929aebba3940402d13dee7bd67fe91..1a480fc228f855db28500e46484af4897dd1b950 100644 (file)
@@ -1,7 +1,7 @@
 <dataset>
   <activities id="1" log_key="UUID1" log_type="ANALYSIS_REPORT" log_action="THE_ACTION" log_message="THE_MSG"
-              created_at="2014-01-01" data_field="foo=bar" user_login="THE_AUTHOR"/>
+              created_at="2014-01-01" data_field="foo=bar" user_login="THE_AUTHOR" profile_key="PROFILE_KEY"/>
 
   <activities id="2" log_key="UUID2" log_type="ANALYSIS_REPORT" log_action="THE_ACTION" log_message="THE_MSG"
-              created_at="2015-01-01" data_field="foo=bar" user_login="THE_AUTHOR"/>
+              created_at="2015-01-01" data_field="foo=bar" user_login="THE_AUTHOR" profile_key="PROFILE_KEY"/>
 </dataset>
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1259_add_profile_key_to_activities.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1259_add_profile_key_to_activities.rb
new file mode 100644 (file)
index 0000000..e879702
--- /dev/null
@@ -0,0 +1,28 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube 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.
+#
+# SonarQube 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.
+#
+#
+# SonarQube 6.0
+# SONAR-7794
+#
+class AddProfileKeyToActivities < ActiveRecord::Migration
+  def self.up
+    execute_java_migration('org.sonar.db.version.v60.AddProfileKeyToActivities')
+  end
+end
index d180c138b72e2deef8c8a0701986853531d2e2b6..7c8a7e274166004cb8b32c1505c03794994b6689 100644 (file)
@@ -31,16 +31,6 @@ public class ActivityDao extends AbstractDao {
     super(mybatis, system);
   }
 
-  public void insert(ActivityDto dto) {
-    DbSession session = myBatis().openSession(false);
-    try {
-      insert(session, dto);
-      session.commit();
-    } finally {
-      MyBatis.closeQuietly(session);
-    }
-  }
-
   public void insert(DbSession session, ActivityDto dto) {
     dto.setCreatedAt(new Date(now()));
     session.getMapper(ActivityMapper.class).insert(dto);
index a50be420e2f6f39b30c8474cb2b154864d5dd1b2..70b8b7a4c00121f581e2adc721018ac38dcde80d 100644 (file)
@@ -27,6 +27,7 @@ import org.apache.commons.lang.builder.ToStringStyle;
 public class ActivityDto {
 
   private String key;
+  private String profileKey;
   private String message;
   private String type;
   private String action;
@@ -43,6 +44,15 @@ public class ActivityDto {
     return key;
   }
 
+  public String getProfileKey() {
+    return profileKey;
+  }
+
+  public ActivityDto setProfileKey(String profileKey) {
+    this.profileKey = profileKey;
+    return this;
+  }
+
   public Date getCreatedAt() {
     return createdAt;
   }
index 0099f81fdb8e6b07fdeda5360728b327735337ac..ec5a26be02053ddf01de2a0c884f38ba648dc48c 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.db.MyBatis;
 
 public class DatabaseVersion {
 
-  public static final int LAST_VERSION = 1_258;
+  public static final int LAST_VERSION = 1_259;
 
   /**
    * The minimum supported version which can be upgraded. Lower
index 064eedfa29569815ad14e9922e4302e8083b37d2..b8c9c9e3eb44f619d054f57454910880d7143d2a 100644 (file)
@@ -90,6 +90,7 @@ import org.sonar.db.version.v60.AddComponentUuidColumnToDuplicationsIndex;
 import org.sonar.db.version.v60.AddComponentUuidColumnToMeasures;
 import org.sonar.db.version.v60.AddComponentUuidColumnsToSnapshots;
 import org.sonar.db.version.v60.AddLastUsedColumnToRulesProfiles;
+import org.sonar.db.version.v60.AddProfileKeyToActivities;
 import org.sonar.db.version.v60.AddUuidColumnToSnapshots;
 import org.sonar.db.version.v60.AddUuidColumnsToProjects;
 import org.sonar.db.version.v60.AddUuidColumnsToResourceIndex;
@@ -241,6 +242,7 @@ public class MigrationStepModule extends Module {
       DropIdColumnsFromProjects.class,
       AddLastUsedColumnToRulesProfiles.class,
       PopulateLastUsedColumnOfRulesProfiles.class,
+      AddProfileKeyToActivities.class,
 
       // SNAPSHOTS.UUID
       AddUuidColumnToSnapshots.class,
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/AddProfileKeyToActivities.java b/sonar-db/src/main/java/org/sonar/db/version/v60/AddProfileKeyToActivities.java
new file mode 100644 (file)
index 0000000..54b3712
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.db.version.v60;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.version.AddColumnsBuilder;
+import org.sonar.db.version.DdlChange;
+
+import static org.sonar.db.version.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class AddProfileKeyToActivities extends DdlChange {
+
+  private static final String TABLE_ACTIVITIES = "activities";
+
+  public AddProfileKeyToActivities(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(new AddColumnsBuilder(getDatabase().getDialect(), TABLE_ACTIVITIES)
+      .addColumn(newVarcharColumnDefBuilder().setColumnName("profile_key").setLimit(255).setIsNullable(true).build())
+      .build());
+  }
+
+}
index 0014464aa2c231c40f5931d885cff7d9ee97a3af..63084a2355109f57a869e95093b893fd2e8a4b0a 100644 (file)
@@ -5,10 +5,10 @@
 
   <insert id="insert" parameterType="Activity" useGeneratedKeys="false">
     insert into activities
-    (created_at, log_key, log_type, log_action, user_login, data_field, log_message)
+    (created_at, log_key, log_type, log_action, user_login, data_field, log_message, profile_key)
     values (#{createdAt,jdbcType=TIMESTAMP}, #{key,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR},
     #{action,jdbcType=VARCHAR},
-    #{author,jdbcType=VARCHAR}, #{data,jdbcType=VARCHAR}, #{message,jdbcType=VARCHAR})
+    #{author,jdbcType=VARCHAR}, #{data,jdbcType=VARCHAR}, #{message,jdbcType=VARCHAR}, #{profileKey, jdbcType=VARCHAR})
   </insert>
 
 </mapper>
index 72e3aa398c76da536dc7c5e26f45d75c65b5f178..b9cafa5b94a633f2208515dd6d42ba9044fc1e46 100644 (file)
@@ -476,6 +476,7 @@ CREATE TABLE "PERM_TEMPLATES_GROUPS" (
 CREATE TABLE "ACTIVITIES" (
   "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
   "LOG_KEY" VARCHAR(250),
+  "PROFILE_KEY" VARCHAR(255),
   "CREATED_AT" TIMESTAMP,
   "USER_LOGIN" VARCHAR(255),
   "LOG_TYPE" VARCHAR(250),
index d43fb92738fceec6533f6b0d1e0f7516de298c5c..eb410ab599ee96d75845fd9c092812a206087aa8 100644 (file)
@@ -23,19 +23,20 @@ import java.util.Map;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.utils.System2;
+import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
-
 public class ActivityDaoTest {
 
   System2 system = mock(System2.class);
 
   @Rule
   public DbTester dbTester = DbTester.create(system);
+  DbSession dbSession = dbTester.getSession();
 
   ActivityDao underTest = dbTester.getDbClient().activityDao();
 
@@ -43,15 +44,23 @@ public class ActivityDaoTest {
   public void insert() {
     when(system.now()).thenReturn(1_500_000_000_000L);
     ActivityDto dto = new ActivityDto()
-      .setKey("UUID_1").setAction("THE_ACTION").setType("THE_TYPE")
-      .setAuthor("THE_AUTHOR").setData("THE_DATA");
-    underTest.insert(dto);
+      .setKey("UUID_1")
+      .setAction("THE_ACTION")
+      .setType("THE_TYPE")
+      .setAuthor("THE_AUTHOR")
+      .setData("THE_DATA")
+      .setProfileKey("PROFILE_KEY");
+    underTest.insert(dbSession, dto);
+    dbSession.commit();
 
-    Map<String, Object> map = dbTester.selectFirst("select created_at as \"createdAt\", log_action as \"action\", data_field as \"data\" from activities where log_key='UUID_1'");
+    Map<String, Object> map = dbTester.selectFirst("select created_at as \"createdAt\", log_action as \"action\", " +
+      "data_field as \"data\", profile_key as \"profileKey\" " +
+      "from activities where log_key='UUID_1'");
     assertThat(map.get("action")).isEqualTo("THE_ACTION");
     // not possible to check exact date yet. dbTester#selectFirst() uses ResultSet#getObject(), which returns
     // non-JDBC interface in Oracle driver.
     assertThat(map.get("createdAt")).isNotNull();
     assertThat(map.get("data")).isEqualTo("THE_DATA");
+    assertThat(map.get("profileKey")).isEqualTo("PROFILE_KEY");
   }
 }
index 6c85da727e30f03f7a8a2c742fccff1ca82d442e..00e8e84fecb43e7061e9a9579caf6755a4a6816f 100644 (file)
@@ -29,6 +29,6 @@ public class MigrationStepModuleTest {
   public void verify_count_of_added_MigrationStep_types() {
     ComponentContainer container = new ComponentContainer();
     new MigrationStepModule().configure(container);
-    assertThat(container.size()).isEqualTo(114);
+    assertThat(container.size()).isEqualTo(115);
   }
 }
index 85a415da6b8c587268247f1527bcc6b19e59b8df..b1502e86b5f7b7230c09f792dbf86f094b0fdfd7 100644 (file)
@@ -22,6 +22,8 @@ package org.sonar.db.version.v52;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.activity.ActivityDto;
 import org.sonar.db.version.MigrationStep;
@@ -31,14 +33,16 @@ import static org.assertj.core.api.Assertions.assertThat;
 public class RemoveAnalysisReportsFromActivitiesTest {
   @Rule
   public DbTester db = DbTester.create(System2.INSTANCE);
+  DbClient dbClient = db.getDbClient();
+  DbSession dbSession = db.getSession();
 
   MigrationStep underTest = new RemoveAnalysisReportsFromActivities(db.database());
 
   @Test
   public void test() throws Exception {
-    db.getDbClient().activityDao().insert(new ActivityDto().setType("ANALYSIS_REPORT").setKey("1"));
-    db.getDbClient().activityDao().insert(new ActivityDto().setType("ANALYSIS_REPORT").setKey("2"));
-    db.getDbClient().activityDao().insert(new ActivityDto().setType("PROFILE_CHANGE").setKey("3"));
+    dbClient.activityDao().insert(dbSession, new ActivityDto().setType("ANALYSIS_REPORT").setKey("1"));
+    dbClient.activityDao().insert(dbSession, new ActivityDto().setType("ANALYSIS_REPORT").setKey("2"));
+    dbClient.activityDao().insert(dbSession, new ActivityDto().setType("PROFILE_CHANGE").setKey("3"));
 
     underTest.execute();
 
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v60/AddProfileKeyToActivitiesTest.java b/sonar-db/src/test/java/org/sonar/db/version/v60/AddProfileKeyToActivitiesTest.java
new file mode 100644 (file)
index 0000000..f5c9d35
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.db.version.v60;
+
+import java.sql.SQLException;
+import java.sql.Types;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+
+public class AddProfileKeyToActivitiesTest {
+
+  @Rule
+  public DbTester db = DbTester.createForSchema(System2.INSTANCE, AddProfileKeyToActivitiesTest.class, "activities.sql");
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private AddProfileKeyToActivities underTest = new AddProfileKeyToActivities(db.database());
+
+  @Test
+  public void migration_adds_column_to_empty_table() throws SQLException {
+    underTest.execute();
+
+    verifyAddedColumns();
+  }
+
+  @Test
+  public void migration_adds_column_to_populated_table() throws SQLException {
+    for (int i = 0; i < 9; i++) {
+      db.executeInsert(
+        "activities",
+        "log_key", "LOG_KEY_" + i,
+        "user_login", "login");
+    }
+    db.commit();
+
+    underTest.execute();
+
+    verifyAddedColumns();
+  }
+
+  @Test
+  public void migration_is_not_reentrant() throws SQLException {
+    underTest.execute();
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Fail to execute ");
+    underTest.execute();
+  }
+
+  private void verifyAddedColumns() {
+    db.assertColumnDefinition("activities", "profile_key", Types.VARCHAR, 255, true);
+  }
+
+}
diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v60/AddProfileKeyToActivitiesTest/activities.sql b/sonar-db/src/test/resources/org/sonar/db/version/v60/AddProfileKeyToActivitiesTest/activities.sql
new file mode 100644 (file)
index 0000000..338d203
--- /dev/null
@@ -0,0 +1,10 @@
+CREATE TABLE "ACTIVITIES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "LOG_KEY" VARCHAR(250),
+  "CREATED_AT" TIMESTAMP,
+  "USER_LOGIN" VARCHAR(255),
+  "LOG_TYPE" VARCHAR(250),
+  "LOG_ACTION" VARCHAR(250),
+  "LOG_MESSAGE" VARCHAR(250),
+  "DATA_FIELD" CLOB(2147483647)
+);