diff options
author | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2018-09-26 08:58:59 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2018-10-04 20:20:56 +0200 |
commit | 2c540713f9289d8cfd14a65f3b4c3c33a4696e20 (patch) | |
tree | 6f880db9407f37ccaf479cc79a8bf1c777a92b15 /server/sonar-ce-task | |
parent | e80c0f3d1e5cd459f88b7e0c41a2d9a7519e260f (diff) | |
download | sonarqube-2c540713f9289d8cfd14a65f3b4c3c33a4696e20.tar.gz sonarqube-2c540713f9289d8cfd14a65f3b4c3c33a4696e20.zip |
SONAR-11310 add temporary columns to CE tables
- add main_component_uuid temporary columns to CE_QUEUE
- add main_last_key and main_component_uuid columns to CE_ACTIVITY
- back to initial paradigm in Compute Engine: even for branches/PRs, the row in table PROJECTS a task belongs to is created in api/ce/submit
- add main component concept to CeTask
- improved consistency check when processing a report task to account for row in PROJECTS now being the one of the branche/PR
- stronger validation of characteristics passed to api/ce/submit
- add api/system/migrate_data for SonarCloud online data migration
Diffstat (limited to 'server/sonar-ce-task')
3 files changed, 215 insertions, 51 deletions
diff --git a/server/sonar-ce-task/src/main/java/org/sonar/ce/task/CeTask.java b/server/sonar-ce-task/src/main/java/org/sonar/ce/task/CeTask.java index d71f9d036d0..3ea246612fa 100644 --- a/server/sonar-ce-task/src/main/java/org/sonar/ce/task/CeTask.java +++ b/server/sonar-ce-task/src/main/java/org/sonar/ce/task/CeTask.java @@ -22,10 +22,13 @@ package org.sonar.ce.task; import com.google.common.base.MoreObjects; import java.util.HashMap; import java.util.Map; +import java.util.Objects; +import java.util.Optional; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; +import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Strings.emptyToNull; import static java.util.Collections.emptyMap; import static java.util.Collections.unmodifiableMap; @@ -37,9 +40,8 @@ public class CeTask { private final String organizationUuid; private final String type; private final String uuid; - private final String componentUuid; - private final String componentKey; - private final String componentName; + private final Component component; + private final Component mainComponent; private final String submitterUuid; private final Map<String, String> characteristics; @@ -47,9 +49,10 @@ public class CeTask { this.organizationUuid = requireNonNull(emptyToNull(builder.organizationUuid), "organizationUuid can't be null nor empty"); this.uuid = requireNonNull(emptyToNull(builder.uuid), "uuid can't be null nor empty"); this.type = requireNonNull(emptyToNull(builder.type), "type can't be null nor empty"); - this.componentUuid = emptyToNull(builder.componentUuid); - this.componentKey = emptyToNull(builder.componentKey); - this.componentName = emptyToNull(builder.componentName); + checkArgument((builder.component == null) == (builder.mainComponent == null), + "None or both component and main component must be non null"); + this.component = builder.component; + this.mainComponent = builder.mainComponent; this.submitterUuid = emptyToNull(builder.submitterUuid); if (builder.characteristics == null) { this.characteristics = emptyMap(); @@ -70,19 +73,12 @@ public class CeTask { return type; } - @CheckForNull - public String getComponentUuid() { - return componentUuid; - } - - @CheckForNull - public String getComponentKey() { - return componentKey; + public Optional<Component> getComponent() { + return Optional.ofNullable(component); } - @CheckForNull - public String getComponentName() { - return componentName; + public Optional<Component> getMainComponent() { + return Optional.ofNullable(mainComponent); } @CheckForNull @@ -100,9 +96,8 @@ public class CeTask { .add("organizationUuid", organizationUuid) .add("type", type) .add("uuid", uuid) - .add("componentUuid", componentUuid) - .add("componentKey", componentKey) - .add("componentName", componentName) + .add("component", component) + .add("mainComponent", mainComponent) .add("submitterUuid", submitterUuid) .toString(); } @@ -128,9 +123,8 @@ public class CeTask { private String organizationUuid; private String uuid; private String type; - private String componentUuid; - private String componentKey; - private String componentName; + private Component component; + private Component mainComponent; private String submitterUuid; private Map<String, String> characteristics; @@ -154,18 +148,13 @@ public class CeTask { return this; } - public Builder setComponentUuid(@Nullable String componentUuid) { - this.componentUuid = componentUuid; - return this; - } - - public Builder setComponentKey(@Nullable String s) { - this.componentKey = s; + public Builder setComponent(@Nullable Component component) { + this.component = component; return this; } - public Builder setComponentName(@Nullable String s) { - this.componentName = s; + public Builder setMainComponent(@Nullable Component mainComponent) { + this.mainComponent = mainComponent; return this; } @@ -183,4 +172,58 @@ public class CeTask { return new CeTask(this); } } + + public static final class Component { + private final String uuid; + @CheckForNull + private final String key; + @CheckForNull + private final String name; + + public Component(String uuid, @Nullable String key, @Nullable String name) { + this.uuid = requireNonNull(emptyToNull(uuid), "uuid can't be null nor empty"); + this.key = emptyToNull(key); + this.name = emptyToNull(name); + } + + public String getUuid() { + return uuid; + } + + public Optional<String> getKey() { + return Optional.ofNullable(key); + } + + public Optional<String> getName() { + return Optional.ofNullable(name); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Component component = (Component) o; + return Objects.equals(uuid, component.uuid) && + Objects.equals(key, component.key) && + Objects.equals(name, component.name); + } + + @Override + public int hashCode() { + return Objects.hash(uuid, key, name); + } + + @Override + public String toString() { + return "Component{" + + "uuid='" + uuid + '\'' + + ", key='" + key + '\'' + + ", name='" + name + '\'' + + '}'; + } + } } diff --git a/server/sonar-ce-task/src/test/java/org/sonar/ce/task/CeTaskComponentTest.java b/server/sonar-ce-task/src/test/java/org/sonar/ce/task/CeTaskComponentTest.java new file mode 100644 index 00000000000..556b9f76cc2 --- /dev/null +++ b/server/sonar-ce-task/src/test/java/org/sonar/ce/task/CeTaskComponentTest.java @@ -0,0 +1,105 @@ +/* + * 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.ce.task; + +import com.tngtech.java.junit.dataprovider.DataProvider; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; + +import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(DataProviderRunner.class) +public class CeTaskComponentTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + @UseDataProvider("nullOrEmpty") + public void constructor_fails_with_NPE_if_uuid_is_null_or_empty(String str) { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("uuid can't be null nor empty"); + + new CeTask.Component(str, "foo", "bar"); + } + + @Test + @UseDataProvider("nullOrEmpty") + public void constructor_considers_empty_as_null_and_accept_it_for_key(String str) { + CeTask.Component underTest = new CeTask.Component("foo", str, "bar"); + + assertThat(underTest.getKey()).isEmpty(); + } + + @Test + @UseDataProvider("nullOrEmpty") + public void constructor_considers_empty_as_null_and_accept_it_for_name(String str) { + CeTask.Component underTest = new CeTask.Component("foo", "bar", str); + + assertThat(underTest.getName()).isEmpty(); + } + + @Test + public void equals_is_based_on_all_fields() { + String uuid = randomAlphabetic(2); + String key = randomAlphabetic(3); + String name = randomAlphabetic(4); + String somethingElse = randomAlphabetic(5); + CeTask.Component underTest = new CeTask.Component(uuid, key, name); + + assertThat(underTest).isEqualTo(underTest); + assertThat(underTest).isEqualTo(new CeTask.Component(uuid, key, name)); + assertThat(underTest).isNotEqualTo(null); + assertThat(underTest).isNotEqualTo(new Object()); + assertThat(underTest).isNotEqualTo(new CeTask.Component(somethingElse, key, name)); + assertThat(underTest).isNotEqualTo(new CeTask.Component(uuid, somethingElse, name)); + assertThat(underTest).isNotEqualTo(new CeTask.Component(uuid, key, somethingElse)); + assertThat(underTest).isNotEqualTo(new CeTask.Component(uuid, key, null)); + } + + @Test + public void hashcode_is_based_on_all_fields() { + String uuid = randomAlphabetic(2); + String key = randomAlphabetic(3); + String name = randomAlphabetic(4); + String somethingElse = randomAlphabetic(5); + CeTask.Component underTest = new CeTask.Component(uuid, key, name); + + assertThat(underTest.hashCode()).isEqualTo(underTest.hashCode()); + assertThat(underTest.hashCode()).isEqualTo(new CeTask.Component(uuid, key, name).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new Object().hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new CeTask.Component(somethingElse, key, name).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new CeTask.Component(uuid, somethingElse, name).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new CeTask.Component(uuid, key, somethingElse).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new CeTask.Component(uuid, key, null).hashCode()); + } + + @DataProvider + public static Object[][] nullOrEmpty() { + return new Object[][] { + {null}, + {""}, + }; + } +} diff --git a/server/sonar-ce-task/src/test/java/org/sonar/ce/task/CeTaskTest.java b/server/sonar-ce-task/src/test/java/org/sonar/ce/task/CeTaskTest.java index dbb26c47ca3..a72e0b39b59 100644 --- a/server/sonar-ce-task/src/test/java/org/sonar/ce/task/CeTaskTest.java +++ b/server/sonar-ce-task/src/test/java/org/sonar/ce/task/CeTaskTest.java @@ -20,13 +20,18 @@ package org.sonar.ce.task; import com.google.common.collect.ImmutableMap; +import com.tngtech.java.junit.dataprovider.DataProvider; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; +@RunWith(DataProviderRunner.class) public class CeTaskTest { @Rule public ExpectedException expectedException = ExpectedException.none(); @@ -92,14 +97,39 @@ public class CeTaskTest { } @Test + @UseDataProvider("oneAndOnlyOneOfComponentAndMainComponent") + public void build_fails_with_IAE_if_only_one_of_component_and_main_component_is_non_null(CeTask.Component component, CeTask.Component mainComponent) { + underTest.setOrganizationUuid("org1"); + underTest.setType("TYPE_1"); + underTest.setUuid("UUID_1"); + underTest.setComponent(component); + underTest.setMainComponent(mainComponent); + + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("None or both component and main component must be non null"); + + underTest.build(); + } + + @DataProvider + public static Object[][] oneAndOnlyOneOfComponentAndMainComponent() { + CeTask.Component component = new CeTask.Component("COMPONENT_UUID_1", "COMPONENT_KEY_1", "The component"); + return new Object[][] { + {component, null}, + {null, component} + }; + } + + @Test public void verify_getters() { + CeTask.Component component = new CeTask.Component("COMPONENT_UUID_1", "COMPONENT_KEY_1", "The component"); + CeTask.Component mainComponent = new CeTask.Component("MAIN_COMPONENT_UUID_1", "MAIN_COMPONENT_KEY_1", "The main component"); underTest.setOrganizationUuid("org1"); underTest.setType("TYPE_1"); underTest.setUuid("UUID_1"); underTest.setSubmitterUuid("LOGIN_1"); - underTest.setComponentKey("COMPONENT_KEY_1"); - underTest.setComponentUuid("COMPONENT_UUID_1"); - underTest.setComponentName("The component"); + underTest.setComponent(component); + underTest.setMainComponent(mainComponent); underTest.setCharacteristics(ImmutableMap.of("k1", "v1", "k2", "v2")); CeTask task = underTest.build(); @@ -108,26 +138,12 @@ public class CeTaskTest { assertThat(task.getUuid()).isEqualTo("UUID_1"); assertThat(task.getType()).isEqualTo("TYPE_1"); assertThat(task.getSubmitterUuid()).isEqualTo("LOGIN_1"); - assertThat(task.getComponentKey()).isEqualTo("COMPONENT_KEY_1"); - assertThat(task.getComponentUuid()).isEqualTo("COMPONENT_UUID_1"); - assertThat(task.getComponentName()).isEqualTo("The component"); + assertThat(task.getComponent()).contains(component); + assertThat(task.getMainComponent()).contains(mainComponent); assertThat(task.getCharacteristics()).containsExactly(entry("k1", "v1"), entry("k2", "v2")); } @Test - public void empty_in_component_properties_is_considered_as_null() { - CeTask ceTask = underTest.setOrganizationUuid("org1").setUuid("uuid").setType("type") - .setComponentKey("") - .setComponentName("") - .setComponentUuid("") - .build(); - - assertThat(ceTask.getComponentKey()).isNull(); - assertThat(ceTask.getComponentName()).isNull(); - assertThat(ceTask.getComponentUuid()).isNull(); - } - - @Test public void empty_in_submitterLogin_is_considered_as_null() { CeTask ceTask = underTest.setOrganizationUuid("org1").setUuid("uuid").setType("type") .setSubmitterUuid("") |