]> source.dussan.org Git - sonarqube.git/blob
f0b31e5c9aa189cb4b2d8ae077ecd77c750d8acb
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2022 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.verifyZeroInteractions;
46 import static org.mockito.Mockito.when;
47
48 public class MigrationEngineImplTest {
49   private final MigrationHistory migrationHistory = mock(MigrationHistory.class);
50   private final SpringComponentContainer serverContainer = new SpringComponentContainer();
51   private final MigrationSteps migrationSteps = mock(MigrationSteps.class);
52   private final StepRegistry stepRegistry = new StepRegistry();
53   private final MapSettings settings = new MapSettings();
54   private final MigrationEngineImpl underTest = new MigrationEngineImpl(migrationHistory, serverContainer, migrationSteps, new ConfigurationBridge(settings));
55
56   @Before
57   public void before() {
58     serverContainer.add(migrationSteps);
59     serverContainer.add(migrationHistory);
60     serverContainer.add(stepRegistry);
61     serverContainer.startComponents();
62   }
63
64   @Test
65   public void execute_execute_all_steps_of_there_is_no_last_migration_number() {
66     when(migrationHistory.getLastMigrationNumber()).thenReturn(Optional.empty());
67     List<RegisteredMigrationStep> steps = singletonList(new RegisteredMigrationStep(1, "doo", TestMigrationStep.class));
68     when(migrationSteps.readAll()).thenReturn(steps);
69
70     underTest.execute();
71
72     verify(migrationSteps, times(2)).readAll();
73     assertThat(stepRegistry.stepRan).isTrue();
74   }
75
76   @Test
77   public void execute_execute_steps_from_last_migration_number_plus_1() {
78     when(migrationHistory.getLastMigrationNumber()).thenReturn(Optional.of(50L));
79     List<RegisteredMigrationStep> steps = singletonList(new RegisteredMigrationStep(1, "doo", TestMigrationStep.class));
80     when(migrationSteps.readFrom(51)).thenReturn(steps);
81     when(migrationSteps.readAll()).thenReturn(steps);
82
83     underTest.execute();
84
85     verify(migrationSteps).readFrom(51);
86     assertThat(stepRegistry.stepRan).isTrue();
87   }
88
89   @Test
90   public void execute_steps_in_blue_green_mode() {
91     settings.setProperty(ProcessProperties.Property.BLUE_GREEN_ENABLED.getKey(), true);
92     when(migrationHistory.getLastMigrationNumber()).thenReturn(Optional.of(50L));
93     List<RegisteredMigrationStep> steps = singletonList(new RegisteredMigrationStep(1, "doo", TestBlueGreenMigrationStep.class));
94     when(migrationSteps.readFrom(51)).thenReturn(steps);
95     when(migrationSteps.readAll()).thenReturn(steps);
96
97     underTest.execute();
98
99     verify(migrationSteps).readFrom(51);
100     assertThat(stepRegistry.stepRan).isTrue();
101   }
102
103   @Test
104   public void fail_blue_green_execution_if_some_migrations_are_not_compatible() {
105     settings.setProperty(ProcessProperties.Property.BLUE_GREEN_ENABLED.getKey(), true);
106     when(migrationHistory.getLastMigrationNumber()).thenReturn(Optional.of(50L));
107     List<RegisteredMigrationStep> steps = asList(
108       new RegisteredMigrationStep(1, "foo", TestBlueGreenMigrationStep.class),
109       new RegisteredMigrationStep(2, "bar", TestMigrationStep.class));
110     when(migrationSteps.readFrom(51)).thenReturn(steps);
111
112     try {
113       underTest.execute();
114       fail();
115     } catch (IllegalStateException e) {
116       assertThat(e).hasMessage("All migrations canceled. #2 does not support blue/green deployment: bar");
117       assertThat(stepRegistry.stepRan).isFalse();
118     }
119   }
120
121   private static class NoOpExecutor implements MigrationStepsExecutor {
122     @Override
123     public void execute(List<RegisteredMigrationStep> steps) {
124       // no op
125     }
126   }
127
128   private static class StepRegistry {
129     boolean stepRan = false;
130   }
131
132   private static class TestMigrationStep implements MigrationStep {
133     private final StepRegistry registry;
134
135     public TestMigrationStep(StepRegistry registry) {
136       this.registry = registry;
137     }
138     @Override
139     public void execute() throws SQLException {
140       registry.stepRan = true;
141     }
142   }
143
144   @SupportsBlueGreen
145   private static class TestBlueGreenMigrationStep implements MigrationStep {
146     private final StepRegistry registry;
147
148     public TestBlueGreenMigrationStep(StepRegistry registry) {
149       this.registry = registry;
150     }
151     @Override
152     public void execute() throws SQLException {
153       registry.stepRan = true;
154     }
155   }
156 }