From 2b93b6e78216b2c7c5f8c1b44bdffdd0714aaaa7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=A9bastien=20Lesaint?= Date: Fri, 22 May 2015 09:34:57 +0200 Subject: [PATCH] SONAR-6568 add CE specific component "API" --- .../component/ChildFirstTypeAwareVisitor.java | 91 ++++++ .../computation/component/Component.java | 65 ++++ .../computation/component/ComponentImpl.java | 142 ++++++++ .../component/ComponentVisitor.java | 24 ++ .../component/TypeAwareVisitor.java | 35 ++ .../computation/component/package-info.java | 24 ++ .../context/ComputationContext.java | 31 ++ .../computation/context/package-info.java | 24 ++ .../sonar/server/computation/event/Event.java | 92 ++++++ .../computation/event/EventRepository.java | 26 ++ .../computation/event/package-info.java | 24 ++ .../measure/MeasureRepository.java | 34 ++ .../ChildFirstTypeAwareVisitorTest.java | 304 ++++++++++++++++++ .../computation/component/ComponentTest.java | 54 ++++ .../server/computation/event/EventTest.java | 60 ++++ 15 files changed, 1030 insertions(+) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitor.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/component/Component.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentImpl.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentVisitor.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/component/TypeAwareVisitor.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/component/package-info.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/context/ComputationContext.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/context/package-info.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/event/Event.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/event/EventRepository.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/event/package-info.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepository.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitorTest.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/component/ComponentTest.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/event/EventTest.java diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitor.java new file mode 100644 index 00000000000..70e0d37a607 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitor.java @@ -0,0 +1,91 @@ +/* + * 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. + */ +package org.sonar.server.computation.component; + +import java.util.Objects; + +/** + * Implementation of {@link TypeAwareVisitor} that implements a depth first crawling of the + * {@link ComponentImpl} tree. It supports a max depth for crawling (component strictly deeper than the specified + * type will be ignored). + */ +public abstract class ChildFirstTypeAwareVisitor implements TypeAwareVisitor { + private final Component.Type maxDepth; + + protected ChildFirstTypeAwareVisitor(Component.Type maxDepth) { + this.maxDepth = Objects.requireNonNull(maxDepth); + } + + @Override + public void visit(Component component) { + if (component.getType().isDeeperThan(maxDepth)) { + return; + } + + if (component.getType() != maxDepth) { + for (Component child : component.getChildren()) { + visit(child); + } + } + + switch (component.getType()) { + case PROJECT: + visitProject(component); + break; + case MODULE: + visitModule(component); + break; + case DIRECTORY: + visitDirectory(component); + break; + case FILE: + visitFile(component); + break; + default: + visitUnknown(component); + } + } + + @Override + public void visitProject(Component tree) { + // empty implementation, meant to be override at will by subclasses + } + + @Override + public void visitModule(Component tree) { + // empty implementation, meant to be override at will by subclasses + } + + @Override + public void visitDirectory(Component tree) { + // empty implementation, meant to be override at will by subclasses + } + + @Override + public void visitFile(Component tree) { + // empty implementation, meant to be override at will by subclasses + } + + @Override + public void visitUnknown(Component tree) { + // empty implementation, meant to be override at will by subclasses + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/component/Component.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/Component.java new file mode 100644 index 00000000000..b1014dcb54b --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/Component.java @@ -0,0 +1,65 @@ +/* + * 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. + */ +package org.sonar.server.computation.component; + +import java.util.List; +import org.sonar.server.computation.context.ComputationContext; +import org.sonar.server.computation.event.EventRepository; +import org.sonar.server.computation.measure.MeasureRepository; + +public interface Component { + enum Type { + PROJECT(0), MODULE(1), DIRECTORY(2), FILE(3); + + private final int depth; + + Type(int depth) { + this.depth = depth; + } + + public int getDepth() { + return depth; + } + + public boolean isDeeperThan(Type otherType) { + return this.getDepth() > otherType.getDepth(); + } + } + + ComputationContext getContext(); + + Type getType(); + + // FIXME we should not expose a batch specific information + int getRef(); + + List getChildren(); + + /** + * The event repository for the current component + */ + EventRepository getEventRepository(); + + /** + * the measure repository for the current component + */ + MeasureRepository getMeasureRepository(); + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentImpl.java new file mode 100644 index 00000000000..b9a66977021 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentImpl.java @@ -0,0 +1,142 @@ +/* + * 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. + */ +package org.sonar.server.computation.component; + +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.sonar.api.measures.Metric; +import org.sonar.batch.protocol.Constants; +import org.sonar.batch.protocol.output.BatchReport; +import org.sonar.core.measure.db.MeasureDto; +import org.sonar.core.persistence.DbSession; +import org.sonar.server.computation.ComputationContext; +import org.sonar.server.computation.event.Event; +import org.sonar.server.computation.event.EventRepository; +import org.sonar.server.computation.measure.MeasureRepository; +import org.sonar.server.db.DbClient; + +import static com.google.common.base.Predicates.notNull; +import static com.google.common.collect.ImmutableList.copyOf; +import static com.google.common.collect.Iterables.filter; +import static java.util.Objects.requireNonNull; + +public class ComponentImpl implements Component { + private final ComputationContext context; + private final Type type; + private final BatchReport.Component component; + private final List children; + private final EventRepository eventRepository = new SetEventRepository(); + + public ComponentImpl(ComputationContext context, BatchReport.Component component, @Nullable Iterable children) { + this.context = context; + this.component = component; + this.type = convertType(component.getType()); + this.children = children == null ? Collections.emptyList() : copyOf(filter(children, notNull())); + } + + private static Type convertType(Constants.ComponentType type) { + switch (type) { + case PROJECT: + return Type.PROJECT; + case MODULE: + return Type.MODULE; + case DIRECTORY: + return Type.DIRECTORY; + case FILE: + return Type.FILE; + default: + throw new IllegalArgumentException("Unsupported Constants.ComponentType value " + type); + } + } + + @Override + public Type getType() { + return type; + } + + @Override + public int getRef() { + return component.getRef(); + } + + @Override + public List getChildren() { + return children; + } + + @Override + public org.sonar.server.computation.context.ComputationContext getContext() { + return context; + } + + @Override + public EventRepository getEventRepository() { + return eventRepository; + } + + @Override + public MeasureRepository getMeasureRepository() { + return new MeasureRepository() { + @Override + public Optional findPrevious(Metric metric) { + DbClient dbClient = context.getDbClient(); + try (DbSession dbSession = dbClient.openSession(false)) { + return Optional.fromNullable( + dbClient.measureDao().findByComponentKeyAndMetricKey(dbSession, component.getKey(), metric.getKey()) + ); + } + } + + @Override + public Optional findCurrent(final Metric metric) { + return Optional.fromNullable(Iterables.find( + context.getReportReader().readComponentMeasures(component.getRef()), + new Predicate() { + @Override + public boolean apply(@Nonnull BatchReport.Measure input) { + return input.getMetricKey().equals(metric.getKey()); + } + } + )); + } + }; + } + + private static class SetEventRepository implements EventRepository { + private final Set events = new HashSet<>(); + + @Override + public void add(Event event) { + events.add(requireNonNull(event)); + } + + @Override + public Iterable getEvents() { + return events; + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentVisitor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentVisitor.java new file mode 100644 index 00000000000..98e02828f48 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentVisitor.java @@ -0,0 +1,24 @@ +/* + * 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. + */ +package org.sonar.server.computation.component; + +public interface ComponentVisitor { + void visit(Component tree); +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/component/TypeAwareVisitor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/TypeAwareVisitor.java new file mode 100644 index 00000000000..9e59e178935 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/TypeAwareVisitor.java @@ -0,0 +1,35 @@ +/* + * 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. + */ +package org.sonar.server.computation.component; + +/** + * A {@link ComponentVisitor} which can exposes methods which ensure the type of the visited Component. + */ +public interface TypeAwareVisitor extends ComponentVisitor { + void visitProject(Component tree); + + void visitModule(Component tree); + + void visitDirectory(Component tree); + + void visitFile(Component tree); + + void visitUnknown(Component tree); +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/component/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/package-info.java new file mode 100644 index 00000000000..4e4e221e7b3 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/package-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +@ParametersAreNonnullByDefault +package org.sonar.server.computation.component; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/context/ComputationContext.java b/server/sonar-server/src/main/java/org/sonar/server/computation/context/ComputationContext.java new file mode 100644 index 00000000000..171639acbc4 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/context/ComputationContext.java @@ -0,0 +1,31 @@ +/* + * 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. + */ +package org.sonar.server.computation.context; + +import org.sonar.server.computation.component.Component; +import org.sonar.server.computation.language.LanguageRepository; + +public interface ComputationContext { + + Component getRoot(); + + LanguageRepository getLanguageRepository(); + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/context/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/context/package-info.java new file mode 100644 index 00000000000..d15e656106a --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/context/package-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +@ParametersAreNonnullByDefault +package org.sonar.server.computation.context; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/event/Event.java b/server/sonar-server/src/main/java/org/sonar/server/computation/event/Event.java new file mode 100644 index 00000000000..260be3c0474 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/event/Event.java @@ -0,0 +1,92 @@ +/* + * 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. + */ +package org.sonar.server.computation.event; + +import java.util.Objects; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +import static java.util.Objects.requireNonNull; + + +@Immutable +public class Event { + private final String name; + private final Category category; + @Nullable + private final String data; + @Nullable + private final String description; + + private Event(String name, Category category, @Nullable String data, @Nullable String description) { + this.name = requireNonNull(name); + this.category = requireNonNull(category); + this.data = data; + this.description = description; + } + + public static Event createAlert(String name, @Nullable String data, @Nullable String description) { + return new Event(name, Category.ALERT, data, description); + } + + public static Event createProfile(String name, @Nullable String data, @Nullable String description) { + return new Event(name, Category.PROFILE, data, description); + } + + public String getName() { + return name; + } + + public Category getCategory() { + return category; + } + + public String getData() { + return data; + } + + @Nullable + public String getDescription() { + return description; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Event event = (Event) o; + return Objects.equals(name, event.name) && + Objects.equals(category, event.category); + } + + @Override + public int hashCode() { + return Objects.hash(name, category); + } + + public enum Category { + ALERT, PROFILE + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/event/EventRepository.java b/server/sonar-server/src/main/java/org/sonar/server/computation/event/EventRepository.java new file mode 100644 index 00000000000..1e55c0c18ad --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/event/EventRepository.java @@ -0,0 +1,26 @@ +/* + * 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. + */ +package org.sonar.server.computation.event; + +public interface EventRepository { + void add(Event event); + + Iterable getEvents(); +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/event/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/event/package-info.java new file mode 100644 index 00000000000..4a57b598b24 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/event/package-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +@ParametersAreNonnullByDefault +package org.sonar.server.computation.event; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepository.java b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepository.java new file mode 100644 index 00000000000..38c4e77dfd9 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepository.java @@ -0,0 +1,34 @@ +/* + * 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. + */ +package org.sonar.server.computation.measure; + +import org.sonar.api.measures.Metric; +import org.sonar.batch.protocol.output.BatchReport; + +import com.google.common.base.Optional; +import org.sonar.core.measure.db.MeasureDto; + +public interface MeasureRepository { + // FIXME should not expose MeasureDto from DAO layer + Optional findPrevious(Metric metric); + + // FIXME should not expose Measure from BatchReport + Optional findCurrent(Metric metric); +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitorTest.java new file mode 100644 index 00000000000..d3b66354cf9 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitorTest.java @@ -0,0 +1,304 @@ +/* + * 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. + */ +package org.sonar.server.computation.component; + +import com.google.common.collect.ImmutableList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.Test; +import org.mockito.InOrder; +import org.sonar.server.computation.context.ComputationContext; +import org.sonar.server.computation.event.EventRepository; +import org.sonar.server.computation.measure.MeasureRepository; + +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.spy; +import static org.sonar.server.computation.component.Component.Type.DIRECTORY; +import static org.sonar.server.computation.component.Component.Type.FILE; +import static org.sonar.server.computation.component.Component.Type.MODULE; +import static org.sonar.server.computation.component.Component.Type.PROJECT; + +public class ChildFirstTypeAwareVisitorTest { + + private static final String UNSUPPORTED_OPERATION_ERROR = "This node has no repository nor context"; + + private static final Component FILE_4 = component(FILE, 4); + private static final Component FILE_5 = component(FILE, 5); + private static final Component DIRECTORY_3 = component(DIRECTORY, 3, FILE_4, FILE_5); + private static final Component MODULE_2 = component(MODULE, 2, DIRECTORY_3); + private static final Component COMPONENT_TREE = component(PROJECT, 1, MODULE_2); + + private final ChildFirstTypeAwareVisitor spyProjectVisitor = spy(new ChildFirstTypeAwareVisitor(PROJECT) {}); + private final ChildFirstTypeAwareVisitor spyModuleVisitor = spy(new ChildFirstTypeAwareVisitor(MODULE) {}); + private final ChildFirstTypeAwareVisitor spyDirectoryVisitor = spy(new ChildFirstTypeAwareVisitor(DIRECTORY) {}); + private final ChildFirstTypeAwareVisitor spyFileVisitor = spy(new ChildFirstTypeAwareVisitor(FILE) {}); + private final InOrder inOrder = inOrder(spyProjectVisitor, spyModuleVisitor, spyDirectoryVisitor, spyFileVisitor); + + @Test(expected = NullPointerException.class) + public void non_null_max_depth_fast_fail() { + new ChildFirstTypeAwareVisitor(null) { + }; + } + + @Test(expected = NullPointerException.class) + public void visit_null_Component_throws_NPE() { + spyFileVisitor.visit(null); + } + + @Test + public void visit_file_with_depth_FILE_calls_visit_file() { + Component component = component(FILE, 1); + spyFileVisitor.visit(component); + + inOrder.verify(spyFileVisitor).visit(component); + inOrder.verify(spyFileVisitor).visitFile(component); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void visit_module_with_depth_FILE_calls_visit_module() { + Component component = component(MODULE, 1); + spyFileVisitor.visit(component); + + inOrder.verify(spyFileVisitor).visit(component); + inOrder.verify(spyFileVisitor).visitModule(component); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void visit_directory_with_depth_FILE_calls_visit_directory() { + Component component = component(DIRECTORY, 1); + spyFileVisitor.visit(component); + + inOrder.verify(spyFileVisitor).visit(component); + inOrder.verify(spyFileVisitor).visitDirectory(component); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void visit_project_with_depth_FILE_calls_visit_project() { + Component component = component(PROJECT, 1); + spyFileVisitor.visit(component); + + inOrder.verify(spyFileVisitor).visit(component); + inOrder.verify(spyFileVisitor).visitProject(component); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void visit_file_with_depth_DIRECTORY_does_not_call_visit_file() { + Component component = component(FILE, 1); + spyDirectoryVisitor.visit(component); + + inOrder.verify(spyDirectoryVisitor).visit(component); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void visit_directory_with_depth_DIRECTORY_calls_visit_directory() { + Component component = component(DIRECTORY, 1); + spyDirectoryVisitor.visit(component); + + inOrder.verify(spyDirectoryVisitor).visit(component); + inOrder.verify(spyDirectoryVisitor).visitDirectory(component); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void visit_module_with_depth_DIRECTORY_calls_visit_module() { + Component component = component(MODULE, 1); + spyDirectoryVisitor.visit(component); + + inOrder.verify(spyDirectoryVisitor).visit(component); + inOrder.verify(spyDirectoryVisitor).visitModule(component); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void visit_project_with_depth_DIRECTORY_calls_visit_project() { + Component component = component(PROJECT, 1); + spyDirectoryVisitor.visit(component); + + inOrder.verify(spyDirectoryVisitor).visit(component); + inOrder.verify(spyDirectoryVisitor).visitProject(component); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void visit_file_with_depth_MODULE_does_not_call_visit_file() { + Component component = component(FILE, 1); + spyModuleVisitor.visit(component); + + inOrder.verify(spyModuleVisitor).visit(component); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void visit_directory_with_depth_MODULE_does_not_call_visit_directory() { + Component component = component(DIRECTORY, 1); + spyModuleVisitor.visit(component); + + inOrder.verify(spyModuleVisitor).visit(component); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void visit_module_with_depth_MODULE_calls_visit_module() { + Component component = component(MODULE, 1); + spyModuleVisitor.visit(component); + + inOrder.verify(spyModuleVisitor).visit(component); + inOrder.verify(spyModuleVisitor).visitModule(component); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void visit_project_with_depth_MODULE_calls_visit_project() { + Component component = component(MODULE, 1); + spyModuleVisitor.visit(component); + + inOrder.verify(spyModuleVisitor).visit(component); + inOrder.verify(spyModuleVisitor).visitModule(component); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void visit_file_with_depth_PROJECT_does_not_call_visit_file() { + Component component = component(FILE, 1); + spyProjectVisitor.visit(component); + + inOrder.verify(spyProjectVisitor).visit(component); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void visit_directory_with_depth_PROJECT_does_not_call_visit_directory() { + Component component = component(DIRECTORY, 1); + spyProjectVisitor.visit(component); + + inOrder.verify(spyProjectVisitor).visit(component); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void visit_module_with_depth_PROJECT_does_not_call_visit_module() { + Component component = component(MODULE, 1); + spyProjectVisitor.visit(component); + + inOrder.verify(spyProjectVisitor).visit(component); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void visit_project_with_depth_PROJECT_calls_visit_project() { + Component component = component(PROJECT, 1); + spyProjectVisitor.visit(component); + + inOrder.verify(spyProjectVisitor).visit(component); + inOrder.verify(spyProjectVisitor).visitProject(component); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void verify_visit_call_when_visit_tree_with_depth_FILE() { + spyFileVisitor.visit(COMPONENT_TREE); + + inOrder.verify(spyFileVisitor).visit(COMPONENT_TREE); + inOrder.verify(spyFileVisitor).visit(MODULE_2); + inOrder.verify(spyFileVisitor).visit(DIRECTORY_3); + inOrder.verify(spyFileVisitor).visit(FILE_4); + inOrder.verify(spyFileVisitor).visitFile(FILE_4); + inOrder.verify(spyFileVisitor).visit(FILE_5); + inOrder.verify(spyFileVisitor).visitFile(FILE_5); + inOrder.verify(spyFileVisitor).visitDirectory(DIRECTORY_3); + inOrder.verify(spyFileVisitor).visitModule(MODULE_2); + inOrder.verify(spyFileVisitor).visitProject(COMPONENT_TREE); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void verify_visit_call_when_visit_tree_with_depth_DIRECTORY() { + spyDirectoryVisitor.visit(COMPONENT_TREE); + + inOrder.verify(spyDirectoryVisitor).visit(COMPONENT_TREE); + inOrder.verify(spyDirectoryVisitor).visit(MODULE_2); + inOrder.verify(spyDirectoryVisitor).visit(DIRECTORY_3); + inOrder.verify(spyDirectoryVisitor).visitDirectory(DIRECTORY_3); + inOrder.verify(spyDirectoryVisitor).visitModule(MODULE_2); + inOrder.verify(spyDirectoryVisitor).visitProject(COMPONENT_TREE); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void verify_visit_call_when_visit_tree_with_depth_MODULE() { + spyModuleVisitor.visit(COMPONENT_TREE); + + inOrder.verify(spyModuleVisitor).visit(COMPONENT_TREE); + inOrder.verify(spyModuleVisitor).visit(MODULE_2); + inOrder.verify(spyModuleVisitor).visitModule(MODULE_2); + inOrder.verify(spyModuleVisitor).visitProject(COMPONENT_TREE); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void verify_visit_call_when_visit_tree_with_depth_PROJECT() { + spyProjectVisitor.visit(COMPONENT_TREE); + + inOrder.verify(spyProjectVisitor).visit(COMPONENT_TREE); + inOrder.verify(spyProjectVisitor).visitProject(COMPONENT_TREE); + inOrder.verifyNoMoreInteractions(); + } + + private static Component component(final Component.Type type, final int ref, final Component... children) { + return new Component() { + + @Override + public Type getType() { + return type; + } + + @Override + public int getRef() { + return ref; + } + + @Override + public List getChildren() { + return children == null ? Collections.emptyList() : ImmutableList.copyOf(Arrays.asList(children)); + } + + @Override + public ComputationContext getContext() { + throw new UnsupportedOperationException(UNSUPPORTED_OPERATION_ERROR); + } + + @Override + public EventRepository getEventRepository() { + throw new UnsupportedOperationException(UNSUPPORTED_OPERATION_ERROR); + } + + @Override + public MeasureRepository getMeasureRepository() { + throw new UnsupportedOperationException(UNSUPPORTED_OPERATION_ERROR); + } + }; + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/component/ComponentTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/component/ComponentTest.java new file mode 100644 index 00000000000..c6b0d901f0e --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/component/ComponentTest.java @@ -0,0 +1,54 @@ +/* + * 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. + */ +package org.sonar.server.computation.component; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.server.computation.component.Component.Type.DIRECTORY; +import static org.sonar.server.computation.component.Component.Type.MODULE; +import static org.sonar.server.computation.component.Component.Type.PROJECT; + +public class ComponentTest { + @Test + public void verify_type_is_deeper_than_when_comparing_to_itself() throws Exception { + for (Component.Type type : Component.Type.values()) { + assertThat(type.isDeeperThan(type)).isFalse(); + } + } + + @Test + public void FILE_type_is_deeper_than_all_other_types() throws Exception { + assertThat(Component.Type.FILE.isDeeperThan(DIRECTORY)).isTrue(); + assertThat(Component.Type.FILE.isDeeperThan(MODULE)).isTrue(); + assertThat(Component.Type.FILE.isDeeperThan(PROJECT)).isTrue(); + } + + @Test + public void DIRECTORY_type_is_deeper_than_MODULE_and_PROJECT() throws Exception { + assertThat(Component.Type.DIRECTORY.isDeeperThan(MODULE)).isTrue(); + assertThat(Component.Type.DIRECTORY.isDeeperThan(PROJECT)).isTrue(); + } + + @Test + public void MODULE_type_is_deeper_than_PROJECT() throws Exception { + assertThat(Component.Type.MODULE.isDeeperThan(PROJECT)).isTrue(); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/event/EventTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/event/EventTest.java new file mode 100644 index 00000000000..4726dd2dfed --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/event/EventTest.java @@ -0,0 +1,60 @@ +/* + * 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. + */ +package org.sonar.server.computation.event; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class EventTest { + + private static final String SOME_NAME = "someName"; + private static final String SOME_DATA = "some data"; + private static final String SOME_DESCRIPTION = "some description"; + + @Test(expected = NullPointerException.class) + public void createAlert_fail_fast_null_check_on_null_name() { + Event.createAlert(null, SOME_DATA, SOME_DESCRIPTION); + } + + @Test(expected = NullPointerException.class) + public void createProfile_fail_fast_null_check_on_null_name() { + Event.createProfile(null, SOME_DATA, SOME_DESCRIPTION); + } + + @Test + public void createAlert_verify_fields() { + Event event = Event.createAlert(SOME_NAME, SOME_DATA, SOME_DESCRIPTION); + assertThat(event.getName()).isEqualTo(SOME_NAME); + assertThat(event.getCategory()).isEqualTo(Event.Category.ALERT); + assertThat(event.getData()).isEqualTo(SOME_DATA); + assertThat(event.getDescription()).isEqualTo(SOME_DESCRIPTION); + } + + @Test + public void createProfile_verify_fields() { + Event event = Event.createProfile(SOME_NAME, SOME_DATA, SOME_DESCRIPTION); + assertThat(event.getName()).isEqualTo(SOME_NAME); + assertThat(event.getCategory()).isEqualTo(Event.Category.PROFILE); + assertThat(event.getData()).isEqualTo(SOME_DATA); + assertThat(event.getDescription()).isEqualTo(SOME_DESCRIPTION); + } + +} -- 2.39.5