├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── misc └── logo.png ├── pom.xml └── src ├── main └── java │ └── com │ └── github │ └── vbauer │ └── jconditions │ ├── annotation │ ├── AppIsInstalled.java │ ├── ExistsOnFS.java │ ├── HasClass.java │ ├── HasFreeSpace.java │ ├── HasPackage.java │ ├── IfJavaVersion.java │ ├── IfScript.java │ ├── IgnoreIf.java │ ├── PropertyIsDefined.java │ ├── ResourceIsAvailable.java │ ├── RunIf.java │ ├── RunningOnOS.java │ ├── SocketIsOpened.java │ └── UrlIsReachable.java │ ├── checker │ ├── AppIsInstalledChecker.java │ ├── ExistsOnFSChecker.java │ ├── HasClassChecker.java │ ├── HasFreeSpaceChecker.java │ ├── HasPackageChecker.java │ ├── IfJavaVersionChecker.java │ ├── IfScriptChecker.java │ ├── IgnoreIfChecker.java │ ├── PropertyIsDefinedChecker.java │ ├── ResourceIsAvailableChecker.java │ ├── RunIfChecker.java │ ├── RunningOnOSChecker.java │ ├── SocketIsOpenedChecker.java │ └── UrlIsReachableChecker.java │ ├── core │ ├── CheckerContext.java │ ├── Condition.java │ ├── ConditionChecker.java │ ├── ConditionCheckerEngine.java │ ├── ConditionCheckerExecutor.java │ └── junit │ │ ├── ConditionRule.java │ │ ├── ConditionTestRunner.java │ │ └── IgnoreStatement.java │ └── util │ ├── FSUtils.java │ ├── InOutUtils.java │ ├── NetUtils.java │ ├── PropUtils.java │ ├── ReflexUtils.java │ ├── ScriptUtils.java │ └── TextUtils.java └── test ├── java └── com │ └── github │ └── vbauer │ └── jconditions │ ├── annotation │ ├── AbstractAnnotationsTest.java │ ├── InterfaceAnnotationsTest.java │ ├── RuleAnnotationsTest.java │ └── RunnerAnnotationTest.java │ ├── misc │ ├── Always.java │ ├── AppleWorksFine.java │ └── Never.java │ └── util │ ├── ConstructorContractTest.java │ ├── InOutUtilsTest.java │ └── ReflexUtilsTest.java └── resources └── checkstyle.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io 2 | 3 | ### Java ### 4 | *.class 5 | 6 | # Mobile Tools for Java (J2ME) 7 | .mtj.tmp/ 8 | 9 | # Package Files # 10 | *.jar 11 | *.war 12 | *.ear 13 | 14 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 15 | hs_err_pid* 16 | 17 | 18 | ### Maven ### 19 | target/ 20 | pom.xml.tag 21 | pom.xml.releaseBackup 22 | pom.xml.versionsBackup 23 | pom.xml.next 24 | release.properties 25 | dependency-reduced-pom.xml 26 | 27 | 28 | ### JetBrains ### 29 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 30 | 31 | *.iml 32 | 33 | ## Directory-based project format: 34 | .idea/ 35 | # if you remove the above rule, at least ignore the following: 36 | 37 | # User-specific stuff: 38 | # .idea/workspace.xml 39 | # .idea/tasks.xml 40 | # .idea/dictionaries 41 | 42 | # Sensitive or high-churn files: 43 | # .idea/dataSources.ids 44 | # .idea/dataSources.xml 45 | # .idea/sqlDataSources.xml 46 | # .idea/dynamic.xml 47 | # .idea/uiDesigner.xml 48 | 49 | # Gradle: 50 | # .idea/gradle.xml 51 | # .idea/libraries 52 | 53 | # Mongo Explorer plugin: 54 | # .idea/mongoSettings.xml 55 | 56 | ## File-based project format: 57 | *.ipr 58 | *.iws 59 | 60 | ## Plugin-specific files: 61 | 62 | # IntelliJ 63 | out/ 64 | 65 | # mpeltonen/sbt-idea plugin 66 | .idea_modules/ 67 | 68 | # JIRA plugin 69 | atlassian-ide-plugin.xml 70 | 71 | # Crashlytics plugin (for Android Studio and IntelliJ) 72 | com_crashlytics_export_strings.xml 73 | crashlytics.properties 74 | crashlytics-build.properties 75 | 76 | 77 | ### Windows ### 78 | # Windows image file caches 79 | Thumbs.db 80 | ehthumbs.db 81 | 82 | # Folder config file 83 | Desktop.ini 84 | 85 | # Recycle Bin used on file shares 86 | $RECYCLE.BIN/ 87 | 88 | # Windows Installer files 89 | *.cab 90 | *.msi 91 | *.msm 92 | *.msp 93 | 94 | # Windows shortcuts 95 | *.lnk 96 | 97 | 98 | ### OSX ### 99 | .DS_Store 100 | .AppleDouble 101 | .LSOverride 102 | 103 | # Icon must end with two \r 104 | Icon 105 | 106 | 107 | # Thumbnails 108 | ._* 109 | 110 | # Files that might appear in the root of a volume 111 | .DocumentRevisions-V100 112 | .fseventsd 113 | .Spotlight-V100 114 | .TemporaryItems 115 | .Trashes 116 | .VolumeIcon.icns 117 | 118 | # Directories potentially created on remote AFP share 119 | .AppleDB 120 | .AppleDesktop 121 | Network Trash Folder 122 | Temporary Items 123 | .apdisk 124 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | script: mvn clean package -P strict 3 | after_success: 4 | - mvn jacoco:report coveralls:report 5 | jdk: 6 | - oraclejdk8 7 | - oraclejdk9 8 | - oraclejdk11 9 | branches: 10 | only: 11 | - master 12 | sudo: false 13 | cache: 14 | directories: 15 | - $HOME/.m2 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # JConditions 3 | 4 | [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-JConditions-brightgreen.svg?style=flat)](http://android-arsenal.com/details/1/2414) 5 | [![Build Status](https://travis-ci.org/vbauer/jconditions.svg)](https://travis-ci.org/vbauer/jconditions) 6 | [![Coverage Status](https://coveralls.io/repos/vbauer/jconditions/badge.svg?branch=master)](https://coveralls.io/r/vbauer/jconditions?branch=master) 7 | [![Dependency Status](https://www.versioneye.com/user/projects/562e9efb36d0ab001600163a/badge.svg?style=flat)](https://www.versioneye.com/user/projects/562e9efb36d0ab001600163a) 8 | [![Maven](https://img.shields.io/github/tag/vbauer/jconditions.svg?label=maven)](https://jitpack.io/#vbauer/jconditions) 9 | 10 | 11 | 12 | > There is an exception to every rule. 13 | 14 | **JConditions** is an extension for [JUnit](http://junit.org) framework, which allows to mark test methods with specific conditional annotations. 15 | This annotations allow to permit or restrict execution of test methods. 16 | It helps to keep clean your test methods using declarative programming and prevents a lot of unnecessary code (see [Assume](http://junit.sourceforge.net/javadoc/org/junit/Assume.html) class). 17 | 18 | 19 | ## 10 second example 20 | 21 | A picture paints a thousand words: 22 | 23 | ```java 24 | @RunWith(ConditionTestRunner.class) 25 | public class ExampleTest { 26 | @Test 27 | @RunningOnOS(LINUX) 28 | public void testRunningOnOS() throws Exception { 29 | // Check some Linux app 30 | assertTrue(exec("some-linux-program")); 31 | } 32 | @Test 33 | @IfJavaVersion(JAVA_8) 34 | public void testIfJavaVersion8() { 35 | // Check some Java 8 specific code 36 | assertTrue(com.foo.Java8Class.isCorrect()); 37 | } 38 | } 39 | ``` 40 | 41 | 42 | ## Features 43 | 44 | **JConditions** has the following conditional annotations: 45 | 46 | 62 | 63 | This annotations could be used with test methods or/and classes (it will allow to run checks before each test method). 64 | You can also write custom annotations or make composite annotations. 65 | 66 | ## Setup 67 | 68 | **JConditions** uses [JitPack.io](https://jitpack.io) for distribution, so 69 | you need to configure JitPack's Maven repository to fetch artifacts (dependencies). 70 | 71 | ### Maven 72 | 73 | ```xml 74 | 75 | jitpack.io 76 | https://jitpack.io 77 | 78 | 79 | 80 | 81 | com.github.vbauer 82 | jconditions 83 | 1.2.3 84 | 85 | 86 | ``` 87 | 88 | ### Gradle 89 | 90 | ```groovy 91 | repositories { 92 | mavenCentral() 93 | maven { 94 | url 'https://jitpack.io' 95 | } 96 | } 97 | 98 | dependencies { 99 | testCompile 'com.github.vbauer:jconditions:1.2.3' 100 | } 101 | ``` 102 | 103 | 104 | ## Annotations 105 | 106 | Some things that you need to know before exploring an examples: 107 | 108 | * Each described annotation has a simple example how to use it. Examples are very simple, they are existed only to show the main idea of usage. 109 | * Most of them could use injections to insert environment variables. This injections/substitutions could be useful to parametrize tests or to organize profiles. 110 | **EX:** "${java.io.tmpdir}/test.html" 111 | 112 | ### @AppIsInstalled 113 | **@AppIsInstalled** checks that specified application(s) is installed. 114 | It could be useful when developed application has an optional integrations with some external tools/apps and 115 | it will be good to check this integrations in tests. 116 | 117 | ```java 118 | @Test 119 | @AppIsInstalled({ "ls", "uname" }) 120 | public void testAppIsInstalled() throws Exception { 121 | exec("ls"); 122 | exec("uname"); 123 | } 124 | ``` 125 | 126 | ### @ExistsOnFS 127 | **@ExistsOnFS** checks that specified file or directory is existed on file system. 128 | It is also possible to configure multiple values. 129 | 130 | Available parameters: 131 | 132 | * **value** - file(s) or directory(ies). 133 | * **type** - type(s) of FS element (FILE / DIRECTORY / SYMLINK). 134 | 135 | ```java 136 | @Test 137 | @ExistsOnFS("pom.xml") 138 | public void testFileExists() throws Exception { 139 | Assert.assertTrue(FSUtils.fileExists("pom.xml")); 140 | } 141 | ``` 142 | 143 | ### @HasClass 144 | **@HasClass** checks that specified class(es) is available in classpath. 145 | It could be useful to check integration with optional features. 146 | 147 | ```java 148 | @Test 149 | @HasClass("org.junit.Assert") 150 | public void testHasClass() throws Exception { 151 | Assert.assertNotNull(Class.forName("org.junit.Assert")); 152 | } 153 | ``` 154 | 155 | ### @HasFreeSpace 156 | **@HasFreeSpace** checks that FS element(s) / disk(s) has free space. 157 | It could be useful to check if it is possible to: 158 | 159 | * download some big some file from remote server 160 | * generate and store on FS some data 161 | 162 | Available parameters: 163 | 164 | * **value** - disk or disks that should be checked (ex: "C:\\"). 165 | * **min** - minimum amount of available free space on disk in bytes. 166 | * **max** - maximum amount of available free space on disk in bytes. 167 | 168 | ```java 169 | @Test 170 | @HasFreeSpace(value = { "/", "C:\\" }, min = 1024) 171 | public void testHasFreeSpace() { 172 | // Download some file 173 | } 174 | ``` 175 | 176 | ### @HasPackage 177 | **@HasPackage** checks that specified package(s) is available in classpath. 178 | It could be useful to check integration with optional features. 179 | 180 | ```java 181 | @Test 182 | @HasPackage("org.junit") 183 | public void testHasPackage() throws Exception { 184 | Assert.assertNotNull(Package.getPackage("org.junit")); 185 | } 186 | ``` 187 | 188 | ### @IfJavaVersion 189 | **@IfJavaVersion** checks that test is run on the specific version(s) of JVM. 190 | 191 | **EX:** Some features could use external libraries and work only for the specific version of JVM. 192 | It is possible to check it, if you use full names for classes (class loader will load them in runtime). 193 | 194 | ```java 195 | @Test 196 | @IfJavaVersion(IfJavaVersion.JAVA_8) 197 | public void testIfJavaVersion8() { 198 | Assert.assertTrue(IfJavaVersionChecker.javaVersion().contains("8")); 199 | // Javaslang project works only on Java 8 200 | Assert.assertNotNull(javaslang.Tuple0.instance()); 201 | } 202 | ``` 203 | 204 | ### @IfScript 205 | 206 | **@IfScript** allows to write custom conditional rules using [JSR 223: Scripting for the JavaTM Platform](https://www.jcp.org/en/jsr/detail?id=223). 207 | JavaScript engine is available by default (it is part of JVM). 208 | All other JSR233-compatible languages will be included automatically if they are available in classpath. 209 | 210 | Available parameters: 211 | 212 | * **values** - script or scripts that should be executed. Return value will be converted to boolean type (even `String` and `Number`s). 213 | * **engine** - type of script engine (default value is `"js"`). 214 | * **context** - context provider which provides an extra data in script as `"context"` variable. 215 | 216 | 217 | Parameters which are available in script context: 218 | 219 | * **test** - current instance of running test class. 220 | * **env** - environment variables (`System.getenv()`). 221 | * **props** - system properties (`System.getProperties()`). 222 | * **console** - console object (`System.console()`). 223 | * **context** - extra data which could be created using `context` provider. 224 | 225 | ```java 226 | @Test 227 | @IfScript("test.isSatisfiedInnerCheck") 228 | public void testIfScriptNegative() { 229 | Assert.fail(); 230 | } 231 | ``` 232 | 233 | ### @IgnoreIf 234 | **@IgnoreIf** allows to skip some test method using specific `ConditionChecker` class. 235 | It will skip test, if checker return true and execute method otherwise. 236 | `ConditionChecker` could be separate class, or nested static class, or even inner class. 237 | It also works fine with private classes. 238 | 239 | ```java 240 | @Test 241 | @IgnoreIf(Always.class) 242 | public void testIgnoreIfAlways() { 243 | Assert.fail(); 244 | } 245 | ``` 246 | 247 | ### @PropertyIsDefined 248 | 249 | **@PropertyIsDefined** checks if environment or system property is defined. 250 | It could be useful to simulate test profiles or to check some cases which are dependent on them (and could be optionals). 251 | 252 | Available parameters: 253 | 254 | * **keys** - keys of environment or system variables 255 | * **values** - values that should correspond to keys (optional parameter). 256 | 257 | ```java 258 | @Test 259 | @PropertyIsDefined(keys = "os.name") 260 | public void testEnvVarIsDefined() { 261 | Assert.assertNotNull(PropUtils.getSystemProperty("os.name")); 262 | } 263 | ``` 264 | 265 | ### @ResourceIsAvailable 266 | 267 | **@ResourceIsAvailable** allows to minimize code which is necessary to download some document/file via HTTP/HTTPS. 268 | It is also possible to cache downloaded resource between test executions, otherwise it will be remove after test. 269 | 270 | Available parameters: 271 | 272 | * **source** - HTTP/HTTPS file or document. 273 | * **target** - path to file where content should be saved. 274 | * **cache** - flag to configure cache option. 275 | * **timeout** - maximum time for connection to the `source` (default value is 10sec). 276 | 277 | ```java 278 | @Test 279 | @ResourceIsAvailable( 280 | source = "http://apple.com", 281 | target = "${java.io.tmpdir}/apple-homepage.html", 282 | cache = false 283 | ) 284 | public void testResourceIsAvailable() { 285 | final String path = PropUtils.injectProperties("${java.io.tmpdir}/apple-homepage.html"); 286 | Assert.assertTrue(FSUtils.fileExists(path)); 287 | } 288 | ``` 289 | 290 | ### @RunIf 291 | 292 | **@RunIf** is an opposite annotation to **@IgnoreIf**. It will run test method if `ConditionChecker` returns `true`. 293 | 294 | ```java 295 | @Test 296 | @RunIf(SomeInnerClassCheck.class) 297 | public void testInnerClass() { 298 | Assert.fail(); 299 | } 300 | ``` 301 | 302 | ### @RunningOnOS 303 | **@RunningOnOS** checks the current operation system and runs test method only when it is specified and `value` parameter. 304 | It is also possible to configure multiple variants (to run test method, even one of them should be fine). 305 | 306 | ```java 307 | @Test 308 | @RunningOnOS({ 309 | RunningOnOS.LINUX, 310 | RunningOnOS.MAC, 311 | }) 312 | public void testRunningOnOS() throws Exception { 313 | Assert.assertTrue(exec("ls")); 314 | } 315 | ``` 316 | 317 | ### @SocketIsOpened 318 | **@SocketIsOpened** checks that specified socket is opened. 319 | 320 | Available parameters: 321 | 322 | * **host** - host address (default value is "0.0.0.0"). 323 | * **port** - socket's port number. 324 | * **timeout** - maximum time for connection to the socket (default value is 10sec). 325 | 326 | ```java 327 | @Test 328 | @SocketIsOpened(host = "apple.com", port = 80) 329 | public void testSocketIsOpened() throws Exception { 330 | checkSite("http://apple.com"); 331 | } 332 | ``` 333 | 334 | ### @UrlIsReachable 335 | 336 | **@UrlIsReachable** checks that specified URL address is reachable (available via `URLConnection`). 337 | It also possible to configure multiple URLs. 338 | 339 | Available parameters: 340 | 341 | * **value** - URL address(s) that should be checked. 342 | * **timeout** - maximum timeout for URL connection (default value is 10sec). 343 | 344 | ```java 345 | @Test 346 | @UrlIsReachable("http://apple.com") 347 | public void testUrlIsReachable() throws Exception { 348 | checkSite("http://apple.com"); 349 | } 350 | ``` 351 | 352 | 353 | ## Custom annotations 354 | It is possible use `@IfRun` or `@IgnoreIf` to run custom `ConditionalChecker`, 355 | but it is also possible to write your own annotation (like `@HasPackage` or `@IfScript`). 356 | 357 | All JConditions out-of-box annotations was created using unified extension mechanism. 358 | This mechanism is centered around 3 main things: 359 | 360 | * Custom annotation which can has additional parameters that could be used as input data. 361 | * Conditional checker which make decision to permit or restrict running of test method. 362 | * `@Condition` annotation which allows to glue custom annotation and conditional checker. 363 | 364 | Let's write an annotation which emulates standard JUnit's `@org.junit.Ignore`: 365 | 366 | ```java 367 | @Condition(IgnoreItChecker.class) 368 | @Retention(RetentionPolicy.RUNTIME) 369 | @Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD }) 370 | public @interface IgnoreIt { 371 | } 372 | 373 | public class IgnoreItChecker implements ConditionChecker { 374 | @Override 375 | public boolean isSatisfied(final CheckerContext context) { 376 | return false; 377 | } 378 | 379 | } 380 | ``` 381 | 382 | That's all! Now, you can mark test classes or test methods with `@IgnoreIt` to skip test(s). 383 | 384 | 385 | ## Composite annotations 386 | 387 | Sometimes it could be useful to have possibility to resolve the following cases (to prevent unnecessary code): 388 | 389 | * Specify all needed parameter for some existed annotation and do not copy-paste them. 390 | * Glue some conditional annotations into one annotation. 391 | 392 | It is possible, because JConditions extension mechanism resolves all hierarchy of classes and annotations. 393 | 394 | Let's make an annotation which allows to detect if our MySQL database works fine: 395 | 396 | ```java 397 | @SocketIsOpened(host = "localhost", port = 3306) 398 | @Retention(RetentionPolicy.RUNTIME) 399 | @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) 400 | public @interface MySQLWorks { 401 | } 402 | ``` 403 | 404 | Let's make an annotation which allows to run tests only on Linux machines with Java 8: 405 | 406 | ```java 407 | @RunningOnOS(LINUX) 408 | @IfJavaVersion(JAVA_8) 409 | @Retention(RetentionPolicy.RUNTIME) 410 | @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) 411 | public @interface OnLinuxWithJava8 { 412 | } 413 | ``` 414 | 415 | 416 | ## Building from source 417 | 418 | JConditions uses [Maven](https://maven.apache.org) for its build. To build project, run: 419 | 420 | ```bash 421 | mvn clean install -P strict 422 | ``` 423 | 424 | from the root of the project directory. 425 | Profile `strict` is necessary to check code style and to run static code analysis. 426 | 427 | 428 | ## Might also like 429 | 430 | * [jackdaw](https://github.com/vbauer/jackdaw) - Java Annotation Processor which allows to simplify development. 431 | * [caesar](https://github.com/vbauer/caesar) - Library that allows to create async beans from sync beans. 432 | * [houdini](https://github.com/vbauer/houdini) - Type conversion system for Spring framework. 433 | * [herald](https://github.com/vbauer/herald) - Logging annotation for Spring framework. 434 | * [commons-vfs2-cifs](https://github.com/vbauer/commons-vfs2-cifs) - SMB/CIFS provider for Commons VFS. 435 | * [avconv4java](https://github.com/vbauer/avconv4java) - Java interface to avconv tool. 436 | 437 | 438 | ## License 439 | 440 | Copyright 2015 Vladislav Bauer 441 | 442 | Licensed under the Apache License, Version 2.0 (the "License"); 443 | you may not use this file except in compliance with the License. 444 | You may obtain a copy of the License at 445 | 446 | http://www.apache.org/licenses/LICENSE-2.0 447 | 448 | Unless required by applicable law or agreed to in writing, software 449 | distributed under the License is distributed on an "AS IS" BASIS, 450 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 451 | See the License for the specific language governing permissions and 452 | limitations under the License. 453 | 454 | See [LICENSE](LICENSE) file for details. 455 | -------------------------------------------------------------------------------- /misc/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vbauer/jconditions/c5816a8439df7cc891a25387cc08ffa22a3cd5c6/misc/logo.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.github.vbauer 8 | jconditions 9 | 1.2.3 10 | 11 | Extra conditional annotations for JUnit 12 | https://github.com/vbauer/jconditions 13 | 2015 14 | 15 | 16 | 17 | Apache License, Version 2.0 18 | http://www.apache.org/licenses/LICENSE-2.0 19 | manual 20 | 21 | 22 | 23 | 24 | GitHub Issues 25 | https://github.com/vbauer/jconditions/issues 26 | 27 | 28 | 29 | Travis 30 | https://travis-ci.org/vbauer/jconditions 31 | 32 | 33 | 34 | 35 | vbauer 36 | Vladislav Bauer 37 | bauer.vlad@gmail.com 38 | http://linkedin.com/in/vladislavbauer 39 | 40 | architect 41 | developer 42 | 43 | 44 | 45 | 46 | 47 | 3.0.0 48 | 49 | 50 | 51 | UTF-8 52 | 1.8 53 | 54 | 4.12 55 | 56 | 3.8.0 57 | 3.0.1 58 | 2.22.1 59 | 3.1.0 60 | 2.8.2 61 | 2.5.2 62 | 3.1.0 63 | 3.1.0 64 | 3.7.1 65 | 66 | 3.0.0 67 | 3.11.0 68 | 0.8.2 69 | 4.3.0 70 | 71 | 72 | 73 | 74 | 75 | junit 76 | junit 77 | ${junit.version} 78 | provided 79 | 80 | 81 | 82 | 83 | 84 | io.javaslang 85 | javaslang 86 | 2.0.6 87 | test 88 | 89 | 90 | 91 | com.pushtorefresh.java-private-constructor-checker 92 | checker 93 | 1.2.0 94 | test 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | org.apache.maven.plugins 107 | maven-compiler-plugin 108 | ${maven.compiler.plugin.version} 109 | 110 | ${java.version} 111 | ${java.version} 112 | true 113 | 114 | 115 | 116 | 117 | org.apache.maven.plugins 118 | maven-source-plugin 119 | ${maven.source.plugin.version} 120 | 121 | 122 | attach-sources 123 | verify 124 | 125 | jar-no-fork 126 | 127 | 128 | 129 | 130 | 131 | 132 | org.apache.maven.plugins 133 | maven-surefire-plugin 134 | ${maven.surefire.plugin.version} 135 | 136 | 137 | 138 | org.apache.maven.plugins 139 | maven-clean-plugin 140 | ${maven.clean.plugin.version} 141 | 142 | 143 | 144 | org.apache.maven.plugins 145 | maven-deploy-plugin 146 | ${maven.deploy.plugin.version} 147 | 148 | 149 | 150 | org.apache.maven.plugins 151 | maven-install-plugin 152 | ${maven.install.plugin.version} 153 | 154 | 155 | 156 | org.apache.maven.plugins 157 | maven-jar-plugin 158 | ${maven.jar.plugin.version} 159 | 160 | 161 | 162 | org.apache.maven.plugins 163 | maven-resources-plugin 164 | ${maven.resources.plugin.version} 165 | 166 | 167 | 168 | org.apache.maven.plugins 169 | maven-site-plugin 170 | ${maven.site.plugin.version} 171 | 172 | 173 | 174 | 175 | 176 | org.jacoco 177 | jacoco-maven-plugin 178 | ${maven.jacoco.plugin.version} 179 | 180 | 181 | prepare-agent 182 | 183 | prepare-agent 184 | 185 | 186 | 187 | 188 | 189 | 190 | org.eluder.coveralls 191 | coveralls-maven-plugin 192 | ${maven.coveralls.plugin.version} 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | strict 203 | 204 | 205 | 206 | 207 | org.apache.maven.plugins 208 | maven-checkstyle-plugin 209 | ${maven.checkstyle.plugin.version} 210 | 211 | true 212 | src/test/resources/checkstyle.xml 213 | false 214 | 215 | 216 | 217 | package 218 | 219 | check 220 | 221 | 222 | 223 | 224 | 225 | 226 | org.apache.maven.plugins 227 | maven-pmd-plugin 228 | ${maven.pmd.plugin.version} 229 | 230 | false 231 | true 232 | true 233 | false 234 | 235 | 236 | 237 | package 238 | 239 | check 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/annotation/AppIsInstalled.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.checker.AppIsInstalledChecker; 4 | import com.github.vbauer.jconditions.core.Condition; 5 | 6 | import java.lang.annotation.Documented; 7 | import java.lang.annotation.ElementType; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import java.lang.annotation.Target; 11 | 12 | /** 13 | * Checks that specified application(s) is installed. 14 | * 15 | * @author Vladislav Bauer 16 | */ 17 | 18 | @Documented 19 | @Condition(AppIsInstalledChecker.class) 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD}) 22 | public @interface AppIsInstalled { 23 | 24 | /** 25 | * Application or applications that should be checked. 26 | * 27 | * @return applications 28 | */ 29 | String[] value(); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/annotation/ExistsOnFS.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.checker.ExistsOnFSChecker; 4 | import com.github.vbauer.jconditions.core.Condition; 5 | 6 | import java.lang.annotation.Documented; 7 | import java.lang.annotation.ElementType; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import java.lang.annotation.Target; 11 | 12 | /** 13 | * Checks that specified file or directory is existed on file system. 14 | * 15 | * @author Vladislav Bauer 16 | */ 17 | 18 | @Documented 19 | @Condition(ExistsOnFSChecker.class) 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD}) 22 | public @interface ExistsOnFS { 23 | 24 | /** 25 | * Files or directories that should be checked. 26 | * Parameter depends on {@link #type} value. 27 | * 28 | * @return files or directories 29 | */ 30 | String[] value(); 31 | 32 | /** 33 | * Type(s) of FS element(s). 34 | * 35 | * @return type 36 | */ 37 | Type[] type() default Type.FILE; 38 | 39 | 40 | /** 41 | * Type of FS element. 42 | * 43 | * @author Vladislav Bauer 44 | */ 45 | enum Type { 46 | FILE, 47 | DIRECTORY, 48 | SYMLINK 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/annotation/HasClass.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.checker.HasClassChecker; 4 | import com.github.vbauer.jconditions.core.Condition; 5 | 6 | import java.lang.annotation.Documented; 7 | import java.lang.annotation.ElementType; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import java.lang.annotation.Target; 11 | 12 | /** 13 | * Checks that specified class(es) is available in classpath. 14 | * 15 | * @author Vladislav Bauer 16 | */ 17 | 18 | @Documented 19 | @Condition(HasClassChecker.class) 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD}) 22 | public @interface HasClass { 23 | 24 | /** 25 | * Full names of class or classes that should be checked. 26 | * 27 | * @return classes 28 | */ 29 | String[] value(); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/annotation/HasFreeSpace.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.checker.HasFreeSpaceChecker; 4 | import com.github.vbauer.jconditions.core.Condition; 5 | 6 | import java.lang.annotation.Documented; 7 | import java.lang.annotation.ElementType; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import java.lang.annotation.Target; 11 | 12 | /** 13 | * Checks that disk(s) has available free space. 14 | * 15 | * @author Vladislav Bauer 16 | */ 17 | 18 | @Documented 19 | @Condition(HasFreeSpaceChecker.class) 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD}) 22 | public @interface HasFreeSpace { 23 | 24 | /** 25 | * {@link Long#MIN_VALUE} is the same as undefined. 26 | */ 27 | long UNDEFINED = Long.MIN_VALUE; 28 | 29 | 30 | /** 31 | * Disk or disks that should be checked (ex: "C:\\"). 32 | * 33 | * @return element(s) on FS 34 | */ 35 | String[] value(); 36 | 37 | /** 38 | * Minimum amount of available free space on disk. 39 | * 40 | * @return min space in bytes 41 | */ 42 | long min() default UNDEFINED; 43 | 44 | /** 45 | * Maximum amount of available free space on disk. 46 | * 47 | * @return max space in bytes 48 | */ 49 | long max() default UNDEFINED; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/annotation/HasPackage.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.checker.HasPackageChecker; 4 | import com.github.vbauer.jconditions.core.Condition; 5 | 6 | import java.lang.annotation.Documented; 7 | import java.lang.annotation.ElementType; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import java.lang.annotation.Target; 11 | 12 | /** 13 | * Checks that specified package(s) is available in classpath. 14 | * 15 | * @author Vladislav Bauer 16 | */ 17 | 18 | @Documented 19 | @Condition(HasPackageChecker.class) 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD}) 22 | public @interface HasPackage { 23 | 24 | /** 25 | * Full name of package or packages that should be checked. 26 | * 27 | * @return packages 28 | */ 29 | String[] value(); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/annotation/IfJavaVersion.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.checker.IfJavaVersionChecker; 4 | import com.github.vbauer.jconditions.core.Condition; 5 | 6 | import java.lang.annotation.Documented; 7 | import java.lang.annotation.ElementType; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import java.lang.annotation.Target; 11 | 12 | /** 13 | * Checks that test is run on the specific version(s) of JVM. 14 | * 15 | * @author Vladislav Bauer 16 | */ 17 | 18 | @Documented 19 | @Condition(IfJavaVersionChecker.class) 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD}) 22 | public @interface IfJavaVersion { 23 | 24 | String JAVA_8 = "1.8"; 25 | String JAVA_9 = "1.9"; 26 | 27 | /** 28 | * Version or versions of JVM that should be checked. 29 | * 30 | * @return java version 31 | */ 32 | String[] value(); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/annotation/IfScript.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.checker.IfScriptChecker; 4 | import com.github.vbauer.jconditions.core.Condition; 5 | 6 | import java.lang.annotation.Documented; 7 | import java.lang.annotation.ElementType; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import java.lang.annotation.Target; 11 | import java.util.concurrent.Callable; 12 | 13 | /** 14 | * Allows to write custom conditional rules using JSR 223: Scripting for the JavaTM Platform. 15 | * JavaScript engine is available by default (it is part of JVM). 16 | * All other JSR233-compatible languages will be included automatically if they are available in classpath. 17 | * 18 | * @author Vladislav Bauer 19 | */ 20 | 21 | @Documented 22 | @Condition(IfScriptChecker.class) 23 | @Retention(RetentionPolicy.RUNTIME) 24 | @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD}) 25 | public @interface IfScript { 26 | 27 | String DEFAULT_JS = "js"; 28 | 29 | /** 30 | * Script or scripts that should be executed. 31 | * Return value will be converted to boolean type (even "String" and "Number"s). 32 | * 33 | * @return script or scripts 34 | */ 35 | String[] value(); 36 | 37 | /** 38 | * Type of script engine. 39 | * Script engine will be detected using this parameter and mime type / name / language. 40 | * 41 | * @return engine type. 42 | */ 43 | String engine() default DEFAULT_JS; 44 | 45 | /** 46 | * It is possible to add some data in script execution using an extra context provider. 47 | * Data will be available in script as "context" parameter. 48 | * 49 | * @return class of content provider 50 | */ 51 | @SuppressWarnings("rawtypes") 52 | Class context() default Callable.class; 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/annotation/IgnoreIf.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.checker.IgnoreIfChecker; 4 | import com.github.vbauer.jconditions.core.Condition; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | 7 | import java.lang.annotation.Documented; 8 | import java.lang.annotation.ElementType; 9 | import java.lang.annotation.Retention; 10 | import java.lang.annotation.RetentionPolicy; 11 | import java.lang.annotation.Target; 12 | 13 | /** 14 | * Allows to skip some test method using specific {@link ConditionChecker} class. 15 | * It will skip test, if checker return true and execute method otherwise. 16 | * "ConditionChecker" could be separate class, or nested static class, or even inner class. 17 | * It also works fine with private classes. 18 | * 19 | * @author Vladislav Bauer 20 | */ 21 | 22 | @Documented 23 | @Condition(IgnoreIfChecker.class) 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD}) 26 | public @interface IgnoreIf { 27 | 28 | /** 29 | * Condition checkers that should be checked. 30 | * 31 | * @return condition checkers 32 | */ 33 | @SuppressWarnings("rawtypes") 34 | Class[] value(); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/annotation/PropertyIsDefined.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.checker.PropertyIsDefinedChecker; 4 | import com.github.vbauer.jconditions.core.Condition; 5 | 6 | import java.lang.annotation.Documented; 7 | import java.lang.annotation.ElementType; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import java.lang.annotation.Target; 11 | 12 | /** 13 | * Checks if environment or system property is defined. 14 | * 15 | * @author Vladislav Bauer 16 | */ 17 | 18 | @Documented 19 | @Condition(PropertyIsDefinedChecker.class) 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD}) 22 | public @interface PropertyIsDefined { 23 | 24 | /** 25 | * Keys of environment or system variables. 26 | * 27 | * @return keys 28 | */ 29 | String[] keys(); 30 | 31 | /** 32 | * Values that should correspond to keys (optional parameter). 33 | * 34 | * @return values 35 | */ 36 | String[] values() default {}; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/annotation/ResourceIsAvailable.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.checker.ResourceIsAvailableChecker; 4 | import com.github.vbauer.jconditions.core.Condition; 5 | 6 | import java.lang.annotation.Documented; 7 | import java.lang.annotation.ElementType; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import java.lang.annotation.Target; 11 | 12 | /** 13 | * Allows to minimize code which is necessary to download some document/file via HTTP/HTTPS. 14 | * It is also possible to cache downloaded resource between test executions, otherwise it will be remove after test. 15 | * 16 | * @author Vladislav Bauer 17 | */ 18 | 19 | @Documented 20 | @Condition(ResourceIsAvailableChecker.class) 21 | @Retention(RetentionPolicy.RUNTIME) 22 | @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD}) 23 | public @interface ResourceIsAvailable { 24 | 25 | int DEFAULT_TIMEOUT = 10000; 26 | 27 | 28 | /** 29 | * HTTP/HTTPS file or document. 30 | * 31 | * @return url address of the resource 32 | */ 33 | String source(); 34 | 35 | /** 36 | * Path to file where content should be saved. 37 | * 38 | * @return file path 39 | */ 40 | String target(); 41 | 42 | /** 43 | * Flag to configure cache option. 44 | * 45 | * @return true if it is necessary to use cache, and false otherwise. 46 | */ 47 | boolean cache() default true; 48 | 49 | /** 50 | * Maximum time in ms for connection to the `source`. 51 | * 52 | * @return timeout 53 | */ 54 | int timeout() default DEFAULT_TIMEOUT; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/annotation/RunIf.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.checker.RunIfChecker; 4 | import com.github.vbauer.jconditions.core.Condition; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | 7 | import java.lang.annotation.Documented; 8 | import java.lang.annotation.ElementType; 9 | import java.lang.annotation.Retention; 10 | import java.lang.annotation.RetentionPolicy; 11 | import java.lang.annotation.Target; 12 | 13 | /** 14 | * It is an opposite annotation to {@link IgnoreIf}. 15 | * It will run test method if {@link ConditionChecker} returns `true`. 16 | * 17 | * @author Vladislav Bauer 18 | */ 19 | 20 | @Documented 21 | @Condition(RunIfChecker.class) 22 | @Retention(RetentionPolicy.RUNTIME) 23 | @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD}) 24 | public @interface RunIf { 25 | 26 | /** 27 | * Condition checkers that should be checked. 28 | * 29 | * @return condition checkers 30 | */ 31 | @SuppressWarnings("rawtypes") 32 | Class[] value(); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/annotation/RunningOnOS.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.checker.RunningOnOSChecker; 4 | import com.github.vbauer.jconditions.core.Condition; 5 | 6 | import java.lang.annotation.Documented; 7 | import java.lang.annotation.ElementType; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import java.lang.annotation.Target; 11 | 12 | /** 13 | * Checks the current operation system and runs test method only when it is specified and `value` parameter. 14 | * 15 | * @author Vladislav Bauer 16 | */ 17 | 18 | @Documented 19 | @Condition(RunningOnOSChecker.class) 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD}) 22 | public @interface RunningOnOS { 23 | 24 | String MAC = "mac"; 25 | String MAC_OSX = "mac os x"; 26 | String LINUX = "linux"; 27 | String WINDOWS = "win"; 28 | String OS2 = "os/2"; 29 | String AIX = "aix"; 30 | String HP_UX = "hp-ux"; 31 | String IRIX = "irix"; 32 | String SOLARIS = "solaris"; 33 | String SUN_OS = "sunos"; 34 | 35 | /** 36 | * Operation system(s) that should be checked. 37 | * 38 | * @return OS name 39 | */ 40 | String[] value(); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/annotation/SocketIsOpened.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.checker.SocketIsOpenedChecker; 4 | import com.github.vbauer.jconditions.core.Condition; 5 | 6 | import java.lang.annotation.Documented; 7 | import java.lang.annotation.ElementType; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import java.lang.annotation.Target; 11 | 12 | /** 13 | * Checks that specified socket is opened. 14 | * 15 | * @author Vladislav Bauer 16 | */ 17 | 18 | @Documented 19 | @Condition(SocketIsOpenedChecker.class) 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD}) 22 | public @interface SocketIsOpened { 23 | 24 | /** 25 | * Default value for host. 26 | */ 27 | String DEFAULT_HOST = "0.0.0.0"; 28 | 29 | /** 30 | * Default value for timeout. 31 | */ 32 | int DEFAULT_TIMEOUT = 10000; 33 | 34 | 35 | /** 36 | * Host address. Default value: {@link #DEFAULT_HOST}. 37 | * 38 | * @return host 39 | */ 40 | String host() default DEFAULT_HOST; 41 | 42 | /** 43 | * Port number. 44 | * 45 | * @return port 46 | */ 47 | int port(); 48 | 49 | /** 50 | * Maximum time for connection to the socket. Default value: {@link #DEFAULT_TIMEOUT}. 51 | * 52 | * @return timeout 53 | */ 54 | int timeout() default DEFAULT_TIMEOUT; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/annotation/UrlIsReachable.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.checker.UrlIsReachableChecker; 4 | import com.github.vbauer.jconditions.core.Condition; 5 | 6 | import java.lang.annotation.Documented; 7 | import java.lang.annotation.ElementType; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import java.lang.annotation.Target; 11 | 12 | /** 13 | * Checks that specified URL address is reachable (available via {@link java.net.URLConnection}). 14 | * 15 | * @author Vladislav Bauer 16 | */ 17 | 18 | @Documented 19 | @Condition(UrlIsReachableChecker.class) 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD}) 22 | public @interface UrlIsReachable { 23 | 24 | int DEFAULT_TIMEOUT = 10000; 25 | 26 | 27 | /** 28 | * URL address(s) that should be checked. 29 | * 30 | * @return URL address(s) 31 | */ 32 | String[] value(); 33 | 34 | /** 35 | * Maximum timeout for URL connection. 36 | * 37 | * @return timeout 38 | */ 39 | int timeout() default DEFAULT_TIMEOUT; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/checker/AppIsInstalledChecker.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.checker; 2 | 3 | import com.github.vbauer.jconditions.annotation.AppIsInstalled; 4 | import com.github.vbauer.jconditions.core.CheckerContext; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | import com.github.vbauer.jconditions.util.PropUtils; 7 | 8 | /** 9 | * @author Vladislav Bauer 10 | */ 11 | 12 | public class AppIsInstalledChecker implements ConditionChecker { 13 | 14 | /** 15 | * {@inheritDoc} 16 | */ 17 | @Override 18 | public boolean isSatisfied(final CheckerContext context) { 19 | final AppIsInstalled annotation = context.getAnnotation(); 20 | final String[] applications = annotation.value(); 21 | return appsInstalled(applications); 22 | } 23 | 24 | 25 | private boolean appsInstalled(final String... applications) { 26 | for (final String application : applications) { 27 | final String app = PropUtils.injectProperties(application); 28 | if (!isAppInstalled(app)) { 29 | return false; 30 | } 31 | } 32 | return applications.length > 0; 33 | } 34 | 35 | private boolean isAppInstalled(final String application) { 36 | try { 37 | return Runtime.getRuntime().exec(application) != null; 38 | } catch (final Exception ex) { 39 | return false; 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/checker/ExistsOnFSChecker.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.checker; 2 | 3 | import com.github.vbauer.jconditions.annotation.ExistsOnFS; 4 | import com.github.vbauer.jconditions.core.CheckerContext; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | import com.github.vbauer.jconditions.util.FSUtils; 7 | import com.github.vbauer.jconditions.util.PropUtils; 8 | 9 | /** 10 | * @author Vladislav Bauer 11 | */ 12 | 13 | public class ExistsOnFSChecker implements ConditionChecker { 14 | 15 | /** 16 | * {@inheritDoc} 17 | */ 18 | @Override 19 | public boolean isSatisfied(final CheckerContext context) throws Exception { 20 | final ExistsOnFS annotation = context.getAnnotation(); 21 | final ExistsOnFS.Type[] types = annotation.type(); 22 | final String[] filePaths = annotation.value(); 23 | 24 | return isSatisfied(filePaths, types); 25 | } 26 | 27 | 28 | private boolean isSatisfied( 29 | final String[] filePaths, final ExistsOnFS.Type... types 30 | ) throws Exception { 31 | for (final String filePath : filePaths) { 32 | if (isSatisfied(filePath, types)) { 33 | return false; 34 | } 35 | } 36 | return filePaths.length > 0; 37 | } 38 | 39 | private boolean isSatisfied( 40 | final String filePath, final ExistsOnFS.Type... types 41 | ) throws Exception { 42 | for (final ExistsOnFS.Type type : types) { 43 | if (!existsOnFS(filePath, type)) { 44 | return true; 45 | } 46 | } 47 | return false; 48 | } 49 | 50 | private boolean existsOnFS( 51 | final String filePath, final ExistsOnFS.Type type 52 | ) throws Exception { 53 | final String path = PropUtils.injectProperties(filePath); 54 | switch (type) { 55 | case FILE: 56 | return FSUtils.fileExists(path); 57 | case DIRECTORY: 58 | return FSUtils.directoryExists(path); 59 | case SYMLINK: 60 | return FSUtils.exists(path) && FSUtils.isSymlink(path); 61 | default: 62 | throw new UnsupportedOperationException("Unsupported type of FS element"); 63 | } 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/checker/HasClassChecker.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.checker; 2 | 3 | import com.github.vbauer.jconditions.annotation.HasClass; 4 | import com.github.vbauer.jconditions.core.CheckerContext; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | 7 | /** 8 | * @author Vladislav Bauer 9 | */ 10 | 11 | public class HasClassChecker implements ConditionChecker { 12 | 13 | /** 14 | * {@inheritDoc} 15 | */ 16 | @Override 17 | public boolean isSatisfied(final CheckerContext context) { 18 | final HasClass annotation = context.getAnnotation(); 19 | final String[] classNames = annotation.value(); 20 | return hasAllClasses(classNames); 21 | } 22 | 23 | 24 | private boolean hasAllClasses(final String... classNames) { 25 | for (final String className : classNames) { 26 | final boolean hasClass = hasClass(className); 27 | if (!hasClass) { 28 | return false; 29 | } 30 | } 31 | return classNames.length > 0; 32 | } 33 | 34 | private boolean hasClass(final String className) { 35 | try { 36 | return Class.forName(className) != null; 37 | } catch (final Exception ex) { 38 | return false; 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/checker/HasFreeSpaceChecker.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.checker; 2 | 3 | import com.github.vbauer.jconditions.annotation.HasFreeSpace; 4 | import com.github.vbauer.jconditions.core.CheckerContext; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | 7 | import java.io.File; 8 | 9 | /** 10 | * @author Vladislav Bauer 11 | */ 12 | 13 | public class HasFreeSpaceChecker implements ConditionChecker { 14 | 15 | /** 16 | * {@inheritDoc} 17 | */ 18 | @Override 19 | public boolean isSatisfied(final CheckerContext context) { 20 | final HasFreeSpace annotation = context.getAnnotation(); 21 | final String[] targets = annotation.value(); 22 | final long min = annotation.min(); 23 | final long max = annotation.max(); 24 | 25 | return isSatisfied(targets, min, max); 26 | } 27 | 28 | 29 | private boolean isSatisfied(final String[] targets, final long min, final long max) { 30 | for (final String target : targets) { 31 | if (!isSatisfied(target, max, min)) { 32 | return false; 33 | } 34 | } 35 | return targets.length > 0; 36 | } 37 | 38 | private boolean isSatisfied(final String target, final long max, final long min) { 39 | final File file = new File(target); 40 | if (file.exists()) { 41 | final long freeSpace = file.getFreeSpace(); 42 | if (min != HasFreeSpace.UNDEFINED && freeSpace < min) { 43 | return false; 44 | } 45 | return max == HasFreeSpace.UNDEFINED || freeSpace <= max; 46 | } 47 | return true; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/checker/HasPackageChecker.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.checker; 2 | 3 | import com.github.vbauer.jconditions.annotation.HasPackage; 4 | import com.github.vbauer.jconditions.core.CheckerContext; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | 7 | /** 8 | * @author Vladislav Bauer 9 | */ 10 | 11 | public class HasPackageChecker implements ConditionChecker { 12 | 13 | /** 14 | * {@inheritDoc} 15 | */ 16 | @Override 17 | public boolean isSatisfied(final CheckerContext context) { 18 | final HasPackage annotation = context.getAnnotation(); 19 | final String[] packageNames = annotation.value(); 20 | return hasAllPackages(packageNames); 21 | } 22 | 23 | 24 | private boolean hasAllPackages(final String... packageNames) { 25 | for (final String packageName : packageNames) { 26 | final boolean hasPackage = Package.getPackage(packageName) != null; 27 | if (!hasPackage) { 28 | return false; 29 | } 30 | } 31 | return packageNames.length > 0; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/checker/IfJavaVersionChecker.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.checker; 2 | 3 | import com.github.vbauer.jconditions.annotation.IfJavaVersion; 4 | import com.github.vbauer.jconditions.core.CheckerContext; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | import com.github.vbauer.jconditions.util.PropUtils; 7 | 8 | /** 9 | * @author Vladislav Bauer 10 | */ 11 | 12 | public class IfJavaVersionChecker implements ConditionChecker { 13 | 14 | private static final String PROPERTY_JAVA_VERSION = "java.version"; 15 | 16 | 17 | /** 18 | * {@inheritDoc} 19 | */ 20 | @Override 21 | public boolean isSatisfied(final CheckerContext context) { 22 | final IfJavaVersion annotation = context.getAnnotation(); 23 | final String[] versions = annotation.value(); 24 | return PropUtils.hasAnyWithProperties(javaVersion(), versions); 25 | } 26 | 27 | 28 | public static String javaVersion() { 29 | return PropUtils.getSystemProperty(PROPERTY_JAVA_VERSION).toLowerCase(); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/checker/IfScriptChecker.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.checker; 2 | 3 | import com.github.vbauer.jconditions.annotation.IfScript; 4 | import com.github.vbauer.jconditions.core.CheckerContext; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | import com.github.vbauer.jconditions.util.PropUtils; 7 | import com.github.vbauer.jconditions.util.ReflexUtils; 8 | import com.github.vbauer.jconditions.util.ScriptUtils; 9 | 10 | import javax.script.ScriptContext; 11 | import javax.script.ScriptEngine; 12 | import javax.script.SimpleScriptContext; 13 | import java.util.concurrent.Callable; 14 | 15 | /** 16 | * @author Vladislav Bauer 17 | */ 18 | 19 | public class IfScriptChecker implements ConditionChecker { 20 | 21 | private static final String CONTEXT_ENV = "env"; 22 | private static final String CONTEXT_PROPS = "props"; 23 | private static final String CONTEXT_TEST = "test"; 24 | private static final String CONTEXT_CONSOLE = "console"; 25 | private static final String CONTEXT_CONTEXT = "context"; 26 | 27 | 28 | /** 29 | * {@inheritDoc} 30 | */ 31 | @Override 32 | public boolean isSatisfied(final CheckerContext context) throws Exception { 33 | final Object testInstance = context.getInstance(); 34 | final IfScript annotation = context.getAnnotation(); 35 | 36 | @SuppressWarnings("rawtypes") 37 | final Class contextProviderClass = annotation.context(); 38 | final String engineName = annotation.engine(); 39 | final String[] scripts = annotation.value(); 40 | 41 | final ScriptEngine scriptEngine = ScriptUtils.findScriptEngine(engineName); 42 | if (scriptEngine != null) { 43 | final Object extraContext = getExtraContext(testInstance, contextProviderClass); 44 | final ScriptContext scriptContext = createScriptContext(testInstance, extraContext); 45 | return isSatisfied(scriptEngine, scriptContext, scripts); 46 | } 47 | return false; 48 | } 49 | 50 | 51 | private boolean isSatisfied( 52 | final ScriptEngine scriptEngine, final ScriptContext scriptContext, final String... scripts 53 | ) throws Exception { 54 | for (final String script : scripts) { 55 | final Object eval = scriptEngine.eval(script, scriptContext); 56 | if (!isTrueValue(eval)) { 57 | return false; 58 | } 59 | } 60 | return scripts.length > 0; 61 | } 62 | 63 | private boolean isTrueValue(final Object value) { 64 | if (value instanceof Number) { 65 | return ((Number) value).doubleValue() > 0; 66 | } 67 | return Boolean.valueOf(String.valueOf(value)); 68 | } 69 | 70 | private ScriptContext createScriptContext( 71 | final Object testInstance, final Object extraContext 72 | ) { 73 | final ScriptContext context = new SimpleScriptContext(); 74 | ScriptUtils.addAttribute(context, CONTEXT_CONTEXT, extraContext); 75 | ScriptUtils.addAttribute(context, CONTEXT_TEST, testInstance); 76 | ScriptUtils.addAttribute(context, CONTEXT_CONSOLE, System.console()); 77 | ScriptUtils.addAttribute(context, CONTEXT_ENV, System.getenv()); 78 | ScriptUtils.addAttribute( 79 | context, CONTEXT_PROPS, 80 | PropUtils.convertPropertiesToMap(System.getProperties()) 81 | ); 82 | return context; 83 | } 84 | 85 | @SuppressWarnings("rawtypes") 86 | private Object getExtraContext( 87 | final Object testInstance, final Class providerClass 88 | ) throws Exception { 89 | if (providerClass != null && providerClass != Callable.class) { 90 | final Callable provider = ReflexUtils.instantiate(testInstance, providerClass); 91 | return provider.call(); 92 | } 93 | return null; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/checker/IgnoreIfChecker.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.checker; 2 | 3 | import com.github.vbauer.jconditions.annotation.IgnoreIf; 4 | import com.github.vbauer.jconditions.core.CheckerContext; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | import com.github.vbauer.jconditions.core.ConditionCheckerExecutor; 7 | 8 | /** 9 | * @author Vladislav Bauer 10 | */ 11 | 12 | public class IgnoreIfChecker implements ConditionChecker { 13 | 14 | /** 15 | * {@inheritDoc} 16 | */ 17 | @Override 18 | public boolean isSatisfied(final CheckerContext context) { 19 | final IgnoreIf annotation = context.getAnnotation(); 20 | 21 | @SuppressWarnings("rawtypes") 22 | final Class[] checkerClasses = annotation.value(); 23 | 24 | //noinspection unchecked 25 | return !ConditionCheckerExecutor.isSatisfied(context, checkerClasses); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/checker/PropertyIsDefinedChecker.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.checker; 2 | 3 | import com.github.vbauer.jconditions.annotation.PropertyIsDefined; 4 | import com.github.vbauer.jconditions.core.CheckerContext; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | import com.github.vbauer.jconditions.util.PropUtils; 7 | import com.github.vbauer.jconditions.util.TextUtils; 8 | 9 | /** 10 | * @author Vladislav Bauer 11 | */ 12 | 13 | public class PropertyIsDefinedChecker implements ConditionChecker { 14 | 15 | /** 16 | * {@inheritDoc} 17 | */ 18 | @Override 19 | public boolean isSatisfied(final CheckerContext context) { 20 | final PropertyIsDefined annotation = context.getAnnotation(); 21 | final String[] keys = annotation.keys(); 22 | final String[] values = annotation.values(); 23 | 24 | return isSatisfied(keys, values); 25 | } 26 | 27 | 28 | private boolean isSatisfied(final String[] keys, final String[] values) { 29 | int index = 0; 30 | for (final String key : keys) { 31 | final String variable = PropUtils.getSystemProperty( 32 | PropUtils.injectProperties(key) 33 | ); 34 | 35 | try { 36 | final String value = PropUtils.injectProperties(values[index++]); 37 | if (!TextUtils.equalsSafe(variable, value)) { 38 | return false; 39 | } 40 | } catch (final IndexOutOfBoundsException ex) { 41 | if (variable == null) { 42 | return false; 43 | } 44 | } 45 | } 46 | return keys.length > 0; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/checker/ResourceIsAvailableChecker.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.checker; 2 | 3 | import com.github.vbauer.jconditions.annotation.ResourceIsAvailable; 4 | import com.github.vbauer.jconditions.core.CheckerContext; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | import com.github.vbauer.jconditions.util.FSUtils; 7 | import com.github.vbauer.jconditions.util.NetUtils; 8 | import com.github.vbauer.jconditions.util.PropUtils; 9 | 10 | import java.io.File; 11 | import java.net.URLConnection; 12 | 13 | /** 14 | * @author Vladislav Bauer 15 | */ 16 | 17 | public class ResourceIsAvailableChecker implements ConditionChecker { 18 | 19 | /** 20 | * {@inheritDoc} 21 | */ 22 | @Override 23 | public boolean isSatisfied(final CheckerContext context) throws Exception { 24 | final ResourceIsAvailable annotation = context.getAnnotation(); 25 | final String source = NetUtils.fixScheme(PropUtils.injectProperties(annotation.source())); 26 | final String target = PropUtils.injectProperties(annotation.target()); 27 | final int timeout = annotation.timeout(); 28 | final boolean cache = annotation.cache(); 29 | 30 | if (!FSUtils.fileExists(target) || !cache && FSUtils.deleteFile(target)) { 31 | final URLConnection urlConnection = NetUtils.connectURL(source, timeout); 32 | final File file = NetUtils.copyURLContentToFile(urlConnection, target); 33 | if (!cache) { 34 | file.deleteOnExit(); 35 | } 36 | return FSUtils.fileExists(target); 37 | } 38 | return true; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/checker/RunIfChecker.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.checker; 2 | 3 | import com.github.vbauer.jconditions.annotation.RunIf; 4 | import com.github.vbauer.jconditions.core.CheckerContext; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | import com.github.vbauer.jconditions.core.ConditionCheckerExecutor; 7 | 8 | /** 9 | * @author Vladislav Bauer 10 | */ 11 | 12 | public class RunIfChecker implements ConditionChecker { 13 | 14 | /** 15 | * {@inheritDoc} 16 | */ 17 | @Override 18 | public boolean isSatisfied(final CheckerContext context) { 19 | final RunIf annotation = context.getAnnotation(); 20 | 21 | @SuppressWarnings("rawtypes") 22 | final Class[] checkerClasses = annotation.value(); 23 | 24 | //noinspection unchecked 25 | return ConditionCheckerExecutor.isSatisfied(context, checkerClasses); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/checker/RunningOnOSChecker.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.checker; 2 | 3 | import com.github.vbauer.jconditions.annotation.RunningOnOS; 4 | import com.github.vbauer.jconditions.core.CheckerContext; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | import com.github.vbauer.jconditions.util.PropUtils; 7 | 8 | /** 9 | * @author Vladislav Bauer 10 | */ 11 | 12 | public class RunningOnOSChecker implements ConditionChecker { 13 | 14 | private static final String PROPERTY_OS_NAME = "os.name"; 15 | 16 | 17 | /** 18 | * {@inheritDoc} 19 | */ 20 | @Override 21 | public boolean isSatisfied(final CheckerContext context) { 22 | final RunningOnOS annotation = context.getAnnotation(); 23 | final String[] operationSystems = annotation.value(); 24 | return PropUtils.hasAnyWithProperties(currentOS(), operationSystems); 25 | } 26 | 27 | 28 | private static String currentOS() { 29 | return PropUtils.getSystemProperty(PROPERTY_OS_NAME).toLowerCase(); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/checker/SocketIsOpenedChecker.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.checker; 2 | 3 | import com.github.vbauer.jconditions.annotation.SocketIsOpened; 4 | import com.github.vbauer.jconditions.core.CheckerContext; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | import com.github.vbauer.jconditions.util.InOutUtils; 7 | import com.github.vbauer.jconditions.util.PropUtils; 8 | 9 | import java.net.InetSocketAddress; 10 | import java.net.Socket; 11 | 12 | /** 13 | * @author Vladislav Bauer 14 | */ 15 | 16 | public class SocketIsOpenedChecker implements ConditionChecker { 17 | 18 | /** 19 | * {@inheritDoc} 20 | */ 21 | @Override 22 | public boolean isSatisfied(final CheckerContext context) throws Exception { 23 | final SocketIsOpened annotation = context.getAnnotation(); 24 | final String host = PropUtils.injectProperties(annotation.host()); 25 | final int port = annotation.port(); 26 | final int timeout = annotation.timeout(); 27 | return isSocketOpened(host, port, timeout); 28 | } 29 | 30 | 31 | private boolean isSocketOpened(final String host, final int port, final int timeout) throws Exception { 32 | Socket socket = null; 33 | try { 34 | socket = new Socket(); 35 | socket.bind(null); 36 | socket.connect(new InetSocketAddress(host, port), timeout); 37 | return true; 38 | } finally { 39 | InOutUtils.closeQuietly(socket); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/checker/UrlIsReachableChecker.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.checker; 2 | 3 | import com.github.vbauer.jconditions.annotation.UrlIsReachable; 4 | import com.github.vbauer.jconditions.core.CheckerContext; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | import com.github.vbauer.jconditions.util.NetUtils; 7 | import com.github.vbauer.jconditions.util.PropUtils; 8 | 9 | /** 10 | * @author Vladislav Bauer 11 | */ 12 | 13 | public class UrlIsReachableChecker implements ConditionChecker { 14 | 15 | /** 16 | * {@inheritDoc} 17 | */ 18 | @Override 19 | public boolean isSatisfied(final CheckerContext context) { 20 | final UrlIsReachable annotation = context.getAnnotation(); 21 | final String[] urlAddresses = annotation.value(); 22 | final int timeout = annotation.timeout(); 23 | return isReachable(urlAddresses, timeout); 24 | } 25 | 26 | 27 | private boolean isReachable(final String[] urlAddresses, final int timeout) { 28 | for (final String urlAddress : urlAddresses) { 29 | final String url = PropUtils.injectProperties(urlAddress); 30 | if (!isReachable(url, timeout)) { 31 | return false; 32 | } 33 | } 34 | return urlAddresses.length > 0; 35 | } 36 | 37 | private boolean isReachable(final String url, final int timeout) { 38 | try { 39 | return NetUtils.connectURL(url, timeout) != null; 40 | } catch (final Exception ex) { 41 | return false; 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/core/CheckerContext.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.core; 2 | 3 | /** 4 | * @param type of context object 5 | * @author Vladislav Bauer 6 | */ 7 | 8 | public class CheckerContext { 9 | 10 | private final Object instance; 11 | private final T annotation; 12 | 13 | 14 | public CheckerContext(final Object instance, final T annotation) { 15 | this.instance = instance; 16 | this.annotation = annotation; 17 | } 18 | 19 | 20 | public Object getInstance() { 21 | return instance; 22 | } 23 | 24 | public T getAnnotation() { 25 | return annotation; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/core/Condition.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.core; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Condition is the core feature of JConditions extension mechanism. 10 | * All other conditional annotations could be built on top of this annotation. 11 | *

12 | * It allows to specify checker that should be run before execution of test method. 13 | * This checker permits or restricts to run test. 14 | *

15 | * See an example here: {@link com.github.vbauer.jconditions.annotation.HasClass} 16 | * 17 | * @author Vladislav Bauer 18 | */ 19 | 20 | @Target(ElementType.ANNOTATION_TYPE) 21 | @Retention(RetentionPolicy.RUNTIME) 22 | public @interface Condition { 23 | 24 | /** 25 | * Conditional checker class that will be instantiated and run before test. 26 | * 27 | * @return conditional checker class 28 | */ 29 | @SuppressWarnings("rawtypes") 30 | Class value(); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/core/ConditionChecker.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.core; 2 | 3 | /** 4 | * Conditional checker describes a rule which permits or restricts execution of test method. 5 | * 6 | * There are some moments that are useful to know about them: 7 | *

    8 | *
  • Checker class could have any kind of access modifier on class/constructor.
  • 9 | *
  • Condition checker must have constructor without arguments.
  • 10 | *
  • Constructor could have any kind of access modifier.
  • 11 | *
12 | * 13 | * @param type of context object 14 | * @author Vladislav Bauer 15 | */ 16 | 17 | public interface ConditionChecker { 18 | 19 | /** 20 | * Checks if execution of test method should be continued or not. 21 | * 22 | * @param context input data for checker 23 | * @return true if execution should be continued and false - otherwise 24 | * @throws Exception on any error (it is the same as false in return value) 25 | */ 26 | boolean isSatisfied(CheckerContext context) throws Exception; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/core/ConditionCheckerEngine.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.core; 2 | 3 | import com.github.vbauer.jconditions.util.ReflexUtils; 4 | import org.junit.runners.model.FrameworkMethod; 5 | 6 | import java.lang.annotation.Annotation; 7 | import java.util.Arrays; 8 | import java.util.Collection; 9 | 10 | /** 11 | * @author Vladislav Bauer 12 | */ 13 | 14 | public final class ConditionCheckerEngine { 15 | 16 | private ConditionCheckerEngine() { 17 | throw new UnsupportedOperationException(); 18 | } 19 | 20 | 21 | public static ConditionChecker detectFailedChecker( 22 | final Object instance, final FrameworkMethod method 23 | ) { 24 | final Collection annotations = findAllAnnotations(instance, method); 25 | return findCheckerByAnnotations(instance, null, annotations); 26 | } 27 | 28 | 29 | private static ConditionChecker findCheckerByAnnotations( 30 | final Object instance, final Annotation parent, final Collection annotations 31 | ) { 32 | for (final Annotation annotation : annotations) { 33 | final ConditionChecker checker = 34 | getConditionChecker(instance, parent, annotation); 35 | 36 | if (checker != null) { 37 | return checker; 38 | } 39 | } 40 | return null; 41 | } 42 | 43 | private static ConditionChecker getConditionChecker( 44 | final Object instance, final Annotation parent, final Annotation annotation 45 | ) { 46 | if (!ReflexUtils.isInJavaLangAnnotationPackage(annotation)) { 47 | final Class annotationType = annotation.annotationType(); 48 | 49 | if (annotationType == Condition.class) { 50 | final Condition condition = (Condition) annotation; 51 | final ConditionChecker checker = 52 | findCheckerByCondition(instance, parent, condition); 53 | 54 | if (checker != null) { 55 | return checker; 56 | } 57 | } 58 | 59 | final Collection extra = 60 | Arrays.asList(annotationType.getAnnotations()); 61 | 62 | final ConditionChecker checker = 63 | findCheckerByAnnotations(instance, annotation, extra); 64 | 65 | if (checker != null) { 66 | return checker; 67 | } 68 | } 69 | return null; 70 | } 71 | 72 | @SuppressWarnings({"unchecked", "rawtypes"}) 73 | private static ConditionChecker findCheckerByCondition( 74 | final T instance, final Annotation parent, final Condition condition 75 | ) { 76 | final Class checkerClass = condition.value(); 77 | final ConditionChecker checker = ReflexUtils.instantiate(instance, checkerClass); 78 | final CheckerContext context = new CheckerContext(instance, parent); 79 | 80 | if (!ConditionCheckerExecutor.isSatisfied(context, checker)) { 81 | return checker; 82 | } 83 | return null; 84 | } 85 | 86 | private static Collection findAllAnnotations( 87 | final Object instance, final FrameworkMethod method 88 | ) { 89 | final Collection result = ReflexUtils.findAllAnnotations(instance.getClass()); 90 | result.addAll(Arrays.asList(method.getAnnotations())); 91 | return result; 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/core/ConditionCheckerExecutor.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.core; 2 | 3 | import com.github.vbauer.jconditions.util.ReflexUtils; 4 | 5 | /** 6 | * @author Vladislav Bauer 7 | */ 8 | 9 | public final class ConditionCheckerExecutor { 10 | 11 | private ConditionCheckerExecutor() { 12 | throw new UnsupportedOperationException(); 13 | } 14 | 15 | 16 | @SafeVarargs 17 | @SuppressWarnings("rawtypes") 18 | public static boolean isSatisfied( 19 | final CheckerContext context, 20 | final Class... checkerClasses 21 | ) { 22 | for (final Class checkerClass : checkerClasses) { 23 | if (!isSatisfied(context, checkerClass)) { 24 | return false; 25 | } 26 | } 27 | return true; 28 | } 29 | 30 | @SuppressWarnings("rawtypes") 31 | public static boolean isSatisfied( 32 | final CheckerContext context, 33 | final Class checkerClass 34 | ) { 35 | final Object instance = context.getInstance(); 36 | final ConditionChecker checker = ReflexUtils.instantiate(instance, checkerClass); 37 | return isSatisfied(context, checker); 38 | } 39 | 40 | @SuppressWarnings({"unchecked", "rawtypes"}) 41 | public static boolean isSatisfied( 42 | final CheckerContext context, final ConditionChecker checker 43 | ) { 44 | try { 45 | return checker.isSatisfied(context); 46 | } catch (final Throwable ex) { 47 | return false; 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/core/junit/ConditionRule.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.core.junit; 2 | 3 | import com.github.vbauer.jconditions.core.ConditionChecker; 4 | import com.github.vbauer.jconditions.core.ConditionCheckerEngine; 5 | import org.junit.rules.MethodRule; 6 | import org.junit.runners.model.FrameworkMethod; 7 | import org.junit.runners.model.Statement; 8 | 9 | /** 10 | * @see MethodRule 11 | * @author Vladislav Bauer 12 | */ 13 | 14 | public class ConditionRule implements MethodRule { 15 | 16 | /** 17 | * {@inheritDoc} 18 | */ 19 | @Override 20 | public Statement apply( 21 | final Statement base, final FrameworkMethod method, final Object target 22 | ) { 23 | final ConditionChecker checker = 24 | ConditionCheckerEngine.detectFailedChecker(target, method); 25 | 26 | if (checker != null) { 27 | return new IgnoreStatement(checker); 28 | } 29 | return base; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/core/junit/ConditionTestRunner.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.core.junit; 2 | 3 | import com.github.vbauer.jconditions.core.ConditionChecker; 4 | import com.github.vbauer.jconditions.core.ConditionCheckerEngine; 5 | import com.github.vbauer.jconditions.util.ReflexUtils; 6 | import org.junit.internal.runners.statements.InvokeMethod; 7 | import org.junit.runner.Description; 8 | import org.junit.runner.notification.RunNotifier; 9 | import org.junit.runners.BlockJUnit4ClassRunner; 10 | import org.junit.runners.model.FrameworkMethod; 11 | import org.junit.runners.model.InitializationError; 12 | 13 | /** 14 | * @author Vladislav Bauer 15 | */ 16 | 17 | public class ConditionTestRunner extends BlockJUnit4ClassRunner { 18 | 19 | public ConditionTestRunner(final Class clazz) throws InitializationError { 20 | super(clazz); 21 | } 22 | 23 | 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | @Override 28 | protected void runChild(final FrameworkMethod method, final RunNotifier notifier) { 29 | final Description description = describeChild(method); 30 | if (isIgnored(method)) { 31 | notifier.fireTestIgnored(description); 32 | } else { 33 | final InvokeMethod statement = (InvokeMethod) methodBlock(method); 34 | final Object test = ReflexUtils.getFieldValue(statement, "target"); 35 | 36 | final ConditionChecker checker = 37 | ConditionCheckerEngine.detectFailedChecker(test, method); 38 | 39 | if (checker != null) { 40 | notifier.fireTestIgnored(description); 41 | } else { 42 | runLeaf(statement, description, notifier); 43 | } 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/core/junit/IgnoreStatement.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.core.junit; 2 | 3 | import com.github.vbauer.jconditions.core.ConditionChecker; 4 | import org.junit.AssumptionViolatedException; 5 | import org.junit.runners.model.Statement; 6 | 7 | /** 8 | * @author Vladislav Bauer 9 | */ 10 | 11 | public class IgnoreStatement extends Statement { 12 | 13 | private final ConditionChecker condition; 14 | 15 | 16 | public IgnoreStatement(final ConditionChecker condition) { 17 | this.condition = condition; 18 | } 19 | 20 | 21 | /** 22 | * {@inheritDoc} 23 | */ 24 | @Override 25 | public void evaluate() { 26 | final String conditionClassName = getConditionName(); 27 | throw new AssumptionViolatedException("Ignored by " + conditionClassName); 28 | } 29 | 30 | 31 | private String getConditionName() { 32 | final Class conditionClass = condition.getClass(); 33 | return conditionClass.getSimpleName(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/util/FSUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.util; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | /** 7 | * @author Vladislav Bauer 8 | */ 9 | 10 | public final class FSUtils { 11 | 12 | private FSUtils() { 13 | throw new UnsupportedOperationException(); 14 | } 15 | 16 | 17 | public static boolean exists(final String path) { 18 | final File file = new File(path); 19 | return file.exists(); 20 | } 21 | 22 | public static boolean fileExists(final String path) { 23 | final File file = new File(path); 24 | return file.exists() && file.isFile(); 25 | } 26 | 27 | public static boolean directoryExists(final String path) { 28 | final File file = new File(path); 29 | return file.exists() && file.isDirectory(); 30 | } 31 | 32 | public static boolean isSymlink(final String path) throws IOException { 33 | final File file = new File(path); 34 | final File fileInCanonicalDir; 35 | 36 | if (file.getParent() == null) { 37 | fileInCanonicalDir = file; 38 | } else { 39 | fileInCanonicalDir = new File(file.getParentFile().getCanonicalFile(), file.getName()); 40 | } 41 | 42 | final File canonicalFile = fileInCanonicalDir.getCanonicalFile(); 43 | final File absoluteFile = fileInCanonicalDir.getAbsoluteFile(); 44 | return !canonicalFile.equals(absoluteFile); 45 | } 46 | 47 | public static boolean deleteFile(final String path) { 48 | final File file = new File(path); 49 | return file.delete(); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/util/InOutUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.util; 2 | 3 | import java.io.Closeable; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.OutputStream; 7 | 8 | /** 9 | * @author Vladislav Bauer 10 | */ 11 | 12 | public final class InOutUtils { 13 | 14 | private static final int BUFFER_SIZE = 1024; 15 | private static final int EOF = -1; 16 | 17 | 18 | private InOutUtils() { 19 | throw new UnsupportedOperationException(); 20 | } 21 | 22 | 23 | public static boolean closeQuietly(final Closeable closeable) { 24 | try { 25 | closeable.close(); 26 | return true; 27 | } catch (final Exception ex) { 28 | return false; 29 | } 30 | } 31 | 32 | public static void copy(final InputStream input, final OutputStream output) throws IOException { 33 | final byte[] bytes = new byte[BUFFER_SIZE]; 34 | int read; 35 | 36 | while ((read = input.read(bytes)) != EOF) { 37 | output.write(bytes, 0, read); 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/util/NetUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.util; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.OutputStream; 8 | import java.net.URI; 9 | import java.net.URL; 10 | import java.net.URLConnection; 11 | 12 | /** 13 | * @author Vladislav Bauer 14 | */ 15 | 16 | public final class NetUtils { 17 | 18 | private static final String HTTP_PREFIX = "http://"; 19 | 20 | 21 | private NetUtils() { 22 | throw new UnsupportedOperationException(); 23 | } 24 | 25 | 26 | public static String fixScheme(final String address) { 27 | if (address != null) { 28 | final URI uri = URI.create(address); 29 | final String scheme = uri.getScheme(); 30 | 31 | if (scheme == null) { 32 | return HTTP_PREFIX + address; 33 | } 34 | } 35 | return address; 36 | } 37 | 38 | public static File copyURLContentToFile(final URLConnection connection, final String target) throws Exception { 39 | InputStream input = null; 40 | OutputStream output = null; 41 | 42 | try { 43 | final File file = new File(target); 44 | output = new FileOutputStream(file); 45 | input = connection.getInputStream(); 46 | InOutUtils.copy(input, output); 47 | return file; 48 | } finally { 49 | InOutUtils.closeQuietly(input); 50 | InOutUtils.closeQuietly(output); 51 | } 52 | } 53 | 54 | public static URLConnection connectURL(final String uri, final int timeout) throws IOException { 55 | final URL url = new URL(uri); 56 | final URLConnection connection = url.openConnection(); 57 | connection.setConnectTimeout(timeout); 58 | connection.connect(); 59 | return connection; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/util/PropUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.util; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.Properties; 6 | 7 | /** 8 | * @author Vladislav Bauer 9 | */ 10 | 11 | public final class PropUtils { 12 | 13 | private static final String VAR_PREFIX = "${"; 14 | private static final String VAR_POSTFIX = "}"; 15 | 16 | 17 | private PropUtils() { 18 | throw new UnsupportedOperationException(); 19 | } 20 | 21 | 22 | public static String getSystemProperty(final String key) { 23 | final Map properties = getSystemProperties(); 24 | return properties.get(key); 25 | } 26 | 27 | public static Map getSystemProperties() { 28 | final Map result = new HashMap<>(); 29 | result.putAll(System.getenv()); 30 | result.putAll(convertPropertiesToMap(System.getProperties())); 31 | return result; 32 | } 33 | 34 | public static Map convertPropertiesToMap(final Properties properties) { 35 | final Map result = new HashMap<>(); 36 | for (final String name : properties.stringPropertyNames()) { 37 | result.put(name, properties.getProperty(name)); 38 | } 39 | return result; 40 | } 41 | 42 | public static String injectProperties(final String text) { 43 | if (text != null && text.contains(VAR_PREFIX)) { 44 | String result = text; 45 | final Map systemProperties = getSystemProperties(); 46 | for (final Map.Entry entry : systemProperties.entrySet()) { 47 | final String key = entry.getKey(); 48 | final String value = entry.getValue(); 49 | result = result.replace(VAR_PREFIX + key + VAR_POSTFIX, value); 50 | } 51 | return result; 52 | } 53 | return text; 54 | } 55 | 56 | public static boolean hasAnyWithProperties(final String value, final String... variants) { 57 | for (final String operationSystem : variants) { 58 | final String injected = injectProperties(operationSystem); 59 | if (TextUtils.containsIgnoreCase(value, injected)) { 60 | return true; 61 | } 62 | } 63 | return false; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/util/ReflexUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.util; 2 | 3 | import java.lang.annotation.Annotation; 4 | import java.lang.reflect.AccessibleObject; 5 | import java.lang.reflect.Constructor; 6 | import java.lang.reflect.Field; 7 | import java.lang.reflect.Modifier; 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.Collection; 11 | import java.util.List; 12 | 13 | /** 14 | * @author Vladislav Bauer 15 | */ 16 | 17 | public final class ReflexUtils { 18 | 19 | private static final String PACKAGE_JAVA_LANG_ANNOTATION = "java.lang.annotation"; 20 | 21 | 22 | private ReflexUtils() { 23 | throw new UnsupportedOperationException(); 24 | } 25 | 26 | 27 | public static boolean isInJavaLangAnnotationPackage(final Annotation annotation) { 28 | final Class annotationType = annotation.annotationType(); 29 | final String annotationTypeName = annotationType.getName(); 30 | return annotationTypeName.startsWith(PACKAGE_JAVA_LANG_ANNOTATION); 31 | } 32 | 33 | @SuppressWarnings("unchecked") 34 | public static T getFieldValue(final Object object, final String fieldName) { 35 | try { 36 | final Class objectClass = object.getClass(); 37 | final Field field = objectClass.getDeclaredField(fieldName); 38 | field.setAccessible(true); 39 | return (T) field.get(object); 40 | } catch (final Exception ex) { 41 | return null; 42 | } 43 | } 44 | 45 | public static T makeAccessible(final T object) { 46 | if (!object.isAccessible()) { 47 | object.setAccessible(true); 48 | } 49 | return object; 50 | } 51 | 52 | public static Collection findAllAnnotations(final Class clazz) { 53 | final List result = new ArrayList<>(); 54 | Class current = clazz; 55 | 56 | while (current != Object.class && current != null) { 57 | final Class[] interfaces = current.getInterfaces(); 58 | for (final Class i : interfaces) { 59 | result.addAll(findAllAnnotations(i)); 60 | } 61 | 62 | result.addAll(Arrays.asList(current.getAnnotations())); 63 | current = current.getSuperclass(); 64 | } 65 | return result; 66 | } 67 | 68 | public static T instantiate(final Object instance, final Class checkerClass) { 69 | try { 70 | return instantiateImpl(instance, checkerClass); 71 | } catch (final RuntimeException ex) { 72 | throw ex; 73 | } catch (final Exception ex) { 74 | throw new RuntimeException(ex); 75 | } 76 | } 77 | 78 | 79 | private static T instantiateImpl(final Object instance, final Class clazz) throws Exception { 80 | if (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers())) { 81 | return instantiateInnerClass(instance, clazz); 82 | } 83 | return instantiateClass(clazz); 84 | } 85 | 86 | private static T instantiateClass(final Class clazz) throws Exception { 87 | final Constructor constructor = clazz.getDeclaredConstructor(); 88 | return ReflexUtils.makeAccessible(constructor).newInstance(); 89 | } 90 | 91 | private static T instantiateInnerClass( 92 | final Object instance, final Class clazz 93 | ) throws Exception { 94 | final Class outerClass = clazz.getDeclaringClass(); 95 | final Constructor constructor = clazz.getDeclaredConstructor(outerClass); 96 | return ReflexUtils.makeAccessible(constructor).newInstance(instance); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/util/ScriptUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.util; 2 | 3 | import javax.script.ScriptContext; 4 | import javax.script.ScriptEngine; 5 | import javax.script.ScriptEngineFactory; 6 | import javax.script.ScriptEngineManager; 7 | import java.util.List; 8 | 9 | /** 10 | * @author Vladislav Bauer 11 | */ 12 | 13 | public final class ScriptUtils { 14 | 15 | private ScriptUtils() { 16 | throw new UnsupportedOperationException(); 17 | } 18 | 19 | 20 | public static ScriptEngine findScriptEngine(final String engine) { 21 | final ScriptEngineManager engineManager = new ScriptEngineManager(); 22 | final List engineFactories = engineManager.getEngineFactories(); 23 | 24 | for (final ScriptEngineFactory engineFactory : engineFactories) { 25 | if (isSameEngine(engineFactory, engine)) { 26 | return engineFactory.getScriptEngine(); 27 | } 28 | } 29 | return null; 30 | } 31 | 32 | public static void addAttribute( 33 | final ScriptContext context, final String key, final Object value 34 | ) { 35 | context.setAttribute(key, value, ScriptContext.ENGINE_SCOPE); 36 | } 37 | 38 | private static boolean isSameEngine(final ScriptEngineFactory factory, final String engine) { 39 | return sameName(factory, engine) 40 | || sameLanguage(factory, engine) 41 | || sameNames(factory, engine) 42 | || sameMimeTypes(factory, engine); 43 | } 44 | 45 | private static boolean sameMimeTypes(final ScriptEngineFactory factory, final String engine) { 46 | final List mimeTypes = factory.getMimeTypes(); 47 | if (mimeTypes != null) { 48 | for (final String mimeType : mimeTypes) { 49 | if (TextUtils.containsIgnoreCase(mimeType, engine)) { 50 | return true; 51 | } 52 | } 53 | } 54 | return false; 55 | } 56 | 57 | private static boolean sameNames(final ScriptEngineFactory factory, final String engine) { 58 | final List names = factory.getNames(); 59 | if (names != null) { 60 | for (final String name : names) { 61 | if (TextUtils.containsIgnoreCase(name, engine)) { 62 | return true; 63 | } 64 | } 65 | } 66 | return false; 67 | } 68 | 69 | private static boolean sameLanguage(final ScriptEngineFactory factory, final String engine) { 70 | final String languageName = factory.getLanguageName(); 71 | return TextUtils.containsIgnoreCase(languageName, engine); 72 | } 73 | 74 | private static boolean sameName(final ScriptEngineFactory factory, final String engine) { 75 | final String engineName = factory.getEngineName(); 76 | return TextUtils.containsIgnoreCase(engineName, engine); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/github/vbauer/jconditions/util/TextUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.util; 2 | 3 | /** 4 | * @author Vladislav Bauer 5 | */ 6 | 7 | public final class TextUtils { 8 | 9 | private TextUtils() { 10 | throw new UnsupportedOperationException(); 11 | } 12 | 13 | 14 | public static boolean equalsSafe(final String a, final String b) { 15 | return a == null && b == null || a != null && a.equals(b); 16 | } 17 | 18 | public static boolean containsIgnoreCase(final String a, final String b) { 19 | return a != null && b != null && a.toLowerCase().contains(b.toLowerCase()); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/com/github/vbauer/jconditions/annotation/AbstractAnnotationsTest.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.checker.IfJavaVersionChecker; 4 | import com.github.vbauer.jconditions.core.CheckerContext; 5 | import com.github.vbauer.jconditions.core.ConditionChecker; 6 | import com.github.vbauer.jconditions.misc.Always; 7 | import com.github.vbauer.jconditions.misc.AppleWorksFine; 8 | import com.github.vbauer.jconditions.misc.Never; 9 | import com.github.vbauer.jconditions.util.FSUtils; 10 | import com.github.vbauer.jconditions.util.PropUtils; 11 | import org.junit.Assert; 12 | import org.junit.Ignore; 13 | import org.junit.Test; 14 | 15 | import java.net.URL; 16 | import java.net.URLConnection; 17 | import java.util.concurrent.Callable; 18 | 19 | /** 20 | * @author Vladislav Bauer 21 | */ 22 | 23 | @Ignore 24 | public abstract class AbstractAnnotationsTest implements InterfaceAnnotationsTest { 25 | 26 | @SuppressWarnings("all") 27 | private final boolean isSatisfiedInnerCheck = false; 28 | 29 | 30 | @Test 31 | @RunIf(ExceptionClass.class) 32 | public void testIgnoreIfException() { 33 | Assert.fail(); 34 | } 35 | 36 | @Test 37 | @IgnoreIf(Always.class) 38 | public void testIgnoreIfAlways() { 39 | Assert.fail(); 40 | } 41 | 42 | @Test 43 | @IgnoreIf(Never.class) 44 | public void testIgnoreIfNever() { 45 | Assert.assertTrue(true); 46 | } 47 | 48 | @Test 49 | @RunIf(InnerClass.class) 50 | public void testInnerClass() { 51 | Assert.fail(); 52 | } 53 | 54 | @Test 55 | @RunIf(StaticNestedClass.class) 56 | public void testStaticNestedClass() { 57 | Assert.fail(); 58 | } 59 | 60 | @Test 61 | @AppIsInstalled({ "ls", "uname" }) 62 | public void testAppIsInstalled() throws Exception { 63 | exec("ls"); 64 | exec("uname"); 65 | } 66 | 67 | @Test 68 | @AppIsInstalled({ "fake-app-12345" }) 69 | public void testAppIsNotInstalled() { 70 | Assert.fail(); 71 | } 72 | 73 | @Test 74 | @ExistsOnFS("pom.xml") 75 | public void testFileExists() { 76 | Assert.assertTrue(FSUtils.fileExists("pom.xml")); 77 | } 78 | 79 | @Test 80 | @ExistsOnFS(value = "src", type = { ExistsOnFS.Type.DIRECTORY, ExistsOnFS.Type.SYMLINK }) 81 | public void testDirectoryExists() { 82 | Assert.assertTrue(FSUtils.directoryExists("src")); 83 | } 84 | 85 | @Test 86 | @ExistsOnFS("pom.xml2") 87 | public void testFileNotExists() { 88 | Assert.fail(); 89 | } 90 | 91 | @Test 92 | @SocketIsOpened(host = "apple.com", port = 80) 93 | public void testSocketIsOpened() throws Exception { 94 | checkSite("http://apple.com"); 95 | } 96 | 97 | @Test 98 | @UrlIsReachable("http://apple.com") 99 | public void testUrlIsReachable() throws Exception { 100 | checkSite("http://apple.com"); 101 | } 102 | 103 | @Test 104 | @UrlIsReachable("http://it-is-a-wrong-url-address.com") 105 | public void testUrlIsNotReachable() { 106 | Assert.fail(); 107 | } 108 | 109 | @Test 110 | @RunningOnOS({ 111 | RunningOnOS.AIX, 112 | RunningOnOS.HP_UX, 113 | RunningOnOS.IRIX, 114 | RunningOnOS.LINUX, 115 | RunningOnOS.MAC, 116 | RunningOnOS.MAC_OSX, 117 | RunningOnOS.SOLARIS, 118 | RunningOnOS.SUN_OS 119 | }) 120 | public void testRunningOnOS() throws Exception { 121 | exec("ls"); 122 | } 123 | 124 | @Test 125 | @HasClass("org.junit.Assert") 126 | public void testHasClass() throws Exception { 127 | Assert.assertNotNull(Class.forName("org.junit.Assert")); 128 | } 129 | 130 | @Test 131 | @HasClass("org.wrong.package.WrongClass") 132 | public void testHasClassNegative() { 133 | Assert.fail(); 134 | } 135 | 136 | @Test 137 | @HasPackage("org.junit") 138 | public void testHasPackage() { 139 | Assert.assertNotNull(Package.getPackage("org.junit")); 140 | } 141 | 142 | @Test 143 | @HasPackage("org.wrong.package") 144 | public void testHasPackageNegative() { 145 | Assert.fail(); 146 | } 147 | 148 | @Test 149 | @PropertyIsDefined(keys = "os.name") 150 | public void testEnvVarIsDefined() { 151 | Assert.assertNotNull(PropUtils.getSystemProperty("os.name")); 152 | } 153 | 154 | @Test 155 | @PropertyIsDefined(keys = "unknown.env.parameter") 156 | public void testEnvVarHasWrongKey() { 157 | Assert.fail(); 158 | } 159 | 160 | @Test 161 | @PropertyIsDefined(keys = "os.name", values = "Linux2") 162 | public void testEnvVarHasWrongValue() { 163 | Assert.fail(); 164 | } 165 | 166 | @Test 167 | @AppleWorksFine 168 | public void testCustomAnnotation() throws Exception { 169 | checkSite("http://apple.com"); 170 | } 171 | 172 | @Test 173 | @IfScript("true") 174 | public void testIfScript() { 175 | Assert.assertTrue(true); 176 | } 177 | 178 | @Test 179 | @IfScript("test.isSatisfiedInnerCheck") 180 | public void testIfScriptNegative() { 181 | Assert.fail(); 182 | } 183 | 184 | @Test 185 | @IfScript(value = "0", engine = "application/javascript") 186 | public void testIfScriptMimeType() { 187 | Assert.fail(); 188 | } 189 | 190 | @Test 191 | @IfScript(value = "true", engine = "unknown") 192 | public void testIfScriptWrongEngine() { 193 | Assert.fail(); 194 | } 195 | 196 | @Test 197 | @IfScript(value = "context == true", context = ExtraContext.class) 198 | public void testIfScriptContext() { 199 | Assert.fail(); 200 | } 201 | 202 | @Test 203 | @ResourceIsAvailable( 204 | source = "http://apple.com", 205 | target = "${java.io.tmpdir}/apple-homepage.html", 206 | cache = false 207 | ) 208 | public void testResourceIsAvailable() { 209 | checkTempFile("apple-homepage.html"); 210 | } 211 | 212 | @Test 213 | @ResourceIsAvailable(source = "google.com", target = "${java.io.tmpdir}/google.html") 214 | public void testResourceIsAvailableAutoSchema() { 215 | checkTempFile("google.html"); 216 | } 217 | 218 | @Test 219 | @ResourceIsAvailable(source = "google.com", target = "${java.io.tmpdir}/google.html") 220 | public void testResourceIsAvailableCache() { 221 | checkTempFile("google.html"); 222 | } 223 | 224 | @Test 225 | @IfJavaVersion(IfJavaVersion.JAVA_8) 226 | public void testIfJavaVersion8() { 227 | Assert.assertTrue(IfJavaVersionChecker.javaVersion().contains("8")); 228 | Assert.assertNotNull(javaslang.Tuple0.instance()); 229 | } 230 | 231 | @Test 232 | @IfJavaVersion(IfJavaVersion.JAVA_9) 233 | public void testIfJavaVersion9() { 234 | Assert.assertTrue(IfJavaVersionChecker.javaVersion().contains("9")); 235 | Assert.assertNotNull(javaslang.Tuple0.instance()); 236 | } 237 | 238 | @Test 239 | @HasFreeSpace(value = { "/", "C:\\" }, min = 1024) 240 | public void testHasFreeSpace() { 241 | Assert.assertTrue(true); 242 | } 243 | 244 | @Test 245 | @HasFreeSpace(value = { "/", "C:\\" }, min = Long.MAX_VALUE) 246 | public void testHasNotMinFreeSpace() { 247 | Assert.fail(); 248 | } 249 | 250 | @Test 251 | @HasFreeSpace(value = { "/", "C:\\" }, max = 1024) 252 | public void testHasNotMaxFreeSpace() { 253 | Assert.fail(); 254 | } 255 | 256 | @Test 257 | @Ignore 258 | public void testStandardIgnore() { 259 | Assert.fail("Standard @Ignore annotation was broken"); 260 | } 261 | 262 | 263 | private void checkSite(final String urlAddress) throws Exception { 264 | final URL url = new URL(urlAddress); 265 | final URLConnection connection = url.openConnection(); 266 | connection.connect(); 267 | Assert.assertNotNull(connection); 268 | } 269 | 270 | private void exec(final String ls) throws Exception { 271 | final Runtime runtime = Runtime.getRuntime(); 272 | final Process process = runtime.exec(ls); 273 | Assert.assertEquals(0, process.waitFor()); 274 | } 275 | 276 | private void checkTempFile(final String filePath) { 277 | final String path = PropUtils.injectProperties("${java.io.tmpdir}/" + filePath); 278 | Assert.assertTrue(FSUtils.fileExists(path)); 279 | } 280 | 281 | 282 | /** 283 | * @author Vladislav Bauer 284 | */ 285 | private static final class ExceptionClass implements ConditionChecker { 286 | @Override 287 | public boolean isSatisfied(final CheckerContext context) { 288 | throw new RuntimeException(); 289 | } 290 | } 291 | 292 | /** 293 | * @author Vladislav Bauer 294 | */ 295 | private class InnerClass implements ConditionChecker { 296 | @Override 297 | public boolean isSatisfied(final CheckerContext context) { 298 | return isSatisfiedInnerCheck; 299 | } 300 | } 301 | 302 | /** 303 | * @author Vladislav Bauer 304 | */ 305 | private static class StaticNestedClass implements ConditionChecker { 306 | @Override 307 | public boolean isSatisfied(final CheckerContext context) { 308 | return false; 309 | } 310 | } 311 | 312 | /** 313 | * @author Vladislav Bauer 314 | */ 315 | private static class ExtraContext implements Callable { 316 | @Override 317 | public Boolean call() { 318 | return false; 319 | } 320 | } 321 | 322 | } 323 | -------------------------------------------------------------------------------- /src/test/java/com/github/vbauer/jconditions/annotation/InterfaceAnnotationsTest.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.misc.Never; 4 | 5 | /** 6 | * @author Vladislav Bauer 7 | */ 8 | 9 | @IgnoreIf(Never.class) 10 | public interface InterfaceAnnotationsTest { 11 | } 12 | -------------------------------------------------------------------------------- /src/test/java/com/github/vbauer/jconditions/annotation/RuleAnnotationsTest.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.core.junit.ConditionRule; 4 | import org.junit.Rule; 5 | 6 | /** 7 | * @author Vladislav Bauer 8 | */ 9 | 10 | public class RuleAnnotationsTest extends AbstractAnnotationsTest { 11 | 12 | @Rule 13 | public final ConditionRule rule = new ConditionRule(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/com/github/vbauer/jconditions/annotation/RunnerAnnotationTest.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.annotation; 2 | 3 | import com.github.vbauer.jconditions.core.junit.ConditionTestRunner; 4 | import org.junit.runner.RunWith; 5 | 6 | /** 7 | * @author Vladislav Bauer 8 | */ 9 | 10 | @RunWith(ConditionTestRunner.class) 11 | public class RunnerAnnotationTest extends AbstractAnnotationsTest { 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/com/github/vbauer/jconditions/misc/Always.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.misc; 2 | 3 | import com.github.vbauer.jconditions.core.CheckerContext; 4 | import com.github.vbauer.jconditions.core.ConditionChecker; 5 | 6 | /** 7 | * @author Vladislav Bauer 8 | */ 9 | 10 | public class Always implements ConditionChecker { 11 | 12 | @Override 13 | public boolean isSatisfied(final CheckerContext context) { 14 | return true; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/github/vbauer/jconditions/misc/AppleWorksFine.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.misc; 2 | 3 | import com.github.vbauer.jconditions.annotation.SocketIsOpened; 4 | import com.github.vbauer.jconditions.annotation.UrlIsReachable; 5 | 6 | import java.lang.annotation.ElementType; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | 11 | /** 12 | * @author Vladislav Bauer 13 | */ 14 | 15 | @SocketIsOpened(host = "apple.com", port = 80) 16 | @UrlIsReachable({ "http://apple.com", "https://itunes.apple.com" }) 17 | @Retention(RetentionPolicy.RUNTIME) 18 | @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) 19 | public @interface AppleWorksFine { 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/com/github/vbauer/jconditions/misc/Never.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.misc; 2 | 3 | import com.github.vbauer.jconditions.core.CheckerContext; 4 | import com.github.vbauer.jconditions.core.ConditionChecker; 5 | 6 | /** 7 | * @author Vladislav Bauer 8 | */ 9 | public class Never implements ConditionChecker { 10 | 11 | @Override 12 | public boolean isSatisfied(final CheckerContext context) { 13 | return false; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/github/vbauer/jconditions/util/ConstructorContractTest.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.util; 2 | 3 | import org.junit.Test; 4 | 5 | import com.github.vbauer.jconditions.core.CheckerContext; 6 | import com.github.vbauer.jconditions.core.ConditionChecker; 7 | import com.github.vbauer.jconditions.core.ConditionCheckerEngine; 8 | import com.github.vbauer.jconditions.core.ConditionCheckerExecutor; 9 | import com.pushtorefresh.private_constructor_checker.PrivateConstructorChecker; 10 | 11 | /** 12 | * @author Vladislav Bauer 13 | */ 14 | 15 | public class ConstructorContractTest { 16 | 17 | @Test 18 | public void testConstructors() { 19 | PrivateConstructorChecker 20 | .forClasses( 21 | ConditionCheckerEngine.class, 22 | ConditionCheckerExecutor.class, 23 | FSUtils.class, 24 | InOutUtils.class, 25 | NetUtils.class, 26 | PropUtils.class, 27 | ReflexUtils.class, 28 | ScriptUtils.class, 29 | TextUtils.class 30 | ) 31 | .expectedTypeOfException(UnsupportedOperationException.class) 32 | .check(); 33 | } 34 | 35 | @Test(expected = RuntimeException.class) 36 | public void testInstantiateNegativeRuntimeException() { 37 | ReflexUtils.instantiate(null, null); 38 | } 39 | 40 | @Test(expected = Exception.class) 41 | public void testInstantiateNegativeException() { 42 | ReflexUtils.instantiate(new Object(), NegativeChecker.class); 43 | } 44 | 45 | 46 | private class NegativeChecker implements ConditionChecker { 47 | private final boolean value; 48 | 49 | private NegativeChecker(final boolean value) { 50 | this.value = value; 51 | } 52 | 53 | @Override 54 | public boolean isSatisfied(final CheckerContext context) { 55 | return value; 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/test/java/com/github/vbauer/jconditions/util/InOutUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.util; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | /** 7 | * @author Vladislav Bauer 8 | */ 9 | 10 | public class InOutUtilsTest { 11 | 12 | @Test 13 | public void testCloseNegative() { 14 | Assert.assertFalse(InOutUtils.closeQuietly(null)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/github/vbauer/jconditions/util/ReflexUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.github.vbauer.jconditions.util; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | /** 7 | * @author Vladislav Bauer 8 | */ 9 | 10 | public class ReflexUtilsTest { 11 | 12 | @Test 13 | public void testGetFieldNegative() { 14 | Assert.assertNull(ReflexUtils.getFieldValue(null, null)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/test/resources/checkstyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | --------------------------------------------------------------------------------