├── .gitignore ├── CONTRIBUTE.md ├── LICENSE ├── README.md ├── api ├── build.gradle └── src │ └── main │ ├── java │ └── com │ │ └── devexperts │ │ └── switchboard │ │ ├── api │ │ ├── ComponentReference.java │ │ ├── ComponentsRunner.java │ │ ├── Identifiable.java │ │ ├── Integration.java │ │ ├── IntegrationComponent.java │ │ ├── IntegrationContexts.java │ │ ├── IntegrationFeatures.java │ │ ├── TestExtractor.java │ │ ├── TestFilter.java │ │ ├── TestProcessor.java │ │ ├── TestRunConsumer.java │ │ ├── TestRunProcessor.java │ │ └── TestSplitter.java │ │ └── entities │ │ ├── AttributedEntity.java │ │ ├── Attributes.java │ │ ├── Test.java │ │ └── TestRun.java │ └── resources │ └── log4j2.xml ├── build.gradle ├── core ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── devexperts │ │ │ └── switchboard │ │ │ ├── entities │ │ │ ├── Pair.java │ │ │ ├── attributes │ │ │ │ ├── AndAttributeWrapper.java │ │ │ │ ├── AttributeHasSingleValue.java │ │ │ │ ├── AttributeIsPresent.java │ │ │ │ ├── AttributePredicate.java │ │ │ │ ├── AttributeValueKeyIsPresent.java │ │ │ │ ├── AttributeValueMatches.java │ │ │ │ ├── AttributeValueSetContains.java │ │ │ │ ├── NotAttributeWrapper.java │ │ │ │ └── OrAttributeWrapper.java │ │ │ └── valuesupplier │ │ │ │ ├── AttributeKeyValuesExtractor.java │ │ │ │ ├── AttributeValuesExtractor.java │ │ │ │ ├── BlockFormattingValuesExtractor.java │ │ │ │ ├── ConditionalValueExtractor.java │ │ │ │ ├── ConstantValuesExtractor.java │ │ │ │ ├── EnumeratingTestDescriptionFormatter.java │ │ │ │ ├── FormattingValuesExtractor.java │ │ │ │ ├── IdentifierValuesExtractor.java │ │ │ │ ├── TestRunValuesExtractor.java │ │ │ │ ├── TestValuesExtractor.java │ │ │ │ ├── TestsToStringValuesExtractor.java │ │ │ │ └── ValuesExtractor.java │ │ │ ├── impl │ │ │ ├── FeaturelessIntegration.java │ │ │ ├── IntegrationImpl.java │ │ │ ├── VoidIntegrationFeatures.java │ │ │ ├── consumers │ │ │ │ └── LoggingTestRunConsumer.java │ │ │ ├── extractors │ │ │ │ └── FileTestExtractor.java │ │ │ ├── filters │ │ │ │ ├── AttributesFilter.java │ │ │ │ └── DefaultTestFilter.java │ │ │ └── splitters │ │ │ │ ├── AttributeKeySplitter.java │ │ │ │ ├── AttributeSingleValueSplitter.java │ │ │ │ ├── CompositeSplitter.java │ │ │ │ └── TestCountSplitter.java │ │ │ └── utils │ │ │ ├── Arguments.java │ │ │ └── FileUtils.java │ └── resources │ │ └── log4j2.xml │ └── test │ ├── groovy │ └── com │ │ └── devexperts │ │ └── switchboard │ │ ├── entities │ │ ├── attributes │ │ │ ├── AttributePredicateTest.groovy │ │ │ └── TestAttributeTest.groovy │ │ └── valuesupplier │ │ │ ├── ConditionalValueExtractorTest.groovy │ │ │ └── TestDescriptionFormatterTests.groovy │ │ └── impl │ │ └── TestCountSplitterTest.groovy │ └── resources │ ├── log4j2.xml │ ├── sample_test.json │ ├── sample_test_description.txt │ └── sample_test_full.txt ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── integrations ├── build.gradle ├── bytecodeparser │ ├── build.gradle │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── devexperts │ │ │ │ └── switchboard │ │ │ │ └── integrations │ │ │ │ └── bytecodeparser │ │ │ │ ├── BytecodeParserIntegration.java │ │ │ │ ├── BytecodeParserIntegrationFeatures.java │ │ │ │ └── BytecodeTestExtractor.java │ │ └── resources │ │ │ └── log4j2.xml │ │ └── test │ │ ├── groovy │ │ └── com │ │ │ └── devexperts │ │ │ └── switchboard │ │ │ └── integrations │ │ │ └── bytecodeparser │ │ │ └── BytecodeTestExtractorTest.groovy │ │ └── resources │ │ ├── log4j2.xml │ │ └── test_classes │ │ ├── junit.jar │ │ ├── jupiter.jar │ │ └── testng.jar ├── cukes │ ├── build.gradle │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── devexperts │ │ │ │ └── switchboard │ │ │ │ └── integrations │ │ │ │ └── cukes │ │ │ │ ├── CukesIntegration.java │ │ │ │ ├── CukesIntegrationFeatures.java │ │ │ │ ├── CukesTagTestProcessor.java │ │ │ │ └── CukesTestExtractor.java │ │ └── resources │ │ │ └── log4j2.xml │ │ └── test │ │ ├── groovy │ │ └── com │ │ │ └── devexperts │ │ │ └── switchboard │ │ │ └── integrations │ │ │ └── cukes │ │ │ └── CukesTestExtractorTest.groovy │ │ └── resources │ │ ├── log4j2.xml │ │ └── test_classes │ │ ├── Mixed_feature_1.feature │ │ ├── Multi_feature_1.feature │ │ ├── Outline_feature_1.feature │ │ ├── Single_feature_1.feature │ │ └── pckg │ │ ├── Mixed_feature_2.feature │ │ ├── Multi_feature_2.feature │ │ ├── Outline_feature_2.feature │ │ └── Single_feature_2.feature ├── javaparser │ ├── build.gradle │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── devexperts │ │ │ │ └── switchboard │ │ │ │ └── integrations │ │ │ │ └── javaparser │ │ │ │ ├── AnnotationParser.java │ │ │ │ ├── JavaParserIntegration.java │ │ │ │ ├── JavaParserIntegrationFeatures.java │ │ │ │ └── JavaTestExtractor.java │ │ └── resources │ │ │ └── log4j2.xml │ │ └── test │ │ ├── groovy │ │ └── com │ │ │ └── devexperts │ │ │ └── switchboard │ │ │ └── integrations │ │ │ └── javaparser │ │ │ └── JavaTestExtractorTest.groovy │ │ └── resources │ │ ├── log4j2.xml │ │ └── test_classes │ │ ├── Annotations.java │ │ ├── JUnitJiraTests.java │ │ ├── TestCase.java │ │ └── typed │ │ ├── junit │ │ ├── JUnitTests.java │ │ └── pckg │ │ │ ├── JUnitTests1.java │ │ │ └── JUnitTests2.java │ │ ├── jupiter │ │ ├── JupiterTests.java │ │ └── pckg │ │ │ ├── JupiterTests1.java │ │ │ └── JupiterTests2.java │ │ └── testng │ │ ├── TestNgTests.java │ │ └── pckg │ │ ├── TestNgTests1.java │ │ └── TestNgTests2.java ├── jira │ ├── build.gradle │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── devexperts │ │ │ │ └── switchboard │ │ │ │ └── integrations │ │ │ │ └── jira │ │ │ │ ├── HttpClientFactoryProvider.java │ │ │ │ ├── JiraIntegration.java │ │ │ │ ├── JiraIntegrationFeatures.java │ │ │ │ ├── JqlQueryTestFilter.java │ │ │ │ └── XRayGenericTestsCreatingConsumer.java │ │ └── resources │ │ │ └── log4j2.xml │ │ └── test │ │ ├── groovy │ │ └── com │ │ │ └── devexperts │ │ │ └── switchboard │ │ │ └── integrations │ │ │ └── jira │ │ │ └── JiraIntegrationTest.groovy │ │ └── resources │ │ ├── JiraIntegration.json │ │ ├── SampleTests.json │ │ └── log4j2.xml └── teamcity │ ├── build.gradle │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── devexperts │ │ │ └── switchboard │ │ │ └── integrations │ │ │ └── teamcity │ │ │ ├── AgentParamMatchType.java │ │ │ ├── AgentRequirement.java │ │ │ ├── TcBuildTestRunConsumer.java │ │ │ ├── TeamCityIntegration.java │ │ │ ├── TeamCityIntegrationFeatures.java │ │ │ └── swagger │ │ │ └── codegen │ │ │ ├── api │ │ │ ├── AgentApi.java │ │ │ └── BuildQueueApi.java │ │ │ ├── invoker │ │ │ ├── ApiClient.java │ │ │ ├── ApiException.java │ │ │ ├── ApiResponse.java │ │ │ ├── Configuration.java │ │ │ ├── CustomInstantDeserializer.java │ │ │ ├── JSON.java │ │ │ ├── Pair.java │ │ │ ├── RFC3339DateFormat.java │ │ │ ├── StringUtil.java │ │ │ └── auth │ │ │ │ ├── ApiKeyAuth.java │ │ │ │ ├── Authentication.java │ │ │ │ ├── HttpBasicAuth.java │ │ │ │ ├── OAuth.java │ │ │ │ └── OAuthFlow.java │ │ │ └── model │ │ │ ├── Agent.java │ │ │ ├── AgentPool.java │ │ │ ├── Agents.java │ │ │ ├── Build.java │ │ │ ├── Comment.java │ │ │ ├── Properties.java │ │ │ ├── Property.java │ │ │ ├── Tag.java │ │ │ ├── Tags.java │ │ │ └── Type.java │ └── resources │ │ └── log4j2.xml │ └── test │ ├── groovy │ └── com │ │ └── devexperts │ │ └── switchboard │ │ └── integrations │ │ └── teamcity │ │ └── TeamCityIntegrationTest.groovy │ └── resources │ ├── MockAgentsPool.json │ ├── TeamCityIntegration.json │ └── log4j2.xml ├── licenses ├── commons-cli-license.txt ├── cucumber-core-license.txt ├── disruptor-license.txt ├── fugue-license.txt ├── jackson-annotations-license.txt ├── jackson-core-license.txt ├── jackson-databind-license.txt ├── jackson-dataformat-xml-license.txt ├── jackson-datatype-threetenbp-license.txt ├── jakarta.xml.bind-api-license.txt ├── javaparser-core-apache-license.txt ├── jaxb-runtime-license.txt ├── jersey-client-license.txt ├── jersey-client-notice.txt ├── jersey-jersey-hk2-license.txt ├── jersey-jersey-hk2-notice.txt ├── jersey-media-jaxb-license.txt ├── jersey-media-jaxb-notice.txt ├── jersey-media-json-jackson-notice.txt ├── jersey-media-json-license.txt ├── jersey-media-json-notice.txt ├── jersey-media-multipart-license.txt ├── jersey-media-multipart-notice.txt ├── jira-rest-java-client-core-license.txt ├── log4j-slf4j-impl-license.txt ├── migbase-license.txt ├── slf4j-api-license.txt ├── swagger-annotations-license.txt ├── swagger-java-client-license.txt └── xbean-classloader-license.txt ├── runner ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── devexperts │ │ │ └── switchboard │ │ │ └── IntegrationsRunner.java │ └── resources │ │ └── log4j2.xml │ └── test │ ├── groovy │ └── com │ │ └── devexperts │ │ └── switchboard │ │ └── JsonLoadTest.groovy │ └── resources │ ├── BytecodeParserIntegration.json │ ├── CukesIntegration.json │ ├── FeaturelessIntegration.json │ ├── IntegrationConfig.json │ ├── JavaParserIntegration.json │ ├── JiraIntegrationConfig.json │ ├── SimpleSplitter.json │ ├── ThreeSplitters.json │ └── log4j2.xml ├── sandbox ├── build.gradle └── src │ └── main │ ├── java │ └── com │ │ └── devexperts │ │ └── switchboard │ │ └── sandbox │ │ ├── examples │ │ ├── cukes │ │ │ └── CukesExtract.java │ │ ├── jira │ │ │ └── TestCreatingConsumerExample.java │ │ └── junit │ │ │ └── JunitExtract.java │ │ └── utils │ │ └── SandboxUtils.java │ └── resources │ ├── cukes │ ├── pckg1 │ │ ├── Mixed_feature_1.feature │ │ ├── Multi_feature_1.feature │ │ ├── Outline_feature_1.feature │ │ └── Single_feature_1.feature │ ├── pckg2 │ │ ├── Mixed_feature_2.feature │ │ ├── Multi_feature_2.feature │ │ ├── Outline_feature_2.feature │ │ └── Single_feature_2.feature │ └── pckg3 │ │ ├── Mixed_feature_3.feature │ │ ├── Multi_feature_3.feature │ │ ├── Outline_feature_3.feature │ │ └── Single_feature_3.feature │ ├── junit │ ├── pckg1 │ │ ├── Junit1Test.java │ │ └── Junit2Test.java │ └── pckg2 │ │ └── Junit3Test.java │ └── log4j2.xml ├── settings.gradle └── utils ├── build.gradle └── src ├── main ├── java │ └── com │ │ └── devexperts │ │ └── switchboard │ │ └── utils │ │ ├── ClassLoaderUtils.java │ │ ├── JacksonUtils.java │ │ ├── SystemPropsTestConsumer.java │ │ └── TestUtils.java └── resources │ ├── log4j2.xml │ └── lorem_ipsum.txt └── test └── resources └── log4j2.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .gradle 3 | *.log 4 | *.log.* 5 | build 6 | classes 7 | deliver 8 | deploy 9 | *.iml 10 | out 11 | gen 12 | 13 | -------------------------------------------------------------------------------- /CONTRIBUTE.md: -------------------------------------------------------------------------------- 1 | # Contributing to Switchboard 2 | We would be glad if you contribute to our source code and help us to improve Switchboard even more! We propose you to follow these guidelines: 3 | 4 | ## Contributing a Patch 5 | 6 | 1. Create your change to the repo in question. 7 | 2. Fork the desired repo, develop and test your code changes. 8 | 3. Ensure that your code is clear and comprehensible. 9 | 4. Ensure that your code has an appropriate set of unit tests which all pass. 10 | 5. Submit a pull request. 11 | 6. The repo owner will review your request. If it is approved, the change will be merged. If it needs additional work, the repo owner will respond with useful comments. 12 | 7. Before the code is merged Contributor License Agreement (CLA) should be signed. Our bot will comment on the PR asking you to sign the CLA if it is required. 13 | 14 | ## Question or problem 15 | If you have any questions about how to use Switchboard, please contact via Github issues. Just create an issue with a question. 16 | 17 | ## Submitting an issue 18 | You can help us by submitting an issue to our GitHub Repository in case you find a bug in the source code, a mistake in the documentation or a proposal. A Pull Request with a fix would be even better. Before you submit an issue, search the archive, maybe your question was already answered. 19 | Here are the submission guidelines we would like you to follow: 20 | * Detailed overview of the Issue 21 | * Related issues - has a similar issue been reported before? 22 | * Reproduce the Error - A set of steps to reproduce the error (in case of a bug) 23 | * Suggest a Fix - if you can't fix the bug yourself, perhaps you can point to what might be causing the problem (line of code or commit) 24 | 25 | ## Documentation fixes 26 | If you have any ideas how to help us to improve the documentation, please let others know what you're working on by creating a new issue or comment on a related existing one (please, follow the guidelines contained in Submitting an issue). -------------------------------------------------------------------------------- /api/build.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | dependencies { 9 | compileOnly "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion" 10 | } -------------------------------------------------------------------------------- /api/src/main/java/com/devexperts/switchboard/api/ComponentReference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.api; 9 | 10 | import com.devexperts.switchboard.entities.Test; 11 | import com.devexperts.switchboard.entities.TestRun; 12 | import com.fasterxml.jackson.annotation.JsonProperty; 13 | 14 | import java.util.ArrayList; 15 | import java.util.Collection; 16 | import java.util.List; 17 | 18 | /** 19 | * This class represents a placeholder for using a component of one integration in another integration 20 | */ 21 | public class ComponentReference 22 | implements TestExtractor, TestProcessor, TestFilter, TestSplitter, TestRunProcessor, TestRunConsumer 23 | { 24 | @JsonProperty(required = true) 25 | private String identifier; 26 | @JsonProperty(required = true) 27 | private String integrationIdentifier; 28 | 29 | private ComponentReference() {} 30 | 31 | public ComponentReference(String identifier, String integrationIdentifier) { 32 | this.identifier = identifier; 33 | this.integrationIdentifier = integrationIdentifier; 34 | } 35 | 36 | @Override 37 | public void init(F integrationFeatures) {/*do nothing: referenced component will be inited by its own integration*/} 38 | 39 | @Override 40 | public String getIdentifier() { 41 | return identifier; 42 | } 43 | 44 | @Override 45 | public List get() { 46 | return getIntegration().getExtractorRunner().run(identifier, null); 47 | } 48 | 49 | @Override 50 | public List processTests(List tests) { 51 | return getIntegration().getTestProcessorRunner().run(identifier, tests); 52 | } 53 | 54 | @Override 55 | public List processRuns(List testsRuns) { 56 | return getIntegration().getTestRunProcessorRunner().run(identifier, testsRuns); 57 | } 58 | 59 | @Override 60 | public List filter(List tests) { 61 | return getIntegration().getFilterRunner().run(identifier, tests); 62 | } 63 | 64 | @Override 65 | public List split(Collection tests) { 66 | return getIntegration().getSplitterRunner().run(identifier, new ArrayList<>(tests)); 67 | } 68 | 69 | @Override 70 | public Void accept(List testRuns) { 71 | getIntegration().getConsumerRunner().run(identifier, testRuns); 72 | return null; 73 | } 74 | 75 | private Integration getIntegration() { 76 | return IntegrationContexts.getIntegration(integrationIdentifier); 77 | } 78 | 79 | @Override 80 | public void close() {/*do nothing: referenced component will be closed by its own integration*/} 81 | } -------------------------------------------------------------------------------- /api/src/main/java/com/devexperts/switchboard/api/ComponentsRunner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.api; 9 | 10 | import com.fasterxml.jackson.annotation.JsonIgnoreType; 11 | 12 | /** 13 | * This interface abstracts running {@link IntegrationComponent} implementations from {@link Integration} 14 | * 15 | * @param specific IntegrationComponent implementation run result class 16 | * @param specific IntegrationComponent implementation accepted argument class 17 | */ 18 | @JsonIgnoreType 19 | public interface ComponentsRunner { 20 | 21 | /** 22 | * Runs all {@link IntegrationComponent} of specified type in {@link Integration} with specified argument 23 | * 24 | * @param val the argument accepted by specific {@link IntegrationComponent} implementation 25 | * @return the result of {@link IntegrationComponent} implementation execution 26 | */ 27 | T run(V val); 28 | 29 | /** 30 | * Runs a specific {@link IntegrationComponent} of specified type in {@link Integration} with specified argument 31 | * 32 | * @param identifier a string identifier of component to tun 33 | * @param val the argument accepted by specific {@link IntegrationComponent} implementation 34 | * @return the result of {@link IntegrationComponent} implementation execution 35 | */ 36 | T run(String identifier, V val); 37 | } -------------------------------------------------------------------------------- /api/src/main/java/com/devexperts/switchboard/api/Identifiable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.api; 9 | 10 | 11 | import com.fasterxml.jackson.annotation.JsonProperty; 12 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 13 | 14 | /** 15 | * The interface indicating an entity which as an identifier and can be (de)serialized by fasterxml.jackson 16 | * Uses default {@link JsonTypeInfo.As#PROPERTY} include for (de)serialization 17 | */ 18 | @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 19 | public interface Identifiable { 20 | /** 21 | * The entity identifier, unique within functional unit 22 | * (i.e. a TestSplitter in integration among other TestSplitters in this integration, 23 | * an Integration among other integrations in run etc.) 24 | * 25 | * @return String entity identifier 26 | */ 27 | @JsonProperty(required = true) 28 | String getIdentifier(); 29 | } 30 | -------------------------------------------------------------------------------- /api/src/main/java/com/devexperts/switchboard/api/Integration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.api; 9 | 10 | import com.devexperts.switchboard.entities.Test; 11 | import com.devexperts.switchboard.entities.TestRun; 12 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 13 | 14 | import java.util.List; 15 | 16 | 17 | /** 18 | * This entity represents a configured composition of subcomponents prepared for extracting, processing, filtering, splitting and formatting tests 19 | */ 20 | @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 21 | public interface Integration extends Identifiable, AutoCloseable { 22 | 23 | /** 24 | * This method initializes the integration instance (e.g. setup IntegrationFeatures from parsed POJO fields) and its components 25 | */ 26 | void init(); 27 | 28 | /** 29 | * Returns the features of this integration which can be passed to each integration component 30 | * 31 | * @return the {@link IntegrationFeatures} of this Integration instance 32 | */ 33 | F getIntegrationFeatures(); 34 | 35 | /** 36 | * Returns {@code true} if this configuration is supposed to be run, false for the ones which only provide its components to runnable integrations. 37 | * 38 | * @return true if configuration is runnable 39 | */ 40 | boolean isRunnable(); 41 | 42 | /** 43 | * Run this configuration implementation if it is runnable 44 | */ 45 | void run(); 46 | 47 | /** 48 | * @return components runner for {@link TestExtractor} instances assigned to this configuration 49 | */ 50 | ComponentsRunner, Void> getExtractorRunner(); 51 | 52 | /** 53 | * @return components runner for {@link TestProcessor} instances assigned to this configuration 54 | */ 55 | ComponentsRunner, List> getTestProcessorRunner(); 56 | 57 | /** 58 | * @return components runner for {@link TestFilter} instances assigned to this configuration 59 | */ 60 | ComponentsRunner, List> getFilterRunner(); 61 | 62 | /** 63 | * @return components runner for {@link TestSplitter} instances assigned to this configuration 64 | */ 65 | ComponentsRunner, List> getSplitterRunner(); 66 | 67 | /** 68 | * @return components runner for {@link TestRunProcessor} instances assigned to this configuration 69 | */ 70 | ComponentsRunner, List> getTestRunProcessorRunner(); 71 | 72 | /** 73 | * @return components runner for {@link TestRunConsumer} instances assigned to this configuration 74 | */ 75 | ComponentsRunner> getConsumerRunner(); 76 | } -------------------------------------------------------------------------------- /api/src/main/java/com/devexperts/switchboard/api/IntegrationComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | 9 | package com.devexperts.switchboard.api; 10 | 11 | 12 | /** 13 | * The interface indicating a single component of an {@link Integration} 14 | * 15 | * @param compatible implementation class of {@link IntegrationFeatures} acceptable by a specific implementation of this interface 16 | */ 17 | public interface IntegrationComponent extends Identifiable, AutoCloseable { 18 | 19 | /** 20 | * This method initializes the component using both its own fields 21 | * 22 | * @param integrationFeatures features of integration containing the component 23 | */ 24 | void init(F integrationFeatures); 25 | } 26 | -------------------------------------------------------------------------------- /api/src/main/java/com/devexperts/switchboard/api/IntegrationFeatures.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.api; 9 | 10 | import com.fasterxml.jackson.annotation.JsonIgnoreType; 11 | 12 | /** 13 | * This interface represents the features instantiated per {@link Integration} instance and then passed to each integration component 14 | * e.g. jira/teamcity/http client, DB connection etc. 15 | */ 16 | @JsonIgnoreType 17 | public interface IntegrationFeatures extends AutoCloseable { 18 | } 19 | -------------------------------------------------------------------------------- /api/src/main/java/com/devexperts/switchboard/api/TestExtractor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.api; 9 | 10 | import com.devexperts.switchboard.entities.Test; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * A component supplying tests from some external source (files, DB, URL etc.) 16 | */ 17 | public interface TestExtractor extends IntegrationComponent { 18 | /** 19 | * Extracts the tests from some source 20 | * 21 | * @return list of extracted tests 22 | */ 23 | List get(); 24 | } -------------------------------------------------------------------------------- /api/src/main/java/com/devexperts/switchboard/api/TestFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.api; 9 | 10 | import com.devexperts.switchboard.entities.Test; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * A component filtering tests by some specified attributes 16 | */ 17 | public interface TestFilter extends IntegrationComponent { 18 | 19 | /** 20 | * Checks a list of tests by specified attributes and returns a list of matching tests 21 | * 22 | * @param tests a list of tests to filter 23 | * @return a list of tests matching the filter 24 | */ 25 | List filter(List tests); 26 | } 27 | -------------------------------------------------------------------------------- /api/src/main/java/com/devexperts/switchboard/api/TestProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.api; 9 | 10 | import com.devexperts.switchboard.entities.Test; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * A component processing (complementing, decoding, splitting etc.) specified tests 16 | */ 17 | public interface TestProcessor extends IntegrationComponent { 18 | 19 | /** 20 | * Process the specified tests and return the result 21 | * 22 | * @param tests a list of tests to process 23 | * @return a list of processed tests 24 | */ 25 | List processTests(List tests); 26 | } 27 | -------------------------------------------------------------------------------- /api/src/main/java/com/devexperts/switchboard/api/TestRunConsumer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.api; 9 | 10 | import com.devexperts.switchboard.entities.TestRun; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * A component consuming the prepared TestRun (e.g. test runner or some report collector). These entities are the final ones in Integration run. 16 | */ 17 | public interface TestRunConsumer extends IntegrationComponent { 18 | 19 | /** 20 | * Consume specified testRuns. 21 | * 22 | * @param testRuns test runs to consume 23 | * @return nothing 24 | */ 25 | Void accept(List testRuns); 26 | } 27 | -------------------------------------------------------------------------------- /api/src/main/java/com/devexperts/switchboard/api/TestRunProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.api; 9 | 10 | import com.devexperts.switchboard.entities.TestRun; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * A component processing (complementing, decoding, splitting etc.) specified tests runs 16 | */ 17 | public interface TestRunProcessor extends IntegrationComponent { 18 | 19 | /** 20 | * Process the specified test runs and return the result 21 | * 22 | * @param testRuns a list of test runs to process 23 | * @return a list of processed test runs 24 | */ 25 | List processRuns(List testRuns); 26 | } 27 | -------------------------------------------------------------------------------- /api/src/main/java/com/devexperts/switchboard/api/TestSplitter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.api; 9 | 10 | import com.devexperts.switchboard.entities.Test; 11 | import com.devexperts.switchboard.entities.TestRun; 12 | 13 | import java.util.Collection; 14 | import java.util.List; 15 | 16 | /** 17 | * A component splitting specified tests into TestRuns by specified attributes 18 | */ 19 | public interface TestSplitter extends IntegrationComponent { 20 | 21 | /** 22 | * Splits the specified list of tests into a list of test runs 23 | * 24 | * @param tests a list of tests to split 25 | * @return a list of test runs containing the tests 26 | */ 27 | List split(Collection tests); 28 | } 29 | -------------------------------------------------------------------------------- /api/src/main/java/com/devexperts/switchboard/entities/AttributedEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities; 9 | 10 | 11 | import com.devexperts.switchboard.api.Identifiable; 12 | 13 | import java.util.Objects; 14 | 15 | /** 16 | * An entity representing an {@link Identifiable} with {@link Attributes} 17 | */ 18 | public abstract class AttributedEntity implements Identifiable { 19 | private String identifier; 20 | private Attributes attributes; 21 | 22 | protected AttributedEntity() {} 23 | 24 | protected AttributedEntity(String identifier, Attributes attributes) { 25 | this.identifier = identifier; 26 | this.attributes = attributes; 27 | } 28 | 29 | /** 30 | * Return unique String identifier of this test 31 | * 32 | * @return String identifier 33 | */ 34 | @Override 35 | public String getIdentifier() { 36 | return identifier; 37 | } 38 | 39 | /** 40 | * Return the String value of test suitable for the runner of specified test 41 | * 42 | * @return the String value of test suitable for the runner 43 | */ 44 | public Attributes getAttributes() { 45 | return attributes; 46 | } 47 | 48 | @Override 49 | public boolean equals(Object o) { 50 | if (this == o) return true; 51 | if (o == null || getClass() != o.getClass()) return false; 52 | AttributedEntity test = (AttributedEntity) o; 53 | return Objects.equals(identifier, test.identifier) && 54 | Objects.equals(attributes, test.attributes); 55 | } 56 | 57 | @Override 58 | public int hashCode() { 59 | return Objects.hash(identifier, attributes); 60 | } 61 | 62 | @Override 63 | public String toString() { 64 | return getClass().getSimpleName() + "{" + 65 | "identifier='" + identifier + '\'' + 66 | ", attributes=" + attributes + 67 | '}'; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /api/src/main/java/com/devexperts/switchboard/entities/Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities; 9 | 10 | 11 | import com.fasterxml.jackson.annotation.JsonIgnore; 12 | 13 | import java.util.function.Function; 14 | 15 | /** 16 | * An entity representing a single test (e.g. TestNG or JUnit test, a Cucumber scenario, etc.) 17 | */ 18 | public final class Test extends AttributedEntity { 19 | @JsonIgnore 20 | private Function toRunnerString; 21 | 22 | private Test() {super();} 23 | 24 | public Test(String identifier, Attributes attributes, Function toRunnerString) { 25 | super(identifier, attributes); 26 | this.toRunnerString = toRunnerString; 27 | } 28 | 29 | /** 30 | * Return the String test representation acceptable to specify test run by test framework of this test 31 | * 32 | * @return String test representation acceptable to specify test run by test framework of this test 33 | */ 34 | public String toRunnerString() { 35 | return toRunnerString.apply(this); 36 | } 37 | } -------------------------------------------------------------------------------- /api/src/main/java/com/devexperts/switchboard/entities/TestRun.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities; 9 | 10 | import java.util.Collection; 11 | import java.util.Collections; 12 | import java.util.HashSet; 13 | import java.util.Objects; 14 | import java.util.Set; 15 | 16 | /** 17 | * An entity representing a test run of specifically implemented {@link Test} 18 | */ 19 | public class TestRun extends AttributedEntity { 20 | private final Set tests; 21 | 22 | private TestRun(Builder builder) { 23 | super(builder.identifier, builder.attributes.build()); 24 | tests = Collections.unmodifiableSet(builder.tests); 25 | } 26 | 27 | /** 28 | * @return a set of tests included into this test run 29 | */ 30 | public Set getTests() { 31 | return tests; 32 | } 33 | 34 | public Builder toBuilder() { 35 | return new Builder() 36 | .identifier(getIdentifier()) 37 | .addTests(new HashSet<>(tests)) 38 | .putAttributes(getAttributes()); 39 | } 40 | 41 | public static Builder newBuilder() { 42 | return new Builder(); 43 | } 44 | 45 | @Override 46 | public boolean equals(Object o) { 47 | return super.equals(o) && Objects.equals(tests, ((TestRun) o).tests); 48 | } 49 | 50 | @Override 51 | public int hashCode() { 52 | return Objects.hash(super.hashCode(), tests); 53 | } 54 | 55 | @Override 56 | public String toString() { 57 | return getClass().getSimpleName() + "{" + 58 | "identifier='" + getIdentifier() + '\'' + 59 | ", attributes=" + getAttributes() + 60 | ", tests=" + tests + 61 | '}'; 62 | } 63 | 64 | public static final class Builder { 65 | private String identifier; 66 | private final Set tests = new HashSet<>(); 67 | private final Attributes.Builder attributes = Attributes.newBuilder(); 68 | 69 | private Builder() {} 70 | 71 | public Builder identifier(String identifier) { 72 | this.identifier = identifier; 73 | return this; 74 | } 75 | 76 | public Builder addTests(Collection tests) { 77 | this.tests.addAll(tests); 78 | return this; 79 | } 80 | 81 | public Builder putAttributes(Attributes attributes) { 82 | this.attributes.putAttributes(attributes); 83 | return this; 84 | } 85 | 86 | public Builder mergeAttributes(Attributes attributes) { 87 | this.attributes.mergeAttributes(attributes); 88 | return this; 89 | } 90 | 91 | public TestRun build() { 92 | return new TestRun(this); 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /api/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | import com.github.jk1.license.render.InventoryHtmlReportRenderer 2 | 3 | /** 4 | * Copyright (C) 2002 - 2021 Devexperts LLC 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 8 | */ 9 | 10 | plugins { 11 | id 'java' 12 | id 'groovy' 13 | id "com.github.johnrengelman.shadow" version "5.2.0" apply false 14 | id "org.hibernate.build.maven-repo-auth" version "3.0.2" 15 | id 'com.github.jk1.dependency-license-report' version '1.16' 16 | } 17 | 18 | repositories { 19 | mavenCentral() 20 | } 21 | 22 | allprojects { 23 | group 'com.devexperts.switchboard' 24 | version '1.0-SNAPSHOT' 25 | 26 | sourceCompatibility = 1.8 27 | targetCompatibility = 1.8 28 | 29 | apply plugin: 'java' 30 | apply plugin: 'groovy' 31 | apply plugin: 'maven-publish' 32 | apply plugin: 'org.hibernate.build.maven-repo-auth' 33 | apply plugin: 'com.github.jk1.dependency-license-report' 34 | 35 | repositories { 36 | mavenCentral() 37 | } 38 | 39 | dependencies { 40 | implementation "org.apache.logging.log4j:log4j-slf4j-impl:$apacheLog4jVersion" 41 | implementation "org.slf4j:slf4j-api:$slf4jVersion" 42 | implementation "com.lmax:disruptor:$lmaxDisruptorVersion" 43 | 44 | testImplementation "org.codehaus.groovy:groovy:$groovyVersion" 45 | testImplementation "junit:junit:$junitVersion" 46 | } 47 | } 48 | 49 | licenseReport { 50 | projects = [project] + project.subprojects 51 | configurations = ['compile'] 52 | excludeOwnGroup = true 53 | renderers = [new InventoryHtmlReportRenderer('InventoryHtmlReportRenderer.html', 'Dependency licenses')] 54 | } 55 | -------------------------------------------------------------------------------- /core/build.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | dependencies { 9 | compileOnly project(":api") 10 | compileOnly "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion" 11 | 12 | testImplementation project(":api") 13 | testImplementation project(":utils") 14 | testImplementation "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion" 15 | testImplementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" 16 | } -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/entities/Pair.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities; 9 | 10 | import com.fasterxml.jackson.annotation.JsonProperty; 11 | 12 | import java.util.Objects; 13 | 14 | /** 15 | * Util class representing a pair of entities 16 | * 17 | * @param class of key entity of pair 18 | * @param class of value entity of pair 19 | */ 20 | public class Pair { 21 | @JsonProperty 22 | private K key; 23 | @JsonProperty 24 | private V value; 25 | 26 | private Pair() {} 27 | 28 | private Pair(K key, V value) { 29 | this.key = key; 30 | this.value = value; 31 | } 32 | 33 | /** 34 | * Creates a new pair with specified key and value 35 | * 36 | * @param key key of created pair 37 | * @param value value of created pair 38 | * @param pair key 39 | * @param pair value 40 | * @return a created pair with specified key and value 41 | */ 42 | public static Pair of(K key, V value) { 43 | return new Pair<>(key, value); 44 | } 45 | 46 | /** 47 | * @return key of this pair 48 | */ 49 | public K getKey() { 50 | return key; 51 | } 52 | 53 | /** 54 | * @return value of this pair 55 | */ 56 | public V getValue() { 57 | return value; 58 | } 59 | 60 | @Override 61 | public boolean equals(Object o) { 62 | if (this == o) return true; 63 | if (o == null || getClass() != o.getClass()) return false; 64 | Pair pair = (Pair) o; 65 | return Objects.equals(key, pair.key) && 66 | Objects.equals(value, pair.value); 67 | } 68 | 69 | @Override 70 | public int hashCode() { 71 | return Objects.hash(key, value); 72 | } 73 | 74 | @Override 75 | public String toString() { 76 | return getClass().getSimpleName() + "{" + 77 | "key=" + key + 78 | ", value=" + value + 79 | '}'; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/entities/attributes/AndAttributeWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities.attributes; 9 | 10 | import com.devexperts.switchboard.entities.Attributes; 11 | import com.devexperts.switchboard.utils.Arguments; 12 | import com.fasterxml.jackson.annotation.JsonProperty; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * An implementation of {@link AttributePredicate} as a conjunction of several other AttributePredicates 18 | */ 19 | public class AndAttributeWrapper implements AttributePredicate { 20 | @JsonProperty(required = true) 21 | private List attributePredicates; 22 | 23 | private AndAttributeWrapper() {} 24 | 25 | public AndAttributeWrapper(List attributePredicates) { 26 | this.attributePredicates = attributePredicates; 27 | } 28 | 29 | @Override 30 | public boolean test(Attributes attributes) { 31 | return Arguments.checkNotEmpty(attributePredicates, "attributePredicates").stream() 32 | .allMatch(p -> Arguments.checkNotNull(p, "attributePredicate").test(attributes)); 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return getClass().getSimpleName() + "{" + 38 | "attributePredicates=" + attributePredicates + 39 | '}'; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/entities/attributes/AttributeHasSingleValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities.attributes; 9 | 10 | import com.devexperts.switchboard.entities.Attributes; 11 | import com.devexperts.switchboard.utils.Arguments; 12 | import com.fasterxml.jackson.annotation.JsonProperty; 13 | 14 | /** 15 | * {@link AttributePredicate} which tests whether the {@link Attributes} has a single value 16 | * with key matching the specified regex {@link #attributeKeyRegex} and value key matching the specified regex {@link #attributeValueKeyRegex} 17 | */ 18 | public class AttributeHasSingleValue implements AttributePredicate { 19 | @JsonProperty(required = true) 20 | private String attributeKeyRegex; 21 | @JsonProperty(required = true) 22 | private String attributeValueKeyRegex; 23 | 24 | private AttributeHasSingleValue() {} 25 | 26 | public AttributeHasSingleValue(String attributeKeyRegex, String attributeValueKeyRegex) { 27 | this.attributeKeyRegex = attributeKeyRegex; 28 | this.attributeValueKeyRegex = attributeValueKeyRegex; 29 | } 30 | 31 | @Override 32 | public boolean test(Attributes attributes) { 33 | return attributes.getAttributes().entrySet().stream() 34 | .anyMatch(e -> e.getKey().matches(Arguments.checkNotBlank(attributeKeyRegex, "attributeKeyRegex")) 35 | && e.getValue().entrySet().stream() 36 | .anyMatch(v -> v.getKey().matches(Arguments.checkNotNull(attributeValueKeyRegex, "attributeValueKeyRegex")) 37 | && v.getValue().size() == 1)); 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return getClass().getSimpleName() + "{" + 43 | "attributeKeyRegex='" + attributeKeyRegex + '\'' + 44 | ", attributeValueKeyRegex='" + attributeValueKeyRegex + '\'' + 45 | '}'; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/entities/attributes/AttributeIsPresent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities.attributes; 9 | 10 | import com.devexperts.switchboard.entities.Attributes; 11 | import com.devexperts.switchboard.utils.Arguments; 12 | import com.fasterxml.jackson.annotation.JsonProperty; 13 | 14 | /** 15 | * An implementation of {@link AttributePredicate} which tests whether the {@link Attributes} has a single key matching the specified regex {@link #attributeKeyRegex} 16 | */ 17 | public class AttributeIsPresent implements AttributePredicate { 18 | @JsonProperty(required = true) 19 | private String attributeKeyRegex; 20 | 21 | private AttributeIsPresent() {} 22 | 23 | public AttributeIsPresent(String attributeKeyRegex) { 24 | this.attributeKeyRegex = attributeKeyRegex; 25 | } 26 | 27 | @Override 28 | public boolean test(Attributes attributes) { 29 | Arguments.checkNotBlank(attributeKeyRegex, "attributeKeyRegex"); 30 | return attributes.getAttributes().keySet().stream().anyMatch(key -> key.matches(attributeKeyRegex)); 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return getClass().getSimpleName() + "{" + "attributeKeyRegex='" + attributeKeyRegex + '}'; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/entities/attributes/AttributePredicate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities.attributes; 9 | 10 | import com.devexperts.switchboard.entities.Attributes; 11 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 12 | 13 | import java.util.function.Predicate; 14 | 15 | /** 16 | * Represents a (de)serializable predicate of {@link Attributes} 17 | */ 18 | @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 19 | public interface AttributePredicate extends Predicate { 20 | 21 | @Override 22 | default AttributePredicate negate() { 23 | return new NotAttributeWrapper(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/entities/attributes/AttributeValueKeyIsPresent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities.attributes; 9 | 10 | import com.devexperts.switchboard.entities.Attributes; 11 | import com.devexperts.switchboard.utils.Arguments; 12 | import com.fasterxml.jackson.annotation.JsonProperty; 13 | 14 | /** 15 | * An implementation of {@link AttributePredicate} which tests whether the {@link Attributes} has a value key 16 | * matching the specified regex {@link #attributeValueKeyRegex} with key matching the specified regex {@link #attributeKeyRegex} 17 | */ 18 | public class AttributeValueKeyIsPresent implements AttributePredicate { 19 | @JsonProperty(required = true) 20 | private String attributeKeyRegex; 21 | @JsonProperty(required = true) 22 | private String attributeValueKeyRegex; 23 | 24 | private AttributeValueKeyIsPresent() {} 25 | 26 | public AttributeValueKeyIsPresent(String attributeKeyRegex, String attributeValueKeyRegex) { 27 | this.attributeKeyRegex = attributeKeyRegex; 28 | this.attributeValueKeyRegex = attributeValueKeyRegex; 29 | } 30 | 31 | @Override 32 | public boolean test(Attributes attributes) { 33 | return attributes.getAttributes().entrySet().stream() 34 | .anyMatch(e -> e.getKey().matches(Arguments.checkNotBlank(attributeKeyRegex, "attributeKeyRegex")) 35 | && e.getValue().keySet().stream() 36 | .anyMatch(v -> v.matches(Arguments.checkNotNull(attributeValueKeyRegex, "attributeValueKeyRegex")))); 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return getClass().getSimpleName() + "{" + 42 | "attributeKeyRegex='" + attributeKeyRegex + '\'' + 43 | ", attributeValueKeyRegex='" + attributeValueKeyRegex + '\'' + 44 | '}'; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/entities/attributes/AttributeValueMatches.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities.attributes; 9 | 10 | import com.devexperts.switchboard.entities.Attributes; 11 | import com.devexperts.switchboard.utils.Arguments; 12 | import com.fasterxml.jackson.annotation.JsonProperty; 13 | 14 | /** 15 | * An implementation of {@link AttributePredicate} which tests whether the {@link Attributes} has a value 16 | * matching the specified regex {@link #valueRegex} with a value key matching the specified regex {@link #attributeValueKeyRegex} 17 | * and key matching the specified regex {@link #attributeKeyRegex} 18 | */ 19 | public class AttributeValueMatches implements AttributePredicate { 20 | @JsonProperty(required = true) 21 | private String attributeKeyRegex; 22 | @JsonProperty(required = true) 23 | private String attributeValueKeyRegex; 24 | @JsonProperty(required = true) 25 | private String valueRegex; 26 | 27 | private AttributeValueMatches() {} 28 | 29 | public AttributeValueMatches(String attributeKeyRegex, String attributeValueKeyRegex, String valueRegex) { 30 | this.attributeKeyRegex = attributeKeyRegex; 31 | this.attributeValueKeyRegex = attributeValueKeyRegex; 32 | this.valueRegex = valueRegex; 33 | } 34 | 35 | @Override 36 | public boolean test(Attributes attributes) { 37 | return attributes.getAttributes().entrySet().stream() 38 | .anyMatch(e -> e.getKey().matches(Arguments.checkNotBlank(attributeKeyRegex, "attributeKeyRegex")) 39 | && e.getValue().entrySet().stream() 40 | .anyMatch(v -> v.getKey().matches(Arguments.checkNotNull(attributeValueKeyRegex, "attributeValueKeyRegex")) 41 | && v.getValue().stream() 42 | .anyMatch(vv -> vv.matches(Arguments.checkNotBlank(valueRegex, "valueRegex"))))); 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return getClass().getSimpleName() + "{" + 48 | "attributeKeyRegex='" + attributeKeyRegex + '\'' + 49 | ", attributeValueKeyRegex='" + attributeValueKeyRegex + '\'' + 50 | ", valueRegex='" + valueRegex + '\'' + 51 | '}'; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/entities/attributes/NotAttributeWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities.attributes; 9 | 10 | import com.devexperts.switchboard.entities.Attributes; 11 | import com.devexperts.switchboard.utils.Arguments; 12 | import com.fasterxml.jackson.annotation.JsonProperty; 13 | 14 | /** 15 | * An implementation of {@link AttributePredicate} as a negation of other AttributePredicates 16 | */ 17 | public class NotAttributeWrapper implements AttributePredicate { 18 | @JsonProperty(required = true) 19 | private AttributePredicate attributePredicate; 20 | 21 | public NotAttributeWrapper() { } 22 | 23 | public NotAttributeWrapper(AttributePredicate attributePredicate) { 24 | this.attributePredicate = attributePredicate; 25 | } 26 | 27 | @Override 28 | public boolean test(Attributes attributes) { 29 | return !Arguments.checkNotNull(attributePredicate, "attributePredicate").test(attributes); 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return getClass().getSimpleName() + "{" + 35 | "attributePredicate=" + attributePredicate + 36 | '}'; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/entities/attributes/OrAttributeWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities.attributes; 9 | 10 | import com.devexperts.switchboard.entities.Attributes; 11 | import com.devexperts.switchboard.utils.Arguments; 12 | import com.fasterxml.jackson.annotation.JsonProperty; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * An implementation of {@link AttributePredicate} as a disjunction of several other AttributePredicates 18 | */ 19 | public class OrAttributeWrapper implements AttributePredicate { 20 | @JsonProperty(required = true) 21 | private List attributePredicates; 22 | 23 | public OrAttributeWrapper() {} 24 | 25 | public OrAttributeWrapper(List attributePredicates) { 26 | this.attributePredicates = attributePredicates; 27 | } 28 | 29 | @Override 30 | public boolean test(Attributes attributes) { 31 | return Arguments.checkNotEmpty(attributePredicates, "attributePredicates").stream() 32 | .anyMatch(p -> Arguments.checkNotNull(p, "attributePredicate").test(attributes)); 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return getClass().getSimpleName() + "{" + 38 | "attributePredicates=" + attributePredicates + 39 | '}'; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/entities/valuesupplier/ConditionalValueExtractor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities.valuesupplier; 9 | 10 | import com.devexperts.switchboard.entities.AttributedEntity; 11 | import com.devexperts.switchboard.entities.Pair; 12 | import com.devexperts.switchboard.entities.Test; 13 | import com.devexperts.switchboard.entities.TestRun; 14 | import com.devexperts.switchboard.entities.attributes.AttributePredicate; 15 | import com.fasterxml.jackson.annotation.JsonProperty; 16 | 17 | import java.util.List; 18 | import java.util.Set; 19 | 20 | public class ConditionalValueExtractor implements TestRunValuesExtractor, TestValuesExtractor { 21 | @JsonProperty(required = true) 22 | private List> conditions; 23 | @JsonProperty(required = true) 24 | private ValuesExtractor defaultValueExtractor; 25 | 26 | private ConditionalValueExtractor() {} 27 | 28 | public ConditionalValueExtractor(List> conditions, ValuesExtractor defaultValueExtractor) { 29 | this.conditions = conditions; 30 | this.defaultValueExtractor = defaultValueExtractor; 31 | } 32 | 33 | @Override 34 | public Set getRunValues(TestRun t) { 35 | return getExtractor(t, TestRunValuesExtractor.class).getRunValues(t); 36 | } 37 | 38 | @Override 39 | public String getRunValue(TestRun t) { 40 | return getExtractor(t, TestRunValuesExtractor.class).getRunValue(t); 41 | } 42 | 43 | @Override 44 | public Set getTestValues(Test t) { 45 | return getExtractor(t, TestValuesExtractor.class).getTestValues(t); 46 | } 47 | 48 | @Override 49 | public String getTestValue(Test t) { 50 | return getExtractor(t, TestValuesExtractor.class).getTestValue(t); 51 | } 52 | 53 | private T getExtractor(AttributedEntity t, Class extractorClass) { 54 | ValuesExtractor ex = conditions.stream() 55 | .filter(k -> k.getKey().test(t.getAttributes())) 56 | .map(Pair::getValue) 57 | .findFirst() 58 | .orElse(defaultValueExtractor); 59 | if (extractorClass.isAssignableFrom(ex.getClass())) { 60 | return (T) ex; 61 | } 62 | throw new IllegalStateException("Expected ValuesExtractor of type " + extractorClass.getSimpleName() 63 | + ", found: " + ex.getClass().getSimpleName()); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/entities/valuesupplier/ConstantValuesExtractor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities.valuesupplier; 9 | 10 | import com.devexperts.switchboard.entities.Test; 11 | import com.devexperts.switchboard.entities.TestRun; 12 | import com.fasterxml.jackson.annotation.JsonProperty; 13 | 14 | import java.util.Collections; 15 | import java.util.HashSet; 16 | import java.util.Objects; 17 | import java.util.Set; 18 | 19 | /** 20 | * This implementation of {@link ValuesExtractor} stores and returns a constant value independent of initialization 21 | */ 22 | public class ConstantValuesExtractor implements TestRunValuesExtractor, TestValuesExtractor { 23 | @JsonProperty(required = true) 24 | private Set values; 25 | @JsonProperty(defaultValue = ",") 26 | private String valuesSeparator = ","; 27 | 28 | private ConstantValuesExtractor() {} 29 | 30 | public ConstantValuesExtractor(Set values, String valuesSeparator) { 31 | this.values = values; 32 | this.valuesSeparator = valuesSeparator; 33 | } 34 | 35 | public ConstantValuesExtractor(String value) { 36 | this(new HashSet<>(Collections.singletonList(value)), ","); 37 | } 38 | 39 | @Override 40 | public Set getRunValues(TestRun t) { 41 | return values; 42 | } 43 | 44 | @Override 45 | public String getRunValue(TestRun t) { 46 | return String.join(valuesSeparator, values); 47 | } 48 | 49 | @Override 50 | public Set getTestValues(Test t) { 51 | return values; 52 | } 53 | 54 | @Override 55 | public String getTestValue(Test t) { 56 | return String.join(valuesSeparator, values); 57 | } 58 | 59 | @Override 60 | public boolean equals(Object o) { 61 | if (this == o) return true; 62 | if (o == null || getClass() != o.getClass()) return false; 63 | ConstantValuesExtractor that = (ConstantValuesExtractor) o; 64 | return Objects.equals(values, that.values) && 65 | Objects.equals(valuesSeparator, that.valuesSeparator); 66 | } 67 | 68 | @Override 69 | public int hashCode() { 70 | return Objects.hash(values, valuesSeparator); 71 | } 72 | 73 | @Override 74 | public String toString() { 75 | return getClass().getSimpleName() + "{" + 76 | "values=" + values + 77 | ", valuesSeparator='" + valuesSeparator + '\'' + 78 | '}'; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/entities/valuesupplier/IdentifierValuesExtractor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities.valuesupplier; 9 | 10 | import com.devexperts.switchboard.entities.Test; 11 | import com.devexperts.switchboard.entities.TestRun; 12 | import com.fasterxml.jackson.annotation.JsonIgnore; 13 | 14 | import java.util.Collections; 15 | import java.util.HashSet; 16 | import java.util.Set; 17 | 18 | /** 19 | * This implementation of {@link ValuesExtractor} can be initiated by both {@link Test} and {@link TestRun} 20 | * returning #getIdentifier() value of initiating entity 21 | */ 22 | public class IdentifierValuesExtractor implements TestRunValuesExtractor, TestValuesExtractor { 23 | 24 | @JsonIgnore 25 | private String value; 26 | 27 | public IdentifierValuesExtractor() {} 28 | 29 | @Override 30 | public Set getTestValues(Test test) { 31 | return new HashSet<>(Collections.singletonList(getTestValue(test))); 32 | } 33 | 34 | @Override 35 | public String getTestValue(Test test) { 36 | return test.getIdentifier(); 37 | } 38 | 39 | @Override 40 | public Set getRunValues(TestRun testRun) { 41 | return new HashSet<>(Collections.singletonList(getRunValue(testRun))); 42 | } 43 | 44 | @Override 45 | public String getRunValue(TestRun testRun) { 46 | return testRun.getIdentifier(); 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return getClass().getSimpleName() + "{}"; 52 | } 53 | } -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/entities/valuesupplier/TestRunValuesExtractor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities.valuesupplier; 9 | 10 | import com.devexperts.switchboard.entities.TestRun; 11 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 12 | 13 | import java.util.Set; 14 | 15 | /** 16 | * This interface abstracts (de)serializable String values extractors from {@link TestRun} which can be used in JSON configuration specification. 17 | */ 18 | @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 19 | public interface TestRunValuesExtractor extends ValuesExtractor { 20 | /** 21 | * Returns string values stored in supplier or calculated based on TestRun or null if value cannot be obtained 22 | * 23 | * @param t TestRun to extract value from 24 | * @return supplier values values 25 | */ 26 | Set getRunValues(TestRun t); 27 | 28 | /** 29 | * Returns a single string value representation of supplier values or null if value cannot be obtained 30 | * 31 | * @param t TestRun to extract value from 32 | * @return a single string value representation of supplier values 33 | */ 34 | String getRunValue(TestRun t); 35 | } -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/entities/valuesupplier/TestValuesExtractor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities.valuesupplier; 9 | 10 | import com.devexperts.switchboard.entities.Test; 11 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 12 | 13 | import java.util.Set; 14 | 15 | /** 16 | * This interface abstracts (de)serializable String values extractors from {@link Test} which can be used in JSON configuration specification. 17 | */ 18 | @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 19 | public interface TestValuesExtractor extends ValuesExtractor { 20 | /** 21 | * Returns string values stored in supplier or calculated based on Test or null if value cannot be obtained 22 | * 23 | * @param t Test to extract value from 24 | * @return supplier values values 25 | */ 26 | Set getTestValues(Test t); 27 | 28 | /** 29 | * Returns a single string value representation of supplier values or null if value cannot be obtained 30 | * 31 | * @param t Test to extract value from 32 | * @return a single string value representation of supplier values 33 | */ 34 | String getTestValue(Test t); 35 | } -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/entities/valuesupplier/TestsToStringValuesExtractor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities.valuesupplier; 9 | 10 | import com.devexperts.switchboard.entities.Test; 11 | import com.devexperts.switchboard.entities.TestRun; 12 | import com.fasterxml.jackson.annotation.JsonProperty; 13 | 14 | import java.util.Objects; 15 | import java.util.Set; 16 | import java.util.stream.Collectors; 17 | 18 | /** 19 | * This implementation of {@link TestRunValuesExtractor} for creating a value consisting of {@link Test#toRunnerString()} 20 | * values of tests in TestRun joined by {@link #valuesSeparator} 21 | */ 22 | public class TestsToStringValuesExtractor implements TestRunValuesExtractor { 23 | @JsonProperty(required = true) 24 | private String valuesSeparator; 25 | 26 | private TestsToStringValuesExtractor() {} 27 | 28 | public TestsToStringValuesExtractor(String valuesSeparator) { 29 | this.valuesSeparator = valuesSeparator; 30 | } 31 | 32 | @Override 33 | public Set getRunValues(TestRun testRun) { 34 | return testRun.getTests().stream() 35 | .map(Test::toRunnerString) 36 | .collect(Collectors.toSet()); 37 | } 38 | 39 | @Override 40 | public String getRunValue(TestRun testRun) { 41 | Set values = getRunValues(testRun); 42 | return values.isEmpty() ? null : String.join(valuesSeparator, values); 43 | } 44 | 45 | @Override 46 | public boolean equals(Object o) { 47 | if (this == o) return true; 48 | if (o == null || getClass() != o.getClass()) return false; 49 | TestsToStringValuesExtractor that = (TestsToStringValuesExtractor) o; 50 | return Objects.equals(valuesSeparator, that.valuesSeparator); 51 | } 52 | 53 | @Override 54 | public int hashCode() { 55 | return Objects.hash(valuesSeparator); 56 | } 57 | 58 | @Override 59 | public String toString() { 60 | return getClass().getSimpleName() + "{" + 61 | "valuesSeparator='" + valuesSeparator + '\'' + 62 | '}'; 63 | } 64 | } -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/entities/valuesupplier/ValuesExtractor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.entities.valuesupplier; 9 | 10 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 11 | 12 | /** 13 | * Interface marking (de)serializable String values extractors used in JSON configuration specification 14 | */ 15 | @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 16 | public interface ValuesExtractor { 17 | } -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/impl/FeaturelessIntegration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.impl; 9 | 10 | import com.devexperts.switchboard.api.Integration; 11 | 12 | 13 | /** 14 | * The basic implementation of {@link Integration} with no special features provided to run default implementations of components 15 | */ 16 | public class FeaturelessIntegration extends IntegrationImpl { 17 | 18 | private FeaturelessIntegration() {} 19 | 20 | protected FeaturelessIntegration(Builder builder) { 21 | super(builder); 22 | } 23 | 24 | @Override 25 | public VoidIntegrationFeatures getIntegrationFeatures() { 26 | return VoidIntegrationFeatures.INSTANCE; 27 | } 28 | 29 | public static Builder newBuilder() { 30 | return new FeaturelessIntegration.Builder(); 31 | } 32 | 33 | public static class Builder extends IntegrationImpl.Builder { 34 | 35 | private Builder() {} 36 | 37 | @Override 38 | public FeaturelessIntegration build() { 39 | return new FeaturelessIntegration(this); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/impl/VoidIntegrationFeatures.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.impl; 9 | 10 | import com.devexperts.switchboard.api.IntegrationFeatures; 11 | 12 | /** 13 | * A stub implementation of IntegrationFeatures for usage in Integration implementations with no special features required 14 | */ 15 | public class VoidIntegrationFeatures implements IntegrationFeatures { 16 | public static final VoidIntegrationFeatures INSTANCE = new VoidIntegrationFeatures(); 17 | 18 | @Override 19 | public void close() {/*do nothing*/} 20 | } 21 | -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/impl/consumers/LoggingTestRunConsumer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.impl.consumers; 9 | 10 | import com.devexperts.switchboard.api.IntegrationFeatures; 11 | import com.devexperts.switchboard.api.TestRunConsumer; 12 | import com.devexperts.switchboard.entities.Test; 13 | import com.devexperts.switchboard.entities.TestRun; 14 | import com.fasterxml.jackson.annotation.JsonProperty; 15 | import org.slf4j.Logger; 16 | import org.slf4j.LoggerFactory; 17 | 18 | import java.util.List; 19 | import java.util.stream.Collectors; 20 | 21 | /** 22 | * A simplest consumer logging a comma-separated {@link Test} identifiers from TestRun 23 | */ 24 | public final class LoggingTestRunConsumer implements TestRunConsumer { 25 | private static final Logger log = LoggerFactory.getLogger(LoggingTestRunConsumer.class); 26 | 27 | @JsonProperty(required = true) 28 | private String identifier; 29 | 30 | private LoggingTestRunConsumer() {} 31 | 32 | public LoggingTestRunConsumer(String identifier) { 33 | this.identifier = identifier; 34 | } 35 | 36 | @Override 37 | public void init(IntegrationFeatures integrationFeatures) { /*do nothing*/ } 38 | 39 | @Override 40 | public Void accept(List testRuns) { 41 | String testRunsString = testRuns.stream() 42 | .map(tr -> tr.getTests().stream() 43 | .map(Test::getIdentifier) 44 | .collect(Collectors.joining(","))) 45 | .map(tr -> String.format("[%s]", tr)) 46 | .collect(Collectors.joining(",\n\t")); 47 | log.info("Test runs: \n\t{}", testRunsString); 48 | return null; 49 | } 50 | 51 | @Override 52 | public String getIdentifier() { 53 | return identifier; 54 | } 55 | 56 | @Override 57 | public void close() {/*do nothing*/} 58 | } -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/impl/filters/AttributesFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.impl.filters; 9 | 10 | import com.devexperts.switchboard.api.IntegrationFeatures; 11 | import com.devexperts.switchboard.entities.Test; 12 | import com.devexperts.switchboard.entities.attributes.AttributePredicate; 13 | import com.devexperts.switchboard.utils.Arguments; 14 | import com.fasterxml.jackson.annotation.JsonProperty; 15 | 16 | /** 17 | * Implementation of TestFilter based on checking {@link Test#getAttributes()} by specified {@link AttributePredicate} 18 | */ 19 | public class AttributesFilter extends DefaultTestFilter { 20 | @JsonProperty(required = true) 21 | private String identifier; 22 | @JsonProperty(required = true) 23 | private AttributePredicate attributePredicate; 24 | 25 | private AttributesFilter() {} 26 | 27 | public AttributesFilter(String identifier, AttributePredicate attributePredicate) { 28 | this.identifier = identifier; 29 | this.attributePredicate = attributePredicate; 30 | } 31 | 32 | @Override 33 | public void init(IntegrationFeatures integrationFeatures) { /*do nothing*/ } 34 | 35 | @Override 36 | public String getIdentifier() { 37 | return identifier; 38 | } 39 | 40 | @Override 41 | protected boolean matches(Test test) { 42 | return Arguments.checkNotNull(attributePredicate, "attributePredicate").test(test.getAttributes()); 43 | } 44 | 45 | @Override 46 | public void close() {/*do nothing*/} 47 | } 48 | -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/impl/filters/DefaultTestFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.impl.filters; 9 | 10 | import com.devexperts.switchboard.api.IntegrationFeatures; 11 | import com.devexperts.switchboard.api.TestFilter; 12 | import com.devexperts.switchboard.entities.Test; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | import java.util.List; 17 | import java.util.stream.Collectors; 18 | 19 | /** 20 | * A default implementation of TestFilter with logging every single entity matching check 21 | */ 22 | public abstract class DefaultTestFilter implements TestFilter { 23 | private static final Logger log = LoggerFactory.getLogger(DefaultTestFilter.class); 24 | 25 | @Override 26 | public List filter(List tests) { 27 | return tests.stream() 28 | .filter(this::matchesVerbose) 29 | .collect(Collectors.toList()); 30 | } 31 | 32 | /** 33 | * Evaluates this filter on the specified test. 34 | * 35 | * @param test test to check 36 | * @return true if test matches specified filter attributes 37 | */ 38 | protected abstract boolean matches(Test test); 39 | 40 | private boolean matchesVerbose(Test test) { 41 | if (matches(test)) { 42 | log.trace("Accepted: {}", test.getIdentifier()); 43 | return true; 44 | } 45 | log.trace("Dropped: {}", test.getIdentifier()); 46 | return false; 47 | } 48 | } -------------------------------------------------------------------------------- /core/src/main/java/com/devexperts/switchboard/utils/Arguments.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.utils; 9 | 10 | import java.util.Collection; 11 | import java.util.Map; 12 | 13 | /** 14 | * Util class providing argument check functionality 15 | */ 16 | public final class Arguments { 17 | private Arguments() {} 18 | 19 | /** 20 | * Checks that the specified object is not null 21 | * 22 | * @param t object to check 23 | * @param argName name for exception 24 | * @param object class 25 | * @return the initial object if it is not null 26 | * @throws IllegalArgumentException if object is null 27 | */ 28 | public static T checkNotNull(T t, String argName) { 29 | if (t == null) { 30 | throw new IllegalArgumentException(argName + " is null"); 31 | } 32 | return t; 33 | } 34 | 35 | /** 36 | * Checks that the specified String is not null and not blank 37 | * 38 | * @param s string to check 39 | * @param argName name for exception 40 | * @return the initial string if it is not blank 41 | * @throws IllegalArgumentException if string is null or blank 42 | */ 43 | public static String checkNotBlank(String s, String argName) { 44 | checkNotNull(s, argName); 45 | if (s.trim().isEmpty()) { 46 | throw new IllegalArgumentException(argName + " is blank"); 47 | } 48 | return s; 49 | } 50 | 51 | /** 52 | * Checks that the specified Collection is not null and not empty 53 | * 54 | * @param c collection to check 55 | * @param argName name for exception 56 | * @return the initial collection if it is not empty 57 | * @throws IllegalArgumentException if collection is null or empty 58 | */ 59 | public static Collection checkNotEmpty(Collection c, String argName) { 60 | checkNotNull(c, argName); 61 | if (c.isEmpty()) { 62 | throw new IllegalArgumentException(argName + " is empty"); 63 | } 64 | return c; 65 | } 66 | 67 | /** 68 | * Checks that the specified Map is not null and not empty 69 | * 70 | * @param c map to check 71 | * @param argName name for exception 72 | * @return the initial map if it is not empty 73 | * @throws IllegalArgumentException if collection is null or empty 74 | */ 75 | public static Map checkNotEmpty(Map c, String argName) { 76 | checkNotNull(c, argName); 77 | if (c.isEmpty()) { 78 | throw new IllegalArgumentException(argName + " is empty"); 79 | } 80 | return c; 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /core/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/src/test/groovy/com/devexperts/switchboard/entities/valuesupplier/TestDescriptionFormatterTests.groovy: -------------------------------------------------------------------------------- 1 | package com.devexperts.switchboard.entities.valuesupplier 2 | 3 | import com.devexperts.switchboard.entities.Attributes 4 | import com.devexperts.switchboard.entities.Pair 5 | import com.devexperts.switchboard.utils.JacksonUtils 6 | import org.junit.Test 7 | 8 | import java.nio.file.Files 9 | import java.nio.file.Paths 10 | 11 | class TestDescriptionFormatterTests { 12 | 13 | private static com.devexperts.switchboard.entities.Test test = JacksonUtils.getMapper() 14 | .readValue(Thread.currentThread().getContextClassLoader().getResource("sample_test.json"), com.devexperts.switchboard.entities.Test.class) 15 | 16 | @Test 17 | void testTestDescriptionFormatter() throws IOException { 18 | EnumeratingTestDescriptionFormatter testDescriptionFormatter = new EnumeratingTestDescriptionFormatter( 19 | new AttributeValuesExtractor("comments", "comments", "\n"), 20 | "^\\s*Action:\\s*(.+)", "^\\s*Result:\\s*(.+)", 21 | "*Actions:*", "*Results:*", 22 | "# ", "Check result (%s)", "After step (%s) - ") 23 | 24 | 25 | String formatted = testDescriptionFormatter.getTestValue(test) 26 | String expected = getResText("sample_test_description.txt") 27 | assert formatted == expected 28 | } 29 | 30 | @Test 31 | void testFullFormatter() { 32 | EnumeratingTestDescriptionFormatter testDescriptionFormatter = new EnumeratingTestDescriptionFormatter( 33 | new AttributeValuesExtractor("comments", "comments", "\n"), 34 | "^\\s*Action:\\s*(.+)", "^\\s*Result:\\s*(.+)", 35 | "*Actions:*", "*Results:*", 36 | "# ", "Check result (%s)", "After step (%s) - ") 37 | 38 | BlockFormattingValuesExtractor blockFormatter = new BlockFormattingValuesExtractor([ 39 | Pair.of("*Overview:*", new AttributeValuesExtractor(Attributes.COMMENTS_PROP, Attributes.JAVADOC_PROP, "\n")), 40 | Pair.of("*Preconditions:*", new AttributeValuesExtractor(Attributes.PRECONDITIONS_COMMENTS_PROP, Attributes.JAVADOC_PROP, "\n\n")), 41 | Pair.of("", testDescriptionFormatter), 42 | Pair.of("*Postconditions:*", new AttributeValuesExtractor(Attributes.POSTCONDITIONS_COMMENTS_PROP, Attributes.JAVADOC_PROP, "\n\n"))], 43 | "\n", "\n\n", false) 44 | String formatted = blockFormatter.getTestValue(test) 45 | String expected = getResText("sample_test_full.txt") 46 | assert formatted == expected 47 | } 48 | 49 | static String getResText(String res) { 50 | return new String(Files.readAllBytes(Paths.get(Thread.currentThread().getContextClassLoader().getResource(res).toURI()))) 51 | .replaceAll("\r\n", "\n") 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /core/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/src/test/resources/sample_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "@class": "com.devexperts.switchboard.entities.Test", 3 | "identifier": "com.devexperts.test.path.TestDescriptionFormatterTests#testTestDescriptionFormatter", 4 | "attributes": { 5 | "attributes": { 6 | "BrowserTest": {}, 7 | "Tag": { 8 | "": [ 9 | "tag1", 10 | "tag2" 11 | ] 12 | }, 13 | "Component": { 14 | "": [ 15 | "Component1" 16 | ] 17 | }, 18 | "RepositoryPath": { 19 | "": [ 20 | "/root/path/other_path" 21 | ] 22 | }, 23 | "ParameterizedTest": {}, 24 | "EnumSource": { 25 | "": [ 26 | "Src" 27 | ] 28 | }, 29 | "DisplayName": { 30 | "": [ 31 | "A test of TestDescriptionFormatter" 32 | ] 33 | }, 34 | "TestDetails": { 35 | "severity": [ 36 | "Severity.FUNCTIONAL" 37 | ], 38 | "manualEstimate": [ 39 | "20" 40 | ], 41 | "priority": [ 42 | "Priority.NORMAL" 43 | ], 44 | "uniqueId": [ 45 | "123456" 46 | ] 47 | }, 48 | "location": { 49 | "package": [ 50 | "com.devexperts.test.path" 51 | ], 52 | "class": [ 53 | "TestDescriptionFormatterTests" 54 | ], 55 | "method": [ 56 | "testTestDescriptionFormatter" 57 | ] 58 | }, 59 | "comments": { 60 | "comments": [ 61 | " Action: This is action 1\n Action: And this is action 2\n Action: Yet another action 3\n Result: Result of action 3 contains:\n First row;\n Second row\n Action: And then we execute action 4\n Action: And action 5\n And action5 another row\n Result: And this is the result of action 5\n second row for action 5\n Action: Action 6 is required too\n Action: And Action 7 of course\n sub action 7.1\n sub action 7.2\n Do we really need action 8?\n Action: Well action 8 is fine too\n Result: \n result1;\n result2.\n" 62 | ], 63 | "javadoc": [ 64 | "This is an overview for our test case. We need an overview, right?" 65 | ] 66 | }, 67 | "preconditions_comments": { 68 | "javadoc": [ 69 | "# This test case has a precondition\n# Two preconditions\n# Even three preconditions!" 70 | ] 71 | } 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /core/src/test/resources/sample_test_description.txt: -------------------------------------------------------------------------------- 1 | *Actions:* 2 | # This is action 1 3 | # And this is action 2 4 | # Yet another action 3 5 | # Check result (1) 6 | # And then we execute action 4 7 | # And action 5 8 | And action5 another row 9 | # Check result (2) 10 | # Action 6 is required too 11 | # And Action 7 of course 12 | sub action 7.1 13 | sub action 7.2 14 | Do we really need action 8? 15 | # Well action 8 is fine too 16 | # Check result (3) 17 | 18 | *Results:* 19 | # After step (3) - Result of action 3 contains: 20 | First row; 21 | Second row 22 | # After step (6) - And this is the result of action 5 23 | second row for action 5 24 | # After step (10) - 25 | result1; 26 | result2. 27 | -------------------------------------------------------------------------------- /core/src/test/resources/sample_test_full.txt: -------------------------------------------------------------------------------- 1 | *Overview:* 2 | This is an overview for our test case. We need an overview, right? 3 | 4 | *Preconditions:* 5 | # This test case has a precondition 6 | # Two preconditions 7 | # Even three preconditions! 8 | 9 | *Actions:* 10 | # This is action 1 11 | # And this is action 2 12 | # Yet another action 3 13 | # Check result (1) 14 | # And then we execute action 4 15 | # And action 5 16 | And action5 another row 17 | # Check result (2) 18 | # Action 6 is required too 19 | # And Action 7 of course 20 | sub action 7.1 21 | sub action 7.2 22 | Do we really need action 8? 23 | # Well action 8 is fine too 24 | # Check result (3) 25 | 26 | *Results:* 27 | # After step (3) - Result of action 3 contains: 28 | First row; 29 | Second row 30 | # After step (6) - And this is the result of action 5 31 | second row for action 5 32 | # After step (10) - 33 | result1; 34 | result2. 35 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | groovyVersion=3.0.8 2 | apacheLog4jVersion=2.14.1 3 | lmaxDisruptorVersion=3.4.4 4 | slf4jVersion=1.7.32 5 | xbeanVersion=4.17 6 | commonsCliVersion=1.4 7 | jacksonVersion=2.12.2 8 | jerseyVersion=2.29.1 9 | guava=29.0-jre 10 | noexception=1.5.1 11 | 12 | javaparserVersion=3.20.2 13 | junitVersion=4.13.2 14 | mockitoVersion=3.3.3 15 | junitJupiter=5.5.1 16 | testNG=7.1.0 17 | 18 | cukesVersion=1.2.6 19 | 20 | jiraRestVersion=5.2.2 21 | atlassianFugueVersion=4.7.2 22 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devexperts/switchboard/5bc8c7fcada6f5a35369632c19457b5785d32e89/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS="-Xmx64m" 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /integrations/build.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | subprojects { 9 | group 'com.devexperts.switchboard.integrations' 10 | 11 | apply plugin: 'com.github.johnrengelman.shadow' 12 | 13 | dependencies { 14 | compileOnly project(":api") 15 | compileOnly project(":core") 16 | 17 | compileOnly "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion" 18 | 19 | compileOnly "org.apache.logging.log4j:log4j-slf4j-impl:$apacheLog4jVersion" 20 | compileOnly "org.slf4j:slf4j-api:$slf4jVersion" 21 | 22 | testImplementation project(":api") 23 | testImplementation project(":core") 24 | testImplementation project(":utils") 25 | 26 | testImplementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" 27 | testImplementation "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion" 28 | 29 | testImplementation "org.apache.logging.log4j:log4j-slf4j-impl:$apacheLog4jVersion" 30 | testImplementation "org.slf4j:slf4j-api:$slf4jVersion" 31 | 32 | testImplementation "org.codehaus.groovy:groovy:$groovyVersion" 33 | testImplementation "org.mockito:mockito-core:$mockitoVersion" 34 | testImplementation "junit:junit:$junitVersion" 35 | } 36 | 37 | publishing { 38 | publications { 39 | shadow(MavenPublication) { publication -> 40 | project.shadow.component(publication) 41 | } 42 | } 43 | repositories { 44 | maven { 45 | name "qaauto" 46 | url "https://maven.in.devexperts.com/content/repositories/qa-auto${version.endsWith('-SNAPSHOT') ? '-snapshot' : ''}" 47 | } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /integrations/bytecodeparser/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | implementation "com.google.guava:guava:$guava" 3 | implementation "com.machinezoo.noexception:noexception:$noexception" 4 | testImplementation "org.testng:testng:$testNG" 5 | testImplementation "org.junit.jupiter:junit-jupiter:$junitJupiter" 6 | } 7 | 8 | publishing { 9 | publications { 10 | maven(MavenPublication) { 11 | from components.java 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /integrations/bytecodeparser/src/main/java/com/devexperts/switchboard/integrations/bytecodeparser/BytecodeParserIntegration.java: -------------------------------------------------------------------------------- 1 | package com.devexperts.switchboard.integrations.bytecodeparser; 2 | 3 | import com.devexperts.switchboard.impl.IntegrationImpl; 4 | 5 | /** 6 | * Integration for extracting tests from compiled classes via reflection 7 | */ 8 | public class BytecodeParserIntegration extends IntegrationImpl { 9 | private final BytecodeParserIntegrationFeatures features = new BytecodeParserIntegrationFeatures(); 10 | 11 | private BytecodeParserIntegration() {} 12 | 13 | public BytecodeParserIntegration(Builder builder) { 14 | super(builder); 15 | } 16 | 17 | @Override 18 | public BytecodeParserIntegrationFeatures getIntegrationFeatures() { 19 | return features; 20 | } 21 | 22 | public static BytecodeParserIntegration.Builder newBuilder() { 23 | return new BytecodeParserIntegration.Builder(); 24 | } 25 | 26 | public static class Builder extends IntegrationImpl.Builder { 27 | 28 | private Builder() {} 29 | 30 | @Override 31 | public BytecodeParserIntegration build() { 32 | return new BytecodeParserIntegration(this); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /integrations/bytecodeparser/src/main/java/com/devexperts/switchboard/integrations/bytecodeparser/BytecodeParserIntegrationFeatures.java: -------------------------------------------------------------------------------- 1 | package com.devexperts.switchboard.integrations.bytecodeparser; 2 | 3 | import com.devexperts.switchboard.api.IntegrationFeatures; 4 | import com.devexperts.switchboard.entities.Attributes; 5 | import com.devexperts.switchboard.entities.Test; 6 | import com.google.common.collect.ImmutableSet; 7 | import com.google.common.reflect.ClassPath; 8 | 9 | import java.io.File; 10 | import java.net.URL; 11 | import java.net.URLClassLoader; 12 | import java.util.function.Function; 13 | 14 | import static com.machinezoo.noexception.Exceptions.sneak; 15 | 16 | /** 17 | * Implementation of {@link IntegrationFeatures} providing access to {@link ClassPath} functionality 18 | */ 19 | public class BytecodeParserIntegrationFeatures implements IntegrationFeatures { 20 | public static final String LOCATION_PACKAGE_KEY = "package"; 21 | public static final String LOCATION_CLASS_KEY = "class"; 22 | public static final String LOCATION_METHOD_KEY = "method"; 23 | public static final Function TEST_TO_RUNNABLE_STRING = test -> formatTestPath(test.getAttributes()); 24 | 25 | BytecodeParserIntegrationFeatures() {} 26 | 27 | public ImmutableSet parse(File file) { 28 | ImmutableSet allClasses = sneak().get(() -> ClassPath.from(new URLClassLoader(new URL[] {file.toURI().toURL()}, null)) 29 | .getAllClasses()); 30 | if (allClasses.isEmpty()) { 31 | throw new IllegalStateException("Parse result for '" + file.toString() + " is empty"); 32 | } 33 | return allClasses; 34 | } 35 | 36 | @Override 37 | public void close() {/*do nothing*/} 38 | 39 | public static String formatTestPath(Attributes attributes) { 40 | return String.format("%s.%s#%s", 41 | attributes.getSingleAttributeValue(Attributes.LOCATION_PROP, LOCATION_PACKAGE_KEY).orElse(""), 42 | attributes.getSingleAttributeValue(Attributes.LOCATION_PROP, LOCATION_CLASS_KEY).orElse(""), 43 | attributes.getSingleAttributeValue(Attributes.LOCATION_PROP, LOCATION_METHOD_KEY).orElse("")); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /integrations/bytecodeparser/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /integrations/bytecodeparser/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /integrations/bytecodeparser/src/test/resources/test_classes/junit.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devexperts/switchboard/5bc8c7fcada6f5a35369632c19457b5785d32e89/integrations/bytecodeparser/src/test/resources/test_classes/junit.jar -------------------------------------------------------------------------------- /integrations/bytecodeparser/src/test/resources/test_classes/jupiter.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devexperts/switchboard/5bc8c7fcada6f5a35369632c19457b5785d32e89/integrations/bytecodeparser/src/test/resources/test_classes/jupiter.jar -------------------------------------------------------------------------------- /integrations/bytecodeparser/src/test/resources/test_classes/testng.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devexperts/switchboard/5bc8c7fcada6f5a35369632c19457b5785d32e89/integrations/bytecodeparser/src/test/resources/test_classes/testng.jar -------------------------------------------------------------------------------- /integrations/cukes/build.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | dependencies { 9 | implementation "info.cukes:cucumber-core:$cukesVersion" 10 | } -------------------------------------------------------------------------------- /integrations/cukes/src/main/java/com/devexperts/switchboard/integrations/cukes/CukesIntegration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.integrations.cukes; 9 | 10 | import com.devexperts.switchboard.impl.IntegrationImpl; 11 | 12 | /** 13 | * Implementation of {@link com.devexperts.switchboard.api.Integration} providing access to {@link cucumber.runtime.io} functionality 14 | * NB: Not compatible with Cucumber versions above 1.2.x. Use a separate integration for newer versions. 15 | */ 16 | public class CukesIntegration extends IntegrationImpl { 17 | private CukesIntegration() {} 18 | 19 | public CukesIntegration(Builder builder) { 20 | super(builder); 21 | } 22 | 23 | @Override 24 | public CukesIntegrationFeatures getIntegrationFeatures() { 25 | return new CukesIntegrationFeatures(); 26 | } 27 | 28 | public static CukesIntegration.Builder newBuilder() { 29 | return new CukesIntegration.Builder(); 30 | } 31 | 32 | public static class Builder extends IntegrationImpl.Builder { 33 | 34 | private Builder() {} 35 | 36 | @Override 37 | public CukesIntegration build() { 38 | return new CukesIntegration(this); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /integrations/cukes/src/main/java/com/devexperts/switchboard/integrations/cukes/CukesIntegrationFeatures.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.integrations.cukes; 9 | 10 | import com.devexperts.switchboard.api.IntegrationFeatures; 11 | import com.devexperts.switchboard.entities.Attributes; 12 | import com.devexperts.switchboard.entities.Test; 13 | import cucumber.runtime.io.MultiLoader; 14 | 15 | import java.util.Optional; 16 | import java.util.Set; 17 | import java.util.function.Function; 18 | 19 | /** 20 | * Implementation of {@link IntegrationFeatures} providing access to {@link cucumber.runtime.io} functionality 21 | * NB: Not compatible with Cucumber versions above 1.2.x. Use a separate integration for newer versions. 22 | */ 23 | public class CukesIntegrationFeatures implements IntegrationFeatures { 24 | public static final String LOCATION_LINES_KEY = "lines"; 25 | public static final String FEATURE_PATH_KEY = "path"; 26 | public static final Function TEST_TO_RUNNABLE_STRING = test -> { 27 | Attributes attributes = test.getAttributes(); 28 | Optional path = attributes.getSingleAttributeValue(Attributes.LOCATION_PROP, FEATURE_PATH_KEY); 29 | if (!path.isPresent()) { 30 | throw new IllegalStateException("Cucumber test path not specified"); 31 | } 32 | Optional> lines = attributes.getAttributeValue(Attributes.LOCATION_PROP, LOCATION_LINES_KEY); 33 | String linesPart = !lines.isPresent() || lines.get().isEmpty() ? "" : (":" + String.join(":", lines.get())); 34 | return path.get() + linesPart; 35 | }; 36 | 37 | private final MultiLoader loader = new MultiLoader(Thread.currentThread().getContextClassLoader()); 38 | 39 | CukesIntegrationFeatures() {} 40 | 41 | public MultiLoader getLoader() { 42 | return loader; 43 | } 44 | 45 | @Override 46 | public void close() {/*do nothing*/} 47 | } 48 | -------------------------------------------------------------------------------- /integrations/cukes/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /integrations/cukes/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /integrations/cukes/src/test/resources/test_classes/Mixed_feature_1.feature: -------------------------------------------------------------------------------- 1 | @USER#user2 2 | 3 | Feature: Mixed feature 4 | 5 | Background: 6 | Given Everything is ok 7 | 8 | @Regression 9 | Scenario: Scenario 1 10 | 11 | When I do something 12 | Then Everything is ok 13 | 14 | @Sanity 15 | Scenario Outline: Scenario outline 1 16 | 17 | When I do 18 | Then Everything is ok 19 | 20 | Examples: 21 | | action | 22 | | something | 23 | | something else | 24 | 25 | @Bat 26 | Scenario: Scenario 2 27 | 28 | When I do something else 29 | Then Everything is ok -------------------------------------------------------------------------------- /integrations/cukes/src/test/resources/test_classes/Multi_feature_1.feature: -------------------------------------------------------------------------------- 1 | @Regression 2 | @Sanity 3 | @USER#user1 4 | 5 | Feature: Multi scenario feature 6 | 7 | Background: 8 | Given Everything is ok 9 | 10 | @Another_tag1 11 | Scenario: Scenario 1 12 | 13 | When I do something 14 | Then Everything is ok 15 | 16 | @Bat 17 | Scenario: Scenario 2 18 | 19 | When I do something else 20 | Then Everything is ok -------------------------------------------------------------------------------- /integrations/cukes/src/test/resources/test_classes/Outline_feature_1.feature: -------------------------------------------------------------------------------- 1 | @Regression 2 | @Sanity 3 | @Bat 4 | @USER#user2 5 | 6 | Feature: Outline scenario feature 7 | 8 | Background: 9 | Given Everything is ok 10 | 11 | @Another_tag1 12 | Scenario Outline: Scenario 1 13 | 14 | When I do 15 | Then Everything is ok 16 | 17 | Examples: 18 | | action | 19 | | something | 20 | | something else | -------------------------------------------------------------------------------- /integrations/cukes/src/test/resources/test_classes/Single_feature_1.feature: -------------------------------------------------------------------------------- 1 | @Regression 2 | @Bat 3 | @USER#user1 4 | 5 | Feature: Single scenario feature 6 | 7 | Background: 8 | Given Everything is ok 9 | 10 | @Another_tag1 11 | Scenario: Scenario 1 12 | 13 | When I do something 14 | And I do something else 15 | Then Everything is ok -------------------------------------------------------------------------------- /integrations/cukes/src/test/resources/test_classes/pckg/Mixed_feature_2.feature: -------------------------------------------------------------------------------- 1 | @USER#user2 2 | 3 | Feature: Mixed feature 2 4 | 5 | Background: 6 | Given Everything is ok 7 | 8 | @Regression 9 | Scenario: Scenario 1 10 | 11 | When I do something 12 | Then Everything is ok 13 | 14 | @Sanity 15 | Scenario Outline: Scenario outline 1 16 | 17 | When I do 18 | Then Everything is ok 19 | 20 | Examples: 21 | | action | 22 | | something | 23 | | something else | 24 | 25 | @Bat 26 | Scenario: Scenario 2 27 | 28 | When I do something else 29 | Then Everything is ok -------------------------------------------------------------------------------- /integrations/cukes/src/test/resources/test_classes/pckg/Multi_feature_2.feature: -------------------------------------------------------------------------------- 1 | @Regression 2 | @Sanity 3 | @USER#user2 4 | 5 | Feature: Multi scenario feature 2 6 | 7 | Background: 8 | Given Everything is ok 9 | 10 | @Another_tag3 11 | Scenario: Scenario 1 12 | 13 | When I do something 14 | Then Everything is ok 15 | 16 | @Bat 17 | Scenario: Scenario 2 18 | 19 | When I do something else 20 | Then Everything is ok -------------------------------------------------------------------------------- /integrations/cukes/src/test/resources/test_classes/pckg/Outline_feature_2.feature: -------------------------------------------------------------------------------- 1 | @Regression 2 | @Sanity 3 | @Bat 4 | @USER#user3 5 | 6 | Feature: Outline scenario feature 2 7 | 8 | Background: 9 | Given Everything is ok 10 | 11 | @Another_tag2 12 | Scenario Outline: Scenario 1 13 | 14 | When I do 15 | Then Everything is ok 16 | 17 | Examples: 18 | | action | 19 | | something | 20 | | something else | -------------------------------------------------------------------------------- /integrations/cukes/src/test/resources/test_classes/pckg/Single_feature_2.feature: -------------------------------------------------------------------------------- 1 | @Regression 2 | @Bat 3 | @USER#user2 4 | 5 | Feature: Single scenario feature 2 6 | 7 | Background: 8 | Given Everything is ok 9 | 10 | @Another_tag2 11 | Scenario: Scenario 1 12 | 13 | When I do something 14 | And I do something else 15 | Then Everything is ok -------------------------------------------------------------------------------- /integrations/javaparser/build.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | dependencies { 9 | implementation "com.github.javaparser:javaparser-core:$javaparserVersion" 10 | } -------------------------------------------------------------------------------- /integrations/javaparser/src/main/java/com/devexperts/switchboard/integrations/javaparser/JavaParserIntegration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.integrations.javaparser; 9 | 10 | import com.devexperts.switchboard.impl.IntegrationImpl; 11 | 12 | /** 13 | * Integration utilizing {@link com.github.javaparser} functionality to process Java code, e.g. for extracting TestNG or JUnit tests 14 | */ 15 | public class JavaParserIntegration extends IntegrationImpl { 16 | private final JavaParserIntegrationFeatures features = new JavaParserIntegrationFeatures(); 17 | 18 | private JavaParserIntegration() {} 19 | 20 | public JavaParserIntegration(Builder builder) { 21 | super(builder); 22 | } 23 | 24 | @Override 25 | public JavaParserIntegrationFeatures getIntegrationFeatures() { 26 | return features; 27 | } 28 | 29 | public static JavaParserIntegration.Builder newBuilder() { 30 | return new JavaParserIntegration.Builder(); 31 | } 32 | 33 | public static class Builder extends IntegrationImpl.Builder { 34 | 35 | private Builder() {} 36 | 37 | @Override 38 | public JavaParserIntegration build() { 39 | return new JavaParserIntegration(this); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /integrations/javaparser/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /integrations/javaparser/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /integrations/javaparser/src/test/resources/test_classes/Annotations.java: -------------------------------------------------------------------------------- 1 | package com.devexperts.switchboard.integrations.javaparser; 2 | 3 | public class Annotations { 4 | public @interface MarkerAnnotation1 {} 5 | 6 | public @interface MarkerAnnotation2 {} 7 | 8 | public @interface ValueAnnotation1 { 9 | public String value(); 10 | } 11 | 12 | public @interface ValueAnnotation2 { 13 | public int value(); 14 | } 15 | 16 | public @interface MultiValueAnnotation { 17 | public String stringVal(); 18 | public int intVal() default 10; 19 | public String[] arrVal(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /integrations/javaparser/src/test/resources/test_classes/JUnitJiraTests.java: -------------------------------------------------------------------------------- 1 | package com.devexperts.switchboard.integrations.test.example; 2 | 3 | import org.junit.Test; 4 | 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Target; 7 | 8 | @TestCase(severity = "Functional", components = "Component1", tradingType = "None") 9 | public class JUnitJiraTests { 10 | 11 | @Test 12 | @TestCase( 13 | summary = "This is some test summary", 14 | labels = {"One", "Two", "Three"} 15 | ) 16 | public void test1() { 17 | // STEP: do something 1 18 | assert true; 19 | // STEP: do something else 1 20 | assert true; 21 | // STEP: and another thing 1 22 | assert true; 23 | } 24 | 25 | @Test 26 | @TestCase( 27 | summary = "This is another test summary", 28 | labels = {"Four"}, 29 | severity = "Showstopper" 30 | ) 31 | public void test2() { 32 | // STEP: do something 2 33 | assert true; 34 | // STEP: do something else 2 35 | // STEP: and another thing 2 36 | assert true; 37 | } 38 | 39 | @Test 40 | @TestCase( 41 | summary = "Guess what? Another test summary!", 42 | labels = {"Five", "Six"}, 43 | severity = "Minor functional" 44 | ) 45 | public void test3() { 46 | assert true; 47 | } 48 | 49 | @Target({ElementType.TYPE, ElementType.METHOD}) 50 | public @interface TestCase { 51 | String summary() default ""; 52 | 53 | String severity() default ""; 54 | 55 | String[] components() default {}; 56 | 57 | String[] labels() default {}; 58 | 59 | String tradingType() default ""; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /integrations/javaparser/src/test/resources/test_classes/TestCase.java: -------------------------------------------------------------------------------- 1 | package com.devexperts.switchboard.integrations.test.example; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Target; 5 | 6 | @Target({ElementType.TYPE, ElementType.METHOD}) 7 | public @interface TestCase { 8 | String summary() default ""; 9 | 10 | String severity() default ""; 11 | 12 | String[] components() default {}; 13 | 14 | String[] labels() default {}; 15 | 16 | String tradingType() default ""; 17 | } 18 | -------------------------------------------------------------------------------- /integrations/javaparser/src/test/resources/test_classes/typed/junit/JUnitTests.java: -------------------------------------------------------------------------------- 1 | package com.devexperts.switchboard.integrations.javaparser.junit; 2 | 3 | import com.devexperts.switchboard.integrations.javaparser.Annotations; 4 | import com.devexperts.switchboard.integrations.javaparser.Annotations.MarkerAnnotation1; 5 | import com.devexperts.switchboard.integrations.javaparser.Annotations.MarkerAnnotation2; 6 | import com.devexperts.switchboard.integrations.javaparser.Annotations.MultiValueAnnotation; 7 | import com.devexperts.switchboard.integrations.javaparser.Annotations.ValueAnnotation1; 8 | import com.devexperts.switchboard.integrations.javaparser.Annotations.ValueAnnotation2; 9 | import org.junit.Test; 10 | 11 | @Annotations.ValueAnnotation1("common") 12 | @ValueAnnotation2(0) 13 | public class JUnitTests { 14 | 15 | @Test 16 | @MarkerAnnotation1 17 | @ValueAnnotation1("qwerty") 18 | @MultiValueAnnotation(stringVal = "multival", intVal = 3, arrVal = {"a1", "a2", "a3"}) 19 | public void test1() { 20 | // STEP: do something 1 21 | assert true; 22 | // STEP: do something else 1 23 | assert true; 24 | // STEP: and another thing 1 25 | assert true; 26 | } 27 | 28 | @Test 29 | @MarkerAnnotation2 30 | @ValueAnnotation2(42) 31 | public void test2() { 32 | // STEP: do something 2 33 | assert true; 34 | // STEP: do something else 2 35 | // STEP: and another thing 2 36 | assert true; 37 | } 38 | 39 | @Test 40 | @MarkerAnnotation1 41 | @MarkerAnnotation2 42 | @ValueAnnotation1("abc") 43 | @ValueAnnotation2(7) 44 | @MultiValueAnnotation(stringVal = "multivalX", intVal = 2, arrVal = {"a1", "a2"}) 45 | public void test3() { 46 | // STEP: do something 3 47 | // STEP: do something else 3 48 | // STEP: and another thing 3 49 | assert true; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /integrations/javaparser/src/test/resources/test_classes/typed/junit/pckg/JUnitTests1.java: -------------------------------------------------------------------------------- 1 | package com.devexperts.switchboard.integrations.javaparser.junit.pckg; 2 | 3 | import com.devexperts.switchboard.integrations.javaparser.Annotations; 4 | import org.junit.Test; 5 | 6 | public class JUnitTests1 { 7 | 8 | @Test 9 | @Annotations.MarkerAnnotation1 10 | @Annotations.ValueAnnotation1("qwerty") 11 | @Annotations.MultiValueAnnotation(stringVal = "multival", intVal = 3, arrVal = {"a1", "a2", "a3"}) 12 | public void test1() { 13 | assert true; 14 | } 15 | 16 | @Test 17 | @Annotations.MarkerAnnotation2 18 | @Annotations.ValueAnnotation2(42) 19 | public void test2() { 20 | assert true; 21 | } 22 | 23 | @Test 24 | @Annotations.MarkerAnnotation1 25 | @Annotations.MarkerAnnotation2 26 | @Annotations.ValueAnnotation1("abc") 27 | @Annotations.ValueAnnotation2(7) 28 | @Annotations.MultiValueAnnotation(stringVal = "multivalX", intVal = 2, arrVal = {"a1", "a2"}) 29 | public void test3() { 30 | assert true; 31 | } 32 | } -------------------------------------------------------------------------------- /integrations/javaparser/src/test/resources/test_classes/typed/junit/pckg/JUnitTests2.java: -------------------------------------------------------------------------------- 1 | package com.devexperts.switchboard.integrations.javaparser.junit.pckg; 2 | 3 | import com.devexperts.switchboard.integrations.javaparser.Annotations; 4 | import org.junit.Test; 5 | 6 | public class JUnitTests2 { 7 | 8 | @Test 9 | @Annotations.MarkerAnnotation1 10 | @Annotations.ValueAnnotation1("qwerty") 11 | @Annotations.MultiValueAnnotation(stringVal = "multival", intVal = 3, arrVal = {"a1", "a2", "a3"}) 12 | public void test1() { 13 | assert true; 14 | } 15 | 16 | @Test 17 | @Annotations.MarkerAnnotation2 18 | @Annotations.ValueAnnotation2(42) 19 | public void test2() { 20 | assert true; 21 | } 22 | 23 | @Test 24 | @Annotations.MarkerAnnotation1 25 | @Annotations.MarkerAnnotation2 26 | @Annotations.ValueAnnotation1("abc") 27 | @Annotations.ValueAnnotation2(7) 28 | @Annotations.MultiValueAnnotation(stringVal = "multivalX", intVal = 2, arrVal = {"a1", "a2"}) 29 | public void test3() { 30 | assert true; 31 | } 32 | } -------------------------------------------------------------------------------- /integrations/javaparser/src/test/resources/test_classes/typed/jupiter/JupiterTests.java: -------------------------------------------------------------------------------- 1 | package com.devexperts.switchboard.integrations.javaparser.jupiter; 2 | 3 | import com.devexperts.switchboard.integrations.javaparser.Annotations; 4 | import com.devexperts.switchboard.integrations.javaparser.Annotations.MarkerAnnotation1; 5 | import com.devexperts.switchboard.integrations.javaparser.Annotations.MarkerAnnotation2; 6 | import com.devexperts.switchboard.integrations.javaparser.Annotations.MultiValueAnnotation; 7 | import com.devexperts.switchboard.integrations.javaparser.Annotations.ValueAnnotation1; 8 | import com.devexperts.switchboard.integrations.javaparser.Annotations.ValueAnnotation2; 9 | import org.junit.jupiter.api.Test; 10 | 11 | @Annotations.ValueAnnotation1("common") 12 | @ValueAnnotation2(0) 13 | public class JupiterTests { 14 | 15 | @Test 16 | @MarkerAnnotation1 17 | @ValueAnnotation1("qwerty") 18 | @MultiValueAnnotation(stringVal = "multival", intVal = 3, arrVal = {"a1", "a2", "a3"}) 19 | public void test1() { 20 | assert true; 21 | } 22 | 23 | @Test 24 | @MarkerAnnotation2 25 | @ValueAnnotation2(42) 26 | public void test2() { 27 | assert true; 28 | } 29 | 30 | @Test 31 | @MarkerAnnotation1 32 | @MarkerAnnotation2 33 | @ValueAnnotation1("abc") 34 | @ValueAnnotation2(7) 35 | @MultiValueAnnotation(stringVal = "multivalX", intVal = 2, arrVal = {"a1", "a2"}) 36 | public void test3() { 37 | assert true; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /integrations/javaparser/src/test/resources/test_classes/typed/jupiter/pckg/JupiterTests1.java: -------------------------------------------------------------------------------- 1 | package com.devexperts.switchboard.integrations.javaparser.jupiter.pckg; 2 | 3 | import com.devexperts.switchboard.integrations.javaparser.Annotations; 4 | import org.junit.jupiter.api.Test; 5 | 6 | public class JupiterTests1 { 7 | 8 | @Test 9 | @Annotations.MarkerAnnotation1 10 | @Annotations.ValueAnnotation1("qwerty") 11 | @Annotations.MultiValueAnnotation(stringVal = "multival", intVal = 3, arrVal = {"a1", "a2", "a3"}) 12 | public void test1() { 13 | assert true; 14 | } 15 | 16 | @Test 17 | @Annotations.MarkerAnnotation2 18 | @Annotations.ValueAnnotation2(42) 19 | public void test2() { 20 | assert true; 21 | } 22 | 23 | @Test 24 | @Annotations.MarkerAnnotation1 25 | @Annotations.MarkerAnnotation2 26 | @Annotations.ValueAnnotation1("abc") 27 | @Annotations.ValueAnnotation2(7) 28 | @Annotations.MultiValueAnnotation(stringVal = "multivalX", intVal = 2, arrVal = {"a1", "a2"}) 29 | public void test3() { 30 | assert true; 31 | } 32 | } -------------------------------------------------------------------------------- /integrations/javaparser/src/test/resources/test_classes/typed/jupiter/pckg/JupiterTests2.java: -------------------------------------------------------------------------------- 1 | package com.devexperts.switchboard.integrations.javaparser.jupiter.pckg; 2 | 3 | import com.devexperts.switchboard.integrations.javaparser.Annotations; 4 | import org.junit.jupiter.api.Test; 5 | 6 | public class JupiterTests2 { 7 | 8 | @Test 9 | @Annotations.MarkerAnnotation1 10 | @Annotations.ValueAnnotation1("qwerty") 11 | @Annotations.MultiValueAnnotation(stringVal = "multival", intVal = 3, arrVal = {"a1", "a2", "a3"}) 12 | public void test1() { 13 | assert true; 14 | } 15 | 16 | @Test 17 | @Annotations.MarkerAnnotation2 18 | @Annotations.ValueAnnotation2(42) 19 | public void test2() { 20 | assert true; 21 | } 22 | 23 | @Test 24 | @Annotations.MarkerAnnotation1 25 | @Annotations.MarkerAnnotation2 26 | @Annotations.ValueAnnotation1("abc") 27 | @Annotations.ValueAnnotation2(7) 28 | @Annotations.MultiValueAnnotation(stringVal = "multivalX", intVal = 2, arrVal = {"a1", "a2"}) 29 | public void test3() { 30 | assert true; 31 | } 32 | } -------------------------------------------------------------------------------- /integrations/javaparser/src/test/resources/test_classes/typed/testng/TestNgTests.java: -------------------------------------------------------------------------------- 1 | package com.devexperts.switchboard.integrations.javaparser.testng; 2 | 3 | import com.devexperts.switchboard.integrations.javaparser.Annotations; 4 | import com.devexperts.switchboard.integrations.javaparser.Annotations.MarkerAnnotation1; 5 | import com.devexperts.switchboard.integrations.javaparser.Annotations.MarkerAnnotation2; 6 | import com.devexperts.switchboard.integrations.javaparser.Annotations.MultiValueAnnotation; 7 | import com.devexperts.switchboard.integrations.javaparser.Annotations.ValueAnnotation1; 8 | import com.devexperts.switchboard.integrations.javaparser.Annotations.ValueAnnotation2; 9 | import org.testng.annotations.Test; 10 | 11 | @Annotations.ValueAnnotation1("common") 12 | @ValueAnnotation2(0) 13 | public class TestNgTests { 14 | 15 | @Test 16 | @MarkerAnnotation1 17 | @ValueAnnotation1("qwerty") 18 | @MultiValueAnnotation(stringVal = "multival", intVal = 3, arrVal = {"a1", "a2", "a3"}) 19 | public void test1() { 20 | assert true; 21 | } 22 | 23 | @Test 24 | @MarkerAnnotation2 25 | @ValueAnnotation2(42) 26 | public void test2() { 27 | assert true; 28 | } 29 | 30 | @Test 31 | @MarkerAnnotation1 32 | @MarkerAnnotation2 33 | @ValueAnnotation1("abc") 34 | @ValueAnnotation2(7) 35 | @MultiValueAnnotation(stringVal = "multivalX", intVal = 2, arrVal = {"a1", "a2"}) 36 | public void test3() { 37 | assert true; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /integrations/javaparser/src/test/resources/test_classes/typed/testng/pckg/TestNgTests1.java: -------------------------------------------------------------------------------- 1 | package com.devexperts.switchboard.integrations.javaparser.testng.pckg; 2 | 3 | import com.devexperts.switchboard.integrations.javaparser.Annotations; 4 | import org.testng.annotations.Test; 5 | 6 | public class TestNgTests1 { 7 | 8 | @Test 9 | @Annotations.MarkerAnnotation1 10 | @Annotations.ValueAnnotation1("qwerty") 11 | @Annotations.MultiValueAnnotation(stringVal = "multival", intVal = 3, arrVal = {"a1", "a2", "a3"}) 12 | public void test1() { 13 | assert true; 14 | } 15 | 16 | @Test 17 | @Annotations.MarkerAnnotation2 18 | @Annotations.ValueAnnotation2(42) 19 | public void test2() { 20 | assert true; 21 | } 22 | 23 | @Test 24 | @Annotations.MarkerAnnotation1 25 | @Annotations.MarkerAnnotation2 26 | @Annotations.ValueAnnotation1("abc") 27 | @Annotations.ValueAnnotation2(7) 28 | @Annotations.MultiValueAnnotation(stringVal = "multivalX", intVal = 2, arrVal = {"a1", "a2"}) 29 | public void test3() { 30 | assert true; 31 | } 32 | } -------------------------------------------------------------------------------- /integrations/javaparser/src/test/resources/test_classes/typed/testng/pckg/TestNgTests2.java: -------------------------------------------------------------------------------- 1 | package com.devexperts.switchboard.integrations.javaparser.testng.pckg; 2 | 3 | import com.devexperts.switchboard.integrations.javaparser.Annotations; 4 | import org.testng.annotations.Test; 5 | 6 | public class TestNgTests2 { 7 | 8 | @Test 9 | @Annotations.MarkerAnnotation1 10 | @Annotations.ValueAnnotation1("qwerty") 11 | @Annotations.MultiValueAnnotation(stringVal = "multival", intVal = 3, arrVal = {"a1", "a2", "a3"}) 12 | public void test1() { 13 | assert true; 14 | } 15 | 16 | @Test 17 | @Annotations.MarkerAnnotation2 18 | @Annotations.ValueAnnotation2(42) 19 | public void test2() { 20 | assert true; 21 | } 22 | 23 | @Test 24 | @Annotations.MarkerAnnotation1 25 | @Annotations.MarkerAnnotation2 26 | @Annotations.ValueAnnotation1("abc") 27 | @Annotations.ValueAnnotation2(7) 28 | @Annotations.MultiValueAnnotation(stringVal = "multivalX", intVal = 2, arrVal = {"a1", "a2"}) 29 | public void test3() { 30 | assert true; 31 | } 32 | } -------------------------------------------------------------------------------- /integrations/jira/build.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | repositories { 9 | maven { 10 | url 'https://maven.atlassian.com/repository/public' 11 | } 12 | } 13 | 14 | dependencies { 15 | implementation("com.atlassian.jira:jira-rest-java-client-core:$jiraRestVersion") 16 | implementation("io.atlassian.fugue:fugue:$atlassianFugueVersion") 17 | } -------------------------------------------------------------------------------- /integrations/jira/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /integrations/jira/src/test/resources/JiraIntegration.json: -------------------------------------------------------------------------------- 1 | { 2 | "@class": "com.devexperts.switchboard.integrations.jira.JiraIntegration", 3 | "identifier": "Jira_integration_1", 4 | "runnable": false, 5 | "testExtractors": [], 6 | "testProcessors": [], 7 | "testFilters": [ 8 | { 9 | "@class": "com.devexperts.switchboard.integrations.jira.JqlQueryTestFilter", 10 | "identifier": "TestJqlQueryTestFilter_1", 11 | "jqlQuery": "query1", 12 | "attributeKey": "jiraId", 13 | "attributeValueKey": "" 14 | }, 15 | { 16 | "@class": "com.devexperts.switchboard.integrations.jira.JqlQueryTestFilter", 17 | "identifier": "TestJqlQueryTestFilter_2", 18 | "jqlQuery": "query2", 19 | "attributeKey": "jiraId", 20 | "attributeValueKey": "" 21 | } 22 | ], 23 | "testSplitters": [], 24 | "testRunConsumers": [], 25 | "uri": "https://jira.somwhere.elsewhere.com/", 26 | "login": "user", 27 | "password": "password" 28 | } -------------------------------------------------------------------------------- /integrations/jira/src/test/resources/SampleTests.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "@class": "com.devexperts.switchboard.entities.Test", 4 | "identifier": "com.devexperts.switchboard.integrations.test.example.JUnitJiraTests#test1", 5 | "attributes": { 6 | "attributes": { 7 | "comments": { 8 | "": [ 9 | " STEP: do something 1", 10 | " STEP: do something else 1", 11 | " STEP: and another thing 1" 12 | ] 13 | }, 14 | "TestCase": { 15 | "summary": [ 16 | "This is some test summary" 17 | ], 18 | "components": [ 19 | "Component1" 20 | ], 21 | "labels": [ 22 | "One", 23 | "Two", 24 | "Three" 25 | ] 26 | }, 27 | "Test": {}, 28 | "location": { 29 | "package": [ 30 | "com.devexperts.switchboard.integrations.test.example" 31 | ], 32 | "method": [ 33 | "test1" 34 | ], 35 | "class": [ 36 | "JUnitJiraTests" 37 | ] 38 | } 39 | } 40 | } 41 | }, 42 | { 43 | "@class": "com.devexperts.switchboard.entities.Test", 44 | "identifier": "com.devexperts.switchboard.integrations.test.example.JUnitJiraTests#test2", 45 | "attributes": { 46 | "attributes": { 47 | "comments": { 48 | "": [ 49 | " STEP: do something else 2", 50 | " STEP: do something 2", 51 | " STEP: and another thing 2" 52 | ] 53 | }, 54 | "TestCase": { 55 | "summary": [ 56 | "This is another test summary" 57 | ], 58 | "components": [ 59 | "Component2" 60 | ], 61 | "severity": [ 62 | "Showstopper" 63 | ], 64 | "labels": [ 65 | "Four" 66 | ] 67 | }, 68 | "Test": {}, 69 | "location": { 70 | "package": [ 71 | "com.devexperts.switchboard.integrations.test.example" 72 | ], 73 | "method": [ 74 | "test2" 75 | ], 76 | "class": [ 77 | "JUnitJiraTests" 78 | ] 79 | } 80 | } 81 | } 82 | }, 83 | { 84 | "@class": "com.devexperts.switchboard.entities.Test", 85 | "identifier": "com.devexperts.switchboard.integrations.test.example.JUnitJiraTests#test3", 86 | "attributes": { 87 | "attributes": { 88 | "TestCase": { 89 | "summary": [ 90 | "Guess what? Another test summary!" 91 | ], 92 | "severity": [ 93 | "Minor functional" 94 | ], 95 | "labels": [ 96 | "Five", 97 | "Six" 98 | ] 99 | }, 100 | "Test": {}, 101 | "location": { 102 | "package": [ 103 | "com.devexperts.switchboard.integrations.test.example" 104 | ], 105 | "method": [ 106 | "test3" 107 | ], 108 | "class": [ 109 | "JUnitJiraTests" 110 | ] 111 | } 112 | } 113 | } 114 | } 115 | ] -------------------------------------------------------------------------------- /integrations/jira/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /integrations/teamcity/build.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | repositories { 9 | jcenter() 10 | } 11 | 12 | dependencies { 13 | implementation "io.swagger:swagger-annotations:1.5.17" 14 | 15 | implementation "org.glassfish.jersey.core:jersey-client:$jerseyVersion" 16 | implementation "org.glassfish.jersey.inject:jersey-hk2:$jerseyVersion" 17 | implementation "org.glassfish.jersey.media:jersey-media-multipart:$jerseyVersion" 18 | implementation "org.glassfish.jersey.media:jersey-media-json-jackson:$jerseyVersion" 19 | implementation "org.glassfish.jersey.media:jersey-media-jaxb:$jerseyVersion" 20 | implementation "com.fasterxml.jackson.core:jackson-core:$jacksonVersion" 21 | implementation "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion" 22 | implementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" 23 | implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jacksonVersion" 24 | implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:2.6.4" 25 | implementation "com.brsanthu:migbase64:2.2" 26 | implementation "org.glassfish.jaxb:jaxb-runtime:2.3.3" 27 | implementation "jakarta.xml.bind:jakarta.xml.bind-api:2.3.2" 28 | } -------------------------------------------------------------------------------- /integrations/teamcity/src/main/java/com/devexperts/switchboard/integrations/teamcity/AgentParamMatchType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.integrations.teamcity; 9 | 10 | /** 11 | * This enum contains the match type values available in TeamCity agent search by agent property and value 12 | */ 13 | public enum AgentParamMatchType { 14 | EXISTS("exists"), 15 | NOT_EXISTS("not-exists"), 16 | EQUALS("equals"), 17 | DOES_NOT_EQUAL("does-not-equal"), 18 | STARTS_WITH("starts-with"), 19 | CONTAINS("contains"), 20 | DOES_NOT_CONTAIN("does-not-contain"), 21 | ENDS_WITH("ends-with"), 22 | MATCHES("matches"), 23 | DOES_NOT_MATCH("does-not-match"), 24 | MORE_THAN("more-than"), 25 | NO_MORE_THAN("no-more-than"), 26 | LESS_THAN("less-than"), 27 | NO_LESS_THAN("no-less-than"), 28 | VER_MORE_THAN("ver-more-than"), 29 | VER_NO_MORE_THAN("ver-no-more-than"), 30 | VER_LESS_THAN("ver-less-than"), 31 | VER_NO_LESS_THAN("ver-no-less-than"); 32 | 33 | private final String value; 34 | 35 | AgentParamMatchType(String value) { 36 | this.value = value; 37 | } 38 | 39 | /** 40 | * @return the TeamCity match type value 41 | */ 42 | public String value() { 43 | return value; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /integrations/teamcity/src/main/java/com/devexperts/switchboard/integrations/teamcity/AgentRequirement.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.integrations.teamcity; 9 | 10 | import com.devexperts.switchboard.entities.TestRun; 11 | import com.devexperts.switchboard.entities.valuesupplier.TestRunValuesExtractor; 12 | import com.fasterxml.jackson.annotation.JsonProperty; 13 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 14 | 15 | import java.util.Objects; 16 | 17 | /** 18 | * This class represent a single field requirement to TeamCity Agent 19 | */ 20 | @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 21 | public class AgentRequirement { 22 | @JsonProperty(required = true) 23 | private TestRunValuesExtractor valueSupplier; 24 | @JsonProperty(required = true) 25 | private String agentParamName; 26 | @JsonProperty(required = true) 27 | private AgentParamMatchType agentParamMatchType; 28 | 29 | private AgentRequirement() {} 30 | 31 | public AgentRequirement(TestRunValuesExtractor valueSupplier, String agentParamName, AgentParamMatchType agentParamMatchType) { 32 | this.valueSupplier = valueSupplier; 33 | this.agentParamName = agentParamName; 34 | this.agentParamMatchType = agentParamMatchType; 35 | } 36 | 37 | public String getAgentRequirement(TestRun tr) { 38 | String agentParamValue = valueSupplier.getRunValue(tr); 39 | if (agentParamValue == null) { 40 | return ""; 41 | } 42 | return String.format(",parameter:(name:%s,value:%s,matchType:%s)", agentParamName, agentParamValue, agentParamMatchType.value()); 43 | } 44 | 45 | @Override 46 | public boolean equals(Object o) { 47 | if (this == o) return true; 48 | if (o == null || getClass() != o.getClass()) return false; 49 | AgentRequirement that = (AgentRequirement) o; 50 | return Objects.equals(valueSupplier, that.valueSupplier) && 51 | Objects.equals(agentParamName, that.agentParamName) && 52 | agentParamMatchType == that.agentParamMatchType; 53 | } 54 | 55 | @Override 56 | public int hashCode() { 57 | return Objects.hash(valueSupplier, agentParamName, agentParamMatchType); 58 | } 59 | 60 | @Override 61 | public String toString() { 62 | return getClass().getSimpleName() + "{" + 63 | "valueHolder=" + valueSupplier + 64 | ", agentParamName='" + agentParamName + '\'' + 65 | ", agentParamMatchType=" + agentParamMatchType + 66 | '}'; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /integrations/teamcity/src/main/java/com/devexperts/switchboard/integrations/teamcity/TeamCityIntegration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.integrations.teamcity; 9 | 10 | import com.devexperts.switchboard.impl.IntegrationImpl; 11 | import com.devexperts.switchboard.utils.Arguments; 12 | import com.fasterxml.jackson.annotation.JsonProperty; 13 | 14 | /** 15 | * Integration providing to TeamCity functionality utilizing generated API 16 | */ 17 | public class TeamCityIntegration extends IntegrationImpl { 18 | @JsonProperty(required = true) 19 | private String basePath; 20 | @JsonProperty(required = true) 21 | private String login; 22 | @JsonProperty(required = true) 23 | private String password; 24 | 25 | private TeamCityIntegrationFeatures features; 26 | 27 | private TeamCityIntegration() {} 28 | 29 | public TeamCityIntegration(Builder builder) { 30 | super(builder); 31 | this.basePath = builder.basePath; 32 | this.login = builder.login; 33 | this.password = builder.password; 34 | } 35 | 36 | @Override 37 | public void init() { 38 | this.features = new TeamCityIntegrationFeatures( 39 | Arguments.checkNotNull(basePath, "Teamcity server base path is not specified"), 40 | Arguments.checkNotBlank(login, "Teamcity user login is not specified"), 41 | Arguments.checkNotBlank(password, "Teamcity user password is not specified") 42 | ); 43 | super.init(); 44 | } 45 | 46 | @Override 47 | public TeamCityIntegrationFeatures getIntegrationFeatures() { 48 | return features; 49 | } 50 | 51 | public static TeamCityIntegration.Builder newBuilder() { 52 | return new TeamCityIntegration.Builder(); 53 | } 54 | 55 | public static class Builder extends IntegrationImpl.Builder { 56 | private String basePath; 57 | private String login; 58 | private String password; 59 | 60 | private Builder() {} 61 | 62 | public Builder basePath(String val) { 63 | this.basePath = val; 64 | return this; 65 | } 66 | 67 | public Builder login(String val) { 68 | this.login = val; 69 | return this; 70 | } 71 | 72 | public Builder password(String val) { 73 | this.password = val; 74 | return this; 75 | } 76 | 77 | @Override 78 | public TeamCityIntegration build() { 79 | return new TeamCityIntegration(this); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /integrations/teamcity/src/main/java/com/devexperts/switchboard/integrations/teamcity/TeamCityIntegrationFeatures.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.integrations.teamcity; 9 | 10 | import com.devexperts.switchboard.api.IntegrationFeatures; 11 | import com.devexperts.switchboard.integrations.teamcity.swagger.codegen.api.AgentApi; 12 | import com.devexperts.switchboard.integrations.teamcity.swagger.codegen.api.BuildQueueApi; 13 | import com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker.ApiClient; 14 | import com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker.ApiException; 15 | import com.devexperts.switchboard.integrations.teamcity.swagger.codegen.model.AgentPool; 16 | import com.devexperts.switchboard.integrations.teamcity.swagger.codegen.model.Build; 17 | 18 | public class TeamCityIntegrationFeatures implements IntegrationFeatures { 19 | private final ApiClient apiClient; 20 | private final AgentApi agentApi; 21 | private final BuildQueueApi buildQueueApi; 22 | 23 | TeamCityIntegrationFeatures(String basePath, String login, String password) { 24 | this.apiClient = new ApiClient(basePath, login, password); 25 | this.agentApi = new AgentApi(apiClient); 26 | this.buildQueueApi = new BuildQueueApi(apiClient); 27 | } 28 | 29 | public AgentPool getAgentPool(String agentLocator, String fields) { 30 | try { 31 | return agentApi.getAgentPool(agentLocator, fields); 32 | } catch (ApiException e) { 33 | throw new RuntimeException("Failed to get agent pool with agentLocator '" + agentLocator + "', fields: " + fields, e); 34 | } 35 | } 36 | 37 | public Build queueNewBuild(Build body, Boolean moveToTop) { 38 | try { 39 | return buildQueueApi.queueNewBuild(body, moveToTop); 40 | } catch (ApiException e) { 41 | throw new RuntimeException("Failed to queue new Build " + body, e); 42 | } 43 | } 44 | 45 | @Override 46 | public void close() { 47 | apiClient.getHttpClient().close(); 48 | } 49 | } -------------------------------------------------------------------------------- /integrations/teamcity/src/main/java/com/devexperts/switchboard/integrations/teamcity/swagger/codegen/invoker/ApiException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * TeamCity REST API 3 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 4 | * 5 | * OpenAPI spec version: 2018.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker; 15 | 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | @javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-01T01:12:43.660+03:00") 20 | public class ApiException extends Exception { 21 | private int code = 0; 22 | private Map> responseHeaders = null; 23 | private String responseBody = null; 24 | 25 | public ApiException() {} 26 | 27 | public ApiException(Throwable throwable) { 28 | super(throwable); 29 | } 30 | 31 | public ApiException(String message) { 32 | super(message); 33 | } 34 | 35 | public ApiException(String message, Throwable throwable, int code, Map> responseHeaders, String responseBody) { 36 | super(message, throwable); 37 | this.code = code; 38 | this.responseHeaders = responseHeaders; 39 | this.responseBody = responseBody; 40 | } 41 | 42 | public ApiException(String message, int code, Map> responseHeaders, String responseBody) { 43 | this(message, (Throwable) null, code, responseHeaders, responseBody); 44 | } 45 | 46 | public ApiException(String message, Throwable throwable, int code, Map> responseHeaders) { 47 | this(message, throwable, code, responseHeaders, null); 48 | } 49 | 50 | public ApiException(int code, Map> responseHeaders, String responseBody) { 51 | this((String) null, (Throwable) null, code, responseHeaders, responseBody); 52 | } 53 | 54 | public ApiException(int code, String message) { 55 | super(message); 56 | this.code = code; 57 | } 58 | 59 | public ApiException(int code, String message, Map> responseHeaders, String responseBody) { 60 | this(code, message); 61 | this.responseHeaders = responseHeaders; 62 | this.responseBody = responseBody; 63 | } 64 | 65 | /** 66 | * Get the HTTP status code. 67 | * 68 | * @return HTTP status code 69 | */ 70 | public int getCode() { 71 | return code; 72 | } 73 | 74 | /** 75 | * Get the HTTP response headers. 76 | * 77 | * @return A map of list of string 78 | */ 79 | public Map> getResponseHeaders() { 80 | return responseHeaders; 81 | } 82 | 83 | /** 84 | * Get the HTTP response body. 85 | * 86 | * @return Response body in the form of string 87 | */ 88 | public String getResponseBody() { 89 | return responseBody; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /integrations/teamcity/src/main/java/com/devexperts/switchboard/integrations/teamcity/swagger/codegen/invoker/ApiResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * TeamCity REST API 3 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 4 | * 5 | * OpenAPI spec version: 2018.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker; 15 | 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | /** 20 | * API response returned by API call. 21 | * 22 | * @param The type of data that is deserialized from response body 23 | */ 24 | public class ApiResponse { 25 | private final int statusCode; 26 | private final Map> headers; 27 | private final T data; 28 | 29 | /** 30 | * @param statusCode The status code of HTTP response 31 | * @param headers The headers of HTTP response 32 | */ 33 | public ApiResponse(int statusCode, Map> headers) { 34 | this(statusCode, headers, null); 35 | } 36 | 37 | /** 38 | * @param statusCode The status code of HTTP response 39 | * @param headers The headers of HTTP response 40 | * @param data The object deserialized from response bod 41 | */ 42 | public ApiResponse(int statusCode, Map> headers, T data) { 43 | this.statusCode = statusCode; 44 | this.headers = headers; 45 | this.data = data; 46 | } 47 | 48 | public int getStatusCode() { 49 | return statusCode; 50 | } 51 | 52 | public Map> getHeaders() { 53 | return headers; 54 | } 55 | 56 | public T getData() { 57 | return data; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /integrations/teamcity/src/main/java/com/devexperts/switchboard/integrations/teamcity/swagger/codegen/invoker/Configuration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * TeamCity REST API 3 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 4 | * 5 | * OpenAPI spec version: 2018.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker; 15 | 16 | @javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-01T01:12:43.660+03:00") 17 | public class Configuration { 18 | private static ApiClient defaultApiClient = null; 19 | 20 | /** 21 | * Get the default API client, which would be used when creating API 22 | * instances without providing an API client. 23 | * 24 | * @return Default API client 25 | */ 26 | public static ApiClient getDefaultApiClient() { 27 | return defaultApiClient; 28 | } 29 | 30 | /** 31 | * Set the default API client, which would be used when creating API 32 | * instances without providing an API client. 33 | * 34 | * @param apiClient API client 35 | */ 36 | public static void setDefaultApiClient(ApiClient apiClient) { 37 | defaultApiClient = apiClient; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /integrations/teamcity/src/main/java/com/devexperts/switchboard/integrations/teamcity/swagger/codegen/invoker/JSON.java: -------------------------------------------------------------------------------- 1 | package com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.databind.DeserializationFeature; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import com.fasterxml.jackson.databind.SerializationFeature; 7 | import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; 8 | import org.threeten.bp.Instant; 9 | import org.threeten.bp.OffsetDateTime; 10 | import org.threeten.bp.ZonedDateTime; 11 | 12 | import javax.ws.rs.ext.ContextResolver; 13 | import java.text.DateFormat; 14 | 15 | @javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-01T01:12:43.660+03:00") 16 | public class JSON implements ContextResolver { 17 | private ObjectMapper mapper; 18 | 19 | public JSON() { 20 | mapper = new ObjectMapper(); 21 | mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 22 | mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 23 | mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); 24 | mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); 25 | mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); 26 | mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); 27 | mapper.setDateFormat(new RFC3339DateFormat()); 28 | ThreeTenModule module = new ThreeTenModule(); 29 | module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); 30 | module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); 31 | module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); 32 | mapper.registerModule(module); 33 | } 34 | 35 | /** 36 | * Set the date format for JSON (de)serialization with Date properties. 37 | * 38 | * @param dateFormat Date format 39 | */ 40 | public void setDateFormat(DateFormat dateFormat) { 41 | mapper.setDateFormat(dateFormat); 42 | } 43 | 44 | @Override 45 | public ObjectMapper getContext(Class type) { 46 | return mapper; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /integrations/teamcity/src/main/java/com/devexperts/switchboard/integrations/teamcity/swagger/codegen/invoker/Pair.java: -------------------------------------------------------------------------------- 1 | /* 2 | * TeamCity REST API 3 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 4 | * 5 | * OpenAPI spec version: 2018.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker; 15 | 16 | @javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-01T01:12:43.660+03:00") 17 | public class Pair { 18 | private String name = ""; 19 | private String value = ""; 20 | 21 | public Pair(String name, String value) { 22 | setName(name); 23 | setValue(value); 24 | } 25 | 26 | private void setName(String name) { 27 | if (!isValidString(name)) return; 28 | 29 | this.name = name; 30 | } 31 | 32 | private void setValue(String value) { 33 | if (!isValidString(value)) return; 34 | 35 | this.value = value; 36 | } 37 | 38 | public String getName() { 39 | return this.name; 40 | } 41 | 42 | public String getValue() { 43 | return this.value; 44 | } 45 | 46 | private boolean isValidString(String arg) { 47 | if (arg == null) return false; 48 | if (arg.trim().isEmpty()) return false; 49 | 50 | return true; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /integrations/teamcity/src/main/java/com/devexperts/switchboard/integrations/teamcity/swagger/codegen/invoker/RFC3339DateFormat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * TeamCity REST API 3 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 4 | * 5 | * OpenAPI spec version: 2018.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | package com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker; 14 | 15 | import com.fasterxml.jackson.databind.util.ISO8601DateFormat; 16 | import com.fasterxml.jackson.databind.util.ISO8601Utils; 17 | 18 | import java.text.FieldPosition; 19 | import java.util.Date; 20 | 21 | 22 | public class RFC3339DateFormat extends ISO8601DateFormat { 23 | 24 | // Same as ISO8601DateFormat but serializing milliseconds. 25 | @Override 26 | public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { 27 | String value = ISO8601Utils.format(date, true); 28 | toAppendTo.append(value); 29 | return toAppendTo; 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /integrations/teamcity/src/main/java/com/devexperts/switchboard/integrations/teamcity/swagger/codegen/invoker/StringUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * TeamCity REST API 3 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 4 | * 5 | * OpenAPI spec version: 2018.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker; 15 | 16 | @javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-01T01:12:43.660+03:00") 17 | public class StringUtil { 18 | /** 19 | * Check if the given array contains the given value (with case-insensitive comparison). 20 | * 21 | * @param array The array 22 | * @param value The value to search 23 | * @return true if the array contains the value 24 | */ 25 | public static boolean containsIgnoreCase(String[] array, String value) { 26 | for (String str : array) { 27 | if (value == null && str == null) return true; 28 | if (value != null && value.equalsIgnoreCase(str)) return true; 29 | } 30 | return false; 31 | } 32 | 33 | /** 34 | * Join an array of strings with the given separator. 35 | *

36 | * Note: This might be replaced by utility method from commons-lang or guava someday 37 | * if one of those libraries is added as dependency. 38 | *

39 | * 40 | * @param array The array of strings 41 | * @param separator The separator 42 | * @return the resulting string 43 | */ 44 | public static String join(String[] array, String separator) { 45 | int len = array.length; 46 | if (len == 0) return ""; 47 | 48 | StringBuilder out = new StringBuilder(); 49 | out.append(array[0]); 50 | for (int i = 1; i < len; i++) { 51 | out.append(separator).append(array[i]); 52 | } 53 | return out.toString(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /integrations/teamcity/src/main/java/com/devexperts/switchboard/integrations/teamcity/swagger/codegen/invoker/auth/ApiKeyAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * TeamCity REST API 3 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 4 | * 5 | * OpenAPI spec version: 2018.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker.auth; 15 | 16 | import com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker.Pair; 17 | 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | @javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-01T01:12:43.660+03:00") 22 | public class ApiKeyAuth implements Authentication { 23 | private final String location; 24 | private final String paramName; 25 | 26 | private String apiKey; 27 | private String apiKeyPrefix; 28 | 29 | public ApiKeyAuth(String location, String paramName) { 30 | this.location = location; 31 | this.paramName = paramName; 32 | } 33 | 34 | public String getLocation() { 35 | return location; 36 | } 37 | 38 | public String getParamName() { 39 | return paramName; 40 | } 41 | 42 | public String getApiKey() { 43 | return apiKey; 44 | } 45 | 46 | public void setApiKey(String apiKey) { 47 | this.apiKey = apiKey; 48 | } 49 | 50 | public String getApiKeyPrefix() { 51 | return apiKeyPrefix; 52 | } 53 | 54 | public void setApiKeyPrefix(String apiKeyPrefix) { 55 | this.apiKeyPrefix = apiKeyPrefix; 56 | } 57 | 58 | @Override 59 | public void applyToParams(List queryParams, Map headerParams) { 60 | if (apiKey == null) { 61 | return; 62 | } 63 | String value; 64 | if (apiKeyPrefix != null) { 65 | value = apiKeyPrefix + " " + apiKey; 66 | } else { 67 | value = apiKey; 68 | } 69 | if ("query".equals(location)) { 70 | queryParams.add(new Pair(paramName, value)); 71 | } else if ("header".equals(location)) { 72 | headerParams.put(paramName, value); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /integrations/teamcity/src/main/java/com/devexperts/switchboard/integrations/teamcity/swagger/codegen/invoker/auth/Authentication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * TeamCity REST API 3 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 4 | * 5 | * OpenAPI spec version: 2018.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker.auth; 15 | 16 | import com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker.Pair; 17 | 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | public interface Authentication { 22 | /** 23 | * Apply authentication settings to header and query params. 24 | * 25 | * @param queryParams List of query parameters 26 | * @param headerParams Map of header parameters 27 | */ 28 | void applyToParams(List queryParams, Map headerParams); 29 | } 30 | -------------------------------------------------------------------------------- /integrations/teamcity/src/main/java/com/devexperts/switchboard/integrations/teamcity/swagger/codegen/invoker/auth/HttpBasicAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * TeamCity REST API 3 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 4 | * 5 | * OpenAPI spec version: 2018.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker.auth; 15 | 16 | import com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker.Pair; 17 | import com.migcomponents.migbase64.Base64; 18 | 19 | import java.io.UnsupportedEncodingException; 20 | import java.util.List; 21 | import java.util.Map; 22 | 23 | @javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-01T01:12:43.660+03:00") 24 | public class HttpBasicAuth implements Authentication { 25 | private String username; 26 | private String password; 27 | 28 | public String getUsername() { 29 | return username; 30 | } 31 | 32 | public void setUsername(String username) { 33 | this.username = username; 34 | } 35 | 36 | public String getPassword() { 37 | return password; 38 | } 39 | 40 | public void setPassword(String password) { 41 | this.password = password; 42 | } 43 | 44 | @Override 45 | public void applyToParams(List queryParams, Map headerParams) { 46 | if (username == null && password == null) { 47 | return; 48 | } 49 | String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); 50 | try { 51 | headerParams.put("Authorization", "Basic " + Base64.encodeToString(str.getBytes("UTF-8"), false)); 52 | } catch (UnsupportedEncodingException e) { 53 | throw new RuntimeException(e); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /integrations/teamcity/src/main/java/com/devexperts/switchboard/integrations/teamcity/swagger/codegen/invoker/auth/OAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * TeamCity REST API 3 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 4 | * 5 | * OpenAPI spec version: 2018.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker.auth; 15 | 16 | import com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker.Pair; 17 | 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | @javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2020-06-01T01:12:43.660+03:00") 22 | public class OAuth implements Authentication { 23 | private String accessToken; 24 | 25 | public String getAccessToken() { 26 | return accessToken; 27 | } 28 | 29 | public void setAccessToken(String accessToken) { 30 | this.accessToken = accessToken; 31 | } 32 | 33 | @Override 34 | public void applyToParams(List queryParams, Map headerParams) { 35 | if (accessToken != null) { 36 | headerParams.put("Authorization", "Bearer " + accessToken); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /integrations/teamcity/src/main/java/com/devexperts/switchboard/integrations/teamcity/swagger/codegen/invoker/auth/OAuthFlow.java: -------------------------------------------------------------------------------- 1 | /* 2 | * TeamCity REST API 3 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 4 | * 5 | * OpenAPI spec version: 2018.1 6 | * 7 | * 8 | * NOTE: This class is auto generated by the swagger code generator program. 9 | * https://github.com/swagger-api/swagger-codegen.git 10 | * Do not edit the class manually. 11 | */ 12 | 13 | 14 | package com.devexperts.switchboard.integrations.teamcity.swagger.codegen.invoker.auth; 15 | 16 | public enum OAuthFlow { 17 | accessCode, implicit, password, application 18 | } 19 | -------------------------------------------------------------------------------- /integrations/teamcity/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /integrations/teamcity/src/test/resources/MockAgentsPool.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 0, 3 | "name": "Default", 4 | "href": "/httpAuth/app/rest/agentPools/id:0", 5 | "projects": {}, 6 | "agents": { 7 | "count": 10, 8 | "href": "/httpAuth/app/rest/agents?locator=pool:(id:0),defaultFilter:false", 9 | "agent": [ 10 | { 11 | "id": 1, 12 | "name": "Agent1", 13 | "typeId": 1, 14 | "connected": false, 15 | "enabled": false, 16 | "authorized": false, 17 | "uptodate": false, 18 | "href": "/httpAuth/app/rest/agents/id:1", 19 | "webUrl": "https://teamcity.somewhere.com/agentDetails.html?id=1&agentTypeId=1&realAgentName=Agent0-1" 20 | }, 21 | { 22 | "id": 2, 23 | "name": "Agent2", 24 | "typeId": 2, 25 | "connected": false, 26 | "enabled": false, 27 | "authorized": false, 28 | "uptodate": false, 29 | "href": "/httpAuth/app/rest/agents/id:2", 30 | "webUrl": "https://teamcity.somewhere.com/agentDetails.html?id=2&agentTypeId=2&realAgentName=Agent5-1" 31 | }, 32 | { 33 | "id": 3, 34 | "name": "Agent3", 35 | "typeId": 3, 36 | "connected": false, 37 | "enabled": false, 38 | "authorized": false, 39 | "uptodate": false, 40 | "href": "/httpAuth/app/rest/agents/id:3", 41 | "webUrl": "https://teamcity.somewhere.com/agentDetails.html?id=3&agentTypeId=3&realAgentName=Agent5-1" 42 | }, 43 | { 44 | "id": 4, 45 | "name": "Agent4", 46 | "typeId": 4, 47 | "connected": false, 48 | "enabled": false, 49 | "authorized": false, 50 | "uptodate": false, 51 | "href": "/httpAuth/app/rest/agents/id:4", 52 | "webUrl": "https://teamcity.somewhere.com/agentDetails.html?id=4&agentTypeId=4&realAgentName=Agent5-1" 53 | }, 54 | { 55 | "id": 5, 56 | "name": "Agent5", 57 | "typeId": 5, 58 | "connected": false, 59 | "enabled": false, 60 | "authorized": false, 61 | "uptodate": false, 62 | "href": "/httpAuth/app/rest/agents/id:5", 63 | "webUrl": "https://teamcity.somewhere.com/agentDetails.html?id=5&agentTypeId=5&realAgentName=Agent5-1" 64 | } 65 | ] 66 | }, 67 | "locator": null 68 | } -------------------------------------------------------------------------------- /integrations/teamcity/src/test/resources/TeamCityIntegration.json: -------------------------------------------------------------------------------- 1 | { 2 | "@class": "com.devexperts.switchboard.integrations.teamcity.TeamCityIntegration", 3 | "identifier": "TeamcityIntegration-1", 4 | "runnable": false, 5 | "testExtractors": [], 6 | "testProcessors": [], 7 | "testFilters": [], 8 | "testSplitters": [], 9 | "testRunProcessors": [], 10 | "testRunConsumers": [ 11 | { 12 | "@class": "com.devexperts.switchboard.integrations.teamcity.TcBuildTestRunConsumer", 13 | "identifier": "TcBuildTestRunConsumer-1", 14 | "buildTypeId": { 15 | "@class": "com.devexperts.switchboard.entities.valuesupplier.ConstantValuesExtractor", 16 | "values": [ 17 | "DXAutoQA_SwitchboardTest" 18 | ] 19 | }, 20 | "branchName": { 21 | "@class": "com.devexperts.switchboard.entities.valuesupplier.IdentifierValuesExtractor" 22 | }, 23 | "defaultBranch": true, 24 | "agentStackingCriterion": { 25 | "@class": "com.devexperts.switchboard.entities.valuesupplier.AttributeValuesExtractor", 26 | "attributeKey": "key2", 27 | "attributeValueKey": "" 28 | }, 29 | "agentRequirements": [], 30 | "buildProperties": { 31 | "buildProp1": { 32 | "@class": "com.devexperts.switchboard.entities.valuesupplier.ConstantValuesExtractor", 33 | "values": [ 34 | "buildPropVal1" 35 | ] 36 | }, 37 | "buildProp2": { 38 | "@class": "com.devexperts.switchboard.entities.valuesupplier.AttributeValuesExtractor", 39 | "attributeKey": "key1", 40 | "attributeValueKey": "" 41 | }, 42 | "testString": { 43 | "@class": "com.devexperts.switchboard.entities.valuesupplier.TestsToStringValuesExtractor", 44 | "valuesSeparator": ", " 45 | }, 46 | "verbosy": { 47 | "@class": "com.devexperts.switchboard.entities.valuesupplier.FormattingValuesExtractor", 48 | "formatString": "The quick brown %s jumps over the lazy %s.", 49 | "formatValues": [ 50 | { 51 | "@class": "com.devexperts.switchboard.entities.valuesupplier.IdentifierValuesExtractor" 52 | }, 53 | { 54 | "@class": "com.devexperts.switchboard.entities.valuesupplier.ConstantValuesExtractor", 55 | "values": [ 56 | "DXAutoQA_SwitchboardTest" 57 | ] 58 | } 59 | ] 60 | } 61 | }, 62 | "buildTags": [ 63 | { 64 | "@class": "com.devexperts.switchboard.entities.valuesupplier.AttributeKeyValuesExtractor", 65 | "attributeKeyRegex": "tag-1" 66 | }, 67 | { 68 | "@class": "com.devexperts.switchboard.entities.valuesupplier.AttributeKeyValuesExtractor", 69 | "attributeKeyRegex": "tag-2" 70 | } 71 | ], 72 | "moveToTop": true 73 | } 74 | ], 75 | "basePath": "https://teamcity.somewhere.com", 76 | "login": "user", 77 | "password": "p@ssw0rd" 78 | } -------------------------------------------------------------------------------- /integrations/teamcity/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /licenses/cucumber-core-license.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) The Cucumber Organisation 2 | 3 | MIT License (Expat) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /licenses/jakarta.xml.bind-api-license.txt: -------------------------------------------------------------------------------- 1 | Eclipse Distribution License - v 1.0 2 | Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | - Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | - Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | - Neither the name of the Eclipse Foundation, Inc. nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /licenses/jaxb-runtime-license.txt: -------------------------------------------------------------------------------- 1 | Eclipse Distribution License - v 1.0 2 | Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | - Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | - Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | - Neither the name of the Eclipse Foundation, Inc. nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /licenses/jersey-media-json-jackson-notice.txt: -------------------------------------------------------------------------------- 1 | # Notice for Jersey Json Jackson module 2 | This content is produced and maintained by the Eclipse Jersey project. 3 | 4 | * https://projects.eclipse.org/projects/ee4j.jersey 5 | 6 | ## Trademarks 7 | Eclipse Jersey is a trademark of the Eclipse Foundation. 8 | 9 | ## Copyright 10 | 11 | All content is the property of the respective authors or their employers. For 12 | more information regarding authorship of content, please consult the listed 13 | source code repository logs. 14 | 15 | ## Declared Project Licenses 16 | 17 | This program and the accompanying materials are made available under the terms 18 | of the Eclipse Public License v. 2.0 which is available at 19 | http://www.eclipse.org/legal/epl-2.0. This Source Code may also be made 20 | available under the following Secondary Licenses when the conditions for such 21 | availability set forth in the Eclipse Public License v. 2.0 are satisfied: GNU 22 | General Public License, version 2 with the GNU Classpath Exception which is 23 | available at https://www.gnu.org/software/classpath/license.html. 24 | 25 | SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 26 | 27 | ## Source Code 28 | The project maintains the following source code repositories: 29 | 30 | * https://github.com/eclipse-ee4j/jersey 31 | 32 | ## Third-party Content 33 | 34 | Jackson JAX-RS Providers version 2.8.10 35 | * License: Apache License, 2.0 36 | * Project: https://github.com/FasterXML/jackson-jaxrs-providers 37 | * Copyright: (c) 2009-2011 FasterXML, LLC. All rights reserved unless otherwise indicated. -------------------------------------------------------------------------------- /licenses/migbase-license.txt: -------------------------------------------------------------------------------- 1 | Licence (BSD): 2 | ============== Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (base64 @ miginfocom . com) All rights reserved. 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions 5 | are met: Redistributions of source code must retain the above 6 | copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, 8 | this list of conditions and the following disclaimer in the documentation 9 | and/or other materials provided with the distribution. 10 | Neither the name of the MiG InfoCom AB nor the names of its contributors 11 | may be used to endorse or promote products derived from this software 12 | without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 18 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 24 | OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /licenses/slf4j-api-license.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2004-2017 QOS.ch 4 | All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /licenses/swagger-java-client-license.txt: -------------------------------------------------------------------------------- 1 | TeamCity REST API 2 | No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 3 | 4 | OpenAPI spec version: 2018.1 5 | 6 | NOTE: This code is auto generated by the swagger code generator program. 7 | https://github.com/swagger-api/swagger-codegen.git -------------------------------------------------------------------------------- /runner/build.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | plugins { 8 | id "com.github.johnrengelman.shadow" 9 | } 10 | 11 | dependencies { 12 | implementation project(":api") 13 | implementation project(":core") 14 | implementation project(":utils") 15 | 16 | implementation "commons-cli:commons-cli:$commonsCliVersion" 17 | implementation "org.apache.xbean:xbean-classloader:$xbeanVersion" 18 | implementation "org.apache.logging.log4j:log4j-slf4j-impl:$apacheLog4jVersion" 19 | implementation "org.slf4j:slf4j-api:$slf4jVersion" 20 | implementation "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion" 21 | 22 | testImplementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" 23 | testImplementation "org.codehaus.groovy:groovy:$groovyVersion" 24 | testImplementation "junit:junit:$junitVersion" 25 | } 26 | 27 | jar { 28 | manifest { 29 | attributes( 30 | 'Main-Class': 'com.devexperts.switchboard.IntegrationsRunner' 31 | ) 32 | } 33 | } 34 | 35 | jar.finalizedBy shadowJar 36 | 37 | 38 | publishing { 39 | publications { 40 | shadow(MavenPublication) { publication -> 41 | project.shadow.component(publication) 42 | } 43 | } 44 | 45 | repositories { 46 | maven { 47 | name "qaauto" 48 | url "https://maven.in.devexperts.com/content/repositories/qa-auto${version.endsWith('-SNAPSHOT') ? '-snapshot' : ''}" 49 | } 50 | } 51 | } 52 | 53 | test.dependsOn( 54 | ":integrations:javaparser:clean", 55 | ":integrations:javaparser:shadowJar", 56 | ":integrations:bytecodeparser:clean", 57 | ":integrations:bytecodeparser:shadowJar", 58 | ":integrations:cukes:clean", 59 | ":integrations:cukes:shadowJar", 60 | ":integrations:jira:clean", 61 | ":integrations:jira:shadowJar", 62 | ":integrations:teamcity:clean", 63 | ":integrations:teamcity:shadowJar" 64 | ) 65 | -------------------------------------------------------------------------------- /runner/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /runner/src/test/resources/BytecodeParserIntegration.json: -------------------------------------------------------------------------------- 1 | { 2 | "@class": "com.devexperts.switchboard.integrations.bytecodeparser.BytecodeParserIntegration", 3 | "identifier": "BytecodeParserIntegration-1", 4 | "runnable": false, 5 | "testExtractors": [ 6 | { 7 | "@class": "com.devexperts.switchboard.integrations.bytecodeparser.BytecodeTestExtractor", 8 | "identifier": "JunitExtractor-2", 9 | "testLocations": [ 10 | "src/test/resources/test_classes/junit/JUnitTests.java", 11 | "src/test/resources/test_classes/junit/pckg" 12 | ], 13 | "filePattern": "regex:.*.jar", 14 | "testAnnotationPattern": "org.junit.Test" 15 | } 16 | ], 17 | "testProcessors": [], 18 | "testFilters": [ 19 | { 20 | "@class": "com.devexperts.switchboard.impl.filters.AttributesFilter", 21 | "identifier": "AttributesFilter-1", 22 | "attributePredicate": { 23 | "@class": "com.devexperts.switchboard.entities.attributes.AttributeIsPresent", 24 | "attributeKeyRegex": "MarkerAnnotation1" 25 | } 26 | } 27 | ], 28 | "testSplitters": [], 29 | "testRunProcessors": [], 30 | "testRunConsumers": [] 31 | } 32 | -------------------------------------------------------------------------------- /runner/src/test/resources/CukesIntegration.json: -------------------------------------------------------------------------------- 1 | { 2 | "@class": "com.devexperts.switchboard.integrations.cukes.CukesIntegration", 3 | "identifier": "CukesIntegration-1", 4 | "runnable": false, 5 | "testExtractors": [ 6 | { 7 | "@class": "com.devexperts.switchboard.integrations.cukes.CukesTestExtractor", 8 | "identifier": "CukesTestExtractor-1", 9 | "testLocations": [ 10 | "src/test/resources/test_classes" 11 | ], 12 | "filePattern": "regex:.*.feature", 13 | "cucumberNativeFilters": "", 14 | "basePath": "src/test/resources" 15 | } 16 | ], 17 | "testProcessors": [], 18 | "testFilters": [ 19 | { 20 | "@class": "com.devexperts.switchboard.impl.filters.AttributesFilter", 21 | "identifier": "AttributesFilter-1", 22 | "attributePredicate": { 23 | "@class": "com.devexperts.switchboard.entities.attributes.AttributeIsPresent", 24 | "attributeKeyRegex": "MarkerAnnotation1" 25 | } 26 | } 27 | ], 28 | "testSplitters": [], 29 | "testRunProcessors": [], 30 | "testRunConsumers": [] 31 | } -------------------------------------------------------------------------------- /runner/src/test/resources/FeaturelessIntegration.json: -------------------------------------------------------------------------------- 1 | { 2 | "@class": "com.devexperts.switchboard.impl.FeaturelessIntegration", 3 | "identifier": "FeaturelessIntegration-1", 4 | "runnable": true, 5 | "testExtractors": [], 6 | "testProcessors": [], 7 | "testFilters": [ 8 | { 9 | "@class": "com.devexperts.switchboard.impl.filters.AttributesFilter", 10 | "identifier": "AttributesFilter-1", 11 | "attributePredicate": { 12 | "@class": "com.devexperts.switchboard.entities.attributes.AttributeIsPresent", 13 | "attributeKeyRegex": "key1" 14 | } 15 | } 16 | ], 17 | "testSplitters": [ 18 | { 19 | "@class": "com.devexperts.switchboard.impl.splitters.AttributeKeySplitter", 20 | "identifier": "AttributeKeySplitter-1", 21 | "attributeKeys": [ 22 | "key1", 23 | "key2" 24 | ] 25 | }, 26 | { 27 | "@class": "com.devexperts.switchboard.impl.splitters.AttributeSingleValueSplitter", 28 | "identifier": "AttributeSingleValueSplitter-1", 29 | "attributeKey": "key1", 30 | "attributeValueKey": "valueKey1" 31 | } 32 | ], 33 | "testRunProcessors": [], 34 | "testRunConsumers": [] 35 | } -------------------------------------------------------------------------------- /runner/src/test/resources/JavaParserIntegration.json: -------------------------------------------------------------------------------- 1 | { 2 | "@class": "com.devexperts.switchboard.integrations.javaparser.JavaParserIntegration", 3 | "identifier": "JavaParserIntegration-1", 4 | "runnable": false, 5 | "testExtractors": [ 6 | { 7 | "@class": "com.devexperts.switchboard.integrations.javaparser.JavaTestExtractor", 8 | "identifier": "JunitExtractor-1", 9 | "testLocations": [ 10 | "src/test/resources/test_classes/junit/JUnitTests.java", 11 | "src/test/resources/test_classes/junit/pckg" 12 | ], 13 | "filePattern": "regex:.*.java", 14 | "testAnnotationPattern": "org.junit.Test" 15 | } 16 | ], 17 | "testProcessors": [], 18 | "testFilters": [ 19 | { 20 | "@class": "com.devexperts.switchboard.impl.filters.AttributesFilter", 21 | "identifier": "AttributesFilter-1", 22 | "attributePredicate": { 23 | "@class": "com.devexperts.switchboard.entities.attributes.AttributeIsPresent", 24 | "attributeKeyRegex": "MarkerAnnotation1" 25 | } 26 | } 27 | ], 28 | "testSplitters": [], 29 | "testRunProcessors": [], 30 | "testRunConsumers": [] 31 | } -------------------------------------------------------------------------------- /runner/src/test/resources/JiraIntegrationConfig.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "@class": "com.devexperts.switchboard.integrations.jira.JiraIntegration", 4 | "identifier": "Plain config", 5 | "runnable": false, 6 | "uri": "https://jira.somewhere.com", 7 | "login": "explicitLogin", 8 | "password": "explicitPassword" 9 | }, 10 | { 11 | "@class": "com.devexperts.switchboard.integrations.jira.JiraIntegration", 12 | "identifier": "Placeholders", 13 | "runnable": false, 14 | "uri": "%some.jira_url-2%", 15 | "login": "%login-2%", 16 | "password": "%password-2%" 17 | }, 18 | { 19 | "@class": "com.devexperts.switchboard.integrations.jira.JiraIntegration", 20 | "identifier": "Escaped placeholders", 21 | "runnable": false, 22 | "uri": "%%some.jira_url-2%%", 23 | "login": "%%login-3%%", 24 | "password": "%password-3%" 25 | } 26 | ] -------------------------------------------------------------------------------- /runner/src/test/resources/SimpleSplitter.json: -------------------------------------------------------------------------------- 1 | { 2 | "@class": "com.devexperts.switchboard.impl.splitters.TestCountSplitter", 3 | "identifier": "TestCountSplitter-1", 4 | "count": 5 5 | } -------------------------------------------------------------------------------- /runner/src/test/resources/ThreeSplitters.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "@class": "com.devexperts.switchboard.impl.splitters.TestCountSplitter", 4 | "identifier": "TestCountSplitter-1", 5 | "count": 2 6 | }, 7 | { 8 | "@class": "com.devexperts.switchboard.impl.splitters.TestCountSplitter", 9 | "identifier": "TestCountSplitter-2", 10 | "count": 4 11 | }, 12 | { 13 | "@class": "com.devexperts.switchboard.impl.splitters.TestCountSplitter", 14 | "identifier": "TestCountSplitter-3", 15 | "count": 6 16 | } 17 | ] -------------------------------------------------------------------------------- /runner/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /sandbox/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | plugins { 9 | id 'java' 10 | } 11 | 12 | repositories { 13 | mavenCentral() 14 | } 15 | 16 | dependencies { 17 | implementation project(":api") 18 | implementation project(":core") 19 | implementation project(":runner") 20 | implementation project(":utils") 21 | 22 | compileOnly project(':integrations:javaparser') 23 | compileOnly project(':integrations:bytecodeparser') 24 | compileOnly project(':integrations:cukes') 25 | compileOnly project(':integrations:jira') 26 | compileOnly project(':integrations:teamcity') 27 | 28 | implementation fileTree(dir: '../integrations', include: '**/*-all.jar') 29 | 30 | implementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" 31 | 32 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0' 33 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' 34 | } 35 | 36 | assemble.dependsOn( 37 | ":integrations:javaparser:clean", 38 | ":integrations:javaparser:shadowJar", 39 | ":integrations:bytecodeparser:clean", 40 | ":integrations:bytecodeparser:shadowJar", 41 | ":integrations:cukes:clean", 42 | ":integrations:cukes:shadowJar", 43 | ":integrations:jira:clean", 44 | ":integrations:jira:shadowJar", 45 | ":integrations:teamcity:clean", 46 | ":integrations:teamcity:shadowJar" 47 | ) -------------------------------------------------------------------------------- /sandbox/src/main/java/com/devexperts/switchboard/sandbox/utils/SandboxUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.sandbox.utils; 9 | 10 | import com.devexperts.switchboard.IntegrationsRunner; 11 | import com.devexperts.switchboard.api.Identifiable; 12 | import com.devexperts.switchboard.api.Integration; 13 | import com.devexperts.switchboard.utils.JacksonUtils; 14 | import com.fasterxml.jackson.databind.type.CollectionType; 15 | import org.slf4j.Logger; 16 | import org.slf4j.LoggerFactory; 17 | 18 | import java.io.File; 19 | import java.io.FileNotFoundException; 20 | import java.io.IOException; 21 | import java.io.PrintWriter; 22 | import java.nio.file.Paths; 23 | import java.util.Collections; 24 | import java.util.List; 25 | import java.util.stream.Collectors; 26 | 27 | public final class SandboxUtils { 28 | private static final Logger log = LoggerFactory.getLogger(SandboxUtils.class); 29 | 30 | private SandboxUtils() {} 31 | 32 | public static String writeIntegrationConfig(Integration integration) throws IOException { 33 | return writeIntegrationConfig(Collections.singletonList(integration)); 34 | } 35 | 36 | public static String writeIntegrationConfig(List> integrations) throws IOException { 37 | CollectionType collType = JacksonUtils.getMapper().getTypeFactory().constructCollectionType(List.class, Integration.class); 38 | 39 | String config = JacksonUtils.getMapper().writer().forType(collType).writeValueAsString(integrations); 40 | String name = integrations.stream().map(Identifiable::getIdentifier).collect(Collectors.joining("_")); 41 | log.info("Config for integration `{}`:\n{}", name, config); 42 | return writeToFileAndLogResult(name, config); 43 | } 44 | 45 | public static void prepareAndRunIntegration(String configPath) { 46 | IntegrationsRunner.run(new String[] {"-c", configPath, "-i", Paths.get("").toAbsolutePath().toString()}); 47 | } 48 | 49 | private static String writeToFileAndLogResult(String fileName, String content) { 50 | File file = new File("sandbox/out/configs/" + fileName + ".json"); 51 | file.getParentFile().mkdirs(); 52 | try (PrintWriter out = new PrintWriter(file)) { 53 | out.write(content); 54 | log.info("Config written to: {}", file.getAbsolutePath()); 55 | return file.getAbsolutePath(); 56 | } catch (FileNotFoundException e) { 57 | throw new RuntimeException("Failed to write to " + file.getAbsolutePath(), e); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /sandbox/src/main/resources/cukes/pckg1/Mixed_feature_1.feature: -------------------------------------------------------------------------------- 1 | @UserRole#user2 2 | 3 | Feature: Mixed feature 4 | 5 | Background: 6 | Given Everything is ok 7 | 8 | @Regression 9 | Scenario: Scenario 1 10 | 11 | When I do something 12 | Then Everything is ok 13 | 14 | @Sanity 15 | Scenario Outline: Scenario outline 1 16 | 17 | When I do 18 | Then Everything is ok 19 | 20 | Examples: 21 | | action | 22 | | something | 23 | | something else | 24 | 25 | @Bat 26 | @Negative 27 | Scenario: Scenario 2 28 | 29 | When I do something else 30 | Then Everything is ok -------------------------------------------------------------------------------- /sandbox/src/main/resources/cukes/pckg1/Multi_feature_1.feature: -------------------------------------------------------------------------------- 1 | @Regression 2 | @Sanity 3 | @UserRole#user1 4 | 5 | Feature: Multi scenario feature 6 | 7 | Background: 8 | Given Everything is ok 9 | 10 | @Another_tag1 11 | @Negative 12 | Scenario: Scenario 1 13 | 14 | When I do something 15 | Then Everything is ok 16 | 17 | @Bat 18 | Scenario: Scenario 2 19 | 20 | When I do something else 21 | Then Everything is ok -------------------------------------------------------------------------------- /sandbox/src/main/resources/cukes/pckg1/Outline_feature_1.feature: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | @Regression 9 | @Sanity 10 | @Bat 11 | @UserRole#user1 12 | @operatingSystem#Windows 13 | 14 | Feature: Outline scenario feature 15 | 16 | Background: 17 | Given Everything is ok 18 | 19 | @Another_tag1 20 | Scenario Outline: Scenario 1 21 | 22 | When I do 23 | Then Everything is ok 24 | 25 | Examples: 26 | | action | 27 | | something | 28 | | something else | -------------------------------------------------------------------------------- /sandbox/src/main/resources/cukes/pckg1/Single_feature_1.feature: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | @Regression 9 | @Bat 10 | @UserRole#user1 11 | 12 | Feature: Single scenario feature 13 | 14 | Background: 15 | Given Everything is ok 16 | 17 | @Another_tag1 18 | Scenario: Scenario 1 19 | 20 | When I do something 21 | And I do something else 22 | Then Everything is ok -------------------------------------------------------------------------------- /sandbox/src/main/resources/cukes/pckg2/Mixed_feature_2.feature: -------------------------------------------------------------------------------- 1 | @UserRole#user2 2 | 3 | Feature: Mixed feature 2 4 | 5 | Background: 6 | Given Everything is ok 7 | 8 | @Regression 9 | @operatingSystem#Windows 10 | Scenario: Scenario 1 11 | 12 | When I do something 13 | Then Everything is ok 14 | 15 | @Sanity 16 | @operatingSystem#Linux 17 | Scenario Outline: Scenario outline 1 18 | 19 | When I do 20 | Then Everything is ok 21 | 22 | Examples: 23 | | action | 24 | | something | 25 | | something else | 26 | 27 | @Bat 28 | Scenario: Scenario 2 29 | 30 | When I do something else 31 | Then Everything is ok -------------------------------------------------------------------------------- /sandbox/src/main/resources/cukes/pckg2/Multi_feature_2.feature: -------------------------------------------------------------------------------- 1 | @Regression 2 | @Sanity 3 | @UserRole#user2 4 | @operatingSystem#Windows 5 | 6 | Feature: Multi scenario feature 2 7 | 8 | Background: 9 | Given Everything is ok 10 | 11 | @Another_tag3 12 | Scenario: Scenario 1 13 | 14 | When I do something 15 | Then Everything is ok 16 | 17 | @Bat 18 | Scenario: Scenario 2 19 | 20 | When I do something else 21 | Then Everything is ok -------------------------------------------------------------------------------- /sandbox/src/main/resources/cukes/pckg2/Outline_feature_2.feature: -------------------------------------------------------------------------------- 1 | @Regression 2 | @Sanity 3 | @Bat 4 | @UserRole#user3 5 | @operatingSystem#Linux 6 | 7 | Feature: Outline scenario feature 2 8 | 9 | Background: 10 | Given Everything is ok 11 | 12 | @Another_tag2 13 | Scenario Outline: Scenario 1 14 | 15 | When I do 16 | Then Everything is ok 17 | 18 | Examples: 19 | | action | 20 | | something | 21 | | something else | -------------------------------------------------------------------------------- /sandbox/src/main/resources/cukes/pckg2/Single_feature_2.feature: -------------------------------------------------------------------------------- 1 | @Regression 2 | @UserRole#user3 3 | 4 | Feature: Single scenario feature 2 5 | 6 | Background: 7 | Given Everything is ok 8 | 9 | @Another_tag2 10 | Scenario: Scenario 1 11 | 12 | When I do something 13 | And I do something else 14 | Then Everything is ok -------------------------------------------------------------------------------- /sandbox/src/main/resources/cukes/pckg3/Mixed_feature_3.feature: -------------------------------------------------------------------------------- 1 | @UserRole#user3 2 | @operatingSystem#Linux 3 | 4 | Feature: Mixed feature 3 5 | 6 | Background: 7 | Given Everything is ok 8 | 9 | @Regression 10 | Scenario: Scenario 1 11 | 12 | When I do something 13 | Then Everything is ok 14 | 15 | @Sanity 16 | Scenario Outline: Scenario outline 1 17 | 18 | When I do 19 | Then Everything is ok 20 | 21 | Examples: 22 | | action | 23 | | something | 24 | | something else | 25 | 26 | @Bat 27 | Scenario: Scenario 2 28 | 29 | When I do something else 30 | Then Everything is ok -------------------------------------------------------------------------------- /sandbox/src/main/resources/cukes/pckg3/Multi_feature_3.feature: -------------------------------------------------------------------------------- 1 | @Regression 2 | @Sanity 3 | @UserRole#user3 4 | @operatingSystem#Windows 5 | 6 | Feature: Multi scenario feature 3 7 | 8 | Background: 9 | Given Everything is ok 10 | 11 | @Another_tag3 12 | Scenario: Scenario 1 13 | 14 | When I do something 15 | Then Everything is ok 16 | 17 | @Bat 18 | Scenario: Scenario 2 19 | 20 | When I do something else 21 | Then Everything is ok -------------------------------------------------------------------------------- /sandbox/src/main/resources/cukes/pckg3/Outline_feature_3.feature: -------------------------------------------------------------------------------- 1 | @Regression 2 | @Sanity 3 | @Bat 4 | @UserRole#user2 5 | @operatingSystem#Windows 6 | 7 | Feature: Outline scenario feature 3 8 | 9 | Background: 10 | Given Everything is ok 11 | 12 | @Another_tag2 13 | Scenario Outline: Scenario 1 14 | 15 | When I do 16 | Then Everything is ok 17 | 18 | Examples: 19 | | action | 20 | | something | 21 | | something else | -------------------------------------------------------------------------------- /sandbox/src/main/resources/cukes/pckg3/Single_feature_3.feature: -------------------------------------------------------------------------------- 1 | @Regression 2 | @Bat 3 | @UserRole#user3 4 | 5 | Feature: Single scenario feature 3 6 | 7 | Background: 8 | Given Everything is ok 9 | 10 | @Another_tag2 11 | Scenario: Scenario 1 12 | 13 | When I do something 14 | And I do something else 15 | Then Everything is ok -------------------------------------------------------------------------------- /sandbox/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include 'api' 2 | include 'core' 3 | include 'runner' 4 | include 'integrations:javaparser' 5 | include 'integrations:bytecodeparser' 6 | include 'integrations:cukes' 7 | include 'integrations:jira' 8 | include 'integrations:teamcity' 9 | include 'utils' 10 | include 'sandbox' 11 | 12 | -------------------------------------------------------------------------------- /utils/build.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | dependencies { 9 | implementation project(":api") 10 | implementation project(":core") 11 | 12 | implementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" 13 | implementation "org.apache.xbean:xbean-classloader:$xbeanVersion" 14 | implementation "org.apache.logging.log4j:log4j-slf4j-impl:$apacheLog4jVersion" 15 | implementation "org.slf4j:slf4j-api:$slf4jVersion" 16 | 17 | testImplementation "org.codehaus.groovy:groovy:$groovyVersion" 18 | testImplementation "junit:junit:$junitVersion" 19 | } 20 | -------------------------------------------------------------------------------- /utils/src/main/java/com/devexperts/switchboard/utils/ClassLoaderUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.utils; 9 | 10 | import org.apache.xbean.classloader.JarFileClassLoader; 11 | 12 | import java.net.URL; 13 | 14 | public final class ClassLoaderUtils { 15 | private ClassLoaderUtils() { } 16 | 17 | /** 18 | * Provides a named, optionally child-first URLClassLoader implementation with specified parent ClassLoader 19 | * 20 | * @param name classloader name 21 | * @param parent parent classloader 22 | * @param inverseClassLoading if true, the created class loader logic is child-first, else conventional parent-first 23 | * @param urls the URLs from which to load classes and resources 24 | * @return the created classloader 25 | */ 26 | public static ClassLoader getClassloader(String name, ClassLoader parent, boolean inverseClassLoading, URL... urls) { 27 | return parent == null ? 28 | new JarFileClassLoader(name, urls, Thread.currentThread().getContextClassLoader(), 29 | inverseClassLoading, new String[] {}, new String[] {}) : 30 | new JarFileClassLoader(name, urls, parent, inverseClassLoading, new String[] {}, new String[] {}); 31 | } 32 | 33 | /** 34 | * Provides a named, optionally child-first URLClassLoader implementation with parent as currentThread ContextClassLoader 35 | * 36 | * @param name classloader name 37 | * @param inverseClassLoading if true, the created class loader logic is child-first, else conventional parent-first 38 | * @param urls the URLs from which to load classes and resources 39 | * @return the created classloader 40 | */ 41 | public static ClassLoader getClassloader(String name, boolean inverseClassLoading, URL... urls) { 42 | return getClassloader(name, null, inverseClassLoading, urls); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /utils/src/main/java/com/devexperts/switchboard/utils/SystemPropsTestConsumer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002 - 2021 Devexperts LLC 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | */ 7 | 8 | package com.devexperts.switchboard.utils; 9 | 10 | import com.devexperts.switchboard.api.TestRunConsumer; 11 | import com.devexperts.switchboard.entities.TestRun; 12 | import com.devexperts.switchboard.impl.VoidIntegrationFeatures; 13 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 14 | import com.fasterxml.jackson.annotation.PropertyAccessor; 15 | import com.fasterxml.jackson.databind.ObjectMapper; 16 | import com.fasterxml.jackson.databind.SerializationFeature; 17 | 18 | import java.util.List; 19 | 20 | public class SystemPropsTestConsumer implements TestRunConsumer { 21 | 22 | private String identifier; 23 | 24 | private SystemPropsTestConsumer() {} 25 | 26 | public SystemPropsTestConsumer(String identifier) { 27 | this.identifier = identifier; 28 | } 29 | 30 | @Override 31 | public void init(VoidIntegrationFeatures integrationFeatures) {/*do nothing*/} 32 | 33 | @Override 34 | public Void accept(List testRuns) { 35 | ObjectMapper mapper = new ObjectMapper() 36 | .configure(SerializationFeature.INDENT_OUTPUT, true) 37 | .setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE) 38 | .setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); 39 | mapper.getFactory().enable(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_COMMENTS); 40 | try { 41 | System.setProperty("runResult", mapper.writeValueAsString(testRuns.toArray(new TestRun[0]))); 42 | return null; 43 | } catch (Exception e) { 44 | throw new RuntimeException("Failed to write TestRuns to JSON and store it in SystemProperties", e); 45 | } 46 | } 47 | 48 | @Override 49 | public String getIdentifier() { 50 | return identifier; 51 | } 52 | 53 | @Override 54 | public void close() {/*do nothing*/} 55 | } -------------------------------------------------------------------------------- /utils/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /utils/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | --------------------------------------------------------------------------------