@@ -21,6 +21,8 @@ package org.sonar.db.notification; | |||
import java.util.Collections; | |||
import java.util.List; | |||
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.MyBatis; | |||
@@ -28,15 +30,21 @@ import org.sonar.db.MyBatis; | |||
public class NotificationQueueDao implements Dao { | |||
private final MyBatis mybatis; | |||
private System2 system2; | |||
private UuidFactory uuidFactory; | |||
public NotificationQueueDao(MyBatis mybatis) { | |||
public NotificationQueueDao(MyBatis mybatis, System2 system2, UuidFactory uuidFactory) { | |||
this.mybatis = mybatis; | |||
this.system2 = system2; | |||
this.uuidFactory = uuidFactory; | |||
} | |||
public void insert(List<NotificationQueueDto> dtos) { | |||
try (DbSession session = mybatis.openSession(true)) { | |||
NotificationQueueMapper mapper = session.getMapper(NotificationQueueMapper.class); | |||
for (NotificationQueueDto dto : dtos) { | |||
dto.setUuid(uuidFactory.create()); | |||
dto.setCreatedAt(system2.now()); | |||
mapper.insert(dto); | |||
} | |||
session.commit(); | |||
@@ -47,7 +55,7 @@ public class NotificationQueueDao implements Dao { | |||
try (DbSession session = mybatis.openSession(true)) { | |||
NotificationQueueMapper mapper = session.getMapper(NotificationQueueMapper.class); | |||
for (NotificationQueueDto dto : dtos) { | |||
mapper.delete(dto.getId()); | |||
mapper.delete(dto.getUuid()); | |||
} | |||
session.commit(); | |||
} |
@@ -35,15 +35,16 @@ import org.sonar.api.utils.SonarException; | |||
*/ | |||
public class NotificationQueueDto { | |||
private Long id; | |||
private String uuid; | |||
private byte[] data; | |||
private long createdAt; | |||
public Long getId() { | |||
return id; | |||
public String getUuid() { | |||
return uuid; | |||
} | |||
public NotificationQueueDto setId(Long id) { | |||
this.id = id; | |||
NotificationQueueDto setUuid(String uuid) { | |||
this.uuid = uuid; | |||
return this; | |||
} | |||
@@ -56,6 +57,15 @@ public class NotificationQueueDto { | |||
return this; | |||
} | |||
public long getCreatedAt() { | |||
return createdAt; | |||
} | |||
NotificationQueueDto setCreatedAt(long createdAt) { | |||
this.createdAt = createdAt; | |||
return this; | |||
} | |||
@Override | |||
public String toString() { | |||
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); |
@@ -28,7 +28,7 @@ public interface NotificationQueueMapper { | |||
void insert(NotificationQueueDto actionPlanDto); | |||
void delete(long id); | |||
void delete(String uuid); | |||
List<NotificationQueueDto> findOldest(int count); | |||
@@ -5,12 +5,12 @@ | |||
<mapper namespace="org.sonar.db.notification.NotificationQueueMapper"> | |||
<insert id="insert" parameterType="NotificationQueue" useGeneratedKeys="false"> | |||
INSERT INTO notifications (data) | |||
VALUES (#{data}) | |||
INSERT INTO notifications (uuid,data,created_at) | |||
VALUES (#{uuid},#{data},#{createdAt}) | |||
</insert> | |||
<delete id="delete" parameterType="long"> | |||
delete from notifications where id=#{id} | |||
<delete id="delete" parameterType="String"> | |||
delete from notifications where uuid=#{uuid} | |||
</delete> | |||
<select id="count" resultType="long"> | |||
@@ -18,25 +18,25 @@ | |||
</select> | |||
<select id="findOldest" parameterType="int" resultType="NotificationQueue"> | |||
select id, data | |||
select uuid, data, created_at | |||
from notifications | |||
order by id asc | |||
order by created_at asc | |||
limit #{count} | |||
</select> | |||
<!-- SQL Server --> | |||
<select id="findOldest" parameterType="int" resultType="NotificationQueue" databaseId="mssql"> | |||
select top (#{count}) id, data | |||
select top (#{count}) uuid, data, created_at | |||
from notifications | |||
order by id asc | |||
order by created_at asc | |||
</select> | |||
<!-- Oracle --> | |||
<select id="findOldest" parameterType="int" resultType="NotificationQueue" databaseId="oracle"> | |||
select * from (select | |||
id, data | |||
uuid, data, created_at | |||
from notifications | |||
order by id asc | |||
order by created_at asc | |||
) | |||
where rownum <= #{count} | |||
</select> |
@@ -483,10 +483,11 @@ ALTER TABLE "NEW_CODE_PERIODS" ADD CONSTRAINT "PK_NEW_CODE_PERIODS" PRIMARY KEY( | |||
CREATE UNIQUE INDEX "UNIQ_NEW_CODE_PERIODS" ON "NEW_CODE_PERIODS"("PROJECT_UUID", "BRANCH_UUID"); | |||
CREATE TABLE "NOTIFICATIONS"( | |||
"ID" INTEGER NOT NULL AUTO_INCREMENT (1,1), | |||
"DATA" BLOB | |||
"DATA" BLOB, | |||
"UUID" VARCHAR(40) NOT NULL, | |||
"CREATED_AT" BIGINT NOT NULL | |||
); | |||
ALTER TABLE "NOTIFICATIONS" ADD CONSTRAINT "PK_NOTIFICATIONS" PRIMARY KEY("ID"); | |||
ALTER TABLE "NOTIFICATIONS" ADD CONSTRAINT "PK_NOTIFICATIONS" PRIMARY KEY("UUID"); | |||
CREATE TABLE "ORG_QPROFILES"( | |||
"UUID" VARCHAR(255) NOT NULL, |
@@ -21,22 +21,27 @@ package org.sonar.db.notification; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import java.util.Random; | |||
import java.util.stream.IntStream; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
import org.sonar.api.notifications.Notification; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbTester; | |||
import static java.util.stream.Collectors.toList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
import static org.sonar.db.notification.NotificationQueueDto.toNotificationQueueDto; | |||
public class NotificationQueueDaoTest { | |||
private final System2 system2 = mock(System2.class); | |||
@Rule | |||
public DbTester db = DbTester.create(System2.INSTANCE); | |||
public DbTester db = DbTester.create(system2); | |||
private NotificationQueueDao dao = db.getDbClient().notificationQueueDao(); | |||
@@ -63,41 +68,45 @@ public class NotificationQueueDaoTest { | |||
@Test | |||
public void should_delete_notification() { | |||
List<NotificationQueueDto> notifs = IntStream.range(0, 30 + new Random().nextInt(20)) | |||
List<NotificationQueueDto> notifs = IntStream.range(0, 30) | |||
.mapToObj(i -> toNotificationQueueDto(new Notification("foo_" + i))) | |||
.collect(toList()); | |||
dao.insert(notifs); | |||
db.commit(); | |||
List<Long> ids = selectAllIds(); | |||
List<String> uuids = selectAllUuid(); | |||
dao.delete(ids.stream().limit(10).map(id -> new NotificationQueueDto().setId(id)).collect(toList())); | |||
dao.delete(uuids.stream().limit(10).map(uuid -> new NotificationQueueDto().setUuid(uuid)).collect(toList())); | |||
assertThat(selectAllIds()).containsOnly(ids.stream().skip(10).toArray(Long[]::new)); | |||
assertThat(selectAllUuid()).containsOnly(uuids.stream().skip(10).toArray(String[]::new)); | |||
} | |||
@Test | |||
public void should_findOldest() { | |||
List<NotificationQueueDto> notifs = IntStream.range(0, 20) | |||
when(system2.now()).thenAnswer(new Answer<Long>() { | |||
private long counter; | |||
@Override | |||
public Long answer(InvocationOnMock invocationOnMock) { | |||
counter++; | |||
return counter; | |||
} | |||
}); | |||
List<NotificationQueueDto> notifs = IntStream.range(0, 5) | |||
.mapToObj(i -> toNotificationQueueDto(new Notification("foo_" + i))) | |||
.collect(toList()); | |||
dao.insert(notifs); | |||
db.commit(); | |||
List<Long> ids = selectAllIds(); | |||
assertThat(dao.selectOldest(3)) | |||
.extracting(NotificationQueueDto::getId) | |||
.containsOnly(ids.stream().limit(3).toArray(Long[]::new)); | |||
assertThat(dao.selectOldest(22)) | |||
.extracting(NotificationQueueDto::getId) | |||
.containsOnly(ids.toArray(new Long[0])); | |||
.extracting(NotificationQueueDto::getUuid) | |||
.containsExactlyElementsOf(Arrays.asList("1", "2", "3")); | |||
} | |||
private List<Long> selectAllIds() { | |||
return db.select("select id as \"ID\" from notifications").stream() | |||
.map(t -> (Long) t.get("ID")) | |||
private List<String> selectAllUuid() { | |||
return db.select("select uuid as \"UUID\" from notifications order by created_at asc").stream() | |||
.map(t -> (String) t.get("UUID")) | |||
.collect(toList()); | |||
} | |||
} |
@@ -21,6 +21,12 @@ package org.sonar.server.platform.db.migration.version.v83; | |||
import org.sonar.server.platform.db.migration.step.MigrationStepRegistry; | |||
import org.sonar.server.platform.db.migration.version.DbVersion; | |||
import org.sonar.server.platform.db.migration.version.v83.notifications.AddPrimaryKeyOnUuidColumnOfNotificationTable; | |||
import org.sonar.server.platform.db.migration.version.v83.notifications.AddUuidAndCreatedAtColumnsToNotification; | |||
import org.sonar.server.platform.db.migration.version.v83.notifications.DropIdColumnOfNotificationTable; | |||
import org.sonar.server.platform.db.migration.version.v83.notifications.DropPrimaryKeyOnIdColumnOfNotificationTable; | |||
import org.sonar.server.platform.db.migration.version.v83.notifications.MakeNotificationUuidAndCreatedAtColumnsNotNullable; | |||
import org.sonar.server.platform.db.migration.version.v83.notifications.PopulateNotificationUuidAndCreatedAt; | |||
public class DbVersion83 implements DbVersion { | |||
@Override | |||
@@ -42,7 +48,15 @@ public class DbVersion83 implements DbVersion { | |||
// Migration on EVENTS table | |||
.add(3400, "Drop primary key on 'ID' column of 'EVENTS' table", DropPrimaryKeyOnIdColumnOfEventsTable.class) | |||
.add(3401, "Add primary key on 'UUID' column of 'EVENTS' table", AddPrimaryKeyOnUuidColumnOfEventsTable.class) | |||
.add(3402, "Drop column 'ID' of 'EVENTS' table", DropIdColumnOfEventsTable.class); | |||
.add(3402, "Drop column 'ID' of 'EVENTS' table", DropIdColumnOfEventsTable.class) | |||
// Migrations of NOTIFICATIONS table | |||
.add(3403, "Add 'uuid' and 'createdAt' columns for notifications", AddUuidAndCreatedAtColumnsToNotification.class) | |||
.add(3404, "Populate 'uuid' and 'createdAt columns for notifications", PopulateNotificationUuidAndCreatedAt.class) | |||
.add(3405, "Make 'uuid' and 'createdAt' column not nullable for notifications", MakeNotificationUuidAndCreatedAtColumnsNotNullable.class) | |||
.add(3406, "Drop primary key on 'ID' column of 'NOTIFICATIONS' table", DropPrimaryKeyOnIdColumnOfNotificationTable.class) | |||
.add(3407, "Add primary key on 'UUID' column of 'NOTIFICATIONS' table", AddPrimaryKeyOnUuidColumnOfNotificationTable.class) | |||
.add(3408, "Drop column 'ID' of 'NOTIFICATIONS' table", DropIdColumnOfNotificationTable.class) | |||
; | |||
} |
@@ -0,0 +1,38 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 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.v83.notifications; | |||
import java.sql.SQLException; | |||
import org.sonar.db.Database; | |||
import org.sonar.server.platform.db.migration.step.DdlChange; | |||
import org.sonar.server.platform.db.migration.version.v83.util.AddPrimaryKeyBuilder; | |||
public class AddPrimaryKeyOnUuidColumnOfNotificationTable extends DdlChange { | |||
public AddPrimaryKeyOnUuidColumnOfNotificationTable(Database db) { | |||
super(db); | |||
} | |||
@Override | |||
public void execute(Context context) throws SQLException { | |||
context.execute(new AddPrimaryKeyBuilder("notifications", "uuid").build()); | |||
} | |||
} |
@@ -0,0 +1,58 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 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.v83.notifications; | |||
import java.sql.SQLException; | |||
import org.sonar.db.Database; | |||
import org.sonar.server.platform.db.migration.def.BigIntegerColumnDef; | |||
import org.sonar.server.platform.db.migration.def.VarcharColumnDef; | |||
import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder; | |||
import org.sonar.server.platform.db.migration.step.DdlChange; | |||
import static org.sonar.server.platform.db.migration.def.BigIntegerColumnDef.newBigIntegerColumnDefBuilder; | |||
import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder; | |||
public class AddUuidAndCreatedAtColumnsToNotification extends DdlChange { | |||
private static final String TABLE = "notifications"; | |||
private static final VarcharColumnDef uuidColumnDefinition = newVarcharColumnDefBuilder() | |||
.setColumnName("uuid") | |||
.setIsNullable(true) | |||
.setDefaultValue(null) | |||
.setLimit(VarcharColumnDef.UUID_SIZE) | |||
.build(); | |||
private static final BigIntegerColumnDef createdAtColumnDefinition = newBigIntegerColumnDefBuilder() | |||
.setColumnName("created_at") | |||
.setIsNullable(true) | |||
.build(); | |||
public AddUuidAndCreatedAtColumnsToNotification(Database db) { | |||
super(db); | |||
} | |||
@Override | |||
public void execute(Context context) throws SQLException { | |||
context.execute(new AddColumnsBuilder(getDialect(), TABLE) | |||
.addColumn(uuidColumnDefinition) | |||
.addColumn(createdAtColumnDefinition) | |||
.build()); | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 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.v83.notifications; | |||
import java.sql.SQLException; | |||
import org.sonar.db.Database; | |||
import org.sonar.server.platform.db.migration.sql.DropColumnsBuilder; | |||
import org.sonar.server.platform.db.migration.step.DdlChange; | |||
public class DropIdColumnOfNotificationTable extends DdlChange { | |||
public DropIdColumnOfNotificationTable(Database db) { | |||
super(db); | |||
} | |||
@Override | |||
public void execute(Context context) throws SQLException { | |||
context.execute(new DropColumnsBuilder(getDialect(), "notifications", "id").build()); | |||
} | |||
} |
@@ -0,0 +1,41 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 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.v83.notifications; | |||
import java.sql.SQLException; | |||
import org.sonar.db.Database; | |||
import org.sonar.server.platform.db.migration.step.DdlChange; | |||
import org.sonar.server.platform.db.migration.version.v83.util.DropPrimaryKeySqlGenerator; | |||
public class DropPrimaryKeyOnIdColumnOfNotificationTable extends DdlChange { | |||
private final DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator; | |||
public DropPrimaryKeyOnIdColumnOfNotificationTable(Database db, DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator) { | |||
super(db); | |||
this.dropPrimaryKeySqlGenerator = dropPrimaryKeySqlGenerator; | |||
} | |||
@Override | |||
public void execute(Context context) throws SQLException { | |||
context.execute(dropPrimaryKeySqlGenerator.generate("notifications", "notifications","id")); | |||
} | |||
} |
@@ -0,0 +1,59 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 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.v83.notifications; | |||
import java.sql.SQLException; | |||
import org.sonar.db.Database; | |||
import org.sonar.server.platform.db.migration.def.BigIntegerColumnDef; | |||
import org.sonar.server.platform.db.migration.def.VarcharColumnDef; | |||
import org.sonar.server.platform.db.migration.sql.AlterColumnsBuilder; | |||
import org.sonar.server.platform.db.migration.step.DdlChange; | |||
import static org.sonar.server.platform.db.migration.def.BigIntegerColumnDef.newBigIntegerColumnDefBuilder; | |||
import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder; | |||
public class MakeNotificationUuidAndCreatedAtColumnsNotNullable extends DdlChange { | |||
private static final String TABLE = "notifications"; | |||
private static final VarcharColumnDef uuidColumnDefinition = newVarcharColumnDefBuilder() | |||
.setColumnName("uuid") | |||
.setIsNullable(false) | |||
.setDefaultValue(null) | |||
.setLimit(VarcharColumnDef.UUID_SIZE) | |||
.build(); | |||
private static final BigIntegerColumnDef createdAtColumnDefinition = newBigIntegerColumnDefBuilder() | |||
.setColumnName("created_at") | |||
.setIsNullable(false) | |||
.build(); | |||
public MakeNotificationUuidAndCreatedAtColumnsNotNullable(Database db) { | |||
super(db); | |||
} | |||
@Override | |||
public void execute(Context context) throws SQLException { | |||
context.execute(new AlterColumnsBuilder(getDialect(), TABLE) | |||
.updateColumn(uuidColumnDefinition) | |||
.updateColumn(createdAtColumnDefinition) | |||
.build()); | |||
} | |||
} |
@@ -0,0 +1,60 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 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.v83.notifications; | |||
import java.sql.SQLException; | |||
import java.util.concurrent.atomic.AtomicLong; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.core.util.UuidFactory; | |||
import org.sonar.db.Database; | |||
import org.sonar.server.platform.db.migration.step.DataChange; | |||
import org.sonar.server.platform.db.migration.step.MassUpdate; | |||
public class PopulateNotificationUuidAndCreatedAt extends DataChange { | |||
private final UuidFactory uuidFactory; | |||
private final System2 system2; | |||
public PopulateNotificationUuidAndCreatedAt(Database db, UuidFactory uuidFactory, System2 system2) { | |||
super(db); | |||
this.uuidFactory = uuidFactory; | |||
this.system2 = system2; | |||
} | |||
@Override | |||
protected void execute(Context context) throws SQLException { | |||
MassUpdate massUpdate = context.prepareMassUpdate(); | |||
massUpdate.select("select id from notifications order by id asc"); | |||
massUpdate.update("update notifications set uuid = ?, created_at = ? where id = ?"); | |||
// now - 7 days, to have previous notification in the past | |||
long lastWeek = system2.now() - (1000 * 60 * 60 * 24 * 7); | |||
AtomicLong cpt = new AtomicLong(0); | |||
massUpdate.execute((row, update) -> { | |||
update.setString(1, uuidFactory.create()); | |||
update.setLong(2, lastWeek + cpt.longValue()); | |||
update.setLong(3, row.getLong(1)); | |||
cpt.addAndGet(1); | |||
return true; | |||
}); | |||
} | |||
} |
@@ -52,6 +52,12 @@ public class DbVersionTestUtils { | |||
assertThat(registry.migrationNumbers).hasSize(migrationCount); | |||
} | |||
public static void verifyMigrationNotEmpty(DbVersion underTest) { | |||
TestMigrationStepRegistry registry = new TestMigrationStepRegistry(); | |||
underTest.addSteps(registry); | |||
assertThat(registry.migrationNumbers).isNotEmpty(); | |||
} | |||
private static class TestMigrationStepRegistry implements MigrationStepRegistry { | |||
private Set<Long> migrationNumbers = new HashSet<>(); | |||
@@ -22,7 +22,7 @@ package org.sonar.server.platform.db.migration.version.v83; | |||
import org.junit.Test; | |||
import org.sonar.server.platform.db.migration.version.DbVersion; | |||
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationCount; | |||
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationNotEmpty; | |||
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMinimumMigrationNumber; | |||
public class DbVersion83Test { | |||
@@ -36,7 +36,7 @@ public class DbVersion83Test { | |||
@Test | |||
public void verify_migration_count() { | |||
verifyMigrationCount(underTest, 15); | |||
verifyMigrationNotEmpty(underTest); | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 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.v83.notifications; | |||
import java.sql.SQLException; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.db.CoreDbTester; | |||
import org.sonar.server.platform.db.migration.step.MigrationStep; | |||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | |||
public class AddPrimaryKeyOnUuidColumnOfNotificationTableTest { | |||
@Rule | |||
public CoreDbTester db = CoreDbTester.createForSchema(AddPrimaryKeyOnUuidColumnOfNotificationTableTest.class, "schema.sql"); | |||
private MigrationStep underTest = new AddPrimaryKeyOnUuidColumnOfNotificationTable(db.database()); | |||
@Test | |||
public void execute() throws SQLException { | |||
underTest.execute(); | |||
db.assertPrimaryKey("notifications", "pk_notifications", "uuid"); | |||
} | |||
@Test | |||
public void migration_is_not_re_entrant() throws SQLException { | |||
underTest.execute(); | |||
assertThatThrownBy(() -> underTest.execute()).isInstanceOf(IllegalStateException.class); | |||
} | |||
} |
@@ -0,0 +1,83 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 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.v83.notifications; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.io.ObjectOutputStream; | |||
import java.sql.SQLException; | |||
import java.sql.Types; | |||
import org.apache.commons.io.IOUtils; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.utils.SonarException; | |||
import org.sonar.db.CoreDbTester; | |||
import org.sonar.server.platform.db.migration.step.DdlChange; | |||
import static java.sql.Types.BIGINT; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class AddUuidAndCreatedAtColumnsToNotificationTest { | |||
@Rule | |||
public CoreDbTester db = CoreDbTester.createForSchema(AddUuidAndCreatedAtColumnsToNotificationTest.class, "schema.sql"); | |||
private DdlChange underTest = new AddUuidAndCreatedAtColumnsToNotification(db.database()); | |||
@Before | |||
public void setup() { | |||
insertNotification(1L, "data1"); | |||
insertNotification(2L, "data2"); | |||
insertNotification(3L, "data3"); | |||
} | |||
@Test | |||
public void add_uuid_and_created_at_columns_to_notification() throws SQLException { | |||
underTest.execute(); | |||
db.assertColumnDefinition("notifications", "uuid", Types.VARCHAR, 40, true); | |||
db.assertColumnDefinition("notifications", "created_at", BIGINT, null, true); | |||
assertThat(db.countSql("select count(id) from notifications")) | |||
.isEqualTo(3); | |||
} | |||
private void insertNotification(Long id, String data) { | |||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); | |||
try { | |||
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); | |||
objectOutputStream.writeObject(data); | |||
objectOutputStream.close(); | |||
byte[] byteArray = byteArrayOutputStream.toByteArray(); | |||
db.executeInsert("notifications", | |||
"id", id, | |||
"data", byteArray); | |||
} catch (IOException e) { | |||
throw new SonarException("Unable to write notification", e); | |||
} finally { | |||
IOUtils.closeQuietly(byteArrayOutputStream); | |||
} | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 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.v83.notifications; | |||
import java.sql.SQLException; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.db.CoreDbTester; | |||
import org.sonar.server.platform.db.migration.step.MigrationStep; | |||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | |||
public class DropIdColumnOfNotificationTableTest { | |||
@Rule | |||
public CoreDbTester db = CoreDbTester.createForSchema(DropIdColumnOfNotificationTableTest.class, "schema.sql"); | |||
private MigrationStep underTest = new DropIdColumnOfNotificationTable(db.database()); | |||
@Test | |||
public void execute() throws SQLException { | |||
underTest.execute(); | |||
db.assertColumnDoesNotExist("notifications", "id"); | |||
} | |||
@Test | |||
public void migration_is_not_re_entrant() throws SQLException { | |||
underTest.execute(); | |||
assertThatThrownBy(() -> underTest.execute()).isInstanceOf(IllegalStateException.class); | |||
} | |||
} |
@@ -0,0 +1,56 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 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.v83.notifications; | |||
import java.sql.SQLException; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.db.CoreDbTester; | |||
import org.sonar.server.platform.db.migration.step.MigrationStep; | |||
import org.sonar.server.platform.db.migration.version.v83.util.DropPrimaryKeySqlGenerator; | |||
import org.sonar.server.platform.db.migration.version.v83.util.GetConstraintHelper; | |||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | |||
public class DropPrimaryKeyOnIdColumnOfNotificationTableTest { | |||
private static final String TABLE_NAME = "notifications"; | |||
@Rule | |||
public CoreDbTester db = CoreDbTester.createForSchema(DropPrimaryKeyOnIdColumnOfNotificationTableTest.class, "schema.sql"); | |||
private DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator = new DropPrimaryKeySqlGenerator(db.database(), new GetConstraintHelper(db.database())); | |||
private MigrationStep underTest = new DropPrimaryKeyOnIdColumnOfNotificationTable(db.database(), dropPrimaryKeySqlGenerator); | |||
@Test | |||
public void execute() throws SQLException { | |||
underTest.execute(); | |||
db.assertNoPrimaryKey(TABLE_NAME); | |||
} | |||
@Test | |||
public void migration_is_not_re_entrant() throws SQLException { | |||
underTest.execute(); | |||
assertThatThrownBy(() -> underTest.execute()).isInstanceOf(IllegalStateException.class); | |||
} | |||
} |
@@ -0,0 +1,45 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 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.v83.notifications; | |||
import java.sql.SQLException; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.db.CoreDbTester; | |||
import org.sonar.server.platform.db.migration.step.MigrationStep; | |||
import static java.sql.Types.BIGINT; | |||
import static java.sql.Types.VARCHAR; | |||
public class MakeNotificationUuidAndCreatedAtColumnsNotNullableTest { | |||
@Rule | |||
public CoreDbTester db = CoreDbTester.createForSchema(MakeNotificationUuidAndCreatedAtColumnsNotNullableTest.class, "schema.sql"); | |||
private MigrationStep underTest = new MakeNotificationUuidAndCreatedAtColumnsNotNullable(db.database()); | |||
@Test | |||
public void created_at_and_uuid_columns_are_not_null() throws SQLException { | |||
underTest.execute(); | |||
db.assertColumnDefinition("notifications", "uuid", VARCHAR, null, false); | |||
db.assertColumnDefinition("notifications", "created_at", BIGINT, null, false); | |||
} | |||
} |
@@ -0,0 +1,110 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 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.v83.notifications; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.io.ObjectOutputStream; | |||
import java.sql.SQLException; | |||
import java.util.Objects; | |||
import java.util.stream.Collectors; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.core.util.UuidFactory; | |||
import org.sonar.core.util.UuidFactoryFast; | |||
import org.sonar.db.CoreDbTester; | |||
import org.sonar.server.platform.db.migration.step.DataChange; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class PopulateNotificationUuidAndCreatedAtTest { | |||
@Rule | |||
public CoreDbTester db = CoreDbTester.createForSchema(PopulateNotificationUuidAndCreatedAtTest.class, "schema.sql"); | |||
private UuidFactory uuidFactory = UuidFactoryFast.getInstance(); | |||
private System2 system2 = mock(System2.class); | |||
private DataChange underTest = new PopulateNotificationUuidAndCreatedAt(db.database(), uuidFactory, system2); | |||
@Before | |||
public void before() { | |||
// exactly one week before now + 1ms, so that ID are exactly equals to timestamp in the tests | |||
when(system2.now()).thenReturn((1000 * 60 * 60 * 24 * 7) + 1L); | |||
} | |||
@Test | |||
public void populate_uuids_and_created_at() throws IOException, SQLException { | |||
insertNotification(1L, "data1"); | |||
insertNotification(2L, "data2"); | |||
insertNotification(3L, "data3"); | |||
underTest.execute(); | |||
verifyUuidsAreNotNull(); | |||
verifyCreatedAt(); | |||
} | |||
@Test | |||
public void migration_is_reentrant() throws IOException, SQLException { | |||
insertNotification(1L, "data1"); | |||
insertNotification(2L, "data2"); | |||
insertNotification(3L, "data3"); | |||
underTest.execute(); | |||
// re-entrant | |||
underTest.execute(); | |||
verifyUuidsAreNotNull(); | |||
verifyCreatedAt(); | |||
} | |||
private void verifyUuidsAreNotNull() { | |||
assertThat(db.select("select uuid from notifications") | |||
.stream() | |||
.map(row -> row.get("UUID")) | |||
.filter(Objects::isNull) | |||
.collect(Collectors.toList())).isEmpty(); | |||
} | |||
private void verifyCreatedAt() { | |||
assertThat(db.select("select id, created_at from notifications") | |||
.stream() | |||
.filter(row -> !row.get("CREATED_AT").equals(row.get("ID"))) | |||
.collect(Collectors.toList())).isEmpty(); | |||
} | |||
private void insertNotification(Long id, String data) throws IOException { | |||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); | |||
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); | |||
objectOutputStream.writeObject(data); | |||
objectOutputStream.close(); | |||
byte[] byteArray = byteArrayOutputStream.toByteArray(); | |||
db.executeInsert("notifications", | |||
"id", id, | |||
"data", byteArray); | |||
} | |||
} |
@@ -0,0 +1,6 @@ | |||
CREATE TABLE "NOTIFICATIONS"( | |||
"ID" INTEGER NOT NULL, | |||
"DATA" BLOB, | |||
"UUID" VARCHAR(40) NOT NULL, | |||
"CREATED_AT" BIGINT NOT NULL | |||
); |
@@ -0,0 +1,5 @@ | |||
CREATE TABLE "NOTIFICATIONS"( | |||
"ID" INTEGER NOT NULL AUTO_INCREMENT (1,1), | |||
"DATA" BLOB | |||
); | |||
ALTER TABLE "NOTIFICATIONS" ADD CONSTRAINT "PK_NOTIFICATIONS" PRIMARY KEY("ID"); |
@@ -0,0 +1,7 @@ | |||
CREATE TABLE "NOTIFICATIONS"( | |||
"ID" INTEGER NOT NULL, | |||
"DATA" BLOB, | |||
"UUID" VARCHAR(40) NOT NULL, | |||
"CREATED_AT" BIGINT NOT NULL | |||
); | |||
ALTER TABLE "NOTIFICATIONS" ADD CONSTRAINT "PK_NOTIFICATIONS" PRIMARY KEY("UUID"); |
@@ -0,0 +1,7 @@ | |||
CREATE TABLE "NOTIFICATIONS"( | |||
"ID" INTEGER NOT NULL AUTO_INCREMENT (1,1), | |||
"UUID" VARCHAR(40) NOT NULL, | |||
"CREATED_AT" BIGINT NOT NULL, | |||
"DATA" BLOB | |||
); | |||
ALTER TABLE "NOTIFICATIONS" ADD CONSTRAINT "PK_NOTIFICATIONS" PRIMARY KEY("ID"); |
@@ -0,0 +1,7 @@ | |||
CREATE TABLE "NOTIFICATIONS"( | |||
"ID" INTEGER NOT NULL AUTO_INCREMENT (1,1), | |||
"UUID" VARCHAR(40), | |||
"CREATED_AT" BIGINT, | |||
"DATA" BLOB | |||
); | |||
ALTER TABLE "NOTIFICATIONS" ADD CONSTRAINT "PK_NOTIFICATIONS" PRIMARY KEY("ID"); |
@@ -0,0 +1,7 @@ | |||
CREATE TABLE "NOTIFICATIONS"( | |||
"ID" INTEGER NOT NULL AUTO_INCREMENT (1,1), | |||
"UUID" VARCHAR(40), | |||
"CREATED_AT" BIGINT NULL, | |||
"DATA" BLOB | |||
); | |||
ALTER TABLE "NOTIFICATIONS" ADD CONSTRAINT "PK_NOTIFICATIONS" PRIMARY KEY("ID"); |
@@ -36,8 +36,10 @@ import javax.annotation.Nullable; | |||
import org.sonar.api.notifications.Notification; | |||
import org.sonar.api.notifications.NotificationChannel; | |||
import org.sonar.api.utils.SonarException; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.api.utils.log.Logger; | |||
import org.sonar.api.utils.log.Loggers; | |||
import org.sonar.core.util.UuidFactory; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
@@ -59,13 +61,13 @@ public class DefaultNotificationManager implements NotificationManager { | |||
private NotificationChannel[] notificationChannels; | |||
private final DbClient dbClient; | |||
private boolean alreadyLoggedDeserializationIssue = false; | |||
/** | |||
* Default constructor used by Pico | |||
*/ | |||
public DefaultNotificationManager(NotificationChannel[] channels, | |||
DbClient dbClient) { | |||
public DefaultNotificationManager(NotificationChannel[] channels, DbClient dbClient) { | |||
this.notificationChannels = channels; | |||
this.dbClient = dbClient; | |||
} |
@@ -38,7 +38,10 @@ import org.junit.rules.ExpectedException; | |||
import org.mockito.InOrder; | |||
import org.sonar.api.notifications.Notification; | |||
import org.sonar.api.notifications.NotificationChannel; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.api.web.UserRole; | |||
import org.sonar.core.util.UuidFactory; | |||
import org.sonar.core.util.UuidFactoryFast; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.EmailSubscriberDto; | |||
@@ -83,6 +86,7 @@ public class DefaultNotificationManagerTest { | |||
private AuthorizationDao authorizationDao = mock(AuthorizationDao.class); | |||
private DbClient dbClient = mock(DbClient.class); | |||
private DbSession dbSession = mock(DbSession.class); | |||
private System2 system2 = mock(System2.class); | |||
@Before | |||
public void setUp() { | |||
@@ -93,6 +97,7 @@ public class DefaultNotificationManagerTest { | |||
when(dbClient.propertiesDao()).thenReturn(propertiesDao); | |||
when(dbClient.notificationQueueDao()).thenReturn(notificationQueueDao); | |||
when(dbClient.authorizationDao()).thenReturn(authorizationDao); | |||
when(system2.now()).thenReturn(0L); | |||
underTest = new DefaultNotificationManager(new NotificationChannel[] {emailChannel, twitterChannel}, dbClient); | |||
} | |||
@@ -345,7 +350,8 @@ public class DefaultNotificationManagerTest { | |||
String projectKey = randomAlphabetic(6); | |||
when(propertiesDao.findEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey)) | |||
.thenReturn( | |||
newHashSet(EmailSubscriberDto.create("user1", false, "user1@foo"), EmailSubscriberDto.create("user3", false, "user3@foo"), EmailSubscriberDto.create("user3", true, "user3@foo"))); | |||
newHashSet(EmailSubscriberDto.create("user1", false, "user1@foo"), EmailSubscriberDto.create("user3", false, "user3@foo"), | |||
EmailSubscriberDto.create("user3", true, "user3@foo"))); | |||
when(authorizationDao.keepAuthorizedLoginsOnProject(dbSession, newHashSet("user3", "user4"), projectKey, globalPermission)) | |||
.thenReturn(newHashSet("user3")); | |||
when(authorizationDao.keepAuthorizedLoginsOnProject(dbSession, newHashSet("user1", "user3"), projectKey, projectPermission)) | |||
@@ -370,7 +376,8 @@ public class DefaultNotificationManagerTest { | |||
Set<String> logins = ImmutableSet.of("user1", "user2", "user3"); | |||
when(propertiesDao.findEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey, logins)) | |||
.thenReturn( | |||
newHashSet(EmailSubscriberDto.create("user1", false, "user1@foo"), EmailSubscriberDto.create("user3", false, "user3@foo"), EmailSubscriberDto.create("user3", true, "user3@foo"))); | |||
newHashSet(EmailSubscriberDto.create("user1", false, "user1@foo"), EmailSubscriberDto.create("user3", false, "user3@foo"), | |||
EmailSubscriberDto.create("user3", true, "user3@foo"))); | |||
when(authorizationDao.keepAuthorizedLoginsOnProject(dbSession, newHashSet("user3", "user4"), projectKey, globalPermission)) | |||
.thenReturn(newHashSet("user3")); | |||
when(authorizationDao.keepAuthorizedLoginsOnProject(dbSession, newHashSet("user1", "user3"), projectKey, projectPermission)) |