]> source.dussan.org Git - sonarqube.git/blob
536e281e7e71678b14030a89ed90a8ecf246b541
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2023 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 package org.sonar.server.platform.db.migration.engine;
21
22 import java.sql.SQLException;
23 import java.util.List;
24 import java.util.Optional;
25 import org.junit.Before;
26 import org.junit.Test;
27 import org.sonar.api.config.internal.ConfigurationBridge;
28 import org.sonar.api.config.internal.MapSettings;
29 import org.sonar.core.platform.SpringComponentContainer;
30 import org.sonar.process.ProcessProperties;
31 import org.sonar.server.platform.db.migration.SupportsBlueGreen;
32 import org.sonar.server.platform.db.migration.history.MigrationHistory;
33 import org.sonar.server.platform.db.migration.step.MigrationStep;
34 import org.sonar.server.platform.db.migration.step.MigrationSteps;
35 import org.sonar.server.platform.db.migration.step.MigrationStepsExecutor;
36 import org.sonar.server.platform.db.migration.step.RegisteredMigrationStep;
37
38 import static java.util.Arrays.asList;
39 import static java.util.Collections.singletonList;
40 import static org.assertj.core.api.Assertions.assertThat;
41 import static org.junit.Assert.fail;
42 import static org.mockito.Mockito.mock;
43 import static org.mockito.Mockito.times;
44 import static org.mockito.Mockito.verify;
45 import static org.mockito.Mockito.when;
46
47 public class MigrationEngineImplTest {
48   private final MigrationHistory migrationHistory = mock(MigrationHistory.class);
49   private final SpringComponentContainer serverContainer = new SpringComponentContainer();
50   private final MigrationSteps migrationSteps = mock(MigrationSteps.class);
51   private final StepRegistry stepRegistry = new StepRegistry();
52   private final MapSettings settings = new MapSettings();
53   private final MigrationEngineImpl underTest = new MigrationEngineImpl(migrationHistory, serverContainer, migrationSteps, new ConfigurationBridge(settings));
54
55   @Before
56   public void before() {
57     serverContainer.add(migrationSteps);
58     serverContainer.add(migrationHistory);
59     serverContainer.add(stepRegistry);
60     serverContainer.startComponents();
61   }
62
63   @Test
64   public void execute_execute_all_steps_of_there_is_no_last_migration_number() {
65     when(migrationHistory.getLastMigrationNumber()).thenReturn(Optional.empty());
66     List<RegisteredMigrationStep> steps = singletonList(new RegisteredMigrationStep(1, "doo", TestMigrationStep.class));
67     when(migrationSteps.readAll()).thenReturn(steps);
68
69     underTest.execute();
70
71     verify(migrationSteps, times(2)).readAll();
72     assertThat(stepRegistry.stepRan).isTrue();
73   }
74
75   @Test
76   public void execute_execute_steps_from_last_migration_number_plus_1() {
77     when(migrationHistory.getLastMigrationNumber()).thenReturn(Optional.of(50L));
78     List<RegisteredMigrationStep> steps = singletonList(new RegisteredMigrationStep(1, "doo", TestMigrationStep.class));
79     when(migrationSteps.readFrom(51)).thenReturn(steps);
80     when(migrationSteps.readAll()).thenReturn(steps);
81
82     underTest.execute();
83
84     verify(migrationSteps).readFrom(51);
85     assertThat(stepRegistry.stepRan).isTrue();
86   }
87
88   @Test
89   public void execute_steps_in_blue_green_mode() {
90     settings.setProperty(ProcessProperties.Property.BLUE_GREEN_ENABLED.getKey(), true);
91     when(migrationHistory.getLastMigrationNumber()).thenReturn(Optional.of(50L));
92     List<RegisteredMigrationStep> steps = singletonList(new RegisteredMigrationStep(1, "doo", TestBlueGreenMigrationStep.class));
93     when(migrationSteps.readFrom(51)).thenReturn(steps);
94     when(migrationSteps.readAll()).thenReturn(steps);
95
96     underTest.execute();
97
98     verify(migrationSteps).readFrom(51);
99     assertThat(stepRegistry.stepRan).isTrue();
100   }
101
102   @Test
103   public void fail_blue_green_execution_if_some_migrations_are_not_compatible() {
104     settings.setProperty(ProcessProperties.Property.BLUE_GREEN_ENABLED.getKey(), true);
105     when(migrationHistory.getLastMigrationNumber()).thenReturn(Optional.of(50L));
106     List<RegisteredMigrationStep> steps = asList(
107       new RegisteredMigrationStep(1, "foo", TestBlueGreenMigrationStep.class),
108       new RegisteredMigrationStep(2, "bar", TestMigrationStep.class));
109     when(migrationSteps.readFrom(51)).thenReturn(steps);
110
111     try {
112       underTest.execute();
113       fail();
114     } catch (IllegalStateException e) {
115       assertThat(e).hasMessage("All migrations canceled. #2 does not support blue/green deployment: bar");
116       assertThat(stepRegistry.stepRan).isFalse();
117     }
118   }
119
120   private static class NoOpExecutor implements MigrationStepsExecutor {
121     @Override
122     public void execute(List<RegisteredMigrationStep> steps) {
123       // no op
124     }
125   }
126
127   private static class StepRegistry {
128     boolean stepRan = false;
129   }
130
131   private static class TestMigrationStep implements MigrationStep {
132     private final StepRegistry registry;
133
134     public TestMigrationStep(StepRegistry registry) {
135       this.registry = registry;
136     }
137     @Override
138     public void execute() throws SQLException {
139       registry.stepRan = true;
140     }
141   }
142
143   @SupportsBlueGreen
144   private static class TestBlueGreenMigrationStep implements MigrationStep {
145     private final StepRegistry registry;
146
147     public TestBlueGreenMigrationStep(StepRegistry registry) {
148       this.registry = registry;
149     }
150     @Override
151     public void execute() throws SQLException {
152       registry.stepRan = true;
153     }
154   }
155 }