From: Julien Lancelot Date: Wed, 27 May 2015 07:44:56 +0000 (+0200) Subject: SONAR-6589 Support both pre-order and post-order in typeAwareVisitor X-Git-Tag: 5.2-RC1~1829 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=154617a5034da3f35da19d415bc02939f395d25d;p=sonarqube.git SONAR-6589 Support both pre-order and post-order in typeAwareVisitor --- 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 deleted file mode 100644 index 70e0d37a607..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitor.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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/DepthTraversalTypeAwareVisitor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/DepthTraversalTypeAwareVisitor.java new file mode 100644 index 00000000000..c368b15bccc --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/DepthTraversalTypeAwareVisitor.java @@ -0,0 +1,111 @@ +/* + * 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 static java.util.Objects.requireNonNull; + +/** + * Implementation of {@link TypeAwareVisitor} that implements a depth traversal of a {@link Component} tree. + *

It supports visiting traversal in either pre-order or post-order

+ * It supports a max depth for crawling (component strictly deeper than the specified type will be ignored). + */ +public abstract class DepthTraversalTypeAwareVisitor implements TypeAwareVisitor { + private final Component.Type maxDepth; + private final Order order; + + protected DepthTraversalTypeAwareVisitor(Component.Type maxDepth, Order order) { + this.maxDepth = requireNonNull(maxDepth); + this.order = requireNonNull(order); + } + + @Override + public void visit(Component component) { + if (component.getType().isDeeperThan(maxDepth)) { + return; + } + + if (order == Order.PRE_ORDER) { + visitNode(component); + } + + visitChildren(component); + + if (order == Order.POST_ORDER) { + visitNode(component); + } + } + + private void visitNode(Component component) { + 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); + } + } + + private void visitChildren(Component component) { + if (component.getType() != maxDepth) { + for (Component child : component.getChildren()) { + visit(child); + } + } + } + + @Override + public void visitProject(Component project) { + // empty implementation, meant to be override at will by subclasses + } + + @Override + public void visitModule(Component module) { + // empty implementation, meant to be override at will by subclasses + } + + @Override + public void visitDirectory(Component directory) { + // empty implementation, meant to be override at will by subclasses + } + + @Override + public void visitFile(Component file) { + // empty implementation, meant to be override at will by subclasses + } + + @Override + public void visitUnknown(Component unknownComponent) { + // empty implementation, meant to be override at will by subclasses + } + + public enum Order { + PRE_ORDER, POST_ORDER + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityProfileEventsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityProfileEventsStep.java index 4bb1e5f019e..3846599a0f2 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityProfileEventsStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityProfileEventsStep.java @@ -21,9 +21,6 @@ package org.sonar.server.computation.step; import com.google.common.base.Optional; import com.google.common.collect.ImmutableSortedMap; -import java.util.Date; -import java.util.Map; -import javax.annotation.Nullable; import org.apache.commons.lang.time.DateUtils; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.resources.Language; @@ -32,17 +29,24 @@ import org.sonar.batch.protocol.output.BatchReport; import org.sonar.core.UtcDateUtils; import org.sonar.core.measure.db.MeasureDto; import org.sonar.server.computation.ComputationContext; -import org.sonar.server.computation.component.ChildFirstTypeAwareVisitor; import org.sonar.server.computation.component.Component; +import org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor; import org.sonar.server.computation.event.Event; -import org.sonar.server.computation.qualityprofile.QualityProfile; import org.sonar.server.computation.qualityprofile.QPMeasureData; +import org.sonar.server.computation.qualityprofile.QualityProfile; + +import javax.annotation.Nullable; + +import java.util.Date; +import java.util.Map; + +import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.POST_ORDER; public class QualityProfileEventsStep implements ComputationStep { @Override public void execute(ComputationContext context) { - new ChildFirstTypeAwareVisitor(Component.Type.PROJECT) { + new DepthTraversalTypeAwareVisitor(Component.Type.PROJECT, POST_ORDER) { @Override public void visitProject(Component tree) { executeForProject(tree); 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 deleted file mode 100644 index 6f763397ad6..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitorTest.java +++ /dev/null @@ -1,265 +0,0 @@ -/* - * 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 org.mockito.InOrder; - -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 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 DumbComponent(type, ref, children); - } - -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/component/PostOrderDepthTraversalTypeAwareVisitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/component/PostOrderDepthTraversalTypeAwareVisitorTest.java new file mode 100644 index 00000000000..50bd7394ea7 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/component/PostOrderDepthTraversalTypeAwareVisitorTest.java @@ -0,0 +1,266 @@ +/* + * 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 org.mockito.InOrder; + +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; +import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.POST_ORDER; + +public class PostOrderDepthTraversalTypeAwareVisitorTest { + + 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 DepthTraversalTypeAwareVisitor spyProjectVisitor = spy(new DepthTraversalTypeAwareVisitor(PROJECT, POST_ORDER) {}); + private final DepthTraversalTypeAwareVisitor spyModuleVisitor = spy(new DepthTraversalTypeAwareVisitor(MODULE, POST_ORDER) {}); + private final DepthTraversalTypeAwareVisitor spyDirectoryVisitor = spy(new DepthTraversalTypeAwareVisitor(DIRECTORY, POST_ORDER) {}); + private final DepthTraversalTypeAwareVisitor spyFileVisitor = spy(new DepthTraversalTypeAwareVisitor(FILE, POST_ORDER) {}); + private final InOrder inOrder = inOrder(spyProjectVisitor, spyModuleVisitor, spyDirectoryVisitor, spyFileVisitor); + + @Test(expected = NullPointerException.class) + public void non_null_max_depth_fast_fail() { + new DepthTraversalTypeAwareVisitor(null, POST_ORDER) {}; + } + + @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 DumbComponent(type, ref, null, null, children); + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/component/PreOrderDepthTraversalTypeAwareVisitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/component/PreOrderDepthTraversalTypeAwareVisitorTest.java new file mode 100644 index 00000000000..fffa395d5eb --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/component/PreOrderDepthTraversalTypeAwareVisitorTest.java @@ -0,0 +1,266 @@ +/* + * 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 org.mockito.InOrder; + +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; +import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.PRE_ORDER; + +public class PreOrderDepthTraversalTypeAwareVisitorTest { + + 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 DepthTraversalTypeAwareVisitor spyProjectVisitor = spy(new DepthTraversalTypeAwareVisitor(PROJECT, PRE_ORDER) {}); + private final DepthTraversalTypeAwareVisitor spyModuleVisitor = spy(new DepthTraversalTypeAwareVisitor(MODULE, PRE_ORDER) {}); + private final DepthTraversalTypeAwareVisitor spyDirectoryVisitor = spy(new DepthTraversalTypeAwareVisitor(DIRECTORY, PRE_ORDER) {}); + private final DepthTraversalTypeAwareVisitor spyFileVisitor = spy(new DepthTraversalTypeAwareVisitor(FILE, PRE_ORDER) {}); + private final InOrder inOrder = inOrder(spyProjectVisitor, spyModuleVisitor, spyDirectoryVisitor, spyFileVisitor); + + @Test(expected = NullPointerException.class) + public void non_null_max_depth_fast_fail() { + new DepthTraversalTypeAwareVisitor(null, PRE_ORDER) {}; + } + + @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).visitProject(COMPONENT_TREE); + inOrder.verify(spyFileVisitor).visit(MODULE_2); + inOrder.verify(spyFileVisitor).visitModule(MODULE_2); + inOrder.verify(spyFileVisitor).visit(DIRECTORY_3); + inOrder.verify(spyFileVisitor).visitDirectory(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.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).visitProject(COMPONENT_TREE); + inOrder.verify(spyDirectoryVisitor).visit(MODULE_2); + inOrder.verify(spyDirectoryVisitor).visitModule(MODULE_2); + inOrder.verify(spyDirectoryVisitor).visit(DIRECTORY_3); + inOrder.verify(spyDirectoryVisitor).visitDirectory(DIRECTORY_3); + 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).visitProject(COMPONENT_TREE); + inOrder.verify(spyModuleVisitor).visit(MODULE_2); + inOrder.verify(spyModuleVisitor).visitModule(MODULE_2); + 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 DumbComponent(type, ref, null, null, children); + } + +}