From 02fe117cfaf3fb8924d5c6eea20f43344b57509a Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Tue, 31 Aug 2021 11:34:36 +0200 Subject: [PATCH 1/5] Wipe previous content. --- .editorconfig | 17 - .gitignore | 14 - CHANGES.txt | 406 ---- CONTRIBUTING.txt | 9 - LICENSE.txt | 202 -- README.txt | 15 - .../settings/org.eclipse.jdt.core.prefs | 286 --- etc/eclipse/settings/org.eclipse.jdt.ui.prefs | 4 - etc/forbidden-apis/signatures.txt | 38 - examples/ant/build.xml | 165 -- examples/ant/pom.xml | 140 -- examples/maven/pom.xml | 103 - .../Test001SimpleUseCase.java | 31 - .../Test002ExtendingRandomizedTest.java | 34 - .../Test003UsingRandomness.java | 92 - .../Test004MoreRandomness.java | 87 - .../Test005RecoveringRandomSeed.java | 83 - .../Test006RepeatingTests.java | 52 - .../Test007ParameterizedTests.java | 97 - .../randomizedrunner/Test008Timeouts.java | 54 - .../randomizedrunner/Test009ThreadLeaks.java | 66 - .../randomizedrunner/Test010Lingering.java | 83 - .../randomizedrunner/Test011NightlyTests.java | 50 - .../randomizedrunner/Test012TestGroups.java | 70 - .../randomizedrunner/Test014Listeners.java | 30 - .../Test015CustomMethodProviders.java | 57 - .../Test016CustomTestCaseOrdering.java | 61 - .../Test017TestCaseNamingExtreme.java | 58 - .../Test018TestCaseInstanceProviders.java | 59 - .../reports/Test001AllStatuses.java | 30 - .../reports/Test002SuiteFailure.java | 23 - .../reports/Test003MultipleFailures.java | 52 - .../reports/Test004SuiteOfNested.java | 25 - .../reports/Test005WithOutput.java | 49 - .../reports/Test006BeforeClassFailure.java | 18 - .../reports/Test006BeforeClassFailureRR.java | 22 - .../reports/Test007BeforeClassError.java | 16 - .../reports/Test007BeforeClassErrorRR.java | 20 - .../reports/Test008BeforeClassAssumption.java | 15 - .../Test008BeforeClassAssumptionRR.java | 19 - examples/security-manager/pom.xml | 165 -- examples/security-manager/security.policy | 46 - .../randomizedrunner/DelegatingRunner.java | 41 - .../randomizedrunner/TestExample.java | 56 - junit4-ant/lib/junit-4.9.jar | Bin 248994 -> 0 bytes junit4-ant/lib/proguard.jar | Bin 940487 -> 0 bytes junit4-ant/pom.xml | 311 --- .../ant/tasks/junit4/BalancersList.java | 21 - .../ant/tasks/junit4/DiagnosticsListener.java | 40 - .../ant/tasks/junit4/DuplicateResources.java | 61 - .../ant/tasks/junit4/Duration.java | 40 - .../ant/tasks/junit4/ForkedJvmInfo.java | 174 -- .../ant/tasks/junit4/FormattingUtils.java | 70 - .../carrotsearch/ant/tasks/junit4/JUnit4.java | 1912 ---------------- .../ant/tasks/junit4/ListenersList.java | 22 - .../tasks/junit4/LocalSlaveStreamHandler.java | 296 --- .../junit4/NonEmptyWorkDirectoryAction.java | 17 - .../ant/tasks/junit4/PickFromListTask.java | 133 -- .../ant/tasks/junit4/PickSeedTask.java | 57 - .../ant/tasks/junit4/Pluralize.java | 12 - .../ant/tasks/junit4/RunListenerList.java | 17 - .../ant/tasks/junit4/SimpleStreamPumper.java | 38 - .../ant/tasks/junit4/SlaveIdle.java | 37 - .../ant/tasks/junit4/SuiteBalancer.java | 56 - .../ant/tasks/junit4/TailInputStream.java | 110 - .../ant/tasks/junit4/TestClass.java | 14 - .../ant/tasks/junit4/TestsCollection.java | 33 - .../ant/tasks/junit4/TestsSummary.java | 53 - .../junit4/TestsSummaryEventListener.java | 71 - .../balancers/ExecutionTimeBalancer.java | 139 -- .../tasks/junit4/balancers/MergeHints.java | 81 - .../junit4/balancers/RoundRobinBalancer.java | 28 - .../ant/tasks/junit4/balancers/SuiteHint.java | 29 - .../ant/tasks/junit4/balancers/TopHints.java | 93 - .../tasks/junit4/events/AbstractEvent.java | 121 - .../events/AbstractEventWithDescription.java | 36 - .../junit4/events/AppendStdErrEvent.java | 40 - .../junit4/events/AppendStdOutEvent.java | 40 - .../tasks/junit4/events/BootstrapEvent.java | 158 -- .../ant/tasks/junit4/events/Deserializer.java | 33 - .../ant/tasks/junit4/events/EventType.java | 56 - .../ant/tasks/junit4/events/FailureEvent.java | 77 - .../ant/tasks/junit4/events/IDescribable.java | 15 - .../ant/tasks/junit4/events/IEvent.java | 8 - .../ant/tasks/junit4/events/IStreamEvent.java | 8 - .../ant/tasks/junit4/events/IdleEvent.java | 27 - .../ant/tasks/junit4/events/JsonHelpers.java | 86 - .../junit4/events/LowLevelHeartBeatEvent.java | 13 - .../ant/tasks/junit4/events/QuitEvent.java | 27 - .../ant/tasks/junit4/events/RemoteEvent.java | 11 - .../ant/tasks/junit4/events/Serializer.java | 190 -- .../junit4/events/SuiteCompletedEvent.java | 62 - .../junit4/events/SuiteFailureEvent.java | 17 - .../junit4/events/SuiteStartedEvent.java | 54 - .../tasks/junit4/events/TestFailureEvent.java | 14 - .../junit4/events/TestFinishedEvent.java | 59 - .../events/TestIgnoredAssumptionEvent.java | 14 - .../tasks/junit4/events/TestIgnoredEvent.java | 60 - .../tasks/junit4/events/TestStartedEvent.java | 14 - .../aggregated/AggregatedQuitEvent.java | 8 - .../aggregated/AggregatedResultEvent.java | 23 - .../aggregated/AggregatedStartEvent.java | 29 - .../AggregatedSuiteResultEvent.java | 310 --- .../AggregatedSuiteStartedEvent.java | 22 - .../aggregated/AggregatedTestResultEvent.java | 138 -- .../aggregated/AggregatingListener.java | 184 -- .../events/aggregated/ChildBootstrap.java | 15 - .../events/aggregated/HeartBeatEvent.java | 45 - .../events/aggregated/JvmOutputEvent.java | 28 - .../events/aggregated/PartialOutputEvent.java | 27 - .../junit4/events/aggregated/TestStatus.java | 11 - .../junit4/events/mirrors/FailureMirror.java | 83 - .../tasks/junit4/gson/stream/IOContext.java | 27 - .../tasks/junit4/gson/stream/JsonReader.java | 1597 ------------- .../tasks/junit4/gson/stream/JsonScope.java | 71 - .../tasks/junit4/gson/stream/JsonToken.java | 85 - .../tasks/junit4/gson/stream/JsonWriter.java | 647 ------ .../gson/stream/MalformedJsonException.java | 44 - .../listeners/AggregatedEventListener.java | 23 - .../listeners/ExecutionTimesReport.java | 233 -- .../junit4/listeners/LineFlushingWriter.java | 82 - .../junit4/listeners/PrefixedWriter.java | 64 - .../junit4/listeners/StackTraceFilter.java | 104 - .../tasks/junit4/listeners/TextReport.java | 718 ------ .../junit4/listeners/antxml/AntXmlReport.java | 321 --- .../junit4/listeners/antxml/FailureModel.java | 15 - .../antxml/MavenFailsafeSummaryModel.java | 51 - .../tasks/junit4/listeners/antxml/NotAnt.java | 15 - .../listeners/antxml/PropertyModel.java | 20 - .../listeners/antxml/TestCaseModel.java | 32 - .../listeners/antxml/TestSuiteModel.java | 55 - .../antxml/XmlStringTransformer.java | 53 - .../junit4/listeners/json/JsonReport.java | 308 --- .../junit4/runlisteners/RunListenerClass.java | 13 - .../BeforeAfterRunListenerDecorator.java | 86 - .../junit4/slave/EventsOutputStream.java | 40 - .../ant/tasks/junit4/slave/JvmExit.java | 24 - .../NoExceptionRunListenerDecorator.java | 78 - .../ant/tasks/junit4/slave/NullWriter.java | 19 - .../junit4/slave/OrderedRunNotifier.java | 194 -- .../junit4/slave/RunListenerEmitter.java | 123 - .../ant/tasks/junit4/slave/SlaveMain.java | 553 ----- .../ant/tasks/junit4/slave/SlaveMainSafe.java | 39 - .../tasks/junit4/slave/StdInLineIterator.java | 37 - .../junit4/slave/StreamFlusherDecorator.java | 22 - .../tools/DumpStreamsFromEventStream.java | 76 - .../tasks/junit4/templates/json/css/style.css | 814 ------- .../ant/tasks/junit4/templates/json/ideas.txt | 80 - .../junit4/templates/json/img/arrow-down.png | Bin 168 -> 0 bytes .../junit4/templates/json/img/arrow-up.png | Bin 162 -> 0 bytes .../tasks/junit4/templates/json/img/error.png | Bin 560 -> 0 bytes .../junit4/templates/json/img/failure.png | Bin 825 -> 0 bytes .../junit4/templates/json/img/indicator.png | Bin 139 -> 0 bytes .../junit4/templates/json/img/omited.png | Bin 189 -> 0 bytes .../tasks/junit4/templates/json/img/pass.png | Bin 531 -> 0 bytes .../junit4/templates/json/img/stderr.png | Bin 466 -> 0 bytes .../junit4/templates/json/img/stdout.png | Bin 428 -> 0 bytes .../tasks/junit4/templates/json/index.html | 38 - .../templates/json/js/jquery-1.7.1.min.js | 4 - .../templates/json/js/jquery.pathchange.js | 111 - .../tasks/junit4/templates/json/js/script.js | 1240 ---------- .../junit4/templates/json/tests-output.jsonp | 677 ------ .../com/carrotsearch/junit4/antlib.xml | 63 - ...arrotsearch_ant_tasks_junit4_tests_Crash.h | 21 - junit4-ant/src/native/compile-mac.sh | 4 - junit4-ant/src/native/compile.sh | 21 - junit4-ant/src/native/crash.c | 9 - junit4-ant/src/native/lib/crash.dll | Bin 64956 -> 0 bytes junit4-ant/src/native/lib/crash64.dll | Bin 94146 -> 0 bytes junit4-ant/src/native/lib/libcrash.so | Bin 1475 -> 0 bytes junit4-ant/src/native/lib/libcrash64.dylib | Bin 4256 -> 0 bytes junit4-ant/src/native/lib/libcrash64.so | Bin 2139 -> 0 bytes junit4-ant/src/proguard/rules.pro | 23 - junit4-ant/src/tasks/Tasks/junit4.html | 701 ------ junit4-ant/src/tasks/index.html | 8 - .../js/google-code-prettify/lang-apollo.js | 2 - .../tasks/js/google-code-prettify/lang-clj.js | 18 - .../tasks/js/google-code-prettify/lang-css.js | 2 - .../tasks/js/google-code-prettify/lang-go.js | 1 - .../tasks/js/google-code-prettify/lang-hs.js | 2 - .../js/google-code-prettify/lang-lisp.js | 3 - .../tasks/js/google-code-prettify/lang-lua.js | 2 - .../tasks/js/google-code-prettify/lang-ml.js | 2 - .../tasks/js/google-code-prettify/lang-n.js | 4 - .../js/google-code-prettify/lang-proto.js | 1 - .../js/google-code-prettify/lang-scala.js | 2 - .../tasks/js/google-code-prettify/lang-sql.js | 2 - .../tasks/js/google-code-prettify/lang-tex.js | 1 - .../tasks/js/google-code-prettify/lang-vb.js | 2 - .../js/google-code-prettify/lang-vhdl.js | 3 - .../js/google-code-prettify/lang-wiki.js | 2 - .../tasks/js/google-code-prettify/lang-xq.js | 3 - .../js/google-code-prettify/lang-yaml.js | 2 - .../js/google-code-prettify/prettify.css | 1 - .../tasks/js/google-code-prettify/prettify.js | 28 - .../src/tasks/stylesheets/antmanual.css | 20 - junit4-ant/src/tasks/stylesheets/junit4.css | 12 - junit4-ant/src/tasks/stylesheets/style.css | 72 - .../tasks/junit4/TestEventBusSanityCheck.java | 95 - .../junit4/TestJsonByteArrayRoundtrip.java | 53 - .../tasks/junit4/TestXmlStringsRoundtrip.java | 76 - .../events/TestRemoteEventSerialization.java | 156 -- .../tasks/junit4/it/AntBuildFileTestBase.java | 150 -- .../tasks/junit4/it/JUnit4XmlTestBase.java | 65 - .../tasks/junit4/it/TestAltJavaVendors.java | 28 - .../ant/tasks/junit4/it/TestAntXmlReport.java | 97 - .../tasks/junit4/it/TestChildVmSysprops.java | 12 - .../junit4/it/TestCrashesAndExceptions.java | 32 - .../ant/tasks/junit4/it/TestCwdConflict.java | 12 - .../it/TestDuplicateResourceCollections.java | 16 - .../tasks/junit4/it/TestFileEncodings.java | 31 - .../ant/tasks/junit4/it/TestFiltering.java | 32 - .../ant/tasks/junit4/it/TestHeartbeat.java | 17 - .../tasks/junit4/it/TestIfNoTestsOption.java | 37 - .../ant/tasks/junit4/it/TestJUnitCompat.java | 25 - .../ant/tasks/junit4/it/TestJsonReport.java | 25 - .../ant/tasks/junit4/it/TestJvmLogging.java | 22 - .../junit4/it/TestMiscJUnit4Attributes.java | 103 - .../it/TestOnNonEmptyWorkDirectory.java | 34 - .../ant/tasks/junit4/it/TestOomCode.java | 14 - .../ant/tasks/junit4/it/TestOomPermGen.java | 15 - .../tasks/junit4/it/TestOutputCapture.java | 30 - .../ant/tasks/junit4/it/TestPickSeed.java | 47 - .../tasks/junit4/it/TestPreconditions.java | 30 - .../ant/tasks/junit4/it/TestReplication.java | 53 - .../ant/tasks/junit4/it/TestRunListeners.java | 26 - .../tasks/junit4/it/TestSecuritySandbox.java | 21 - .../junit4/it/TestShutdownHookDeadlock.java | 18 - .../junit4/it/TestSourceSuitesAsInput.java | 12 - .../it/TestStackOverflowInEventEmitter.java | 12 - .../tasks/junit4/it/TestStatsProperties.java | 12 - .../tasks/junit4/it/TestSuiteClassesBad.java | 19 - .../tasks/junit4/it/TestSuiteDuplicates.java | 16 - .../tasks/junit4/it/TestSysProperties.java | 51 - .../tasks/junit4/it/TestSysPropertySet.java | 16 - .../ant/tasks/junit4/it/TestSysoutOOM.java | 12 - .../ant/tasks/junit4/it/TestTextReport.java | 118 - .../junit4/it/TestUnhandledSlaveFailure.java | 15 - .../ant/tasks/junit4/it/TestWeirdClasses.java | 15 - .../antxml/XmlStringTransformerAccess.java | 7 - .../runlisteners/UserDefinedRunListener1.java | 45 - .../runlisteners/UserDefinedRunListener2.java | 45 - .../runlisteners/UserDefinedRunListener3.java | 45 - .../tasks/junit4/spikes/FloatSampling.java | 119 - .../ant/tasks/junit4/spikes/LocalRun.java | 53 - .../tasks/junit4/spikes/TestStatusesIDE.java | 43 - .../tasks/junit4/tests/ChildVmSysprops.java | 19 - .../ant/tasks/junit4/tests/Crash.java | 24 - .../ant/tasks/junit4/tests/CwdConflict1.java | 15 - .../ant/tasks/junit4/tests/CwdConflict2.java | 5 - .../ant/tasks/junit4/tests/DisabledGroup.java | 15 - .../tasks/junit4/tests/EscapeSequences.java | 10 - .../tasks/junit4/tests/FailInAfterClass.java | 17 - .../ant/tasks/junit4/tests/FileEncoding.java | 23 - .../tests/FireUnhandledRunnerException.java | 14 - .../ant/tasks/junit4/tests/HeartbeatSlow.java | 12 - .../ant/tasks/junit4/tests/HexDump.java | 147 -- .../tasks/junit4/tests/NotInstantiable.java | 15 - .../ant/tasks/junit4/tests/OomCode.java | 25 - .../ant/tasks/junit4/tests/OomPermGen.java | 81 - .../tasks/junit4/tests/OutOfOrderSysouts.java | 62 - .../tasks/junit4/tests/RandomSysProperty.java | 17 - .../tests/ReasonForAssumptionIgnored.java | 34 - .../tasks/junit4/tests/ReasonForIgnored.java | 53 - .../ReasonForIgnoredByDisabledGroup.java | 12 - .../ant/tasks/junit4/tests/ShutdownHook.java | 20 - .../tests/SlaveHangingBackgroundThreads.java | 39 - .../ant/tasks/junit4/tests/StackOverflow.java | 22 - .../tasks/junit4/tests/SuiteListeners.java | 69 - .../tasks/junit4/tests/SysPropertySets.java | 11 - .../ant/tasks/junit4/tests/SysoutOom1.java | 23 - .../ant/tasks/junit4/tests/SysoutOom2.java | 11 - .../tasks/junit4/tests/SysoutPassthrough.java | 53 - .../junit4/tests/SysoutsOnSuiteFailure.java | 31 - .../junit4/tests/SysoutsOnSuiteTimeout.java | 32 - .../junit4/tests/TestAfterClassError.java | 14 - .../junit4/tests/TestBeforeClassError.java | 14 - .../tasks/junit4/tests/TestCreateTmpFile.java | 21 - .../ant/tasks/junit4/tests/TestDir.java | 14 - .../ant/tasks/junit4/tests/TestEnvVar.java | 17 - .../ant/tasks/junit4/tests/TestEscaping.java | 24 - .../junit4/tests/TestFailureTypePassing.java | 44 - .../tests/TestFilteringExpressions.java | 55 - .../TestHierarchicalSuiteDescription.java | 48 - .../tasks/junit4/tests/TestIgnoredSuite.java | 22 - .../junit4/tests/TestInvalidUtfCharacter.java | 13 - .../ant/tasks/junit4/tests/TestJvmArg.java | 14 - .../ant/tasks/junit4/tests/TestJvmCrash.java | 20 - .../ant/tasks/junit4/tests/TestMaxMem.java | 15 - .../junit4/tests/TestReproduceString.java | 18 - .../junit4/tests/TestSecuritySandbox.java | 11 - .../tasks/junit4/tests/TestSeedPassing.java | 33 - .../junit4/tests/TestStaticScopeOutput.java | 33 - .../ant/tasks/junit4/tests/TestStatuses.java | 31 - .../ant/tasks/junit4/tests/TestSuccess.java | 14 - .../tasks/junit4/tests/TestSysstreams.java | 20 - .../tasks/junit4/tests/bad/TestAbstract.java | 8 - .../junit4/tests/bad/TestPackagePrivate.java | 4 - .../tests/replication/TestNonReplicated1.java | 12 - .../tests/replication/TestNonReplicated2.java | 12 - .../replication/TestPseudoLoadBalancing.java | 48 - .../replication/TestSuiteReplicated.java | 14 - .../junit4/tests/sub1/TestAssertions.java | 10 - .../junit4/tests/sub2/TestHalfSecond.java | 10 - .../junit4/tests/sub2/TestOneSecond.java | 25 - .../junit4/tests/sub2/TestTwoSeconds.java | 15 - .../junit4/tests/sub2/TestZeroSeconds.java | 9 - junit4-ant/src/test/resources/hints-fixed.log | 4 - junit4-ant/src/test/resources/junit4.xml | 1572 ------------- junit4-ant/src/test/resources/security.policy | 37 - junit4-maven-plugin-tests/pom.xml | 70 - .../src/it/01-basic-test/invoker.properties | 1 - .../src/it/01-basic-test/pom.xml | 123 - .../randomizedrunner/Test001InsideMaven.java | 18 - .../src/it/01-basic-test/verify.bsh | 19 - .../02-config-inheritance/invoker.properties | 1 - .../src/it/02-config-inheritance/pom.xml | 142 -- .../randomizedrunner/IntegrationIT.java | 16 - .../examples/randomizedrunner/UnitTest.java | 16 - .../src/it/02-config-inheritance/verify.bsh | 16 - junit4-maven-plugin-tests/src/it/settings.xml | 55 - .../maven/plugins/junit4/LogAssert.java | 24 - junit4-maven-plugin/pom.xml | 144 -- .../maven/plugins/junit4/JUnit4Mojo.java | 891 -------- .../plugins/junit4/MavenListenerAdapter.java | 73 - junit4-maven-plugin/src/site/site.xml | 10 - pom.xml | 692 ------ randomized-runner/pom.xml | 76 - .../AnnotatedMethodProvider.java | 44 - .../randomizedtesting/AssertingRandom.java | 180 -- .../randomizedtesting/ClassGlobFilter.java | 23 - .../randomizedtesting/ClassModel.java | 294 --- .../randomizedtesting/Classes.java | 15 - .../CloseableResourceInfo.java | 40 - .../FilterExpressionParser.java | 315 --- .../randomizedtesting/GlobFilter.java | 69 - .../randomizedtesting/GroupEvaluator.java | 178 -- .../randomizedtesting/InstanceProvider.java | 8 - .../JUnit3MethodProvider.java | 25 - .../JUnit4MethodProvider.java | 12 - .../randomizedtesting/LifecycleScope.java | 19 - .../randomizedtesting/MethodGlobFilter.java | 23 - .../randomizedtesting/MixWithSuiteName.java | 31 - .../randomizedtesting/MurmurHash3.java | 42 - .../randomizedtesting/ObjectProcedure.java | 6 - .../randomizedtesting/RandomSupplier.java | 14 - .../randomizedtesting/RandomizedContext.java | 390 ---- .../randomizedtesting/RandomizedRunner.java | 1997 ----------------- .../randomizedtesting/RandomizedTest.java | 891 -------- .../randomizedtesting/Randomness.java | 83 - .../carrotsearch/randomizedtesting/Rants.java | 59 - .../ReproduceErrorMessageBuilder.java | 105 - .../ResourceDisposalError.java | 13 - .../randomizedtesting/Rethrow.java | 26 - .../randomizedtesting/RunnerContainer.java | 11 - .../randomizedtesting/RunnerThreadGroup.java | 30 - .../randomizedtesting/SeedDecorator.java | 18 - .../randomizedtesting/SeedUtils.java | 70 - .../randomizedtesting/StackTraceHolder.java | 12 - .../randomizedtesting/SysGlobals.java | 235 -- .../randomizedtesting/TeeOutputStream.java | 163 -- .../randomizedtesting/TempPathResource.java | 27 - .../TestMethodAndParams.java | 17 - .../randomizedtesting/TestMethodProvider.java | 26 - .../randomizedtesting/ThreadFilter.java | 14 - .../randomizedtesting/ThreadLeakControl.java | 940 -------- .../randomizedtesting/ThreadLeakError.java | 11 - .../randomizedtesting/Threads.java | 139 -- .../randomizedtesting/TraceFormatting.java | 94 - .../UncaughtExceptionError.java | 11 - .../randomizedtesting/Validation.java | 111 - .../randomizedtesting/WriterOutputStream.java | 288 --- .../Xoroshiro128PlusRandom.java | 97 - .../annotations/Listeners.java | 30 - .../randomizedtesting/annotations/Name.java | 15 - .../annotations/Nightly.java | 29 - .../annotations/ParametersFactory.java | 42 - .../randomizedtesting/annotations/Repeat.java | 29 - .../annotations/ReplicateOnEachVm.java | 21 - .../randomizedtesting/annotations/Seed.java | 40 - .../annotations/SeedDecorators.java | 32 - .../randomizedtesting/annotations/Seeds.java | 32 - .../annotations/SuppressForbidden.java | 19 - .../annotations/TestCaseInstanceProvider.java | 52 - .../annotations/TestCaseOrdering.java | 44 - .../TestContextRandomSupplier.java | 24 - .../annotations/TestGroup.java | 81 - .../annotations/TestMethodProviders.java | 25 - .../annotations/ThreadLeakAction.java | 22 - .../annotations/ThreadLeakFilters.java | 17 - .../annotations/ThreadLeakGroup.java | 34 - .../annotations/ThreadLeakLingering.java | 25 - .../annotations/ThreadLeakScope.java | 36 - .../annotations/ThreadLeakZombies.java | 38 - .../annotations/Timeout.java | 38 - .../annotations/TimeoutSuite.java | 45 - .../generators/ASCIIGenerator.java | 16 - .../generators/AsciiAlphanumGenerator.java | 21 - .../generators/AsciiLettersGenerator.java | 19 - .../generators/BiasedNumbers.java | 270 --- .../generators/CodepointSetGenerator.java | 139 -- .../generators/RandomBytes.java | 31 - .../generators/RandomNumbers.java | 80 - .../generators/RandomPicks.java | 62 - .../generators/RandomStrings.java | 45 - .../generators/RealisticUnicodeGenerator.java | 92 - .../generators/StringGenerator.java | 45 - .../generators/UnicodeGenerator.java | 92 - .../listeners/ReproduceInfoPrinter.java | 45 - .../rules/NoClassHooksShadowingRule.java | 32 - .../rules/NoInstanceHooksOverridesRule.java | 33 - .../NoShadowingOrOverridesOnMethodsRule.java | 89 - .../rules/RamUsageEstimator.java | 987 -------- .../rules/RequireAssertionsRule.java | 62 - .../rules/StatementAdapter.java | 72 - .../rules/StaticFieldsInvariantRule.java | 183 -- .../rules/SystemPropertiesInvariantRule.java | 136 -- .../rules/SystemPropertiesRestoreRule.java | 128 -- .../rules/TestRuleAdapter.java | 61 - .../randomizedtesting/PrintEventListener.java | 66 - .../randomizedtesting/TestBiasedNumbers.java | 80 - .../TestChildTestGroupThreads.java | 26 - .../TestClassMethodFiltering.java | 122 - .../randomizedtesting/TestContextRandom.java | 87 - .../TestCustomMethodProvider.java | 76 - .../TestCustomTestContextSupplier.java | 40 - .../randomizedtesting/TestExpected.java | 43 - .../TestFailurePropagationCompatibility.java | 148 -- .../TestFilterExpressionParser.java | 157 -- .../TestFormattingRandomSeeds.java | 37 - .../randomizedtesting/TestGlobFilter.java | 18 - .../TestHookMethodOrderWithExceptions.java | 131 -- .../TestHooksWithEmptyTestSet.java | 43 - .../TestIgnoredRunCount.java | 26 - .../TestInstantiationTime.java | 28 - .../TestIterationsAnnotation.java | 30 - .../randomizedtesting/TestJ9SysThreads.java | 35 - .../TestJUnit3MethodProvider.java | 71 - .../TestListenersAnnotation.java | 95 - .../randomizedtesting/TestMacSysThreads.java | 33 - .../randomizedtesting/TestManyThreadsOOM.java | 34 - .../randomizedtesting/TestNightlyMode.java | 54 - .../TestOutOfScopeRandomUse.java | 135 -- .../TestOverlappingMethodProviders.java | 26 - ...TestOverridingDefaultExceptionHandler.java | 77 - .../randomizedtesting/TestParameterized.java | 124 - .../TestParameterizedShufflesOrder.java | 87 - .../randomizedtesting/TestRandom.java | 65 - .../TestRandomInStaticInitializer.java | 27 - .../randomizedtesting/TestRandomNumbers.java | 61 - .../TestRandomizedContext.java | 47 - .../randomizedtesting/TestRandomizedTest.java | 264 --- .../TestRepeatTestWithComplexDescription.java | 75 - .../TestResourceDisposal.java | 108 - .../randomizedtesting/TestRules.java | 133 -- .../randomizedtesting/TestSeedDecorator.java | 73 - .../randomizedtesting/TestSeedFixing.java | 30 - .../TestSeedFixingWithProperties.java | 82 - .../TestSeedParameterOptional.java | 64 - .../randomizedtesting/TestSeedRepeatable.java | 55 - .../randomizedtesting/TestSetSeedLocked.java | 17 - .../TestStackAugmentation.java | 94 - .../randomizedtesting/TestTargetMethod.java | 43 - .../TestTestCaseInstanceProviders.java | 73 - .../TestTestCaseOrdering.java | 103 - .../randomizedtesting/TestTestFiltering.java | 64 - .../randomizedtesting/TestTestGroups.java | 187 -- .../TestTestGroupsOnOverrides.java | 80 - .../TestThreadNameContainsTestName.java | 32 - .../TestUncaughtExceptionsDuplicated.java | 119 - .../randomizedtesting/TestValidation.java | 83 - .../carrotsearch/randomizedtesting/Utils.java | 102 - .../WithNestedTestClass.java | 361 --- .../contracts/TestAnnotationInheritance.java | 113 - .../TestAssumptionsAtClassLevel.java | 88 - .../contracts/TestBeforeAfterMethodOrder.java | 232 -- .../contracts/TestClassLevelIgnore.java | 24 - .../contracts/TestClassRules.java | 75 - .../contracts/TestMethodFilteringInIDEs.java | 30 - .../generators/StringGeneratorTestBase.java | 69 - .../generators/TestCodepointSetGenerator.java | 115 - .../generators/TestRandomBytes.java | 26 - .../generators/TestRandomPicks.java | 35 - .../TestRealisticUnicodeGenerator.java | 7 - .../generators/TestUnicodeGenerator.java | 7 - .../JUnitAnnotationPropagation.java | 108 - .../inheritance/PrivateHooksPropagation.java | 57 - .../rules/TestNoClassHooksShadowingRule.java | 79 - .../TestNoInstanceHooksOverridesRule.java | 101 - .../rules/TestStaticFieldsInvariantRule.java | 146 -- .../TestSystemPropertiesInvariantRule.java | 134 -- .../snippets/TheGoodBadAndUglySnippet.java | 57 - .../timeouts/Test001TimeoutSuite.java | 49 - .../timeouts/Test002TimeoutMethod.java | 36 - .../timeouts/Test003ThreadLeaksMethod.java | 61 - .../timeouts/Test004ThreadLeaksSuite.java | 52 - .../Test005ThreadLeaksSystemThreads.java | 60 - .../timeouts/Test006TimeoutAndThreadLeak.java | 49 - .../timeouts/Test007UncaughtExceptions.java | 60 - .../timeouts/Test008SeedsAnnotation.java | 65 - .../Test009TimeoutOrNotIdenticalSequence.java | 68 - .../timeouts/Test010Zombies.java | 78 - .../timeouts/Test011RunawayThreads.java | 158 -- .../Test012RunawayThreadsKilledAtOnce.java | 52 - .../timeouts/Test013ThreadLeaksScopeNone.java | 39 - .../timeouts/Test014Timeout.java | 38 - .../timeouts/Test015TimeoutOverride.java | 60 - .../Test016ThreadLeaksCustomFilters.java | 45 - ...t017ThreadLeaksCustomFiltersException.java | 46 - .../timeouts/Test018TimeoutStacks.java | 36 - .../timeouts/Test019ThreadLeakGroup.java | 83 - .../Test020SuiteTimeoutStopsTests.java | 67 - .../timeouts/Test021SuiteTimeoutHanging.java | 99 - src/site/site.xml | 30 - 514 files changed, 44589 deletions(-) delete mode 100644 .editorconfig delete mode 100644 .gitignore delete mode 100644 CHANGES.txt delete mode 100644 CONTRIBUTING.txt delete mode 100644 LICENSE.txt delete mode 100644 README.txt delete mode 100644 etc/eclipse/settings/org.eclipse.jdt.core.prefs delete mode 100644 etc/eclipse/settings/org.eclipse.jdt.ui.prefs delete mode 100644 etc/forbidden-apis/signatures.txt delete mode 100644 examples/ant/build.xml delete mode 100644 examples/ant/pom.xml delete mode 100644 examples/maven/pom.xml delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test001SimpleUseCase.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test002ExtendingRandomizedTest.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test003UsingRandomness.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test004MoreRandomness.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test005RecoveringRandomSeed.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test006RepeatingTests.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test007ParameterizedTests.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test008Timeouts.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test009ThreadLeaks.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test010Lingering.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test011NightlyTests.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test012TestGroups.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test014Listeners.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test015CustomMethodProviders.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test016CustomTestCaseOrdering.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test017TestCaseNamingExtreme.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test018TestCaseInstanceProviders.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test001AllStatuses.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test002SuiteFailure.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test003MultipleFailures.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test004SuiteOfNested.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test005WithOutput.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test006BeforeClassFailure.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test006BeforeClassFailureRR.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test007BeforeClassError.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test007BeforeClassErrorRR.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test008BeforeClassAssumption.java delete mode 100644 examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test008BeforeClassAssumptionRR.java delete mode 100644 examples/security-manager/pom.xml delete mode 100644 examples/security-manager/security.policy delete mode 100644 examples/security-manager/src/test/java/com/carrotsearch/examples/randomizedrunner/DelegatingRunner.java delete mode 100644 examples/security-manager/src/test/java/com/carrotsearch/examples/randomizedrunner/TestExample.java delete mode 100644 junit4-ant/lib/junit-4.9.jar delete mode 100644 junit4-ant/lib/proguard.jar delete mode 100644 junit4-ant/pom.xml delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/BalancersList.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/DiagnosticsListener.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/DuplicateResources.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/Duration.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/ForkedJvmInfo.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/FormattingUtils.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/JUnit4.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/ListenersList.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/LocalSlaveStreamHandler.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/NonEmptyWorkDirectoryAction.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/PickFromListTask.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/PickSeedTask.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/Pluralize.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/RunListenerList.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/SimpleStreamPumper.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/SlaveIdle.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/SuiteBalancer.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TailInputStream.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TestClass.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TestsCollection.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TestsSummary.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TestsSummaryEventListener.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/ExecutionTimeBalancer.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/MergeHints.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/RoundRobinBalancer.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/SuiteHint.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/TopHints.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/AbstractEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/AbstractEventWithDescription.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/AppendStdErrEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/AppendStdOutEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/BootstrapEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/Deserializer.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/EventType.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/FailureEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/IDescribable.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/IEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/IStreamEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/IdleEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/JsonHelpers.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/LowLevelHeartBeatEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/QuitEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/RemoteEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/Serializer.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/SuiteCompletedEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/SuiteFailureEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/SuiteStartedEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestFailureEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestFinishedEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestIgnoredAssumptionEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestIgnoredEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestStartedEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedQuitEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedResultEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedStartEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedSuiteResultEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedSuiteStartedEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedTestResultEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatingListener.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/ChildBootstrap.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/HeartBeatEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/JvmOutputEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/PartialOutputEvent.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/TestStatus.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/mirrors/FailureMirror.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/gson/stream/IOContext.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/gson/stream/JsonReader.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/gson/stream/JsonScope.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/gson/stream/JsonToken.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/gson/stream/JsonWriter.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/gson/stream/MalformedJsonException.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/listeners/AggregatedEventListener.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/listeners/ExecutionTimesReport.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/listeners/LineFlushingWriter.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/listeners/PrefixedWriter.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/listeners/StackTraceFilter.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/listeners/TextReport.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/listeners/antxml/AntXmlReport.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/listeners/antxml/FailureModel.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/listeners/antxml/MavenFailsafeSummaryModel.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/listeners/antxml/NotAnt.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/listeners/antxml/PropertyModel.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/listeners/antxml/TestCaseModel.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/listeners/antxml/TestSuiteModel.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/listeners/antxml/XmlStringTransformer.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/listeners/json/JsonReport.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/runlisteners/RunListenerClass.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/slave/BeforeAfterRunListenerDecorator.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/slave/EventsOutputStream.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/slave/JvmExit.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/slave/NoExceptionRunListenerDecorator.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/slave/NullWriter.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/slave/OrderedRunNotifier.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/slave/RunListenerEmitter.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/slave/SlaveMain.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/slave/SlaveMainSafe.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/slave/StdInLineIterator.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/slave/StreamFlusherDecorator.java delete mode 100644 junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/tools/DumpStreamsFromEventStream.java delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/css/style.css delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/ideas.txt delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/img/arrow-down.png delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/img/arrow-up.png delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/img/error.png delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/img/failure.png delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/img/indicator.png delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/img/omited.png delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/img/pass.png delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/img/stderr.png delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/img/stdout.png delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/index.html delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/js/jquery-1.7.1.min.js delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/js/jquery.pathchange.js delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/js/script.js delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/tests-output.jsonp delete mode 100644 junit4-ant/src/main/resources/com/carrotsearch/junit4/antlib.xml delete mode 100644 junit4-ant/src/native/com_carrotsearch_ant_tasks_junit4_tests_Crash.h delete mode 100755 junit4-ant/src/native/compile-mac.sh delete mode 100755 junit4-ant/src/native/compile.sh delete mode 100644 junit4-ant/src/native/crash.c delete mode 100644 junit4-ant/src/native/lib/crash.dll delete mode 100644 junit4-ant/src/native/lib/crash64.dll delete mode 100644 junit4-ant/src/native/lib/libcrash.so delete mode 100755 junit4-ant/src/native/lib/libcrash64.dylib delete mode 100644 junit4-ant/src/native/lib/libcrash64.so delete mode 100644 junit4-ant/src/proguard/rules.pro delete mode 100644 junit4-ant/src/tasks/Tasks/junit4.html delete mode 100644 junit4-ant/src/tasks/index.html delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-apollo.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-clj.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-css.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-go.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-hs.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-lisp.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-lua.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-ml.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-n.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-proto.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-scala.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-sql.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-tex.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-vb.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-vhdl.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-wiki.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-xq.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/lang-yaml.js delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/prettify.css delete mode 100644 junit4-ant/src/tasks/js/google-code-prettify/prettify.js delete mode 100644 junit4-ant/src/tasks/stylesheets/antmanual.css delete mode 100644 junit4-ant/src/tasks/stylesheets/junit4.css delete mode 100644 junit4-ant/src/tasks/stylesheets/style.css delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/TestEventBusSanityCheck.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/TestJsonByteArrayRoundtrip.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/TestXmlStringsRoundtrip.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/events/TestRemoteEventSerialization.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/AntBuildFileTestBase.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/JUnit4XmlTestBase.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestAltJavaVendors.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestAntXmlReport.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestChildVmSysprops.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestCrashesAndExceptions.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestCwdConflict.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestDuplicateResourceCollections.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestFileEncodings.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestFiltering.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestHeartbeat.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestIfNoTestsOption.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestJUnitCompat.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestJsonReport.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestJvmLogging.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestMiscJUnit4Attributes.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestOnNonEmptyWorkDirectory.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestOomCode.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestOomPermGen.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestOutputCapture.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestPickSeed.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestPreconditions.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestReplication.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestRunListeners.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSecuritySandbox.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestShutdownHookDeadlock.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSourceSuitesAsInput.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestStackOverflowInEventEmitter.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestStatsProperties.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSuiteClassesBad.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSuiteDuplicates.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSysProperties.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSysPropertySet.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSysoutOOM.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestTextReport.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestUnhandledSlaveFailure.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestWeirdClasses.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/listeners/antxml/XmlStringTransformerAccess.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/runlisteners/UserDefinedRunListener1.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/runlisteners/UserDefinedRunListener2.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/runlisteners/UserDefinedRunListener3.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/spikes/FloatSampling.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/spikes/LocalRun.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/spikes/TestStatusesIDE.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ChildVmSysprops.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/Crash.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/CwdConflict1.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/CwdConflict2.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/DisabledGroup.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/EscapeSequences.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/FailInAfterClass.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/FileEncoding.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/FireUnhandledRunnerException.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/HeartbeatSlow.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/HexDump.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/NotInstantiable.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/OomCode.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/OomPermGen.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/OutOfOrderSysouts.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/RandomSysProperty.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ReasonForAssumptionIgnored.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ReasonForIgnored.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ReasonForIgnoredByDisabledGroup.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ShutdownHook.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SlaveHangingBackgroundThreads.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/StackOverflow.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SuiteListeners.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysPropertySets.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutOom1.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutOom2.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutPassthrough.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutsOnSuiteFailure.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutsOnSuiteTimeout.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestAfterClassError.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestBeforeClassError.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestCreateTmpFile.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestDir.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestEnvVar.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestEscaping.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestFailureTypePassing.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestFilteringExpressions.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestHierarchicalSuiteDescription.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestIgnoredSuite.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestInvalidUtfCharacter.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestJvmArg.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestJvmCrash.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestMaxMem.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestReproduceString.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestSecuritySandbox.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestSeedPassing.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestStaticScopeOutput.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestStatuses.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestSuccess.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestSysstreams.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/bad/TestAbstract.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/bad/TestPackagePrivate.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/replication/TestNonReplicated1.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/replication/TestNonReplicated2.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/replication/TestPseudoLoadBalancing.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/replication/TestSuiteReplicated.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub1/TestAssertions.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub2/TestHalfSecond.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub2/TestOneSecond.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub2/TestTwoSeconds.java delete mode 100644 junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub2/TestZeroSeconds.java delete mode 100644 junit4-ant/src/test/resources/hints-fixed.log delete mode 100644 junit4-ant/src/test/resources/junit4.xml delete mode 100644 junit4-ant/src/test/resources/security.policy delete mode 100644 junit4-maven-plugin-tests/pom.xml delete mode 100644 junit4-maven-plugin-tests/src/it/01-basic-test/invoker.properties delete mode 100644 junit4-maven-plugin-tests/src/it/01-basic-test/pom.xml delete mode 100644 junit4-maven-plugin-tests/src/it/01-basic-test/src/test/java/com/carrotsearch/examples/randomizedrunner/Test001InsideMaven.java delete mode 100644 junit4-maven-plugin-tests/src/it/01-basic-test/verify.bsh delete mode 100644 junit4-maven-plugin-tests/src/it/02-config-inheritance/invoker.properties delete mode 100644 junit4-maven-plugin-tests/src/it/02-config-inheritance/pom.xml delete mode 100644 junit4-maven-plugin-tests/src/it/02-config-inheritance/src/test/java/com/carrotsearch/examples/randomizedrunner/IntegrationIT.java delete mode 100644 junit4-maven-plugin-tests/src/it/02-config-inheritance/src/test/java/com/carrotsearch/examples/randomizedrunner/UnitTest.java delete mode 100644 junit4-maven-plugin-tests/src/it/02-config-inheritance/verify.bsh delete mode 100644 junit4-maven-plugin-tests/src/it/settings.xml delete mode 100644 junit4-maven-plugin-tests/src/test/java/com/carrotsearch/maven/plugins/junit4/LogAssert.java delete mode 100644 junit4-maven-plugin/pom.xml delete mode 100644 junit4-maven-plugin/src/main/java/com/carrotsearch/maven/plugins/junit4/JUnit4Mojo.java delete mode 100644 junit4-maven-plugin/src/main/java/com/carrotsearch/maven/plugins/junit4/MavenListenerAdapter.java delete mode 100644 junit4-maven-plugin/src/site/site.xml delete mode 100644 pom.xml delete mode 100644 randomized-runner/pom.xml delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/AnnotatedMethodProvider.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/AssertingRandom.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ClassGlobFilter.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ClassModel.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Classes.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/CloseableResourceInfo.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/FilterExpressionParser.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/GlobFilter.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/GroupEvaluator.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/InstanceProvider.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/JUnit3MethodProvider.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/JUnit4MethodProvider.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/LifecycleScope.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/MethodGlobFilter.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/MixWithSuiteName.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/MurmurHash3.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ObjectProcedure.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RandomSupplier.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RandomizedContext.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RandomizedRunner.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RandomizedTest.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Randomness.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Rants.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ReproduceErrorMessageBuilder.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ResourceDisposalError.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Rethrow.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RunnerContainer.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RunnerThreadGroup.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/SeedDecorator.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/SeedUtils.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/StackTraceHolder.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/SysGlobals.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TeeOutputStream.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TempPathResource.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TestMethodAndParams.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TestMethodProvider.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ThreadFilter.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ThreadLeakControl.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ThreadLeakError.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Threads.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TraceFormatting.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/UncaughtExceptionError.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Validation.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/WriterOutputStream.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Xoroshiro128PlusRandom.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Listeners.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Name.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Nightly.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ParametersFactory.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Repeat.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ReplicateOnEachVm.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Seed.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/SeedDecorators.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Seeds.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/SuppressForbidden.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestCaseInstanceProvider.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestCaseOrdering.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestContextRandomSupplier.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestGroup.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestMethodProviders.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakAction.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakFilters.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakGroup.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakLingering.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakScope.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakZombies.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Timeout.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TimeoutSuite.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/ASCIIGenerator.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/AsciiAlphanumGenerator.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/AsciiLettersGenerator.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/BiasedNumbers.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/CodepointSetGenerator.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RandomBytes.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RandomNumbers.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RandomPicks.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RandomStrings.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RealisticUnicodeGenerator.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/StringGenerator.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/UnicodeGenerator.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/listeners/ReproduceInfoPrinter.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/NoClassHooksShadowingRule.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/NoInstanceHooksOverridesRule.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/NoShadowingOrOverridesOnMethodsRule.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/RamUsageEstimator.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/RequireAssertionsRule.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/StatementAdapter.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/StaticFieldsInvariantRule.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/SystemPropertiesInvariantRule.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/SystemPropertiesRestoreRule.java delete mode 100644 randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/TestRuleAdapter.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/PrintEventListener.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestBiasedNumbers.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestChildTestGroupThreads.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestClassMethodFiltering.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestContextRandom.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestCustomMethodProvider.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestCustomTestContextSupplier.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestExpected.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestFailurePropagationCompatibility.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestFilterExpressionParser.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestFormattingRandomSeeds.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestGlobFilter.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestHookMethodOrderWithExceptions.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestHooksWithEmptyTestSet.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestIgnoredRunCount.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestInstantiationTime.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestIterationsAnnotation.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestJ9SysThreads.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestJUnit3MethodProvider.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestListenersAnnotation.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestMacSysThreads.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestManyThreadsOOM.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestNightlyMode.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestOutOfScopeRandomUse.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestOverlappingMethodProviders.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestOverridingDefaultExceptionHandler.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestParameterized.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestParameterizedShufflesOrder.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandom.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandomInStaticInitializer.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandomNumbers.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandomizedContext.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandomizedTest.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRepeatTestWithComplexDescription.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestResourceDisposal.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRules.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedDecorator.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedFixing.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedFixingWithProperties.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedParameterOptional.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedRepeatable.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSetSeedLocked.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestStackAugmentation.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTargetMethod.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestCaseInstanceProviders.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestCaseOrdering.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestFiltering.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestGroups.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestGroupsOnOverrides.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestThreadNameContainsTestName.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestUncaughtExceptionsDuplicated.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestValidation.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/Utils.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/WithNestedTestClass.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestAnnotationInheritance.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestAssumptionsAtClassLevel.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestBeforeAfterMethodOrder.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestClassLevelIgnore.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestClassRules.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestMethodFilteringInIDEs.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/StringGeneratorTestBase.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestCodepointSetGenerator.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestRandomBytes.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestRandomPicks.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestRealisticUnicodeGenerator.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestUnicodeGenerator.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/inheritance/JUnitAnnotationPropagation.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/inheritance/PrivateHooksPropagation.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/rules/TestNoClassHooksShadowingRule.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/rules/TestNoInstanceHooksOverridesRule.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/rules/TestStaticFieldsInvariantRule.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/rules/TestSystemPropertiesInvariantRule.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/snippets/TheGoodBadAndUglySnippet.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test001TimeoutSuite.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test002TimeoutMethod.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test003ThreadLeaksMethod.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test004ThreadLeaksSuite.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test005ThreadLeaksSystemThreads.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test006TimeoutAndThreadLeak.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test007UncaughtExceptions.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test008SeedsAnnotation.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test009TimeoutOrNotIdenticalSequence.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test010Zombies.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test011RunawayThreads.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test012RunawayThreadsKilledAtOnce.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test013ThreadLeaksScopeNone.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test014Timeout.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test015TimeoutOverride.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test016ThreadLeaksCustomFilters.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test017ThreadLeaksCustomFiltersException.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test018TimeoutStacks.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test019ThreadLeakGroup.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test020SuiteTimeoutStopsTests.java delete mode 100644 randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test021SuiteTimeoutHanging.java delete mode 100644 src/site/site.xml diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 5835e01f..00000000 --- a/.editorconfig +++ /dev/null @@ -1,17 +0,0 @@ -# -# This is a generic editor configuration file, supported -# by many editors (directly or via plugins). -# -# See http://editorconfig.org for more information. -# - -root = true - -[*] -charset = UTF-8 - -[*.{java}] -charset = UTF-8 -end_of_line = lf -indent_style = space -indent_size = 2 diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 8a70852c..00000000 --- a/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# Eclipse -target/ -.project -.classpath -.settings - -# IntelliJ -.idea -*.iml - -# Maven -*.versionsBackup -*.swp -*~ diff --git a/CHANGES.txt b/CHANGES.txt deleted file mode 100644 index 39694337..00000000 --- a/CHANGES.txt +++ /dev/null @@ -1,406 +0,0 @@ - -RandomizedTesting, Change Log -============================= - -For an up-to-date CHANGES file see -https://github.com/randomizedtesting/randomizedtesting/blob/master/CHANGES - -======================= randomizedtesting 2.7.9-SNAPSHOT ==================== - -Other: - - * Update JUnit dependency to 4.13.1. - - * Update Ant dependency to 1.9.15. - -======================= randomizedtesting 2.7.8 ==================== - -Improvements - - * GH-289: Bump asm to 8.0.1. - - * PR-287: Bump dom4j from 2.1.1 to 2.1.3. - -======================= randomizedtesting 2.7.7 ==================== - -Bug Fixes - - * GH-283: RandomizedRunner throws `NoTestsRemainException` from the - constructor when method filter is supplied and no methods match - (Mark Vieira). - -======================= randomizedtesting 2.7.6 ==================== - -Improvements - - * Use thread join internally to wait for forked timeouting test thread - instead of a hardcoded sleep (dumb!). - -======================= randomizedtesting 2.7.5 ==================== - -Improvements - - * Switch to simple-xml-safe. - - * throw NoTestsRemainException if Filterable.filter removes all tests. - -======================= randomizedtesting 2.7.4 ==================== - -Bug Fixes - - * GH-280: Potential race condition in global temp folder generation. - - -======================= randomizedtesting 2.7.3 ==================== - -Bug Fixes - - * GH-276: Annotations on overriden methods are not picked up (annotations - on overrides of @Test methods are not picked up). - -======================= randomizedtesting 2.7.2 ==================== - -Bug Fixes - - * GH-275: Timeouts can deadlock on trying to interrupt leaked threads. - -Improvements - - * GH-274: PrintEventListener should emit display name if method name - is not available in testIgnored callback. - -======================= randomizedtesting 2.7.1 ==================== - -Bug Fixes - - * GH-271: Methods with ( or ) in them can't be selected directly using - glob filters. - -======================= randomizedtesting 2.7.0 ==================== - -Bug Fixes - - * GH-269: 2.6.x runners and junit 4.12 show much noise for a single - test method in IntellJ Idea (thanks Vladimir Dolzhenko). - -Changes in Backwards Compatibility - - * GH-270: Upgrade to support JUnit 4.12. This also means that Hamcrest - is required (as JUnit 4.12 uses it). - -======================= randomizedtesting 2.6.4 ==================== - -Bug Fixes - - * GH-247: Allow java.io.tmpdir to be placed under cwd with isolated - directories and nonEmptyWorkDirAction=wipe. - - * GH-255: Invalid event nesting on security logging crashes the runner. - - * GH-266: QUIT event may not be read from the event log on slow machines. - - * GH-267: Project does not build/ test on Java 11. - -Improvements - - * An additional property 'junit4.tempDir' is passed to forked JVMs to allow - easier configuration of security policy files. This folder must have - read/ write file policy. - - * Added a test case that runs with a security manager enabled. - - * GH-253: IntelliJ only recognizes proper test methods for re-runs - when descriptions have " [...]" instead of " {...}. This fix uses square - brackets on IntelliJ runner. - -Changes in Backwards Compatibility - - * GH-265: Deprecate RandomizedTest.randomInt(v) and RandomizedTest.randomLong(v). - -======================= randomizedtesting 2.6.3 ==================== - -Bug Fixes - - * GH-263: event bus dispatch error (covariant incompatibility due to - jdk 9 compilation to java 8 bytecode). - -======================= randomizedtesting 2.6.2 ==================== - -New Features - - * GH-261: Ant and Maven runner can specify external JUnit 4 RunListeners. - (Steven Zaluk) - -======================= randomizedtesting 2.6.1 ==================== - -Bug Fixes - - * GH-260: maven plugin should use dom4j 2.0.2 (avoids illegal access warnings - under Java 9 and later). - -======================= randomizedtesting 2.6.0 ==================== - -Changes in Backwards Compatibility - - * GH-259: Java 1.8 is now the minimum supported JRE. - - * GH-258: add support for parsing class files compiled into Java 9 or - Java 10 bytecode. - -======================= randomizedtesting 2.5.3 ==================== - -Bug Fixes - - * GH-251: Fixes test case filtering in IDEs (IntelliJ, Eclipse). The tests - are now filtered out eagerly from the returned suite's Description and - don't show in the user interface at all. This also applies to - -Dtests.method=... patterns. (Mike Sokolov via Dawid Weiss) - -======================= randomizedtesting 2.5.2 ==================== - -Bug Fixes - - * GH-250: Non-bootstrapped ForkedJvmInfo causes NullPointerExceptions - (can happen on slow machines with low heartbeat setting). - (Doug Turnbull via Dawid Weiss). - -======================= randomizedtesting 2.5.1 ==================== - -Changes in Backwards Compatibility - - * GH-248: Cleaning up some confusion on RandomizedTest.randomAscii* and - RandomStrings.randomAscii* methods. These methods generated - random strings based on letters from the Unicode basic latin block (C0). - All these methods are now deprecated and will be removed in favor of - more explicit methods that tell exactly (?) what kind of letters are - involved (Ryan Ernst, Dawid Weiss). For details, see: - - RandomStrings.randomAsciiLettersOfLength(..) - RandomStrings.randomAsciiLettersOfLengthBetween(..) - RandomStrings.randomAsciiAlphanumOfLength(..) - RandomStrings.randomAsciiAlphanumOfLengthBetween(..) - -======================= randomizedtesting 2.5.0 ==================== - -Changes in Backwards Compatibility - - * GH-243: Switches from File to NIO (Path) APIs in a few places may result - in slightly different runner's behavior (on exceptional conditions). - - * GH-244: the new onNonEmptyWorkDirectory attribute's default value is - 'fail' which may break existing builds that have garbage in work directories - of forked JVMs. Change explicitly to any of the alternatives ('ignore' or - 'wipe') or fix your build to wipe the temporary folders yourself. - - * GH-246: RequireAssertionsRule enforcement optional (consistent with - "-Dtests.asserts"); explicit target class is also required. (Dawid Weiss) - -New Features - - * GH-244: A new attribute "onNonEmptyWorkDirectory" controls the action to - take on non-empty initial work directory (for isolated JVMs). (Dawid Weiss) - -Bug Fixes - -Other Changes - - * GH-246: RequireAssertionsRule enforcement optional (consistent with - "-Dtests.asserts"); explicit target class is also required. (Dawid Weiss) - - * GH-243: Switches from File to NIO (Path) APIs in a few places in the ANT - runner. Improved messages concerning non-empty temporary JVM folder - (both initially and at the end of the tests' run). (Dawid Weiss) - - * GH-245: Integrate Forbidden-APIs check and fix follow-up issues. - (Dawid Weiss) - -======================= randomizedtesting 2.4.1 ==================== - -New Features - - * GH-240: Add RandomPicks.randomFrom on primitive arrays. (Dawid Weiss) - -Bug Fixes - - * GH-242: RandomizedTest.nextTempName uses locale-sensitive String.format. - (Dawid Weiss) - -======================= randomizedtesting 2.4.0 ==================== - -Changes in Backwards Compatibility - - * GH-237: Methods previously found in RandomInts have been moved to - RandomNumbers. (Dawid Weiss) - - * GH-234: Run strict validation (thread-ownership, lifecycle) in - AssertingRandom only with assertions enabled. This change means that running - without -ea will from now on ignore the fact that random context's Random - instance is shared where it shouldn't be. On the other hand, any - additional memory barriers can be now avoided, in particular when used in - conjunction with @TestContextRandomSupplier (see GH-235 below). - - To enable consistent checking, enable assertions selectively (for - com.carrotsearch.randomizedtesting package only). (Dawid Weiss) - - * GH-229: The default implementation of the Random instance returned from - the randomization context has been changed to Xoroshiro128P, details here: - http://xoroshiro.di.unimi.it/ - - The returned Random isn't synchronized and should yield much better - pseudo-random sequences than the default Java's Random. (Dawid Weiss) - -New Features - - * GH-238: Add BiasedNumbers (random selection with bias towards "evil" - numbers, in particular floats) as an alternative to RandomNumbers. - (Dawid Weiss) - - * GH-237: Rename RandomInts to RandomNumbers and add methods operating - on longs. (Dawid Weiss). - - * GH-235: A new class annotation was added: @TestContextRandomSupplier allows - declaring a custom class (RandomSupplier) that supplies a Random for the given - seed. This supplier can return any Random instance for the given initial - seed (secure random, faster-than-jdk random, non-random random...). - (Dawid Weiss) - -Bug Fixes - - * GH-233: some adjustments and refactorings in an attempt to avoid deadlocks - on suite timeouts. Very hard to reproduce (i.e., impossible) and some very - odd stack traces too. (Dawid Weiss) - -Other Changes - - * GH-232: Rework reporting of ignored, assumption-ignored, - filtering-expression ignored tests. (Dawid Weiss) - - * GH-218: There are some internal changes in handling @Nightly annotation. - The support for @Nightly is now provided via GroupEvaluator (and this - class is now public, with methods allowing inspection of whether a test - would be filtered out or not). (Dawid Weiss) - -======================= randomizedtesting 2.3.4 ==================== - -Bug Fixes - - * GH-227: Static leak detector should print the "original" field in the - test class that lead to ram usage tester failure (PR #227, Uwe Schindler) - -======================= randomizedtesting 2.3.3 ==================== - -Bug Fixes - - * GH-225: Maven mojo's additionalClasspathElements option only adds - empty strings to classpath. (@Anaros via Dawid Weiss). - -======================= randomizedtesting 2.3.2 ==================== - -Changes in Backwards Compatibility - - * GH-222: Make unexpected JVM output available to listeners. This issue - makes JVM output available to ANT JUnit4's listeners so that they can - log it properly. Previously the JVM output was copied to System.out - which could be hard to work with. See TextReport.onJvmOutput for - an example. The default value of 'jvmOutputAction' has been changed - from 'pipe, warn' to 'listeners, warn' so that listeners get - notified about JVM output instead of it being copied directly to - sysout. (Dawid Weiss, Ryan Ernst). - -Other Changes - - * GH-220: Add an indication of the number of failed suites so far to text - report. (Dawid Weiss, Chris Hostetter). - - * GH-224: Remove excess use of Guava's collections. (Dawid Weiss) - - * GH-221: Upgrade to Guava 19.0-rc3. (Dawid Weiss, Ryan Ernst) - -Bug Fixes - - * PR #223: Access private fields within doPrivileged (Robert Muir) - -======================= randomizedtesting 2.3.1 ==================== - -New Features - - * GH-219: Add randomBytes generator utility. (Dawid Weiss) - - * GH-190: RandomizedContext should provide the current test - case method (via RandomizedContext.current().getTargetMethod()). - (Dawid Weiss) - - * GH-217: Permit running tests on the same instance of the suite - class via TestCaseInstanceProvider annotation. See - Test018TestCaseInstanceProviders example. (Dawid Weiss). - -======================= randomizedtesting 2.3.0 ==================== - -New Features - - * GH-216: Custom test case argument formatters in parameter factories. - See ParametersFactory.argumentFormatting and Test007ParameterizedTests - example. (Dawid Weiss). - - * GH-194: Flexible test case ordering via the new annotation - (TestCaseOrdering). (Dawid Weiss) - -Bug Fixes - - * GH-215: In certain cases test case names could be duplicated (be - identical), which could confuse IDEs. (Dawid Weiss) - -======================= randomizedtesting 2.2.0 ==================== - -Changes in Backwards Compatibility - - * PR #178: Move to Java 1.7 and use the java NIO 2 API for temp files. - (Simon Willnauer) - - * GH-184: RandomizedTest should not extend Assert. This permits easier use - of other frameworks (like assertj) via static imports without naming conflicts. - (Olivier Bourgain, Dawid Weiss) - -New Features - - * GH-191: "Tests with failures" should repeat the master seed at the end - of the report. (Dawid Weiss) - -Bug Fixes - - * GH-192: Reworked json streaming to get rid of gson and permit dumping - JVM-related diagnostics (security manager policy dumps, etc.). - (Dawid Weiss) - - * GH-206: Potential NPE in checking getDefaultUncaughtExceptionHandler. - (Dawid Weiss) - -Other Changes - - * GH-210: Make RR compilable/ testable under Java 1.9. (Dawid Weiss) - - * GH-209: Remove dependency on commons-io. (Dawid Weiss) - - * GH-204: modernize and clean up project layout. (Dawid Weiss) - -======================= randomizedtesting 2.1.17 ============================ - -Bug Fixes - - * GH-201: Tests still running (and zombified) after suite timeout occurred. - (Dawid Weiss) - -Other Changes - - * GH-205: Report test seed in halt on failure message. (Dawid Weiss) - - * GH-203: report the number of completely ignored suites - in the summary. (Dawid Weiss) - - * PR #202: support running with security manager and limit the required - permissions. (Robert Muir) - -======================= randomizedtesting (pre 2.2.0) ======================= - -No separate changelog was maintained. See git commit history or issues at -GitHub. diff --git a/CONTRIBUTING.txt b/CONTRIBUTING.txt deleted file mode 100644 index aecc89d4..00000000 --- a/CONTRIBUTING.txt +++ /dev/null @@ -1,9 +0,0 @@ -Contributions are welcome! - -If you use Eclipse, set up project formatting and -validation with: - -mvn -Peclipse - -If you don't use Eclipse, try to adhere to the -existing coding standard. diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index be012db7..00000000 --- a/LICENSE.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2011--, Carrot Search s.c. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/README.txt b/README.txt deleted file mode 100644 index 03be9fe4..00000000 --- a/README.txt +++ /dev/null @@ -1,15 +0,0 @@ - -RANDOMIZED TESTING -================== - -JUnit test runner and plugins for running JUnit tests -with pseudo-randomness. - -See the following for more information: - Docs: https://github.com/randomizedtesting/randomizedtesting/wiki - Bugs: https://github.com/randomizedtesting/randomizedtesting/issues - CI: http://builds.carrot2.org/browse/RNDTEST - -See LICENSE.txt to make your company's lawyer happy. - -See CHANGES.txt for API changes and updates. diff --git a/etc/eclipse/settings/org.eclipse.jdt.core.prefs b/etc/eclipse/settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 01ade8bf..00000000 --- a/etc/eclipse/settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,286 +0,0 @@ -#Thu Jan 26 09:50:07 CET 2012 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 -org.eclipse.jdt.core.compiler.compliance=1.7 -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.source=1.7 -org.eclipse.jdt.core.formatter.align_type_members_on_columns=false -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_assignment=0 -org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 -org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 -org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 -org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 -org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 -org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 -org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 -org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 -org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_after_package=1 -org.eclipse.jdt.core.formatter.blank_lines_before_field=0 -org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 -org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 -org.eclipse.jdt.core.formatter.blank_lines_before_method=1 -org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 -org.eclipse.jdt.core.formatter.blank_lines_before_package=0 -org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 -org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 -org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false -org.eclipse.jdt.core.formatter.comment.format_block_comments=true -org.eclipse.jdt.core.formatter.comment.format_header=false -org.eclipse.jdt.core.formatter.comment.format_html=true -org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true -org.eclipse.jdt.core.formatter.comment.format_line_comments=true -org.eclipse.jdt.core.formatter.comment.format_source_code=true -org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true -org.eclipse.jdt.core.formatter.comment.indent_root_tags=true -org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert -org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert -org.eclipse.jdt.core.formatter.comment.line_length=80 -org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true -org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true -org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false -org.eclipse.jdt.core.formatter.compact_else_if=true -org.eclipse.jdt.core.formatter.continuation_indentation=2 -org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 -org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off -org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on -org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false -org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true -org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true -org.eclipse.jdt.core.formatter.indent_empty_lines=true -org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true -org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true -org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true -org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true -org.eclipse.jdt.core.formatter.indentation.size=2 -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert -org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert -org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert -org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert -org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert -org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert -org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert -org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert -org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.join_lines_in_comments=true -org.eclipse.jdt.core.formatter.join_wrapped_lines=true -org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=true -org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false -org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false -org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=true -org.eclipse.jdt.core.formatter.lineSplit=100 -org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false -org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false -org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 -org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 -org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true -org.eclipse.jdt.core.formatter.tabulation.char=space -org.eclipse.jdt.core.formatter.tabulation.size=2 -org.eclipse.jdt.core.formatter.use_on_off_tags=true -org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true -org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true -org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true -org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/etc/eclipse/settings/org.eclipse.jdt.ui.prefs b/etc/eclipse/settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index e812d3d7..00000000 --- a/etc/eclipse/settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,4 +0,0 @@ -#Thu Jan 26 09:50:07 CET 2012 -eclipse.preferences.version=1 -formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile -formatter_settings_version=12 diff --git a/etc/forbidden-apis/signatures.txt b/etc/forbidden-apis/signatures.txt deleted file mode 100644 index 2f70d305..00000000 --- a/etc/forbidden-apis/signatures.txt +++ /dev/null @@ -1,38 +0,0 @@ -@defaultMessage Convert to URI -java.net.URL#getPath() -java.net.URL#getFile() - -@defaultMessage spawns threads with vague names; use a custom thread factory and name threads so that you can tell (by its name) which executor it is associated with -java.util.concurrent.Executors#newFixedThreadPool(int) -java.util.concurrent.Executors#newSingleThreadExecutor() -java.util.concurrent.Executors#newCachedThreadPool() -java.util.concurrent.Executors#newSingleThreadScheduledExecutor() -java.util.concurrent.Executors#newScheduledThreadPool(int) -java.util.concurrent.Executors#defaultThreadFactory() -java.util.concurrent.Executors#privilegedThreadFactory() - -java.lang.Character#codePointBefore(char[],int) @ Implicit start offset is error-prone when the char[] is a buffer and the first chars are random chars -java.lang.Character#codePointAt(char[],int) @ Implicit end offset is error-prone when the char[] is a buffer and the last chars are random chars - -@defaultMessage Please do not try to stop the world -java.lang.System#gc() - -@defaultMessage Use Channels.* methods to write to channels. Do not write directly. -java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer) -java.nio.channels.FileChannel#write(java.nio.ByteBuffer, long) -java.nio.channels.GatheringByteChannel#write(java.nio.ByteBuffer[], int, int) -java.nio.channels.GatheringByteChannel#write(java.nio.ByteBuffer[]) -java.nio.channels.ReadableByteChannel#read(java.nio.ByteBuffer) -java.nio.channels.ScatteringByteChannel#read(java.nio.ByteBuffer[]) -java.nio.channels.ScatteringByteChannel#read(java.nio.ByteBuffer[], int, int) -java.nio.channels.FileChannel#read(java.nio.ByteBuffer, long) - -@defaultMessage Filters are trappy (add suppression or make sure all read methods are redelegated). -java.io.FilterInputStream#(java.io.InputStream) -java.io.FilterOutputStream#(java.io.OutputStream) -java.io.FilterReader#(java.io.Reader) -java.io.FilterWriter#(java.io.Writer) - -#@defaultMessage Do not use context class loaders, prefer explicit ClassLoader argument. -java.lang.Thread@getContextClassLoader() -java.lang.Thread@setContextClassLoader() diff --git a/examples/ant/build.xml b/examples/ant/build.xml deleted file mode 100644 index 93a12a9b..00000000 --- a/examples/ant/build.xml +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Done. See reports under target/. - - - - diff --git a/examples/ant/pom.xml b/examples/ant/pom.xml deleted file mode 100644 index 5de40335..00000000 --- a/examples/ant/pom.xml +++ /dev/null @@ -1,140 +0,0 @@ - - 4.0.0 - - - com.carrotsearch.randomizedtesting - randomizedtesting-parent - 2.7.9-SNAPSHOT - ../../pom.xml - - - randomizedtesting-examples-ant - RandomizedTesting ANT Examples - - - Simple use-case examples meant to be included in some - end-user documentation if it's ever going to be written... - - - - true - - - - - - com.carrotsearch.randomizedtesting - randomizedtesting-examples - ${project.version} - compile - - - - - com.carrotsearch.randomizedtesting - junit4-ant - ${project.version} - compile - - - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - org.apache.maven.plugins - maven-dependency-plugin - [1.0.0,) - - copy-dependencies - - - - - - - - - - - - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - integration-test - - copy-dependencies - - - ${basedir}/target/lib - - - - - - - org.apache.maven.plugins - maven-antrun-plugin - - - ant-run-tests - integration-test - - - - - - - run - - - - - - - - - - - tools.jar - - - ${java.home}/../lib/tools.jar - - - - - - org.apache.maven.plugins - maven-antrun-plugin - - - com.sun - tools - 1.5.0 - system - ${java.home}/../lib/tools.jar - - - - - - - - diff --git a/examples/maven/pom.xml b/examples/maven/pom.xml deleted file mode 100644 index 502ddfb1..00000000 --- a/examples/maven/pom.xml +++ /dev/null @@ -1,103 +0,0 @@ - - 4.0.0 - - - com.carrotsearch.randomizedtesting - randomizedtesting-parent - 2.7.9-SNAPSHOT - ../../pom.xml - - - randomizedtesting-examples - RandomizedTesting Examples - - - Simple use-case examples meant to be included in some - end-user documentation if it's ever going to be written... - - - - true - - - - - com.carrotsearch.randomizedtesting - randomizedtesting-runner - ${project.version} - compile - - - - junit - junit - compile - - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - default-test - none - - - - - - - com.carrotsearch.randomizedtesting - junit4-maven-plugin - ${project.version} - - - junit4-tests - - junit4 - - test - - - false - - - ${project.build.outputDirectory} - - - - - - - - - - - - - - - - - - - diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test001SimpleUseCase.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test001SimpleUseCase.java deleted file mode 100644 index 6ece9fbb..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test001SimpleUseCase.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; - -/** - * This is a test-based tutorial introducing to randomized JUnit testing using - * {@link RandomizedRunner}. Follow test cases in their alphabetic order. - * - *

One way to start using {@link RandomizedRunner} is to declare - * your suite class as being executed by {@link RandomizedRunner} (using - * {@link RunWith} annotation). The {@link #success()} method doesn't do anything - * useful but runs under {@link RandomizedRunner}. We know this for sure because we - * can hide a hook (before()) method to be private - * (normal JUnit doesn't allow this). - */ -@RunWith(RandomizedRunner.class) -public class Test001SimpleUseCase { - @Before - private void before() { - // This won't work under the default JUnit runner. - } - - @Test - public void success() { - // Do nothing. - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test002ExtendingRandomizedTest.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test002ExtendingRandomizedTest.java deleted file mode 100644 index 98e3eec4..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test002ExtendingRandomizedTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import java.util.Random; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedContext; -import com.carrotsearch.randomizedtesting.RandomizedTest; - -/** - * To start using pseudo-randomization we need to get hold of the - * {@link RandomizedContext} instance associated with the test. This can be done - * manually, as shown in {@link #getContextByHand()} method or (better) we can - * extend {@link RandomizedTest} and have a superclass method to handle this - * (and more) for us as shown in {#link #getContextFromSuper()} - * - *

Note that {@link Random} instances acquired from the context are - * preinitialized with a repeatable seed (we'll get to that) so tests - * can be re-run with the same random sequence if something fails. - */ -public class Test002ExtendingRandomizedTest extends RandomizedTest { - @Test - public void getContextByHand() { - RandomizedContext context = RandomizedContext.current(); - Random rnd = context.getRandom(); - System.out.println("Random, next int: " + rnd.nextInt()); - } - - @Test - public void getContextFromSuper() { - Random rnd = super.getRandom(); - System.out.println("Random, next int: " + rnd.nextInt()); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test003UsingRandomness.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test003UsingRandomness.java deleted file mode 100644 index 0e6f5801..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test003UsingRandomness.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import java.util.Random; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.RandomizedTest; - -import static org.junit.Assert.*; - -/** - * So far we haven't really used the {@link Random} provided by - * {@link RandomizedRunner}. The idea behind randomized tests is to, for each - * test execution: - *

    - *
  • cover a possibly different execution path of the tested component,
  • - *
  • cover a different data (input) passed to the tested component, - *
  • - *
  • execute in a different "environment" if there is environment variability. - *
  • - *
- * - *

- * Let's see this on a simple example of a method that adds two - * integers ({@link Adder#add(int, int)}). We can test this method using a "fixed" test - * case as shown in {@link #fixedTesting} but this test will always execute in - * an identical way (which is good if you're looking for regression coverage but - * bad if you want to expand your tested domain). - * - *

- * A randomized test, on the other hand, will pick parameters from a larger - * spectrum of values and assert on the method's contract. Here, we can make - * sure the sum is always larger or equal than the arguments given two positive - * arguments. This assertion will fail quite often because of integer overflows as shown - * in {@link #randomizedTesting()} (re-run the test a few times if it doesn't - * fail the first time). - * - *

- * While the above example is trivial most of the bugs in code stem from similar - * subtleties (possibly resulting from more complex interactions). In many cases - * the "contract" that we can assert on can be stated as "throw no-exception" given - * valid arguments. An example of that is in method {@link #expectNoException()}. - * At first glance this method will work most of the time, but try passing - * {@link Integer#MIN_VALUE} as a random number and see what will happen. - */ -public class Test003UsingRandomness extends RandomizedTest { - public static class Adder { - //[[[start:adder]]] - /** - * This method adds a and b and returns their sum. - */ - public static int add(int a, int b) { - return a + b; - } - //[[[end:adder]]] - } - - //[[[start:adder-fixed]]] - @Test - public void fixedTesting() { - // Note how we use superclass methods, RandomizedTest extends from - // Assert so these methods are readily available. - assertEquals( 4, Adder.add(2, 2)); - assertEquals(-1, Adder.add(0, -1)); - assertEquals( 0, Adder.add(0, 0)); - } - //[[[end:adder-fixed]]] - - //[[[start:adder-randomized]]] - @Test - public void randomizedTesting() { - // Here we pick two positive integers. Note superclass utility methods. - int a = randomIntBetween(0, Integer.MAX_VALUE); - int b = randomIntBetween(0, Integer.MAX_VALUE); - int result = Adder.add(a, b); - assertTrue(result + " < (" + a + " or " + b + ")?", result >= a && result >= b); - } - //[[[end:adder-randomized]]] - - @Test - public void expectNoException() { - String [] words = {"oh", "my", "this", "is", "bad."}; - - // This will pick a random word from the array above... - System.out.println(words[Math.abs(randomInt()) % words.length]); - - // .. unless the random picked happens to be this number (fixed to get - // a reproducible example, but you get the idea); - System.out.println(words[Math.abs(Integer.MIN_VALUE) % words.length]); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test004MoreRandomness.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test004MoreRandomness.java deleted file mode 100644 index ee4a4b60..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test004MoreRandomness.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import java.util.Random; - -import org.junit.AfterClass; -import org.junit.Test; -import org.junit.runner.Description; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -import com.carrotsearch.randomizedtesting.RandomizedContext; -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.SysGlobals; -import com.carrotsearch.randomizedtesting.annotations.Seed; -import com.carrotsearch.randomizedtesting.annotations.Seeds; - -/** - * Randomness is entwined everywhere in {@link RandomizedRunner}. An instance of - * {@link Random} is of course available from a {@link RandomizedContext}, but - * even tests themselves are randomized, or to be more precise: their order of - * execution is shuffled. - * - *

- * In this example we have two classes that contain three methods (they're nested - * under a single suite class for simplicity). Every execution of class - * {@link Test004MoreRandomness.OrderRandomized} will be different, shuffling - * test methods around (and the random numbers written to the output). - * We can "pin" the execution order by forcing the master random - * seed using {@link Seed} annotation on the class (or a system property - * {@link SysGlobals#SYSPROP_RANDOM_SEED}). Doing so also fixes all derivative random - * generators in all tests - this is shown in - * {@link Test004MoreRandomness.OrderRandomizedButFixed}, every execution of this - * class will be identical (and will emit identical pseudo-random numbers). - * - *

- * All this is meant for one purpose: help in reproducing a failed randomized test - * case. Once a test case fails, make sure you write down the random seed number - * that caused the failure and add appropriate {@link Seeds} annotation on the method - * that failed like so: - *

- * {@literal @}{@link Seeds}({
- *   {@literal @}{@link Seed}("012345"),
- *   {@literal @}{@link Seed}()
- * })
- * 
- * where 012345 is the replaced by the seed that caused the failure. This makes - * the test methods run with a fixed seed once and then with a random seed again, - * easily creating a new regression test so that the bug does not reoccur in the - * future. An example of that is shown in - * {@link Test004MoreRandomness.OrderRegression#regression()}. Also note - * how {@link RandomizedRunner} modifies test method names for such "expanded" methods, appending - * the random seed as a parameter. This is needed to avoid duplicate - * test {@link Description} objects (a design flaw in JUnit). We will see these parameters - * again in the example concerning parameterized tests. - */ -@RunWith(Suite.class) -@SuiteClasses({ - Test004MoreRandomness.OrderRandomized.class, - Test004MoreRandomness.OrderRandomizedButFixed.class, - Test004MoreRandomness.OrderRegression.class -}) -public class Test004MoreRandomness { - public static class OrderRandomized extends RandomizedTest { - @Test public void method1() { System.out.println("method1, " + randomInt()); } - @Test public void method2() { System.out.println("method2, " + randomInt()); } - @Test public void method3() { System.out.println("method3, " + randomInt()); } - - @AfterClass - public static void empty() { - System.out.println("--"); - } - } - - @Seed("deadbeef") - public static class OrderRandomizedButFixed extends OrderRandomized { - } - - public static class OrderRegression extends RandomizedTest { - @Seeds({ - @Seed("deadbeef"), - @Seed() - }) - @Test public void regression() { System.out.println("regression, " + randomInt()); } - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test005RecoveringRandomSeed.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test005RecoveringRandomSeed.java deleted file mode 100644 index f28a2b1b..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test005RecoveringRandomSeed.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import java.util.Random; - -import org.junit.*; - -import com.carrotsearch.randomizedtesting.*; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.Seed; - -/** - * {@link RandomizedRunner} uses several "contexts", each of which is assigned a - * predictable {@link Random} and is modeled using a {@link Randomness} - * instance. The "suite" or "master" context is available from - * {@link BeforeClass} or {@link AfterClass} hooks, for example. Each test - * method has a nested context with a random seed derived from the master. This - * way even though the order of tests is shuffled and each test can make a - * random number of calls to its own context's {@link Random} instance, the - * global execution paths can always be repeated from the same master seed. The - * question is: how do we know what master seed was used? There are at least two - * ways to find out. - * - *

The master seed is always available from - * {@link RandomizedContext#getRunnerSeedAsString()} so one can simply print it to the - * console. The current context's {@link Randomness} itself can be printed to the - * console. In two methods in this class {@link #printMasterContext()} and {@link #printContext()} - * we print the master seed and current context's {@link Randomness}, note how the static - * context's {@link Randomness} is identical with the runner's but the test context - * is a derived value. - *

- * # Static context ({@literal @}BeforeClass)
- * AF567B2B9F8A8F1C
- * [Randomness, seed=[AF567B2B9F8A8F1C]]
- * # Test context ({@literal @}Test)
- * AF567B2B9F8A8F1C
- * [Randomness, seed=[EE581D5EC61D6BCF]]
- * 
- * In {@link Test006RepeatingTests} we will see how this derived - * seed is used with {@link Repeat} annotation. - * - *

Normally we will not be interested in a random seed if a test case passes. But if a test - * case fails we will want to know the seed to be able to repeat the test. {@link RandomizedRunner} - * augments the stack trace of all exceptions that cross the context boundary (this includes - * assertion errors, assumption failures and any other exceptions). In method {@link #failure()} - * we demonstrate this by failing on a constant condition. If you run this test suite, you'll note - * the stack trace of the failing method to be something like this: - *

- * java.lang.AssertionError
- *   at __randomizedtesting.SeedInfo.seed([AF567B2B9F8A8F1C:44E2D1A039274F2A]:0)
- *   at org.junit.Assert.fail(Assert.java:92)
- * 
- * - * The first line of the stack trace is a synthetic (non-existing) class with "source file" - * entry containing all contexts' seeds on the stack (from master to the current test method). - * In this case, you can see the master context first (AF567B2B9F8A8F1C), followed - * by the test's context (44E2D1A039274F2A). The entire class has a fixed master seed - * so that the result will always be the same here: - *
- * {@literal @}{@link Seed}("AF567B2B9F8A8F1C")
- * public class Test005RecoveringRandomSeed extends RandomizedTest { // ...
- * 
- */ -@Seed("AF567B2B9F8A8F1C") -public class Test005RecoveringRandomSeed extends RandomizedTest { - @BeforeClass - public static void printMasterContext() { - System.out.println("# Static context (@BeforeClass)"); - System.out.println(getContext().getRunnerSeedAsString()); - System.out.println(RandomizedContext.current().getRandomness()); - } - - @Test - public void printContext() { - System.out.println("# Test context (@Test)"); - System.out.println(getContext().getRunnerSeedAsString()); - System.out.println(RandomizedContext.current().getRandomness()); - } - - @Test - public void failure() { - Assert.assertTrue(false); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test006RepeatingTests.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test006RepeatingTests.java deleted file mode 100644 index dc93be2a..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test006RepeatingTests.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import org.junit.*; - -import com.carrotsearch.randomizedtesting.*; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.Seed; - -import static org.junit.Assert.*; - -/** - * In example {@link Test005RecoveringRandomSeed} we presented - * {@link Randomness} contexts and how they are derived from a master seed. Once - * you know a certain test case fails it is usually beneficial to immediately - * check if it always fails on a given seed (which means there is a - * deterministic failure scenario). A simple way to do so would be to re-run a - * test case a few times. The same effect can be achieved by adding a - * {@link Repeat} annotation with {@link Repeat#useConstantSeed()} set to - * false attribute as shown in the method {@link #repeatFailure()} - * below. - *
- * {@literal @}{@link Repeat}(iterations = 5, useConstantSeed = true)
- * {@literal @}{@link Seed}("f00ddead")
- * {@literal @}{@link Test}
- * public void repeatFailure() { //...
- * 
- * Note how the seed is fixed using {@link Seed} annotation (on the - * method) rather than on the master. This ensures the method's context is - * pinned to that value, but the master is still random. If you have - * {@link BeforeClass} hooks that depend on randomness you should use - * suite-level {@link Seed} annotation and pin the master seed instead. - * - *

You can also set {@link Repeat#useConstantSeed()} to false and - * then every iteration of the test method will have a pseudo-random context derived - * from the first one (pinned or not). This can be useful to tell how frequently - * a given test case fails for a random seed. For {@link #halfAndHalf()} method - * about 50% of iterations will fail. - */ -public class Test006RepeatingTests extends RandomizedTest { - @Repeat(iterations = 5, useConstantSeed = true) - @Seed("f00ddead") - @Test - public void repeatFailure() { - assertTrue(randomBoolean()); - } - - @Repeat(iterations = 10, useConstantSeed = false) - @Test - public void halfAndHalf() { - assertTrue(randomBoolean()); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test007ParameterizedTests.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test007ParameterizedTests.java deleted file mode 100644 index d42d794a..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test007ParameterizedTests.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import java.util.Arrays; -import java.util.Formatter; - -import org.junit.Test; -import org.junit.runners.Parameterized; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Name; -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.Seed; -import com.carrotsearch.randomizedtesting.annotations.Seeds; - -/** - * Parameterized tests are tricky. JUnit's {@link Parameterized} runner is - * notoriously bad at giving human-readable test case names (there are several - * patch proposal on github but not applied to the trunk at the time of writing - * this). - * - *

{@link RandomizedRunner} has built-in support for parameters using a pair - * of static-parameters provider method (factory) and a matching constructor. - * The static method has to be public and annotated with {@link ParametersFactory}, - * as in {@link #parameters()} method below. Note the funky-looking $ - * and $$ method which are static varargs collector methods to avoid - * explicit array constructors. - *

- * {@literal @}{@link ParametersFactory}
- * public static Iterable<Object[]> parameters() {
- *   return Arrays.asList($$(
- *     $(1, "abc"), 
- *     $(2, "def")));
- * }
- * 
- * - *

The matching class constructor must declare type-assignable parameters. Because method - * arguments are not part of the Java reflection, they can be explicitly annotated using - * {@link Name} annotation to provide sensible names. - * The {@link #Test007ParameterizedTests(int, String)} - * constructor shows an example of how this looks. - * - *

If there is more than one set of parameters, method names will be postfixed with - * a list of parameters and their values. An additional #num identifier will - * be added to make tests unique. - * - *

{@link ParametersFactory} can be combined with other annotations such as - * {@link Repeat} or {@link Seeds} as shown in {@link #paramsWithRepeatAndSeeds()}. - * - *

Note that {@code ParametersFactory.argumentFormatting()} permits custom - * test case naming, see the example factory in this class. - */ -public class Test007ParameterizedTests extends RandomizedTest { - private int value; - private String string; - - public Test007ParameterizedTests( - @Name("value") int value, - @Name("string") String string) { - this.value = value; - this.string = string; - } - - @Test - public void simpleArgumentsConsumer() { - System.out.println(value + " " + string + " " - + getContext().getRandomness()); - } - - @Seeds({@Seed("deadbeef"), @Seed("cafebabe")}) - @Test - @Repeat(iterations = 2, useConstantSeed = true) - public void paramsWithRepeatAndSeeds() { - System.out.println(value + " " + string + " " - + getContext().getRandomness()); - } - - @ParametersFactory - public static Iterable parameters() { - return Arrays.asList($$( - $(1, "abc"), - $(2, "def"))); - } - - /** - * A factory with custom test name formatting. Note parameters - * are reversed and referenced from the formatting string via - * {@link Formatter} positional order syntax - */ - @ParametersFactory(argumentFormatting = "param2:%2$s param1:%1$04d") - public static Iterable parametersWithCustomName() { - return Arrays.asList($$( - $(3, "foo"), - $(4, "bar"))); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test008Timeouts.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test008Timeouts.java deleted file mode 100644 index c0fd04e6..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test008Timeouts.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Timeout; - -/** - * {@link RandomizedRunner} has built-in support for enforcing test timeouts. If - * a given test fails to execute in the given deadline, its thread will be - * forcibly terminated (details below) and the test case will end in a failure. - * - *

- * A timeout can be specified in two ways. First, the standard JUnit's - * {@link Test#timeout()} attribute can be used (see - * {@link #standardAnnotation()}). Alternatively, a more specific @link Timeout} - * annotation is also provided if one needs to be explicit. - * - *

- * The termination of a test thread is done in several steps ranking from subtle - * to brute-force: - *

    - *
  • First, the thread is interrupted a few times with - * {@link Thread#interrupt()}. In many situations (I/O wait, waiting on a - * monitor) this will be enough to stop the test case and return. - *
  • If interrupt doesn't work (busy-loops, interrupted exception caught and - * ignored), an attempt is made to stop the thread using {@link Thread#stop()}. - * This should cause the test thread to throw {@link ThreadDeath} exception at - * the current execution pointer and propagate up the stack. - *
  • Should {link {@link ThreadDeath} be caught and ignored as well, the - * thread is declared a zombie and other tests execution is resumed with the - * thread running in the background. - *
- * - *

- * The information about attempts to interrupt the thread are logged to the - * Java's logging system along with the information about stack traces where the - * thread resided when interrupts were sent to it. This is typically useful in - * diagnosing what the thread was doing and why it couldn't be terminated. Keeping - * Java logging system enabled is thus strongly encouraged. - */ -public class Test008Timeouts extends RandomizedTest { - @Test(timeout = 500) - public void standardAnnotation() { - sleep(10000); - } - - @Test - @Timeout(millis = 500) - public void timeoutAnnotation() { - sleep(10000); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test009ThreadLeaks.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test009ThreadLeaks.java deleted file mode 100644 index d52b6bed..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test009ThreadLeaks.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import java.util.concurrent.*; - -import org.junit.*; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.RandomizedTest; - -/** - * Leaked background threads can crash tests randomly even if all seeds are - * known and predictable. They can also affect other test cases and so we should - * not allow any threads to "leak outside" of their scope (a single test case or - * a single suite if the thread is started in {@link BeforeClass} or - * {@link AfterClass} hooks). - * - *

- * {@link RandomizedRunner} has built-in support for detecting threads that - * escaped their current {@link ThreadGroup}'s boundary. Such threads are killed - * and make the test (or suite) fail with appropriate exception. - * {@link #leftOverThread()} method below shows a simple scenario in which a - * test leaks outside its test boundary. A correct code that calls {@link Thread#join()} - * is shown in {@link #noLeakHere()}. - * - *

- * More concepts concerning leaking threads and some workarounds for typical - * problems with them is shown in {@link Test010Lingering}. - */ -public class Test009ThreadLeaks extends RandomizedTest { - @Test - public void leftOverThread() throws Exception { - final CountDownLatch go = new CountDownLatch(1); - - Thread t = new Thread() { - public void run() { - try { - go.countDown(); - Thread.sleep(1000); - } catch (InterruptedException e) {/* ignore */} - } - }; - - // Start and wait for it to really start. - t.start(); - go.await(); - } - - @Test - public void noLeakHere() throws Exception { - final CountDownLatch go = new CountDownLatch(1); - - Thread t = new Thread() { - public void run() { - try { - go.countDown(); - Thread.sleep(1000); - } catch (InterruptedException e) {/* ignore */} - } - }; - - // Start and wait for it to really start. - t.start(); - go.await(); - t.join(); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test010Lingering.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test010Lingering.java deleted file mode 100644 index eb9a80dd..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test010Lingering.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import java.util.concurrent.*; - -import org.junit.Assert; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies; - -/** - * In many cases the creation of background threads lies beyond our control (and - * their direct termination or even awaiting for their termination) is not - * possible. A good example is the {@link Executors} framework where background - * {@link ThreadFactory} is not published if not given explicitly. - * To handle such situations {@link RandomizedRunner} needs to know if it should - * await background thread to complete (and for how long) or if it should allow - * them to "leak" safely and not complain. All this can be declared with a set - * of annotations starting with ThreadLeak* prefix. - * - *

We can use {@link ThreadLeakLingering} annotation instead of explicitly using - * {@link Thread#join()} sometimes. For example, {@link Test009ThreadLeaks#leftOverThread()} - * can be rewritten as shown in {@link #lingerForLeftOverThread()}. - * - *

The same annotation can be used to wait for background threads - * which we don't have any control on, but we know they will eventually terminate. - * For example, a terminated {@link Executor} does not wait (join) with its slave - * threads so lingering here is required. This is shown in method {@link #executorLeak()}. This - * method will fail (from time to time, it isn't guaranteed) if no lingering time is given. - * - *

There are other annotations for advanced control of thread leaks and their outcomes, check out - * the javadocs in the links below. - * - * @see ThreadLeakScope - * @see ThreadLeakLingering - * @see ThreadLeakAction - * @see ThreadLeakZombies - */ -public class Test010Lingering extends RandomizedTest { - - @Test @ThreadLeakLingering(linger = 2000) - public void lingerForLeftOverThread() throws Exception { - final CountDownLatch go = new CountDownLatch(1); - - Thread t = new Thread() { - public void run() { - try { - go.countDown(); - Thread.sleep(1000); - } catch (InterruptedException e) {/* ignore */} - } - }; - - // Start and wait for it to really start. - t.start(); - go.await(); - } - - // @ThreadLeaks(linger = 1000) // Enable me to make it pass all the time. - @Test @Repeat(iterations = 10) - public void executorLeak() throws Exception { - int numThreads = 50; - final ExecutorService executor = Executors.newFixedThreadPool(numThreads); - for (int i = 0; i < 2 * numThreads; i++) { - executor.submit(new Runnable() { - public void run() { - sleep(10); - } - }); - } - - executor.shutdown(); - executor.awaitTermination(1, TimeUnit.SECONDS); - Assert.assertTrue(executor.isShutdown()); - Assert.assertTrue(executor.isTerminated()); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test011NightlyTests.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test011NightlyTests.java deleted file mode 100644 index a0cecf96..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test011NightlyTests.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import org.junit.Assume; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.*; -import com.carrotsearch.randomizedtesting.annotations.Nightly; -import com.carrotsearch.randomizedtesting.annotations.TestGroup; - -/** - * Running tests on a developer machine is often a pain, in particular when - * certain tests are long and repetitive. If you have a dedicated continuous - * integration environment like Jenkins or - * Attlasian Bamboo then it - * is nice to be able to "stress" your tests a bit more during nightly or server - * runs compared to normal developer runs. - * - *

{@link RandomizedRunner} has a built-in {@link TestGroup} called {@link Nightly} - * for "scaling" the execution depending if is in nightly mode or not. In the simplest - * case (see {@link #nightlyOnly()} a test case is run in nightly mode and ignored in - * normal runs. This can be done by annotating a test case or suite using {@link Nightly} - * or by checking for nightly mode explicitly. - * - *

For tests whose runtime depends on the amount of input data or other varying complexity, - * one can use {@link RandomizedTest#scaledRandomIntBetween(int, int)} method or the current - * {@link RandomizedTest#multiplier()}. These methods adjust to the nightly mode picking - * larger values than in daily mode (see javadocs for details). - */ -public class Test011NightlyTests extends RandomizedTest { - @Nightly - @Test - public void nightlyOnly() throws Exception { - // Do nothing, but pretend we're long and slow. - } - - @Test - public void nightlyOnlyWithAssume() throws Exception { - // Only run if Nightly test group is explicitly enabled using -Dtests.nightly=true - Assume.assumeTrue(RandomizedContext.current().getGroupEvaluator().isGroupEnabled(Nightly.class)); - } - - @Test - public void scaling() throws Exception { - System.out.println("Mode: " + (isNightly() ? "nightly" : "daily")); - System.out.println("Multiplier: " + multiplier()); - for (int i = 0; i < 10; i++) { - System.out.println("random scaled int = " + scaledRandomIntBetween(0, 100)); - } - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test012TestGroups.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test012TestGroups.java deleted file mode 100644 index 2093ba2e..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test012TestGroups.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import java.lang.annotation.*; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Nightly; -import com.carrotsearch.randomizedtesting.annotations.TestGroup; - -/** - * We introduced the notion of {@link Nightly} tests in - * {@link Test011NightlyTests}. Similar to this idea, the user can introduce any - * number of custom test groups which can be arbitrarily enabled or disabled. In - * fact, {@link Nightly} is also defined as such a {@link TestGroup}. - * - *

- * A custom test group is an annotation itself annotated with a - * {@link TestGroup}. For example, let's say we want a test group that marks all - * tests that require a physical display. An annotation for this is shown in - * {@link Test012TestGroups.RequiresDisplay}. It has no additional attributes. - * What makes it a test group is a meta-annotation: - * - *

- * {@literal @}{@link TestGroup}(name = "requiresdisplay", enabled = false, sysProperty = "display")
- * 
- * - * which states that the group's name is "requiresdisplay" and that the group is - * initially disabled unless a system property "display" is set to a boolean - * value "false", "off" or "disabled". - * - *

- * {@link Nightly} is defined in a very similar way. Note that test groups are - * real annotations so they are recognizable by IDEs, can be searched, - * manipulated etc. - * - *

- * Another feature of using {@link RandomizedRunner} with groups is the ability to specify - * complex group-based filters specified via tests.filter system property. - * These filters are boolean conditions, with optional parentheses. For example: - *

    - *
  • {@literal @}nightly - runs all tests with test group named nightly.
  • - *
  • not {@literal @}nightly - runs all tests not annotated with a test group named nightly.
  • - *
  • {@literal @}fast and not {@literal @}requiresdisplay - runs all tests annotated with fast and not annotated with requiresdisplay.
  • - *
  • not ({@literal @}slow or {@literal @}nightly) - skips any tests annotated with slow or nightly.
  • - *
- * - * Important! Note that using filtering expression has precedence over the default state of a group - * and its corresponding system property. This is intentional so that filtering expressions can be used - * independently of each group's default state. Should the default state be taken into account one - * can use a special keyword default, as in: - *
    - *
  • default and not {@literal @}slow - runs any tests that would be selected by their default - * group status (including those that do not have any test groups at all), - * excluding any tests annotated with slow.
  • - *
- */ -public class Test012TestGroups extends RandomizedTest { - @TestGroup(name = "requiresdisplay", enabled = false, sysProperty = "display") - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD}) - public static @interface RequiresDisplay {} - - @Test - @RequiresDisplay - public void usesDisplay() { - System.out.println("Running on windows."); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test014Listeners.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test014Listeners.java deleted file mode 100644 index 7e222532..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test014Listeners.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import org.junit.Assert; - -import org.junit.Test; -import org.junit.runner.notification.RunListener; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Listeners; -import com.carrotsearch.randomizedtesting.listeners.ReproduceInfoPrinter; - -/** - * {@link RandomizedRunner} respects an on-suite class {@link Listeners} - * annotation and instantiates classes that implement {@link RunListener}. This - * allows custom listener hooks on the suite. - * - *

- * We honestly don't know where this would be useful. For now there are just a - * few listeners, among them {@link ReproduceInfoPrinter} which dumps failure - * information along with a preformatted JVM-options string to reproduce the - * given test case (includes seed and filters). - */ -@Listeners({ReproduceInfoPrinter.class}) -public class Test014Listeners extends RandomizedTest { - @Test - public void failure() { - Assert.assertTrue(false); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test015CustomMethodProviders.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test015CustomMethodProviders.java deleted file mode 100644 index 10d2494c..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test015CustomMethodProviders.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import com.carrotsearch.randomizedtesting.ClassModel; -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.TestMethodProvider; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.TestMethodProviders; - -/** - * Because many people are nearly religious about how test methods - * should be annotated or structured {@link RandomizedRunner} can use - * a custom method selector for designating test methods. - * - *

This class contains a method selector that returns all methods - * that end with a substring Test. - */ -public class Test015CustomMethodProviders { - - public static class MethodEndsWithTest implements TestMethodProvider { - @Override - public Collection getTestMethods(Class clz, ClassModel suiteClassModel) { - /* - * We pick all methods with a "Test" suffix. We also skip methods belonging to - * RandomizedTest (there is a private method ending in Test there and this wouldn't - * validate). Additional validation is performed in the runner (public, non-static, - * no-args methods only allowed). - */ - List result = new ArrayList(); - for (Method m : suiteClassModel.getMethods().keySet()) { - if (m.getName().endsWith("Test") && !m.getDeclaringClass().equals(RandomizedTest.class)) { - result.add(m); - } - } - return result; - } - } - - @TestMethodProviders({ - MethodEndsWithTest.class - }) - public static class TestClass extends RandomizedTest { - public void myFirstTest() { - System.out.println("First test."); - } - - @Repeat(iterations = 5) - public void mySecondTest() { - System.out.println("Second test."); - } - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test016CustomTestCaseOrdering.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test016CustomTestCaseOrdering.java deleted file mode 100644 index 8eeef6ed..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test016CustomTestCaseOrdering.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import java.util.Arrays; -import java.util.Comparator; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.TestMethodAndParams; -import com.carrotsearch.randomizedtesting.annotations.Name; -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; -import com.carrotsearch.randomizedtesting.annotations.TestCaseOrdering; - -/** - * Typically you will not want to order test cases and leave them to be - * randomly shuffled by the runner (this prevents any accidental test order - * dependencies). Sometimes, however, it is useful to have tests run in an - * predefined order. - * - * This example demonstrates how to order tests using a custom callback. The - * example uses {@link ParametersFactory} to demonstrate how this can be useful - * with custom arguments. - */ -@TestCaseOrdering(Test016CustomTestCaseOrdering.CustomOrder.class) -public class Test016CustomTestCaseOrdering extends RandomizedTest { - public static class CustomOrder implements Comparator { - public int compare(TestMethodAndParams o1, TestMethodAndParams o2) { - // Order by test method name first, - int v = o1.getTestMethod().getName().compareTo( - o2.getTestMethod().getName()); - // Secondary order: by constructor argument. - if (v == 0) { - v = ((String) o1.getInstanceArguments().get(0)).compareTo( - ((String) o2.getInstanceArguments().get(0))); - } - return v; - } - } - - public String p; - - public Test016CustomTestCaseOrdering(@Name("p") String p) { - this.p = p; - } - - @Test - public void testA() { - } - - @Test - public void testB() { - } - - @ParametersFactory - public static Iterable factory1() { - return Arrays.asList( - $("1"), - $("2"), - $("3")); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test017TestCaseNamingExtreme.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test017TestCaseNamingExtreme.java deleted file mode 100644 index 89f86e68..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test017TestCaseNamingExtreme.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import java.util.Arrays; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Name; -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.Seed; -import com.carrotsearch.randomizedtesting.annotations.Seeds; -import com.carrotsearch.randomizedtesting.annotations.TestCaseOrdering; - -/** - * When the test suite is using({@link Repeat}, {@link Seeds} - * and {@link ParametersFactory}), it may happen that a single method - * results in many actual tests. These tests have to be uniquely described - * for JUnit (otherwise there is no way to tell which test case completed, - * for example). The framework always attempts to add a unique suffix - * (repetition number) to test method's description. An extreme - * example of this is shown in this class, which - * repeats a single test with multiple seeds, repetitions and - * two parameter factories which return the same argument multiple times. - */ -@TestCaseOrdering(TestCaseOrdering.AlphabeticOrder.class) -public class Test017TestCaseNamingExtreme extends RandomizedTest { - public String p; - - public Test017TestCaseNamingExtreme(@Name("param") String p) { - this.p = p; - } - - @Test - @Repeat(iterations = 3, useConstantSeed = true) - @Seeds({ - @Seed("00000001"), - @Seed("00000002"), - @Seed("00000003") - }) - public void testMethod() {} - - @ParametersFactory - public static Iterable factory1() { - return Arrays.asList( - $("p1"), - $("p1"), - $("p1")); - } - - @ParametersFactory - public static Iterable factory2() { - return Arrays.asList( - $("p1"), - $("p1"), - $("p1")); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test018TestCaseInstanceProviders.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test018TestCaseInstanceProviders.java deleted file mode 100644 index dbf37153..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/Test018TestCaseInstanceProviders.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import org.junit.Before; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.TestCaseInstanceProvider; -import com.carrotsearch.randomizedtesting.annotations.TestCaseInstanceProvider.Type; -import com.carrotsearch.randomizedtesting.annotations.TestCaseOrdering; - -/** - * By default JUnit (and {@link RandomizedRunner}) creates a new class instance - * for every test case it executes. This behavior makes sense to keep inter-test - * dependencies to a minimum, but sometimes it's just plain inconvenient and - * difficult to emulate (with static rules or static fields). - * - * The {@link TestCaseInstanceProvider} permits changing the default behavior so - * that each test method is executed on the same instance of the test - * suite class. - * - * The order of test case execution is still shuffled (unless overridden with - * {@link TestCaseOrdering} so ideally the instance variables should be - * stateless. - * - * Note that certain caveats apply, see the documentation of - * {@link TestCaseInstanceProvider} for details. - */ -@TestCaseInstanceProvider(Type.INSTANCE_PER_CONSTRUCTOR_ARGS) -public class Test018TestCaseInstanceProviders extends RandomizedTest { - /** - * For the sake of the example only, we'll increment the instance's counter by - * one for each test, printing the output to the console. - */ - public int counter; - - /** - * An instance context requiring some "costly" initialization. Note we could - * just add the initialization here, but {@link Before} is nicer because it's - * executed in the context of parent JUnit rules, etc. - */ - public volatile Object costly; - - @Before - public void costlySetup() throws InterruptedException { - // Initialize once. - if (costly == null) { - Thread.sleep(1000); - costly = new Object(); - } - } - - @Test - @Repeat(iterations = 3) - public void addOne() { - System.out.println("counter=" + (++counter) + ", costly=" + costly); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test001AllStatuses.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test001AllStatuses.java deleted file mode 100644 index 26c24851..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test001AllStatuses.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner.reports; - -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Ignore; -import org.junit.Test; - -public class Test001AllStatuses { - @Test - public void passed() {} - - @Test - @Ignore - public void ignored() {} - - @Test - public void ignored_assumption() { - Assume.assumeTrue(false); - } - - @Test - public void failure() { - Assert.fail(); - } - - @Test - public void error() { - throw new RuntimeException(); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test002SuiteFailure.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test002SuiteFailure.java deleted file mode 100644 index 86627ec1..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test002SuiteFailure.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner.reports; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -/** - * Suite-level failures. - */ -public class Test002SuiteFailure { - @BeforeClass - public static void beforeClass() { - throw new RuntimeException("beforeClass"); - } - - @Test - public void testCase() {} - - @AfterClass - public static void afterClass() { - throw new RuntimeException("afterClass"); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test003MultipleFailures.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test003MultipleFailures.java deleted file mode 100644 index 30ecbf29..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test003MultipleFailures.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner.reports; - -import java.util.Arrays; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.MultipleFailureException; -import org.junit.runners.model.Statement; - -/** - * Multiple failures from a single test case (followed by a suite-failure). - */ -public class Test003MultipleFailures { - @Rule - public TestRule rule = new TestRule() { - @Override - public Statement apply(final Statement base, Description description) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - try { - base.evaluate(); - } catch (Throwable t) { - throw new MultipleFailureException(Arrays.asList( - t, - new Exception("a"), - new Exception("b"))); - } - } - }; - } - }; - - @Test - public void testCase() { - throw new RuntimeException("testCase"); - } - - @After - public void after() { - throw new RuntimeException("after"); - } - - @AfterClass - public static void afterClass() { - throw new RuntimeException("afterClass"); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test004SuiteOfNested.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test004SuiteOfNested.java deleted file mode 100644 index 38abfccb..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test004SuiteOfNested.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner.reports; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -/** - * A suite of nested test classes. - */ -@RunWith(Suite.class) -@SuiteClasses({ - Test004SuiteOfNested.Subclass1.class, - Test004SuiteOfNested.Subclass2.class, - Test004SuiteOfNested.Subclass3.class -}) -public class Test004SuiteOfNested { - public static class Subclass1 extends Test001AllStatuses { - } - - public static class Subclass2 extends Subclass1 { - } - - public static class Subclass3 extends Subclass1 { - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test005WithOutput.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test005WithOutput.java deleted file mode 100644 index 6d0b9f08..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test005WithOutput.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner.reports; - -import org.junit.Test; - - -/** - * A suite of nested test classes. - */ -public class Test005WithOutput { - @Test - public void stdout() { - System.out.print("stdout-noeol"); - } - - @Test - public void stdout_eol() { - System.out.print("stdout-witheol\n"); - } - - @Test - public void stderr() { - System.err.print("stderr-noeol"); - } - - @Test - public void stderr_eol() { - System.err.print("stderr-witheol\n"); - } - - @Test - public void stderr_stdout_interwoven() { - System.out.print("stdout-begin-"); - System.out.flush(); - System.err.print("stderr-begin-"); - System.err.flush(); - System.out.print("stdout-end"); - System.out.flush(); - System.err.print("stderr-end"); - System.err.flush(); - } - - @Test - public void longline() { - for (int i = 0; i < 1000; i++) { - System.out.print((i % 10) + '0'); - } - System.out.println("... and done."); - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test006BeforeClassFailure.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test006BeforeClassFailure.java deleted file mode 100644 index 2b5f376f..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test006BeforeClassFailure.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner.reports; - -import org.junit.Assert; - -import org.junit.BeforeClass; -import org.junit.Test; - -/** */ -public class Test006BeforeClassFailure { - @BeforeClass - public static void failOnMe() { - Assert.assertTrue(false); - } - - @Test - public void noop() { - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test006BeforeClassFailureRR.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test006BeforeClassFailureRR.java deleted file mode 100644 index 7deaa3eb..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test006BeforeClassFailureRR.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner.reports; - -import org.junit.Assert; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; - -/** */ -@RunWith(RandomizedRunner.class) -public class Test006BeforeClassFailureRR { - @BeforeClass - public static void failOnMe() { - Assert.assertTrue(false); - } - - @Test - public void noop() { - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test007BeforeClassError.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test007BeforeClassError.java deleted file mode 100644 index 03832d81..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test007BeforeClassError.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner.reports; - -import org.junit.BeforeClass; -import org.junit.Test; - -/** */ -public class Test007BeforeClassError { - @BeforeClass - public static void errorOnMe() { - throw new RuntimeException(); - } - - @Test - public void noop() { - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test007BeforeClassErrorRR.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test007BeforeClassErrorRR.java deleted file mode 100644 index f960b992..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test007BeforeClassErrorRR.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner.reports; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; - -/** */ -@RunWith(RandomizedRunner.class) -public class Test007BeforeClassErrorRR { - @BeforeClass - public static void errorOnMe() { - throw new RuntimeException(); - } - - @Test - public void noop() { - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test008BeforeClassAssumption.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test008BeforeClassAssumption.java deleted file mode 100644 index 89603f90..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test008BeforeClassAssumption.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner.reports; - -import org.junit.*; - -/** */ -public class Test008BeforeClassAssumption { - @BeforeClass - public static void assumeMe() { - Assume.assumeTrue(false); - } - - @Test - public void noop() { - } -} diff --git a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test008BeforeClassAssumptionRR.java b/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test008BeforeClassAssumptionRR.java deleted file mode 100644 index ad4fdd4d..00000000 --- a/examples/maven/src/main/java/com/carrotsearch/examples/randomizedrunner/reports/Test008BeforeClassAssumptionRR.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner.reports; - -import org.junit.*; -import org.junit.runner.RunWith; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; - -/** */ -@RunWith(RandomizedRunner.class) -public class Test008BeforeClassAssumptionRR { - @BeforeClass - public static void assumeMe() { - Assume.assumeTrue(false); - } - - @Test - public void noop() { - } -} diff --git a/examples/security-manager/pom.xml b/examples/security-manager/pom.xml deleted file mode 100644 index 06c7a461..00000000 --- a/examples/security-manager/pom.xml +++ /dev/null @@ -1,165 +0,0 @@ - - 4.0.0 - - - com.carrotsearch.randomizedtesting - randomizedtesting-parent - 2.7.9-SNAPSHOT - ../../pom.xml - - - randomizedtesting-security-manager-example - RandomizedTesting Security Manager Example - - - Simple use-case running with security manager - - - - true - - - - - com.carrotsearch.randomizedtesting - randomizedtesting-runner - ${project.version} - compile - - - - com.carrotsearch.randomizedtesting - junit4-ant - ${project.version} - test - - - - junit - junit - compile - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - default-test - none - - - - - - - org.apache.maven.plugins - maven-antrun-plugin - - - - run - - pre-integration-test - - true - - - - - - - - - - - - org.apache.maven.plugins - maven-enforcer-plugin - - - enforce-urls-were-set - - enforce - - pre-integration-test - - - - junit.jar.url - junit4.jar.url - randomizedtesting.jar.url - - - - - - - - - - com.carrotsearch.randomizedtesting - junit4-maven-plugin - ${project.version} - - - junit4-tests - - junit4 - - - integration-test - - false - true - - - - - - - - - - - - - - - - - - - - - -Djava.security.manager - -Djava.security.policy==${project.basedir}/security.policy - -Djava.security.debug=all - -Djunit.jar.url=${junit.jar.url} - -Djunit4.jar.url=${junit4.jar.url} - -Drandomizedtesting.jar.url=${randomizedtesting.jar.url} - - - - - - - - diff --git a/examples/security-manager/security.policy b/examples/security-manager/security.policy deleted file mode 100644 index 8ff49eaa..00000000 --- a/examples/security-manager/security.policy +++ /dev/null @@ -1,46 +0,0 @@ -// policy file for tests - -//// These permissions apply to the JDK itself -//// (actually only needed for "extensions") - -grant codeBase "file:${{java.ext.dirs}}/*" { - permission java.security.AllPermission; -}; - -//// permission for the junit4 jar -grant codeBase "${junit4.jar.url}" { - // needed for io stream handling - permission java.lang.RuntimePermission "setIO"; - // workaround for junit access control context bug in processing - // class test request. - permission java.lang.RuntimePermission "accessDeclaredMembers"; -}; - -//// permissions for the randomized runner jar -grant codeBase "${randomizedtesting.jar.url}" { - // optionally needed for access to private test methods (e.g. beforeClass) - permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; - // needed to handle uncaught exceptions from other threads - permission java.lang.RuntimePermission "setDefaultUncaughtExceptionHandler"; - // needed for getTopThreads - permission java.lang.RuntimePermission "modifyThreadGroup"; - // needed for TestClass creation - permission java.lang.RuntimePermission "accessDeclaredMembers"; - // needed for ThreadLeakControl - permission java.lang.RuntimePermission "getStackTrace"; -}; - -//// permissions for the junit jar -grant codeBase "${junit.jar.url}" { - // needed for TestClass creation - permission java.lang.RuntimePermission "accessDeclaredMembers"; -}; - -//// Test class permission: we want this to be minimal! -grant { - permission java.util.PropertyPermission "*", "read"; - - //// Java7 and up. - //// permission java.io.FilePermission "<>", "read,readlink,write,delete,execute"; - permission java.io.FilePermission "<>", "read,write,delete,execute"; -}; diff --git a/examples/security-manager/src/test/java/com/carrotsearch/examples/randomizedrunner/DelegatingRunner.java b/examples/security-manager/src/test/java/com/carrotsearch/examples/randomizedrunner/DelegatingRunner.java deleted file mode 100644 index 95a14009..00000000 --- a/examples/security-manager/src/test/java/com/carrotsearch/examples/randomizedrunner/DelegatingRunner.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import org.junit.runner.Description; -import org.junit.runner.Runner; -import org.junit.runner.manipulation.Filter; -import org.junit.runner.manipulation.Filterable; -import org.junit.runner.manipulation.NoTestsRemainException; -import org.junit.runner.notification.RunNotifier; -import org.junit.runners.model.InitializationError; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; - -/** Pollutes the stack with non-RR code, so we know the AccessController - blocks are correct. */ -public class DelegatingRunner extends Runner implements Filterable { - private final RandomizedRunner delegate; - - public DelegatingRunner(Class testClass) throws InitializationError { - delegate = new RandomizedRunner(testClass); - } - - @Override - public int testCount() { - return delegate.testCount(); - } - - @Override - public void filter(Filter filter) throws NoTestsRemainException { - delegate.filter(filter); - } - - @Override - public Description getDescription() { - return delegate.getDescription(); - } - - @Override - public void run(RunNotifier notifier) { - delegate.run(notifier); - } -} diff --git a/examples/security-manager/src/test/java/com/carrotsearch/examples/randomizedrunner/TestExample.java b/examples/security-manager/src/test/java/com/carrotsearch/examples/randomizedrunner/TestExample.java deleted file mode 100644 index 435c254a..00000000 --- a/examples/security-manager/src/test/java/com/carrotsearch/examples/randomizedrunner/TestExample.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.carrotsearch.randomizedtesting.JUnit4MethodProvider; -import com.carrotsearch.randomizedtesting.MixWithSuiteName; -import com.carrotsearch.randomizedtesting.annotations.SeedDecorators; -import com.carrotsearch.randomizedtesting.annotations.TestMethodProviders; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction.Action; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakGroup.Group; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakGroup; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies.Consequence; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies; -import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite; - -@RunWith(DelegatingRunner.class) -@TestMethodProviders({ - JUnit4MethodProvider.class -}) -@SeedDecorators({MixWithSuiteName.class}) // See LUCENE-3995 for rationale. -@ThreadLeakScope(Scope.SUITE) -@ThreadLeakGroup(Group.MAIN) -@ThreadLeakAction({Action.WARN, Action.INTERRUPT}) -@ThreadLeakLingering(linger = 20000) // Wait long for leaked threads to complete before failure. zk needs this. -@ThreadLeakZombies(Consequence.IGNORE_REMAINING_TESTS) -@TimeoutSuite(millis = 200000000) -public class TestExample extends Assert { - - @BeforeClass - private static void beforeClassPrivate() { - System.out.println("beforeClassPrivate"); - } - - @Test - public void test() { - System.out.println("test"); - } - - @Test - public void noPermissions() { - System.err.println("checking permission system."); - try { - System.setProperty("foo", "bar"); - fail(); - } catch (SecurityException e) { - // Expected! - } - } -} diff --git a/junit4-ant/lib/junit-4.9.jar b/junit4-ant/lib/junit-4.9.jar deleted file mode 100644 index 1420815611588dceb49a438f987be5c1cbe6a320..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 248994 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

0hs&;+8i5RbpPMZmo`D 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 z zC4gSteEzdpcz5HtYfIh5?&a);hJ&1Z{o1(_81i5Iv2y(efwpOYrvn^0D^1w*7x0A% zJ6u&s^&);35maTvGQ7%%f5GF3DRHNdCanQ{$1?o&-haX42rRpTMkZl_gy8!!{MhGz z!3&}LW8QALJZ#5806PGG?oQ6musG_Y1A81-i1P;dmgeZOO=o5$ zIV;DuKBo3?Td09!@USh^1pJ#EK=%`czB168_se$dF8Ph%Kr9GgDGJbSCv5bZ>+{f! ze690WXC2TSz+aGoUGCR%_1tz!+dG-t{q@r0OMwoh3D}C#2h%LbG{9^X;WAIeMMu~C zKqa$^0%*<#c0lIkw_rYUsh7L$oL3s1)n6#2O$V$#c#u}$qC#UK_R+F0{x=+RC7(X5 zJ1qx+Dj!;jG@`~Ls8^yotxQBzoI;J1KIXWFu|rI zf*ar_$gzewGY%vi^nh3ec{r{PjyOa85Nt{!c)X11!MY+7N3W)uc|3gpm~(T62veV7 zTak&QD+`R(%2NR+8;3xLEc=7)D>8BPUq^I0i7H`bl?sw>c7&cvTq`lrYv@6a5*M6J zBTxWMk(s=f2pVzzqhNFYIp*`yE zP}#qrUqYt6B9dsR`L##+g)fuOt*D`s8Fb$Kl!t;JgDOHU1$M~%1$q8_13J31o;Zpc z(2{^grjSnZe}#6pcCx_L1PH^~ZYzN`wu5nzde3I9YOl`61lszux$> z^p@Q}_)S{4@&C4tyz~mpKQh|jgWbzrZ{A<#gAU#eqf75*`vZ=LVF-TklAGF=PGT>; z4ebv)2o`v7p;uT1S$aR%ALw%v+|b321KmNEUfS>n8fuFMMaxWxATU4{vWjKZVN=+? KWCx9#;Qs+iBOPr3 diff --git a/junit4-ant/lib/proguard.jar b/junit4-ant/lib/proguard.jar deleted file mode 100644 index ceedb3091058ca62dea312eca76dec82b9250381..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 940487 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 z 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

al!F^N7H@ z(>Z((yhC28ZaOzA>bs0mMSGT9-zPi{B&^l_84Qaoov^{JklZ;r7D+nM6nUElX3dMVeU(yOt?K9ZiDP+#ZB_FP z4=)hT=bc(`7zv!Uc0n(R(N6llK{5k5X95+ohM4&IMc&2{vxkg1EF7BRz(lyJF?I-j)OJ33n;P)bgbmCvFbFh2@y&3-^{LiWPPe*CWr6|GsHAxVG|9`Vm|5sShzh02ZDf%|b zs`$g*?w#777tJ<3*ml9a1~%s_G#He20V4)0w(kV+IA!hD*F%Ff!8POs;j=(>UlnF% z=9?Y3Hso|xKsW^eP47X~crTJnz%uN%S8&_;`qc8YtpExC>Sfb;>e|`w*je8F>3aI= z+e#o1O9X^%FMtRa@s&ABq`;FRfC~T`6&-PvW`XGKC@LBgaXTz}&|)Fy!OYM{*~wL$ z|Jc*}QHp3eL%|Ln%5wUWl|Ch#R^D-FD1cZwoxZ9`%bCP-e9Ue`*q$~yaWrYel7SqL z!)q!Q%bdi1oJIT-_snhGlJ~cI|58n8%vH`z9+GK7N{Fhl+ZsVYYfs4^JtvLX<@rH|>x~b?by_rO9C&E@`S3zj0|~xv9dz@x9ji<*Njz zjdpoa2m;3VVTa3^3h#c5wWcR_>^P1}PmQxTuGX|#_Q92y6L^*+Dks?^lMZT`)M)fe zYkt4ll}`w*Z57v&@3~F6om`AfHA|fM2_o&q7;QUlAI5LhtmCW70OjkcL_AG$H@6lx zC4y9MxG3{KtKjEkqBc~sRo6kDs|z!?xmj$rglLdU`KyuhkU3)QfvhJtMsq!yS*$a` zc3{)tH-#R0BI{#B@yc#sytgfZSWKop=nas})rRw94I2bF98GnFv!`%s zK@Sfu;SJ>pYI=~-FDvy(gH+M{wXe^~FInuA;G<@fwBZwjw74X?#)qd+`xwGglz0=v zgmLYid%LM>03EI4zmdkT-)w|*4S#e$N?d2(Ah?9-Y2?20)rPI<#rhn>_($-t%kgFH zPDuJ%p?ICok|^`~*u1R@1VX|yz1a;tDvbE94CdngUE#_?N&Vp%Q_FIBaAzpkd{aJ@ z-ibl5Q5a$y@!`7=Pl!!r9^1&!yZ-BmBkvUt@FC^iS{&4_zecY1&g9qoAF}>oO zR%0YD-F*xK7r4gM=PQ| z>oM=dBSYjXVeB6sZu_b{kwE4WY|;e9lbf`Kz|^XuP72qslzB`S3ks{MV>ImL2*8H6 z*??@xd)z3d#Q=TI$uOIJAd@sXpplBS0G6vFfEU9dlg3K0dnEz@PHtAV5vCdmjS&T% zjE$lM04E>~8jpTXxKx+HON zqK7@JFc_9+Eb7pTBFJ zN*z-wPCLaT9i0havQOZQ0+%9#0uh^rWkwjGg_0+qBszbVu>6MZsN&j7AhsazKG>U> zv|QwnkTS>444;`x4_hXi)sBljCdO;bXr#%EBLKLc2~K2y?pG{a9v{6~mR>+v5Q z(V_hLTems#grx*t8`n~=X^pSP1c(z8OMVN-Ar&65P! zzv0nJPDGJ0QXU)k_tuAt;Kj~lWZP6!?eW#6bgjqt$1{GlTz9^PE1%PoMk^g9`;E#Q zcLNe=+kNSn3^s+4G`>OPOdF!Qu3YaXjK@@7NUOa77F;hQ2cU%SvoNr)aXhlS)I{%Z#)6+(JTlSH6#q_%lwsNX3&U z;6Y7Fr{y}3#(z0368wL*-&Yf%9hQPW(n08te{;GKZI6WlpT1#=-hBVJB{XQ@(m{g$ zl`|~%A6bO|-MswQ68gemnL3%;8JqrV`=SHmp|Xe}V4gOSDWmrt92DLVCK9+}7%`#8sYyYt28H8V68^hY=Zel3c4u`pbW+YiE= zp+RhhA*cBB9!D4HK@F%QLq8e}2*e7VlO7Vf6o(G5xjJAZ%)1@QGR+}u;1`xSSH{S+)Qc61zGAXdjZzGRj*R;bd{=hhd`ntR1nbM7Ox9tZQ8O5=1EPqk z6j!RJ%59=2s+x253u09-M7fI0ex=gUBSDvLT11m*PJ~hyNx!SkubAis=E8Z$c(Cc7 zK}4M(X@VB`R9**&oOG!{HU>2w2aFoG9ZipBu;raK6`fE9hO_yZXarOmnUeU(2Sghq zq>MCow4dJCBmF-JA=i3JIBzZ?`9keG5p4kaG#K+OH@vkFoFz)k(UAdQKe3$*Xzdbi zbfBsRCQF!#@u%L4D*6lSY9IiyCMaYR0RL~hk!laFs`f=Nu z?3ptum4}~yO(8#nrX^YpT4SaNVdzqW6ICb2&6=cLpcO5#MrC80Un;NzYa?kfsUhBU z6m4Z{MPH#9Wq-#P@f#$crqv#X1{zst_^hyIe`;lC?SSU7&F4Ha6$nbW?Nv|vlH`28 zux!`Oi0$+u9Qp2NpL_xZED+5`SMTN{X*?1p$yW`6j)5dULG;i9_PXq`E<5B}E)=W5 zu)n~#>cs*T6@e_L^s_yriJXxzQ9xac#bFp4(KZ@8~?0?x$B4l`pyhB{*8h>Y*ER^z>5TrOoXZ`@KN8^hpZ9kUIu- z7AG~W3Xlr^Tw6p++_S;Brp963h(I)X6{D9en9UkHTsIdL`Spv}{+qRJauS^hzoVpC zsvWFMoUytKUIRh*pt|^S0KUKmTHR)HEonx`Yvw4(#hs0J9(*yL0EqAE7O4%uMSjZm z@JCyg?UAEOzLXX1u6o;P{LUU93ec^JUYDZ}-@}GY5AjZHWo|GB^hr90n|DrQ6inlR zx#<3e^5)CPVE;*>Ce;QnRxS&rWFAKzzfSB0czAgyRv!@=T{5tB{q5^?>M>|Ga~3pY zYQ-i=L@om0qQ6)m!K!Y<(E5|+?YQAZS>Q-;X z^)5A|RRM;ZgVBHL!n92C6RKHUMP*i5`$YQzgNIFX%;+A_WU3l{&qAPlojiOH#>~L0 z@|)@?r&>-K0HAP<2QdK)Wiy@phR$n0L2fm5o0`v)#`fDxd^>MdWU<1+1NtiKTIg!_ zHa(WbG3%QV@3NtNWw*FFjy%$4=Z25Q20U(z+YHgd|~?Dj(|W&Fdc%p z>`mo+2YeN9&>H$u3H$*^#r+-(`8vupGCjL@IiF#MSl0DsdCU7|4vx7boK;?R(wL!a zREeZTZ4pBI+YLnRTRn>f%y<0y{>*@%dlqH(WkSK>f|czj3L%u(nzWYddCcC4KCemH z-_%VBy-k9d7GBi(_ph6_5M9L?a+*m#8{_x~xqnA@ISdG<>vh9<+RtYBi!P9GYYraK z&n!OF{_IAyMZe3>f;ebsL!sU0ZQ26jCgG6_gfj8?MwoQ#*P+`7Wzqsgl(Y+NMtqRw zpz$Ln7zW&wFD%rg1&^r6KAudRk)^p;9F;JoE_;+8h&1j2%zfAC)0gm284|xygds9+ zj+K6v#_IbM1^Oz_@>X0|DdDxKFgQjnz6Q z&GHvTAAoI0h!d}?T<}Qg1g77cO8(ve{3Z3A5#?`~w~X_EfU|8f?{B)$%}le|G015@ z{)~9{%)9J^WhlH1g$Xt4o%Apv9v^kR52bTR#NrnwdSd)8I^@4s%HlWl`*Y6-+Ao5M ziLhti)&LlL>&(yLUI13i}Hq z>GCO~qC7Pr6lY5?@up$T!Ne%0m*cgrL5%fHhFz3jN~naYYSai@j(9PGZORKISzFe) zwEc&UDWZCkq6Boq#mOV8c(LH~@e^3XsPu^v|90Z$5;^;W?*8)K7zz9Ayc{TNqg0m{ zQI$(BIr5HYdy5^0s++;AkLb&dpa^Kw3g2JE7F82wsCUM45%)FOEE&@il2fx5a?v)U zg9pV|_W6|QB%&=D!HQ6s%Fut&>OfK)*kmuSdeMbH%jlVPr`F{kDfH^o)t|FHuH?N| znm?0VSj;@X=XT6JeVXdW`3 zBt*ch-oIMAA15|nwknzlP!(q19pzwO(IQ$na&CB`?j;tle<}aj5IYbp^QKzWE*vlU zJJ$$Vmq@e0yDeARtnneJ!hmS8Oz6XMbBh@x`&8|%dG=TD96YtEJF+)*;$hY zr>D`iDjAM68Labnb6&l{-vSF{0%KMS$)ukjN%E`s8Kqa$kJIb~;2i4Gk$Z)M_Clpg zrLR{8+Z5`xOGFCyj+p4p>fzlFn>P4ats$m2z3uafRF<<3NKqqMAz$EqH7SF;FQv0$+?p%7Lkr`R48kT0CHs?hmj=X( zU8gY6Px1>h)n4$u8$szD77j6}kYH}CDp<}MZ-i556-7cn-5=X4wHTdC`Pnd6Bre_^ znab`eSn=zu}~ib?ShDy3umsp3JR}<7!0=;MwSV-BMxp-L3EQV zoX3&J)fmI|0Q783Y$1GH(#Fk%SusmaOBar}%ol_Ek8fK-nJ=*p)H0l|`iWi5OyhoK zc5URvy2L47nHXce4nq6snAElZH_nXkIC4?!8APzeFs703LGvoWUSZ&c1_}d(a4K^0 zC0QTF!GJ1R-y&HbBI+)W)4i9IBV~APr09wW$;N^R$|JI{ILSqDCOe8&IifMViGK(* zN=SqRm4g;iZ*3S_`U3I}CTK@;o}aLxTj+O<3XWxJ_=UdcUw+VU;K5xy5R#=gq0r6z8^sX(EYn{f$}j^l;X#UA`|v#K9J`=EG`1S z`(xP!8cqZW)v%c@(7qwTfpMQnZ+=U_b`N{HZvu5!f&=FEO{*};kl(0y{Z8q?)f6A3 z`g4v==cbhl)N=E1(Trd%CXl0TP$X;WPh%OS=CMl1+$edAnrec1#6^t z{s0~p{%EcGJ+sOnIW0Dsk0)m`5!c5s%q%qDuaNSMdRz z@rn-9-+T7FD*n+c{-K-m)o@*~XG$MDwod`S4dQ(hJrxpJB-y707AEXUz-=`~@TMUw z(@0bhPixD2CQ)R=Hl3$Ka8W8?ZYU%hGnR^xJ+j99CeP7Kn5l{&zhfnHtYyAt(cc-} zPm>-YepKXp^n+H6Xz+*$(ub}p*w8aXhxd|!TIg4$Oyo|t4@hy^+Iz3-v`4X){E(XvnRMcua1{ChM#SKpIG)=a zb`~R1tnqT1G{{-pv?R`JZ&)7|#9U1#&bD-Re>+jR9Q!xP?REltZLw451lp1jGC&tv zkg|~=wqWod2gZ=--Llrn$lU-EE0|m|d){pg)iU*|Vv`xO^Em;fRP$}fq`PoIs1)qI zGe%Qa0yX(o^YzCCK05j@8Ep0WhEeY65-(bisb}0!6B+cXFn(?5hZaC=9@(@W{H_7b zV$VB0oB-O+oxKnS8)K7_aCE7^`0FY|}_ zT+r)EyIOBi!H2R}nl|96fi)Ja3$=5tnHdYt)+plV+W#(Z=LFLiCvsPJXduZt~VFCv)jh}Qs%C}`J43hDUm6LvRZNJ%`YHWOEJ5itSxlq5PA zR~RX~ef&&eu$(O~TMg1R^!MCE5rXPmY5z_o6P*l#bP)TH%mFE*1sYOxW) zD~)Z;_g5sK4;2XIwFYz8pl>Mt3p__BQlUn?Od|+=BQjGw&WFKgHe_Ek6tgfZ3WdE> zma}s*aZ#UG_K9}hH{?`M!8MPxvpIF3tW%gfR)d6oJABZ!r3KA|?~zMBioqo5pb3+G zmP$U#xCs5RA8Fp#mvs?XmxpJ&FJbdfWucq6)o9eOdF4#P-orH2VxMWB+86Oy2%gRh zHm+|XrTDyZgQDJ>N*j32k}VHehP=|;zk&78jfC<@?-`l zAL6%>{}C|b1~E4D&#nF-t9Wd44t6)x&L@7PKRh{5h`K{4kPbvQH84wu;Sb&dO3B5N zF^X7$Ry6`cLDgqL^p2j{i_>Fl#EGbS4ITB(M~6KiZOoA`SI~*7AhxtMlwUl{?agE! z6M}hsE8?c|=vpY0}PdUGRwL#bSXWu)c)3V0Hx8NYrYBjp6yL?vd7>#tu_`9HQ0hU_lWq?DLdaCgum|hl} zv4Lk_PL`{>0V$Ar(&R>kL%Xgko+Nu*6us}JBVT* zLcbRg6hALj^ieOe_ziZ&>ILgpCrOmo^nm|R>9B&Z?o`a|tX+OV2kb=#@~iO!nvw=_ zm?VDxxpo*e`otm%L2KI}??X9qH*8_inhMw;lSG*MtfxTKX!JEbrsh=Arz73>hqZ0# z59fD0n~P&1sA;$suiqPeX$>#fxK(K5=P79ozXaVn_}_-|10qu}SPNBjQOPLKf0qze zr{WnksR?(QGb1&t4Sq30v~5fHaFqu^?JB{{IdH^iPzfuiTX_`!X9zQGJViqnAs85@ z78n@k|1)dtXlDMuBJ#u>?VTKd{7)t7v@X1n+VZmCNzZuq_>l;9dWan*cnHfnsqhdK zDx3%mByAuq>A)`}7QPH=8Vs)J7EzqER-Lp;TCC#275&5j<)Ip#O81tPnq>`Jd)t=i znvKxU?AM*{ZtXBAB))xbq!N`H z{o&bL&M66495iM=_0#=xYAo)1x9BL{=T7j3^y&YP^-+0J$dpkm+ zzqvTm;qbSwjSr`_gV=Bk_h$^%Z`rWEc?{qp@!lZx7>p0E5`x@%{08BvJh3QxHX?V2 zY}?y4hR?H=0$1;++d%8cdRyrT_&Y}Y4^;o5;rQoAnhKEW z8{Vpc>%r_T70m~Pq5A;?h#se|Y{P3F z2!TE*u!P(P)IpI^pRVYSilAe|x1(M9kMF~#m0;@m^da<^>T7BVg$Vqj6Ww7Qle5Bo zDR6^-#roqSxN)r?VfcIzGPp^R3^`8pW()sBuW)d2aC2}eD*}Y*B$WiBvrag?kLgBF zNkntGQQ_bch%oin(*`*F^Maf$Bhjb)?j1P%buIG({Z;D+gZW^Q&! zufaIpaKi0Pp?S)t7FizAy){iWf=hpGAE3F#xyX5R8M!HZm1QQo&mkKXKRP^;m8 zQ5O!yMav08M2mR)NE5C%7p`n0K{{FFJE@59gpqT{iv{Fnu1>Z|{#lM*KdaJ?;R}Fx zkcL%4=m?se!~dvXD7d@^{YJ3GifzEirz0UF6iOu$PD0)jWro4jfVbO`VZLEPr}0zd z|I!rfO5y9$FmiWr>xQaFl%ly&hmAQl$O+y#3X)*=#vhKw)%8hiYyobkKC+s%dgFwu z1A-MRQ*J%TA4b22jUxOizPsPT>iX)Ux-e-F+p2SHZSGtl>L6npt5ne7u|=;`(^r^k zP$c2;ie~Q0aG$w8eNQQrm}^`An{LgwBzeu}-cSv-M-&6Bm_`ZFyB}4Oy5f2duBIoV zA9N*ZKl6W|Kb=+27-7k4sUVqtygtVZnZ=2Fz+%9-P@ay1w~-4Aqt?7&Z4R+1aQLWcigs6~n?qdv@ZjV;(EXlwot zR=(0wE#GjjESFR}#6+J8{y8=jbTzBT@LrS@H4Z?6>U|uFq==C%%&obE2R`QN(aQ+a zE~{bU%Ef5s#lh1&jYQ!mMH#&BuFm}Wq5pGC3gSUsVmD$W|6@fufDb%%D2_w@5dYha z!<`0ncR#Xvu5e#lKS4Ui&fIupdVE%D~y zs5~k9Oc%}}>I+TZ6@$F?GN+71v+ds$7tb-JRyPtl5KB*DL=EYdKKMbH(R_(SM#X1- zLbEs#o<;lt)PBSdcy^8g&uZrVWsV;FCa3^T$fm^T%*R5dwYCKul$_>AbV#MPv{tPt zvF0?bpk|Cz@AO?fINS#Z-ZNLDprpI9+Ur5ScX4=S9Xw>b=~UwG&QC=y4Y4I*pkzfv zj6D39;%Bm1kyrm6X&&m!Z}3kp!zzUrewrK=bm70YhL+@yWDeXI@ZVLtN7_}3K1HIq zk01*!hPL!!e_mRma1kd78V8D(CxywtiIli~Biv`N!!)cQ%S#p=I0v}JhyhWDD%myuWzc^_Hi`*_OCjT=Gq!ZD{C>hXWH9@P@YOf zMu1pwnowFXkua+)9HOQH5+t7YauVumzw_uWiSrpHd)<^MUM5%|-xJpQIHu8r(Q7Z| z$F*Z9L;H*z&ue+yX2pv9uRuYN(M^i($l0JZ)GN<$zK<^0IsRT$U+Api`_!8aW9zW+ zFI#il95H-lcG?pt#kmYiDjqCb=dmFvI`|NzwF>(kCKoU?<_kqAE-`Ndeo9uk&1H#k zg}*4`ZX57uRAO>6bEvZRfY;yzF#B}sWSz%Md2x>R0_KKLfiO|PD$PAXQwYlOp^XcX zbawUc>2n&C_2SfGDEplonASAP_;C~67;YQ5nNlUo_F?Yb*>A^pi9POBW(aWVVm`WM z{Yg&A(PbR%fJd@q%J@_wqWRSWBK$1?!0Lt+SlkcJ+}VB_Mhx|I`&tVFyN@cmj`}7a z9A3c9o8-4MYI8$NC|QoXFsX@59858u@b9TsJ$Q5<9{DOjm$N-7x~m<;e6hIaz_R?prw?J>)# z?Y|c6x`hyWLcL=0JsWu*3H<4fIgV_|*(#HC>ab{6d9!@WdfpgT^3sHgNJduCV3PhS z{9}_`YRSax0q9q?gqlb~R+(V#JtpKb<5+4JXtyy-{>hs7Ktd#msMTjKSD0wcib7$G zP?Kirs0eiCA$Cq+Z~_)pdF(O&LDQ)nIj=`PCl8ql<7&Ri4>DRVgA}au&BFtAX>cXM z0^6$e`7|q&7~HBzXP~2hSg+LqCM$7)4=G?#|EOAtc8)X)&NcDMQW@h?p;)&8g~qB- zO^$G`Q9j2*93JOM(K8|bGKj8=&O3K*o)^HpDBe*%Ctgy%u!p8GPAM;ky&tn3}=_bi?s41C48E+Fl2H2v@?0K>SWh@ zGTXIEBmZ1jLFevKPh9CnGo2V>V~lCb16+64FXHVed-t0o^I{$-iIf^Td6w{u!;6M2 zgJ%itb(9G+nwN(S28p8Kr~eLtADgOk*d7py(ChUtyv|icrUYg01Cdu%TqX17P{o}a zU}hVvl3@7%+_$yd^EvS1WxKptj-?uX7HduKyqkvn6&ZP=0$30Lg#4ZA;b|Iy4zV!3 z!DV9=Nk~^QAjr;$=B)b`u6vk(91|nc-C~dPAJjj#tb@T~;+lmCo$SbG(}!mX&+!)g zIAs`)Y3GVLn}0hdYrM?|NY_5L4@K!0O!u?LJ39GHSjXkDKitm0%@iB23U!gz$tUi~ z%UQ9dYRYsYSjDsTnSQ4%=2lLpmA{Y@&>P3)qKUtL=OOK1?S&REr=%A1d=;aB9C@6T z<>!gFT-KYN<5CZPi1R(Scxt`bo4wL|25o(%GhI}30RT%gHisb6QA+xviEO8}E;rs~ zR7^*P3`Kpp#~!n7=$=$K5oxQ;^kM=g@E#^K6Uqt|Mp+q#XQ`SdKBH$dtGnCHJ|9QK zNV$s(CgZ%cU7v*>?^??Ui{uq;`{zEX^K6^KvcS-ym-kSV_J#wn2-t_N*Kk9b;EJPwTp$dr5wmT-0Vlmvw z2eT|Xfz?u~l+S_RdTCw}p~QbG9rSg=5LeI@tiSnmG;O$SahqC=I^1?{`m4~>F)J<^ zmQa4W!Wp}EHx|ZEQQ7EEp@H(d8i%eqzXV7tKlvdOXd?sfufTf|NKJB+B|PrP6HijhUqW`-;B zWTTR1kl8}ilSxTb+tX|*+#eC*@NO;|r5^X;v;}vt6v=7N-S%%b+|um537HH+R^M_M zl9c)NDoCJ9Gbe$l#;JEvl+wmL%w|^mf-PpIMjH zXB5OK^~NSao;=sTqXz|O8C-MKKH;wZj6L@q`RC^;Y(NqceguLXX_;(y7mN4tLq!=s zADm;Tiyyny_JL!ri|*0rU z)QQ+hI;+11{p{O*A_|j|1vd{N6&gzUl<^A?ZN$hJ#-;_axNnyZDO=H!@sS5vrF_0Ock*N3(5R=H$cGM$ zoFbxkz&Goyh8L#~`(Jp!C);X#ht`Xy81p65)=PvL*Xf)-8-x~ef^|>ZoZzu4T&5BQ z$!v{qQ@9fYx{RQBHIRAd?Obx9i?=LPEEstEL(M>0XPr4nA1-Wudn5Y+`euSZ+8fnQX8gb6Xn+?ww~s~>TWxk@~_1j%SUqP;Ebz-~CB ztjjAu-MeXHxqkx9n{MIQiggC<2p%n}0r?c)XvXrwEWdI0-}18vAIC@Th{`)z!6?r6j=jD@9CG%3kK<*(PtF8Ox*^H}>-ajDyy638~+_O8 zPOVMglXU7xtMpj&3W6J&e##?ho+e)FIZXB_?W75Edd^6pu?oVU?6J>9 z3I$z)OxvLhLj*u9aUo-%fNTM=?VPHSO)?yFUbf3_nGh22N0{Kiu~d+l_^p>u46Xx4%V1pe9b2Y({*Rnjrg(Dstx zW-QK>U70xo)e~5#C!2G+4;ES)*?eO(Pio*E>AT~QiAnb z=kj5VP^c=&X*yB<$PH535J#vf`~1cFheAi)P4)%@IunRMk^HA-swDwPxlt*|dUQaI zEgHpx5f&|(#DvUxNwM7=|3J%Lc{bJl2>+&9dhuB(0nDv2G5%=)+$b*GWZ?@-bNYqg9+S}!+?1u zp`h&nOnbYtUF#bksk&VdumLY>mzH|sm)g*{cgufC!22%AE@{ql+`ots{ z#ljTFE&}!keBio>kvn>NT{bE%O{p{sKFZhqR5S+GfJlaEt#w1NXg1*_@B^o9|MJ)( zh6<8J)4U(V2 zjRX>#?dZ1Nq_riNhi<>f90HUNG{$haMGD$8Ach>uF@I8mpoeNv*}kGGi*eOU|2vwk zVvFJXL#ik%ZL}EozB4Ih&;WCi^2%WQDb ztjIWGQdvPM0)Hv%3eQ|fQyovp4Gr5`?g00vbc`=F>JilU0V{>!A7ppiBay;O-A;(1 z7YENg3YBIWG}+(KOlP8=8*~_tICgRn=p!X8NKQ)PFGGr9WjP{DUAPJ6(gAKJr$V~l zWAojo4+vu&mA_pDK@~L}WE&It-++{A+%cpcm=YYKK=p4iRH3>smaZu?W*MgH*M80! z<`13`@nRv#gPHSWSKL}Nt#pzn1V=W-Q92%Vw!AP-m>(qn5}t$5kZh>#H$0DvBD}8P zOK`fi57f`pvK{J=kO@ZDWX9{01b8LtTpFxvTrc&q7)qjb^)TJ7Zg-Z#X|vF1O|4!= zMFZK0N9Zx~Md>&XX_UF<)iY1&hx#AHt7zY(0p7><7yktXVhZlaRh#!xu!rjX}z;s4MiuF82)GXE;p<4!}Swv)3F)lzRfsFqOlEos{}tGBIn?z54<+ZLp-|&{W@BGYpWK zS85QHDf0>eOOSXl(>KKobuB;7Z!wJDTu;()zN99dW@Q5>QO*W6N>Cc9{cxSf^wY<@ z0W2u6Sdk19tcp5Z6B|I!2ygfgnB_fR#8}gv+&BGS)K6=#`4gRIFF^a|JFn3e{as%y z>Z>_x0>Mdrtv-zGU2hMn8Ru`k%k`VB4Bg#gZ+4YNyP3-1W)S>B#JXf@MnKuV$;7PEO6qBVF+#5S+Sq#g zQosj(?BP*yLI49NT`lH-;P0sv6@6K4n&C_Q<&wmmC_OrE(NftGnit+}!8s|>M9S5j zX7hT!%?eG+d^Zr;sL^CpdnE0G4Co9gnAzi^2>u|lalyqWClhA(GILYQLsa z(VUfT?;V_@ByuS^NE&6e$nOJyr?Qv$m`xqXw;t~Y-S)-?^E z$uxbCHz-#+=tR^iRXSLoVsnuvnADHbY59~cTs+yiU)5~qSt)B69V4cSx_k`VVr{$;^{1VvOb1S>&?Mo&gH=~(-LZF;EJ1>gq#COJ81^6TPX462% zI>RCB26SA~ia%r{ygRIl>4#aXc-un$8O~V24}k6BcZPKVW40by-0|AsiNpj@p&kGG z^dU}{CedFmQj#z4ywv~qUGV>y{=Zhj)~@E#4nJI7+)V#dQ~6((`WDU4ubfKE&#lMW zItFN)^^s02CKltLm$U?M6SxB~QsykiEFqCMD?Rpr&ee^ceo?tMbN>J#P*x`HVOn}R zoN}i)67`2!MC6Bw91^RINenCH2lQXww)nPjK0VW^#Gf<2uea`bPkzjFY+k)RpV@;6 zc+!P%A#pF<>A_v{^lwP7NP6-PPg)}viDbi*MVtilRPF1*8E3=vV9h6G$G3Y&I)jFZO0H-Xq8j1~1?w>v4hZ|n z?=tZ6Reew!BMAhfK;4q-UgmrQ5qj%KwwigQ@&i^?AOx!mA}v>DRM<+5K>{z%ZxUh7mX?Wn7xf z3DAARZeFS17|9Mv=o?`n9yYDkHXdpqi(x)Bb~V+-?W)%`I*0gKc6le)phe4T;m~fC zillHm$2c2`KRuLh?C6FL)Qh}$ry*~Mz?bZxtZ%R>qpoW$=zA&QY`WuRwp_H{%x22e zMj+qkk}+Y7nH;-klaC*JW`S{Li7Bi9o?qgA%eiK!pn82SYekEI^!CK9By8yAI9Hd& zcTT@|ee_{qg^Tg(-9h(;)iJW z=jyi?Hvof-2kCA<{WI}~6!j4-ac=y8BDuuQcv&=~=c!(|Cfy87VyFKu42~nkB=YZ{ zW^&YrSWpM7(xP2!LMJqPU5LD`WWwzvXjjP9NhBDL@^+=ZY1x_}{_%T0@n0kEDa#sI z@QbBC2~Qu|^y;D%Mp0h=QcUI;xPBkYycBCg1rpe2e?R>J5a??=vP7U$Zn^6Y1J;qv zo?}dU>Z=c)<1jqXgZ{Yu?vYzjgLQ3w`sTEbUYFPr(Pwyg*#Qvf#%^(qd2N>)*m1REQ zC)PB~OM_x;aA4V4uAy~yr`iTM5~^yUEl~{fP2kaWe3$ibQuUB^hz`9L ziG9hRsqFX#5S_Nj#S0|XGqT7tzuP|nJF<*Ke@`Mb^8Dh1>`y=i3{f$>V8|dUS}X4X z4Eu$9NGXl#Ju0G|de#MJ-I&>dc^#S9b*$1x(_b&6OWLrp48Uk|{2_-7@KMlYVF){M z_GVe?=KnbGsUr^HbBVyfFl_!`{f7U$_~(C*57^fGAJU(hEU%<-3NkV=+(coda^psk zrGWepPIR-RdiWru40t33ivzQPLUo1(o2QKpdLwnzX#1L#RLZNC)|Q&>=B%2QF8j-# zj~e&+|0sX9yx23wVGuq6F1x-@zkkknr2f3_IN83JUNgA?1WtJ z9pw1DGBfW?5B~&$41DrXJZ}EI^X*h0!U9?Fp4xANeSU{V13GR89lBGh+PsX=iEjch z0DnElAQx}knNis8;!i!l6YoTNblld%#_w%A05jvC_P%d>GLl>m$2;FTbNdYhKkd^9 zcnS%5^+CFU=(q*PFa@WFE!%l=!+)=x6cpy!0-SGIggiqwiOtbSOp$>ji9#cZz^i_m zn>X}# z{BcX&T@0+Q^Yh<`X#bp_Yo!M^&;MWf@ zxSM18da}?LXa@|v$|dc4N79~u?>b$!>Af)n{Nw%iT7|rC6hW4N59rUo{k{9U9iTkm z8|()=;LGW9f1}<6!s&gx2EGAyKf)budqJ77hB&`ylp=up`LJqlvN)N{*_}>jqN}00 zI9{DMr{sn>Vay|^g~B+Yow(6P&5}h0paH4;F8-xhrAC&Ob*ys~8qu2hEAj3!0kk*? zwCrf?Z(2XmARNSTn^+{{A?AlVg^Ov9NZVjS8U*zFg~^xD0j^;i1DdQA2UkS5P7eqK zL^co2qd^7c1*eZgD1|Fgdsi{ggGBpEsQt@CR~Jzs5n`Iz>){6)Wu5Yqod*q<0)d|O z1vv@sAru8+PEk(5vEzh^bi{w7pf<#E3ao-UaefKI^9u;zMunhHso0SRcF)f_5Co<#dJqDDaYIO13h`_nb2h@7FggC+#vZ;bI7wAS4IaDWwuGxbl44P z@M{qV=ABHKgNnR2_@L~`v=dz$83~bVPS3Wmqw0)%%%02}9)&3*2W^(n`3JUxDJ;G3 zF(N%Zbrs2*wOY|ME&q+gPR-x}q;qVRYkbZTE~P^X%>ozdIWB^fzBA@tH7!=@em~%n zTdplFM!O$$FVwzF+r+R`Yl|E6zzacBAYhG_EN!eU)mdPkv1a%(;fq_*LpgX9c1aHJN~FU~*E7ta!i%?YS6@X^59AaK|J)GMPxaEzN#vTA3T7$IXc5p4s=mrbL{$6^ z+02sDE!9eGDNOLM$g$fG#y@Q(LBF8=ZYm5McUpN@0QIFCgGw${N;Ntg)*eaFz4I?M zQMuY2=!#I3QIL)imA<%=O#_`EPpnKwyCYxvpIpQdl;DqKGcA19w@E4f+nYuv21#WQd$Ev4YPB{~LT|n+K!zTH(QvBZkB9oKSdCL-VAD&? z;a^6Ob$_ab4_bQ`- zue;1WTaV;47@7agEnq}yJt!;#GYA?XX#UKeOBqk|v7>}5v3VELndV#~?`ZVU z!B3*ukYW_64Xx=z{^HIfT{jbM;hG@v8VHmERVvL<`p#OHC4-Yr-&9(XKBAR6!=fu3 zcdKUb{mAgfXbl~dC#o!ICQSrqJICqCrc7l1l`78$zwI(nGCgFb17t(}`;dSxnw~C@ zX0_0D*^Dj_DI0Z7^oyH=%yL^9S%T&4^z4~4q=iO^$%@aGJa`_J-P^%t94n_OD-iUk zWa8Rz<)nq&Whe?^Ew!J(_7k1UhenjK<&X4aLRmzwYvu39qcfK9nDHD{6lg|XZM#HW zB=+3aCeZvR36Uj&r6gVhIQguQ@c>-X53j3(h^bTx3&qsWJT*J!IzD(;MmK3y`6)J( z#J?fYisbB>ZAAs!vOoE{mgwkyce<%o$>s77&Xba;(?&`JLC&ZuE7~ZWYbRcAVTqD) zW@*=%MK^V-`{~e9BAhAeJ%|e)98$U7j)-OV8*Z(qtW~K%Z~LIooU>-@c|l88kutF- z+~ew8ZHYVM2ZlBfw}$B=F#Y4$f#Jf6Ml1ReCYpuTkwHIa{Yj!&tuuDAw2+H2{E~oH zY($z90==_{eID5st~20MY%7|&`2C-cR47MEsP+|wEX)?*w;nLSN%ApacROb)B#Gr? z-=CRvkHRS&+{48g2Pb?#0^DP8{zA=#aEN`+0JN5`V$SPk**Ch60ms?FkIZ9c+2?yB z4e1c7i`0(nFfWln7B$SnEQ7=Y28+xyH0y9;X&@GZQ=%s)TrNX|ViPMax(S)^e0wPX zG)qxku*vYQh($u(?#ZViguhenyIVPB-gtmwu(zq^DEpj{54(ws)JsN-oPLm@@_(q_ zB2u_0=KzRnIEeO5htc9-nMtyaqb5mE4FsWiiL36AmrIVME z%jpxy6OUIT4Iegm{<$I=YD;`h972Dw)6ce!Xd0s25K+^Rxvu2+)YIya#<3(Q)KMF= zJf1N5$rYRTjI2!Yb_X3w`Yc*Q_E-EjGd?O|7DE*>YmW3j2jmBmKkFXJjUuE$pr#w^ zAZo0cl5-r-D(cBTR+v?x?pC0&*c4_H5{MdT+sDdN9(|9@syj754Bgp2hx$XJiTN1M zq(>`1I@CwMIC?nD3JnME#sfqm#@K(^X~j9D;@m)%8uE^ zJTS{SIVvUBJ-usk|~nGYEai&fth??47^Ricdy{mlk2(9B4@ngsWK z>RaR;@PIE)(B$a;1euTQip@|q2VCuahQ#Di`mx#THs2TaPVOrPdUplQoGr0=A#o^b zWvr20S|>xALc-y(en`g9RP6*Ye3kddZtcq~iPz^*sph;Ea0`x3npuER%{4WKWkKag z&8%F?9+#?Ot3Qi;o2Ajq3&tM$Xo=zb!kZ_sJ`LMAwo}3it3-*4^IP3kYf`B})OVOx z=YZ4No#uuXb>b6dbzBv-RTX5iUEn&Cu9diDi4c=4#rHySKm5E?59rR$qqCdNzvday zJK5HdnbmH;+LkdTQSR1qA~NK^x()z73Ea`^xOZM|_oJwok;=XMqu+kG{9%RRWfv-h zJfSEOa0}~TZ;otl<45~jJRFCuo4A81NNB4iu|O^Lp_HFgG|o6}R>#~Etz^bVw(1ve zKn`m_ruxy7tt+%*bH!w;!5_OmvpdwedAQHaOFd%of`ON1kkAjlugKnNM~NSbCyz;@ zn)avQ>Z5)DN@&ly~)GGQGj(%lg!tV+*(KI8^IdPceGF{7FG(Sv!S(wWaJU(z0Gac}Y>3coe9blZZS1!pzy=q?S1b^yKsWmHgW0u59yK z?)udqYe}4YVumbUykHSa>YPjFEUkke3Ge%4P2m~`CNtsNKPHH4HsN>CjLAkZkrXsT zpuaQgr?#Hu6}8^zdSm9}h|AH#0T~&=xjTdVLBES`Rd$6b-vJ7bW*kED((y10jQGJ# zLkIG3qj+g%5P{w4<~15C((2&0Qt4j|Kh6EKW`BsP-(7s z1f}e2nB8a;@35$l3u`%kW=@cwZ~YHROri;?!j!_pBc$7m#VgWbRQ{j5#FC|RF{bK0 z!oM&a8>~`GShHr44xs?n?wZsUJ{9Lj+haj}j5G$cBhw$&%PR22M?!u)Z$ zBS#mx_U^a`7#~Vs;>k|si`*BM9JK=}{~xTC9O16@sY&0Pn>Ro9mwm@ClNHc z5WoP_!%R4sa9?;qdT)f%?{uN4u~tYYB?Ex=Q`;oN-6*lw@5Rm?bA7-d+Vjq~lbXSG z!;AmYUw^qBoO?@RuXi3FQG@GX#RWGm<#rO{{5w@w4`QBjnEY4H8j_*lM6fjCP6#~| z<~4-8(oEwXn7qJ4^r81T+XT-rshdx3)2dz)!Vhv}Vpz*>?P~IxoZPF#i{5048o=Ls zw?YWdX^+8Qx}9CjlHbJ}dh=M}@veVIP zzUpc_aPIbO?sD1!0JUU*u2k{O@2#DI;+u-1y~rD5i(J3T?5PbmC3i*+V!8L}Z#POT z$=-dX;Qu93Ey+t4q=Gs$9#NA8;Qu_3M31grGV!&wUots3j2ERM&^^hOihNSj&R=pn zyvpZxEAvT78z`E>S@|3#&`rR35g9v{vNi<0`C~kPpxnI@-@W-BU2`Yal~MLcOZy}x zf{ZC-(07pO;RtWSe;H?(q{56bCsf*RUBk|b&=|N4^;D%AE*^n{ZB`Z{R{ zWxs1zkkEI-_Ni{dE{_UV*_$>!uLW>z$`|f~tFgmPGcJHk7G7OEF*OEF>vJWAC!o1$ zhX_ueMb3f5CxGGX>nZ9y&I3L8iWuQng6Yt2!S-$hRe@`@zINzt8mr#O7A8q zM>M5l9Q#B)Q8fD7;PyPmw|l-{J$7RbJBl`S=&B^UgBa!2gS<5ol@urFj(<#$K54;N z^MePUt|KR+n~=-vfeF!&`ALg*%e8`#*AJe|qJ`Ej=1Tk8=x*#MQ1VpWJqH>GQvYqnVJ>n0~J{$C+u%U7q(pvPBmi#8)HdO(7=-h;%+y_ zz=>9psQOgq0GDV>oRYpwIoHPAl&aM+9fzTs6^gFaO75I%oV^R~MD%8Nu^5MMTMnr^ z>JW>_7Ce(D^s^(>icuNzl@7E=P0%ZcS0#L#$POe=Wbn11#LjT+nrU=(HhrUa=CMK3 zJ+^n2cDk(VVVY5*xI9+fkUW+cxzGvNDL!vKMbe-fSH2(gQeA*wXd!o!Cj0wgK?K0! zSNk}Zf^vee4q*>*VX(HcIAOt%Hyq#gEawNbR?EHkRa;j1eA&PLDZ%vNZ#jP%qK5RyRMTLqqo@Djcms#_$4o4g{o zgzxWUCFx=^tl@i`H$)ZBV$Cjoig7O|N%Vy!`K%sgPvKEH2pmsT47 zz8E`v<5*o@dU-W6$mzY}nJV)~d@(lu#>kR|qx|WtG8tW=;Sz9AdB`Hk)vRP+U9F$Y z_SY^d9XviE86Zq1A5sG1r5!EHN9cuHyqR=D@q?Zjts4aTprjsn?4$b-bL~G#Lw;Mc z=s=-z3{Pwm8{aHAdKY}_OXQZjYm~)&k@&`VYaJ3j*H#*URUf{u*dHkr4Dr^X!tSO# zg@Dy0I$S+xGSY&x7Y+s3mjKO!wW1JgmSor&Qn&V!we}KWZITQsQf__;_ZVAsnObux zN2A%@H9(eQgZ>-sUYOkR2gk}=z^JTn;0aFRrYz>h(OxTK(x!jprft!|BLk@A=#dRt ziMO3;c8{843}Z&w`IYHS!R1vT)S9|Y!`7o>bp^EwE2A2?hyL7(C!<;IIxG_|G>~_s z_F@T&mU!g#&Y~F7z^A|f1T8unPCILLWJeu$#8FRIsS^fz=i2|)IkYRAeddsR;Qh^! zR9*Sc2GCE{=uPvqS-0P?+FMd$VbH;kbtr;^Aq6m3BAqbKPDlDUhWk~3Ly zM8_V+eSYHAEV^v6vaFO8Oy&G*5|z@*$2!94I<^u`s3KB)%O^s&P5;jX@jq}LoYNKz zmbPkK+_wm4UIXV#t;B(>em$A+5P8RLk7BwQ*WXs>ptMii1dgvlQ-IfA`o8t4G&1)k zZU&kYNPc&ysOMusE0B4+S)|Ot^bJ@x5~wq1L@eJgLL>??G@?S1Z6YJ3r0aE_XKnse zRxxS1^|OI+Dhw%@nw4S{P@r0x1Kz@In7!|NF`H;SP)f~mz%YwCDpHq8-^R@9P7{NAB8;Ir%nWV-~ZvbGqa&&Oq6`zRihe7F;$ zeJnNr#kvxt;52w<_;DlN)%iYfIe%|*0d+nQ5Ey5d&l%MQd+ zRw@mI-#w=;Ots9VwJ_7G%YWj_yrrp#5w$h4FjmK?%Xwsx=Dl!i9-1zY(Yf=EA*(`m)pfJ<4ANG;K>u*qzwdaAmF_~ec?K3gqsim-2H4!n zTA}tPMrdNhlhdZ0uIZLBTr8%vDQNES>C0CyGCBUqJgadi|GyY}ryxUCEE!B zM6i{5)`u?t!jj^)Ljx@Kcqew8Qt{8Gc05Nf_EK}#d4s#XBY5+~Ov>(w zfH;?2uWC~aM7-7a4MX+fITpAa3?l=Pk8^>I*t60nGfC;&3K~Uk0 zpuz<~g$qK;lU37OW`jN+2)mWeF&K2Alk4g`y2SNgfREo=<8|yK+{Xk8_1e93_+_xH zWv!=Xr}f0&K}OtBt}Kb1Ot$pwA_95EgmQ|%$|#4FR-hR{o+dctffM4!5DM9g0=DB| z=R!a&2?DfSf(phKas~>a9BvQ_>E(eNS+Gk=KrK-Mx=uj_QS}-@SmC5-64ZsS!scw4wWOG} z#F)>CFziV%H-wnm-a$+%yCjrDCe_U*9^oxst8)`ai*dru_(nYlE!Ulgy6LX&rQKaj z#FKmNsR7$yM{&Tr?l{dO!>mvSu|OKd04o#$tR7%$jxtmH%=HGi<>cLKOG#Lf)bwPs zIga{H5K`TZNG0BN(wh_Bc;)Ihp&p|`2OL0lV~PwozlrJC803!c;S{_;?18dXA>lie zam}Dc6~hWuOp8=xiw9XAX?l94N2`t=OvSL(pEHsHmPc(Q9a~QEN*!EQHZOOpc?lCa zSl@)3UqK%?UV~=4N+7lBt`us!5@_x3as;b76|HvY-4O6>9ORw^@QnxXZ4eU3vi}U} zFN{rdK=&e$QYz}-S`}CKvT$DEj9$5nUO;n>UdtiXQU_H^9aSjx)WQEO_c%Rjhh6d5 zG~3yLC9E<%3CG-RsvA#2ld2UOghrqo$!3zOXU5jisxn&0sY?=Pn}+Z>i=Itv-f-yW zBHjyQ-)>)ifrz0T;PeSo^urx!4+*SG&^3GA>P$P?M8q-cjok-@W5o6WBarlmSa2g|s^){kG<^+5;;-56>VO@>|i z-bmJF+S0`N2pVH;&9G|D(x9|Mizu5Btd=mGJU;wvo0$+@fKScbac$VX5d~e?LR?|9 zvBXSPb;};sS*^9BZd`*?56kRR=2VYDK`j2XhT;^oBd^`>CP!k?9$qGG`MaVgZ=7+% zeRZ}7{vCyxBo8;y59v0KGssniFgG*XXkYJjNh2wzmLk;J4o)7DnK9cn%;^fheA+Zl z9W3!Vf=F3g9@7*T^#%>br!pBoIE}LWSq>J@hC@E(lH^wRYyzIRb+X>bs1A@Dtyz(C zWCGi*0O7)H)8syOgV9n@)7;kCrKjGJ!n#XWM3lKYkR@gn&SRTBUILAh58PJ{AY_gn z?9*zls4Hv3Odl)KL!6TMv7WTqwv`^F{DT)wwVHI=w&&KumX)uSwOpQ7O#HpHPgx}& z$mDCli?Jb=QEJ=jn{A=Cn?>sobor)h=$*N`)7sN!@87JT;JK_ia zo@2YvORrY)IuRib9X#i@U=SmaxFRVQH=yaFU*%eLrwF2lY3u0sU}O61653OXR3|6j zY(U(i%p+!m=#yV%+m{^j+PIpgp0Y#O(iSA#mB-=%jAH#UP~HQJ)sk%h*D}4jU1QYt zJ7$QEgZ^p}<1+p_3F=%T!-V_mQ@ops!Jf>&X3IH5L|uFu@TSD&1T4bG%^$I#B@zm+^S z8kQc~BdENyX^)rb=^A%ro4ZK>ZZ_ksjmv;Qfh41m!bZuVDW%PS8}}hh#wDBxT*^yn zOR1%?DN=G3(i%qrrGyDmd@Z4E3tbGaCKkR=SN*@duBRp!gZ9_x_*tBHx--3JGdo^p ze7%nQ;I9Dd0e%|iVza6CMy40Gh^FO`+oXPsp?@EJ;x)pVT%w=Rz^E?Sbt?n(OGf)@ z5dKSM`_3R;jCRF<9WuOz2Lili#hAP-kIkO>nsFgwe8!sfz9O`&hfJ350*{^I#jGrk z;T{7I<+Sp`WwKb0_r@?YnwCksXqdJMM}#j~9_w9BC;}e)U3aLQ=Q<_5et-1Br;yr@ zQkMSsfi#&O+nqIXALE@i@X9#$I~d!e?K!t&abP3!JB&wh53x`G#551p4!}PR$$;x zA)6Z;wpZ(kwuufzNjPxuFnPGqNo1+oR{Xf$dQSu>{4A>i{p)W= zXkapgeUwZxmsW8|)@>uqj!5I9VGpy`(;(%{gmpx+=P`fwN6xv+OM+wCM3IaezBcPM z`KQ$8R?CuxI7h0=qPg{Bfo#d4P{7IivJ#uZ!i(pg$dnR!>NI$DJwUxsdNZ}5RKv^a zw*_K_R+F))ZxedY2B}p_Zl|%RlzvHcupfwaQ)LHlV+^(-p;0V@GKu$*h-j8;H~!@& zZ8%Seull`MSN_JJQRL5kLCZ3Catij+xyTpmc`-4=#hkL_^8C%xr^*@^`=zq9Sz&xd z?oPUrsj*QTof>Y|Ru--#oGCYkz>B78Qn^HG+)4{`gO%3APNG#TPP3fd1|G;2l;o6} zA3yhp&#(=&9g#hYr5WX-jM<4Z>fCp_seLN}`hhe8rOyAPG~W;pJArt)Rz;yz<#R5e zRv*NsoHJ!N#UEOI|NWdWyiK6YoGXbP%d0Mab9bjSf{m2&Ga+f`(ReNM>oSoxQ?jv+ zE199mXre1p^N}ik7@fq4B4q-r@Rc{Itz(VbEQ{uyp-6$rP2^W2KP;TZN;s+((g%Si z4kk@xCVKOqMnMyECKjiGq0N>gfhpl*wpQ-P9}7f!*s$y^ZO|xq=Beg(#7dLm zygG!gkxtlF4?nS`?Q39<8D_>FI0D&^RxVAlr5%7E*R6S=UfAHo8ryur)vap~zWc?y z!t7F}_%|NH(^Qaa`;UL}GnLAA;xOHjW2^7FYQBQmZ;Yo?l5MA?+OK-8on9q z&$7vl>YE(t!wc2c4{9(RQ7@0~9O8V(x!ZgSXHnn!mX%iO8M1Aovffz2u3}`ck8>Xo zm@B&2y2#RMV?oF>;%9p7jDo+G$4Wb9#`?khm8@=a?C?0=THs^}XHd?X(O}Diu#bt4 zA=}s9Zz!BjDpURxtC|+I`Sr@flm+q1*1Pm0?wp9rnL;OZrs@+}9?PXiiX9c>Y&7h2 z9|A0>_z>(3$dzX#%V7O;b+oD%*8s)r*VFR!ES0zafwuzR@xqm5A|xL#Q&A#@Oa2%P zNzj)5dzS4t6mgT%8?LmbE-{23tCuKg9?$))aBDfz?8U*E9L4->MhT zY+dd()dzR#KKIt+IwA9b!89!1x2?Qm#+erArKqSQS~j;_n%=qWUL6fboYb3otO=TV zEl-jle^f?fJ^&+&aY`6>Z-5liJH=-aW0;LEw~m6Ac)$$r6-??#sQ=$144V=1nJ4E9 zN?fYqn30XzgBo#&yu$tMS0%^vdPsDxEQD)}aad6!I@^eye1Z#0pk~T*(>5se3H{-BMH1b({&piZ@FXT4A@eTW0s%&rx^)}17%HCtrPS^ql2RNVjUMleRSm^Hj4u!*X z_F=?;Gp18O?g)G1$&(;a)k6Pg3SR#u5(Hi8hi(|vvuigu$N)~yhN!{~QN_u){hn2D zdEau&@w8^u%8C^QZ@>o9ird^qYIAGwN-bAK3&)Jw%8cQywRO32^prh>Tga$l`Sfx$ zN1VX##8~J!{6e75rMe}s>=%ohL|eJCmVNz<^2ze{KdOCM23~H*2qM1{wgYZHu}P|^16%vZeQf4{HG_5Rk!mIEma`ZLvU#4uJ*R-Ad{h*##k z$EmF^2-ifb1Vn%2#$Ulzs%N^3ZhFa{GZ3>;+~;AVz(aPdKHG(Fpk+w158x$~c(^Mp+V8siH49V8Wi=Th)TjXR z^M{KthvugQv-=1<;^t(i-z<_n8Sc)Zy1Rzx9vPljLZCi)y)u$^wRH?*sZi-| zu&fkDmg0Vqd-wN(Lq}DwSx$#_%)XY~k{gI2vKvAb`s)`6+qffXE<_%o5&EI{b%lxe zG@Nm=wIgJ!M###Cq*2DKza?!Bzvwfi&E5z>5^C+{E4dSb&JsxIAUeyz5yE@M)NcLq z1@`tYd#8_`{pY^vJ9Y<>?eXBHeIYAH!j@g`*V>?^m>WeT37TPCiIclno0FtDWQ{3k zS3bZg{IMYF`HAvSrv48dX{&ar8IyTcDhwV^(y;9+_cO1XhA7W`_eF3hjUKfdAnkpf zKVd09a1o($dy0rEYG~-_bU!myyi_={ruV8x)#(li4v--joq>y;J?f1Hx7Q-3;>6Zb z0&@Ro98rT~Vx5*S^13CU+W~-M(s3tL0^axDZs0r*P}31g^qYKUY5bPfPI zG_RQF@RY*jFW5jMJCJ2@W4D6>CuYR-0a;r7#ZV_;`K@BtEg1ixcEf5FLf8EZUA-Q( zJ~=AfYoRW{BZX9`OR6nBG=`Z~OpvwehFj%Mz*oM&K>yAPulZ0I(3(`|>tA`4xTw4R zGxI2^ZukdWKlGgH%WBU4?dcY#53lZ7{ZH?NedYG^tU}L@z4Xo9EDpj68_Er842`3H zvgnYESt8bPB-zxM4vj&c#@|HI>Pd9umod)1?4wPjGz0O5PR=a!PsVP9bfraDD}4J; z{Qp}mucnecNAa6YUlRfV(EcxK`Tx$L|A&icji#pojw?B*76D{V#@H}bQzX}c{Os!H%YkLakVC~-wWMU@0MY04!aEmTF$W{qem z!8@Qk0G|Hym+h&U85=YArp@m}_M6Wyza8%0m)_~%lWRUW14`@E`Pgg{A4M_1-osHY zAI-sOrl`k3TGEW@y4x*v)2*nw@mDUp1KmEtgX~wd*?)8ga6Z{5*C~z=;huDK2N2gz z%1$Zd?hl>DOxFWFJnlM!?j$)0djq~m*ZD!<9?xA!y(goRKKbPQ3Ae(S@cZISzliGj z0DNaz{=Fgp^U)y>k+MTYJ)f!A{Jj$<(sGY`4tl(!NQ19X>~hZw%Wbc$w!Gt-@~0L3 zPRFpeyuBK8j|3R9zWr)FAF07bBtPmscbL>~ z2@jUCFk@|^#JNrZ2DC^fnrqBRv9Qr4i-Ku;Ru)Y`S}T?*j? zl4C-`Mv^kI@a7BylZ<3llvoAeKoBU|!eZQ|m;OLFePT_W!xPW2_s1`cPNo8m780`+ zmhxa_*}LpUG&wsIVNUk#Ub#>`IJFjj4y=+t8Ehq@${Cw`;@LbgtRUQa=SRg9blG0x>^$( zyVxaR^!gmF2Zr=k2BO@i=^!9MwI#|o&_bCH4-{h`edNvj^m+^&U1BkbNbU$2 zW$O<}Cx9L22l#$9mq{=1;Sr`asbhza-+&Xn{g5p~oiV4$c`49HqD~UVRp^n-RqYz4 zJjZrKy$&dAk%#sxnapBF3+|?6LVL3QCwOPk*3*lAqx@0@#kPm(blV|9=QCvndLcNw zl==on0mWue9JF%)59KvSy%!Jl9l|f|p*G-rs(y>kL%&zoeajB&KgLhe-49Jq&N?DyD=@Kme4MlvCN(xsv;6s4YD)k$X^v)#)u`p@JI45(2 znA&C?rm;JEG&7c)uNE@cWnYD2#pmt%!?3bynVm1^x11_(?XgXk#-;6!%1wgm`A8J& zpX&Z)`K?T|vV&D6b034jh*iOrxfOE=YUDf-2i?=p?>?A8biL4NhgfTK!|}At@N!19 z68~02{)uhSlVq51#?uq2=4_l1CbLQHDSk7}&laRaB=r?P;_RS5q8-Rt5B5`c^Mw<8 z?ZMS7UKk)LLJi3by_8$qPgBMbq#MX})NmC)$U}0qZ^~C%O^y%TL2Bk~2IuOeP;Tk% zq#Y1v?ehsa*=QV^g#IeeajJ#cG3dkzsosV#3+Qk zp~7-KY6M#{MNk*onmxr96=f(z775$!nF~z;9U;pKlm%v1xU&;V*Fyh+j5u#40Ri@o z0o<_mOKW9i?zv*@C~cIC&Rk3iYz99J7U-xr_80=_<+2TN||pj>332#=%B2}0ltL}1hgOvpPW&| z8dCv}6WqrjitEwj1gpe9S&KH{;-1*2aNorsi(_yUX>__AQVk*&F#$lki|ZcZdz0GEVZ8VS+Eh zKs8}RN;g}uI;e2o^+3mbv|~Ems0OZE-*pMvs>ne@D}aa#x7M z|LeY>bMB1K!ln$|wqwnKV~mN_!RW}cE;FyYd36YMEdmN>h_;`0WWjL6nsJY1F<*;1 zd571%TF?^~v-hRVY1qyfOSwT)6;4Lu>d0+Wr%!Su4v?b1# z*BoKVI?|kFq;<#Ftsn6QP!k@UQ3_|2c4xxLswd))KGrZOI3-MSY>4zg5$PE-%p+tZ zXNvkj=%W$Q5yuu9oT1Jcp*fzcy0j+ekL&pRi9diudL|9?i2l;b7|kW8m^DXyQ1FqB zYRAT48NFlvDcW`hsw1CeanLz(cgCH1EM{7cXDWKIUp1OdZ93JFLxNkYINNDx7gg&-R)APIrB4K-vMSWDP7 zNs8+1{Ac>lt_y!fsj`7$q4v7frcFymfvR*9t*Yxw=bv3ojdk>jYm3`Q!-b!v|4T2s zJ>UI(=wp0`^Y7?Rp10r0=P$Ik*L>S=A0|MxNM)=7zXsz$a5n`${s3}4=eZbEf8nkq zj@i%S&U8KJ$$3WI<+BGLtd}ag?(DS_AC!YUyWGWRD4vLiHrw3gGZa?>T+fVhu2OrHq-``_!KepMEgK!T*eEz|B(}yCRm%2tz zNjCn(X?fS2mqH-=$uJ|T+bEpxOdGw_>Ao|M>F|ggghXVb;}HM!>5E2B;jvlYid1B) zqY$m`q61lew%xJDx6rtsTVrHD%IqdCza#NrpG5+3tlRE5{f`FFzQk$&^H+NQ?Lq&G zSA0PCgX1bU8$^UI5HnVoM|iU0ukjg+9R;5FvXhy&aSJ1Tp7l9&TpSb%TiyhWHFgwP z7xl4233+?{?sqLX(xQ*$6feNpqn@vx@mQerG+EBBZsq=EhB;hx3X7|&_%_(99c+0Q zk(X!3k_uM>w5y94GOwd1)>EnNIcZTfj>tIo7cy|9WlD@yIG9JzNFFr2y^U}!DDPT;_ z^%xpRK(R25fu!}hcVeR;I9&+*^vZP8BGt{Ovts3`7?goPq0#~YLfM^TN02d-vP+IP zc{PSplcDC43QyP-fl_oi8btKYplnlw&R)-8*5#;pwW3h=&ZF$)$vm3v+f!QiFmmD4 zTt`3ORI%x=a7&Vz+INiHO|v>mZhDm-8pJ)0r%tViip6*6HTvf$xmXfyBg+qe7~k1Z z6QRphQ{txP+5MqV;EDVOf>ud^f%hTU_NeFY>|;+GomW`7G$?Z#afFsoeiNOAPbM<2@-M-g0J zKS89RUZWjzcK|ZxD>-i^6GRsPGLIt0j>&SGK+rGo_}ctOjHfiQo6{`^1ky%NEE;*V z5_oJ>--|+MvO@Znwda_mF0OVXjqVwrTN6s*RPQEO^`AJ+j*}$`X&5eZlGi%TJBIfY zmKv1KqCM5ouQUwtn{B1ZN?M2amLoMw7IJ-y@2bgv4(m%*11=?=tL3E`!y56(>v)*b zm9%_5`hmU2_h-zF^>Yz?eQ_BhWBNA8e?+!dnI%TYX%;?$U;j4-9GCAFY0y2 zelTDCMPOZs?RIUuhpg5!oh`3#MXE9c3oRjbaqTEW0>y7D1lC=k*=td?$R#-rgf|eH z&X5%ea2M%-U}`e+8p9}3kfLNDon07L5d<0K(I1ZbW)Yy*cImcgvxmU&`hy$YhchLS z%`AjNrf|`)FcO`_97NdMp_g>tPBHHH9N}zRhj3P#iAmejg?6z88Mm=ISk5k7l&i5&=n`H`w z5yP!>!rM;aGQ%mtIL9Z)nG6zg7Ph39(*a*!v6b@Y3s3tBIMpwTU>3nkdn85Btx1HZU_Vh&&*nC|hKdlMo*w5iGi_Cs+mzcx`Lz_;moYs3pwAr66E zkDCNS`2@9WmVjk0#kuALFQssUW_k8G)}#nsv* zqZxpWXbf-c2g~0-fo6!O1ANfeo>I5>eTzX|^Fi7tPRs4V*P>&HkR3tS5yNh9(j)@$ zFBr$+Jm!W=XN0~eO=$Rdghnrs!gfU8Xo%Rl(PIpofR5lV8-YSr9SLOgq-jh=m1J>P zMr$Iu*sryj8>I-V255Ey^xmZ!e-OMG(5+F8+LkuOw#Jv)sfKN#9PwV(s}Z_5-T@yq zBm9jx+l`69>!i3nBAx2#?iL0>%YuO?`52R)Z`&f<3ar;Lpm1-=Dy9i&`DNgDWb*$B z!S6`H|M2m8aw9`sUhT2AhI89=;|_Bd+_rAu*){X}0I+L% z=(qB8I}5?r&D=Uv-aGUgceMX?xyv~cXVUqU6{0)W;tT75OSsuL!!JIAUmSUvv&=7v zz8R6)67Tena=0l^3YR>S-%MCVbP6&{qSG_$Y9DpGlf%B36OyC)yJ>^YzD|c%M2Tur zs2mjkaDaA*r4H4!sd@mp;6A2^?F7z?2zi5(CLNOp;Mqe_k}q06gMB}NTAZQI81?po z)Oj*Y2w#{_{Ai$_Q4CF0HHzTG(2w5!L`*R#nPQL~>S8+*Idq|wdXV>yAjA~HUv;JA2H#`OaSe7 zERrByf;m^Dk_m!aI#sZ`|C0;0F$4^AsPXREK*b{zJ(LI^dW0tBzEg<|NMl@jjEfO` z+6YhU&8~|=?RiZOcNOs~e{WXRL~SjxV?J(*x0UyKm!8J^azLNT+vAN6wRrOqqbIs! zpjjxVk;F1;2sQpdY1{bq1yA-%x2&+p31xB-Aj;$#+4MHj2}A_rVLe@nj!|^Y3Z<$7 z;SYJSkh1o+t!-wAb_XLut%PX6)Qu@8Bf@j}n9VEJPpB=h6QJ+X>W?o97?$HfGz; zNXLL^X25V~Kz;fCF38t+NPr#VH@EkIc#S=MiR)Kp<_2z2xA-bC_;bNFlP>ZKagze+ zR&UZx-=wSUrizM(P#mapAJY-qDUmh7}I^T zkP$(V;hGB6Hp8lRU|XM6LO9Ab-rFjWTS+{1K5jsdE0BT{ll>IM{Z{7xL>jXa=eq5Q z$=PmVC5C41MS=He0kO**FM4Dmu`+{`DIGDspLz^Vrr=WDM68$El2MGJf0QCW*Hs06 zCKZI*@y4s=#w+H=>sd4k2=NUY#C;7xM228J7b=LgQ!qgiR8R|?;H_}h4Jg<^G)z!B z1_-|?LXJ5?_aMP5X7DcSe_ds73fkpcvFh6-;NSw5TRL>ww+-?F2fSv_|2lKpKUHyT zqYFpYBHYqKg!$IbY3Jq=-Kv?51|4|U>EDvnmhQKvQ$oP;Z4=yW3o2NF z3F=fqSULd{w55We!^a2FLiX7}L$Rc#nAd8Mu@=_Y42y8XwQ9Lq`*S6Lz2j=pRRjGqGR*68Rm`h5qg@^ zPDp=H9yx}qTH6{Ic#YAbzE$`5+xUR(llHyIJAdWx`~KXg^Y0rN&=Otmhh5S-)2)Na z6#as@pWPxs_PE6XMx7Jk_JC#FkgS>*!t%wa!3|$|v%FrY3*Wj0yk65ALH$8D`#Hgv zT2I=UC#FvgA86tV9`NZoJm6m|r`v&j3TL-Y_B%rT^f$t-rq2w~h|ok*2}WK5$~0z) zhI!H;M;Mi4R2T~-mhA0=(rh+$lO&UvF-yiMggR9;i>YQwTnE@jar0kvNu*<baDTH=J>khs@scMMsS7Rrl4ao}}gV%Xw7Xx;ovH zEhmiaR2!Bc@hllHfUm)HZ=#lVGdS~lN!GFXi&*vxSbf7lSF6=Pe!gI&3#gXpQDAaZ|n@jqz)@0JgVsYlcrCIG;d z6953q|F4$MfBwIfOl=Jv9R6Rg934*sl;y78`6ILA(EoZVgy|>d zq?sO*V0`iV5C-Y@CkcH-!}NX)Pw&%(UjKCarrMp|A0haG>O=3T-?b=p`p|~dO>VB< zT@ZeT!T19AVGi1lm+uU+3%!=bcq=<~Q*!pw+V>ID@37MEK<{ZYJ)-sE4&F?f?2O@u z+~Q)szWBw4)`=_S&h2Gx0!h61z zcYjic{Dl9&4S0RVhy9f51KtOfx*(QFK2oBJ7PYISK-8!_q7r&i!bbX;02U_Wiuym? zJ4wJK6atz6Dw2VvEto1uq(nn?CeVtM!l*_K+%u7o{5iBut$>TfQdE>mFC=7?2@8wd z%c@u&j!-%s?C~9uctAse;Y=a7wA6v-tUwJy>_hRw<-h!m5R zSrSPmBeOJWB+FuD6h$7hHlh*|C7HLHk}pk~r#(w)XlKomB0#^}j`*ly$d*u9KM8zYHy3QM+T&W; ziWy#T-C;P@nLY#bT<5J>Svju>>mzQ|)nK8{vxOLIlA!k7ok@MGaj{#GWhDiFi(sYk z#YEh~I`8Ggv3*`ELhVJR2RgPv&7C4L9a@}-JH>|2YE&axObhI06`$P$9)${TGf9}C zfdMrrVGbeD8cH0NnNRcAwFeV+si4}=Vkz83Og<4Ytldf$?Ra5Z6|?SJ5Vr$GO8+nT z7#^;N03S%PFj^cZmq=sbmw5Q)BZMlQcJ06AGb^-7FLN1oj0>6@g#?ORPJWUQE46N( zEyJmJ@42)Wl}4agR`p?3mSpJBdydR4DMU1I?o2*<28lFutATgVLNlT+C9TA=OvJQD zsrX1EwecC7-T8rWgm+C=MLA%vI?*DJ=8XPtEso4F$rsuh8vo4`P<6|ZMuV^J*UN=Q zqA%&HF0ZXp)JZTkEeh^T-tU@d`*?D<(OgJ_Jza-2xsAgSCh&e2xZp0WEYA zBuXdXpbb9&whxENac#~>C8*r^j z7q58$L`#j|BX<%s^P7+otIr(JZw#F1%VK(?XS^XT7hgoh%$6d9l*La8OWvS4 znm5|2Jb+JnpvOxex_3)z#Hg`2Szh_UX3O57(h5DZp-wE~zthMnT$VUk)0`G*W}wmu z$2t@thGpfpoVpi74b9k$Y6W)Aw@>MX$4u%Y8&h|>9aLuUm%>Dz!*W-Mb-YWNvgW24 zI#|KSir01}O#;*!z`cDr-99#vNpO=57{|f_!KUJV%YebAetunx8a{Hvr!u1BHgrq2 z;X`OpWKH~xDo8-@$fz02#V&Q-#LakdQzniYP1817M?zYB0N&@lWTA?##b_&azR|~=(urGyGbX~vuG7pkLn%^g!_%`U`+7nn6`T^G)MbfKMdN$ z{B0fn2+#Aarwa9J*M;USrKHh8ND@$w2b|2(_r;&4VCehh2xq`xQX!yZus9mtrdE4 zW+E&dAeqdKBHG&Ni9-EoA%2Q&I;MFKhU?Sh&aI=N%_kIp+l4aDO37kpG&qc0F!1J4 z5mnVvtnCGPmOS=HXR3|G-I_|dj6T|=P4HtKb`Y7=>Vao~rjO@SYdq!b0j_w{SY4Wk z>@*Ty@O;f2&Y0WmI~!5ZxtyJb)_D&aMHbd9NRY*Cb^jt+tc1qdOoOh3+6aUI9$QAa z(3tK0b6r~RM;v>DZ!v8KqmerTZ|sskhg<2|PSAV%F%c{gfc9X`f*Xv(IePGdj8+&m z(`+!!MwHCV_z8Zq4qW+LVa%OErekIPj4`pE+2-rMh|K7f_7y;5nwW8N$i=M4qxW<( zg@&|?WJ8t51hkSBOeD!r?!Ib`D)S;9ruJRdhDLa%?*&6A-shH}jo!;@1(bQ=m z1-Is{0=zNJ!TfbT9aibYXWrUfA59=oi8aC(Zt-CiZG4Gwe+)JF6t3aiwpekP5lwQ2T^E2OA9`HHqJJ(Y(;J}vL2#aowd7Kf~; zUh_U`zTbKqR}aVDZxOw+E1 z-ekI!>yb`(9D(e@s6Mqg5_!+0Pct_xq)RjSl%-J}O?v-AqMJkGukGR(^~tM>EX~>= zgFbom4@$Q>rLW5674uUExr%fGOSXFXmwPOqQyv*_VH8ZqHt`|b$)Wq5R~S9LFC&{% z8d*=)YC%*Kt@hSGCz}0fyE>wVxIE0JYm;7N%+x51{;P})Ib9lAC#pPX;1EOCB_g$4 z%vvjq&fUk6y<8aX$l{PkKZ%BBaV-4okwC^@9vK@R$!Zt**83AV>EhVYE`+RpzE1`D z;V9|SLeeRQzB-X{ad_l~=^RYwCf&swpdy+DtuH)361z{PyCs96B9lKiLc6afyHys= zyYD8uRT#~EM4vkTZ{JOKi`f2pdDu6rT^||VVqZ|#N6E@l;{0D#ba-i*xXWEdjE~GV zPi-{$;Z1U7Op_Xsk*Z>HSeH@XpjpP zmbDi0)oIK;$dH9DJvZ$e;tt117xz@S*~v{er|4aobLYCGQNBQf^77km_K8)ldilGX zm>W@fA=lZlD|N0>&z4}uA}z=bQfso0SzD5M4fIEutNIU22l7dYEu{sQC9x@OJEumd ztgJ1~4M~qcvdJ`bZZo+Hwe1YZq$Gde?c?)hNj64p;CyA8TuN|5y#mb3>v;jns_oWa z?QW>%RLK|fvaf~d`(J6goIJaGDR&LjWZR56y9@VU-!6v4v>o~-5uKj#eGW+0&SPH0L3n&cU^_rN&F+zL&pzq_@;cNbsxM_;e?{Ftf5 zH0UOc`ujZkJE`T_y7}=M0?D5NOZbDZGVJ8BY{Zts#B38F{3%=U3l(y=-fHKT-yfOBkjr2aHIkXc@zprxLfo!s5Wys41pxQnm*b{e#shi@!$+g#tNkbAfse^zCQ zgNeM21E=~NBZKBAy$qW8V>8T&6Coj+&4hK1zw+{PAnT_$9D4gud7J(D zz}E3x;p=aY0zL(#L>cQdbzGZQbFA1>dI73gb&#f1ai z>6fR>t`&9P{jlrObP)o)KJY$kQ^JNH721 zg|j_m*n9o9c-)(M!SVc4grk}agqFmSQ$4|GW@pH~(gB`F-2?~3@$7vrVQ+)NglHuF z%66pKgr#L_sReoWjIu@%O1dn5Z6oJLuxavcG5P0_NnwN_CEK|dcxEL^8 z?MSGWdV^}O32sEodApLPN^eUyBcQnX1owET_`5?xq5aBvHY2SqOR-GZ5Op9;SQ8{F zHNYY3Tg4|@YnuAp0WPr&+!pMYCV3*9dN+h1Pm32SIKlQ4Qgd-D<4=51$L zh0k25Sw+PxEG2ZDbt}AD3P~5S*PXCEppaff^J_Jww*IYXiZ-|xQ{26574=(6$)8f% zzGPhpQy!7lk{GzI4IcNUTmwjrO=IjSDu{XKgc`D~4Xjjn6yel9;JlZq6dsk`(DSj@ z)|)bPkV`(}Lw#~yawipN6uxkwAhTr8nW$HCrDvn#djqq9%0UNL#<=NDUY1Jsl}XD{ z1F`mv$H<<4Hsyn?rCkElOb_hp)&7f*n=8lLf3;w&r8OMB@f>%L>vgJJ@Yc|-TSZ3V z?rFuX#5pZAs1mW|@6`0Rp053-@$!*PZ6n6xqbz_r zZ8YO*G#kWqAfN1nzHT*Zg z=AFt%Q<5tq63p2HB0Stf@&)N^NaP(Nkx!~59yG}hRL^*!Zg4fFL{&y*WX}pt-CHuB zY{5L@QIp6wPT~bLsTWS)e8Ik-J@rU^NQ8C!{(}XvM?eG|c=AU377V!?az_mb#x$r< zFDN}?_d(<~R3PZ4-#v5J`!;RCW+=k|BRt&MqkYw;4rx6-@{-!5b@i`}J}k@T=B+Q; z7htz>Vyi}pmhVsqu)+nd!8Sn@yKa3JaFr%+2h10O-*ElSV0;(&2iia{F2o1&D`mVN ze{jBby}5Qh@j4Ch8VxZAPtp)E`CmsXl`uOBM8GpDLepRKPGl3-Pav^=Z@TwHxG#xt zKa!p&yp!|vTR(;P=WHI{EKa5Ixw>6oun*QAY=Gx6f%=`naF}QA*PccvyrEH!QEkp2 zL69F3=1=Z=r|&=!i6H)geA*yp8la{ztZ9(q^^Gwzi;3|~#56%xI2ar79|CTP1^rF z=yk-GF)JF!u{(BXN`FKl;!TxEM>=C7(w!-JB8y0JVaTd=gH=^46wWqNSo?S`ZO_EUY=d%%yRxY_!V-O5Q~z@M z-FCPy{Pm`!dS|(~T7JZ`+K_AJZ?PeywT6*3$9UDA-@+|`rAGwI=2D;(Y*Qt$ zDy%7aQ&6%eh4tM6zntwJq!qNh^6aC`u7VrT%u%faUS7pzw4C7|P?W4`mwXWPJdk0xj=XB<11na0^u^y0Tb4@KVFlnO-^-~5_3!8VAhZPb2IHEM#Buy&uPyd79 z70QV^FyDnh?aMfuAo3zDz%yjvE=oHGJHn>X2Gpae#Wj)T>Z!{39UYNc7v%D|Dk_Lc zRJ$|W!nHj9gGqpHW_0F4y!K3$`(#QWKK#;WmT_%mtxm!;P$ z7tT+N1rAX~7oc8|6`P>a-%9XdlLaJ4boQV#g^z-#Lv zM`0#g$|q4w$7UXo$!@!Cx8F^-qu!SwN=u9sUAdIr@92~yBU?*Swt}Q`8Byt0qZEyC zAVzyqd?ZvgBAUT(yxn@QSFJJSjNBYNTtmuKEje|8AK8h?V8oPuU?wdvZ0H>FCxLx7 zfskD=at*4B6LezaL{Q+!`Cj`N%9TvNG$*N*MU5xC-PyC6V-^Cb4atZH$v(^)2|lMV zqlEd<$vLgm!4Y2HX5PSjKHhACQbnArCw6F)vnO|GlaIw4iGm6`X+cVPhMYuu zMzWK%(&DkLq|p;ke>Ta!e_J|wID>n1|HlsxPr9aP(;OM*84|41rbTcVV?(@hyO??>=3`7T$k*`sL7}MWcqjRfH-W!|anaZ&-UXokJ;oX-0gl*iL zrs)s})5tT2)2c;t=iU>d8TM(qgk>JZW#*RO**f$)JPNS!4$$sgX*^iq?|A7W@XmY* zB)|Jh4UKoGD8SkUSXTJ;G_mKV~ z>D(uDwc`Y;ynpmxW3m;vq7?`S`7l}q=6o61kM}v^m37811U_T3L{#X?(k~_{Qu05Q zO2O`oLTG{-R***ZJ^KRwubHCL?brP}bRZxa)Bm4Lk&30WmA%b>WQua2eNmV3#=gEJ zl8iV&p*x4r=-EgONr|DHMG}5d0jG$Vt;-skHRE`optf#kUlq1QakTBgSl3bnSG2Zi zU#?f#)z)qdZCKkaw`uFdTYvqYp4wbrZ|CX8LF6aM@Z#b5{qm>pt2=&rF`w@h3Mj^e zNI;aSWWSO>Vow}?$e*$w@oVlpl!3`V@fS* ztmm2V*2R#+zPflbLOah$1cu{X{iyV}Tj#%5&UGGKtKGo?Js|au z`)a(dX!bAr%b&;9cRc)`^!CfQ*aF-2Py244cW$11eOvtu9PhW}f3L`U*2CLx=jeD_ zLc-nm+koJ)0uFAA&T$+(TR|MT6lT~PVh6LZ|~-dZ1%w5?T+lzjp=7h z-#*u)j=<00dh6FLg25iyPx+x;n^#EquZsOk?7vb&9IT(sfPnd1Ir!a$+j{JuwfnoQ zpWT4pmap`}1NUudTu^4P^6<7WtYM&uPjb<#xz=Fa@j{gF;v{!Bf+gK-3-&pUjB{cA z>g~j;YqRO1#rvh=76sLl5k$C+1vKb-yC@N@9N{&6-iXN=rO_N9=P+}^= ziHa|*q5Mz98VO9z#n%wRh99Oo4Fs54lg40hII1Z)X(ot+%EXbWS#yK~vrtU2i3$cMm z+D!YZ3~1=M^h}RX=@`QT?U#e zm`6y65M>x5XE-TKBF)L-lo;skZYs}p3Ygnj_4DJxgO7im(qA)lQ7Oj<2UmWTor#;w zoJbb1pvqd(jjt+}<~6i4f46OChT{v@Hux9L_Y!UJGayT>b5_#);mcBhn$NyBeyVQ} z1hOu;Q#M{CjFT`|`WdmRbAFYe6o5F$wSo-9!h-7k$jyG~d&}Itj>5{0(X1drg>ww& zC|#pW5+Ka8evjFK*`!PV6RVl$2xQNr>6dI<;i#y_D@UyT3=LwG;iz`u90%%l9rUaL zaT%Hn5yp}!z!l&Wss!^gS28f&akuBJ6csio=VnxIDtn0sX4H@)Bt|@c6WHygpZlUo zLHLxVx^N;bCJ6l`nUc;tNaS8*8ebv5-T6_B$T>9`fq{>?kh(r-@`4mSk#vmmG07z^ zQ9!YEZJ67e-%S1bViNGJgdBx&Uav+6%%8l+i zu|5)D#A;r{Y&;**rbvoqxe`8On(aahJ01-6Cye0aIdmv(hYd0pp~UIL+d*PbJ^tL? zo2Waw(A_BP5T5_>UAWAX%e&vMcpcVOy3yC0!3;?{RA(yIN#y}HqvYr;Hq>np;cvyz zhLo4gIG?popt(DTxc~Tzq%!jGme;j3uQkWap3lZO!1K{(Jn9)ld|`NSsq;$EG0pU;7P7{$!;WdQ&af)7cfMs+3k99r#(_t1Tm#3nt{h?k^Rn^c zs@6U|B(qV|@IgrVhq5ixq!8iq@Qx+-%u|apc;pkYBbEAZJQOI!1V`tn+#P3frRlS{EnsWiL+D z!bX2L_m#Fdd$KREWMYCeGhJzmwTPPEJAnn@Z(geQY|7g2^3Z@$sr zGYIgPj{LsxMjhM+$dHo<+`iy5BAmK+#sHN;ZeO&vvsZlEMJMpQfU6U(QOis#i4wf4XGOOuY39Tcp-Vn=E5j z&uh^Iuqs-Fy!tiF02&Iht3@hQNd2T}o$53!hSnToW9QZ-*`+PQ8$`zS-7`in+}N|& zENhfZOkCO1@ah`L{RM;4d%A7 z0K`>0#g1~jw&f{#(Yob}&UXD;8%d(>Ar@BfpxjzQzqo=~6kWA!wvxg4_a%Cn^@!BoHs?GJCvKH&NFt>rYHld?F?r!>0HjM3RzoC-K6n!tmPI^fe&Cu+HjUoR%c&F#!qP`RGs(uwd0 z!V4!wSpONmnz^1E#&Xthz{9 zj_cP-v4KMK8!Y@}i&G|X`5TsaW~Sj~N*kGKvVB9OqbNDxeGIvjZ<)p=grl+V}i{BuH(h!Atbk-5y zufZm}i%i&ntZHT4OChY+M@~szZG@1hh}Tm-mC8wROS*63&_44BWuvqWhObRDizTXr zD?=}Ljm_hY{%es1{}6n?W6C7=vAltgx0Ew_iqA}-jkgp#kLz^cLZufivP|7KRc(FR zF{8bO=5FcU%Qs-^k_BG1iE?;is9o*;GpKrrcKYRoJ+sR~%^|^jJ6PL!tlv0*lfBz1 zx)bZ1lkHRNsKGjv4leRWp{fZqKW$M_*Qum~_}n%8aaRx0yPY~6EAm$K1j*H%!otci zdnhiQ##(HFKI`#F4ss(|Kbdg9cZx-2Ho1uhVM4Ua+**rt>2QtGz|4cU&Drz%=NgnG z4+pAxyD80~Q^r%xA75V<7i#n4n~x=xJhST)5|=eYvw<$ZOz@~mH}pU4_x+S|IJp8X zZ2;!fljh9ECqCSij7M|6Ce~#e(q3|Dr6q$*5hZ>a$AIL{FOS@nl1iG^(gFCD z`SdOA-I8WkvLaaPYj$osksF?~xIdn>#*z0-Tohuf=Y1Q3K0Xlvg=fOd2!4zBtcN<} z_Lau_HXn<_Iib0b&CD2Rt4!p}Q=CIm*!5KES)lBhBvd*WF3U8Hh)VXHRX-oKR`dYx ztioCf&19Duk+Z+lS^hM}ATPRxSC}MD+_AbWPr0HC%3jnQC&X2Jx1Q^5`k6x%Uy z82w?c5<}L9Y}erV{qG)RnEK8>7wUub&lJ97o(0dB26!Dw z;H+_d1ya5z3K75WT5!Pa4UBFprZrfAXaPIoz8Vs(w}DL*!dn|+!3Cihg4F=TH9_SX z(8&k6Ge974VeuL;*`d0_GuyP>ALiQkiJN*Nw|tmvNk9h494k}P3R2TH0HaLZ1vv}E zAZVzVLn?}yj8!pPpeY>u6S>S2+1L}gU=8XZHgtptdJyTbduWcO;5iccZy#dtCeMOu z!rKZS1-SGjyz&+3Qp?00Fm15k9Q!AUY9H*XX4Pb^X$q8DVyLxrFi-d_$r~Li|85Xv zVgzy|WsuE2cTfkueFLHmov0d!5=oOk!xFP&_c;i$9od4I;y0A}Toq}p^g`91c!$)S zJwRuH!m@x^C>`ZQ8phx_vjDF_h0s21lXjRJRw-E!uIVAb5qVN}fo-@ePIFa+jf-rc zID}Tqvt!))R)zg-(iGXOs;B_seP=5{J3w{CWb+|{@x zmNDy7eMb2pD*R;p>{r$|qDqH3MsklOIDcMIkovN^A7S|+UTK;lEl$N2BY+wsF;1S` zxL}+DJ4(5!6i&%}>^0aUDDN{LM3tW597$C^%umi3KctY7A!0XW1T$3+{lIMGe;DZ% ztUSY{FsLFOzr2Z$b8Y?^hZ#T`-+Oc3SUz5zb4SZ-!6e^|NdjIxATLc4ejUuTDTI+f zMoLy21%uU}9qJdI^vurI6HxAdpan)%xpq`=j{t! zzcCOvYRu#ZVvf@=)+Q(5zHU8C1dIS(kP4mK5tP(Ea2P&NW1lSuNAT^BPtXVGaTm3p z1k6@3V_u*{XOKV0a|rX*?@WFiO?mK31&~*W&vlSI`_g)OAc|j)a;y##+3iww#39FE z^<_&df@~{;inwQtMe^866tNY_;!6Vt75z>mJHdV0;-Zqt7{gJ3(T!j|#>|=uI!j!Z zv|nQ#$=~0M3w+F}j5wBkN7^WiOhei@NPIuHdCSp+RGHCNY_8zcP~NrvG;B}$oYAxP zd(bEN55jAC7T@$h-i>)Y$+M?1K`O?Ff$Ama2WXX>^fMf!Pgyo!=9)?*A05MU_$|S} zUk2Y2TLg>s>wQ}e5BAiiPQ~Cc@3wFP6}3~kk@8ysvyog9Sodh0ra;2zN=kJFqRMmTPFWf#;t>*e|Q5s*@q2eTsX zb36UA2`?$#j$DNRQOZ`eG5oXWauoCCVoL8;Z+9iyvA>#w(Zp#7K$+6~OoaPj6%nv| zTp*0opUNPL|8^lxS{A7i3Lk3Ls~Jt&n{$@Tx1-PL8y#Qx}sky2mk)y=)l9LmV3j5e5p;-)N(Ca|s!wz~VhlZ^%rC zOBKV?x!@|(0ID(~Ri#AB3klX%l58vcj7Gm4FQ|F%y?huRyh!7aD@1M;VOtY-_N_-$ zqhLJ-7M2P*^kv{L+$~2Rk%c!gIQ{v`vu9(~6CnzE~^+`b~H%FR^?Fq~g#% z4H7@lSag9KCx=dNy-zK-#mt0xSa=-e?L!gtI~b;C6SzL*RvP+WEb~H|H@HjShr=kz z@+}&&e=x|;@I3@XUkCl$yQNd-SFoH4TYrU??A=uRo8qNUe(~wwhk4V#=Q*WXB9reh z*9EfiCIm0!)g$M55Y|9lCleAY%7$JGoe09tW9V^pxwYp3^@$&}TYhp0 z3aPp7E9J;GGo%j8|KoIWWdpZ!36a4vB*YnL@rFD=^hhD%lS?((G`L2WD&YuQHxL%w z3kg1enIoyDAwBj8nODC>O{P(9TN1m{4(%Z%AMK?nQCA$aPT26%f<8fW``FcwLv?VxKaqjeo#?BHC>tu;JR$eFt?6is{s-?BRxcvOt z&$N010p?fnTMjsMn@#Y=cUelx3`I>XNrZA%b#!(G`YJl_VCM2RON1Qm!h$A49@RU| z)G!frjvwm_kT%g9?h7vmNIE^Gh#vlbJr5HGmZt1+lNubcQxqL}U)R7W&5{dZ}3#;9q)d=2<$qZeb)bhwo*QcDv%XWmbNpj;@5W;J57hhHa3jOwoy5mEQ9`#w9N z^{JJ5lL3{a&gOKn9$qsk1H{-*_cPVVC&>oz(mn=P3DKVfE`WHvj02 zfnxdjx)-DH4$1lR;ymK0lNTq-fDI>2`YIcxr-%r;gY-p??kH=hqrNf*tL|{ek$zHF`f-wq zlh}w3H96SEgMH;eHkp79wI;_*wpmbGWsRW3PA*M$9@n*ICSbVZk{hJ5va#tDy}C?8 z@))mKIkORu#thAN_enWZPTDFcm+bP8!VcHo+5}$8I^<^O6Jlg?B}a>1C$E40YotLd zBu#kiI_Wwd2J8TOwAOShSj^VMeY{ICH@mHe2Dz>OhKa+08>P%*(&bS3&f+>s@QZ!> zM0d8HYn#nM!!{sCI*%(oks1W@V7kUOMM@@czx5aR4?7MWqgAS<3ra%Gp+E<8thp0u zdo-zJVsYx2N+TTx0VKuQv^z#5oXZTSYUB`dxj3!TA_18X+axw_*{*%-fc54RyLRn$ zxF`r``{hX;3p=eMziimKfax3#H{N&*s3z!9><+fpsBd>&yx_MLaxn>jKFyWqY5tD3 zEAy@VQWtNwP-0}0dq=1*PReyMu&yd&;f{W1@s6K=?v4oal=Yq)=2vxt>r_F733^+c zO-CI`&=Gp!A097|Nb&=vt!TPyA61ObzHB!=xtIC@2mcNxyqve)Je4m7F!h{nD^3k{?{!`jV zmP_t!d@tKgi8dBQ6iJuBc~MXaAaSG`gh}0C{&Q)F3B#b2GEgg(bI40aexVc^h+4tV zcGFWrb$C$De3I?ZSAt25-seY9Kkn4)aYl`XJ7Kv%+{)>oD=d#wH+&FkNydGkcw@Fl z{+ia@@UA%GRrCCap%#fMR4j_W?<$1*0a-kdKPNR}xN0o870$eFLpi?(<9>vWb~nA- zC#7CsgJ!3y1_(ChM8#BwZ@r{1Bb!u&3?G_zWNnGbH8315kYw$NdESTWtSX$7WKD_| zPiwT1WNEp@bF@S73u_zmO^gPFiy(I|ZP|e_&{sYB>cD`J&IA_L7%Sj8$<`P%5YZQ= z`pQ|;4JDZVX69a5e6y+*W?-tUFMuC2G|XU=P4)=3;*BikoZf^Jf7?tv^g=#;z0eID z35d~(Ipn4vpg2X5-D7bUI7M-bW>~Vzc+E=MRk{Zz3kVG{p!}ejcm+lKjHLcM2+unh z47G1w>l;mb#`LVr@E$=Ci7K-`E4)ig_M5l`lVlqq_U~w9nq-=Tq2C(U;5(IGz%xl`Xm_UIEHhdz%RvMtb}!`FVO!?{{74NQIN_= zl|cdlU10(NG5xn~Vq&&tc4qdj>PEJ1X8%A39MSmlP_e-Cr-zn9p|_#Zlh82?b0aa( z=H{MgSJS0BpP~hp(Xdilmvhz$wpu9VfWy4WW{f^an4Y$~IB{)O;cyF)aW$$C=pf+5 zpS{C~4~QK*^>cAaE~9FhcK7yvA3y#1;+H@B;JY*H*Y|lCkiP}e02=UMNHEheAJROS z$>v~Ru3iuOe8F=i&b8v%eQtY_ymj{2%^7_7ZT4o{vKzEQI^Dw3zy6<3nNJ0~@ z8T4LLgGcuYNrs9kf%5V@3Y8F5dS49YVA&cpBmLvak|xMX683!A3Z^mF z#K;7WUu!CkQ;b%6T^|Q~N>VAH#$}UjDjqUEWqSNlU!$syQAEnpEo6{z8+1WJX=(No zeMU;84cKJoFWTDZnQ~2d@=KMadEYtp%mm`QPKWwBRds5Vq)Mv=bixnG z)-&CbjFK?tM21|L%Y&%YnNKtIv^e(sqKr?Nsmm5kTl>kKDD4~HD&(Nc;dBm2yH)3S z%hulcP&X(iPw=)=OX}pf3s9%V502^0&G!5Sc^hho1f@m-1NA$ocT`)Qqjf1bUyTvq z$7;?9!dWyKZsy4S@GvapIh|?i`UAdC?Gf4?jXRuA^^xD99DxX`z7ZzW{_z488H35R zPu3XHXaT5e1jnGhH3!&rF3;(`{S}N4iX0usYA;ySXZqZMP`SrWUi*A2?IIGv^A zv0>gZWF+b=&6vdR?O-;3`>v!=lurE+$=)OC%C~ruZFhr&wn_G;#9Exa6^qcIr)Ldg zR&97=hc*8-b`zU~J5^QSOD*J|OtBX1>HiO+od;3AqX-1X3udNj9IIpI^L zj?pdC{_rYAf6&E`$x_NDmLny;vyQf`gR@1wCj>n%{0R&-w(!VvLRjZ|I^_Bekk-r+ zQP{|ERK)DSRL|gk87=-qWl}gfhWyegJdP%!15Q!Qz5$+MVECberNr1PyUASt0pfNu z(m{CIn!3^E@USe^1zFXnLZfK%MjjbQ_YIVB3l+I+iFElR5Ta3K!oWW5J{_mv^BDh^ z0m28up3+AB?KyAGC+Nnf7Ukc-NVUH|P<{mbn3)$uua;YSMMJ5JU$a0HZlS9vyxyDP z3eRGbL-KqWj|y+Z5vz2J$ylii0^<}L>bSwY<$+uEZ@nK1{TS`V=c*D4;w*=w#z1{> zzStjri{@m7OWB%a`H)D6fM%BHC$WiaXn0ve68XfF_B%pyu2!kE*<`rfv=)z(kj)m6 z6i?ZOA4;bD$wVh(^0=%eAD@cn4NO&KQEu6yhl)&wE`Bu+R=#RGxs7zY}ZqX%^W|sk58Y;54Vk zI^E|LH1Vy$#O5iY3oR+TC#%pi4szL|POzs^ZK@WTH>>p<) z6XDvTNNGu@vZDCFy&;%B2%>G%BJLsYS-8u*b%Suejc@v*CL(qO#Y?TewyW}j+`Oef zJ>gT|q}2)#j3Y>+#A-@~TbBmdl8Hn#>*EbWHJB?%kwL557j9USiIaxQ7n=HHCS9u@ z>^ZFJXwvxekAyT=ykYV*owd30nH~_GU$Hhev&1nOAQL}IfaLvrh z&CJsILkCza`>Gew8q-9tO%S&=LG|?-QC|vCC_m=d9@7mdyXPnrY0z|X@+YSr@4>WM zpxc~vW!(3QNy9t0zF|cE$^IMAf&52f!E!=mjaB%VULr4$c)5a2*S@bExDEdS4&zRN$s*?Q9y6m`^4NBgpQC86sP z3k9u6gVjSNglWO4ONFWCq`|ebrD5F$NW8+95(GV!&d)juwLRkWI9<69D`44UOz@OH zS=`S#x#_n!>vH1`2XlQcJq(!RNlR3+owl|_UKpEsru&3*j_|1O>PFj&xxIyWL&o!T3Y z5qxX3{z^zo1R>9E!F*R*xFK zZP>I?*~Yn31AtQ5F^-InvSxFX{*;J34>nPB7jXyZAN|79A0N)^xbq&U&7;Kg_vmHp z&6}K({(I-+%#ufi??IU;4Tw!v@(Ovu=*-Vm)*U(IEH);%P+ck(8u4eX;smOPwNUE` zEr_ykk_;mNMuT)(3v;2~m@6g@eW3Q9AKKBDwx#c>F^0j=?Wi!urY-L$al;txNzP$$ z(THJ;o?R#Zt+HC|A?ALhs?q3tL(|E3hkZMl=#$G6%}(AnP_6N?8Ljt}10_;TQ`ShS zSSTZ~KfF*Cn6|0FOm#*;V~m|Fb%%QKAY(#X{iMKL-P9Uj5IgD0Gj>Gj@`l9V z_RzFX4GCj38Ux#rM%ZW%Kxwt4DrZB@DUKnu@8Cc&uHdiN!Fsag`VGl}r$NMGLyB*uCk||bwc$>uGj{Drh~FsiooAraYG#@Y}3HHZ$+D4U z#b#0ORNA_Qn=JhWB(bdj$o;4%;j~l z%z0zy8!WhW!?%{*fF@4UH<*ob`Qz_D3Mu~;ONkNf8p?tI0X2M^R{HqlLA4 zua~7I&3Xm>R2t=(97?hcdpCQTneIHD@|&*T-33 z?-NpQaz1$zf7+pSMU_*#W7cKKS07^0IqWudOeWN|>6Op3>B?}}6)$q3v#)lN@s2G| zo)(e;*!+#}+bDkZ{`RV?@Zj^`6Tyo5+T-e=jN!z17M1a=$F!~_1Rxwa$C_(#OA7&+ zOktKNORr+4G?_R7j;k#1UbfA1y9r{ubTf$p-dL&9^Ufmn;YamMJiieRL2~mTR-AdU-%;ZYh9jtoF;^JO zQ<~Xo^Ls;~M6Tw}yT}7*OmWo9qkI00oMB-f{9>`4=4wFJpKAy;0}KYhmB;KZHw4>Y zvpZ^tAkDJ!j==(!dWM8P(15PJ2Uifpn(d-Z25PfxbGHf$bmS+Naf-;f1lO*}v=blrlAeUF?&&i~~bk~IC~6b7e;{~qy-^ikb@boh)oVsqf{ zB2U9KFTIEVmf=8l*T3q0#$x+Vxt#r$OB#eY{grRIe1`a+4midBT`r~U%^m(Bo2hD> z@+eBEdf{zwy^f7AP@W=68^Lt78kFib;I%?zNK&2;t|x-wEiBWIsHye0>ly^U?E6WQ z2avByqkd(Alxb5z|uFDPg&&9KE_VwUI>I@%fU_j;>R=$rLOALZbQdB&xF~S2@Ue z+<9>|oc>c}VZeCH@TPVrVGf!;r4nh6>19vL1fI$_u4`|Tr8?FDoi?5CikMhdTWb5t zHHl1c5)Y1W7dO`ErhHi8?}mf5-rF=SHZxG3q1CcF#Ia|06`ma^t(Mrb{MSUjSo79# zySYQ`i$ygLzrfXHg7)q_WjE->eR_VR zsFHo?_DcqD_eh5~REXCogZDI2={ysWo)C9X>>Io>*T4));f^-6CioP_8AjhwD3RXU z6Kjy>$m%5bN+YW?OT1{fHg>psuxyTO$W}(_W`|d^}o9v5&W-YJYj#2CD<5kfsApk1;{FJ)4D zr4B-TYYFssDuC<%&3d~Cxw<-A8N0cf{nIthRkl-D5=8WGqf4nqOTa+-Eh;pxJWMQY z%t@vMGM)(Q+n-Qjux7JbT+))hleh05zbhx(VHvXz`C1&)+E-So z@cHQuvB#tfOKy+O7-0-dwxw)7I%v1W#AIU}XQX}KLVt7;$$-r)dvGE{wb-zd6l_$w zA(`wQT^@8Q(X;MLAU=3_>ctSQVvgyHKU%13q3K4iV6bMv$et7kh*urbylRQFA@-ZL zK_W6)9zLDtR}eva5fs4($YG~($bc2fF7yaxYXO!vc%k0CE>2WaLXDh$s2vFAFgC#0 zT@YtX*GF~GBVdiXIKyr56lwWL(L9Z)S0rTiS$nw-3pnDS-)vwC4-E6+JY+OD5vY*k zuQ@jK-yR9rk26+z`yj<%?$}>Tz9tEIEb*l?d~E0|Hjj)&X?%u;(m3a< zy_+HJd2f#XdsL8ruJaD!L#@+Xkp9-6TC2DdV1@Czq+p8@i`WL{v_|=P8r6oxbJuQ| zckXtkIOqiqQMTkGtI&ERpQxK(jwF`?e_;Ppxc+5=_otSKaY2EATA_e|IR0DVlCrlq za~82Ra&a+p5i&6`b8!*3^8EKiQ*Nq_%Az1DV7GK`4!fX0cNi7}$&yM`P?0`ZQ*gpH z1^Cz}i@rl%lE-QS>T3c^aSY)vP(aGzc$=Jx)WCgVclH(6tk=sG*ZFS&fdJr)5qngm zDba#`EwJm1*ad6)C@?#l<&Ir)3Ta4a|JJ!C9X~_z*(_w|$?nWei)^FcxEz~RKS&{3 z@T)XDjFD~6SOIX3Br|jmx%Q9j=&r*~miG=|+chMYD=A^d`trZsFu2TdLfp)p{CcqK zvpADz+wuL4z8bU_Q9HopIOAHz1R{#Y_ZvrvBY5WkZfO%bViN7R0M%p*Ch9zGG@|%9 zd(Zy6uZNxy8Rz-_2k<|~Va z@bpbY25``*Y^m3j8)N0c9n`J@v)tOw`As4qUsG_6tRW9d45LT}T*B?W?@hbC?Z)%d zrt4CEp7ICiL96ywtL=Hofq8n3-r&qScU8ujo-s_bz23tw?Pxr8e1KCQ{n>n$3;~^B zhUp63J1O{GG#%eDO&4;?yIk4eG_Iei#m7I-h08)oVA_oXNX^^7_2w7c)!Y4 zsS+K|9=^Ag`I$(-h!%x!#K~XLdl0&GD6(?o-MK7TT|(E$H0(OaTGpB5BC&-A(Fn6h zeEM#Uxf^Ss7qbq3xC3A>mBj-kvMugEx*s&$tA30p0~wGeo-stwIAtvm{DZf)Y zG96YqU4pNWs1tUvYgA;t<(u2Z*;_A(Ciq+curg9Esy}64Apfaw|MJCQ9&W3NzZEY0 zTj3c02ZeKSb#^oPzr68jH5~;MA=JMR8{fm~j;S%k6jRz%C#GRh6)B02jb#;)cXZt` zFc)vwH|eOq1|zt+y5<8u&4lbNK6&clH7c6{;qmSAP=}Laal36YV(6~!^MJ3)uCM3hV&ERKarx>- z(6CO@-ORA`M8A6V5hWL!sSGCcu=}}26A_kS+Sj;D`s)3<$(YfxqYz1JbJJO6*2x+g z2^hz8eDTU7(kD^PO4>(tP2XJc63)_{UT4v(OftG%2xDwX;qBRKCAj7Fz^IuudxSIa zO%^5%5C6Ho#<=abd7Ha1)2xzNZMuOl#UPqeuR+dQ5q%5SyIiWI)vOFHVgR4%jFDzl zne<{kK^4{8oz0;Kkyb{0dq4HYtfqr5(k}b;CSG4Lu=-U1!9Qq9x8Wu*qVgp?HfNSe z;Kzcv(*hf3Pw(O+%>A|VRZP$VDklbsjtQvujD&hEipsWBn+LdqQ=!Rtjx##>9aE>> zNsqt))JhtwjOAju8)gu@->J%Q<{)()y~rEKn>*olkINd#*dyiE&SgyTQGb#DbTC6*Btgz6)aieuVQo^rt=o#eOG@ms~=!QN;CFEFQ9;6u`S2+pK zDRZYFwub=3(dVwNupy87t$}rB-US=O`~~5)a<$4I5dO z?Ba8Z{$d7ceqs*%W>pE-S>Pcg7y}}Ya7g+rpOZ@qD&p{-gZ-sMV2{#{xn1b##(Fch zt=s}vD6&-DNCL(K$~S-#N^cx-ikcyUazggvi*)H!jcTXpT-_1=fm~}0g-`;4hQLIt zRuw@QMMz|VNhS7ITo>l)j)iiQZ-9g~A+$dNlP!;s_PtD{f~7F2NinSH;3D0UZ?eQF zRdcmuFqOExobiS##s}swZ?L1BQGS<1nNv_(Ldqt>7nylu?f)A0&=;R+*!dk_tf2l+ zc|@u2X%GKL-!z=9{-cIsT0=)xRpUFv$lM=vRPus~dleo42|jG5ex(eFFM6#&K&`1w z&*X7*%NXGCKs?Ld*zmAfSb1M%wUYd_l2uE}dTeHAKQ|EAcq|r>dw;hU$X>efJJ|^` z5*N3XearBB=Ccr3*|Es?o7s9hjb;F@86gAj!f1uU5H3iU%EzEFWaK&=(Gu;sB`zv3 z5Nb(S!%PMyKlL1WOp@M;Mow#lv5H}mV&ocIBvl-@34xixK;{|V9hw@^bQ_MgSQ~@k zoy?zQ;us{IIr0K$xP2`OPDhQQ_SEWccG1{d!v~(HQ`|z29;KtRcC$_ly(xnGh zJ;(EIS-l{sbPrkDPCg%`uUPNNivdB?qorhl@mvJX3Q}fpseJgNk`6opG^VD z55DH_$hYH1E#l$vIUF@w8ToLU%mQS0vMrsPDgdgkq^swY6;=@h0s9|CN&V+#XmdkM zEWLB9OUF|(;^O3V_$}FvoylSLOEr4@%Ii1_{dC$S6X5H7v1Wsg`3?aYv zffo<4(d(Y9&7A%!EZsBe6~o#nan?#r_`WE)wHjkscAAcY1GFCM240Vc66_4GWK}1m z`by7Sy}kic_#IUz>~d$F$pw4Wo-p!_{>(hlpr@CKxwzr2Fjsj8DrU_ zb1BEmglY;62W%to@W&L~9iy%-J1eb8}=q9g$_rQ=VjI{G{b_A zKGHE`uHs);PI+B7H}CSQi#9*ey)+{w_6CKQ3iHgd&r1+gPUkuM3NIjZ;aB(n!ie#z zZiiY7YEo^9wkJm7nbx2kTP6c&k|x@WPB5ts*PRXM@5{T+2r(dkjSx9IafU~mx2(~_ zNo(`RhVd&b`o73fqL}w8{~?7r<8AD`mKsRu6t*qx2t8_3arH{_i7|GSq8FUmO0pS} z2cc+y?Y3(dnDYRR1>Uq9z-(hZ-3@M^Jnf7lCZ|q5aGJ7G$3E%yo8UZo=dHuxRcKjL z>LEu$Er|Feb*d-*0X4tHI1R9xg|ABBEW|2#dib7;KFCRI!Y!-Zsu{}Xi3=lTFUa#e z!3kRVUulhkL TPV|}cbloZK7pF{S3KJE<*e8`!nw0hpfVQQYj~1ULye`)IKn)mAhe#b(zy);V z{FIu8HqvX3uetq~eG1~Aj1&Ljbp=Zmfe~Zf5rS7Zk2@}*9y;Gwan(Z|rI6pl%_Q)_mqTE*+a(j2PrXYrztUK&e8zRZqtZnnSZ}^ z6faG6m~uOP;^$i2EzLYo0KZ-exaXmqCE1^o8Fur@(DbNh+Lo8{)>zwiMUufEKy0aW zU+gM|!jcIKg;Ay$VkcctF{b`+V$b09k6Me1U*H(Z7D=C0ULVGBFkTPs<6{0_oV^2+ zVBxZ++hyCfZQHihW!tuG+qThV+qP|Y)zrTC#LV9N-Z|&YM65rsBEHm{PiC4P*+oi@ zKLegwYA6yNS;FQd;AFLzn(MuKu=8|>o|ofRj0wTGmv!61tv}+X$UW6%a95GQU0iPn z$(>7HCvAvmTK#3Mz_ig9NuA({!Cc4ADa@sM2tb)?lG9S4ZPBMtc^jPSrgnA&D;7P~ z``5g4XDx*k_D4k+|4|YCa}8L+<|p=<=o|hsOp~o7W4pi)@14oc;;g-1c$zTzQWDUxqAtS{q4 zHZdcD0S-<$tH`MA^GP+ygPJHEkQ9)iD?hR7Lc{ z+r@WWP~Ry?;Vc4Ov7)uJW@2`%*Q89+ZJfU6^qTyhF_Ki9^!W@QJZVb3fdN=cxDGQ$ z#RF^1v5V*_c}mV!;((AGY?0kZg`9;ro=(ved-OQuxcpnixoCXnb^GMiw~gcS9&DgQ zmIe=V%aUw$EaakNN$#V?grua$fiVgE6~}#Ie^br;84vUQFUw_$v?r8y*C(aJ*!*}M z`R9IyM>&W~Nx_0Si-is;Bbm)U+?s?FO-aEIXZ(7bUDD#bv4N{bWgfvJb2^RO{Dsmb zEV4GIfFVZ@qI`GhMLERvC*-)f6!JaHIf@I~Ym(+FveR+7e|=eMN1e;8KN%LvPt*3l zs%ZY>WeFQw8UN1&D_eEL7Wp5L>I-A%0)V8k<~UCKQ;(t%NW^anw25ME$l|6jY1dL? zJFd>jX+Z&nID>sC1ti42*M1%Hnu3ZaF7`_>8F!TMOTg*$W6^9lurbthly;UV;jd=M z&a+##8fRX$`|B=nm_3%TEB0_@(<^3&7>?ca|DNU1HwHO(HO+GJowiG;7akuq`KU_5 zU`kBMbTP1QvE=j??cY25L_aVVI=^0!~r;(3gHRPk9tf$z}%Q=w=0= zd4TVq9{~g}TSm{UqW&dd5*^!A;@C0~zJ8qEA_n%5q;=UyQ*)u-&7sk2-IJ7lzS(ZV z7s-H%NfmH-k`zY(_)rpp6oz>a?)~td52ftU#Z~3AVdogb;qU!{)R-G}EF&Z_s+b<5 zJhT>7nwB_hPL#rU`K1oVbLG(i!HT63Vq`q7LoF|KzG+tlrdA^FVYhAGmUDa74uIhr8*fK=FD?ql;bS>EI}MXoGQqZA#ZF=Xo)&6RTBKzFbF`?6cS71_ zd@H5oQuXaMXBx{8x3b`5-Ta6NRY_TnfmWV|Ejz_B!>wp4=T&3X$XKMwN{Ue5guQ8x zfoxP+qucwsH1h0GHsSB_D+2K>`_!1yfvd^sQlc11;y9A1i|0DVsFZzfA4=-_w8zli z5o_tp3VZ1~o7C#4ku=xX#w6X=;t06o*hHB2a}kabsbNf*HEai1x1l^1(rS+rr-ODd0nQH`!Fs z#^y4sdsPXN)ElR|A0qW2Var1ux)gguQf&w#ceI1MdL7>3DrA*WXN2B{In~}DO|F21 z^$sp@ud_F`#%zeUL$?@&3-}?A#UIV%CR%fG>;&8sG5Lk#d``aiGY3Kct95xx)DA9l zwuGM>JuLKbwjWDf*%J$Zr|Fo}Wci{mKd)>>DB3eraDO>)=LsLjWcjR*3w&t_mWW%n zB%Y3R7bM8dtITWw8rK13b%w$vZd{gkw?n)cYvzEwWj9UC1<5?A{#SGuLrhRalhz$H zk(={EDTHO3&=GKMv7XxQ#W{LbAc^74;m z2#~Xb%T<`oJuuzut8I(ip^x};%kni`M&8Fp7-1V6f;Y(cNql}6Nd}q%bd@G&JycfN zytrgS$tDOJS+hV8r8WH&5ZO*YxY5|>LiEH>T#4jAXl zHfmy7OfJ|MsZlpqE4hYkXA@JMjU?0vEk#Hg5@PFhK_T#ZctmjIOVn0{B1xEWxgtpa zI7)x`eLQ@EFN7Yhk2=HHY*eGSZLX8ehwKralg&=H?}rP^UoQI*0dy6s5eEQP{i%m` zg26Ea$(3yZL69IJ*dajZePw`3eG({`F;wiu2}#Nd{tO&NhjA%g_8_Gyi{cJ2)DqL9 zeY8Rt4Gw8>QDjH-H_YL$FWBXvKQr6ZWF^Vt-OHFP9{k0g4KGFg#E*TvIcHKD{5TMb|?ABftn?^o#L zdGt@FJrhW(zpIyS($zKh!5Ez7xR__pNRvcKcpw$-K@gd*G8Y)d^_U;D?pgN`W%*g4 zN>7Nx3#!s8axSbT>C`n7u`KCtq;Mo9zdyIHOD>+Bxv<6P!o#2mI7|-~hxHCG?EwS6 z7Z|8@+nfSoVRw2?#V6UA(inz6@q9NvQO#kqCAC2(>oerVDDyh#dRlBsWG21`;mV$u z$J@~jDH1i+jIXuPCF3wrZ?P^=`0LnoG`6HeyJDob8OJcCa;8ckly|uq@VuihEphEo z@MuVP@@Cj)mSk62L>w8XhRe%{D9BK!`du*6<~xh%GWkf;PoT3>6QQsn#&|NK-Qa3d z5m_h>Cx)s)Rui?C>D#)vspp7aMVy|nBbub|cNt=-7ND`0c)9_fhsaPF(n$`bfJkXs zU@jD~WjF7Owo-73Pc?ka62hRGeXhcY2q9&#Oy=nfIGQQlc7@pPMuni=%J^U50hLai z5y8$zVrt&S1=yOqVTWS;S(+BurF|KN4C2%GFn?v$O&Hf(zQyS(*z07k-1B57n|&X% z6cl2cwscbg>?ZZ69i3UZ3khL6I(e~I?So_P3Xa6|32Ow*yq=|C(e96B))vL$iksMW z`%;9!s}FTWvq6X98=klxIc1-u}1dSbAqp@E;$8|CrtV=~!oxrT_o~wof!%|f&CczSYl6GCkoH#ls$S%jHB0k_o zbX!}7?qsyY)NX!#y0a%rhBtFjYV`;$pxqwBwC0Fw$>Np8DW))-zjmxivGCBN-tT{- zDL$$R`YklMROKgpE~|)Di_q?pKuxC9?8VnjFKhZ_WTG((3!BZn@6rh^S)NUMxdh2# zPo6Ey*r@a2UT*`*LPR%gWqD^X#x}zrVtTo2z?5sLr4aB@A6*&k_6sHp>n)0^&&93X zgzB&@Fp1u@Z>`lEm*kIKOOxFr*Wkw(s9x+eDEBB@wHHLg!%^_JEIr=|Sw>C2qhFw_ zT=okiEUV}Fc1W%H2lgl7`ID%ZfZi5~l_l)E=If12llI_y+zY7W#rBhEHvyfwHxn;| z=LHYMgwE$XazNO8pP0PZH7mE|1ZO?ghxi+{ znkW2#&*QCaoHys??^lHx`Ab18`y%Baa@{kbZNB#PXt@O;ycopp>~$6F;ensx<{jMF zVcR$4``(^9CA4}+K_%A^RUZTd*ZCC?XH^P90IAdAca8+6g3NN}lv@7tWgCFVWP#I2 z^NT#{)6b#!G%@$Zlkis_1Y-acps6UCBkqcV;{16IWj+4XtQ8R;0zGp2&?hltVmxjB zDSmSL*j?=Fh_W1UjXLTwT|pY5nn`j4v01(YwCZjqkzL$d6)xIboQ} zncD*5x0-I%6lFbu(IjChAV3J;*3Xs%(dRMa@#A9IwPx*wwOQ{4DEW}(jf%3acreLh zZ#f)`I{Z{L)O0_WgTj?TDg%;fSyd!5P4Yqi_KhPUd|y^SFi}d}#o5BXh%UvQuL_Q? zDC{`lWY!eqgx0k`ab7#NOzKNHj($*;MV@?Wk;11b^O8!z$kNB}bKd~B+^(n)iMsEX zrU@Ey-`JBHfP%#tt4hloAcB_YJLU{OxS^W9ez_sk?viAkRDYqWrP`zN4RCagym@O6 z!f5w}zC!T!%iWnee1+s5;JuQ3MOU^3bL@?56ktLb@NAX3<TV*(I`W3>K;ZmAgV07GyA!j=#0xLIBeRF~MX=q~lb!xTYG#k|ROh$;B;febbGNk1 zABiGHP9=Udid-KNz61lRHJ!ApG+E5%Coi-JQ4h@I2P_X^hfBWSWAn<{VDOC93B%Qm zZ5Gw?z~WZs$+Ku5Rfbds3RC*aby4E!RMlYGgLZ4XE0E;~;Kkf>pARWTIbl)RN2VD7 zwBD^e$=XBe<;5rt-wQ#R8^4CF%PTVfqg`D5Xczy@3iDr> z;OGP?xgSbs1$bQ1LqgJiXSBa$EjZ46yH0oW`S|_?{SE6VK}^3Mz&@PN6xI40 zFwr1g(g0KKV019v*z5_q)xceIscZ#fI7P3$S#rQ`N>D@C<+4J>O_E?`^+5?0-QdM) zyFxWgk0+>)WWD5jA833w>&zh@Rs0`9cA$RbB#&~Zvh5FO1zX!^zd5S z_NKjQBUV%q9rgUr(e=Ha3ryRUQ9^_cs1RWjrIn}4k{AXLZwQYBW}-PfjjT)6(I#C2 zTL^@A0Es7H>1+u;@(ZGqGvgKI zNWy%-1$hL8y~K76Jbi%818s4HB)tVL(Lc2tA_x64gS@Z~+5({?WE$4wStD`Dd#r59 zKX4EsfHLT`r2mZcr(?3QiCZ)LZkt$mNFap4;m6pGAm;5!rn{25T*%D@@*>yd1j{J- z8cZ^96ZSqw?==MU6hxxfL%kBI+6P$n8WkDO5afFYmnoQ}UW1&n!!A68d9OCthtixC zjIt;iMSS6pr87ImaYwvrS28I_ud5Y4Y42YEJ55({<9$M42*$g1B>YDCnT8KNTlS~H zEEMoCR%|^bQKpw@iAd$Wf~nY%sR~eyI}&Wr=1H#zc$Sv* z7x=LadFcNNo0m4XF_v|~BR-1TO3t#ztEx5Kx2{1%cF(Df@!{E-DMN7RzGjbU)|!bSl)PW*KUQC>-M3vgaIz+7)4KAC^RZghCd&+8`O`d*=i`OdLz2O!DrO5;%j z7Pde80Y(P)BBh-<_W+Y}j*o1S-X46Hnn90JETydh-0$<#mi0xv2Ra!d1DoxnH);Rm zVP3+f9oW4jxOkAqx5d59YB=InzPf!HSx9NuSz;F|14aCZJ&Lz1*A%ayl!-hL96p5< zv-uLMYH=d~QqUkT?k_Z!GyBdUq>zXakdkd=cEz^g2|F7e3Jc8#?UdvPTp*~49LmV6 zWs1#U87hDeI**kt`l9oq`Bs=8AvISH7k6&4&m!*XYL?mWB|4YFE+cy^(V>EyDoow) z+WZ9)orS1n7^FfEI=(m-?b1($>p{B6f6V4y+l<^;lTOKCpSkq`rMzWL)Zz-0hG@DI z8l&zZEVevjWN&>-ANgyWV4zCFD5lAl=yD|(x0vt2a9Rdj%4;M>>YZDt?zCm;HURm) zSD4CdzuAe*_5A>ZA411(y}n*6CQ#l}H(U_`11QUsQ>R+yr9&0VX=y|VfGSFyIeVP; zGo=jE_PKTD1DxQvqM3w8+%e}!W`}@+RM~*xC<@TRHb}QcEb+a75qtpET=u|)V)wqL z7~BI-(L=&?35O8A5)VWP-WW@7=3f&e)5@fAiA8 zQc*KV^SW}2_54Q`P+EnEFc;!IBTV@Fkz73KtCpEQSF$xLfHSo-=xtm2sR@x!1HRhuQ#O z_aJ$8ne68)HNo>}BRc(wfnR9f;4;XTKsM4SviQD&g*`cT{mvq-Avnz#Wd zI8U(T3s7U*>d0phL%R~QLO@zd5#+NmI&*>;FkJ{s&_fqT8aCQdy&3 zM;SKW91M7*2u~%bsI&;a7o65+jfURvvq}Or__e5Ol#iY_?smTsLi8YzuNSX4XH8Hl z@93HFWHQ|`{f5iY<@;w=467GE=bfNXPLxm30Ad2YH&30AF@*kd1iS!I^hXRqH@%g; z$8N=AXzS=mMc-sH5j8avzt8&Wijz58E=XY8^LJOobj$An#l-UfEE-I27hGrWZ zD3Ru3`Fn~9X?_P1k?v2sobcIwEK|c9fxbVGoZIney9buekkrv z{ach8)09Ezv_mcjQjScK*85Lw`kHsAW@JK@*Q;*fOtV+0_<14Km=mMZ_E#q4`hk56 zJe>js=1OtZ&4wnLcgYS4e*ulol*H-${3F!?I>if*^%xSwQtK@#v(Q-H<44)kiEBcM z?$YKM7yX2&qS6zvRW?NndAZ6JhHW9BYRNf(Xfr|yJv(hK=p2{%J*VHTNN%leZs_Dq z7xLMTAy{Vl;Fz4i5o4=VZRN;ySax`MCjCS~ROikjBx;ML@5(p4x?tQDbc_UGhd^zG zJ_OuznoB#rzc_KwWUnW2GgSWAIsFNb+u&VS*)eTc;%tFlRYMmJDC5& z{r_85TC8II13SX|plZgX2uTVw;X_6!>OzG^wD_e+HjiftioY5-Y|bEWjC>|OxQ|FqS#awgCYQA5@! zpHVHX$?#;DQmoq@p>q#>QdG^y=3W>L2#!kgaHuhtb z4Z?JHB-XEER19WqFm(4hhnBLrT}jNx4W`<}OS=js!J)@|;d1jYdMP!oS%#r^ zenxA%VBx$Ux(Bzi3p5VMg-htVSNgQ<5<*d!fq_D<|1=h^uO%9xdsNUT)BM(zIW*%r z#8`(~`B}nfD-E5^`n{j{eXBX=2%Xa`JoogPy7*e-lUEt0@2`Iwaz(Y+NNH0TN$`Y6 zLwVVyVh`quF?<1~ImC6S+=X^4&`X%2{4)Y3!Vg_Z$!j1#L{_CBdvV1a5+*KPkhk$R zIKE8Frri-+;gF=WYid{c8JN#NJ8qlzY)rgp;=N?!LlVp#Ejwwi#sp10GJ9zbVso;E z(;>t?wfqv6Ire8>nr-Ugz_?AX*wj(TsB~*VT9*;qGS{FYO`dy-Qflfh>lN6aHPqHI zbOV%)s#S%|{hnf>+=H;%iQ)b1>ipMQ(Fi4_WIS$X8950imKjfoO+RkN5duF^boW5% z?*UV@RcsEC0|r21Fg7u{IVb3&&P^9NObGZG#2A7AdrhglRMq!!Q9C@iUldOW5TwPS zZp7KJyY@q85Z$RV%qBClT^LZ<1jP85vVEGp0L-|0h0(2^+{gABr|LCjGI7&0mQ*oERO zk_YS(0`t=1dPu(iHXE`nf@-=1@avcTPo5?4-#4@WeX3QgykYYLdhleXwb{$i$!n6Q zCd?o2<4d=TqW}~^Do`Y-;N~Ug(OF$ucO+Y?WwIdV1}A|J0_~^A3Ql5{<%LHm5_`Is zc$-Y8cfW4D%;^29>T{&`pD<- zb8DO5vWH?|r(2K?Hc-mot^B^+pZ>ubb)*f}L@;8awP;oA4h>LLuvpNXnbDVBM$qQp zW1EfB7&<=F$aKC%PWXc|^3~ZUntYZG1;q$(?U7L%JqH&2#XCH5{hKjRV<4Dl41I+t zzI-yd5rsG8yq8@A6AiSk_R5FB(J7t2Nl$qb*c(3&QATrvq@KA&GLg~DoVsFv>pJ@N zhhj5{xIl_D;8HVFys(x~WPFDYL!0<-GO1|je(%?25J+-V96u@0+v15ZbzKj573FLek^7?Q*?4sTbqu@_s0j!?&pO3X`eOB9sIf-S(uHqWgAui z-isSU;hqmX0QYZ(3BtY*$0{Bp20X(0-gP40q{UlxA;|$G|Hiij9T%7lnT!%A;NeCt z+45bC7>o(Dp9b{;<#-x1P3z&HqHiWCuxLbamx4AM_QWX4(RwLP`>^D^GY-{ByMqD_ zk~nMcWDanEm-D1X%h5E{;jl%1^?ZtpQ2$>V1=@lG?5|nV#v{q&#DUsb&wksB#nvnk71xQIBJe7}@{rTPm1;$FtH3 z=Vjm$gm;A+#C~(DS|gC;%qDq~^k{DqkHIXS??Dmd@gyDOu68EQ!$J!I@zl0gH9G9g zRgp{!f`7Nao}%2y_MN#N;&J_6DBB}QHvcE*f{`(Fq=7cVxV(EaXrp)LK6oAm9^fUi1cX#C0=Fnq}izC>4YxFbG zDbbo-C7_pC=}qz}f$$^NIx8vcTn`-H*;n+Kkkh5mM?s8^Dn4&QBC#!D6vcYv9^@6Y zD!&~Hkl#FLc#!-$i?*6aU`tcjyl;)HVi4aM zoC3#Xyt_u+ZLu`yrm*i{I%1da$mh_(98x`qVTJ&XZc!pd$P;f7D}2-oZT<>FjL{5H zNRXBa(q(4z$R{!p%(CWLgi~@U3`ZBs|JI`>!ls$n`tjA}KfYSz|IF_GGk^X6W=JhO zo{#JRdgQO51%exu9&=&CKTsl(L}H{5yhIY6%}q+fVHeQ`50X!c1XeU&RPJAe;WeP} zc~WwjYZFtK+;meDn`fWT&v%$!AU9Z2dcBZnDr4;-7NQ!iHh&PTNLHJ5bp!QfZRcRv z`M41+ZHevhq2s=uRc1*kOA@YhROpMo9?4D&wRpVYu9c1W`rEe~$8Y3sQXz90QpH-P zCX0jM3R?#CnT4=~3|J#VT@yS`!6W>TNMBDp8%+n5|^7?%FaI{d=6-dZAS&rBg58cu63sd z7*wnkv=(JdRW`Xa`KE@?+4{qWCnMZv@3owsgp1Ha8RlE-?1h8!80VjJqtr%lVt62g zXXiSg%O+`Dq%%!Xe^V4ccVWzvu%jV_8e4F(q`TH|w<}`(^uw>OfVT`Y%pWAgsp5Dc zQV-o5SVw7R&)stSx`uxR%W;@Q93n>$W7XNEdfn(}RE-m0GPV6W%m^R9e@%@s2q8Zz zt5^~1>+(jPx^IEI$bRzqRe1+;(o-lr^J^$EsPZw;Jqm^UZ(yB=wEB?o}z{iiYMV)Y9(Y!$?BowRh^3|vP3FhmyHM16dI zL_7ooX!tN;e&hf|r^YF1Ae_+jF=@FVvxdr=>y8^8J**XH@1a*sH3Rg7U7}74ZM@FP zlh-~+Zqt`Uy-Bd|U$MBA9iAqbi~!28n_4d}Dq9tLDqH8re{E&E0e%DVrqELg;ZqhO z)Dsr$b6+OL#q9|spoIh_MG;!o>-AqTB3m+$4#e6+fJK<~1cF=}o#VrW5`PA{`;13+ zrrp`#UjHmF#*nh7qq{b2=A#=%{S+Lw*qj-lb4O3Tqx#hBwFsk#ZLN(P8 z`C~;O!aBu8Sn#5FZpN&;wQWZf0uM*45^53#eaCUD!JfUor__{KO8~1*WDtnvpB(~O zk`fz|YxpsmE2ZOcZYi)KU6|k|qXwD+*hIiN*I>OPgD^KzYqM>K$*vkp|LAY#6%Js67qGLV1^QL{YAY67=StlG3x&mA-kc(cah-!8?oXFgPM1T_~ z65=2;2K;>r+@-tjCAz(Sz3ahSU62{GRl6cxgE4<)`X*jG`FB5COh_8dx(a>+jv#kM z96-9{%k>e@Lzcv)*a`MYWFe|E=us-}9qBVDOy(sj(@$M@hk%teQn=yRf@>$W4#jQy z14UbHW$A&aB^tku$ zLE{2W-0PC1JX}$0XRN1H>T7{q89(^d$VG0n>ILD^iN zs11qeBrHN>1wEh2OXu~w8*1~lsX<|o9>n0exihXucWNZ^f&C)FB?AWS$-U3&OfNIp za%o|r3!b`$N#;O&(FH4 zq(;CAgH7JC1lMAE5p616GlxS7t8h)IVUg9mD@S!DFRtmAVx6XR{_lR}b(umd8#W|Q zC>wl>@SzZ_xq%&Y;XC_&yVc#Akmw5M9a%^<|b#MsVyRG`%`Eonnl^%0}!H6yG6WKTVQW@o;Q zD!RSk%;UQZW>o9!kU!rEyY_CCmNA9Q(GAc#vQ7k3k$9o8r7H^d$T^1Uf{{=qcKU&p z^CFm(mKCM-O}Ry8I_$xb^KEIUL&-JF>a`zH<@44IS%VFNhgndFHGZPU+z}4kAxDq? ztuSJvhbN;`sSM&>oX$54=Np%&#wmLmVj~dn6La>P(ug3BoA`F1;BnS%5xZw(yTGmL z6Ylm2Sucp+YZ>RvDXw>I1^$24-Gj~dJz6}M%&Tl}l|82O>ic!h`|}6vWRyM9Br4*n zqLY(zAX~pDgc92p{ryIa3F}-8Fe^W%PB7S4IPzdtXH_+3RXOruas)W!%$0LRVgBL< z|FkE(1C=S_)0<-kh@q~VNjDWSog4R3WDB+-UTh?_c9BW$n7tkw6l2)xBXk9q=Q_oB zcn3kff~H>6C{LLxV!n~gat+~n`gy&g17AVqz|mqL=w!nTyznLO!quZ@1`)joXqg8b zp^Q&W=37Dmdo?^+vC10P__K#%^AmV*=Xt{5LB>PB38a%EFW(lSb26(uV&?@(Y7CKw z2?~f4Fowgj2Ots-vTAE-H{yne2X0fW*&|pMRu}n#C&%EiAgp>`fNKh> znK5wQV)Yq$8@S@|x!AS9pDc-+*sX6)$y%5+EMFp|_sB0T<`p zGTl`VwfLVNa%(jkx|xgQol5DW@3N>;5cG(!t;qqDfFz#L5;Y)0(Gs65EU(|<>H}WRjt;B zu(IY%YisK(6D`Z;r54rV=FDQ%N}iVg#zankJ z4`mwOqQZ8*UeC~eg4j~MRtEfOrw8yw8{!kr^yR#ZG5Z@c_pV3V!$loIRPf_jB3-k~ zkYyc>Y?p?po`y|{fsV3u|r2rX>nepp%0ghkwhh@rUiocg${0zkCmoExRn z9B{@d;2bfUOo^d3bMU5YhNLVS+Q>c5Hu93WY=$foHuHjr2(wiF8g12}6l}(TS_Tz8 z_DP;QY{pHV0a!A7nQ|AoqkMZLw{l-F|3M!@FeM77Zaxxng<_dzJ_sZY@gXZKjkTU^ zUL%AdmSCT_GL-0wxqn*D6w!o3^a0s6l;+=!$7kGJ)TM!-`(&Oyc{ORM56W%;8pN|l zut&+Qlh}~{r6Q3FoqX## zELQVA+HAd}>`S=!Lg%2%{RHQrtdKZ4GUTd9uqT!JYgnGm5@+C7iM{bSHK?kEejf!k zyklXuH=>{eF#fFqC?d-zS)MAe?svv-)o`y*RNp~7oq?@>P1nFv;WRBPQ?hoMYQNL4 zMAFH|3wU20jFqgdqjwnp#T;H-Q<(EOF$uzIxMx;%8!Rh-hfwPci_j49+tH^8*r4*W zXarL6o9ekbzSZPkvsn~=Jt4$V0d`(iUL};0@_)>dmubMf8(Tywq3x>DbTAZsh(V&Q zXGsUI!?@LXkHd3cmi6lElEfG=9MaZPw?8gnZn_ST3d zlhTxUe-3YKFp1=DmmM-J@%b$brE8K(r$kv<)l4RZ@qFEF{nb&1U4Rv<5vBs-)He|s z-mz}L33sS!tvzede~c|;LX!C;QfGC0$IA16YZkZS@rIef?b6~VaLlNTy$9Psh`bM- zWtQ%4a$Av{2m?M`L}ay=S$8IuPL0b5*ybnirx-*(CU&#N7?3hmD#$JFvP}bqZVa@$I1oY{zhF%TFrTktrbI*Xo?R<>a`FLRsQLv7Dx^Sjeqtxr&_Zy~ zH&5-E>{3E96rNGN&=Ideij79rEP4bE->8-);IkXhLjE&C5cn z%W9FUSsg#)@FF2rJ^HaH8bcoIm)3!q+n$P21b7gWC|fTHQfkWKZvj$Oa2uuv^h7x& z{+s0~Yw*1gg<Z3tz#ETZS{o}%7VNUV8a&nyAVxkv#y@j!6 z5xt8QoaSEfA%iN2?!N>vgQRl76g#$h8*I2V@6Uckpoz`QzvXbspWLt)LkBc(z9q09 z2Mh-Nm+|(+tsHP~9&N8IZz>8?AQaa+qMS49QSc@<7E+2jDqaM-$(h)Kv~#x+E(opg ziiv{vrazZ!j`pPis$|w*jW4~WbN`x*#o^qOH-{ML+t-o64sN=P=%DPw2g@^b2{EDo zI3Y=f`rwxpAn8!j`l%I*+*Udf(x}!$_yo%;mWNoVaHgk}DU(Ggohk>Pt9W7O%G-0$ zs+g5a!Yr04BC$|5Nf#eA1+W2}ZH=&~BSC^>91`hb!8Qb<6ctdiESOVf)B05_my59L zkVGssi54@VbFf0eT8ad!Ca;%e?_w-N{Q4lkT@p#pb|H5v5i~7t%9&O*2g(*oGsaU3 zm+=cCqzRI6=~FD66``~)*6n8~7juy^{PL5_0y08Fv6eT- z(xC=@M~r!kW)TrhEP&~f+EhO*M`Ba%^A-6V38F>0a%kHE4Q{D)!eF@{(JvICK8I6o zdGGWD{F421twmOXgaG$oy>7#xi}|iWQwfGiSt<32%(GqT_Uj`=R&^m5h;-DA%re^c zsS?k^pjlcymKqCYpgBIPh=vNuKxMngwuS&1sa;aWXE?$Z{XG43Gr#GeZMI9dJJfdB zBqMJjDrd5@g4;5BF_V|Oh1W`Kk^P*pM7;8wT}tIbVG5s2_DocFy>+6;+=N&5%e)jl zV7^!^I=s{17lzd3^hWmPQW^c9#TRbg_h1GZ_`N~-tVK`f5tA*fY8sBrRQ8OS72GTB ztY7P;#b>2O=}S>67^WY`GZHRid{_BwuBLg>9)noVFQaZKSEKj&(;f~>a1!(ZqIzk>>45t+0X99_c!-P{nnrgy6|Hc~AVqTW9Z%J(D zoh%A{?t{uMoWTWtd{!7?yRLh8nNQO}U#U5HIUIr)NX4ZRsnO*A4Pa7gS zFO*>u!TPrIZ8G)yYf$675#W~+=iZ4=&)*T8qE8XjX@H8qstknAyb-vMm<3C3jl#kW zCRujZDOwD3IrP(rS$^=O9YZm${l-c(xbMk6VQ|D2-pXoAD1F)%S3dF9b0H@+u^@8) z5X#c~D^L$T+iY{U189Z&5VS#L;r~0Mip~de-oxWDPmZ?fo$d5xbd$4gAbhCB5=o31 zSub>z=IN?slH0P8*dYfV@;9oRqyX-8pJ-O(gB>sPp#df5?hzaBFO69R^5>TOoR`M? zaV=r@ZhqZTJFRUxM~p*FoQ5}8bTyA(8pWY;-Cw^Po(WzM)`$j+BWruT4)ZX1yh<^z z>Gi$W z7Sh~)B@Q-@eb`9@4qLIeUH(Stvb*0!z0K=z=RaXc0-^SX>AZ;_NE^8sAG`zZbagDd z>_yqEqpD|u8^yW5dSF^#NUyPsL` zsBKE(m~HKltv}%`OW`Z#UXZ3WEE-G26Xw1~z7^Tts-I#usRy!>6-w{h?Kb1RZCX}sUQ}&rRc-34 zURz&(;MSB@AyB#^*~ltfFT6&*d2jtL8MDYAgow?zKpPfs@TAWySB7HPD$WU1@0D7i zw%P$9F@XC|VcpiI#inylQvW{pwSe|Fhq5DzKl2sByc;@AwX zpK%<0k&`DIMq1o|%y(6EI9-BH%d=2IL`ES>mE0|2M3x8HR1W8G0<6>yCTW7FX#%fS zX6grS#&RtsF7vdj9s4N(!hhR4_MTkztM?qHBzry|7|CgH#LgxF?+VVv$p#BbG32D! zi&M7>`opN#Y^7MTT@T=L@O9jYcu92hIXD1%^ z;<|16_hUHcI@RSqRAe(gmBV^n^5ZF|kJ!mmKCr_UQ!0%UdHs@7x&l>CzZOVlxQyr| zyDb9#LhfM|hSPtB#|Q~6y>mX>!{Xk8o*Gbnp5=mu+v#sD4mG{SSr}+93H4eC#6AoO z%Js_Uur}r6qED$2zfZP(8*lYG((1Xt)A5pf_dwlY^UgMXr>ye|kF%C`c0u9l1buU| zPG|(2(C|O1>UB`{!`tP!&Lr`frqAZFE@|eR(PdsbY;(-%6NEFZGG=M#?z|duAZkCt z7?Z5R;TfZ#maD;0E2_ddQ-u}H`F-kwJdcwm;hG=havzFv@sEu|pQzJH~?Y8cdHN7IFKDH5= z(y#JS-*Jh*9A<0byoaGZN>X1|b<}UzZE+OPF1256EX6S zviB(2QwaU%(h=p)!4H=IqU?1tvo(^iarq%f{;?hFpX*+AZzp6ml<#ih%=9g3vkoT; z2w^l!f;E{{L~=~>Sz=&JaAXK!0V-J+GW}B%*G?`e2*u9=$wsRmSx*_Z*GrAzB{*_%(b;GqkH#t$DqV)uA8lo&Ofd<-Y?x-Bj29S2*0Fm zD}r7;>JY(*H;)AvVB7laW}{#B{(e3I;U@5o7Q?mg4H58qdSdWK#oC?G<8>B7yY7bt z#Y(=W1;u)rozmLeLe$(z@VYAxgTh@8m$vO8@H$Ke${jFmzT?*TZU!P9Uz+l~VqYIM z=DH?2rTIQS#3tH!`Ty}j&`Y>8hPxh6BhI?dLj^PPO6I#cd4{t)vt;bi4FR)H^2JWP zgSkE+z$kq?#K3@?cqK&xGlKSr>k~o@A%>PhkGD(dYi?{kzjHeX%s~%9Kkr|*t44V=w!ZbedOdR!K%cF zu(aU9kYwjFSg09knli6xl(~wS4{PPYRV~c6P&~O={vBSgMOG?Bs$M--K+}>s3B!Y{ zReFQuL$^~|>QqRvY#JJn-)!r z%I3J0I7@p=P?q{Eo5cbkS&U9=q{fEBr`)u*+o~WywxFMbzMfnAjkuAO^n@KQk4wOW zdv|@EWHJkCWk|m8aK>5V&P^TCuBtjkqh0qyWP?Gu;*$c>la-ScSg2ntiN^ORmhw0^ zmW)8ttjR!X{K9P%R=+e@rhZQxh)A6ZiXrd3v=iPC+alEx<2a#Nh%!c5Q?TBvDlLSAB4SQlxYHzjt*B3BHORi8-cvl-R~ghrie zFFVlAAT7}D00AU!p9_-n))mC-Rx>9V=k)1u}jVBu|G03q!kfJJ;kLl*Oqp;i^@vu)gIV(^iE^<63ZDe6RGap z>zGW5J{pxVEV0vejp&eJDF@rXF-#xLL7x*OYoaQ7C>#XJxZKu+3 z6_irOr%fwuLr0K?yIXx8u8Nt83?I;Sc$&2qER)CIEbpjoFV>4fPLua{3dXlIX;5U( zAQZ%9Y2>Zp8hF~0gw+fj#v&>dn5Ld=FY>3wV@gb^+j6)SOOPoLDkJBmPkak5nVQv! zTcQd)3r&y?M3lJqD`qTg0$VX=*E}ny3AdA_D}6TJ5ZBB5)tx)ANVf2An%Js7t{qGT z*j*5h@4M+)d?ln^{eGIHm8zdM|Nh|31%|v;{=H&#`x0l(n(Vo(=}lSC25% z4pUKwL946>U0qa1@+V{-nyP~mERFJauWie9mdYpl4hgm;cvzFQtNO_YY9gc$F6`$( zzD5_Ez}Gel9wB{um_t$zM+~mdARbv7i}^$7o9>R)s;O>u68Eh+;5b?$*r9;_HZ3s~ zFNGr<4Pk-Rngnv7h6#0n>ZmR_d)EI;`w@tIn!gfm1%xsFRlL5I7szcUL5;jlAS0Zg z>IjM14U=BLx@@_1(XtzeYk0k~0qGjq!5z)EadU@woU7WT$X~}sma~=wYKmH&wg;;V z7$NkTzoeMKnZUY}(z3)2PKKt&8K%Ffo4FrU0repTR5Tws2vy5BS7o8-g8SYvMPrKO zi#2e{{Cff{?!YonnPD@|FE7YVY^1)<8N5j?9RF34@({X~J*3PAXmtQ7eQM`qmMxG& zQe25>TZIez2O#7Pn}IunFs z=m^9Dd4^YV7&Qf6AmkTO$fw6Sak;X2b`lbiLz7*6+mXvZaYe*iQ9|qyL+mkJ4ADgF zaa}jaSEC}EL4Nso--8sSd%i~_K-G|NjUwzrnD(m3Lj=i4t{8;Lni+GA3nEgENSg5< z*MZWmYiqxfUTJdBmCl+%gcDW7i8cQHXTer81`4t2Ko3CJVLST7nCo_4!p)G*(2#62 zp}rqBfpyic9LjVTZ#3{A9i<$rKMPdB7qTgkSl48^lH=@PmQ4xaxLYma^A4Tn3-D-; z#19~spC)%0v2*1Zo#jt7rnM+ca%Hi8a$#~tH0uJ_s+*IT8dA*s))_|Rb(2TGE!H0! zpss|{N{YhoHp4uK-?l}691GKMM+L77p)F55U|W`ufOIvzb?kv3p^1&_+wEC}gS_7| z3Dp-83B^W0F{`O7X7no-FBmbIpZi;kj#9InOrAE&Kh@L9-chC6^u0`PRv7YQvSXu8 zs_Rex24d{`MD$LLy9dDfqfvy@Dfo0pbKO8*4OO8J@7!YB#C`APdFb3G;#^3%*3+&1 zypiu265JxvA}9`@Mfware|`Up1MDBEr8t{YjPc_DYxt2{|Gm_bHLx);{`Z-T{}kI( zlkzFI$d5kO*A}xp4PYC|Des|R94#O+g2t~K3=>$cU&>a3L-Z+f|P_3E29yT!Bm_4#}b=kH-H=73a37{1>U%%%W*o4SMgY9le& z80^;FL1>^dm>KK>aZO@P|3H;$au(8Aa!E-NLy+)YnN8VPkQ{gDgGqr$#}J(M*l1fr z4_#6VD~HDz%t}ca0e0`Hu~Cx-ndy;_3~iuBK{;Arc-Fo1!epFt!V>!Gyk3>aKjC zBQkC6g=|Jy61%p^;M!U#c9=CyRM_G;Ya@10H6DM?+W`yE8ujapt$P${%S5Ia)Xa={ z)|eBxJ)u(9NRPO#x`XWekg1Fly|Gs~*wObYYJaKwA{{)xmoSYUx~)65Ok=8oBEv+0znkGDta6#u>Z?5LW>dPFpF3V?T}#{Ros{<2%CF-~p%# zgMpfiwa(Zc+IGvi{n-y=hiY_yFIixCE)HO>;;)Igo_xf*!x_V7sV*!)r@#3dAT`fD zP=MVM)Gq86m^jRD0$>aT?jiWctM&PZZm@7vHxuVAvBtd)eC%Hr5NTB*XEQgf!qcvM_7VPA#u`B zSD5S;n+`mDujEGK1@1q(dH+m80hPx#-2S+}8h>10LjUctM&7{j=WF{(ClRoQcaRa!2rBv))FuhdMYEEMPWphvXcC$T2-IGxa%bmtfx+lpPe!a!+isOskCHp3W7?Rz({0T-Gki(_-xqU#|V0Z7&RnJiOd@ zZ~4D?5XwgAUgSmvlj_`3Zd!spe`~^BOS2@h#5S}isCoY| zKZ30pxieM*AV}tv7g4OX`%sAyS_OLurd>qv2Z5V`3elm<1CYpUDZL$%>-4(LGD20?O%ihZ+ig;qq5#JO+Y zwrO$|)?h%|vW7n@d7wZuZ6O>(KL_m^J5iTR6~V72GM8@0_}8A_{bFBcygQe?ovj-u zvUre3x3r!6&~mN0y;e05#ymPj(t4{`35uXpq5TPXKQl8zRN}ufDSx=K$6W+Vw~Jt^qW1Elf08GsdB$maFr}d1v7zxD z%UBh{Z-9p8z>^c&kuYWvVfv&D}pQ`o|&JhFCPA7-^rCsVv=?tJAZ@7 z8wDXw7yu+Y8k~NVV5K z1zXwgs|5)KmX$m>4O(GELBIC`olJQ=y18r4zTu$%&!V~n3 zx^_guNjDYOaTrT^kB(q%&T0=L7J53<$V?xJj{rQ9?v~dCJA&zEzJ-KRzIJ&EJ5!m^ zLb*z*aVw!QkP6KRtq`7a!nLk3H8z*6B7oELZAjKCDPhQ?g)NBjX`flwkKZ0qofBP1N>^4Y0b{NJl`=zG zBK}$KxIgfs|33Ud$=SfjO3A|0M8)3N;6LI8mF?^n_|d;{oR#abj5wEM zwn8}z`YA^-kbeIbWY!q`0oc6Una5o=%PX#nysDDgN-^I8y%a>dfw?v&bNI}kJIP%? zAA4NY^7;CH!sdr+f?6OuZ%*L{2x6+)>xshst+{5U;gbFx>Z+ZfVd=^0vhhQp=asM=AizUZ-v67yRP*Y(JJ(<=`?_}NxBht< zziYw}TeP<@U+(MRfFPmsme)iQtZ%}KBaoR3F?KfE5QR#<(Z z4^jn6S$_71QGX91z~dE3SUyq%8+5ZpvzyJ{BaNwy$Cba{hoVRUiBS8=ALRYPh`5$^ zT(^530|w<28t<7D8`u~QYu~br;BH?du?BvXkHTDtT5LK%qzY(xDj!)K~aq=MaP1YW% z4LEQ-CNth8B%gHK;~uKnvBWd5qY_#!o-@?9v_4Q6Ba-=F+5l}5TL-6fjJfj+mwxoaZoI`?sDs2G!0apZB0?u_dxI z!N-~+aXZ^r^u=x>GQeKYNmG1Ns*}(ah1c!SJR}NEa9C-rRB|1c^AdU!b@p|?OTZ6~ z3@F>-lRZgdPdN#1N?aDG?ROlsB~py*M09}1iqk$C(NlQww3MqvmrZqBIvo8nc^gxL zX*#-JS+uH1Cy!b>44Yaq(4&$12&k?CFo>wFkqsfrM|s+ zLbu}$J-S_Oan@AY5Qno=7XPZcq!jrRbYQo#e2x_{7`GqDZ<`{Q+1X%myk%R^n=`); zZl4^GTG-(WRY}YPATs|V`UXy=Ud#k61GtE(1^065eKMh8~jZYJ*v1TxY{ zfb+G>{N{Z8f=Q&o{NNC`X?Wlkg5VGY0`4=nkJDjwTbw3{jovf2UfXfU9y?AuPM<4& z+b{HN$RqWXzPYGF8Tc#qs?c%~dr1V|ka@8C+3`6@jZP$Mi-NCAn7rp)Z4C_tdl)e1 zn7JzU_$H>(8`(2tF~5IUJ~1QF9CV=)8?6gbA{)y2*lPB3Qg${af^7E0IZ_))klvp_ zP>@R%-jNGDi>KMI<_ultnhX2_S|-Al8)S1D)+%IB znRl%C=pr!o_=a2QYzv#&TVgEjHaxZtzxJTY&>ddPg?bkPMsM*J@W{nmCme~r^Z=N* zcn^!Smx6c)ai|Sp^#%uLXT$@B?yTMa`t*gKcd!*75p@c^<4~R3ENhB115W#SBf8CY zUe?Ue>GVR9v?rNW399ftDjK)egHlz>GAqUYvU^gsWQfY##SJoPqPSzwjPTo5n|gV7 zQmb$m!{Pk&_M!LkX33=i2TkEQS=XbDm}rx)M`MR0(rF5Dho`G&+Ktucn5VspU7LcI zEw*(3CY9Cquc)n9o$VR_$p%D0w@Ro(c`s}^KNT!jnod3Y1v6i(z^DUv>*VI-B5fAR zT7`4gUW5tMrnI-=ZF0s>`+(A<5Pj&8O$wCqFAeS`>@`0S)W@^4zuy6JHyF%EJ=$HL zPLO$6wor1Dh$HrH9lBXa6Q3ii8$Jvl zq<{go0+A0gk;YOJ` z&aiP3ut>rvA)yG-f`_smBH6Tc9%-xGJlj*^hAg79ypnNqUJ-jz(Uj=1u9XS0kBFHg zbBxXqUbXp;jGC0eUWacY%%aMr#!13x0swOGA7BnlTCcxQA@D`ar4S#sO6Y0(70`Ce zq3o9c$W@W5izh$9=ruqrv(RlR3)bB**i^uW954AFFM~4)mZ%FfoqaRqSHK@DbOe0x z&WjZ%spbOSu)bE<$-Idw?S}E5p0$VFnJ@5gp`1Z!3qApD)10nF9wJ7jkLQVxV$txhg!pZLcwmMZ=SXsLOWDWksRP?n%h+QZ zrYq<3;M;#wm$+?Jd?U2*4zbrK>8S>B7Gv{(J7f*x>BRj?;u*J^KjwxOww*_Tc57DD zn_G1f^PnrRlfGV53cL)}K5I}piHMu{C>3Mg=xcEK4(&C zw%JzVOeaZ>3p?9=GH=8|B9q>4*MSZx$17L%XY0Mq1M=}t%It5!4?mJfxA9lIzYlPR zUt}ELQQ6-zOV{!DqpUL}XS!KV9Wza~IX&$6G>d!PgE;dnT%CTXnYS_zu6n{#`gR*% z!<}(p_t!yujtOm1>XJmtB;lkb5H;BwDW(yOf_MPUlEQ^}&h6oxHwu&PEQWc}v{$Kd z5_zNlXL^Sk?PC7%kJiHb8A$!_qv`)`^Zi$<-46oN7E1+LhYWXi_-dG)0#@G10uXsj z#?su}+`$6L(E>(7X?`+LSTNIlbXvfOD-$D(6%kSV6TxKU0ceGbxYn2RSLyLu|l(BS=?hQ(Fv<#By8^N*b## zT;cj#hbf@IHoTKQUIs;eEWIqLwwtcIViG? zSVbb6M^ibi*Qpf;tL^|Mpy7)%WY0T@Wq+w?ZWMfG-5mu3_3AV)GDe}>w7~cP%G-h{ z#sF%HRh8cM09MsTTQDGk_fiNx{luvSL!!@KZl%?G3uLkqd1;G^PQ|Iq=Q2Oq)77Fx z8q0+iJX>sOCBI=-Hc3m5DrH4^r}g2A4*?fvzEC!Gwmo- zqrOA>yeoqH{-((_nC+3kkLoVe@*3o7cX4x(hQqa;{3(y(|zT518 zdHW3NGN`JjuUkU(LOg#6MAt%n@X$ExMYa{%sA0H1t>EUC_WXRn$Ik#XUh;vGhlIgS zNc|>38r-1wwO|~2ef|XLugO~#m?bHD`xEK$gI$22w6aTjro4cRZZ9bjn?ct`e@5Q| zo84gunK82>#Z9MUDA`mxqhlz6Br=rwg|gH~4M=}DXjk*Hj$B3cc@z#Z=g#LYMkOiD z>dTqz(-6aD=N3r&OTAHo5>Qmn-c>UB`>%nYS|YWv*XoCzefYzCgv)#s2X)I-K`k8# zRT@z~d+kl?wkP^MrnTfEF21BU7T3p8HPeUp34b}LM)s4f7ghZ$MeQHG{%d13J^QCz zED`-rmjeG*G89d04D9XyO|WliSb1TIq4<)eHm5emVv{*icF6#-EG5uM3L1iO0qdPH z7s^6N7-g20Y>iu)MNvao95NF~6co=1YH6O3947K>g3}x(uB0u@HOoViX!G45xxYYo z1JC@HENW?Pq}KA?4};srx%}OI?KP9l;dI;b-R*+Xulk`gkmmCzTnyQJBn*>#A7n`5 z%Y7-TZr|$THa&36=i%_2*BeOA{q&aD?hX0-RYuoy{l}g}gV!5l=Hm`K>van_<8ezk z^Lm5hy&87C_pY1$gNSL*-v#^l6#8mEDH@Z)J}?2{Q~YVury+j`4^Tnss@y1n)G@T% zVPUd6a{+aQ71+`v$Yp76V$U05^n_aD8=MzLDD>hU*3aHJhJD@nNJkYs8mawABF3LcRh*+ zC)MRJFNCh)@e!mjLAP)Qz>PL1k$L4PMY8VrhDz&pj z5nr=3yDTuo%~m8Mcah{b9CAnxiO0L)FN*`BO?ozNbXXO>%8(ZpQvihwl{#ik+m!tz zC8?P6(!-FlG=Z1E_Y6UC_BydY7fd#9seq&QMT=*tVBg1&vFm5A^}#WN1z3h9*!69i z%*~z2j*s%vd2Fv9X~#l?T0T$gnnu!9A}eGocUrko4;U>GZt}C1ggL%F*lC z^XH^F(hk}OlehFsi?8H*M6foG&VMOhl+*UXPBz6jJ=;WC7w2nj9c`I*282mbmY>nP zW%6%swqEmDD;R=NeYMr*Bj|J1C_63W5d^a$U7g8aG9vSg;v)6(XEWM|2joU5vQ=-S zP||KYBiZK4eqzrlP3fx)=?EdWm2auKOLigsewzLpl(qXfAlH>IFmK2ossmn>zG2TO zAG#xWHvxfsmFzYoc%GyJD${!g}r^9;6A1HoCe=dF{GsLLBk#8p+Tr{R!N=Ij_4%MEy=9Ya;%uP9{ItNGJ3;g`aL0Qhc8WKI{PtKl2!N_ zawytV)T2NsPg@_Okq&u!Z*q_B%AOk1>~%z0Vp$7Ni(4iC zHM#cBQSD+hyLR-bE*>Ml|0|cwffl1SBy!l;d9#pvmQ7=>ne}u*3--RV%C%qRR;_uH zNs5hCvHlu{N13Q_Ye&l3FON0-H5Ap`1}j{hLeO=a+tjnYpt*Mnf(JMxO5ToJdE5E_a9RluSU!;f6tXb0t-aVX> zFfm}>(z>-neT`>TrRBsVlstzID?Iw{fT#)vP| z!5_OjFWV!0lb$g7vV;|;Jp%fq$aR>4#Z@9k=WjT`UN9~6K5OHM5NFspE85<6oaZUS3OYH~SQ*$f0X?+)SNL$3(nf#fz#!x>CtLyXtzPh#qd4C2)kaKymqW z;*gp65VGYKaTgjz9Vp%qE@6M@q>%n^m8aMPefg8H0+I<)Wjh&4)4UF zw8PyJu3HPmk@2EDijmgV_)F%791Y|R0BmGyxA_wdYlO-@7fCNH1r}t*oDu`iB~;(Y zVnyN3nZ<}=mez9$NemQv=J|S^ zZs9n~?S<0Dr8svb`y<|H_tU7sbN{x=1cdZsncW}F)y!Q7tku7Sww;8sMl7sNlNaqF72c6zwqdp(lMtjKOTOzW`LLzv)0(_az3aM#myOpB3C=@a+mxHy zMXM;5&r@RdPnGCdGm#_6$vv7`h4g-b+sHJ7dtw3}UhNJOd8hmQm;UiTN@qs}bpGb& za1;yqKV|#=o6`9&9gt~N9VILkbYECv4W!m)kP7~mR#uU5F|~#fRZ1K1IYT8)7-0kF zhj{8e_9G!2yD*TGllqWiU;l`0sP)i#pabUfNe`^4-$+F_2?)`9|lBKVy3oe zuiDEEH3@wg-2YhD0c{+C}-y1f7yi z*~a;FIg;K-!wq_Xjyq+zs%^E@Ue}##10nYU@-8v(tkbae0AcOG2w7@=yS24ePS$N? z8I0egDA-LYgFXruW+Z-Bdm!GYaDognqBU9`=6)GGjF-?b_6K@aW5*d*O@#9GyBZylQV3fCP|~4P0T#^ni3c8sUkXUS8ENQ!nb*&7Qj;rcBA${{s>PBPY<)i;PTKp%W9Jb1 z5y7c9riE^j&iMpTVg!85>|J`mE6ItgFES*A6L-@QO6Q!Mu-XvGf@7gQFF$`=up;sI4^+L&HaQ|+r_34_k-tEbg~x7U-$gFxYKbHbHcCR_OQ#4Uhjy@3 zdTkSOoO_?PENIL*sFR)TwX(|uB8S6wM5&Fn%rLlfkq%^(6{9`no`du$VWVTyrg(DR;5XZfTB zZW)UuJm%QR4z>?6eP`YTx0v3M+e00n*agOZA7zyTrjj#QExxE8_OV4N*!wN(w!#i5 z+KnyNIjhcHP=HGelI49gV>ddtHP+;sh=|6__K-=Ve&f)(K40Px`WD$;$AuK}Tf7%U z%pS&*3`98{`oB+Gv;-C9bjU5nLo1lhmT>s;2$`YBx!$a#tiTb z>A7nk5_iC)bj5)Q{EefB7)4|PdzFD15I7A+7lMI1FY#Dn-vah%VscC!)`Q3aPKcfS3qP5`J`&pOz^)qf zZ76!7(9?JWPUCb~j8dUc3+V$Q!*t?gt7cLaJvCjkuYa)%{8K=pSdxh*cnWJF3`^BWFZ2F*Z6Nfn4(N!#kd3Z39 z=5?Lxb#?7FbDisy)c5su>Gq4RU_RtH;d)p#d)Gj6V1hPNj>27QfJ;X{KF%QXc+r{< zX$aac`&1D5y77=2u8AT0z#}&7-pU@}dgO+eOE+2|s-XYL5V{2Y0eupZ60#D|a$vsN z@X@$KdsPP@0VzBdGj%T(%K68K1w5GKDuH$~ftAX;oKAN#V^O1@Nb+-ymB~@W0qXZY zTCc@&2Kau*GFHpXT$W6esoA5;D$Qf1?y_outTWWwh?L0MW{80hUQFuv8@t{l*WklZ`uq%%gp;F68B^=OZ#C`DNgj2^W6TCXIAG9;;gTzK)Dl=1M!qe1IBhS(* z7VO<_z5QqzRmZljNY4U2RyR}qaE`@>ExXWnX*YDEy)ry3U3A3tLY^VKInqWP5}MD$ zM|Qn=g}SYlFw6*$OLc!Hqf~ePw~%ZJL!H)D0$lqqlQ?Tj8QVgGbdsFnty7V7=z5Zh z0?@O1(yZv-XqWoI|(5GslZaz;S-Kkv#@mx?y22e=2v?|r@b5CCGU1cMj)gC z^f6xM*n(sZE=G01(w<}9;<^fMQkl3ICgCd>7f%+YCtSnkr@v>x8K9wkaJZXA9eGFZ%yv<9Tj6?r z1G;RQ3tW-_ctrIF!pU&tsTP#2XxvX{kDH2su4aCQq=25i=&vC20+zrNKY!y_Ic&XFPzG z(E89(3q>o?b9+=R``AG)xk$7dNJ(_D4BTo;+4(3HF`9VgAvwxuAM~drP7%FoUpLN0 zIgiJWz!xHwIg;xFfs{7*_Rp)M9_IrSLlnoy%I;5kU8_Pr*^;p@BWjGHZ~p-O)^qla zFB4+Tg%b60$!_;tE1HQoasRjqaNYrOUKn7O6==(9jHPtEesP5=U3B7IbR;djrNw z)wO;7i-F;vk`JOdiWB{#7nuou{bK*W8yNnz8-*5PU3!Z1;0su$?MnTYAjeWJ zobkWB)+*>N@m_Fyg*!|IsP=L*;%V6P6_5--cTso85OHBMG| z&Ji>5UZ900r?-(RI&xj0iJ0)Ul;LJBl?Yk%E?Jn8KTy(lrZ;7}4Y(LGQA9n1nk5B$ z;KtIn^2r-@Z&{33y%t);Vr%BG`D}_VW&Exhq9l;pbc7WFF}iIDu|p@mS!e}6>5w|+ z%P{mJJYqxJ)``w7>u@g8XmpP||kJbQ#jaxG#Alq1^W ziamMdOBul)s^b`P7|D8?OB}L%3NB>cbp$8gr%RP5s%Zm}>n6t7Z553cb3fy}&a3=d zX!C*M;@VBBM5x@kGC?P_7G^MR2)6YU=JhIIl|?y<(RE)Qk!2j^6NM5Pd}oo`aYR%0 zJA9C)gSQ3zobQK#Tf)qy;RJfA`pe?32}~ZEB2K5n^FUJcv{PF{RI?ZnF;^nPQ9he` z=S{Z>$WG+Bff~ljZIsnQOLC8)dbukREuvd<`K|ohEsNACl;Q{jlg>Qay;6};$!;Z4 zAWReHf&@U{yS8XxPw7$kUScC6w#!ZKpggH|iVA)&_Ub2!J(l_27ynAEbGVxn0c~&7 zQmYQu+7Ka1oKP&BM9a4nbr_R!#1%mn2&x6(3LPY(9xF=|?kK%+clf?yE?pcxY?Du4 zl7rQk7_`2WTP|+01KIA4sAH24T)+5+@D$r4Q!=@4g;A)NBs9O&TeJ_A(H;BcC^VDq zU{N~Vr+pMU-IQC*+DUgDu~SSHrnr(`0sv<7@`AUt&zShhkH0WiS2$dih;2c^=2k3$}XKJ%qy{REw_7S9HCUuTOXT+O@lCDjK$*Gcr>rP1bW(H zYDeB162|RS0(ftH?ctqYL;lLSE;Ode5DB7}R7od`Vbqn#Rc)h;P%6W4d|i%1o8l}WY1GFdwXn78G&lU*K)0^*L6Na!Cq z9j6_jxFRq6)mCgdqWek6=U7$Y;98Vn`m;2XPRed@Dc(d1`vSJ*U-MllVlperaNu796vWF$8cmi^ z!zW7GLp0a4{SV#4{B@#HR>rc#wQ(PN`!CMA6{ID6^@MrqA$6M}qcNRwLI&iN+kk83 z=5h$_wWv4gV|bR*m@4`&oW`M)^Mc6ekFoEP7){~H^m%GF{RKB;5i9jgl>60n`#-i* z)oiDz+Wy`mVUfp~sv$@z-O+juT~`7=nk9?{Ry@~RpWRD%?35kz_b=1Z!knn zF46?1@zJ|GnU^$YVwi)%*P-mrpORIm$`mQcg&~&v#l6x5&VMfPO?EyXQPd(7KIy zE`YV7VaO*z)cOsGc&;TQv**aD_?Uf9PUxgEdumal5F!RW#&JpCf+xywB|vgD;_a;r zu4M|i9;(GZvxN^%jsM)Zct;V>3R#ANwCw76H@8EYwM3#hfW9TGXq?IsXRt?teBBM~ zaZFzNCM8NwBhM44c=owiff3+`Y?5|fHKB~VP>_uRU*x?~z+KS~gS^=9Lwuwpybs>- zw@LUJpzzJZc@GL!q|@eqKb+Pgtm=_-IB}*jBDPKY@}_USxGTkEJoKU1^Q0S%#smRH zHcXr}%sIXKd}+!@t8C1w?tp0W3jPn)KIlpg+WNJuY8&Y!e*`-v_A9X5!k0;qUpItR z)4(HeZ<}$r#MvU?EK@JoEMV#|A(!F|MXAE}B}Ta!Sy`WuKWpcl!pBto<__JA6Z>=q z4R~sXz?YhcBxW-_b|*BrH4<1g))qB$m@WN(|KgUc>4 zcvcF=88I14Wi`gK7-v)j02$0#No`$Z9dek0*0Bz)EXG(#fS8%PCgh>pbI{DY!>UUT z>dVkj6aQjrF5nT9^~eR>1p!;7&9X|Hc0qDr?zkGXjXJM+ICwlb8&CmDHx80;bryGr z+otN@4tq8O^kN`VheHNv1sjmor!xVD51KGIM%v1bJT2bjbwnM#)*hb*M8R^(3Vepz#0STA)x z&!euSA1{SBG+x_Z7flG7RkrLA7*oa4>+F7Usr9KG_d_pRdAYG$4?=*wBQ{g^*ykzxw`7m?}X3}`d4RA-0c$?0!DYd=u zWn>dUfEB+;646o;XZPTaPbml*A}i0)Lii?a{J6z88YsN@qXSs0M!`hs>KQl@cKE@f&WjWE|RCbU$xb`<_r=#bZ$ zXCD!6)fCehNjx$+YdnH%sT~~{s+3NyZdqNXUEtdP*rN5T+7K>v^kCXJxDP%`7oV7^ zU`r_9%`LW!o7GudT;7Le&!*8`OH{mcECP3N4o4vjtx35eM&&H|%<^sgkD~o_^a`M$1{u2Wr zCq9~yjC0CiMvi>b{1Ch;qOQFb)wMuL%|35p9o3j>jvznP+M3TrY()`;leVQiBOv0g z!62iaLe{=eM5Fi0_fEO4d0J8FORM=IOwHy6gJp!=x=>VB*j)sh zS^YihL#UU(LUfz02&g~M`O=Va?ZyX8&FA;gvvh;gFYhczgxZMwILYd^l zeVP}LDO(qaGp$RRR5RsLR6T{$xb)#%*nOTPvewsctYdlU!`H6>qD+2&=p;Ct=9^UWbP zPp8_MixNwnp2yZuXlYV>m%~^@8dD7s%Ba#Y9_p=OzZ$?x5jp4=V@5Cysd-qxXb!6( z$+mXKCP?BsPgLC1itEa_^FHHd^d=I9mP(8|6y=mkX$}FE2bXxOl2Vqe-SKMlsyj8~FBgx0M<6=hU&SZROBK?^0DF*_fQ?Xbab)svD@uV_(oP>> zAeKi@9-1TRYS1*wMOn{Ymi%#ICZ{vfi=KG;J)l;6F+QDipYeVqm6DO@=>L0?KvFSw z4*ZZkMnM++sP)`wV-H?4W6%kTJ%rV*S2Yv8#7~D7{S2{aS!9kdgQZr*n`Pcmb8yvC zb5f*^KqcxTUT#ExCCu2OTkMtsqKBEhC#{+yLUFtVHZ@IGvUAyPTa4Sz@v( zM|7$ML-Ma=g3kV`u~0_h>1!;-=g_CQx@e&yHc0U4_%noAi1Gyg$zlre@W&n^3Q~`!Xh@?alv3-dhD%(j;l3 zVrFJ$W|f$knM=&f%*@QpER~pvU(OV3Vgj!aGq^&8oerO-|btv3cx$8HCZ^VVE5Mu z($KF^0)^9R_g_jF7R&PURrs!uVp+syQ3R}F@$0wdG+6_94`Vdk+UiRTv{}@&-0JEs zIW?!xt92D`nsc{16-Rmr#IO#rqu7gB_{6bW_c4cY{G18{AYu%eV*I9&B$-oWA}HWq zf1{r(NfwLAYxU$xNr^0F`UsB^T;sNYA6l(=?)Ng`pY0KqXq07ujj56eBMdpr(y$ci z`~RSghZL{ol*Zu&<-}qsbW^CHE|$bUDW17y4Orf}w^}h>A5LP9?cxvB7W%Kn6LjX9R0axiJYxg6X#Z4lo+w^<-H@36bMokU z5bZnj%KB%E_{lSO>qNd|_It;yo>RWBQ+}8K6TeQy`3R)_t%YBl&8K|XEqngWy!IIba>ATwa6Kqmv73P3UtRY70_Lip-wf=&CK48Rp( zzXfm?5NJjYzzdT8fUy8k2el4p5oEol*aOoB!kmL?59BDoKLz6L=Pp3KHfm+)57!Zx zi`{$>1Zoo^0=oyo4T$ZhFkt-wz6N6h+6u}Okc%?W9Nm%K5#EvB5#N#jf^lbi416qf zOnl5U<(?UyDUl(OIhHY&Ntr>JdBv>2tiU?UG|Mu}Jj=?+#K^+P%*a~LRL`<&?$`g8 z;2HaZd}n;@dQ3T`kja^m&uq^kVD2~YmgE`zf_`TWykoXwxMTXra>abb+Gogbz;D8D z-Kd*K`V417>IX0>}sd{C(IH~ScTQ*+!Z`?-5Y@QodsB*?pfUP{y%v9K$A zZd;^#fp3oIua`}dTgwr-4UtkZyUV@U1=Hr z_QEuV-G875GBaEh?P>3^c*>Y0$~yx1a)91^87D_)UmU>q#@Tr~=RJkCcUltDXskVnl*(0Lw63}dkgnCyv z{EhAXOAPa*xc`@Qr0p;E=Hjo5eg1aEf7JWC^ee~7Ac6^qaiC+rhXDu^@;FFiARZCs zIOx|>hCBH{LPvn<4Epcqc#Csp&ho(Py=1y>j@YXU2F(aL51TH}nd89zG?pbxVK8 zdzwDc}g0ozibV(h%#B6M?%V{$q5+DE~2aYd#><9}Dl!(HlEf zMhO(`U=5BEIA9?IV$&`Mp&UTmujm37EFFr2kP5*LVnvpKU;9DbFY00fye^245FN)$L`Ve$6M9MTrJ)r@1~g3Y83@(Xz-BDP8K6_( z$H1n7T#CR`kTikd{lW&wir{n*X+X>U$^{ULf&bK%K(hhGYL3x#$H{p_Yk*qQIUwrf z*b!=`qgH`Wf-l1yg;@n#h5rh;6|4>Z6>=-=D)dtDrns$mUI?N%ux9ZH+=6WdyQE%W ztGHR{CV264)fkg-a=Yf~#}2Obk9f^s-yi(_uLW2Jgf)n)@le6O5mb)@yd%8RyhFSI z-m#{9^X~@VO}-m_H~Vh*-L!Z1E#QUt4(E>acr0pwKV*RaA3G75NF&0juBq?Gd?N;g zU#CUU{wPAMLALR#!95OK2sC_XF|UOuJTjww&KUjrqd|*9c|0dTw<$YYgJ>i_K|uJ) z6Z6^k&nBddan1SrS1J{%uUslz|MMcrKbVmJxnAP@_oZ>$3{wN#)z(mUZ#-|F96i|% zYGV}2Bea-EoG~YQo=BNGBdItPF*o=?7FJeP=WL_Nsh*1q)8oxez|@5fq?y@y&y)GZ zUG4fwj2RoNb;(oj+O;xGY8F1n>O9t>RT;aib><3lZodo3qLeHpYwn;6&7!4jIcx5K z3&o-L}v?V_!08|(If3+1AotUK%WkPG9Yuj~^mU;jPPqKGUaE8pNf)uOR% zJS*QobKaR$S$RgDnOE4ER@q4g2NU1yJ;-9TEF*Kz)IH2%wQN0e&&)l0*Ay$J9M$ zSs%-L?AevO*p54s83qsqTgA793frB+d+rEPiLffH( zH-foCJ7_qMQ#)!nk8?Y0c$ZTsf1>PtTNJJaYm1A(*v!9f^3J*I8-g|qN=hH zCx*RlGRwGTgT}h9;a63SZ_LPym4%b;Qo1@O}vzb~kx<>R#ENh3WYq`}9Rnc{+ z8>gDCTHUtQYFBqmHd?o+e#uv80Cmg9_I52RZ(m$X!I!+WnyzbQf5uAHn!cv-xAuiv znx3`NSIsXkg3+z5$(vm2x7?3M$sE$R(7bPYA4zgKHO^Tm<(pj7k&A~pHV1TWvrRLy z<%Q%zRWph2Z!+7XX#`yjtNNOJxxO+N$b^+}oBk=;2tx<+A1a{lF~-ft-f^xfjWReF z{I7UrxH`X&{Bwrf;<>_Y3DRG-J%2wrH}T0q-1*gw1?8VNoSt~$T{~kwtV!x#o_Nu{ zbP#Afe;uzK^k*XwU!Q+W?dyojKX;s)y|B_VaTuR{@aX>fxiOg}B}!gg-4gD8Atc3a+cF z+>7XbFGuO+FW+2UI`cc0_OboS##rB1TqK$Xn%;!rFT!TxDyHYSkXx|0SFcKlZBM%+ zY))Q~*JohyS~_N6NgKV}sYo_G8~WIFPsqQ-GJi?vUg_k%_GXR~451^N!t0&Iw|Od+ z4^+Q(0nagbyAIyL>mTl-7hSAU*tF@N%xdVIBSX~3|0rJGgGX+4$L(ewd~rLMW8SFc z9GiAKr{{;Jjg54Y;@=cw#;= z?_`Czay5UtuIcf)bY5DvdUEXZM!&SPv9h0LkaFi_WV!?uvWn`#V}=z$+^sksH1>{cv^ctnMnG|4yS|EwH)1k>mEkdimT#c=dao zh`b^9^3?8PP^!)RjjKmd#$Mu(gwr_qlYXIdc<$~pIS{9-6URIDA&93;{G#X7KM%{! z{vu=7R^dbDP{aJGphQ3HGm?jU0dOphtB+PE>Rx%1Cc_ z+~kghe>dg7;Je!&D7(DbCE$c7FGtPooK`%dcPw{g9_gAIn7O&Mt77+WuAy}e^y!o#rDk_bM!J<(>6= zqs*Q&rqh%vb#I4uU52@bWE~IiqPR$VS1O-k>9o`^ZRP5yhq3bWeB;>Cx1hz&$QwnR z*>CumUoaqlz2RzXv zX@AQk!rh#Kk~Sq7Jt|V?O`uMTGoS6}Vc3RgX<-9$H_lSrvykS@VW}}*Gh(22^o9Y% zq4d#!?vBlM%c=FwYEHFl>+J85c(bwMFpm)9YT7a1qxO2dr_{q0dyr=p}-U*v2J-b=fpA;9rXeB-yB9V-OH9r?}?} zu;6d!iB2GYXKjz{hczV|im+P#@^cELRF^n$#FD#i0>Z_fwC$7Kb+5whm2i zqDy%)UHv~<9EKW}O-DIG9$ z)`T_KdYw8xwBCdtw5v z9zSoy2}6(3G*bA5&W3H&B8 z;t%qvb)(3WD|91zO*WD|pn|3VuAoA<7mH>Oww$aS8r24B zU+)3o0Xf1GVY}Z738kc&EtVM;vMv)+|B7xcA&Ml9);WQj5Z5?RqUaE?HBa~ zNm%eKcr6rl5{Rho1NE#p5*~<)&Ka1E-WH&P-WGU5`yEK0mLIQM(UHd^@c_X=+>!Db zYD90Z=D^M&{$ON}JSsiN8=VlEU;1W#&lrsm_ENS`ZKCf2_p03J?RBB=g7#|M`0o8d7Xb28yb;+8M;8F`Q@t_X z8$%ZW{$Bqqb*&PW4Vo<+UQSN#~ukf-^Ceo^?p ztg!ccE}8Nza@u{HDL9I{$sv9qFz_>SL{_!J5TZzJfk>hfqWF4?|ug zf-eQ(=1;}pBvk_yV7Gf~Uh-xv3))en+SDO6Y<16BGV!)H)opE)w`%I4b6wx5Y#E&6 zt_*LC310z#oqA+K$QFX`RWL@rPLPcOmNKAn(CZ#G~&DHtP^zRP6gO8@(7xb$IaoJ zP@cv$vbs>NgLgLlhS?T#3%;c35^+!FE9e5`&GDHqp5`@jx-e!!Z|j%|nNQlB(pd(~ zq;btbWWwf>{t-Nx?49#95jgE_6mSvX0_yC;gW?lJ2qK`mD}bCBnDcakx;NlL^NPTO z;8VpZ43|P}R>~@rTL7_5Q@4n2{=%x^Zb3JUN%z z2&0__pK@3z!UD(lUA$n31qMHn`Lv=YEN%kl)Jh9hkMz92`Uvcln+w@1 zC_wk6i00i=qSq} zJ;`*c%dwyIbPA+C0fd(65@BXK73$hdiaAA6V**OcbV<@Poho(hCQY3}snY?eWxB)~ znNFp;wv%d3vD6xXmNH$^)l8>aUHeH_r(o(;Ky29-5oe}T@s`b`oKrM4C!n@$i=-{n zsd~$9($*=Qx($$9wnglo=~TXDJE`XsPwfuqDcd4_%5CceTh?tmsdF1gZ4c-w>n6R*yshib*UNw1bL2$;#R*$E(8`qdMZjs8y`KM9U|lfK z)RUU8V6D5a&9|KYpL|Nxr~+;A1N~G^N}d zyTk}%pHX3fq?oGG%qQrMK|`z}#5Fbc^n-p54VPGYR~mS45UfZ?vk4wVegVjII_Gl0 zTZ(Bj%ULAOaP>L+%&tE4jCsC1UHJoH4V|z+FfkYk4@$6rfDoi3qd6&ug~XHRB+N71 zE10-Ic`A#SC#ayvPn?c=;L5{t(XVB4_|W{+!Zs|~U=E%&F*+felKwV3=QY_ZXP-q} z05{8ejZJCJ6tY-mt4qyDk8_E+Q6!d@*IaD9(tVsIyvyWtm8NBsA&IG1uDG(LtK8PC zOl_|%zR)a_r?bMh*pU1SBX8Md*0C?IXsXlNfGmaQ zpP4DOuy`h%xS_2=XmJMnNp#qVoxk|nXZ?O39)jyIMQ=NUUF^o)Bb0TkgbvrnFs(5II=x8km1B1#!0eun%eMEFn{s|N^ccNNcY4LXC+W8bD&{Af zX_{R9fPG`6{)XeFF5~5%hhlelN$GlMiItYPP}59j=xvgr_sQj%ctdA}y|vP)vs_mK zO}6@s19s8s1y5^}&DgJ`ktzw2Gl6=klq-}?=@a;M#LqKS~d&l&>A9=24o>z zy2W=rCz}IvJ!)IaBb#CJ<=M2H!|=AtQDQ?g%rR7FqX=bTZJ8WdMML;%ORIc#cR5v& zg&OO<3F@M5(vs*S?z@Dgg);dn7u_Pc&rf~?ga!F#dCx5YkpPi5--RSH>j>D=5Ubv6nuymn>@WSf!c(_< zSoj%`wS331biJYi9vI4g4TvvPLn2#~cIXAMBu3E{!KJnWzc5LMme-gQViI*I3X%`f z151S&ghh8r?yN62N52w%rt$J734wsBG5W-L&7&ZB=$m-;%!7AG#@}<- zit+x9{|EBFoXUSe2l8LaU=e(QRmOjH0{>0! z&i`g#lA4R9&EH#ps=G-JY==*=TIfT}W>GZK*u1>u^0q)KkzZ6tC_?pXrbj?OWG8>$(@Fk;WB ztfHGJ1p0$X@(BQifVK1TWSXr`b9?S;t)B#y`?-vWi=0;2i0H^8n2tr9l?2fgf}EF`fXrmdR*MvJz_`3=n8B|2 z;z=ZE@g9oN@ca;%Za>{R)3JkNw}&9&(p1Z#zC@`$(p$)xlHne~KJY#=vBVnDPw4Cw zomm<$^@%19zUnghsJe zyJN<;c}OQe%dg_wMFnXy{fBb{K{T1m^mAX|T{Dmw%@rC5h z`#%pjviA1YY7Q#ymM;I>5I;HlFCZnpSpxrI$6Q4RX%t8cqFUA&i9j|vschwPOJ*1} zs*n(pK{eh_HaMR-^m_97zHNP5_nYu0Dbl)D{S8&HJ6nuJoG zrylp+j*~5K^Pl;CpC8Bpm^WS^+ZmU_Am$~RiN`f;^<)-irCgNLFJDf0VYvEH2PGmS z9M@_FByD;q(b;vi&1_UCbBT1YX3ug9=zF>iwe#uGl%%AXP0^A*vX{*4JUjX ztMBU+b5lmsu63MnZQm@_W4wAyG-{-}w4b)Z&er8!o#q`mcB=I@8~K`aEiPtZTukpm z)jmuvD^yt3+!8UrDK|@t7a!=+r~XPC<8!*`onNbY!JVqgl)q>V$mX+ooF7``S3mO+ zMSf_s*5CxAXoNiY#AdzJ7H?3b=K`CkJ64k-aci;IR@OE(6t4EvDk~u4t96>$yzzw(cP%>+r#85j;WrL_d8`@ zw0HITpwOiKhU=#D)*}qvi%yetEA=`Q-0#_xAP#iqzyW`QX(5))O6Zt(OyZm`H#r(O zH^!mz#8=SSHv!U4L{z^~=w|0~}$d%3P)xjO0V|#$`*w3=80}rOO7+&ww!3Nb|4*KBw zABe|Zy9(1NaUy;-zzNL zFlT$WinR+1)H+mLceXY@wu#N#4{eU^9P=*|eNjBu!0zy_AKuSEC zNg~0Cf+<0Qh$PyX6tv-yBVOdlDpF>ETqHA#mF6s;pk&fME8WX=rIfUfxTN%F*+i9s z>2wp--EjM`EUX8D23j#cVeNzkmdL$HN8Uh_&`d*tPa%hFpPPNlG6R}{#V|j?)>|fR zrZ-peO_BS`%z4L@i0FhHWeK%=Tpa(sh%kyqyrhS=jJ1fnqjGs(Goh=RxRUy&lLYD$ z!RJO*_Y5*n8qyGqr%%6^Z^X$B^3&>CylWNb4afVFAv+KA%%Y*XUNT%Zy5?~YW=fH1 zOhw-PA&C537`A6)<%LAu&*@az`3Eu-?nH_(!Atb@R)Y5S zNJO6i+dKyPy3R!i^<{cmJ1QQ9L9o~^*-QL74kj1dH(ec@6Z&ouf9y@^40+{4UVQbC z!pVJD9ZMJ;=n!ZVu8-avkm4h%k`^IbIgV=1-m><`QGm7nXX#ab^R#?tCQ+@yQOzmY z-jKSdNH1#ThoqeiZ|&J`A#GGzbI9OxjPpmwV9s4}b_TWlZu?~BAejEogj@L=L~Tt^ zQlU>}k4WD*CMRjb{EvUZRGqI+qF4UHC=dI}W&Lji9;;Z|I@p;0!!qlC1|DzPqnV<8 z$~|pdxOM4mlJswQr>HZ)mV#^3l#=9L%C~`Tt~c`Ngl1TG`20fN*O-6##^A zGv$DtH)PnF_jCwVANySR%=Ak{I7lFI-uWwp45g$U%)Y$LdK3e?PIIvU%-x-$Qo7=F z-lc_8fVs*HGG(4^TGWdLnw+n~gq=Vq+0IxOAhkBfnmJu^E6uTiDuESRtmnmtBF|sSzj|E)I0}Wm%Q{uuG{;Z_| z6kyEIuI>i(g}nPE6o%71V8Wht^hH#K6<9Jc@ph}@_sO7q7edXB>0ljt%nICj^3~MjJ?z<&3Kg9V7h*FkO3VNZ@s-ro1*z0~oeKvP zd<`chxqRgXZ5HnInR&cWoLF$?Fjb`4fCWt}BV*jLVsJ;auP|LmW?;SuxYl{E6n6#b zfDqRw?K_m8r2t{{*@yM|QWtivijq6Bhi#1OHD-O)it&4?4DMPG9&@>ESal7+6%;PT>eRE7Ol<*NB=*#wA(5tAGhY{W(X z0d0pkNnHe!(D5Rp!VhAcmMHXo(pllxpcoX<%BQFa3T_0jX?V>*2{1)ab?xx3y`pzP z!Mf_Mpd_vKV`LB`Q$Fbip@O9h9(uIa3eiyKDh*ish{yI*odJ`dod5^GL;8LuWNg3O zJH;<3aEJA#Mdd%o5Fv10U^IKoDq z3`L;@r(;7~dC?=XY2N}G=Qd|$6yJu#Kpz5t*;fqQKk-~uwhAQp0h~jm&N!diCoHh? zo%Fb#=b7Td#Cn7~xqeBKbI`gC&!?Ut@oH0@=iDM+OYV1J$emV3_EdcTkym1+ZA#D2 zWmc!CB-5;03Oo$)O1wHW@n}2-R~w6zA=5a+P&|Zn5s5h4GCI&568fFsK*Vbn)7k28 z!JHAh+27(-+9MX9u}-d`8IV?I&#q*ALUA)(EnEQ$lX4@i1D%`HIF6-k%DNx)PD6jF z%$F;~BVC+*hrS@f)iu~vclup_*`t)}XolHW()FQ!H$k14c@?)AHXd{)CBSSsD&#DS zrNg|iY2(T%^Wr`; zdRpJ(2c9Tx$^?=n%9VG}4o~yWT5VSCIfbWDY-N7I_Evs|o8M3| za)(kduJ#BK9xT?;)H^LRAp0;hcu}uyv}jXJHCLSOR2DT?6rgm4S4ga2)f6XD7((@& zTl%vAlH@-p^H5IOwLzam{$@Pxv`)FBVt{_4`pqXTr_u2pkD4o1nz^DR&>Y8ZRaouQ zDWJY_zJ38l=kh1ff+}5Jvj?9s%m=xU;3m84w|dpvC|HYCBOARp z6IAQsU20K#YI$5~?B#kmvvyp8I-L4ibSfVpHzes)8U5_w;8RrNhO$BghaiV1UAACp z+e~^%<`M%qE9-OKs}Sh8s26`>Zg_Pt2{@F~i@Rnj1@ z0@5Fn^4Pg?>vm9d7MQ6WRO;OXmK?sBE9Luaw(XX984GZ}zl-l@$%r&LxuMhIdQ65){U)wqJPfJC5b-%fh@ZRi63ES_xO}*uj;AJnJ^b!vY z|4g2e`%dEZ{$s2@4DUSQ25sp63o{bg>7*Ee?^0^35EZ~IlP$qZe{fVYiFn_`BQ7oH zPORXXsMO>#*L6x+P6PLgtzRMzZmu?ZV941>eKtYes|0l24y`YQg_sW@fM}*$LWTR^#WF)yVTdTaBuQMmDDZtW|ip zBaS<>yWeYMV_ncqq@bO)i8-!fb6)7)2wrudkJ3fE1DTh$_1>{s0~tg+rQyLf^{<@e zRvY`W9?Qqn!J1#R6T5l<^2@#JTe@xAJS$$IJnw*(AT_N9U5UD2xoKJ+_`tKHPMu8) zZ9B(C#Ri<%B$WorT&p4HZ1CAiHA=PD3)?Z;l^3m;~Qcges`VuqWBGu5UG#FWMPc&X{Id1>en%I8Bs@zHTN6`gnb%04ImH&RHq zq`2@7xi2Q^4x6ojM)G|SzmX5@O$+z+x7s=mcwQmgCsd{YA+<6@^WdR;7M*g!)bQAS z(2$rV;K9*xU^Zhx9)sn=ap3#nP6ZNaZ)lvdxmZh(&Z&27xP6#BVfBaXJ8Ot{6Hz%D zxMJmu8ZuHTni>)*85Lw#=^PN!--o0wne=z?q<8SbC`7)RMkT9cvabz#hr6%r?}2DuN~qM) zmeE0o@kIFUzs4*vInuEjjB21 zTtlXMAJj=5yU1;F&#Hm!MO%918@3~BB|tWaIOqB~Z=Z>_&wNS2hHh=^I2^y(J{?-# z3~c+8V5SnxS1|k9`H_9$^&uiH5X&}|v>r7`LW`}VP3-1^C|vLR&v3GyXx>M(77Zwe zKo)L7$w@1vChet~0PQ#t92HWedvU>AidAI{DO*hdAo@J|WHUhm@WS{>5)!{LoMQ7J zQ^lani%nki5fGkYVnmgM-N#gby-Qqn7-1{B{G3rgN@>feT%^Vt2%DkEhw5|1SoIt1 zbE&7Kj=7NAipEPzE{M=w&HLBCz~G4%fnisF0sfMs|67nI|A~e7|1>8xtZnc#&_C*W z7&mdfZN}_*Y~+$_#@yf{jVag3Y*%b?#^OM~xjHPM#Ji6@wx8>{6V8DC61JqKr$?I1 zzXe?&OG5q~PsHw40QC%tLPYkgL`+O94UMF&joxxlD*Wwa=J#)pCSpV+;gyc3EuJU8 z6W_~MiO;tccc5;<*;Hdbib)5`W+xm9&xmW5$>5nGv@5wgro+&IJ32(f8>B&&pR+gN?HdPLeooQe%^zjBE_6J;`yFi#ue>z<;XMC*sIaCUxGEd+r#QgrRDubYssSM79fk@K~%%LXJx- zSW#FG6QZo4br(ietC5}#u?+T>)QLeJsz5(3&pXU$yjA|Bik6g>D|Lx-eyC!@`q~x* z?au%|Wx9S-lDI+tYd5xh*+*;@}tu5Vx$rZQa*;Jj3sL|y#*gLJ^!}xWtfSR(r{MN>ku|+=B$du z-s*8Le2sL#?Yt-j_WTo0&Qh#clo6`TT`{VjpH08GfbiM`z)!%dVL6_N`%Tf)14!ci zE1?E>>z0qvNwd_8Bj@9DL%vX$hX|XTp63r$()QNs!KXKa< z5`bA*yh>J{q^6N`uv6li)Jk>6cU0|Qb6czmH;@<76CwJGMIwsF@nlZZ@9<(wP7+5)C=M)O%i+R)Dj=E(SB z&iHc9zhp$X!6Z4b&WNro2iz*W{Y7cQQ;wQkTbn<&m2D@ZWV$w9NVaOQrwP>K%oxul zoS`d=zyElsEQbOOA7A=&c5;k`PZch?&kfaQiO+9HB9FIUIl#pCh;^giF+H?xyRLHb7%`mTHmI_}@-nMs zvNFRG10TvrM8kVCqfJSNJ$(Yd*9PuU611z8|c??3lIwm(4m2(drJ_d)a@c)D?a zL;CDj821-IE%ngyxW4P|5(~Y!WOC(N+!jbpg=Ma;0#xitmkK}Rpc;n%5!ow)uj1OP z7Nr#xAo5y=1NQ&aN9ocHE6So0Tq>rSu6Z1`T=0ihsG8&+yA7#o=1B{yvT>k`uZa4k ziBKs$-mq0kt3{PNxhU)f-hP|{SFFQLC+6**~;8{ zlU#M7sKwR@v-X#6x}sQa-yU$0U?;U2EtOieD7Kdv`d|?Rq-gC@-Re@m-5cq>%)K?woLjF|sWE4uwW^r)tb=0JlbPkbz+5Vk+`@*!v zE8FVQ;*XdxbT+^ALyZ%fZ(A<8L%Fp%KqelnI`kUfIl9U1A0WJJh;b%=r`B?odhg(@*8U~zX|Rz*Ag}o96-nioa~pfxi-9fKtB$P z3Q0#Wj9G6QMB63|eoIC;0L5^~vGcH~vvG2Fb6xFNvM*W=4$9{+VqJ-#M{#cR+!(DH zhP)xRlqMHHTV_n$dcVI+m$p;P8r(AU$(TZW6No4O!`x)PpMZ|=OV<_;$+D>4Y#U{Z z{c3+4Y)WsI<SvvK#%BAI1u~`S=x;Y<|x5b2>MgS;>>x<>!mg8 z;W|hSZu>;ZTzv#qk&M*|VP}C{i_?t>M&!pVu}wAoZ(yCZ5^|eto26*pyu=FpDfL4u zyJ#GFz9#mo>5Ct{_J!R;2%eiZo+7Q?-gKVR$MwPWTWdiTpbhKdK6B!DZAjiZ5$;ZG z@^=PR48?ajEeus2gT!THe(U@s3iyBi#ZMtIzxEU8%TJN?<);w-pKUfbOJ~ck4JC|1 zHa7n-2U7pL^zWYa+LXVgkq!HtE~Idiw$zrV4o`EE%n29)cbKoDs;USS8Q1n{hr!)}jQL@p#UMnxlv>UX5*IF;GjDZ=3?(^11oJFr3$DDv|Rw#bQx$yxXNkY})= zol1zX9kUHP!+_-@mh@)g2`in8*lC{vq_4ov;d_9%)%N(2Q2dzi!&or6CmD)zu39rH zSjP>cRj~YX1F0$9YbDuZ_LgcZsGn1k4xQhxUnWSoO6zJ2a1VWlSTsH)In~(`N(=9@a4iJFQk@In?k-(iE}~DFGP;y-x<29*0eZ7~eddJE z%=JY<5^7lOMthFv3UdZ)-BWc27RT-7%3w2fSa6_@L_Um7zK(XvnR927#~L;j${S7T zCa=#F_^S`$NyIPy*8F#dBRJa(rgQQIZDrC5oC=8_v`lB#O7@W8UOY z;HqcdsW!mbSoF6R#(7?x;wx-zK&Jv?ruVu-2N^Hg)j&2u%D@$0!Px2&$=Jf7ttBVe zX^y$PSQA@#LyuCuqO}jr%dG;%*XSeAD@*g;C6B4%o1}|ywx$-aZ4Np*Iu*uZ8vAj_ zTkr7y><6n}Dl(n^N_t56z>eH^=RQK0ddNW%?nByzHmnUec}&6y(}KbwvF zI3~A2>1t_}p2}jAm=4ckH5Ua1LD+I6{HpZoWDuH=15o9H>guGd{Tb>OZl?Mw!)5N7 z!4oLc=G~`|yVLiYLApd;rWPH28`5%DIT1pc2W|My$ObKQ!;3jM^l8YTHsz6HnQ1tF zr$RgJ^j#+8xOc*~Cf~VXd%5Y{>rEZM8Uy3UnlL{6;7ll|!WzxMaa^)RKBWY7yjDDf z%5&(isUH@A3q&G7QoZtzv~(qOoh+pF6cw^8(bd+zApS@tA*#m9T-#>R)-qttLGt-q zL5Cx_XI2`*PapvraQ%^6xHtKXC9&|$dT{*im!L_@_c99uiF=iNGj|+r85K?1_G6Xs z_BdRA?qM1`>4m{g@>+-;?V(Ql&(>MrlYi-nh-jo<>Ay4u@2e;J|EDSc)D2B9%t{Y2 z;Xz*8AKSQoWW&&$f}W1-DS0gfGG%yVJm$4J0&3)>7Gb=Rk?+NLpMm&O*32S|V?AsU z-;>^MW%x^9-n>469K!T4HyPZZ9$^xp`OxAmr~XKlsS#KaqXwNE3RV52GN&mroNE02 zeK_aQh$Gjlb&`G67+Xt5)|xy>H~oU;08@ap-u|o8KyDtrmG=n(6?x1=q0ZFb8Gv68m1u3*shPe*SZP!F}??>%)eEN z@vZ}U@4pAv$C}as^P;vc@FfNrdcAOL@ErrHBb4QqKGVU534^-={5jIL{{o92%@+{{IZK;Gc@1n)A4w22Zdf3Z%og7$gQzHprJrfG zNh+la(=%%-42_OE^w{?=$eqU?%l^)@C|}L$bRP2=`Wf+>Bl1kO9s$hIKHg=nFvEX! zh}9K2-W`MWBv5IQWt$mT zzl4!?PhkUGq=4O4d(^~}+5B7EgKi=pz9mmRW>cr}R-GiVR4 z#(WTR&-Cw9s-NUc80+N@5-si^q<^yF)Q4zN@k#f;y-JVjmL?klJXHBocEVB>M|E{+ za5f>Jd``498Y}ASyawg4F1z)v-(=kN#->vB_-ED?Y_?)c+-MtNWUyB(w80OV>ph`K z9U3{PR(FdIP`*77&TY}WT$q5oKP(N^a#ps_}4X`e%ZSEqB}e4qv^`BM8d8 z0a9^Z?D#F_W60=)OJLJIjF1aSU~o?GvnRs+p7zM%T2&vPhFsS< zK}Fg@np#V>z0h&u*=54pJ`&d6beS$x7kfM7rIKoa#7ko91>+T+C)B406kH{6Io=t= z3Q1qHhE|~BCV4mwRR>@~tM(8>_~K{HA#^gZ4Km;E3LV5ll@4&ytKOAVE$WWZBEcqx zzDG}QOEDrGsVko_6^-rGUw{L80xq3?1uUO$k?PG2+cU*Rpxn>JI#qH*9`H8;S>ql# z?u6GgKMPr2Q4TQKe}~{K^{*icKu|$hoCp6ezRoE)v#5LX9VZ>zw)4ie?WAMdwrzK8 z+qRQ8wr#6}PCA)N2r~+s5+P-l?oS;tl~%IyVXjyX+Ka_0YKhQ_n|S`R*Phe6 z=~wd%;eG_FoLf$j>zQEVLYHE*}34}03bMau7p&7xU;5&>+yB7IlC zjPL%1uskfV0{a#kS1}(a;xwQuz1pbcNypO-WE(FWcl0H|IRGIrPI9)&Vw&fhmFi|Y zPbskF!hiTEm1+L`4FlB$$+$Fs8lTb)9MJp{{QV_*SZDEbFDt;~c~+k%XU3`ZW?_Kt zkD2NWuIgjMg`O8)LT6U)(*fTC^zwy>s^@$(mibPZ7MRaqoz^K*nTBxfoflP>wbBmd zF&*`7GPAouO0bT8Qj&H(!K5PnB$x6`vQu0NER;A`NOV-vZG;z9{8C}FWQVA9bjnPi zlHV{JE%h5pRk(7MScmN7Sg{Vp@kO9g+k#;M=WKj!MUcv*dGC%S0DwMcqsy(>W zTjV7BC*%L#$o^xS?8(>H%KWy8BvJf734oUNjIx$SPKHjNBL5*SE1Mdc{7;xyjV7!I z-m>dwyjx4tce1coZ7dxu5OQ-tx|MF7N<7W>DBLD7wOX@vz^%Vpoz(N*N@F|R5QfaM z3i9tBHt7C5))pDX94l6W2@_-{JIpjsND^y;gf_I)255n$$fBUrO-{ygE$`8w^{Gs8B_%ji_&eH=R+|F#tN!IM80-30hEz=v3u0{=Q^5C_%8-4#^?>& z!qJ*UMTLPSs>5tf5rY$G6`E)a zsjDR(^O>($L#&zGY4>hoMH|6pTqLE?A&7gZjCRm^B# z)rtvcF-v&<(}XkQI_9Dw5I#h3f9vMj+wBG=c{a<=sV$d38>xv8Y~Q7wmOn`f_2P;` z6jiQ^<=(|bbJr~P$TGEpbUraxw3}m*Fj~AdYTheK5DHq&+}-tZ=$}{8dy6DVu5|d} z`Hm=wxTdAdJkDbCa&4=bI8+yj?Gz8~R02OA(CRa$tyeJ2?i z=OyIbcuSc;T6D0%ci%*nH!F7LX`hPaXD={w+BfOR{c<0KZ-S1-#szgUPF!W)g>i^% zXvhh4-)FODim*vYamC2f3R=cI+r$zUeX40SO+ehrS(`^j6R;WUUOXh?Q>z5sSg4syL!*q~pN^Y5%zG5mOmz5Cske0(t`N~Z1 z^tRF@P+_h-*nJe`socR?z174Pl`$cv1y8=hYJAOGH<-Pu%T&v|I|r9X;xc1nxd_Lk zSnT?0v;uzYceAcueWPjFVotl z4qb0h``dW_kc0e+vJU-&&qrG;h(_ z9)_Fv;(a_t+}UR1{T-7zE*E^yqq{#YZ%3HmlHT%$=bmFG**Y$WpE)Ogg1t`HiOddy zyi*-stJ)H?J1a1a=U{#N?;cr-?_3_lDKDDTa@JIMP2L|JTFD966Fz8V2u|^YC^TUO z!s4H&s2C^suen!}JJc>;hGRL16rO2_n^eD8G{|OJ$PaVx>UWUyf>v1cC)q8MoW-`} z-lo!&A2p7;Ec(jRwR`X z%N`|{m*wnJJawX2rkVYpqumSRSV^DFO@25pMT$AgW6!W@ahVP%0?c&nWXIuxZ=NNm zd-BG!3{n{yxshlN_TOO;(y$sE2RTdjU&eGlfjR~?_b--p= zwLoRiuxJv;RDvpSEB%cHAMOw;uHD}6e%~#u&E_MMut6bdiz!A~vuXi#z4Qtn9UVO| zsv&S$KG@2+>7By1_|En-lFvR}M4cNfhZ=jo+2!Zs#@^Lq88)QCbYJ9i8fnPSkQe93x1LhYD-4Dmz`to9P1bsFk`itHee+Ms8k|=!ebsetyRZa*r$NtOki#`Jrnk(rai<(%6@Ut+|#(TRVhp zoAGHagO^m9Ev%orVqm%laIcW(jfib6!DRKA7EJ^eM*|bGWRt zP9&>@)hLK9?g*b)j*;uT3Mz;t%_CbH5+s`00Cq}w2jRF`8Z_0j9|!0kv<;;dvbJ|* zqkk|x7Ef|-x>U06rVNW3qLGq%`2>jQZ?Ch=Kmvxqjp~rYBrZK;U%XU8heG`m7)msgUZ|rtp+L>~hFFdu9}rZg z)ZAwX8VBGEjviCQtHut#EY9``0YXrnIFTx>g(%yI|G;e6Kp1Xkv*=?(;3!Zib4vumUUVcO%2X>UXNrge|)pyP^) zC;8$Q)D`+wD)GQzPkrY+8X5CdJKjOR11QS3PCF56l|o;?hHrCimRQZr#dbx`nmCTWOn!dcxaFv_gaq83a7qG9O7mm$2;(tD2=kk!muBZJ?H0L0iC0|DmZ1#$Mw7 z9*CrCL2IgI(OfxkZ%*UXk^w6L$y4o)LC;%NAB_Tr7%|MWDP19^#H1;z{o1vtP}MP_ z(&G<9S9XLEaqgL9M5}WEmkv3Asm^XL;FzB=Mcg_I4dYieLbR$!1g^UWU2#~iYj3QJ z@~m@;*rfPg;X|zngsl~duQ}8i^So2N_`_-Jf6s8c?`wU)^T#M0D%^Q~P>*(;V(Y}) z??KA@f1xn$i+2ZQ-EqhJ!L}&@>_`}I@};-LmfOQ;MtW4k6_i-w=DqOBbYJPNPg_Mi zA|UTPqYlY*LnSQG4qZqI$~GM{Z-$dy1ab?Z?peLZFwcMaWaJ*U-X2;%iTDKTjkuq| z^GetshLQ}v6!(2#sCDPMa!z({cNe0!9n7n7SE7=sPu0X>hz7Y>4 zjb%}(7TuWM7uJ824YSUT@iuplS)O=jh>pcKQvFVzS!JhT_3kuDjZJSv-@)eb;ihNG zJ3DmLJ9$7~%CC(j9+&Ij%`-3VZpK_`(8g|*-ppWqN+4X<;4N{hT&w7@x}U_V?SMU3 z=wN#syemy2`o0R+c}8~?i}ez71!>jSUqE}EC3%2`%D z3zzo$S=6Kn{Psl?lml~s9{NU#BdZ>Bg;?sq!*8E0`xD|SE)(=T6A_AEUAQljN8b0V z6i#iCbiu|In+Shb>2@cBpHK38xGWg?Lyb}X@^1-PFW9r3yPJ{uX8V3auW|A+*espu zskzL_{{6~Mm_yuib}Np)PT;ety@)9$92P-&v*&Wa8YkR0H$-GxAy<1W?wY11sC;!) zE27d+01(g^D$tsD)%AluCyt;cM6F^Aa*eQk>y^hR5P8c-PJpgwVT`~BCB9w*gJopFp02k8m$P; z>lhPVp}_C4q;VsaC|2`a(?ZY&8d|@4`zRTGfqgozKrRnfug;ABm3eIx{rs7m^T)5+ z{0P=u^pnyjRRS}zPKM$^54A&>jBlBK)UnBeUZ6=i#6p5sYF<3vOAnmNUs zKPmqy*Fi6Kpq*GzD8diMFC+HIsYNkhI#;^WZ8P^9>^Y-f>;RYrGS*h166ZC<+23-# zj5yh#4{}5UECIur{e5?f^d+j7y|;_`>W=<(bF>Ti%-P#rJkh-G%J4@u`}cQIb8KP? z0x?gV7WmSjGy5Q%W=qFWZ)4t(XvzYVqvL4mjxdD+($lpyZjCze0OiwoG;d5g!b~xN z(Z720Oe0J=fVuz58lo?IjtQ~GZY~_3Qg8PsIiKYXb{9MFFGaB#T?xmcWgH>!`wh7x zkpB|ZmICjTI`KFhRvck<0~M69UX%m~@}UV%e0jvUa|?ucWkg=t#U9;0;GM^|vsrk} zZ(hIuA3OuX<#2zQbjo%aA0AvB`sAXvn>0tDw(HBqnvzb@N1{j<1(~AbPiMqVw!N}3 zXCc|MrmZ-AG*$cw&0YyET~|Hro{;_846SBx339r36DBmGY)?bYysVGl&u-(rtSO0E z_E(^BI(+96gI}--K!GajiZ_CZHjOuWld@Du=FkK?Wr^K-U{pRw^!qO!mj6__l@44y z?#w@aymbEms$4}Udvhm4+yAS|-R6VxP#sw@mu_4K!t)6R%ni&*iHfG|pm_Z*JV>%3 zN;hkSB{33fi0+9tiY)9kCk_Z(%k6p5%bk6&xm^dUjm3EdVuQ6!$nA?C{T=}!Fxql2vu_gC4ox+q|T6>FzMu>k64yaR2GyXCP$@K zaxa70#{~qFWnzaA4%5+0BMiD5A*7x_?o$F7p#`GfTsj1U^+yJYJ}5AhoTvscps*vz zQ|REMOb?i(5#Sr)ibq+CM_p*nRk@Y%&sDW+-6C)>A6JnRf zlapd2XG;;Kii8}-nOwC}G*aabW1v(nWNl&?7mqduGvYh`HcuGxwh)hxBENb}DiDoF z;w(iZ2iX*IauLZF_!L2oVJYO{n5Ya}f;2=vEV8W`1k6G=3Okw!W{bV8<7C?e%)&%D zk9dMKWIQ~wt(gQcLPx=lDA5m#9UQ>9)lo1Y|6Uj|HSzep*h35Y;W1eU7gbgMxtwDB zFFN+`s$!#9aM?(UkXuMQLj=vP^u(W(EhJHhUC9Z#lqF>+XQWgoSn^G(j?|=0R&}y4 zC_smdtkFO<8eV?ygWtPRdmw z&^w4u+O|u63s-b|TUg2$DXS>}rFjP)e3Qsc<-e~XypZZPeacm7aX^x?^xY_hBO&<< z)G%0z0G8+*A&K8tX=L~asnF6)5y(B(alG|iVL>Hj(3R-DNkR@??$5?p)eWj#gvP}Y z79qD%5BBjHj9G}`$CSSO0Uq%Z%-}1Xd*uXM3`VGR2=NDLB&A;I3ECwYJ=lYxHpRxQ zq%fkc5Stg~dv0=j@OAWqX`(LaZgi8?h<9pFCZe5{diw*(r?{|x$dB%9R|V;PWrlUb zAGbJevQxWdc9CxatXC=N{`rRX!yh8Cj*|il>BS$$u_Y>>3h-T&CwUfYB7iT|q0h)S zbCCOvQLRWl>;u@zFR_U}mf_zi{v{1*2bUNJxc9bUuM9-JtMxAj$$X#(Q1IRi82)e( zd8}7`njZ>+AJvApBL|Ei_f=sz7|~zw5xcBuGT*^ED6H&A(Mb?wtMwwrO5nvy_1eY& zdZIBQQ8UE`UqLfV8+LRaa1)8x=^~@DfT@)=VH!7taRwZ1*^ye1 zjG_ip)hmpIZMG|k9?-_{(YO@8;5qFBG5af`Mg_s=ksBdTf!La2AA#6Z<=m=wZf zV4zMRqw=L6g0Z&6KE%cwFd$q?BAcRv$*imjQ;wq@Q4iEO80lch4m{3Pa0XjGdK+uQ!0N!k&dQLPLbahoR zQaC4bRW*&;n6S#|aE#PYD=TSf;Gl>MZTL*Ix~Md8D7l&v(JaAF(o)RQ1TGk%gGD`j zCFBfn>h~oEcQibCz!a>`B27EkRCr7~xC|>yJBhU5CT^-!ZlhG*nNlm4A5%?JW5`5= z0OgFNg-??wS?{^8=-7_qX>lr&A(X{d!d8Op4gu-wL+&h4q&Y)XSzR6(LZgWO?}J9O zEnJ=zR#IM6m=?QU7}Bx?ePrJl>r4%Dhq`3H(Fl?cH9~I(jeO-iH9zhi zPW@*XN#ex<`n)8kJaGLbJg!X|isve$QffH202`9N={te zg}=x}%(dK0SGc4rPf2!m?0VR`VLVAd%%MFsU>C*0 zBHKek@Qjs#%4=Ytw8jE7LVnLwvSEX~MwbaiPrRFS_#@f{Ci`gmvxDndQ{V2YcYmN5 zONO@43yyniERs~L;&=D}HF9H3eWOuHu(8#5>R=H7o(;0$R`FPW)9QuVG_@cixFEly zdSnlv)k}u)ryuR&P_VK+OBH*hU~NEYP3PGNnfg-;!#e>{8X|aP-v@7GOK#2v!5A4E zZ^a|wI}$c{ps^=3F)7h|;CageZZmq6NZ!U9(Bh~beeye$R$W}(P(Y`F0cBJujWH`A zXa4HdnkN3If|ka2OgX(1)s&^*%gaES$vDj)$`*f?JHWX57Osf3P8kR7r*5 zdLTs8${!q83#ngUJGuOm<)yk~dpt&}b1QtjUKId1E9T5ar$LObyEDjI)=BfNr_S9} zdrh2>!Nzn`F(#_wtSof;hIx*SWG9jU<6h23O0ewkZAA?&qAZxKsA{MxOy=Yocncbt zgMvNECoN)dFi%3KPxu&=MJ{QL>@jKFd?Z5KsVWd+&1nys1R6Vdwb(iPn6-4#a)Xw2 zG*$4)@q_r!;9Qqp=cNh}1WeTJId0@=YTOEBS}r}PI~uUJdq%%gs%NDlCNmUi=cr4# z4c&2PY}q$^p=0?~FFH-v^pf~h&ng`1Gt+#r33l*mv5u(7WoxNus;Y$$Czzx#Hz1~0 zM0m5M(Q^hJsR`C(o7GP<&}u6YFhfc94|*0nede%p%GToLlV%RXr*3#JX-KLD6Bi15 z7CmtcS$N_RQ%!Qp05n;r3#sS@lFi)R?jCj_(?{#!(#*NIMMiTY4(U@J&PwHU7o(bK zB)g+HqDJf=me>Hd$OfbXTw`rmIsB*tCU3!}GcA?6dDoMW%K4&*kgDw=Nwp{~CQKQW zCe+`#`{wGuIAQ?v97)az(~bgiGFitb-!K#KkNpr`0{t^GR5zdJ8i4r&Ky1HKlG7wCj zUVvWNdJlhUIa+aEiA6+>!G+`FURv^lZic{maJhuMgfl#UNd))af~sK@T!A=R&T2=m zSf$X^w3328d5Lvpu$}LC9w)Mf=OQO4x}W~NGSe7at&_jlGo9|ATX|$r@Pv1$2(a(5 zd&zOW<6(Bim3JjZt(W<|7C`XI0C*>6feMi~btG3fFdsdR7D9C1-gwuV3jN3w(5<=e zP|37aIq~aPti8>Y!b>Uj>q;SC7%V?|9M6xBPg_-ED{OGxU2q{qh;3P7z7+`@O$N7( zRm{@5-GR>0pf!GuF^ANxQJcL-M^8;mSZ&Z;v7r<&ImEpP*Q$_lCXlWq)%SVIr8@$8 zpp1|m#tG@m09pmk>IzUlp}SlfekXMAqo{|An8vMgH!w?E$JiFVF-)iTV=y2=VgfVE z9?}>j^m?>rE2OK7D!iq%I4rYasz_I`Vy8t{t`&UWcIx*%&SKALQJlYR&KQ`C( zMe;8{J@{c&p4PVEXhs)lWu&bJk)w8vG8EWGBL-}GE-22fqUs|bHhh%{G5kk)o-(oG zRN&XQ&aj%@c8iq~2G*947#@h~F{RBytgW6cWugt|wmi^)&QXvU(Q^w!Qwyp2~AT6_lgE_~&oW;PHe2u1&aP^+dk%=)6m)#EWJm7n+q( zrt})PbZm*y@Hl;lXKRR;lRWULoQGe4M%#EI6H~GV99u z!sIB3kJT`^T*l2ZkJjI|*~F9h$n5@k-^jCCS?WytQ9!flc+5y_Zhb#$0=s{i+=r$b zmpxj|42+mMw%o##pjBWM!LvSm(Oc?%L}1A|9(GF@Lp`mE4d!%}@G#3%PpYo1@7lIu zV6=Lrin|J0GV}ZA6g7l<%R|QY{7yKF#l2u)p_)Q(LP?V~&fzp;7Y9 z=b9R}Wy@pK(YmBcIw}5zZURe{&sVo?0n5L@Y(*h+jbsOb%U)wi4< zszWaOowaK{yzXG&_uVqTN@a@_NY3tT@i&$>b?vaWT$MZA5%5T~L;QpN+qq=@D(N*y zZqvKCn!E|3s*-kfr9E=1!`^xpSl>{^v>+LC?;W$2Nyt}shKEAUeBgPyS+kOm}7}S8u z7yoTooBdpb8v;f*sOv1HkMIpxPD>z!H?*thGVE9%yt9~05fpGvv2U+O2IKQlof4x~ z7-An*Rf$|aBLgjlqYbeOM(J)~H&K z%BL}VhU&b#q~9%ieTQ0>HYvEbAhm%x834qE3Wf`&v_{1d>BmD4FKr_xZUMLVS1kWX z)Nbz=J16!zcE1Krezhrn#(izv@oj{qGZTyCIy78^U>SChWmCn-mg+?6x%>3g6Cd%& zfxT?2TSqRDa#t6(I^G~50YV)9vX8yRYCZF=HNH+AhIqK~1O|=zG0;ZI-y_V`Korkn z28~IzPCC>0b0@ZeIHP#L*&>?vifIPjs#vK-1@Pyu3LuRqS#a*B*_98BUJeN3VMSUjsZ?NGkV5#mk*kibEJL{LobWRUY^-AI|lX_PGHM-D)|cG z3&-~l;JVEiwvvOWuAV54Ud-g^4`|Zt7Z0kPymEF6$L9}ly1CS|3&-mZc)Gc?vx~=O zp1ll=`4S8%nCA~h(hLPa8S0K0oINKRU7>5I5{9}#*m(rhoydQMz^ceiLzs>~>)@q8 z>m!VuyfKc;2dzOrd~$7=)xD7R?#*r&&z^3f)6+*-7f;gt_Q)hHVb=U}Ml@H?rf#uQ zo;Lyr?((pi#q-V4N$2*?|UETe^?VZ-sFQm$zac>E8;;QoN*j@Z+aRYzA9*GN*`lP_FZGE|k*(bwJG5j!vIM z*(-8sJqnyU#d9@jy`m#m>7D!|Iq99kBU|a6g19v)6Vys~*EfRQLSSDqhWPFLM=|i_ zSit2CB=I#tns6fC^-ZDkBZNVq1UP&4;4Hi5U;YF^{#AIiJKTSFGR4&Sq3l=k_%2mB zQz#?oC-+SNd<=ghrOtN=zwG=__bYp}e{=8r$ZdZQOd_Oyi$ocDpB;AG*Ml{8eT)83 zJKcRGba~Ss{K6&gGfsj`sb{S%gQ1amBX;8sUkE68aKV@J0xnlzXzdQd0LL z)y^hOPU5}dlcXj_Z7|0359VzklJ zNv4YST#;UHX^e;d<;XD*34jZusND1Z4!9pXXW!=V4ie#*yG&GwNJ~Rsj2?|U`9;G= zcg1IMT|dUmN6$wuC{;-DK(&CYjEihB^fm)c z=-nW+xbu#ynb?BRF`>D2_8uk!Knc#YCNSYt@kI?@)1yC1$x;dqg=jG|b~e#`{@&ti zB(U(v<{frCWazRw)inQm{7Eo*}zd<*3h8O!|n(oL%3@X4#j^XiX2zL&6sC(XEH z<6N$-s-+_BzLl3LXI)u`gc%;Ki1|pIz2YOu#-*wdFd|m1K_}rySPn?v<-Jex(OMe= z76{yjPNQ?eyk%>e@$IGn(wBJ)4*knlw}A$vNzR$HRz8KcIKEV)2ErG_N{0%|C}T%E zDvK6>?Mk9sk2K4$N;?I>3QNc~jB=SFPrp- zb@r;Vyr1kz82J80JAu^8EQLRc%nr(@w4H@a)tsR_`{E?!hJVdBG8gGtv6Rkoz(jT_ z8G%p*(&erFt3StNv8d}dbZr-pe^6A5M_Gnh&?;*&WGca~TlH;CRGPKP8cav> z*PsqQ_a0O(s>zDPr8;L9frOwYk*p_lw5d#D+n7qTavs@kOsmwwvCWoNOB>w`rMOMa z!H4tG9KBUNH&ku#{=vhWahP_*#gF3v#x9i5uwdGQLCXayGT`bv22AyKoMF? z{OMcYW*m{_WY`8#9!T}j3S1+IA}FSWj!>(2XeB*Oq0`u~=+nB&;$V}F#lDX6TIf{l zp~^pmstZoAu#p`GF0VMSEAqtbgaAcS=j+0^6(a7k#>OdLM+x^K2i_Mxr!jjKDX;Pf zNHWOBOm7O$?8L3t)=)RTx!lw#3x4FviVS58tw`nOh?B*>4*+_t#N#rD`iW_lgy%`M(?X7*j1J5Zs!HP$W&Lt)vi_4&2FFfG#&C}EG3r_eC`=5wk4aTJW^xpQ@p+%d&hcEsi_Dd|f z#KpHAH5(*Le}|b{GMl-#3nu>gYo>|P$seAF3UX;1CY9gA(p@<*e8c6bwo^3QOtTst zH6T^)9gls3GVPut7tOlF+}6^=0DNIcD*ozrjd^%i-5rHx%c=ypaN=`V8=mbAA_aGv z(s6Q~?ua;kJ(2RGKL4S+2xMqmv#L&OP;`+?j>tK~+MK6e`Ez3+`;T^6;4fONC~@e0 zpa<)&^K*r%V$Edt*MYqx${$v4^%fQq`zM--!QIw-dPvU+$yYpvjcJ(?uMU$J?61uU z1*RDHdb4Cq*^gapRxT&WhcI%UTB-flNP^6UP+MBFXe2a#4WN-2*bH$r*OVHr)fRh;88MJJLb4tKXakXmW}sqVFM<{YEp@;FVcGXjIOF4am4H$C>#9_^-^<92^x#|{r_ zWzBZ5XS%y+;NK!(23e`r#Z6^MGHCm?7p6;dg48P8sAp-6mStM;5%K{JwTGnk8zmzK zw%@N3aLtcLIF)3kwL%jexPs*i4i1#P#<8vFg6&V8VW-(geodNl_yE}mqzBj#KGoek zyRk*=z6hz_5a$|8n{A}i)s4M0Xxhj`+$%}CTaoaGE-aAu(`^ZA%ezj+OtVkE0!yG* z9oIKE&Ckl?%qmz|AjkLmOXC%D8GmGUGi;y1LO^Oi2R@1&)T(2DWv+66QIey3B79jA zPDgVU4WpZCGS15;5KL)O8d^UdcY2a4mKTIJ7H@+^AjRxFxx$3m-DLcc>wVEq-H=cLcciOJt?TH&B z_onOWxN8F*5MQmowU9qfeiY5xFm1-L)1h8PX8GwhOmJ67UD~N448tz%`M(pcZ~H;ugYr z7m>jaX7Q}I^gu3MccFR&*6zCNAPlqE816YJ5=r}jDQ*jDiE%oq-`a+7jhj}gT5cQt zAUyeOgIZ=2SIuwhmOS~>5l_`mG4%PSC2jJ37+MR{u}P*XA@dml;2cYirO$h|W-l1nh_VrU> z1h8mYb0)inG-)Ds-$0!<@N(wigJRZ$wnt2dMz0&ShlJjFk?Rap?$fk_)S8+1W3*z| zn*JViz0&ILg{jpT^<>DrQpTDjFpC$&d033(n^m4$cu!K+r0Rp=@rKpkDt%N6W$Zx&h=ze)`;0a zR?pKttjGSo2~uoYxmV7EUj?#tb)hkJqY=|HsHgVtg6+98@&KMJC+zJ($SwHx6wNuu z$iIx!U@rffN$}UOAb=vA!Nxmb-D!`A7231HtjiFfM+ovlEfhu?4N*Enh6nDOI%7ff%MP|}YY98G9G>&% zE2K9|Z+dXf0a6*~5;X!Tb{I9_5e^W}hQdNv;CVmdgS9B3I3=MpMX5Md_AR9;bEWK4 z#i>)J|6F5ckyB)#N4{ZrZ=yNVeTL)-b(cavG1;**L(}vO?Wm3K82f*Rrw>|t=@FVB zcD(a=u$k)I76#mQI9#&Z<@C&c7C2m9fjt)t{zHCW8>RmS3f2XKb+-$MZV{4?{8M<2 z9Q;T9PKU5dda)X3l>q7m_aS=`=dqEEf0-(-Jq z7fZo88T}45{LffUpRF7rxYER)RH%{)dqS)N^wfHz`61kVV6X{b*a z@&h3wq6tg{D%^2X8aYvpbBrQ;$j?N8xBzavP@yehK(_fLZ=KO%I_BTxr!}*4JGF&` z#N52RW6apEe&ikqpddyNLkG{s(SOvqyLL;)F?Qi78Cw(Vh){8_r%a!yN=vrPjZHn% zp;%0&5Y4y@UdA~uLjx=2DyWQ~oFsh;B1RJob*Mc_7GF|d8zDfMQQ{EWrr7S9i%s}q z!g!+>(dDkZMej))+Qnv%sxPLJeV|$w<&-GvuR0%4Ok)Myq*lK6Op~fat8-KirNhgI zbu*tLp$VQ?fLawQ5Gk+8^n4`le-2l-;cPaCqA~)DnPhLE%hJTS?dKtR_|aS(pJFL~ zvfkY!_3YMNdIMNNw#JboUBof)!k=O)O|;Z5Fz1t%c(JB<9td1|F(dW}iK5>)!uK@jau#4m}N4719m3;-nsG5FQGk2(q zI@a}+?||dO#(oHsgm5v5-A7?ZX8&gTeRzy-EZUp>AU7G!U4KVme<%KQRO3xY`E3g_ zT?6V7K6O@&CNG>u-=M;WIOudt4Q|W_U`N5?6wqO20UjA?lpt+reVwE}u zdm|e8Yrs$D=dXE$hWO_>+{lDFhAx%t8d2npNsK1`l=2=<^B3N1zwqemr%$`E+YiD- zxL>ZyCQuKFKi7qPRDCuzuUcYTsNMilwuc6O5rcf0@c>6gb_o#Q`dIHs%ooUE-|ni# z_d^2USOtvc>ERpr@;T*$6h$f|YlzDfC1UIMItD}8hnK+DS0f;(2%+lQh4%ibhqJwN zi0Xt?YHtRM>*opQN?g3uPZ#oifp#prBIt4bYQSs%7R`gqAP_N~Ij5wGvoLHR27a zPsKfj)gavFND*HNAN@1J<6#WUy<(0jU=Z4=tACfLq_rdQVlN}Lk(XG@j@x5-qZ>K5 z;UC*WJ60%y0I_i3gy$MT54O!~f##x*x_5Xa%n5g;Uo>_bvj1g9E_YN_LVzZCx; z#h}<0D^+gxmA$Jce8ngZb+Z!Fvf17Au!r9Ld`&qj^(xJMD%cULn8sKOVm=;xfI+)r z*j^DHxINcTZSY@IOD*N~m-P+yf}z_X!SeJ+O<9g}9q1H|n}!(guym&Gg2>NZ%x;*X z_g;LPAY~1@SbICcLe_j+0h1m0fSdly?Q&J+XG5eA5)0tzgXbEZvtfX;H_p}%Tea#$ z1k8*AYBt~CZ8Uf{71lMm`To;Kh&8l-`y|}WLA*S@5rkHmvn&zOIHq2$&1x#Sv0A$b z$MA|uP^r>f7hbei8i?rSdo&^g#cB8stlL#Cs!vgE0=z-n4}fvA_(P9(vW+Dbrk_JZ zF(ZaJ-s+Ls0d#O9o?Za`pevV9;#P}A+xgPXLb*1vEW0T2k`kW`lxrrxcIpk(QVSK` zLN(k%H4Z^Jd{LYE$~NI!5FTQy)~^0AeUZBepi8$=PmEDdlu=KZQ4dHklLP+1PLQJq zAA|^tOtsJ)!3ei-BwIg*btV0Zs&;intEP%=L+Qiuha|arL><$J*W{IWC_}>vj!}(m zfboSv4*iN2n;(8Ky<7Dn`O0FBYn(xyC&c>?h<9j+cPxl^@XbpV*3(%7P(93gMxE>B zILvz^@--sudg1>nf)jG-`cxk^(1AD>aGqKa_N9UQR)aC>0rq?YO3t7hN%uGfqBRbx zHFv7D7pk>*sx<|wHGjqWTcvt^BXHW|sx107rEXam^%+_eXtyNdH7R%pC;V(9ShpmU zD-$%EBGR=Am(!HjAj7L-V~6Bv@~6XdCbXjXL|!n8Jy(#`@0$KdZ5rdsLazqAYCrKc zZp-p$JZI%c*2SL7P$G{Ums6HvF$U{o{|-o40hj@OW!uHt% zFG80=6PHM~8n5s{dpP3alOx7-!)cW=n2sV8rkT`bM-9{L5=@Om5x+RZa70XXO!ZUE z+>o*a(lWBBs|i#ib7Sx$hgm-R&d|oGd5LMs?C4Q61CLb&Vi>D0 zarkYx)?}#94q*!`G_D`h)RBlG_1`41v!Au%985uaTabQ8HlmC-blv=U@nN)cmz@N8 zU7_(RS~Wo!(p8tKmNtT0#k)i)B7`NoaM{VD^Yh#m!d3f3+%!EJ5A6MmO_CgTQIKScTT{qdo z=@yY+$C7Z@;2Notiq%N2(KEKVzo?l5X|i^*F;7r^i5#-zz^Qw6Qr-Tks*7A%iv_tC z;7fE;^hUG!as#1jV;bA=MriyfATHKcT>bb4K~Z-(eKydN*)>9~cZpW#9Hq?%tJ{t8 zt4eq!E-aUm2L6DpR?)bAdfXr@ae(H8RGi@mGb2XFqPG6HBkcH6_ZU~_7+3c=t9uGB zdg#{cY&brc-v=yn^}bepx+!DgKhkEKCD40Jsr#OC0rU-<+;RGZ6{g6exh}N^>eq&< zuUoPca(EZY`O(mrqK+n+uL(h}w4A#){!bnJ&W!V=^uzAM^EChX=~pr_!M>P^Bc8pr z0O=QVY=XP-ucq`i1bGypogSC6io1OqRWEaFF2JNed0B{+k@?CSuA@=a~cN25zM&5|YY zziOiG;WBm7ZjU3gSYKQRn=C#0NneTHa&tcpvb_o628ETS+&V@l1rlr>A|eTBtR&GL^aty#_tgKuE|Y!%QjleOB>5J`%pi?f>}vXH_w@R4(V+bgD4NY zC=Ys}E_-24Z^TW3c9%{B-iTblie@(|dK-RCH^Scsd`|P5!HGQrxSHG0b&sBeT_|Ed z0o6Mw13rIf`2+u8=eHpTY(4!ULbWJ*p&{%@bsH*n%y4Xx2FmsNB3rD=G4*E*?R9M% zQ~QS0o{{gHUU)EK<>#6YcJF-{H1=Ci1pgJ&j!#%l3~IAvBX;UiEDGhe$3C(%))z0H zX_@ko-!JuxAE~zqb2om9)KCf2?4m#o(z(#&P0On= zHr4fq=S~!)N;>W3K6X!Ga5p2>W z?sEcm>%1nY@TSJ+WrKH^w%i^tHWwIMOZ2M;!5?Y}_7F3Z{9>>yg!Kb-1URhgjh;Qd zk{^Sx?F`FP$#M5axILsG`hGdlKGlX}&Nuo066-~K?F~BUIU4SJO27(|DgJ)!kWSZF@~zVR3Z4fo|5PZWbke^1dRZB|v$v9)MB>~( z-VFI8 zbsFgq@i+!;ejZg=0ZELA35@K(CALxOwHLw&`)7cExz4O%D+lW$hFvNBmaKMr#`7K5 zBHUQT6Y`g)+{)Kc9@!o0&dWs$-g>n~TAo4T%u(I}olLR7sXiIeKSaiJ95VcMk%g~= zFZJTSBmInGj`ZRt-C}|INsCEBudZWmlS9pH;7XUKWoNWeL(+8L$u5<8???sj&FfvF z%EuaTe1eldJLqs|6m1j=C)?8JHCJ2Ph(V3<9^|iC8E*0CFQ~ls$-K_VJkK=U;a}y^ zO-h)jd)OHn&Ejvmr z+^?srRXnk9xY2)1e&I@dNgl(Ny)xE))`LyVmn9sqQ{D3H>v41Z zClnrHjVs}=2Lev$y0Iv)uK1Heb0ZJE^%*@CEOQ{sOqzK%{VeA^Xb&Gq_GeEZcHZxF z@2)<;`!TU@YsKIA{dnqs^9(G9e-%IIHQXQ+Bm4Re>}xKZu;LEtF#KP#W*2UGKdxDU zSr_}bHs$uW<>9wXUj&bYOkc>4c}!o3Cj!QwuqS;+pZZh&Lmw|Z7ua;`6IdsB&Ve1n zyzq}MQ()=l1_Z-8L){Q3+$S07Z92-cT8162JS%2U)|;kK)~j(XV+#mrEy=F!yDRT# z7QtTr(9FX_4#gg5>XBpl(!2;`5tMtP_hi`&xk1whmhG~-g*xaj)j4*2>pl)IY^7P)x0o!y2?%>bmrtwJiWe``P{W~pJ2%ygm0lvs< zb!oa%{r~6;7(m}w8yBHD`#}*z_wu#eSV5q)`-!3Pw15btdrYwD;r$<4?5P3o+Wq^` zy!mOzs16|zyhwqh*1r%y5E}!EkUSjdfkb=67!ItUV@rc=;CR*`W5fKOM}p$3@rgbBo9scC$hbLj5}y>hB}CzT>Oq= z>lt~B!udjLeC@;>w{Y9iG2!p;xNTl`cc9=(_o?O+VSD(!zV8(ZEdp`R;htDEI^H1p z6{{BID}-l+@~-?9Z3iW9K;ytUjiT2eXQXdU@!p&^SG0V-f+?r2+V$Pt3qlDnVbhIK_af8qlfDoLzEN8Oa2pkfa*kuI=kV7FWD$ z;)W>)rY&qXyZflji~d)lpA5m|uRAyT?~(&M!nj7cNOpjUTQ_AME=a5%=+O$tNhqP8+)(M46M~)PmGPDLZM~rHb(5+g=aci;Zrvh!lGe7@DIr=|FSm?Vj z;LCrNW}bf^`u~ICj2+#79br*(wD=W;B4+qc&9UgHe%O9~_>iA`>ttcO8d%tU{RK04 zL@)ved)=!F8%s4;Ex40iK<=bfM`wn_^fBq4x18D!VEzDJV53ung6?t~O0|llpt3({_{s{X@R+852N_nQCs+wHj|)@rP#FV z1GgA!q-=5}R9f%pGF(w-7c~}hISdDzMlf`T0Kje`3kiu5JVg& zNG^d7;lb3&)!NzWHKlkNE0=rhYU;N0)62$Wx1Hp(*ZYwR@R!mx8ExG@IW%EO7knR+ zu4dQ;mm7A)>&~6KKagx+;`7{?PUnrg4G@caHOv=|)u1so0Tu3#J&_!%M;*!rH~LT< z*v1|5x8|yp8Umas!${&3?q-0NM?*AO>Ajfjfm-Q9CDZFtx~^o)LuKRZ(i$!|*vwIt ztNYnGH{A8%TK4C;cUPa(STJrEINh_NV>lSy@I+UV_H{qitt1_Zn#Zk{JEUCA@mOnn z&x-r4rtgbp*K}a#EthT=uHEf!v^$cV?eQ25ZWoH%!y#+V=5!(#w>#PO-k1(|dnVb= z)BejXZqDXK|Htdr$E`0M?_aq4LjpM7$qC$%Zf=h_ve?_A!N8B#XrIp!USA_Twk=-Y z0|oCWvXAa0@14Nd132zi5Z<%m%2M}d3*V<_Gx6-^N0IOZ3Mgf2#NM5gm$X0mUO2A&j4I z4CWuF(QT@)&7MaJX8=`ykMox~QY44?*fe^qW!U4N!^su4mVgELpGpTs#Gm!DTCxaE zU&&FjKhniC+uVk#y|XqcO5D852iCeY(_!y=bkm0>3Y{t;MTY=m87lbMlsROQ z!U$AD{rNHg+${|?Es-$}3S^%zH+RBE46A{(g$!u{IU)joilI#CQj*I)b{;kB(zHk= zp^n?=+Yv_JrA5i7PvI|Q6rv957tCLmC&vsA@wpm(FQmyI36nUisA6$Kp;V?`+l}Gi z(CP>O3g)E}thW#J!|gUr=peR|!5)IZc^A&IuV6w8nVlK(lEt@1Y<!sQ+q8`S)@{Q@`xwN|#`HIe-zs4D|_@#M4kco7RC-v*Ru$1KLC9% zk04`m7+DNzA^Gi?xGxwJA+xo`Wyhh^Ff3Z=n3czdc=1J_nX=92)CB`4EaL+8i~gvBR1xj$yA>o3 zw6a5#Oc%Dki8@_aTtW_0qYD<}!lvRg#ydfr7Sb2^vAWIK7y^sZkngE)Sqwbi{|9RL9K zmS~$ggGMHLZlN(*0?iZzV={1qFO^wkW8W(RugDIUQ)%SfYweR?(7E0jU~RE?k@g;E6+O^#cj59s&U9K+vSf67=kL92!gSO;NW zTtvQ0ytqcFPssJ9PbeSW7|@%lQ^P&)XhlRsJzcXT(uj`-FHEM3j@8f( zw(7W2-9(mIq3laL(F~xGnO+L*D!I&R^02WYT&hopWK^9-GL)9tb_q>B|3ha3$V*VQ zOkS$~*9|pHULOhs)^w$hBkiE5n-_^6vc#4k|5&z)VXFT!y8Vx2hE&-4U&X4sb}6P3 ziZ1o%?&Kc(M!t%r&1juG!Sx#v(0EBS#{uN80^3P6XVj=o=BQ?+_O$b11y`Iu&kpz{ zc6^)+vV6QUgt!LkhMncb5~_t5lncdwY3;aKLk1)R3nX0FTa*ATOlyX-Y_8^POw+&^ zUC+IPetI?LMpjlccd@l!NI?V~_kBBSC{R6>3bDLc9t8JT^(u{Sc6NrDh60;PshqAZ zg%Udrp}642(=e*6AwpY(C-LEMx0f4{mQ91^Kv*ncHR~97*HuLi;BWBG^{XDL&I<}z zCtEr&@DB`@VMgqu8-3iwD`Sva2&8QfSSeLpgdq&gil zkibdGvg(n<;jJ&JAP4r2)ie3b1=w$=7%Cbg)?RdyPaU`gU~g&vg5L(wP12B1T?o?{6qi6+ z&qVgA5eD9}yEx;YxlA!Nxt_Gbig#pb5{76qXe}6mV+}i{`g`%KCU*b1uFJ)gA#ScM z*K?OUYEV0Sq4Z<%aY`Xb?F$*PzO#NPvtvyw7;t5YsJ*Iz{*>&Ky}E(&soXJrYWLGA ze}a80_4}2-l5m&rtG(Kx`~?1}+*&0Aa+lL9V;uBuDW?d@)oG`c(uZqVNFYg zF%VK=jnc#E523OS8jm?lFI**0POf(hj#gC<9v`_KkYrUgP@$|mPIs{G8XzsRE=Wl) zsvD#1nqX2|RSuR>T60#dYQV5Ai2zkEtJ9$53RxnrQZ;F;*EMibW=)+^TJ=t**{xl= zGbS+W5jT0_cA}O;eK3YtaVsBBxtny%soEWr)a{Zqsa(UPwXPmmF27{gZPPUweIS$F zO-E93MV!f+M8cz6%d7j7%yQqAOD0pLVL(F(RTmApQPiNiT+)CKRbG{yUC=-uNlsnS zfbQqkINox*Q%$)s;wPuFX7TyroSfb7H>14fO8Y?V+A=V$u-4vXA38pL(95Ob%KOvJ zZ-REe6RC`>S!0S;d5P%CG4R-=Rr=U|YzHUG(S;lNN0UkoWPM%h*WLOZSYDe7K3)bD zeYrJ0s}~2w-%Lqf@PuY_Q}j!W2}3+jvAn$}HR-lqs*kx{Fs|=07;CtC7FA8UMnY>; z$^?7EC+(M%6sNdQkqTw1w+J3~GR*_G+)(^`v10VwQU5JYhFH+YU;QE%Fr1i@4Wb2# zvOqClFBG$&g^J47*5nxtIVntRQi3)QqAwvbz?>+GslOOd@;AhJ31g*SPf=E440l`(;pwibph)ONRUgUr~h%*}ln{)(hb!b01V^|KEJ*~nd21{(scz+=oU2}= z@lhEvnLdZ!Dnfe?B#eRCyxc@6>i}+nBL{+65SKx)TIR6hJaBrW3`|)eUkHvAr%`kI z>CL5{rrVtjB)G*A=c+tLsEi2#i6(mpkCttbhK=4}KB1mPj5##;vqk6Zy`~TGXYdUh zVKpSOlWN|;v5INIM_}JLim9Ajmg<<^ABr0;+4NKsJ_`Ip!(hl0cDKTu>1Cm(?}VCI zb|5-o4!bc&xwmr}ctXy6RS!eW;O%(zQ}$QlF3YYBQ<*4@Zc#+1WB3=`k&wkRjyhy& zimb=!-6mku?>HaqB3Pm9295ZUXf zV6~OC3jOToAeP}@;x_`j4^5ueN000ad5dQ5Q7Po8aqEyBskSlSRqaMsJ(JBfdncM} z?UeS-5YwAwp=uFbXzYwB3pT+_X{GN}zUGM>W4#=apvz}k9vo;SVP_wjby8z1Vd3Ix z>B5E?otFpkk~R086hHz(Zrqu>GHO97jY;skljDg1bn=~=m9Rc@?a~Ui1PaYY%&V7h z6-o?kw#*#ea96*muZV$DWSxNej0M)iBBN6E3ki?4>{Us+9T{8XQc{O?jHk;}{YMg@ zqDMx4w5jeA_H0oF=0^LYw@pLkiW?l{%TzNr>6d^q(n@w2dcSg2#~hvoIM})bl}^vV zh7u+f3@urGV(;PVN^r>BD|b)rran^k8amj!IwVYLXFiioO(vWKZ>$>*qj?D;3l8MJ z&qMz=eExfsdtf%`9eNWdvoyw~jD|Whw}XEG14WNw4jUf+yvI&p zIt#eis*RvO9_h=$8~&F)$_&R|o^aw`f8F?Es%UI6jyg6)zy`VY(CM2iV7jEya?VnS%JYet11Jjnh9tsUE|#$<3vRc8atXwStMp`@8}!Gy?LceGhFj*cpjD(Zjt9w zM3{L?*CD14Z)3m*Oh;3fNbgLVsmjqZLWLeGG__W$DmVt)Cs!FY)0}Ma)9e1`&;Ai0 z4}xzRq<{|r7bf_VX#iy%Y-3NE^`~?Y!=6;%fPhaN7$CXtwH=e6J=O7mV)S%HOZ6MP zuEA&aN?@E}Rlow52Us2QWUhIk^55IlLY~YX8wA^8ku{F|98T&r~j5M5G#L-pA>E1MKaP zfaiUvJ*WR48&i2my65UtQxv~yT)Jur^MZ_hBR~hJ?UFyHGmqo}KMw?X z4pp6bF<=c*-+?}S4I5yJWS=60I%MY_E1)~qWBX65tm>&RclFB&#C~=P=-J>Hs9_bwd zL65Z8royMtZQbb!XdN0Z0VX(3ogA2D!OLsrutVN9&TMIcH#194&vVD7sC%gZLXPbK zbxPVWVk0_k@F<8W!)53V)a2+M80Ya)(oFHrIlCzW#fpugY<$}`4Dh~NM5N=$>=X`1 z+sOs61MjdlP>ztdYahTS#L=TxFdDe-!I>@{<15l_k-j<&hN@J^Qi1^sH>ey`$V^`& z=b+xX>KgLN9NqRT#mY_s)fqh#?y3wGCNdpm@hD3oYz!Lg98`H8aL9-X7bJJlx=GRc z(V|UF0Am-X>27l!xLdzt7ohA&rasZObwz-TV*mfQZiQasJ-_z?L)ybZk8~DgO9X-75%!0Q-x6@L_r61L%Q++H{zY@a zM93Bm4<7-SC3IGy^=U0m(fAoLdMaXDXtv@-_qimh+Pm!k-bz-;vAz zB)l(Dc(=F;ybG`w6~q_Vt|L~rFnX?X0QMX5DMHQS(Ua!r^a-_##{1lE4+rOT24pka zcV)N}-y?-LWCNoS%ks1|;d5$8y8~S-Nr{I=&aZ`Bjh(z$oMLOLar9JXvd zKThvm-Mw`5z)ngG&nG4zZO}_uK!q?UN~KFcwyJyUazxTBTFICqiZ&w z5Od#2)}I=ZSU82opM0b-Z>LayIlfjbBLq&!p=fd%Kd|4}ibTst99BQ;b z44^TFxM||O3mQE|9BJR~NA_BiaY1I{15CSix8ZfeJ9|pm$8Vlt^dz$S5y8jGQnnc+ zY+H=$k#jLmq!B)0hI-^iBJ}AfnUv-c#4I8S89=%HCjpCSw{Y3WaA%G(EeBgZqS)zX zW}1zSRcl7rVabAkL{Rkv^8FzRTOsM%fsM^k=h*~0gV3*JpHgihbbD0UmmbPY%53zL zeWkkULOLzPsoqKoG1#S+HZp0^go1?ztG zUTaCets3@sfW08Uf8+57yM?d!+qMIBQwO367`k3U*-AFM%}ZiOQmlXJ%mWCMc8LT4ryVWshwH^cH+FGizLSD&Rf;O{}!FhO4 zi5JlW<}IKVYpO`a4hi$@5*FB~2K9N1a37s=8OsPwHUNej5)X}vG8xWypA{frw}9Ya z`}l5o2Z&~7m)t<>>45SSu&De(_GMLiFlEfJO*zaFCo!$3r7ri85YLDeYf>_^F-W!$ zIuV1n;D9{XVyClIr@3r$AJ*wQCYGHsjV9cPv51BW0AU&|xY0x+8#uuxj>qLs-GWL# z9R2wnHO1df*$|ELhNzO0f@^w^B&Gx@2j>17{zeJ3A)8V0KS>i!zROPt59 zKJZxNVD;Vhh;Vgp_^Js)Tl>adFx#@XZUX=y; z5q@iG+0tA**=DQ&@pl~PySRq-wGcePfW)5p!gNCt>>7D;{pAv~Z0vb_!l!U}#P7^m zw6kWr(l}q*I6h$z-TjBX6dR|r*|;Q(vGG6Kc7#davo`RU0gbol0%d=!w!B(*<~uX7 zPq}5fKQPX>W=v;0%?_~VI#2ewao$lo3TJQ7h2FZlXRRARO|+`k{ubvnF&u(2PDL7L zq?((1Y20e$NhEuZi1Qj1d5nlZM8zLt6t=4Pvf!cFs|C8W$^ZG}*xzPv7!&2y*&xxe zQ;4x3DFJ3Zvr;R_TVni}9m!b1kL`wiyM)2C+YTUF<6>U!vN}JTHi~BbysH#Zms@>IUCqI z|MxU}b*h9nk_z^yUm~r=0KXKVMv-E(WJf&f-vZDk8|tE@0OW|U4d(O~;4$g+N#uwR z+BQ1!>&|^xND4yx*+|dZLfyqkPX#*9x!?W4Pq(xxsSHxvq!*LN&&|!t_Qy=7U(e^w zssuna``L*1KiUrH4uwDhwvha`I+%?uaH9PH$ml0g?Nz|+rvh4ZdJVh9;Oy05Pb1sQ zk?1P7L@2fcRM+;U;0=2&FITXOt+N50woIMVP%ryhs277+C@&2=x@UHWUL-j7yS%@S zM(W|q&EV#z7<0`8O7lY7`sxv)V99ltD$F;Yo)uE@vd`9yHRui7q6!lzDh#TS=Fif+ zRXuwA7Nw{OpvuqW6`NL~e~f(!nc+*wmUuMfAz!3A2Cl0^izl(amdnc(gcPG;X_!$% zA>e^4C@-?;7Sd3D@n>$7(WcB!%Hfov{49qA1)4-4&KuLQ=ACY>YhQ>>gxwm%yl)No zkx2A(Y>6qNW6!hNadCgoyeWAyIFk&kC|z;S(0L&kvH)9Tus+P!#jmTVsw6}s>N?b| zFtD#}&h<$<>i@a}GPQB_nkrrwqx&0PnFO@;TI5r^D-i?*4e|=9&9~;6hoqj*+~jNFAto7k#Njy9la(o_^W!)UHie{f~L_Awn&{inuG6W@1rzWT?5 zKKPt+*$FdPE4!f7=z1S&1NWe;mqbl%nA>deNC zGwP!%W;Lt{SrU;xlu!jQ~p{}U4i*yQ6REKqA(%M$ss2Uw9KSCG}~QxsL*{fd{l(n-$$04 zVxQvDZQlZ6W>*7YX3v967ygb=7x9i!*I{1;p?1#&!ERTE3^vRi>O;6|%5WRuj&>XA zj+fVdKQBz^G8GQvi3lNdZ3^KM4Z%omLU2Is(XOiAHqsgR~=W>M+qV-{3-YDoJGDbeCO2@4Vs5bCU=sJ{`}lNx^sBzgR` zFZ8v*80SnN=4=6JV+@JVD>LgaS=W24iB|O;|L8OgVUL8;YoZmd*;vM4M(!nSe?AKA zwY{Q`Je(YvpqVMj=yerAmJxWU4e0OGm0)=+Q#XcHpeIDfxPvO4mz%LjV~{CatgZK3 zH=}Axf~)Jl|6!iO51kkP#I|GmclCGdIpw38)yHDA@~N(PR*vthnnCOAfcl~VGiim~ zlDz)LS{A56TJK&>YLFJ~ig&w;^6`#9bvI}%@hLbLF*h5fy{v8qTcxvvj#w@HA8MAywoa9L>zB1$yso+PG@ppD6(0eehA(;5A^A-SBvruHsA1m1qx`l~(Eu&0dq z@v9_tK&q$`Y932C-Pj11QQ5zdQE_yVQc{gH$6C+ZQDZl7_onr0>YC*W|XS13IzJ;2nXN;>Bg=Vfi&H z3+7znU}3(HiX?Rwyib(zTb7aotnqHUc5@-@1mtRoh~+%sY-F7fj@tuBMllpFRgHTA zD_55CH5oaJ1s#_W?b5sc9fc1biJv%DJ+HGR@Y^?6BN^L%42DVRt*Hit&-nFR@!ONG z03P)TP_KI0)?Ez@rYswxSE%ORgk3ui(3J-eggQW`7~=DMGG`}b6*_R6j%dj)^#!Ba}!4kERk zId-VNALB^)k%S?KZJrs>jRgAciB+6f$nKt9c;F_q5kd1x{ojg+AHe_lYy!-Ftd;qN zv6#RE0EqnGoJ}IuCN?Iv&Z-91F8@oJcuLLYm&StZYs+eq=|W;v{unH5C4vRS{I@y+ zA0B8)d0fgOu(_#&7)xE+^}rNO$}f;9=0N%4- z2|LwBy`x$~$(W@YtAl5dJ_FK@RarmmcrsxGUT+@8X06=TVwuOKQZT_u%2c5mSy}4D zOb-3%5d9sEN>hdDGC?Thr;HTdFXf zI?;P8efncp3#Cc|cFG$qk2Iqt*#>DXmKP=QWA7WctOCxP&N&p0_8}A5;SAz5a?otL zq2z;ahWetW9Z>!RXC+>9_7(jUKVMCX+u;eB&ykv90}oq7@`G#{aT|Eg-xK97y9%_n zxZ4!CrK{0$A%JZ6sDpz&eq7bJfe`H+r)per*%!-Rjc^Sq#n(S_@4M)!qIhMa6s`wK zLp~v3Wau<|bl(oC_J?EWeo;(OSwl(J^DYbZ5$iPBv87O>$u&0>UKLRf?rI|(k9Rr( zLm^Ricl<+cjJSqMLqr&{cimxl#$~HX^~1p;7$m;4bu@-zAu*MNt|p&h5n&b3fxXNM zMrl{Ssu|Fr?)KK*2^uSv%@MlG&5Hi5IT9W1buOD$>c;B=K6Gcd7N+ouUE<|+q~1d) zk(%AS?oLtXoN$Iw z;)uwnGg&Y1F&1+K8RHM!Q!ZQ%r(TokbuU)y4VpId=T`MLiLyP;pybcYrlX znAw&y|1B~Q^t=GLS11w-gNogVL&lT1i~ltOe~f77*-5#JAlDowgsF;JDT?Oy5a8Yc zy2TPT3SP(2;afK1ka!&j#AILpL3j(&kdo)6d@Ks-=CJ|U)jr-r)$O`=&d=WZyzDYr z>K9wUOq31m@o{cg{S%I)^F=q|qaHb->{TGbaf3)(v-+B64|028=kN^Ng z|8M-2lCy!4m5hPC=&wrc|LU+(b)1k?&_{pBHb{*%%r%4NRqNvsH% zkcz|-QfWc&{v-%!A1_U~Glfxgd4k%NKe}h8I_qYr#ScKEi97KGs-Xd?L+eujF#WBB z_B9)$ejGwCNc7myq&|1`q)(oM3I=5|g3egp<*;mix@5QO)X$7Dh@GuMGM#poWq^LP z_14r&$hX*(#DbM+u57l6wPvvGoZ0EK<20xgRpcHZf1WV9I8yNN{U8ykC4BIyVP}yA!gm zrBa)ilPHv5o#!|QL{?ahzhh)egVOES#4e%svhu6M?UTfA&^`Whu!~~6O0iF`Flk)j zxntdqF3!H^XKxVf@~RMw{tVeG=5$nKHKffUSFvN$4!+0~!5<_E7ni$TWDT%_PRnXf zZ}+)~jX2qp$?%P?d7!RtMH$Fxg>sd|U~oU!{nalJT60dKGsw$by(hsvER_z>fazF= z9>dmR)B*PjaF1CtxGc|44In0jPz+#e-WKi%&^Pb^ZDNjNQVj9 z>pdAZ5tpRziNs?lO)CX2ai=KeOiG8Af>Gi{4I+*wr_Fs#vREa>=UF@Tg*IL!@}w#Zf5~IJ=8*Y-IdXRqq2g#HfkFSHchWX>hA^>1p(~yQ+b# z$|m7Q>{O+86fY3Bep|1?jJ;##QvvTemZ!dB?@SbPM z8+>6w&S>`oW=3A)z@%(77QFk6O3Y4Wk2U&vp|i5k14E{|%@53GuJiT_#82!&2PCE5 zM#PZ}nesd4s)uj(>_bUBw?evB@<9==U_cw~-9diW#Q-4mRr^;(I)qdKbHIRk;or%> zXvoQxqTwY%Y|_;Tzb<;perM(vJnYpiWSx;`lp5BW(~rouZ_*k+hd#HRVbpkQgt7l& zu=^GIpMgRut=}y31ZnZ7kZ_VO;^iX;w3mhEJ;gQQBrXUnc!;Y*?V(45pAfR*CX~aa zQzzbG<=9=9X%hFz;_x|9ToNao6OJ9z7TA@7+qHtjJM}feM^s>bh1zv^Y;tmRs1~!e zl`II(Sud4b^X1k84T^CN#&uJ{9L@x^J>gSvhl>AWi(QD0gd3&QzTaP}0yltYjUh*E zjeqqwhMStG zxR)=nxsratBcv`$W`9u{M=&s95u^>F(`kN6sxYK2(aOm!hWCGO%`~hQeBuQL07!)d z0Fd~<@#m^0juxgCMh4CncDBkM_W!F(S6x#?5T zx#nwCyJuc#+~sifU3(73R3jsj#2&mexsFuXTUB(wewZTcy*Of}%7Zptc4@EmV1L`T z(wNbAQr0xE(?|-+a$s}wV(7AKGZoxk&oF;HVo0^pt=S{flGLjLNf@A@W9k({TI^%hS89WK@*pFG_(($lLwL!{e zH{S=4HrZmJH`=E)g_%rm3-twlAiX~D_pb^MJvB@F0(-$7lm|}YkMQ=CK#uT$JZLv* z-r&BssTDkuRNvaG?l0DqBNSpUmyEM!2}-c#f~8CTQyVM4q}%jh$>QLH+NOy7nniOp z%#R8zk&N>(AtYU^PG2F^U>jpcuWcQlxZGT0Ok3^23qv?oB{{M99Rs^X-d{Gc(r7F3 z?q8UN`t%hI_+A+nDBe#kbtUtD5Jp(kLOJC+cZwM;xJafrm_ou7m5P!(~j={3K3-4_L$RpDLrhq4mQ2Qx~SGi&w`n#=*xz$ROik8mBc z4+C++9`&R`S>#^TT-6dQzc%bqq!r;SY8CG|XaH)5U(MYbtW(9P)$&p`daI&di^UZx zkiB+|Zg(H|QWW@E!mzhn?wL3Qp5&h_wA$LqKP``8#orQ`lMcl^|8U_5+F-Heo?%-Q zRmY+Q4oAS?;!E6;fYvVj69rA(!G8<7LXWuz=D+~}W-v(k{~|}2oM3hxH=+vJk1!0f1My?<$@%2&&U?8Xi@x->?OPF<*LJeoFNjI z>^?F$WsHQlooub_&G1>bpI*X?>5J>l?DkpRq}$F^7sZX=PnQSR!*Tr&uP1KbpU+Z| zjXO-*>)m}>THT3Z9ZF4y)_|3Ad3(5*F5P}C<+3)h{%%U z5W9XYjgHvj50$KejkY%cDLBWS4HZgU!!sQ1uEa<;hdX+-o8x^R?xSw%?%3i5>TH9v zFB0|%OEZS)VGuNCd(=ddw0(aH-2XHKMG<1RfTp+PQYVtP0^Z{N9w;(h18|k*BVx+u zpX4vUeZ0Qf{bb1Aiv6X?-kSYp$lj{`MnIZw#D+s$LY{;M#2^)}!BKSx^?x4a=TF06 zW3OT}QxMS98TE&z5SYreOqmM}jUi?r)_+?JdfK{U%h5bP%Kmdy4*I?3awlyKgJ%I%g=KL-xac-7F;_``SZ${IIY38myJZDdW_xwh21QL3N9+m zA;FyI1M=89Zk$m!z@{UwHhVY`AwqphLrwBol1fwQ2EDqMEKz zbe1{?LJ>-&p5m6!73CK64dgRSn8%JjF?wC;!CqN*R`g5&rii96{sGj}mv0Z}m$ z5h?fw0OL3}p7rO&i&t4{_Uh{A(&79ho*LTr2N+%ONM)`m9#YgfE40dudopRk>0w@I z(8VO((O7@}D`v=f(3D149S4Ec!vy-42wumN83`0k9edd-IJ3N9cV~GlkQ;2Q6BFWl zwroS~WN|*Qg!#DT@V9CFmx{jsfLS9D+xNUiExKE=HbQ{oCD-o@d6{M+4p}w!aA0x+ zL;e~NLbspyTVtHS>EBXd!m?Gi(~3S!CW&JIl8?DLoUzFKw^9XncKeET3V; zcn4&dzT@*V>hBy@l(9do#KYe^GpHM#~iR^m0^T2&(mh+54FkhzZs0F_Ri(s$sVWtj` z3SM;r0Ub|3~#yg zScgyT)*+jc{1Ud17lo#AHQ!k3jhVII1?RRNZ=`H-jx*YQQ~q#G4iz za0=^bdVI4iDzAiT*39wVbqIWtvJ^9{4_87C2x->R#7DA5S&F&FM8~{@$zVcLQ?^If z1Y1FH_9j=djan6*SKjBJU<}9Vsn^g`EUX~yau%ck5$V_jm7K=Aa~7LYFy_mw>v@#8 zIp6>tb%LhvY(LV4vqGYU>1{{A`_H&;4;jC?F=%rsE=s}Fcs*#k^~GSUYI!O7l-8#a zG1|R-=i{!~on{iJCY?kM&Ohh1J-17)+;dMJ|Gw-`i`!y+9Eu>i>Poh=1?}AFKJ!FQ zQ8gD_gAR*{!kBFh&)+Gl;hmOY^g&vSQANy#;Iu(rr3C^_`vNH2?-N>$#~I6%$5&Bk zB(NMwDbED%W@e0kEpi4M3IaSY${NUCagYZ#8$vpf$qT}$uu78Qm*tO*bU`316iTzw zX7U5FjGGvJgFu!mFsQQyk3%5m5-b8~iycW$7B^(8+l_cLA4pmY;It^N1?ZgO`(~pT zVW_Yoabtl2P`Dg$3@PolyXQ=)F&D=9_NA{oAg@Fl^%J9V8ZHs3GlviBQtdXU#Hp)s zg->KZE83kx%5}{nrN*nTb|e)ml{s>z(&>n8v7v^Ae!m1QG!Fpko;BqjH>q)4m2zDz z<#4^rOB}I~lTh$yHie+Bi)$@NLtW-!bRR}tnC}T_I-`R*WSt|Sk5r@g>cot}b56BZE z9wLY3fM?_QsEc3G;EQ32xe%{<9>SC(#-pw=lUwu~1kRZEj?$LeN^IbsQj!ct|PTYEJWfmZ@A{v~^69T|r$|jdoJ*J(WXatfPVN zcOii#g612w~oePzVt!s*uASG;VD*{5EwGCImea|mqk(3xsI}xvYSG+;umxU zN=0sXz<(*&7MsUiDY+h^4f%Wb?zYtHW9qxgogWBFVC&lU=^)QPO0r3A(;VzOnL{#mMOo z#mX$281^WmvsOMqW@i;VlPdE11;kP5bPaN}XF*M^$GIeMKCy z!DP7yh61J$i7;j>cK12O0hZ)cgDp9;>515(&JxhtLzA@pzY`Hl`;?Sd{28hV{Q!uy zl-3oSdtPnJ!aA}{ExEP%tNA|XC6=ps(H_uIS`RH!@B7DwgPKffs-_4=E49f4o7dWu zZR)p3p6AObVm*&R>IuPR&YUSJ!iX`F((DW^<`Ef>yXWd*Ug|N6(~(Ndjyg8~6=v=z zu~kgKVAa!}7up`Bul$geyC`;@IeYkSOk6QlAy^;GcL(u7Bz9^8`N2eY$-#w&SBG0sy(VtN8qao&!njHB8Bo(l5(-<{)Mrr zJ#e%7#Ky6Zl#1Jm;Ud+`{NJsnjbk2o4?8;AGSm-A%B9G24c;-7X84ut_km$QvE~jHCCZH1&_!T z*>%B+^Y#?DkE?GU<0WH=(VLhE&BMm&r)Glwx?lF^m4xLvDU+J(f&rOk7n7 zb-A4Zsw>kewM5c2o$0`R1h~rZDeDp_*^b13t_x2J#e2NNn^o%ag@AR=LwVD9$R;#CBd17TCbG9do(EU%E&LEG#Q%8-8mNiV69M!dG+xU5Lk%({ zXGKqrQ}3)N|CVrENsyO`y{c#D&wiV?@<%9pS1^s1H29y&i?#EXk*aam3 z=^_C6Bnz{Pp(AOit}2K+_BNaTG&P;6@q2%{umgWU4wz!r){`8|fi1*@Xw?OKk~GjTIA5&3*wYCgf%~ zwMtKzf|FiWLB?{4-q?`hq&awP-~G3r1E$BpYi)5hr>^1Hd2c--J(DGcQMm)rb^PBX z28YzL$=pemrUy)5_)}IkEqeQrIHl3y1C{DX(k2>|#%PDBZF&Bg=(MAI6Gay~O5SK! zd48#;EVswE>A1EVHP?i`O*mkr0*tTd=mFwQvzlt#FEoLnk(!{&Sf@C8-F1XHsRO^F zrT+&MW~z8g4FtRFy{fB}J1i<*M$9xTD_N$J!QA7l&9pMX!h7kT3S;=pDQa_C9aM3D z5SemDxTG?*5mwA8L-8o{rLyNQfFgnP(pr;{RAtEc=y0+k+lg{7)zo7?(=CYC2+fg# z$rPft)pSv;$Q{S0t-y#4_x_+F2H0JFu!gg6x$Z=u_DFe228V8+WQ>^*<9!(V4E;Bf zN4UdHjaIme33tPmJ9ozjA$XSfL|(s>D?N?oax^M}OF7Rk2CDlSFXUW`U(w{@}#!<_&;VzT)GW_>*}1Vf>&v zN!G*-+-#{0$>Kqsa_%KUzI$s)&T_<7lVla37JL55_V)Z>sF6fJ(j|jRMD$MR(iAMy z4sZtsuLKf8FFH{%fmzCwtP3-JQA#gLDazPIF5yUqqAfvGRoV--`3u)Js#oF~e9r9< zIi$CR>W40d%sXHAf%@`lVu`whvacGh=j2c4GLzcWpS-wrP^+|&mqAv;{~2v_Cw3P! z5X*Ymv&8eQVreJu6Wz8F?ziCbGK%TCbBya3x!$R~Lwb#~zvHyU!x#QD_(A#VPq^M4 zkc;}cXLEa_^bvLrHsmAzIm+U0C-Wjl!Ob`F)WN4N9Qtw1m;a2hv@zr(`FTPc;-|Pb zipl#S`|?UxW~10GwaK&J>-cr~2CQuNnoroV3HQU>j92C>w)ryjb87f%hWu?kcLsfnohvT$i&G><#+p^!Ax+%gzW-9a>&ovluQOGK@tG$EGf*t zYD(%9^5O(5MdPKoxT4=KOE*OA^rG?NOG4aWmirJCL@3<9sRk2}4kHZZ0^;f!6F(o5 zZ`0a6U!V6VeMpOp;`&+wA_6M?uz~ZIT0Dgt`ueDYAso0eX5P#f4tBKrO(4*3DF!*{ zbeLv5l}0#gFcwT9&Xrr2tdq6}?aYSI<;!RBHtCAP7|SpV*3O(}bkWn{O~{b!_F~tU zaRfD2&*+H9uiEmS8#v)=53N27XZJl~vU9jxn-_QCR4(SErgobYLQ_3iQK3$}94k1n za;3m4Nblaqo*jGahMYXb7TKrV@-1zMxYbKlI#wpQUf$yA5l9Ya4r1sEOywE^=C;J! zUw1?c7&Bxs?5-v>Z&u3(P`<;BZT^HpPd~*B%HIga<7+pCWaOFX=o=TqOo_NHa{ zqG({m4yl?Ewj%MNF)Z_EVbgKCvHuTY=M-EC6mIEs%#Q8kL?^aw+qP|XoQ`eVwr$(C zosPOQxieEWb7!jVecbO`^{=(Qbw+a@{d-1Gl&=6TDS7;&yjL<294*8yvJ!K#X4 zW*h#28!1opOUqHRBmGe`rE}ECw9^CF%F@6eQC-?kjU>y_+gj&SP(F%4VRa^Gr<9b- z0p79ozk52^1mKq~e*cdNWlz8_3+3A&355s(!uVh9I2#)U!~f84zu63Gmd=(g_D=t6 z>lLeC+AEu4eRX$d=e%4EG$jU1Kn89{6AKL^q#H9-yV82tqir`;w!;DeY#8KzRbO`;6eB1i9op}gy7BmZ*j z4GZ@01XGaVofxO}lAsiz7@??yZm4J=%2!~k63#DZk(V*Az=5O_?=$h|BZX2|A?bF-UMdDdv`p7{hbZwr4PP`xI72`GX+;q%4O3 z!pov7o~p`_AFIG~I}-#q{U%r`o$xZ4NP00K{=F~g6Cee{C0h0fJm#Tn5Wd&J3i4xR z&H)Vfe4&GbiM}c%10nTvHEm-O#v6Hxzq~5osD>j0XsOUE8CBq<4yHm&m6Gl|Y0r^j z&n=}1MjTUD_NTHG`AjtwwW5N>qSv%wry-if)WubGWkr_L(s^^zGGZ>Yq*xL<=0sj4 z+DHlHqFmukU1%9cT%$zNDwP(nwF+WSEU)Qr$s!jPC->ya#Dl`qyrNPBD*!t}uq$Cr zmRu&QMc9SOrc?13B=)KYJq_@1u;%&gFXWBk@Ux3XlXBArZ1fgN)l@d{Q86W|O5Mc< zx>)STJi_Bu1gak_I|QlPO})=N;IJ2r6?2~urYg-%bm@W=Pve4@iW1w=}m#gX-W*yhw#z7KDTCK z76r8$u6ayFr7`L#zVwL}da;{l-C1hBb@TjtmgzsNE&sx|JT^7t2kb1@Ep{UOY!V*v zs>)OCCXP;S!$)F{kZtm|ijdvN`JY)4^OTdcwt4bO2~`m~W;s&O&>+?EqJ zgSl?;zbSRBBf0!(gLGfOW+B8c9q;H=-LfJbXM5(-q~l-RJbhEg&cPQ}+CT3Hqlf+Y zauM?RV}VdH;T*6H4dr3jfVhJ_`6a^5AJRuadKMVhxbkG-C-7w5LY@ z8Ol>5&#Nh8@1Vk#NeW$&=tBpA3FAYaryc)Jw=e9rhsIxTTg~~*W%_{23E^>0?63^k zbuc?`ffgtpky(m(|5aoK4RiF-L!L_CWelF(vcAVS=Def)6J+F;?oeC%4_1kx-Nl>7 zBOV)Lb5#Ofld;T4oS{m%p-RsC=Hw*&(`bc{El&1FPTz*vVNd7ejZh%6Yi{aig73t> ze^#z7u&9qBDL*e#sYF^yFatED_=Q0ff+yNAD^K5;q8@Qp*{CZRrYlM^t3<>bz4Q)8 zZ&cd@^?Sa*lmDmF1JScf{_FJa2Vc=2PoH3HpQuTe&Omubbj&;UYO{NY#(nCOAyu_7 zYa4_fv&%b#%YjxK?jCcn*8tIb=E!|aH@x0@R2IH4+$*$y2DN+g@j2#-(s<5mQsUR- z)cl6H9pyB1hvL9DyN6@g9@KM9QMX#ScB`ByXBb&#=6uVQplhCdOEG;i51~fP>0q@r zIF-w7v^$)XLX33;%!@Ti9ueknpKd|jyiBaD!CUAB8S>d*#VThdN9GTXk+PR`oEuB+Uv}JTY^M>&& zIdT}7?|!5{@VLOt@P~d?5UfR075^)c4zaGoyV`!E$3NY_nU{O(pVly z5al8v2)ZFH>{1|+VKp3GpQVn>X+ccnVLL}aBx-xvcZrMq!GQ^#+`dt0VCe!a`hiNpp>wg#4QFODlrD?v@LVoyRu`kK z4q{fpftb!ok#ROWQnw8}71#!!O5FxJ>vAB~qd7cGLN{aNs@7TN#?B>@t6Mp$Nayx_|w{Hcy-K;~!@fo15$E zIcUpT{n@llc(;soD__9(<7=aiy=#4`v}lkp{59xus1SX}A?^Zh@SnjFrdXN~@F7OJ;gj8CkV(JRvHmV~jl`Sr`IKQdN>SX} zw-hsGntg@%UdW83*SJh+R}j$K+&D6C#cs(NXzW%t9TvyFOZe36QjebEwF-GA+5f3f z$zHdG`|{ZRZw^`aHkL?6Hi9Tg|H}GLh$WBDw25dh``#`|RYvbP;k`I!#uk!cR&~I% zEx2?ubH2Lgh8$zl8#$C*sF_`1J_L%_dI6bB!`aHwABYX4lcH5xQ7~eFpr@`4@VHry z#lwsX&S(Ca_+pI(z?Xq0NLk9Pc$fCHO>-E(AOutL4c<1%7YJNa0ZXwUCao)KQ26zh zMvEqaW@DW{WQS%8Q5?E=vYu}MxIhp?Hlv8-*KS#3vRw9F84`hJORwGvFmiV?gq~3Y zTV|7cL62t8VbDWCcnmafu_vH87ZD8fvKu1law0;JFzv77Y@=$LUv1+&yS{53F{Q<$ zQPlPfw2$8@jo3Tf97-4D~?hM|f^O?_u%WeCOt%UU-x?a8#eL#opPUzxw=Ot~`0*spF>>T6Jx=M! z2^V@|Z)O;1E*OR|b`&5LQB8ehiJ*ux)2yqg-{4Bdscv6o9Zf9a;Np46WGlMiDuP8u zIStbSDU`v_WQ*Ee98{7jQ)0k9kcxKyDi~30$P_#i*fYFB8b@CpvPSf{zSlc70!zWJ`=>V1M{5IUWIJeEII-ZcLXNxsD|j}D#9MbE zu!d8TYXJVa)C${&Bq;?O?H96(pp~AoTc9!i$hu*s{mt07PuNErABAS}vywRM|NsAceMm z1ldMb6Q-KUU43{~-lA^CYBoOK_J!2be>3I%il;Fx5k9yJ^BIKL#F_LtmX*lmf^eew zHmaikkmQlzBKQ;u3xBzAP$#3LUkB8@xOF^)@4P{;$=qOkTZS@}q#V7=CQ}Luei>gL z*sIa42)Fh&0G810o>|}C>TH@kEZniwrZ37I5N-;qU6>BjX922fFzS_es%<(UwmLRp z)GBQWk(F(0f)IScyQ+@-FJ)_!!#{W^4+nvKfng?}IT5i3#=sQAcG%egKEJ=d*uU}) zJhJkPAk-#a+oJeIC|lVjKBN8b9n8 z)T?@r&J(=1#3yk-xVv9@Fpr3k=2<++4^K?uI zY>BW3^%S>6fpdBQ9ulhhL|*@)K>vy&K>rG~uY6Va$gWDr3%W8o5HMbPspei{mT#-b2T%km; zT!*8d*DuYMt7?hGMI=#usyFEaaa3=Llh>$l97;lf!3Z!8~nFa?hz-EoKVIxsNtx=xR*e} zkX%=sn>b~c&Ex%-om?bXrXioE;IDjyP+c2o-_UA=JtfBuF3-Htu_BMCP;#F9c(HLh zybb)x1r;Ka5}y^i>G08WQx#I`SJG)854?T;^NY>{XROXBY*$_+& zTPb22oV|a-zZPS8Jd$mhYWE-Pr4FdIqofm@nY)Drtts(dM7f0fTVDHOv(lU<t%QG#?7$By7wQMXP zVpDC7$=FpvykgPcWzeALvM7L&$#w$pJJO$39OwRG0pDzr5wL-M#;yn%^}FFx&f%nx zX*p74A0KrHo;$to=RH1f9x#~ox8#+31-Cx}b0@qO4sv-boclP+$2%i&`9+-E1ZWqU z&-g*`X?0n2&y!uekk$6U&bMg1Ejq)CLU@>Pax8SsDSqUDwjVhAcEsF_(HQF2B$;0; z>kV+juP4^<288vQX_KC9ihiMu#=q!;F5vAHUz%70Ca$LR4G~7OIG2R6f^B%Wmz~m4 zp?u2%7>q4WLAo@V^@h-{*a>C&xDNT+tGR{eYx|J{{BNA^2L z<$&N5Jz;%*17Z?K<4=_X=AR=>R9!^DyLYGZBv4Y?0M)>w%1h+E6+__QwUy4h_t4hp zC9p1@4QPv*xZf*q!salbJL-3$3`XAzWj17~3U;i6<#E7}30-#JZO$kS=tpoM^)IVO zp|q+B1z1%{gqGCyks%B;+y)2m4gxdhiL(64`F1W(I6*GAE zv$d>j_DI^)SIv}O1;KgyM?)bl9=5Afu{l2naO7P{rnN~yv%T;Z@ zn2UWNnzWHu$zc2>xcm@>d)QcDv;6>%9HHk(22{VF()*?yP=0XNcR-iETgzw9#Hud} zoQ2l&Y5jd>56tX4arY{iw(7_|2M9Garl}VDf z**^KQ?5RRDT-A#6LaFA`Jt@)qv#GFvkp4Z6L2I zPf{bIP@zL5=Tlyuq{^ul*hX0JKgO~cV7d%ZRh(H(^!<27MJR${ z@7U4kA7Au)sg?ssKjm>l{UCZV2J}LA&k`+x2;{Zv+{WbO_$RB}V|8|6b9O&ugCN3) zMN(6?>vDE;^QX%~SPEasysrl9D1(GHjXLx{0aFK_LZDNq!tSeqWGZd=rafBQy$0oAJ;RUKAS*n?MMsn=0Ynxk68YHn4+)yfY7A3%kL7NjD2* zQ=QC7O@f98@aG(ydE}98v?~qCULR%I8ic0{?SL%#FG{w$ zNQ5gRu+Fu+Fr(KbHS7l{v@fN44snm6b~Ox4}z+ESyT={Ut*N%7L1cjimXBE0B?- zo)!=I{%n^Vy8TvJhL){_;nG###fR6B? zzhFd)0+XbPltU!hLpa+j?Tjcq4Sv!k5r{}Pd^pQtG8*lWYBd4L)&|E$j0B{0VsjP6 zhS`P2$JiQp6l@y(Kati*0ef*UG_xR+%zY2=bv!ivN*C1k^jd;@Huy>YDr{?*1xrL&CJhdG3 z(LT-QyxF7B;3~i-sP>#-M-yvj_H@i0YM41z_bs#r(w(tWF00^fk6#E6`K>Y~)a({Xhgc-x1#Br+D5f=} z4tSD1QdvA=As>7nE)d6* z`GeJC584aAILyRSh>q%T~jx*|40fqxgZcw?eF? zdZ?Ft$(Btncd8ROEJu?|m-!+RQ(h*s zCVXCg@TQ`Y@i<_YCRaV)w(Jw`zF~9GG`vv`w7Xrj&_+~(8C#$nOO6RKT+pCQAn&sn z2Qw~`DvPVgm#ZM-mJc&sxUUPnuvOx`QH*(4Ja zAi=dqM)fc3H#rGV{`Y^mQf9yNn7Rt7?9<<3@t^NZCf9#ASygs5lCU&&GITPw@cjRV ztJx~j@~Dbv|Lh3i;Zwzb#EVZB7RYdiz&ByFX=`b~!a0v%D<9MMStv;vWqc1$)17;6J5O_Va)0&cgQg8KqXP-b(?UxMz`}oS zkQGN2B)D!R zyqU$!PF;sql-MAM!gm)OY0bnKYWWQnG|VGTUz|OT!=St143jiZS1Hl3qpMAK|BYPQ z&?^s$YC3?+bQ;XFOXVGH(u4NwOsuxEciZJ);^62&qj8`y3OB|>#hb)B(&(=UEXBhf z;xxiit{bWUiPISJg^hlZS0ueDX374yq|QE_ZqNl4@TE2>hfbsKiZybZ1{GSPJGuSx zleY9kyji5uO|dmzS!hCo2H%Yl8jGs6g!oO(Wq3 zEWbR3)*-^uiM=p~&MwFmns*MSdZFs;`TXk|%`2hdFP7jkkdZGqfA1gs^d2RM!WrzH zgdR7>s@C2q??~l_Mauebc8HK9lc<5Y2^kanSoH!bGzhnT>6nT{k{3NQl_U^w@Td7V zBV`j^!f*6IEwTjoemf#LwLxcnnS?&5Gm7CcWAY0l6fDstOh({o76aIWy+Y!13{U#3 zl3@LO$@`{qQaAl(Uj<(fm0V_$KLBKE!0veuTr1jurHAREI-6`z^bNw z9}oou5D=dK{*XABI{g>NL`_>6O&skXq?`MiqkyQwU5A+B8XOjVnMb$~OTljdk)DK6 z==KjWcXRf}Mv<}U-y;*kz;c!2{tA_f1Wf%zV80HKFQMWyj^{{x$Y;CrijJexNblW6 zK6mkydzaJK>)-pI)>06?VK9VEN8;bMSV)7SjPMcr38BPYRH3ab@Wz0#{f3cfMaE8& z&`MwpjHfTc1!I9Bygd|WSK+?ymco5bC_4?og_zrZbOK)>lB)J77?~TGR7e zg`2c`<`P4HeP4i4?%((^$p+%yfia13A>ok-{gfDfH^DwA|!! z%G&Cb>e{u6p6`$Uk<#x63(7NKLnO#G^AkQl>T^{DSUOF?EbfaIn_(;RX~WubWIG?6 zXiB4f)?7erQ{i2%MK;A`dx(zGF%v@&kl?TH3g!{%2nQEcinT-iB^A3R_nLDTp_b_~_j^d-{ zZIyY|6lm;M-F6ZTI0?lh_@N7OWg6Wq8G}s`-ds0_&hJz?YGtbmJE5Z?Q=4>|dOLi{ zk{MKsZjJc^va}bjU%h_$d4&o4b$4d68fHc+N$wdP-n=fQkC~qQqSIi@5w#XduL?~S zwwT8~hY-49?KInc#msV}hi0LszlI(+y2qNk%xH^Gl-8!{vM(SkJ!h3EWZCtPWUuk{ zbcLx6U&yyV?0{!g3lcoM)w&%%CkxR#TG#W+3gTA~({iz$`p+d$QBfX==tDfT)LVo& zH&t47sho$0Bv!li(I%RR>y1Eu7lqT3N9T>In|8C(>EG#rg_TwT1Oj5~MJ@M#sv)_N z0uiGNEbnV;6rX6R);o%}NQ()(R4q=|`j_!H-l*8aas^<-PZUvOW(wKxGQ;S%E;7Tu z%x_kRXk3u?JQDcygpo?;{1-o?FGZ=}k@jc$KP7*YK#rvg6pW?!DUq6k%2sE=@bKNZ z7gYM6AY4FKv&P?nf*L7E-{2OlLvUdShe|ITk92v>ALCpd-qH|yT#W_{2P ze_614Fck=RKe!hza>a#VblJcB&V$ZskhWC|@P*;*7^olz@hE!0JO2U7GmO$;bcSgE zv6Pyio&L5bO!Pns``sKJeD{}#l~HLZRcL`rDasL?mt$n@^JtGlZmu`<@!$suKdiEI z1=1f^E9jAog8i{tjY=XZ(3SDH)moF~<1}NYQnDO{otm@y@bH`Da2t|;tELIBE9jp* zg@lC1IPFUn4G`^9^UO_ss2IuGCWg*9&%#DWu%-QN#E|YNzE=m?Y{a zo%mG5)UkO{KK`&{xK^y1NaQZcu`qHTpu@RR4dqfud@LKI5~e7yL~vQOJ_0C!Nd~NV zv!a)7l zb6e^6G!YQtJT;0UD_yq+?J*v`U=XEU6)Pi6J2Yw{xpZ|3Bhfp`R)?i@s}@AT?DeL* z*dI<(w#Y&x{BMUlLUjhN)p>jY(l&__ePh75QEwqa2@Z2NRV<`IodVk6_4C{9jRv;kXE zh$Wsz*k4HvUHei9eT)ms@DSNySQ)C?UYVo8Kw8@ToScps1Md5C$pT%RD;V3gU3@16 zeUwOuKiUlH91A!b6bcDGt4qky!}wRx@PC%XA@L_G4s1<|i`=Sg4+ql4Q$sq1kku?~ zo7hn(2(4s6f1Ce;q;;Ohuz}I6ijwNq!-aDXIo$77Vyf;+DUaM}l5OtyDC5Q1jWka*1o?j9M@HGkcljd0pS;5Ywxz zl!_oKEF4-D)qi zS&v&ozvUvkufbvV!8aX46U9;&#rl?v#1Xcsp4c0#w7DNQYK{orvb3QP{}|23Gq|rl zFL~GuUehPVoL?x$&lE#g*9_RS?*6{LMSPzg#S-j&@Fl$B_WNR-Cp~`bav**02J|$$Mfq zYLTx7l<&+o_T16UXNiS<6`2a=Nr_|dHkw*}o84BBH^hkf z{@PaBmAd2}71gs%)YFrjyD~qrmF^;KNS(Ks()1n<=8etqlAaRby7X~z^VAjRB#GIh zYRfjQ9V+2CI@I<-A%`gZEe)LbgpAzQf$_oNP!Wg78$Dbib$CLMxU1N*OKY3%mZ6+^ z+M$edmT635IrtQ#IZH(QNt77lY}Pzw4U0L8oCCDwy;94n6}Ga?A+tx4=NCABmD3^N zJ*BHP_vA!p;KzV&x2~zmGH^0YG$Xv+&at#@GP>1qB6`$8OJKcck@iMxfc9ske8(`d zm|NOz4rZ=Xq&GPBNTSkl#>sX*1`v-_Id5ae0$`#G86jiAp|y<`k&d3#Z|8%$OHyrq z%enS4n*R60qir{u!ZGyCb1C{)0d`N=q8-n4)CDVT_K9eSey+BSD8(+a(}5wEd-hgR4-`%W8=2I3{bwqISG9?Fd7B7;I{o zk)2Q8WH{)c4HrztP$=Tr3AV>dK1_8fnP5Z}Nds!ZbUgyDPTYVOFT9@j?Sz)64+Ta-SyP=tG1*RN-$+CACWyU)Mvk(&(3_I$W*O#Rnu zBs`g=A3@5_ou-R@3}>p)*pbPjY+0sN?d!k_4s{o>W3+)J=Qdw7j}$KG2Fs>w^s^!L z==mykh+D`dLKDFD)IBdJH1IxC$h(vn2b*r`by_k_i(hXMyg@|1iU-%)vN*EUos?s2 zb`lHTPDsL%^`?DbyKUEHUT_U7rWL-g#-3wL<`WXu+wdt|@#{Cu8Ac%OuV6fxvM3^o zwQc+eB>qLZOC0h<_*K`iNu+AG8J@v|dGvf=*#?{QdkZHml^oW4^KR&QTTY6mQuej= z#QOdS*~gNjS+`4>`xIO_SN9AyYO31mX(_JNu8wL;W6~Ek3Tj&z{kBFuM9I$k_ao%y zEbSeR`FQI7~j%-a^jHVQ+OZ|5mW!dmOTv(-< z9H}2R_-K;S8&kJVPvti;2D29yQ&$t-GK!XA1o;i-&yb`G+Uy(iGudtNVu_ZYiY!8@9WV|ePf|WCrx*hc9ntX4Pat{xji06l zgE-_mU+;ceoOJrHDts`!;WbsC?rnHsaEjevpY8lOnjai1-G>j&4*3{I3qe+}%o0ng zU_@ueO9JHxkY9WxerNQHws_euGV%D4t$vn%`RwuX_A_h7pnXI{#mKgQkenokSBTk( zv&ORJD1r=&xPuCHn$swK$49El(tJg^eAi-c29$C47c7l$i0YGcPKTygLvHk(tR02oI8JG>C zqyr}b9zLKw{*1&hJwkyLc!TcvUSwHP2=eL3@%%4o}Hq z^_$|WC;(lp00SBRAZ*s2!=tr|TX?esc_<~U>d!|~DTLX@&w`+F6r+#d=`3lU)V4mu zBfp}D^pOlO%$LD^HfosDvd1qfT|Rg5CE$v;J#l6u&emsP= z=Uh|7R~CmAg#4BD`Zu2cdwywJGXkrwaSGD1iX_=1Y3<=BY<$~O3Vp~d5#bNMyzh#K zSR?4^e%JV+%DEm2z^Z<8yIq1#Ec*$>6ugp+j-~9@i0TjKWRnJaD_u0?awD`zlrZQ+ zTkV{|RX~7lLZ42pxi(>mC$IDe!|-MK^`J*>X*nWaZD|kUu%5gwA#7JpvM<`N9Mhm= zGq2XPvplv`@Q)73YupwNTtG8S39_7$5lggyMwoUZO&YCdjYv-$tf)~>&;a-*Kz;+Q zMPm1!IRu9g+Y8VxPkpGzfOdoK5bhO)REcMHFTF(EX%I3EC~(^R&)@`tf}8c*7NgwQ^asxJP`i{Kj8aoKw-IQ0S`P1$mHW-napU$O-cA2OCU5hGw5p zg!z{Z>}fxm57aJMm#2>{F5d6Wu%9B1xK6|33!wKOL7?}RxaW}R)1#1(b+1^%#{OhF z1=mcz1+EGhjDzA^k%k9+-)L(^q1hzA(F6S=zh8TK2C6*t${ul1oAQapDlX@Woe`m? zR99vLm@o-@Xb(fiMH8b`Ry{{~d(BiliDc$518v&B>&14O1@b2AFNfTAm_XshTJhCTi==!oF&ISU0tnBNtGaz8C$nF3hi zS!*_LWCn(m$&Xo3E9aVdH(D73EDE+ZpHkG+oI1}8Nl?L0_y`Z|j8}-zNd1JO4 z+EeJgqek~oOA)OK6gy(w9+;IwyEd_SF`_DXJ$4Usl*J0aBTr?iSgKf#4P(13CKF+K zY(c1*7Ge`}F+4DfBIplBAD*1b4+i{a3wN_v)G$Pfe?nkNiSS&e!uI^eq)9RY<{zc( zm&MMN2g_-f(ZVJvT_qHpS`B9`yAa!*ph&N?FW6)MZA;an%B}i*Q+lID1WJKUj%yTs zDJg$NqNEL4hkIP=L|et6UmKd2OQj#t8 z)IYCv#%ut&B69aii!yw+LNH}7+wWl(V}Rw?`nKF7CdXMcaQz(2e^+0pKo1X@_MEa` zJlW=zd8>=3m{UISq`*5CqLC*EJd!y+C-h_#UJMJI5^Yc1^6lSAt!b>W48 zADM@tsSs`i=QORnxH|t4#wm*!Mb!?@H2pDjVtSmvlm(4oM zXRr8pkj$SvPKlTXZ)c) zUm$D%2DO&ZEH-wOugtc|;*GlajzO_x-|!yYGoHA?Y%Nl%dK3C5u$C`SR#n9gKWj(i`S(xk-Kzz2pL zCB7iIqgr}k=^Z5Ru9DoQ+yl?V9WxUj_jvAoLsi+YB+*ke&%eF#@n}xDk|ptLl6v*o zM~6+R@^XsSGK~)CS%>z;cT6RfNvUjvgAP(s#o$spUW2LUWMB$O6l2QYx#wfNaJL*0 zZ`i~n`%UcM3eqKLMtv7OE>X;IJwoZOEPiyne@r)>wa)OoXRM3fXs z4c}^xFS^1^-8oB~jl6@CfAD_i;(LxCozE~Knm{st!MxFIql{^a95&q^L^!Wm>BqIi zgWZ{qt>tt*U3oAqDz8auOt13}%REhpJ|qz)mVO4SyrV=Ur;g+L$?n`~XQ}M;c^=F9 z=zGG^FFvXs)3;#yOzuO}uKO;}7Gt6%KGV{31b8jtRo&^YHM{l5yb)9i(-0Q?QDGH- z__LSFbfn*WuS0gP;9I=8mk<^zz`PJp;(vpQk+FKkq)TBv_S<=_oz($jm2EEhp(6@d z9V48>)vqWbwx^Dg2v>W!YKGkIzblaiqgia-PRtXjTS=Wh9FmzX0ugTk*aVO5FDo*C z1kozP-jX5EACDdwm`?ryQ-QaISJ8O3!;K4Zp%bN6JHX-kqhd)ktxzvo^a4ekXz768 z1h$q{^H@MbfW}Fh0|%Xav10tmo@}v{Y>}ENt%SVg0Hz7H<49 zLtp3T>1FsM`GF6q&xM&x;VF$P?n&jQV&zQ}CwCw z)VL>gwdYsx5`Jg)XO9yIewNfErLmexw@szuLFs0Zu9;yS{U$19C4PKs0=wl1+E;KZ zU^vrcRG*6K9TMpzt}2Voe_N(8tMLh>=JZX4I@x@yaCuX)Y$rhJ*)D7ucrDhW^g_<# zy;3yW2*;GM)6xq$9j6#~$;t&am+a`O7|Y$ouMRspdVC7w7&v#IEP2l-VOiXmYkQkM z?v7b2hOj&)rL;vtI?*G_eogSK=v4&XQe@mAW)L2Ijn2PZV_KfDs% z5eg9`!zf$b$>`&<-!~eq?2b`)?heT~Ttgm zYoR+f*f_JFySN*T91uP8hQIJ6`uUIi^<$=23V$cvv8`Xxn>79zGy6rF*)7l38El!+ zCnPIceIk^Y5^1YN;ATBoCypDV-3*Gi0DJGxhC#M}ng zce-W1Q+VyH1RmG&Skv~Y#p%jxh_0mb~cY?=xMP+)sTfvqG<)RwLX1?J>3Y$7#Md;@Tc zcU3%q(^f9$$q_8NneKSkVROx=lC$)2Ilm&pHzLdC^a^mFsej&_Nb8;z_3Ov0Y4$4L z|Da=Z2W4}&T~fO9<1as!yRkZ@dEyU7Mz7HKOLmS2TYs9Kb=tVyTi79r{v;r6=I5|@ zFBa3mA`32$_u(?!u6%g?I={Btc(;!y>G1Qec=J0Y(Q>~}txZqQ_(jOM0fi+to0J`y zkgHyfW0rV$GnqKZ3Qw1c`&P4$b&eBHK5E>8cR|FtbmgS-x7DfbbIdW>C~Y#AJWNy^ z+U^o<|DFCn%bXHjCKl4)G2Z!aLIuZvG4vKObvAagbofs1{?ELXsGY0rw<+L1K%W0A z&6})hZG)zY_V326lRmWNX}Azt6wWSH=!d6-HnoC4#4%ZMv1su5O%wiFwywE3GSV;< zW5(;Cdcmgx5(0G(QV3Z-jL{NSv>2-K0pYI?Xse?z#a{}&+|0JA4OX9yvs>OX?WgzI z&a*yl&jX?$aQ7C_u4m9jkZi#cY*G!93DXHS@qwLyb)aM^U=wf-n~%4hVDqPtA{fO* zVu5=6C;!chaVgr);b;v~MNu7WCz&GIIUGrZ28b5OUt)NJIYix#P1L>}kOMz}P#bb6 zp=5x9jI_8cuPK>qz(Wl01z$5`4GvheHmx!{WClcpD{09!Cek%%M1C=C19y|JmQJ3G zd@F9KSS4yA`!gl1n~8Olj1aS`v^)+xxe0YE8FMI^0$L3P(y-#Gij9@!^gdIWWRR7Y z@WRqVV_|R{ID&0&Gh5F2Ed|g1yAVg}i!|ep@2EA@efWbCfj|0uyl;;h16RquY*`1f z0{)I7Rx`|oh7l-%XE#vZdHP>jic{iC#R z|MeBz44u+BQ(2hQwmdXh&4DoO^XT4P-So*rh8Z2NPf+qk-2uAVk0)yt{|wQJps?Yt-B{WSA|^mCF`^GNXM$CH)l9UmQ4BZ!$k#4#{7MOZf<%1UFi|k%&9_#)9Y2OoN}~P+Hkt&DC13#xEsAY!Ftt8>(1W>(`)-6YV*SfT>rRY zGTpI7tq0!EP?A$(66e`|=aCg%5v@Ry1&BK(W{DYE9#!rQjVLnz?!=vSTa5_QnrY!r zscHvBxM~bhr#rVqG(yo~Wa73**Uhf0J5#D!Pv@mWy!RiuxnZ|+VVjHrwRL!vue%!2 zmKuZngIpI?vyp%+u>;~SwVWbzJ`?tYYaSTCQqhQ+etJoP1Ot&Q;}HPrNJF+*Y@Zrh zVWOt3Fja>_xSdQf`nkL#P5ZxKJd~PLwN+`;Bbw~25DKVc@XsBZE>Yw5HyeD`S+(Ob zS~>jDlvn?M>8To&w#`T1Zn-Xs1!1*XclO0`!vkD5gr2oB@f`PyW+}vldyaEcgkmRgq5(?hh2Qo>-7G$lpc z`u@(9Ln|%q4lk%924fiMb7LC*{l=8+Duv>T4}8znT`aQY-&cq5YR47iW`a(y=Dz3> zWA$ElI}apwX5n?^CO&@y_JL~C1$zcEhFQ1gOUi9btJ@NgdA3nQL9wc?6P`+v5;|e`dYp8 zt{}R$caNvLwx_2B#&dk^xPZ-@2jCitJS^-$LzN2Hb^VMy)29#+WPLPv8TKDS_!w^P z2s%j28O-T?Tyjzajp+K!NIvL-Zp23l8`C%JW)seJu_UeS(?sj8A&*7`O`RtM-3O+;VV9nm9L9kF zznEaFtD+o%sw^TJ$YEziO@A}%Ap@J($a=EfcY)KLw>Q)E0!t_jOvem38#3^^ zUD5Yli0--FcaW)t+L;G>;B;5*-LQWIyI`_D84-7r%IqW^`>>oO4wLUb7rh2z3MPI@ z;^;pck^9s23R=HV5-wx)3fjD25|+aWeA7(zSiN`(@f12 zzP7P_lTI-fdWoigAB7RYzbZ-~n2XC>=@uPQ#Ko`?)_D7=iU<%UB`{3kX=TyE-b;J- z%^c^w7NO;W<0QQz4b$ptkMeJktVVaLUKhaxV!m5K)0JSh({!W z)ZEQkYZuIE6UNT*td&W-mowxcExojsp%=T&FUlRv75JS_!pAio+Kps zib*kPB~?=2W=XSxFNZMX#Xw?CNq`3k42G2ZusJq}mTmQ_)qx-o@siO|u{eq3e@DzZ zwX}BNpR4aFXs9SFr~uSndu|v~Y;mGZJ+KWX%-J?`#>a3DPIlqkWo*l9W|i&XQ%gE#lt(p;`<89I=?4CSYt3PrEp3-M%;(J`8v z*<@XvD^SRr=cgIr${7;HPf;lQ;h*V#2vNk353z=n8^?q>N16`ATT%?IQcyI|-9#b| ztMK2d+IoKAnEMW({BTZm3GU=f;Fxy0$yI>5|XE)X@Y@eoCR*t&vyYkt{)!>EW6JW^> zL++R9x@Lyaj?BpiHClU<3Eba_E!&4Vp3CwSD?(*oMXHjt1Op%Q!!>|GYc&|WFPw-q z5tynTsJirL1k;Z9>nLTOBeT6@p2f7@EMu&J9L>V@yy;ReVCD^ezd1ef#k^hIj`-Uo88Q-rUCB9p< zlE5%iwj~P`sQkMd=m=?kb|s|U*o-B6Ji?;Q%vH~2_J&-_&HO@EJQCC!`dX_FEog_` zqQVDk1gq3SGIgezPFVpWpF~^R!9d(1tJI_9R}7zCKq;rieBVx9q1)id18^;KL;)}AWE&&MIv+Z z%cHj}=xckrH_Jf;NdPq#FEoKFuTX%JOg(JQ?`0cRMcZAH5v?tbz;kzM^MmIQ^bIVP zB(*iCryM@?IH|DP=OJ!?NQedM>a7^QhTL-rd!Fl`Bfl(5Y#~hUi>+G|fNRoINNCg_@-pd3(f1KbGNR%2|u+DlY79Rn)rVOYC`a=a92vmBmU->R+9*t_xdk zF~)ya{ApJgc`EpI;hK`0IeTUwh2b&RADVkT=USXcoz{3AYHuPh>#tmb^?3RM(p{>g zTcV%2To(7{CaqW^UsA|T9~FwD)v(yEt2iG}I|B4qcjMA5RSc5;O_VX|JI4kwCE46m z&tcga-*BK=s3Lq1?m&z&Q8(=J>w|wTBjP#L8mU?Cpu!7xwR0w)J{hADFN3mCfc~hg zd2;d?6;9q!T`F)+6P@9$I_>;AMI*ahK3PLfxI$lOQtvHvsJ>0xLH(k--25z7bqWZ( zQrWEoZK1$MVZa5Y@G0m?DSr(r@iUvL+q5=*k=hAfl_Qr$WhTUWS`ED#0d<^m;a7KQ zD%u@-9(&RR9A{eCs`|%e@jd6kDvQ%&DxJHE{2j-E>tISPvt((`K3aJ+|4P&n8V#75 zHt!_qzeb}&&#@(k{pQ_JbxZySJH|8>-*5^NMt=geKnPQtlfar3-)Ab-0J>6kASSb)~XJOiz!dS_Hbw zwLDIz(u6?AYxpwiY1m5N89**nRA}D`xMOy5G=HM0H}J0!XO2hA|zW_HhlV_ z)|&mX)gR5vm@ph#_@J9d5fmRd<^&YWQt;R=&xLBa1r1-`;dWPFjuk@EfvFlJd+&)6 zzQy;#sP3Z42mb}z72+NM<=`4}T!%np`EbYWOx%ls*B^FVhB(0@sPD5t`YW9?@{>AB z?Hi#XpoIII0kwN4gpg?ua_Vc#{QK{k3wh~V_*C|V@KVpr<&MLXE>?MVw9Hb#=p`Zh zJ7UJCR>OD1nqaYa_@eH)pifBLo|An5y5kqxoq`A#XXvmH@%N^UqgbZKUQFwzn2DpC zgs#S3tf%MYSxjq7kXP&ChJuq2|vlG~ERu7j3IH3hoh zXwAo2ENd$p|M9lkSo%?F#$_^3y4U;lQE%_Zs_}ce3~ORua!|*SD`8(thK@sVntCC% z(Qgfqc-1OgG}P~@`D(Iks0!sq7A4N>0LvlO`5Y+igBD)U(IbkSLEi6+DC|prbF`;> z(5RoJbqT}sWtbVQm+TiFM9?ebt&pqj&IHc3}8 z%7HPtw+l3-(@q-`QXnr3x~q|ldrw6 zT-k%{BNo8U1MtpWPk008&R7jRhuwPxjlDmTQW>W1g;d(y8IMnSfZ2;jAcwtX3;2$1g{M3E{ zS9r1g;5sJlmNB=?gN0lABwCF4wjglz_H5JlPM#=JqjPSLfUv5_d+N?6m|jl5rJX{K ziREEm3deyz==%#A!4zg;e4~P}3e-H~m#I2#m@WY=ym9`Z3Q=2L4`}`>m(vAt2Q7ow zd~bH$Y`WGD&>sjJSwJ=cE6ogr5pv2vL%V+-Yo2q4f>#!89KEKzblO$9QpZ1eZeTtz z+H}cVR{VU8KXL3r;@-U)v1u)%6YLxMW)c`Ir7#C?_McOu!@c-|qv^KzCPy0hoNwPs zfbYe!q%p(^gcdR!`jTm`B-=VQy9ki?c1MwRVV>4+H2v|+m++Uk;u*|-*jIcAu8svv zvYvvR1zb!~!QgJ{{S)Vxy?E=9&er|b*2CuOfA|~25euP5s45p>a7eVQ@mm&oVozTF z;`4pMef7E;GgkEW1t!`Clol{Bd7x!s=B|JT@o~i!ucl zOFD)u@i`MzE5KgQNpJ@1&}S=q zn#FZ8;b`nmq`RiD? zeIINFu_?8WJO)#n=n>wwVz-fEZZldKYZJxbddIfz=q_hCI)`3#g_yOO`u)=0*z6Bx z(+f2uvIYZ2ZxB1BHTmKC16FSo*Ch^npbvI@!v`a0yc{Xq7FxG>JA;@>=rem}1l+Zm z6Lxi#AtO0d+}$4m|9v-RxJvY(!u;{$Q{=}F!TIt&dF`YjBCjNDI#gn~g#hm!E4kIWFI_cx3vOUT^VzG+aHz5Nn{b(1!2gsP2A zWmT0nijZ}M-fX$rg}RMhQ}c3>c9~AqMZmP*%~YqiWwr^^p2WH*}ScSA;w($&&^ZNgT^tf&jW-M$4?+q=LpT-D9e{WF~GJy62zvONlT zPM@F5rF$5|Q#j3*SjNs3VO23LR#?kGI*OTPrv6sB0e5&_w#&n1ZX5~rOJkN|qn5CZ zG(L@?d(}%Nr||m3&3oaW{;|}D(=!z>;DnQdjLru#lj^BFInf@!gJhjugIs?8nYgB_S#llxk*bw>;- zga4r)Eow9R;NhN_UJ!zDu{Q^IJK*fif&36V7LL(TT>`5S@SCkkeTZ0_!@J>d{)4;j zgn@)Mr%Ss8@B#b5R-TaW0hISQ#^)unS7vJh5TBD9DS_{|KY}~_Jdpy1@t++-1E!}8 zJR{pvyq@2H0w3fPpHY1^YdJffksc9c?`iERyad2Khg;!dg7Mz)TMrt6{b1O-z`g=F z0u!JQ#}`*HC7ZAEKna_#_JE+}OAO+7#LT}w0lcKuOJ-Prxle%7trxlhu&)JJBhU(A zpnB^d(2DR~zPH2fD>W4GV#wKjI*@XUPS_oV=y}WjQ4&^j59MI_!bsRX_OmN8Jnh~A ze&=p)<0Uri<_*Yy?KN}y8i%+u0?GDKgD7bD1o;nxjOh1*%qh@6K;vJzPf6on4kP5K zp-!*U0rHcR$W-06(PJp+s?M$Nm&dO>XlW2^boL{7_>A%knhJT+I_r@5Cbg!C@^j9m zq!o3okIUg=cD0NIv5`vZ8p_Dw@;9wA9%*H_#C2ZJ{*J4z2FNFGB#Ek0>&?c__VQw9 zm7(+Yu;IJ*VTcebTpOMO{Hm=!OBp8@vel&~c06cw&I}_Aom&R6)ZVuwHPhDaa_3rN zL5~Ud&-JL`rN^i4F{yIu5QzpPuO4T&gso08z3{L0@<%ialO-7Gmv#1}Bed?W0KVsy z%4(gxMea!6i;858C5j`hhnj}a=Gt{GFYQ96NrJt7E2Eoy3IL#-K<>dxDiS% zHqiQvOm?`m1f$VJ60~76u37fSrKY7nOBX1C6p{&a{9N>7^CrsVWDdKsSi7F<{?6XI z=beS;G*Vkb5ZrhtMD=a1bA~$LnD%m#l3+&pD%=O3s=b%LJZ0FhuIkQA8$AX^Z1VS> zG^wH#cTMwnF=Ekb5G6JSuBwX3*6tei?;NS-mEH7RN&zLm?3k82|4bc{PyRXz!zyb^ z-zwzIcC!(!v%^OiH>o1;BtZi_9q_v-ds}3bz~{NNi(XCT4O#+hA!tPlvEiG@aGy5F z;94dbvS$(2LCuuUQ{Y5<$o}}BF+E68>` zgg1xfXAT64XjOsAur#x)$&V<;Z3ee7;LnNGqT12Kf=s6uiCQJ}jxP5--nSH2ZxFpE zu-%a(+!a|Jdc8ImS4!GfxZn@B6p!_6V_0vXL@^+?v^ct0k3TBf01D9mqBqesj}|Em z6t2>^UlKVP$dp!a<6IYRk{m8(qHhw=#e!|>>@m=qgRyUt%f#(!q1hvjBol2O zw#Jh+=ab&Jt%uBCvsm$#)QCE&xi*GSakB3{De7^aR4})aqwGiUrU%En^;xEFP%NNt zU=(*2Jyq40@ULRnbFdKB7_uLc;>Cn`jPk^+6I{cLjBohZzN7c6l_iJ|Ii53{rCjpw^b#q@)-+@*{an`X63yt zV$x75PnyZII%>64`6El1FTXuGHPz7W$7|Q6d)$t&EiwHWkV-ebFhctWN5wah zS!=wYYRfL~DV5u3a|(Y8uZDqq#mUd}TEXMaren?~aS83{ptY`zf<9~3>%q(hQ6dIR zN6(oTZ>r?D@5Ic&m;q2j$7(qin}|@!%m8=X(mu}IVq=>EGlI79XH@p=$p;EwBfK$P zk(pnr#5l%;UICzG;}1wCRDn9SXT-FysNWkCtQnkWO7ELk{RT_rQl^v5i!%S5xw%yWUW)T6xTU+ybyLZ!Qb7uuq6U1o7$6p^4<$D-pd$c2kK3SN1EGRE-m z^?o3ar3i$qf#cdhwC-AN6^ogCB-{OQ>ZUvg5I#ZPZSLLJ{~dH@#_Ix$$0{UOD*$2Ye`?N6S9s>z-RZh{5Pl&Djw3*Z1>omqA`;tH z4U-kE4GRIAxYrgX00l{4}e0?JzP4EiV2cYi)Zrc#Z2;soOHMzS3w`~mM z2=>70oY>`u_%;Fx1b?%<{O${f6EFrc2P#QH$j zU)*y5df@Am{64tl0@E#mtpT2qh@SEsAKbQ&qLm)d(ak9ZgYuMv4MN2iMcL}bpmDcj zkxNvNXkeNQYT|F5&JA(xtqgfOWyZp^t1=5?dQGNLQJj$&{GA%x2g8qc3}YycK-Kau zrzt+m|E)Uc%7Hm6o<|fgjF9;?(LR8TAb}Q%4QGCyuPM7UM2DlB7*Xe{bmHQrC6L8& z7d$nUS6!{B;r};%8^h(EH2oXcn3NJmBkjhlGnq$g(%@%-`MPlG%0%BY^uh&68c(1% ziGH7{5$ER45GQsR6rIxuy8yK^95?8i5P{urMh0<@EFHEegEtCqN2B+1NT7=X35rfu zkjcyH^1C>rTr)SCrA`q&TD49SQ)X}sit=zGz&e;;N96URI#J;}U2@hpt=*SqRaq%E z_b`CL0DZz$sZYEbP0dwBC-pnjs{Egs3;jblJ7GH2sc)3>HmSW7qe9h5I%;ofAf3IF z##%YG84R`9CToUkxB>Tu!iXikG-JVNs{5x_S>qMFlU~UbqyKQ^PJLyMtG2d0Wx-+8 zhMs;SUtHNFy$p0q%kt+ zX;+WY23ZyBCUe=&ti-UHHe8FUtk?Fw338nThyT)w6i($W9NSC_ueI|JMbmF_dPhEw z=3+TAw#q~^yAMFi4&(AzSmo02)g(hZ%H z(oThsPmuXf1=3R@)%4^XyaV%VeO%ZVni`Tl-Bza z^l7~+r9?ZM$t~JSXfdn{y4njelv8aE$v2hgPB4ln&}#Sy81h|)gAR7!{s6-R6a0X?j%)#4 z{A#Px6T324UB55&tEtixxq7#~T3h@os`{k0{$5}Hf__Df_x8Y90A_bp^UBvA!z_65^kxKY2?23`9SU%*ip z*j0?%t)xE^BG1<8ZfPm}mj-LnUUDe>w+0MJk83C$f0mTu1hA|BQ+!TzdPq>+sTO(Tob%&I@ zW#n8vf3bUH;yA}3PK*G()x*4y`*E$ria^8M0nggDnC6;*idA!7qLIctKsTFpQ~8P$ z{TO0#5$4_&Cb^wb>a+0oMzy}FN{enf;b?PMEr|0P>ru1#m6WNpoOGf&;u^p-K$wV^ z)ZXAd=92O}cl|tAkRNh8QDtah$L?hb6FI3s-IeinEWK% zHZ&gDkgQdC`;bAdg^pn(lBs5uLX%WU(~;PxZJ&}(szrOL3}I6=G+wf!J67JTNja!h zLAR{>mPMvjvI?5csKx&D8&17yXuN0#WURbF)8wFX$-RtaOxq-dMYCibRGUic@jqV# z>siN}vac7xEo*ly8jopP{CjybK( z6?H0I;3nrkJC*&gYLs$DE*4uHTaJfuo19+wtB@R)l6T`8Rc;Zgz@M#8_WiGHUTm%) ze1$qd377ptCsX~Hoq*e$?Y5UF5AyEot%&fhtC!ek5Z@i2wAn6= zNZFevp!k3tuUr`FL3{tn; zJ8~zRws=;V?ze8UYd9PbFwy3R?H~5i0o2{Z94;5~039G+4dBn%8ut#;P zS|M0hxTLaq6caqrA1X8;ycDH+Acolg>WTLZ_svh7wYb+lz`RxA(sd>HUqH%eEZne- zi_24`^+fs0P41*m3WoaQPHvK$AG3^7%p;l%iKS9Y=ZVn$UKmuiM5WyoQG(0Ti{Sdbe^$-VhLmr~ehs2D$ulq+gF6HCUPNJj_cT9MJ&ZN5z;&Bp!XdZAJ zf{CGGWy+uIjbH&K9fymdB4sM3m@S$iE#u2qmAVC20H7JXb|$3%N)gH_q(Dv*-u`!f zl2ASsslZYW>=cLqbGFK`q8*2R5Pj!UFsi0>{K11pHJ&yC$Nsls`$ziD7Az@@%M$1; zwV`0<0_0qNCJDwYj0?LcX?)@jM0x}z`TcQ{g#6GZFC|TqjA+VSX+Eh) zFKLQn*9EJRLC0Paf?^cJ1$4w|_yR*@`C?NqLm0Gu=zlqd-~yQs1DOML%m(RV+8RDJ8s^HMp^9kx zZ2PDdWonD)LCB$Hk$uxF)yQXk+q?GzhKdofmc0=n1k-E>$=(v9?~$g`3WP1~qi!qa zN;wTs41p?%lM1q!*1C+o%5vetQg^|y^`m`dw8?rY@crb!1$)?)r7H%5`m*VY|8Znb zL+t=rbU1%38U(tk>-nQQViwV0o%-$$t|U0oTSRAE)rRND`q*_MH`49LG^XP5V?{X8 zM9o_lZJLjt{-A%dPW`OhZK)^vb<3>!->0Aao0``wZ$)p0~wz&#(o3hZq+s}P#?jqG*kO_ zGX~`9wVZpkb55?X$jln#QMW5F`jd;U-RZWNbg#|!PE3jSE^hiyM{v%bzATOUezi*^ zM8Lh=K&XFfIvd6t|MS3Vu%q09@QXTNM+P&;=DDxMhnTUC7ixw5m4C5e;goLTG_>aM zl4c>vE3GXpvD{i-typ#`ViVcN(B0@7ij+`G{WlL{4*7lFYXcYdBG-s)n7u&@unn@H(d&i^~ zh~#*@fJo`8N2$a%fkV}QnnhxqC{)_?3Q8beXHz5Tz zrlK8V(2cW`^z7_UB5HDt%$;l6)B+)w=eXS2 zl^vXaE1`el_C^h$B?Zu;(JT8eFJ9cW%DHK3qrJ7o&B@`S7Nw%FWx`23s&iX_sz#8b ztIN+&KcIg%miXQq->W^EuPgh`8}!Hx^XPFH%}XzG$y{G!k9vLqr&2C{Wdri)Q65sE zjk>EVx=$f|^5S`HL;vncef+{MaYcXp;)?pt+Dj+gtySB*LqePP@&6Bsa^4#3k^Q$p zO^EvA2k-yTg#XXVw1kzJt?B>JfY&(FK-EC|<_CofG4dF)*3%AzD$I8pDF2;HRZUf; zbHRjdcxf6mCKk%z?qqd!J|D`^{JE*XPwriL;`ug~z3`p?{p-rlAsH+++9=srlzSiRClQ@ufnC7VF?yZ`@Z?SvaF2|v$FPYB!F|0d9g8nySbQ;D{DD9mWW?L zOArIaPdP=p)lGC8?lXdZ(IKS=o_6eJYBoU9s zI965K{j}Kr$`p!?1D*-ZZKxomtXzS!NtBvk$H{CKX>L$$2ul%#r^kZ;LyMHhXnp^L z$m~pFRn%z`d|77Ob!c{kU4BiZ&n%pK+0K%AY7IUN_fK2FLxvLFz6X<8ylJ|VOx;5( z_BC*@->u%L(M2Fi?K+V-Rco-;N&w5#Ul!W={zH+u5~H5Rs^5{2Ns&4ra z*yigc0oC)C>Uq(bm~>Oi`7&M`SE&~1?I|7cy+`3dm(9(iPNjuVNW%|k3Tfkh=z%*v zsM84LhAk$x8E`bONJMyY_UPCS{V-?#3^W6oHl&4VXmh>wl3Ctc!Q2(d)Z8}tN72jo z>uK}YX*uQX0TQ%)hxP1FY%- zn26Jziqv>2Hk|--)qVJtNzULVUx$kbvADE;_8yCNtkQ|G;RpX>y4Hw>I^L1fgvPpP+O8N+i$gwk zxA6M5d}lN@&Nf};g%C;6Q`{c4Sn{;!PrYd7;asoh$E&J_TLgMwc_14tpaAm)w~Lny zKX(!gsOx~O-$|?yuNeoPVcBK)z#qW(mC~g9EK{e$dPu2uOx6x|38KW|ZWSkCxj?Tk zpXvl!Oqd9Zl>+mHE9V&2XHHFXrjhzq7z)vXm93OG3c?|0Y-rR#-wJKAC&p%oxVa^# zSw7Z%(i&I~09TrFIZ?D{GEZKWBw8Z;%ZBv)K7j%xn7iU{3(&NtJjz2@&JsKqgTKP7 zvCd+O>JnYcxMrLFTze~upwzNG{D2jSL*jac5~n;Xe)%aq|JNTq9rp~U5c#kGD&rJ# zw3&cpl}^B-#jwJpA>~W_LrY@KeV!Oi^r^65w8#$ZFSHf!dMIwWpl4c8@jY}0UPAzY zU?rwWHva)y;sy9ZFdf>8WGPcX#}-*n$%SXF6+qa>HXce;qJ(U0rFyrve!h-_QxslG z4+5POpnT{X^o9Pw7!c9^!_o;hN7lrMB7`FfYc-nYa)bphcZ*Awk1+2s$|N9Y-goAsMbg%~A1vC6`WE6eRItjImkaT4B zpDkm=sh{}?rfu)S=H*F)O(mbME6&VnQ6cVxrpskT@y~^pyfq&sdo}JSR)+gqFPl}uR(Z_B6WkY8DD^%?NQ<3ug7t?2NWUK1sX!gH) zd{p!tP&JVFF>4y8-HFSHi`f#>g^aFzTZw0tGet%BieF9X6CcW#jcAG_#uSZ@sSx+V>zdmPjYJNN)^wN)R4#m>OR7;^;Ac=e?9VRr7Y{1r}%kM8tM>$BUw0oE5DRL7eA9Edlf zSF9RE1gpoLxg@+wu7M(N4c1heCldJjM}2o?!+kf=x*9)BA&FMz>Q`G))8{XU z?5pdK#RMDu4r)+d~TxCULl^pXvj>s?yYB#2|J<8o(e<1Ss(wb?QA1zm_!=TAV>WoAS=JFz=ALx%y0sO*();_-Z^7GZAj&fF? z5%w3%AWTu=NJD1`@*e~yjI-V_)Y=xgM#%y@+`h6cx|o0X%!GW6-GwP}8bVwG-D3;W z8Wb!B6>5;TL}bm}h55^6M8)I?iPSEIcp1(qx;n)3$G@qifwh#GGt`VHw3yKWMC|r% zO!=RVKeFuGpFlM9NgCc!3Od4>>Tlc(S)!URrL=jt+#>3F-bm`jAn1(XCK9ca3M&yc zX(&a&1p1Q5K2gSwznwE{Cittl8L6HbXO(-NQYDQSKYups#$C}=hFtx2wAEtXFkYFP zG=;pO4DcU-95i)rl|qoi@PO{YTqy}&z|VZGq6C7#BLRP(_XIDzBuiMwnfk?{ zWbfjtLcZmp>{)S9A;rEcU23%g9!!Ezi@o`|v#WLDhK2YkydP6zl~`;3KUtgqA=6DL z&UpU)cf6G2{+~^HQuZ#c&Tc0EapkF)Il28O4^7U<)x`4u%|g@ue^7Ow_U6v40GVGR z+pGX0A~*mh^iN?ZB$3}lNMt`lBba0I~GN0 z+_|7rR&ZM#df3?R9(&llw#C|{bFGZZE?2DDhFfp;hGL*|t{XwyD?2sdpVz4k(Yssr zR;X@T2OqV{4PCiw2HLrA25MBaE+ACYW&se;J=Toiua6IL&}*7RQLpzxwlACdATCvJ zd2nq9{b=+Zf~Qu;#sqM$M?l@BJ7q73C*wOO+%Nk?GhrRKjO4xBoD_!y&_!v& zkSlSumv7cXe)}MsvxkdS5t3i%5kdfbJ-eba zFuv&jiukr9;^X>jYUZAh4Fy|LZf-9d?zuC$6sSnl4zY*xj0S0@z0SD($IuGF<2CYm zS!lG!ul6QaaDI;;t1$he$|#4kbpsdLQA=GrKOE%HOq3?E&yvWJW9M3sVn{5{o!h=Hhw ztV2tm`{U43S!i~4Sbtn`!quah;rMU8*8=1pTbqzjx|#T?WywzBojfe@iVii$Nw^7^ zE5rVG-!+>FLxUdVrScB7yHNq#YDOL$EGV%JP`^*%9w~$n$;~o}BJR_!y)d=1ZQFZE z#Ly1q?tH9RFa!jNGG1{>mCD9)xB62YNtwaar4cfu@p)7-r#CP{un{oR(0vLCD7A&X zxWAlC`mJwgKH?@E{$u|>2cBE=KEt0w+yrKl6^xM3OLr^cFh8x;Z*LLdfIA^gj^%GWcw-_4?g9a z+(FybHwKrvNszz40nA_Wg(fj!co&bzv9@!+G4^VB4vi>#dfsr zyuueYI)XVaXRSMF3AXL5M~(IYPxI~8-dZV|l_l)_!^5sV6xS?I=?s$RvR>z`7QKX9 z$%}GN`}9U1(N4D#K?tkowp6j;hx4)XnSa(d3Nq`&_`ndK9J=o3xujWHOhLCu@pJoU{JVE= zaPAPuEuZgiM9_n4KawxYL$IofVu`^Hem<<*S5Al*kvfvkP@^fM8zn|RiQ<5z(!MFj za0sPbT}CkW)8M}llC4}&lI&c=ZT_n@eLpTW>I?=*f3c6W9fMICtyc7bI>tfd{FY?% zMBHBan?8TXwv|BwFYp_YoozQC3^i5IXLV+jPRdKb4U%qkAi!H1QI_-zL24rrwo z>=AkBa}yr~| z80TLSMRx1QwIpOZLWTAqGR`g|1aBRY13diN46^ZLMH~&0Pvz{z*$xt=*)HF+dqIAq zlJjXP+mn>y>BN^Wj?IJiaK+i~%epz7jxKJ^ng^O}`iiWfameQRsa(!Q(vy*LEH@Q=r((ol&e5Kg zHaY%v1cImcd}C0yl*wwu@Pd$|tCirvm)#-%g*=L4p}$RSsxrbCaX^oga-q`bW|`yi zR3cT%AhqNM$P2FqDjBcf$HuXHagfi#u1c9EjKbH^J4R{aoL{(-Ih<$+;J(|28I{D? zD+?T4TgAWMP?``JBO48Adg$imsnlCY@erCrPA9ex?_b}~rldW_tNKj)D4w9w^sNpz z$sIG&{CSWyTH%n~gF#k$n-sy!Y9XJLK_4l%5lkm;3jhL zKGiosw^PHDmMr_B34JCbgrC!B8?Hr>N37_b81zLDCE06O==QLDW?hnaK!qCyLt%+Z zlV1(9jbcH?i`nBUaMP{NqCrx)2xY~bpL}v#`iyTh|3SM}2-cF!mOvOiKH`YX8XbB~ zNY%ao!^Ms11Y6h4L2pIwVf2Qrr8Emlk{4Yn~~UnkFutN9WJ9 zN1xQ1SL9`;R8|!xzy~qS+XAQSCd|k5Mr~0$uSB|w6`y@ zRRL#R_RXaNgoSNle>7*y?IYPpk^ZDFA>Q_p7_bB~VEq$3#QyPTFo6O#K@$ka>Zvc9 z>WCN4ALLQT^w#yzB1x(2hT?bvhc#)HGqfYm!UACKAeY1=hPS$-sojL;L3!tkRjSI- zooc%^gOL5k6}IQsb5HeK!cPq`{2v4*574RL3L?z>dO-1?SHvnbO@@J~VxhwML7TBq zC}ze_Opyy=1zGcR^Qi?m+-XOpQWsYXrl;6|mLdp6YKK>F#lSs!d~vc_VVZ^(ad{B! z0}}D96Y4_f0kwluX$h~u%1%qJ;p!2^s9gX^sLKGzkTmN}q9g7e+(+bK2Vgk!NV~Ve z%V*eGCa);!fxeuf(GyQC6eEGF=E@yb>O6ky9%`g8hnqVsfVH)|s{Ep{6Y#W=YAvPl>KmB+m&mVqi|&!|AJvsuI<(JN~F za&!dr22t_{G=wwxRa5&&XWZFl!ndWurkD^^ z4uY&kkk7^*Q7G`j{kL{yfQi6HHShMh!?Tn<+W7^{!V)=ZemAew2dKmb9rOph;5L{ho^mu+*K56fH&z#qQj5?sJ(3%v-+fZTCXT!JKt zX`WsPL63G#LR?Kw{PY*eM=HXv7W8>Q;4)~ybCpb_hWNk4$Ojuh zF2+S9zG{K8NAl5xwg>fi@Wgt%*0s+C$bOy$9tw0DzxCMjdI<}O8_g1GL+BCfT|xHUI%7S%bs+oDfeL`q z^{jyI+3aQH1Ws7#_fP?&cQX=AK6(NjuwSsvKfD8b5`ifKd_TYNLjo}Oa>zb9D2Ki| zKB@)-BAsKtJ%G<;pAJYb6Hozbq^P?)3NMH#U!oxa-pU^-d%P&$=;O>^6+pd6!h{zy zp0B$r0tK@rC|xDFfX3vKUIL0sNh5^pP-Q-geg@Xs3Ajs^b+w|Tq$QQ}T zEygCsxjGG~9gTz=TE^Za=uu;bpd8}Ek+F*zVFLc>TWD18$UuGL+>~Cyxv$VUmot}7 z(7-R!mpU;)QvRBiISuF;#$M}w1Nv^`q5REXM-oc%%s6k>PvZNJX0wj}7h~TTBwMq! z*|u%lwr$(CZQHi3)3#6B=IQR!w(aieckWDl^WB)aF+VCIYt_zOQ5BiF*UEelLUu<% zd5@Zf+N`m&$be6oaEpmN>lJL?^ScSp4~QR?hxcYS#W?R zGDbe)n$RKb>4v=Oax06+Q!&cqnHdNqws7oR;UTT*In|cfZinOa#@FxveGU$i|ej3Uw?4J5uy3nz4e+f(JPc zx?t(-nxlmIj+urbRd(~|Nvc;(*TQvPoA^OXYs$?WZ&e{Bt2}djI1q)m-N3M3-73@S zvS@1G6f3G+_<*@lb|9SrYx%%QQ{`rv>zRYCt-^mFIdYB;z1F1#lTNDc^0o(riS@zRFyV;+!Rf=>u-Q`~uG)DrW(HXSY8=T;~TARE;2MzV9B&ORa=G`rxz zBbU5$&r;V1aGzSf<20d8RSYHxOBG|CVHIrGBG`s?93k1?0o2f=`f_aJiKi05lTY4> zJ6IoejsLo)Y=L?nGwl>mr`sX6X+84%&FLe_1tZOiUa-%j;%SmP?L_A{QK%kz#xO-U zT~kHZf}&Mvq|Wo_!SaSkBgOu=%^@j;s$Lk@A*x2%2ZkCoe=ymhY?hV1VE7$%7T9%w ze&qJvMSu_u+A-Rmt;Z(q3=@SD4=YOIKC)ui*lpw(ky8x}ybOC<^4b-|Gzm7 zfujE%u>RSf$AbCKd-Rfa|7nk2Roe!|6y?jzePhcGyt6b#THBzIV8gc12{9qfh!UNe zwrxeK5@PZ4M~Q2uwy6nXFE>iexCjw>-T;E}6j&s1E-k{qCy64GjBkvY5yRL>CI)^) z`g7*O#nRC8X16bw^ZPmfK6ldR^V)nBfM(EIkVeQF(9BR9VWVL%KG$iDG@Na{W%9~# z-F56C1jik`<2=POUPhP5yAiC5O$6SB-%GSdzU&JCMiYL_ zg(0B52AC-mkiK@EF#s`n4u2Gdk87ig0= z@=5@jJ%7@YyG0sX!A57Q6`S|NAXJJOC}?DfUFWd@O`gQ*72)hy&Ff>Bh%rM)z~%eh+D3hwG~o`_8J&wU8Z)hmWLvQR3@@){xMi|`lrK^op+ z-JV407h4hQY}qW^GaXHmGx6qVr`eFmcyre4O4*Jblmgk6 zTEu@p=)fr8R89=5HzZmuUw(=U1Y~biimn==v1Mr(g+emg*RxxZ;fJsqs+)BW{KmL zg-mA2aFY@RQKicJZHTJ4j{Ccbs>)QIcu|q3d=C-uFM)EhjQDLg{*Ox)B0Xb@J9ZDD z?U1+2QEMk-_Q@_CD*Zlc*}NX=X#GmOAZndaWze7ROrE_%CDiH$F+oj^9Lb`3*-{6l zY|6XML5=Dny(OUC`hW(NP=9cbKZc9x8|_v^su4dTbYiBHFK#T#cdi?6gUYguQsAVl}3I?xoTJQl@I zBTpz&EFKwnmj5Dp2tSt3V?4qV&$iWa{qcnK^!9o8+$#^`G_UOI7X)bn$e5n*XSAOy zh9UHyV^(vtx)5vTLW$H%qJAB`5$|~Pk5F)}ka9zT`>oF#)XxC5X$@~r1@1)fU1ga5=R8zQZtvFH>eRmmKQ$R~oFv`(Z1j_wdy&kU1Fh62sYp&|L zqw8`f4|ev>K^55wq(@XUB6Ua9o6|2m6xM`Hr>Ud_gIU&|%*-HK^B$1~_xqSPot1I> zwSrT=0#g)SF41c|$fJn>&ps?~;NCqDXADv)eG%y{Z6irVF5!(v0=MN*n^7rVg@8P2a?HrMK#COLw91=wTWzEen4@2o{qXs zE^#N`sEQy3`Y(wa8bSXn$F_H_<_#Ft4cW%=M$8v?%)9qm6g-ahAf~sD_I(C0Yz%`o z&vt4>^!|C%Q=Oym9uJks%Ts*8$yJ6APhe;zU88tbTXf@~Xy$oQ#A;#fA_S)h2M~xX+SP{PSS+-zT`k%Kum==u_HIv-QN(UW66Q&CEu#sBx ze7a)kev0T5rdjojuYBgxUIIjYF0-iuJ;>}Rg;I`yeK1y2Sg&nZui(0`-uc>`IiiV8 zG(6?36t))9t&*>zAwNnmqgrJNBkR+S2Mw2B@QU+ebOf zrekJYwvK6A?v~OHT~g_JYx5h+W*^UU(U97Lc4w5uveXy@FWAv$B{|{@#-L1fhUz9W zl%_UXOu=WNUaHgYL4SuPIy~<<7h3BF5ZfBtnh)UQX6PISDn5nvv>8Sm})ic3Hjc^G^?;2u5@SAZ8&4E3a&4B}=jz zrCu|et>#opb}+*b`&ivUT|6>7?~KleEs(fEK#0$OGtumCk@+JG z2mnz2W2E_?xYz&f_x`Up_O5m&q8`Sk4*#W}nX4!(KOlhMs|+<9bw^m_bSDslADK%0 z+k-GEqX3+BGu>^N)l@od<))1%)8hvGr8uUm6dVo*%RMbHv&kmA}-_re%xkYnK?TI%QA*2Kh(G^q>_0qPJcLP zuKPHQGX@EBlg^hfUX%nfm7B5yE5xQ@Cu0if!g%F# z#+b&`i`G5Kc1?&J9#Pz*{szP7g1S6>P%*W<_(Frn7vwpyZTh3O)Ni=f2W?Hn9V76H z%$lr7Z!WFO47O-(>H(=7Gu9<#P2$6AOYf7-h5Jim?Rz)aUus{#|Alz?XFOKBZkz!A z_&1jP_%~Ahe~!n0jmDlIw?-UMl&`GZtw6($VUP|HP}25ETj8KA0HgM3x&#mn&|;G{ zTZ26&;c1uyB`rRU(!(x356^n3$?gNfc?#6Z1r05}mtq?EXP73G86-97XT#36_Xp1H z=Uiv6qj-M*4@d#}T1$(ek}$CD8Y8J;YE%|qRh|W^GSw*yiqRS{RCHCH1%=4y)b7ttX14_ZkW;X z*Ab{T@)}xZc0b}tcHKdyaVsw$FO!eEyP=DLDU3k@uf^7tRu}H{iKygivAptD9pe1E zcx^lZw=Zw^2%?wzqvRybv5u|aLU?!_W4q@3p z46jpZ^_i>ccg;>Twx*9hVr{Uu+xjY-uE88__>r)n)f%PiA;0fA!PpgXJ_)&3A8dJ3 zSEpN+a;&kBw8o^EF4|+H5Ugx_Cv5G^#+AroH8S49OkUXKVYK47H8<8=XqA+ZZ^}Em z>=3_xeWUlGyAc5F9=g5r12?FEgzB?Z?Y?-LNR#NUG}>O-XqnX#oR5oCMEAVau;i@U z+HHu%Df{P8Cq~eVCk3V7VmJQjX-27h;=P42x6_@~T;N27IRa z<+b4egZ52(h#;hSnO^7yl-X!J6pORqgA$lR(1}db?(R$Sw1vn zV8IQg5N5*I#A$5IY_D*MN+QpL_h#R;|%k%WZwnpeDhOp#3s9- zkpr0kn&c+D5{TZ6+_Fre_Z|*pJX)e+O7LRX?`jJd#kYAsVN_oa{>O?8mMOo_Z|*fGP|-;y?K3?eS~6kp>|9DD#7xA{Bw2 zLR|u#<`(vuZgmDood=90&x?TZF8#!~Hxl4H3w-d5-f*+Y>R!Kgb7m<}OWyg4z)iim zS(cCIukpWf37{#6b#vhrl*2F?SJDdgDNhzLBSlgKLOO>dC~8Kbs46}c59JQvJZp$& zg99NhRnq&}e53TsbKMo<-REPT$Bu*>z4Ap~0MKs~3C0j|u?ybfq!^z|FcX73fZ+E; z8!5>j@>pC|#Jnl-2BZyh;@)%QLY$P~ofhJTPK^g{ATNEya`?#Qet4v-CXb|rFHs!6 z%0T7NDu0GKVhxs#S>)Le>m)%!>56V>&-~#Ub!px4m2&hecKlLrwLi!xSfr)rX!iah zD2@hc7t3lX|GFshO1#{;y;ks-SCcNxlAF(T#B>HCx8xCPGIOkG&GBK|fwb`dH}FYH z?SYrl&qB)lQm-5J)JV$MGAM+9Z*(2GwskGb|NJx4Ol4Z8+}F(fN&gn#{JFIS8(%MS zzk9IhJ1c~M~xwjnyHp*Erw8V1hj)}3|#1;GX@*#atkF|JLp{@Fbon?voIf7#9j#9 z1v8nc%;dlngQ<*^W#+62*~?ReT5>HXZ{?_2WteRWh5d~*L>>!tkdKrQ;}SO+0gL9y zh0q-3K}PgMcY#di%0?2sDT}i#6}I7tP1x;kJ;_6f^x>Y0DD|>!D?5 z0BsQg%jw4IR<~6}gF7?c1_i-v*QA4z)g>t9O2sZ4lroBv0~cy-HYvBnpx>CjdP2(c zGfhOQrpd2~4g;&U@aLd@leNU*=^ex%jOqIv-Dbng!#b$N{=HQz=VS)e^~_{<`ZVw+ zO0m> z6e<^kevpp%2(zh60hXOlJSvdmTnl!sA?9hK_Bj|&FYXnluxQX}zff(YU)YHwD2>%b z0Yxz%F4??PQhpm_r^Q4?ac(Bo7q{NdsK79nr>pvecnYGa_{7Mo{NR8|MA&L7qZTm~ z9MSWuPlWqo=v90o>quPQD@tM`8`bjato&lVsd|66AwBiB3()LO!oWiIU`NJcHIXi6 zusozv;nXODl6Ore&7-eaYqFr?;ys;n=sO-;%e*~(kKA#yW2s+!br&*^u77lAb3oRK z)!nMY8@QIleIBt2Z(~+>j*J~pZq0B6pDXkTUa&7^ReHHC>)fB4gU>l0F>#(@tT0?- z2{XrnDy~1Bcun@Ka;UZ_NzxzW@YJGfv>m!~<(@^rt#JP}LEoZ<+$ic*1pRrYH!atr zla)Qz^nk5w6nRt{aql~CtxIEB{Ms_UdAp1<(_&q(#4>c#qUqss42Mo0h6NecWm6?? zXS0w;@_tD>IdV3Ie+pvH!0_{#3>kOkOTs%iLkT(vSXon+Xdnd{$tQZD7UFlN51^>@ zxCy`_B$<41T--_`prEp(~9SwF5^eisMJ>6U*tL6yTNZ!Il|8F9b_K{FM!S0!^A< zct{wmF<>^bnB^1Hx^hLnh6I`D9rVi=b|6+_kf;^(2K>+aK;n;KN2*8IrEjA*N+Nm# zaRhbzd`3h_zTt6HpEw3NgTzIX#UO&)9uHA_K(Ws!>>VO|$mG}#Rjn~jn*%UcWyC2F zD^tu91gYunvy)4*o=Xt-$RYr#{T^%g48(@TC9D(S75=cJ6RgO3II>QtChm+A{Wp9C z`kp_}2#44nNhXMJJkP+@f%An|#F2;-Vi&Ln3~8oAdul-^PI{T8Pna0AP5K7R1koIB zXU7f*g7fq~N#U-8ebWAtp{E?D9koqs+ZgDNDIoT2gXI_ZVN9uJAsnQC(V%Hw@h72{ zZl0?I|JQZ?i~J;?ZMo^q9pnz)&}S3y^ZEe%3dht;aE005Tz008L! zLyD_xY3pEPX=Z6^qGsuA`6J=~uRM1v*E0uY7D!sk4BBA_8c# zp&iGma))*5feyHd`5cFW3=gq;4rD0;T<=y&hUFG2Z{C9ht9XQa-oj`IgE4Z1SuA$E zy6P(LD(~#H_A1kq?@gTZ!tJ}a&+GB*Bj#*eZ4Yu|x_} zvplBo8(-SLSHEYWB&J$7&ZQy?1H(h-4{Y{3YL7OrfVusK5}nzETA z1x?w~5rY=4e3(T`rhFJii)GP>jMi-4h>iAWt|%1E+0qe&R?Ctx9_`+;Api~9(vgG~ zZQh8HHf_#`k~VFAk3tJaHrm*tAqS1x!jXnHu6X#inIjO5e1S+PI<+}sfk+HG7R|QV zqI{T2Ysj*pQ%zI3nj~OJCX#%Ay;7h`EJg>c#7m5-4DfUrOWx|<8JD`{A!%#^Kdb@NC|dAbp==a|kB@rjBIICL{*`zvG+7jtw& zxMnze!?;{1F`L?1w%IB{n@tlpo0IDy(Z_k0Had8xzV5bGu`Atln5Plq_fpWo&jx{b z_np={FxsRy!(e;Ch`DbzSmGdf@i?bg&JwHW8epr5i+wvJOKF z3{A-zDa$qn-4HHH3Z?{~w3T*?Hn8c(a^GDpC`4H#t}&Fcw82sgrRy#)DQGP}M977U zW8n2^q)F0qE?Qqty>!p-4r^u?9C54zf(n4oZg8Z0IMdxm#Xd z(x?f3pa6)N1i_iBrG+9qc^H_{B^MZJ&%kP(%%Q>=_=d!h=;cnQ6>QM* zO%)SzE1m@capsOa!1K;5 z*4TKMYpn`%8f%c6$UzW5m_r}4GGfS;Ftw$gY?>zNAhki+WYxo0S=5e30-D6v*)228 zXt5?O8j^Q<1f%zSWP2V5JrXcuX9nyr!LM=B125B=1~qoJA4l;wf9oAr#e1JF{>m_j zv*NyO;iqHQyxHRWl4$*)n-&^xEiA=~fLMJ=kQBPbii9X%!yZ#b>B`ho2_tnB?w0Qo z@#tuJ*7q;RCD_teq!uqgt-P9`DfFiGC{%0B(6i~Jo1zsDE!`Nc;r$Rx>&nwbkvOf3 zNhTC58KW~#@m+5n4G1KST_^XO7?MVyA-dmMYH_$G5v|nm^k3ZCH*PgvI-#+l12W4+ zT4ro;_6-$jCuxWYZd(G$8h0Al5F#_tUn(5OVqy#RKQ2GFVOOk9J+yJuAuw*rfZ{*kWXtB>b`3*g=SN;(y;bZ1Hvi{62v}Fvz*()ML)7~@lf5}eR^e4 zn*1dk90>+Nb~RTu``ddPg;aJDLMlIjNlSt@7UHae-Kpy9 zhoLriL%$lloZR2BiD@-8k#@9daMe&6`k{$3nh!4Y%1qPKVvcd@CYSyNY09R9GMfW;Mswxh7O5dH0%?XGf8*08Esl3>5Gyy?uCIlL z@4-of1Hn6GbGBEzi#ydYqqtZMCZ0MT?PwX$lS=nEbb~C#SlB*(ADvf2?c?PEbW~gL z-m%(N`~clu)PkS)WNBkqc`7h-zA&se&ycf`3f)^IcMyzZc0y})c$MorjXCwCvCD9o zw_fQ~qZ!SGvx^hBHBC#^15AM35mUYRK$f8q6sWvi9G8sIWreJMW^r3bQuYng=QcP`CJD-9<^mAZp zs2%USKw*mM_UB&m{yJ2RUm&e71cl2vF9?bR=B(s8F|;5+ZB+n3M9-~wu_pTV0J%S( zNUS;QugayY(p;e3YH9)kx}%rBRUz5VyJ7JBjU#l9FF|9Qiu=UYO=wx2^#4_cqoTX%A)hs6%G4+GrCPX zwT3fkw@^QkNv~v`DItI;y9&t)m?`K$qdPIpX0aQ~rx$_b=r?J9}aA_>vK>)@LG7p;SzhJ@z6 zH0%TWbH_;wDmq*=?^l`a=Gm%ovH~Mx6ZhQnb%z$H8~9+(U)(!A)2?7j6Q36NPbCn# zmZp_CQ80%s?C+?UkkcjOzMN{91idtS)g3L}dS1E46;Jn?zmJU38^OTRyIDc{f~8y? zD(Dw!DK+hOvCExo)-OC184>d<&}y|SMe96#ds2; zwRk(QJx(XqZGeJq!aGf8x7C$*8D8Mr3^GdZc64T(L%kP{SPmdvS$XXSGQP~1qs`3C zkD+F0vTbTOOeOhk# z{3XF^j62}g@;!k=f>W;HT?Cvw`$+ht4{>LCZ6ux{yFA%&NjTMJ3E_@;^XNVVbn^lQ z+Yt2uJ<#~>kCSHlgUR09-7gqdr#tzJ6qdYIU%Aiomcw0F-eKPzN?$=&S70jySLgG~ ze485Os4G&3ee-V21eYKlTmH&Q@GnF9IU&${;|2n$cVvJ@+UiL(u{@Q#Jt9Mw!7j## z9=iDYP3c$D>Fm($fK*fg=5?myjg^rIo`>u#?}z+ZiGff6d%d)UcBD4O=VsyQuH%1s2hTebT&QJY-t z>^ECJ-DBh|9nNI;N~4)7mz&cdbX9S2!U=mX%d{S3B?C>Hv+ZF0-urXfdpXgAko2ot z8aLLriw-bBFR#lmCel=l1Y6gXwEJrsvZ2_{2Puk+nuZsW(=;}&C!i<9B-L*}8(G@? z@P#0Os-p3MK!L!fH&g(&e8U-6Ye8)7r&m>b)Z35#>hkmVFRWq05n`!cfa%)3GxUoo zXpU;sUO{ea=Hmv*aaqc-#pYT~8gvy6H)L7#UuMugX@|EaoH4yOuoyH@RLisN+g!|r z^Lo?0erjLX1l@W5FMOj`!Oz;$W>fxsEtHt@#<6WEmo2HEYFSCkY9`_A(kd29-|pv- zsrUYL1gnH`L!{ilwsdJQ{cZcF>%Zws9Z50Z2hHd1FVE1gnui>`cCiD0>Wx7QtjXeT z;jY$;_gB*D-ZcdMDG{BiH+}D}3T#gX+T6IB>I5E&n}K@*B@4zFvV^w}eV5-1C?C4J zpK9VOVk%6@Q$UUMpPMNWBpcajWXv5iGb&uw!)Pv6mUv40*7dgw%>E?b(*BFiw<0lL zu8Y5Y>})Q^OdDgVTSk_&e(pbNq}9lnXQNX{g)60`sw8Fp%PFaTA-nzuw z9_yBhrEpkJ#s+SNw>YISR)`Pks08Gg+0VJjM_cD?H*L!)<*P+R*=sdON< zf6m)#Rd>DG1w+Mm8MQvL(B!LbSa^h^k1cM4py&swsk))+DsRwi%7?kBE&`raO4TZh zMS*F(Dx~O3*%K0jToAtJEn;kY3t#XE30MYrvcEmvnvL@&hSFmrt2rM?GRIQpmD4QGQ|4$BVk9slt;oOE4FH>&gclQKmKB z>dU_P_kX)%yTS)@-vkRC8E6jrwbNVvRyqVv=s1A*;Gff3kk^x|y7dqW;}=LV#v@Q2 z-4w2Rci9lL60;?4*^t2XJ6pt!wk`R>Teztg_Qg@Yo<((WeY51#?3bY>5kJfMQL*8z zGFv*a6`Ag;G3V!n=#g!Qo0(~scPfJGi0Gs2hM%KQu@bbB=m^W@s#FKl6R(z9)w)sV=T^%0e$Ca1UZz4~E zSZE_(e!-N&JE81G8p*VdG5;}+7u`7OInkQvMiyIbZSwS=&p}Q7FDSb}gGEgp4fo}rm8!Vkn{p3rRc z^ktujCVCGj-;tfDlY3%6mhvyEDc-ZnFJ{LsWuD-saP%Af#n#z*O|OaEnKgC7(oI7A zXPra(z@1Z&u8E(asTWo?6a5Px!t+o)19--M6v^=J$loz1zBZJf4DY1L-XY5R=-2BM zp8E0{;}b_SFY3nXe8+=?tO_QSpCB(}Ri4-nDE%8+{U zJVe21e&3&Dx}IP|c5y*^Cu?Dt5iVtha3w2<`^kUxL%5<1RP#X+Co)VV-(bBK2M4Tf zd>L(r2x1*$zVq+a7c;E0hc;Yar{sn-f=dtO0kvQEMG!Y-Co`ZDJ7!gAZ-+E&Z&7w(n5Iko&(7|{iI_ViIKhdUbcpXf zhT-x9kP;kyALPO4opCDi2y!wUxNVp3G}Z0w=dUr-KpRz&=BQ@)cG?I z$S;m~zosA`7S%a0)%UOa$iDB#wc=}F1vLZ!D4&$N-x6_QKd!lg5j(Dt^dQ|YFH8koBLe2denZHZ!tz3rL1cSi zD8JC7=xP%YR{r^`aH#CUd~-q&*I4S!m4vG_eTqN$0G$zI-cPJq593}YpNM0?vmC6qe>xF_g z!w#Mj4vcp>#Q5;)4s^$fa}Gd~xP_ABLm-IjLMlKwV-I8`oM2eQ?1GC2`v7RMjT*Qoc#f*f2j%$uF-f3}Y z2Ki7XwS|!61D#{Ms=TCucv2_TK}mkG<&2D#4`Pyzzhn!WePrI?9v#zYT;oM5&PZ%V zCAQO=kg)Zy$N0eIPz&}VkGqGGT|-OuBJ@syQchL5=spO7`N^8XQm?R)f59lJMgv`Jn1dkNq&U zkPg%nKHd`!&Ue6Le0Vnr1pRQw?L$bmA=nx3rf-CEyU|*#Xiabi#JI=p2|c-qXLm=z z2)-fsU71HwaL{+rUK+Z>8Rg)wi^6e9?*+us&vwZjs=LA)enQ3J@KQ&Cam-7Dwl~V| z@b8?wK0$bVw3*;sdkXOU!5dq=EI*+@yk450(31kZdw=c~-Uug8fsQb0$`mkeXhnF} zj-5OFelDKXoUrXU&)jW<*9)hO^K*UQVsI3m*FP6!R)l-+=()p#bMQV0!uv}9e4*mf zpf8iL$}+$ML;ZpA(&s;IgoineJH|7>OvWlJ{0D~apLp;;af=6rvY$4+$w)=j?TO)c zQoJI(WUM0c{9wsHP3c(0@S^ZaQv6~+N>;IH0r=^kCSD>|vDVz+=FbK31I8sF?+Dd3 zb;J;L2)m9isEQc#YeD9HncTlMcMnU-tU`w_U7;$B0?3Eh``}%WC!dI7z$@+c(- za?dgyW(Te{26$m-A(8Ehnw-uVciALJa6nZU`|tN$G7d;`;!o=piFWTo(0!2D2o0M= z1`Z+VI}iGQ%MF!g0BZx0;)LGfc#PBAP!H5Xr8t0Hm@>G_$hV<2+b%SpBBH;-Q3?hZJ?bdPa;-&}4Iuhme2k@R^G8psJgT)L~ zVNR`Kc@a@5#CmDrN^vhqdWX5xd94Ulvs*rr{rZc8eI~2b6Z%wZ|0i0)dpy~UBsiiK z_^&ghiJ*2*T%ZrJ0>L-j_nhIkOZ6WW@=My9KTiUIQ;UC}WxdfYxq(0z3VZ>+@36<7 z858h9&Ia%Y#9^KoefH3wAP4whLEcgLjO+aekGX7GzFrFR>! ziaF<2&w+VAAMjs-ws1a>dhaHOk-OA|C9eE;tw%odg?yZ?6ST48ssoA?YL!Y=-jAxr zE)kP9WGfAII-x5;l&xL)zm=;ObSumEIee$LNfY6n)jSa@tMPD5UJUE4z?8SZLI!i2 zdl>r%gJAg4wBWa!6D6=wOC zrYu>I8&+!i;Vd~@UbDul_vqp3-mfTPzA%P523@RCs=@cT*NGeMv zgsqJDfT!9}Zm>Jd9LD!OPS?$Y)cVfKb+T19EHOu?+Oa%?a%?$?AvUJ3PlB;*jC+&Q zCgM~FDa}D0Lk;<|c;lMv8AC|3%YxzID8$reh01eqeb+Ntt%$R$f139Sg7Xkg+DHLC_M)E{b?CF%>7G%3-x;u*OzZ*RBI*T@4fmmsPfR zN7RgtKm`#O6tkaU2`i?sdZ$TF2R_SCz*L9+jOjG?TlUSKAk|C$5z6C@3<731sXj_d zDXdcDikW{0Gg;eo)|qkrhsqYMp0e~E!YI;unWfC|7pn5z!dkc7q$ZA!XVnp!m&XL-W3|3&pLGP&%-$~!BZ)Rx#B>{l)DY#l#D?v4rp5Y5 zaBC8MGaibpgr)KvS`dA#W9(5V)?xidE>5Ye6lUCP3*TC`7-+i`QI~u_+L{B6ebsY$ zjdPPcmnm3**WFL4o)Oy&-`F zYT<*<7;l#PwUDn1C<)lp0_{KPayLJ<)}0hLu^CL7x!qoUFf|1#*v zE=ft_rU8zot-HFR4>#Veh$=T_Tdoh&nSCyCijB^Uz$V0&$$rp%|g;){9|x(0cewGotOG4KoX} z&RxBi6Ln8TSK%Q(+ywpP~PFz+mbze4P|g%$HqX1j>B+28UYkz_53Ejua0UtCbo zV99UZh4h(2d(KEpoP~MDe9_~juVX}Fs>S7-iFsS zyKiZ6_*Y7n+IH=S=HPH?^)c1%c7}orDpS49Q7Ldb(-NcPtu@1aQts#33*6v1 z|9jlW;14JUFt@DWWTuA?ShR zdtnE(9)ijrStf#W*K?WRDZxa;w$1=7e!mdob1=R3Bs0TJ_w8F1Og9P`%> zO;%ePJ&~jqo++BSC(Lpux;PUq@-+A@9@zI=ZgYJv16?%34Vm%70giM7GI$Oa*Kdb#RzaBPtZr2GWwEyLi&ooA|r8_+Omq$M@K7Bse2Pk3h`j5 z*Ongm=&U*e;8b+h9$3|^I=@w6@r^>mS~Nyg{8TWgYAx5|>|nKjB!a{T?u=nw2kwxY ztzS^`E8A;#of$t%GI|5uP}y012-Esdeq7Xg7j9Tty!;JNp5Cq~#eKp2#888Z@(FXJ#q^7_w4W3+(+tyK+1Wtny(4qQZ#JC!_&M%Xf1|sp z%q#w`%9tl^ZE7g;?cVthN8bGYROZA;&f@yA`&7g&6u-c`$_k%-ymye$)?4LP0f_+9 z-?{N_qE|ypMpfotUROyepp!56MQETJ6Mvni_VDY3zA`dNulV?)3nR4CZHdJZ`B3?Q z3%3hDsM=T?Xp@p%AsUu*U@gQlmu8b3?Rt zY}^Y)=!42hf>kYC1-}b(C(N5)@u1wpMj6UEeeeN6`wAnJ&oKTB6aTr}k)OJvps|2g z0n@_U99cLUm=LfQS9G1nkkY0CUKU-bdiD|MxZmE^)cXYk;Stu&Mi?PCWxQ2kNYO$= z^tdL-$34yw6}vXQj*D}dy4jYztd+uCw472NsZ}e;t!PCFPK}}ot-4wa92(SvZj6E* zF2GwKlRJ=9hU$`jz2R}hBohuqIBgh=Ga7>RpFWEqM?IK9`=n5bocGnw1 zOnan0C3i1wKtbAd*EeOVC`607{3ztAxEVk*oz(>jr|kAe6fc|!Ln8!G%td8EV>*?I z1_f13Y;_0G>IQ<sPIv200) z2-yfiAkBhIl2R56vkUK(F>j`D%S`c~BSqW$iq^vLQL2jChYGQV$@?~xbA`Yrlt&!>4rtC}jcdos=k_J$X}yHwcJLm$VB}5O z_SJ=HAVM|OieX>SlJn57TKdKw5yM)B@;ap&>jl@bz&o8)uUhNO_4g7ORwX*ZLBH;k zB#s$W!OodP!$^-1aYfdsGi(aT=v@jcAt+8+5~p0OO%YQ5UugH)R-Aq1jaW;bB4<2A zt{#x|(y(wl1?OK0-cYKA4)+vjv3rp0FT=>e?sQpQKEM3UqP~*$t0(SN4_~VWs6ABQ zxJVG;zWJgC!?01e zF#KVc=QE;>NJ`HR_v^pQoZfEFXOG$F|7aSr2F~7w2Ese62!KIDHqP8S>5YQo>SN6{ z7#N^Lck3MV*LifXgw;7_{-Oq}Et<;LS-g#nI|nkR-L?j?4!q`a4b(X-ydR_VoL;b+ z?U7Ji&RVq7f3^xdhn7*(@^kLmf6*?L+gX-EIbv;1&nf8Ke?zhTI(UJ-OUcd^BOtJY zh|zn%(sPg`Fq_^)oST@YRVPrr#kz7T?>&8M%bmvZWJ)z#uH16;iJzUQ1m)J#?mwHK zaKZCnWtZ8p8zXm4!^CL`gEF+Teo;M1u|TcE9h-a5D;Lm7lP0KBu#z*@KGom6HcSYa za$T>Kc6}EDaZ#mh%&}Uw1tno+2k|o#-WdqA2q!lZiJW@IpTW_X8sWYpx>#z(-o&-w zdd&P|SHsHfw_N(0@NxY&+caZRoV~11I58RD017=aS)!%X=cP=^sRvWbeM6vyy@7(dgw7ecXcP43{KmeZi=q?xO%Fz!v6_LK9-y-ZNi@wc z!sQ)u+(t5#FsM<+8z{S?Gj!KN&7yUOycIAln)6Cs15aiNBkz%%cs^tV8;2>OA^n5` z`GscDhaWDRdXUT$WV}}>ruaWC&ZFz zsT6XPXbjyVLTIU$fE(RO>T&%RR`Y_A5`+|`45EjJN-{J>)zl9s!i~t@hjDg=Z*eCE zNVG~W#IpeU>f&B0B7IUs^hg;8zJn}KjG2DX%v&tgr1X5jSYCe7EqJ$l30=OWiru&M z5}6Ta)hrE*((E<^(T_7Dkl(n_pDUhz^js$n6^k>`7tefv|M&8*!kci^`iFS+{8Iul z{NGWJZvTQg(hJ(y2-_GsJO4M>W31AK+z-==cXIfT79G(ZtfC%D)WS;*BOwV7BJ2E( zp42cYHL2}xpG-Fi-wU8$ieo1N!4QEZ*H)(U(M9H!-?xt+V0(W<7>5&;(b{}{G%x5o z6dcL{ri->l@Ae)ayiR=KCXR=lyM-sNGElq@$B{)$)+6T`>EIvK>-(Lo-I``6^^ReL z>Mq=H!sP?sW3!h{w{Gxi+KMF0&Q?;bw9!Eyr5I58&2ru}TSa7}-`Yw-jULCHL4_~n zqm+VJ%9ogZ^*J*ITV2AlZdg1lnYs=Nmzu=V;Zef4P%Ee?E;xe53~Kp7gt%211OJ1u zcMP(%+p>hywr$(CZQHhO+qP}%q;1>ANu1P4e)-<+uC7}VUswIuJDzxA|Jq}&xz-wU zjxjIYXSUqt8iB(m{rS0E*ij?W1{)uy$P6XMtB%%ewlF~`7HK1c<W&uc7?|+(Lm?}LE|m=>vfqA}fyHc>IVq9wp&>C?!utU5 zp&W9YBo!$opiYgQefXat?d^X40&Iv33Z^-=g)tl$K&RmvH(VH0hxUZt!w}0Z(nRkf z6UGG1Dpaw(+V2>09r}X`KSW#^;=cOi^**tV8+J{0?K=SpUL z_^|C3PxW1P&Zw=r%DQ$2+)QfRwV@JUW#5K}82pF)+(KWa1as~&dY4`9FQ)r}!NdrI z4fGV98iSExs^9Iq_&9^1K;B`k@vZx($}6I$0T9?RW*2OsqayJi>x6J+xc@AuR2HYdQqTVrQE zbDVrmeqUYP;0>`=v5qt{{e#}v(Hcz36QfNVw8bWdBZF0;tYJpdEm%TprX)uS%pR?A zaPr+c?4JVn6kLf?ujst>zw%>02N|AK+e|-V4Vxcsn_{_y4cTp=!YZ?DqJ!)1@&1Gr zC1+}3IH;a!VR7@)44X3*krX>!Q?P2}X213&i~U)xQ)H-tqh-NPUOsbqQz<1E^>11+ z5q9?FWYT6UOP77B3^ThzW?UCHR0lVb&-$8%)$_Z`(RTocTg6@Xuq(VS2r3GOMWOY8 zS@}LE8EP5$8`UoVIW*b{VHEZNA)s^=%%RVyuH#b_xEz8^slvPo3A7NI?2efq>VIPx zU?Z>ktdKQctX+Eye_g zDqPE{aB!bcU3Uh~6V*2*;9*`|vnI9bXE2U8-WS8qbglNS+qPsjjuWOkkYGRA_sX)o zVc&y1FWHFs#$(}3>gwa25h-sXLiUFTOK=|PUUD7Rz1_q~U!vIKR)HF0k{MfeHREf0 zAf)QC;C!~0k~^yUPp92PR-!gTVb%p3p^-yhnD9w7apkSKsn=_-vfrpK$GS@+z?RU) z2pSr#4fFE%5fUa;)-h<0|F!S$94LOXifO=%=ieh2Re5$tf!#mC!E7oK5@&txt3%ehMi<@$WGeXdB{SD9UOS;Ob(l zV?}^zIc3aRQYQ>X>~@)Mz4ypv`;swxyT$(d2pGRIrU_HXoU zWgg}Z)?!b;|Ds-?T>Qjc_`#p!CnYfbzf*#cy^D*z?Z38iF-x2OIK8JPOUrKwAdG!q zWn_eq3V5JMX+z8nLpFLi z^}+CrC|KrF-*%8M7ouXum0W3{H?C|-b+BPH-I}O_-C|mukc+Es!n~!qpEJa?nyhVH zCI-*OuOts+fZ}lYSfC*bb~%wgDD|`O8~h&IR`*1)SBn=KHCl0|6K3 z8pk6Blfp^Gz)8kvS}=JJ)9hmX&8!f1k6_hV6lHs|9f#59sdLU4czB`M8xKC0DnK8X%~}1NV>FdyVv=a_iQ>R_wUpDm^?uB zdIV9}6{1KZiI7-`4GNi);$)ifd?S)59%mvd%l3Rj)d5-X!G`^2ocUVYjloir&7S}D zL)Tn?6pVBDOm3KeNv$^B%V*RPx8RcTc$$`8^X{o$Edh2t&Kljddv|DU;KDo10l3@{ zBp%Z-^T=VP;|5f4*GkO>%o1t2VfvQ0>X!FFHJxfwY1zmQ)C*4IZ`76jR^cD_(bRL? zX-8n~YkM)ae8ll1Z>N9*D>Ia-{g~~7T`VEmI8fZG)SRlZ-u7=5?3|0LPT`6~D`A2# zNjY;{P`B9Y36y4fOe3GWcCq$s+qtF*Xr_6NQ#rr%TW4I!?M24WjyOw1q>Kdz?J?Y% z3yon@+_S{RhPoplIwqR$_-`1>TtYp5r+i2a z99SHe1UYg%EX{a?P64#}D`_b7A!G7r&8dT z=vCAl(hL0{Bdl3E;vm?=?&%o66>%RUNb$}Xz{h3InKB_wMa_h`MO2&m%0F_rip(=Q z?K3z8UV+P|>lK{$3MpT!amjHSB+oXBo`@?gT@rm|fi0(z>5+fApnM-A_#bn8BOlT) zbol^%1JNPY6aAKt|0To0m`bEXTHE9Qf(R)kY$?U^guFa|)+eU%*2vtSd+A*6Ao?bH zD>bYC{$G+>*c3?y+>hfxhzI}x?f*Ne{VQgLZA=aA{tp{5qYdeUql)?6$1;&Jb8L}S zBD?iiB%W2Wqa+pB)*|~ej|ExlJkUv=E!l0#%zbAk1Wlm_0UkvGg{MPML{ub2TC@j| zUI9@Bg=YYnX8`!l`*x-$H#66o9dd&H*WUH@^^c|R_xrB*-urHLdbobyHy{89kbG>v z(W@f}+Q1QFMHu<|3HkMdvfE!xkUSIpd=q_txL*3$&u@(<<{-I=@nh2}vIJUggIe8v9Y1^N!~7u(mr69Ul-@fY9czuSZOfY*!a zpSpw6MIegMKpU{UR*FMa)rgD=T0-TK8Hfl{g{p#5qt+-ks10(3npJ4f8_0xWqgbyn zNDgX7$%$3yWXy{>V3SV*5Od5*Qn9I&7%G;J2X55dEYH9zW9A=@0ub0Kx1tu$vNnBJdrSNa>n zHtjF0v3Ln)K-(N>sl3#t6%9n4Y2$kz7?Z|%JY_~pypGhSRcF&C1>u@g%j{V}ojQHm zVggq ziHGy0+IF&Z+X!mH)&hq6nU*$G!3N%7LoU{nId8dnO~(b1ErJ5zspo?uGIjXhIS6N8 zhzim0URCgx3U>ZMo8O7QgBf{qqm_pn3-B@^^g9?F>8F=>NNOnYreS1l!deJmgANKY(xaOMqE%UwZ|U=0b|jyYeH_=*~p<_ zVKIOqp22Uw5Z;s^GB50O2+H2h&gM3VJ1w@|@@U9_%qO0>m4z!saEn0B~SQHL;ik+$wrmBlZXAp@FVPsaw%!SIBBKMYSyg=NjvP;KEsNDpVVRlzE z;FO&!@zMwp>@Yl>xu#`OZ-PRRu3Mg0P@5w(pywpCW;Zy}n4i&wcyI ziu7%%k#%gutVflzgS*(cPWg?&7C73Mtm~ZUI{;_#R>+^4xd}W>rtoUGUe_tXzYd6K z)q(FNh6D+Gn?-pBOetsc0(;U5W>e<@oasz!s_IQksuA>1MROkg7@%C70VfWfVvk2$ zvpvhEti2nNom?uDQ!c6PLmaS8~|(TE)b$MmSjZJy^G|YHMg-1qgfAqEp98nhz3#_m1vr7WulDCZDg}E5c4b5DhEizWdK`MWdm58 z$^oK>%7|G`@u5ymxe;{t^cW}OIM`X?PU3W??cakLZXljCp&McS26b zwrJ(nJwym99jUm}y@-pt4@Yi+i#R@u4la;t8qZ>B2@fnmH3qy%ts1`1y_F6c?_|4j zR_ZYh^_4B0>YVA87!eLO)Ii%Wf-5^1)wND&;_4T))Y>eE(|6Ro3F(?cCVk|oOhEJt zRP8~^D?IcnJHb=3D|a;gJsEEyBaNV(YpsXG;d45)p*%c^oH`@N8bLOB8hPnj~i-0JQKq4U{1)^FPQ77D%QLAl^NWYTLL@01xJ5$lh{YV_4k|CWa>UW?QKei{+A8@P7B+EhQ2bwd8Wd!j7GgL;GpwLMtt zI98h~%upYywL@l5&&`rhTLb)6+3|TcXiN^Pd4)pv={{y+FN>1w=pg?(XLA4-Hh--; z{2W$n6>K{t;`LBA@ob`yG}L>R&kKeJ(&;LNbum6Hgn{Ki6;x|P8y}0tXU>DRnb(Q0 zj?4A=BU5l30QuGN(rzSe>8-5>jFoGSAH#-$GsosIliLZZ9ev9iN{(^~K0=(QoDBvO zQw~Tc$(?@tE9t>oJ5phaJZd+G&qk`xda^egQbWoKzlQ!36_?hhWnh5geSmcS-8?k! z_Sbq{3UXD{`{u`KK6bYomz%=+BDj#%BTk^8r`SFpsdmf+z6@h@aQiNTRZ~|cMie_j zY^|@&6m8ag(t8m%7~DDIvp#7<#21<{Ee@Qt0VPfF$vhNw0qkZWu-YJ1#Gn-iP=KFc zo2K|$>m#jHzC=E%?F+!JB)h2titdktotlQYx++RQ@d3tL2_wi=>?E*CR}9}-OY0u6 z>5Z-X5Q`h7c{-F^MOUuITjU9e(T1U5ee$_$L#7MEque6VynF%EQpSxfZb;r(%w3l^ zzPgl~o%Px)Z6MRGi-Rnb_JAV8K9e}@OE_G}CRoiPx zK2mRRMGCkeccnn=i!ak1g4h%VkyNCEtb(|syPL6Q%TDvf= zb`*|Cx>Lq?g;Ye}k8Os`iUJJ98|ur?$A&kd9!=W7ib)yW(8*=QdWO zxY81BnpPy+xPoJMa-ks?!x?0HSJT^fC%mEWccpspsUz7zEoa}k#$W%;x;*U4^|&M4 zmP;SbEJ7Id5VJ)2cw*=Dq|q-}_%JxI=m`*~ z$BwQooj>8l%E|@RBM-1wz6p!Qj7IOr_Eh&l?q1tY(vUB?M_#;}OcDo{^@JLMFrOGj zAp?EG7`If1QHJnuMSf!(@XNi*YtT53vC|qdp5JUIx%YDmgFcr>99{JHf6+m4%Y1iJ zK86VThAHI3iuA(JomHs!dz%8M-^*1*#9f8>#!>OwUsOkhsFKtWdNvqNt$KsnE~I(>qnk7HL>iRZ~c${pp4u43{7q3_l!ITb}X5P$o%v;xWqrPmXEg zG7)L3gyfI^RdmWfkNviHj&v8ucM}e_jQQi}F^#l#;qs1)+!k(-%;OH2iFEWv2|JQ1 zL66K1==di2rIDm4D^x{MX)JlSWuDQBJJ2to#aiMj;^`u;{62ZgzJXd*ZL3fv@_3^-dr43)2>d>G!jW6K8nkro{jnNz1mEUha<*j1Q1Qa-oy%_Lr?E$q01qQj z4JTeK*z(0*;`@uizR-;Sa`xih28WvNn{WU?Uk6KfEq}iat_9KSiJHw$ZZ6^i{9= zbaHP%<2@A7geZAY{1m7@+hkSsRk0+M27gkDB6z<5eA3ynQoRZa!sJX&bGccwhv%;c zsDdz6XiAy##9N1*PVb*0G_%At>27O<=JTaY@AgiW=tckZ<( zM%xm_7DJ=u;iOp88itf_TW^l`my_eC*rYQhkC|PHp-ufRV6&nU`Hast@JpvTV~WR@ zVvqMhPAlES#G409HOmdkdAy6+i$C-61`2s$qKv{TfGc3UwUfvirEd^Ne5dOuV+jT4 z38P@L%L%1cU1MZ6I1$XXljm9eCi>35>Mhmr3{>(H864g!twz?#7~A_OHi1R6b54y% zDm}{X{tKMDke)FCKX9u2kiY+HYVBru0UmK5DuHpvxs!aCsd_T#dIOB@P;u)U3iEqy2>J-^Oz}@>qF|; zu6LqT*|EGlNVQ;2p<-vU5Ybt+T|2vZF1_P@S8EZ)kl0eh702}Y8EIT`5GrRRAIBm< z2c{+>>*R?ZjJX>1iPFv3ZKW}FYl!+q>f4ozAop;^zthDSxg`r6ZQo7E5T4l(Kf#w>)EmPqVoXY*h;BDAiE%#Eg-He#!^~E z)>(n2vWb#;^5TJc9axvegwpKrl!+!v4X7VNjB=^T-~;?G;^rs2QzJcRxKH@?ybacg z&EK5$w-MwPdVglW&5|C}DH-zlxR@?k117ipqV_=0cFNliB97n<4F|f@Y5)IZTm8?< zltR{V=l)rhpg%Mn`~QIQkgzm$GITPw@KkX!bThU2KjcU1|K{p|p{>_i72XOZsB6`r zqurvPWJR%KDibYa6Tx@WZdz=bL78YsKJmX0k>`iO|3&AUuWK<-q=q}+?sC55F{kg~ z^Z)V%R~SYH24g#82!BVylUPqmNKRlkC^Xn7gyO=xSYI_{o_^`ALs!YxYrp2+p#!dF zCQ-R>SUVu9iKDXD0z@B+o9a%_38ThrGODT}o3b59sCN;0FFA`K*2cy0=4*d1R_^8z z^PNQSKW*(P7;Z?eUb>yk{fiZ>W{3YXGxuKWL-)33Ky=0ORYg*Dv+igO=V0Qjp#s!J zHEbsn=^YO}&LR6u_298{u5<=;grh+2ASX0?V_FuQbyksXW>#cvbh-?>HEN9j|LljV zJBwNVh^(u$LY9RYHS8wW`Pxj@o|Mrac&=P>m!UBl3yH)gJ0&F{At9w9C@r=)WK46p zWLdH89;fb9&e*m6E`u8G;mB1aCiJib6*ojTx1Nu?gI*h1~bOYGb*mU`IOAM=8 zqqs4KF0uFU)!IMqTjJ=_AM=;ocLa{V`qTD1=>MgS|LJ_KjBV+I{Yfh~Km9=eO_}*$ zJB6H~t?9p!#wu5G$chMGa+EYXbSRS}R76A+H*E@t_h3Oz$}K5SVIW2_X-#RQThear zBKRZjckz+y6p`@z!kA|{X^V@YgZUer=4O5NXVWLQzxMnAWQa%&l?H(^@nj|pJjO>_ zV(fShH;pj`W&WPOhD4V$>%859|uFpJJ?Mx)~n#n}HG<)&1onPH?hmuI?X->5nb|!_{>eQms zH7~|g8$w4rkhLS``nW3hk;mC=(>NfizxQtf5D5T6s&^nC_xb zZ|fombEC~&g^ueRn?GArO2n=5jkB60us@Af%R*0w>ot$!9U!)(xZKNGBP!Kw!-(=y zX6>_4M;K&6r-sryU|kdIXsaqf_l0_MlpVwdwNF$)80rX8+)iyMBZ!FzDG73oVXjEG zm%q$fvRQM7e{30IaGPi|uz>snj_-8a!|B+^k079C!5(T632rg;w)g|)iE4=p?n!vDCH6w7L+%+Y$88}B z?JIoAxc-df?g73((V2b7+0gFFmlBr z$Z#`bVeY)bp1K9w`LutteksTYDTV$*;a338XDA%J+y)ouCEUlWfCWCNvOj0j z2C>fQ*#zvbW;p)&hglU#2n5 z`1tmA0dw{hg7FCwMY@H2LsrFtu zhc-cP9|lN;$-1+$tQlUZ+AJAEtb43=VYy|eIvKNqxE8W@m_&vgI<)1p`v!1tnNiR# z;ym)2F5w8Q7X`Y=Q5H!gq%uNo zGdLJ9t)nWoM@FPP^Pr-uZ`moJKm!89qD=`1rsP z0~3YK4=Vb2TpTV!`7}vz&@z*&;?oIiHNzkVR(J5TRCKDsRtQTJM4>|mW1{*cK~LRC zlb9%o9nENpfckc>g@FkokoD+{^k?zuGr37AS$Z7<69Y2?Lm(hAG%+wU5Omnc05nMk z#^yhrLjDQOXd9BrxSz0;`q4bF{0~kc3QnfZ|IEkzx6GfiXTPX`GWM&TflJCY_+U8F zdFi5nVSSt4b;>9w3u8l!N!aL6+7PuHMQXEY_*1ygiiqxQzZm{Yan#v9Q4lPqH^=+- z?-S?Q_SVJ(o>>P))I%(-DM{0zzaSodxwnU`hO zSg%%gVG3=V?Yy{Q?5sQ>iIc_LWYRH$x}OsV7!(<mjQD+2{OjV?_J;00F&QNTG=5A_Ju|8~!DX+o>hd=#8=wL&AZfj5ib!AEaB8*a)%_6e~zt^Vpc%u9V`;z2xbqF3@;ZrpKuB3W6>~dIAs@dwgrFf zfW#3W+Qi(0-~<1^+L?2n)NtbbOm3Ih{GVNz{;kb(sT z3JeVaQaYg{NwA4vyn(xakj&j2GK$jx2oyzh8j`n}NRam_#=MLB>2Y~UdCuc9bJoEt z?Au#)g>{FSmzjHt$mjdB?&m99{Nq*zN*$6Gmt68=x2+0Kn*A>tJmQM(CjHBR0t+Y~br?ZHV*; z9VGp9BmJc|)gyF&hI}!sUY%4f*`jq34Yn9PxwkIEqb0f*=jx39(73q*{9XfDZ_PN+ zns%Ty>wpVhGrZ%X8NLF(26HPOv1?kN@oNj-K?<0vMSIW9-x;-QU&r-x`*FfGa)008 zz1{`T`Q5xO$KQ>AzZd`Nu4&Ug^8C7?_Z%>S_t+f1eoOn@kk31a2it!FkLEo+hi5MT zx}FT!!Ef4F{&^jLjTy}w{c=Y0%(JTx(SIV3_Rb9U6%>e0`;7F@zik@*xiY6`SP!=U zz#iRuYF=-=?+Vj%VD4{j|MMzs%`?2|D{T;Bw$Dk1&_?q~+apVit zAbeIsbFeuayI`L7!tJIuIRgKPMY-HzwP!;}vLoP#^8(h!j9IIvZ`S$pc|%hIW^z zU)v}ytp`=_!z1u~)o(Y%$@19s2Hfk9fd~2`}v~b-%Nxee{_i2J_j2Pc*tl&-|e;jh@MUAKLBN+2=+k8vo!S z@W+P)-~3@P4d41)I6;t64?JwYX~synwogbtJ}FIHe2Bh}3P2DxE#Kzc*j=N?#OPE9 z0RB+hp=oh`x`7ZRS<25BKNj8V{3}3yKifd4e9LPIKz>Z%giq8+`P%{CPuSlBO^m(% zh2dK|Y`){$nmaQvpxZrT6!Hr#;#fWW^XUUPiXZ;6fuh{^3IjmUiIl2|#z^*9T;*cGx>ON6n}Z`eMajFQ~-Yvw29q-@AI~>W6pogr*<* zqQ$QtdsrvtsQ$+hP5lz{8LPj$zv1&Mjn_XpQh$GC<@2kJ*FQU2dw+%H z^DB>G;PD`DISxZ~5 z#g>wEYFt%)S#(f!p5q|u8-i3^7MJA4WbWy@;4+RDI-Tf1YBEbzPZg~qI<)X`NhNg- zB9#S8T~8GsR}gaYoF@#4udE9uq9sRHA0<;;uY**Xi>jxDD7d>)dJx5Vu;~O-ErF-2 z2e<7dUsqYHr-olgOHEY^v9>}>TOWZ^OI1%DueOF3JAe^Lqy!BCH}Mn_*3)cdgqYHT z22uumu<1}rASC&sLoYYW6Qs~E`lPbf0>80MmQG&@yH+PVF_S6oU`;5ZjYSt*amMAv z3uZ~42N5Gf6UZ9SI5;weTpW!`Y706F*>9^^vP$PFMdme_^3kItwUR9Am=eNZM#%>b zrhqqB#z3s4RlK4)WyBI^N25ZHsX2^FH|PoLk0ql?KwVh@CvJ=~%8r&59oN6=QS@YvErir@%;gxa> z@u*C+aI#{0G^A=ON1U~)ai@0-^4yl17xQK=2m45H<>OgWRKwQ9B4(phTA5FEhUb4ZDS{@7 zx!C9pzHr7Sc)MRj>>aMeezDve{O&2m#o@wfZ5vyxC9}b9$`uKjV@t)G@i>!$#Nh*U zzwBUYqN0k^S{WO9EhuX+TlZkJL~pF+xLaOPni3;@>svNX5Ye%%EXtPZO@-eSt0XGL zs;tx`??HlUnZ#;07+&rV)8lFy$sxAxP9s4I7fq6b741PY>n*RTMVHPc3MOu;+A&_{ zw7gSVN~D~wCVbB!T|Fqft}Og}?E1^zZDq3Raz(YcXrF<$GG2_yK4|EfVuk0TAG;j zE+g2gOinqb5S()ZWYzQj{xMStx%nL{ldY|1Rgi8ej5{wmIqTZylBdI?ZHrQJ0YDlr7iHvM?I zv*emOeYq7g+R0j$fRR_`s;FPX>v}jO-AE2Y3uQeIM`z$Es-<(%mf842932*lW!tso zAzMyBtP8(nE;w9FQXXJ|=VHI`e=K_z9_XP~(&}sJQK2zMAu&u+26l;@6ThT3>^N;u z8ZizJ?5_r^vfC913Eo^KK`_=yYOKS_ZaXCf&piXz)|kwf=&K~6cwqgapwyHSvN9#{ z@QqQACu*luh7!! zrBAlTJ3cn>h(yn42{xoRdKLa@07`f}$X_b{c452SDcNOERdkxpL~Eiwwu2d+A^;K#(>D!ZPbN}u0?11jVVki4RK z61wID%#X|AZ9&(2o?bawSUjOCQpW?ax*H{9LDW#x*JPIc8DV09M93pv2fGijidw8M z9@%IBL^?BNvSs3YQzK@-LT$e0ao2ZApkRRHAQX&Cl|=ZGvt$FIxvhd3CN`1>v78*z zq}lZ<5O1vOaa>|J49hrEQkWe;dn$AHeJXBMEj^D|a@+;1az|NKlLJt??P@nY^c-5y zOATmTt}2Q$VGS?Ey8e0`7S4r!D07CDd;F*tA)&h?XbVjjV3i(M&jlfk?koJ~MVd(1ce76m1GE8q$-L1^tDEjTS=kQh+moQj027 zR>D@*qQr8QJt?WMr1S_DO!A6dV|HBO5`*i4Bb{>|&XR@loaf}OuuClI4OXq42}MT` zS?RrqZ8k8L*eLy}g_N48bRoF4#`xSsQ=NO>Ok)*J$!#YOs`g_*tKHV7$xhv}1as9^ zc61kkp&Lpciw0gjB_D$_nZ%y!JVYLV(j8=(+-S~0T!6^Xd#{k&)YCJ!xksJHZFMmI$uo3_3wl@|^emStx=8$ug(J zGHPu^q^LepH1b6@d#xj|1aqmIa`S1o6^r&l$EiP>4)15uHfp2-ufCq7=y=^KWb|Fq z?g@D6IUAj3H1ad9#JHs!sW)ck}IvX!m(PYTD6*R(6{y_md=>bv62l)|la`tkGN9xt-m9 zJtbXj%(}apPx$Mz(pTSQbEV^l(1y|p(Cl@WnxCd6%_-|@^`GHN+s+Qw^mq+AUh!lR zj8^%OV`yl)+TzAEyZrOB8cUX}kulG2CP<(r+cRXw#_X}igFlN(4$l7TThTGcMyQom z`UrHk!#9T9THU6T<2T9Y>NmdbC^R{C;3Y^RvmFQ$#MKTaM2DNEuW8BT$U*Nnztj_& zVqX)YEYa73?C`K&XBwP}OJ|ASK;R=`uEH^q>oO?a%!ezJ)U%#Ye3^reD9DPC<-#|9 zvDE4zJ0NZ;UFYXQar{qL1Q{zK^Sc0%H+g!LI{1NU*C*G`u~2aSeGoA`3)K@y)+uU& zONudl?3%ilwb4}Iq6m}3Gxym9K>V&d+;hqahR?3-=OC~d#=XX|im4^huy3K|OA=#< z-Daj-8++#KZh%QXnjBEu0i6cYWgBixRV{2iuf#P0V025c!#}^4lw|hYBq!~=e5-gP zon5b~0GeZAzh_Zo%qE!IEgnYEyb1QJTIm`vkT0D{)D%lSloQ~Y7`rN2Osn4Rq`25c z&`JR@I!g}73K^*e7JVnc#{We-ZeNZLdSTWDORpW|LfjjX^wUo9jVUJbN4}a(Qh&%YhuWxG19sDm|A3AfI`iQwtz->?vRA^YZ zNj;OZ%nTj&q@!w+poza-rVzOOTaZ)kr-3Of8CdeFa9AN7J?Q2wab%q48xp=htKdqE$p zUtH^hLKU`z+i1a!_6FB`ipT7fjY3Az2&2D3@4x$B+ZBVI=po5^f+25>2KgBUvvA0I z(2sBbz$dWb(MB@j8^LHO+$LOYkIn;qu8K+Itso$o&jnTReJLjR$Ap^EfZTjTpL~V* zL)n^+d-@q!3`lth9e>k|f5&$6jfFP}J$HtVe?=2~BPI6GZ=6cgpD+z;v@|1Uk?7qtppr1)$d8Dl28%pr5-983SA@Fh*P z#;QWyoQYsEG0bLmQeNSLqo~r^v`z9;rrEp=7#FK=8R!!c$<{B9CEDlAuL8_|AWQo* z3hH`S({ZRQ!D$B%iJo1e8P22-%RdDhK$&eU+KP*uCGyXWwPTVUtY~)EuQ?i6mxB2U zM=^Hji{bqp6s?e18xV~@h<&TB`*$+6!e-qtD9f875cX!}iljXYHUm#OMPvfA@}qEP z3~_sp6>LCWxZhjAt9sML5L&pg!Izd0gaC7ZQ;vB94Dt{(5-GLPbm=JY(^$A6K9v!W zgo(LYaG60A1A!7c0tH80L`A@}cPlQ^#`#?{Acfy&?lAhpHc zTnrve7w%Poe}>NbydNN*226RB^gzH4MUltHWC5Qn2UlFAF4^UQsYHhtW-PCoH4P39 zK1FE82;7uUQ7`od%Sms9glW0);zyf|HH`?w3)>D?RyrK$RRj@NNXiG0t(Z-YnB$?c zh+`2Cto0<2c-ppTY01dOQKEoiG*U_;9;?l8<gKfa7!ao7XYG3%3g#S3GA% z2b&Rp7D;*bMX)&5U%hxZ1}|b-rfw%&Os04kD{{(b53}+aXAdJF0DkjAhEUG(!WQMLn}R zuu!5JQaJj?!eA}KI`}m5RB~TyGP7KvuHo?jXtt}sv&j?c72!wX@1;q4`?4ScUrhwwWGaUt=e3P%oMha4@o9;bO^hT}TXQz#Y|>;Cv6(M2q@wGoe-M z`P5LD+#I)*gsaU0Puyp)8)2j4+>8S+mTv5zM#rz{M9vje#sU%$A#Ut|?`Vbjn!2 zL9u1ceZs5>vU2pA7fMc9lT;o|QDwbkj7wVAR9$BVAE3J=7U@?&sYhH0ZUk)2{n>`>B@eJi0xmc$>_?1Hi;u5q zWNZnJ(PJ?V+7LHO%7f^7Q>~aF~{wryo+qF>h0xEm^H2q4b*rv&7Obsk)`t zDPvqTw$k0xf0uDJo_7UoAC<1sAjCy_r%UF|q&!PWmNhEBdOy~iefx6b%PCb+aLRE! zssfM{VFr$kY&NxB7sPBzhURVbc&>1obM*CRbuBq(RTs=AsGwr|Q1{dtF}k)H$@5uq zpL@{Zju+p-pR+poqC&&-pSKizctWG7GqF^VFCC@e+)ftSzIf*=g_r6oovedznvpk! zg4Ew?D)@0e$4rZEotwgc_;^V1Fd)jh8CEg7I=S-nr;$RS5ey=&gg7lF!uZamEZ{(+ zjI(7KdA$|-+xV$`qmYk6ZI@RoAa&C9>voymmC?%&v{KslyCXTarL}s^Y;*a=-A7qO z)Gea^#`;Ezm1OOYY%W+UjjuBAc}`mVfxYHl{SSGhgk4D$D?>GwSEK6dk6S#CR>D#d z0*@v*MEy`%-uUj+vbX-HQeA9GHQPiViAsjPoZ5d9>OiXo2>3^j`e~a{qyq2Z*FrXe z()cDK;XJ>vE}?5_>lu5;&$abgz<~hpXT7pWTr^vf;S=mRsqom~dM+5}@|ccT_nO@E zar_-JVY{@iz%f5+<0VfLH6DGq!@kuc(;~+IP+dh!F!HLPhC*+JSd3_7OqPqJMRId5 zGCKYbGa9QGx9}UH>mnGH*zlisvi<1cKJg+glzJ+3`O#0p1T{9)2sM$na+0LucYIov zrLvtOxJKo}!;}l#l1vKbiQ}Molgr4&WBqT5Vy^gGrh?0Bi&Cz7OZ>B0kz0D4me{|& zM3RWowx^VQHuGJ5`Zln0&q~IOZk)?E@jL02WYky&7kT*P=PG-9j#g;rVmL)?nlwO4 zi+bfF8yhjBen7OTmiF5Y}@F1TricYcd~RZv2TIw`iI_%7(issCAGN-dt&_CaG9y@Gx^A8R_#4@waTN)6`4OXTm zS^)>*3Zg?=v~_K9CAEy*c9^#ync!(vkh)9_Z_#JvpwVM=!_(&EhLfTlo@s-Ym9aS= zwioWxo!@Ni>}QJ@k!|#6zp(k0P&iIY%E^rnYcBT1647qKsW$ zeQciC9z9A*$xLM}#r&Xihv=2HtHDc}Zs8Kl9$wB7zr8z3gzHzDOe$N691ofc=CP3{ zp55L|{_AFKH6=R9c5DihiIv0hY!*A)$^LF%(di~28s4qMI`Sw%qvs}KO9rkI%xG8A zX+81}$UUXr|3}$72Uo&v>)x^L72CFLqhqUM+qRvKI<{>)>A2&LZ5v@dMyxIF$lmKj6-5OJAd4n390N!g_! z7XTj;m*5l+;w7D7PFdJEzhG^_Z}_PKJ_2XQ9hG*Ps7W`sQzSY}56;^Vx@@R)HlSxE zi*%VE@tn=vi!?7VRcY@d{l-PC@?MhZYraBUvW0@IYV&0HaJEM#Dm@L&2pA$FgSISX zsyb%GA4ZmfrUZM_cB;_Au2zvFIJD5m>Q2|kdJr! zl2P)~matl6u9IY5s@9;WX8Sn08}*Nzyx9A(DK&Z-`oL0*0jpTPh%lP6*V<>aI4ytm z=ejbAtHi8Uvc=>eMVnexWXFiXGzNi%E8Pp!~ngIIs!nxe4lPB}0ee#ar&xiZ>9r+<8LY2!^8NcBu z4LU`$k-@u+vItT>!eTBYw_nVn*_k!CJlPCh7|%5+`Z?UD$JpoS zQ4nPUYzIEN<$~O{igr}GVJ?lW6A7HJ&GLiq@h)aMENqXZ9r2Q=~vq9$&6fjO%M&^n0wqYXRomkcr9BhtF+3}+pACpAc#@ExImtFe zU+71io;X7o&)jmcd9tAVB+lrXoQB@Vd+ zL$d{$iuQ=|c`|!?eUix~kEW@&j|1F=j6U$#!BhB#!s=Q;Y&OI043x^UqJov zvJh-b6us0Xt&!`NiF@|wkQ5UB5dP5<=k}2w{N`i&;k)ttO0g#(d_b_3{W%)^25R~t zwDAnN_G}E{K`|C)1+Wk&E~L?vzS+`~Oil1L;rbyuJ|>8tg`5SPqaNXOH_gA^a!wL;)%eOvLPy8(2_WRoV^F<$-tF# zL2Nd!KFW3HQlIk?lqK^iHB~^62n&~_WBxP-Q2@ST-bjQAI3FY5m8@UE5^lyK86_Jw zcPvv9ZXTwNc4*W!+*(q-vs5yy&RZIXF^&#{8OYPq`%&Hxmk_FyRo@RMXE{HhymH6L zkcnSxb z3sVEG-5G05$`KDaif{wAypy@7cEdI3Bjzj7P1ce?Fp9?-wl39?)M3Hj7KV}V+RJ@e zI1>M7X74h9eiyhl3-Z|YCcZY8x1UHqTu-8gBHEQ0^ca2yfMw3mtlC$D)8{!`Zd=Ur zZC($SJp|spy14|zRKa*#xi%_Vgh{3`oe6p^mo0Im&-EwapY4q(UaI(DQocV=hjZFM zsOUYmMLh!-;Tz(13KO5^V}5V+%tYXyW&xj0y`P#}pWa#@Zh}=}A8xZ9^EW>!pA}Zc z$V;|9iLd;ipL(F)^yMc$@y(gyKYg6dv_4cwKg&8s8`0kMK|g9hKbQPJaV(xU5v$N| zHsu~EKU^aHF2O$L69kqYnXn`gwru7CIz>Et`O-R1fo8NpkE($0ioK3OL3)Gk@)}{% ziO?BY*gg@3fC&OX_`$%vv($ilN)TZ`;$|e!KX1`K^Pu0%h(5DT*wy^GE^;9A4-d}C zZn65BsUXVun6_W+{BOYTg!Kb&@6oBq^?3~7f7gauYKR;Y92tWw?%qW-*2bpP9(WCC z#p5nM0-Zwo-;?yd5cIxK(N$6$tAH%d-^IZ!#=tB_gK3NyHb4PkT#!Ysk)~(D&CCZ`j#%zA1D?2EytM|4 zVB|DGb|k+RC=w))0|p@i$j*U3Cs4R{q1YS9dy?Rr*-Khucp5e91PT&^f?#JSaCif- zgSOy00#Xa);EI2%h}Iy(TpHL;+OhsTJMn%wvSva(%KTIzC|~lOzZX3ptqsWyjE^eN z6OIoZoqr09pqM4lA0RZesNv$J6Rz(u*Qe^l-yMWV(@Qvb2N>Kq}XyXqjR3vDLI&mVdKIn?Y zHJi#LI(gPIr|^itbi(?ug^~Jw&?VK2#Zs){=wJlG>|?>1eZqJLpf4IMT;7lg0-p5v zvAwdGL_F#dqkT_U;2Iyw`kB&}UYzUEwoX-;Q%Xa0&j$D-&ixg>kN)wt8P=xJ$Nh$< zMwO_3!G)Dd`PSgx2UGMCV^A&`)HxAF(YFDpIg|x^)>1Ip=)<9j={ua!hXm(vNuvanXhEZN5HJA1Q98gFZ78($ zAhh)`wDs7u^?%<(K=@N|77B>S_=P&wUoZ6>9}2%P9HmLWd{SHSQZ%vUY$tzACeQs$ z87GZm3L>P0YLlHSkgo=TuLOp#1c$E#fzJZN)_}z3{E^&;)S8$hZh3snD9ay`1>#UL z5dUQDSu6s3Xik?^&}5JB9_dThct!9cw|ekmO?JzLrSY?|ts4n@6n;iWAL`fraO1E0 zmOCEcEw7i&uWg%h#UYtINBD_-cbKtQOT3;x(N8_`7vM*do8C zbHMx+k__(v%!&M`KwQ#6xJ5#-%x~g?{*%msFnh${^-dt8GJNI9>5#>K5FZTO?k29R=d`}_6mKaw>~=_CGyNFl5yuC z?8Mo>%)EO1b@LcISS@sNhw`%W+~ei{EpQ3>6k=92%P{_ z)t>lUk0VLu0@nGcm_d?upJX*7Hy2vHE{#ct+Nf(){JFRti2^0*CZ*!O3mGM#1UeEG z%@I?_@k!p%Eq{-TwHD65L^5n=Rus+eO1KVAu@VT423QO{w^TODC`*Z05f`33zPiOzwmCSC!bYz43^>mUXoI-r7dd9~67a`Du*YxA_6lABJb>P8h%I?Ydo!R` z78W3mp>*nAInWAObzeVO+8(pct1Q@kH{j&W5Jg{{+&A`Ox*p?bK>piz;jXWLWm^WkxPF2wZ8vNc{XB#LIvs1AbYs{Z1(Sa|w z64#ZCB>gq#1iV!V%?|CtW~33V&RAj-rhSn=*sXcjSO^9Bll_$W18u=nL9YEpfTrD@J9-#?6s5Rq#B zw}oYB91&l-K&gVFDrh@{1bwide*Q#%qqT!H;2vuNaOATOo~*EdWINBLU(U513=$8v zMJYyNO%-l113BCmZ`<+C+rd@N(rNJ<^n7b2GmFAzA_X8*swg*?hJbam3g&kZETn^+3eHr%x=O0v20qGaC>_pyR-Ygc#fw>zSD&Epuz6COK1@kC7A7{o4W{n*pDBXg=` zGkUK6Qjit8M3Lbr7aIcU^804ZQ=5jxweM9ezqIT!V=N0G?iO<@2O1)UUMKRTm!Lft z!iDXKUAXWZgWeOXq|+|BoS%IiSUPy?i>Dc0Ot~em`v?HLpJU34M(5JqFhTvBXm|l;e5`Xu? zSrm9f7FfV=`hw3JYrrx`G!Z*#;)H2)C`@qw*P7-W)1X*yPl{1-=IIstLl-_~Kn>u> z4Eb)CVSX!CFNKsUa-(S`!K0Xajb_dZj;#Y&|w8#^-!Pnhbpz-T#3QRFgq@(h<)e=K^!hKMdOp+YGwb4Cj!tcP*JZ ztPuQ-pb@x~cGF<8Me1Hl5~9HuA^o@*!a7}qb&_b<(>@*Pz+?Cs=73JRhGf3~ZAzqO z^YEM$m+6y3uMJeFZ76r$aF3FGJ;1Y2oKLv`zf37^p;W?hfg}dDw@YLJCpre^o&@H; zv9Z+eO7Oiv@V!TOuS8>g+7=eM8U_bmIN2X*S13Hfgg8^SxSk5Zu-M|C7XTB032Vp> z$V_3RA>{aaC8*H@RQZ(uQ|!&UIjF`7viuiE?lT1IrvCvBV>4D7RCiin$;r^8I%4;2 zz-6G%o)^Gb4wzvM00+%5W~n$O0idEh zQ4T<#FBB!xwqcjIc*f`dJCRrI5Gb`KVBgB%8C#)j zy(zpim-@@TC+7a+E+FW+_iT{F#$Vnd2{Y<>4xg;NJ zA^xx~3TEopLs3CYv&#bd3l>+H;m4q7so_VOI8)mkwP5`h5;U~$NM}YH^JInzn0h?tp=7QCgdM=i>Fl{N*~D*cujMLl$zz%$%c( zplnSxQg4GGbzt?M3kOlykn#GI2um=Z6mbAZS^B0l(L_l$u^C36C#*zrjmKMZ6`uib zCQhv%$aj5rlY9bUzcBSci#hO*AbA7MnDD_=%*!(zx6fArqAmR-Aj~vaqZ3z$?S%s7 z2?OSd0`@`zbq5D^hx=nFCoEtB)&%(#RkQy?IJF^765Q#6ym~=c&60>F<}d~`INp!> zqq5{E9TzZ&^oTK^#;UM*Zk@p}0PZOZ*bMCko?6e0rDD2th}eti`7r9FEFRQj)>ETw zuApkSfTo18LGv+b{c^4BN_}du=)o&2m|E8-lMa`{dw1)bc?HQ@ zwtV|FJJyy;$u>h`oeOI6Bsr^ykQ^W+HEqEZP$< zOt^+6N`Ou9^@;-LQ#t%Xb)X`VQ*?_6&y)naj9A>GQgXYL8d6- zk=z0j)9hd%Q=){UO%PKRcina!()&Z|FEhwaguf;_>nN+7Hzt*UFCKbRjZiqiI%kM|%oyXGF3v4Wg7@9q%$p(pW9dnV zs7jqq=Mrmxn1-AVHe* zBPM~o=T(B@bXZcIHymJkB=Ltg?vDu>-15hq+T z?W1Hv*Tfb~VVw%d$U2g^|$=FDA}Z^@{7Ta#KMThGx)3C7JZ4#cxc3JUk%cwQEyB z9BCG{gt|3_=%s=?m4&PAg{tqqnuqBXos8-r2iUzj(CJpdPI#qUFuEFDpbc)A-;L=F zZ8X>o*snS^VQ!I<1Gd0=>v$~K^t}bDV(l;&6MzI(uGu^IfDN|Po4Ur5J>t3WMzgl1 ziuq3Cuavz%Y;RJ$w7yy2>>eT|)lm5Q>Yd@~A1)B`fa&i-W^iR3K*vL7mf2dnAMygZ z@r|V>;Zd9s3q+);3JlqITb+n#-9h+!BU`{e#(J}GW!cRRKnCF&^}tEDTRi+>eSL^+ z04YUU5+?63x9QZPC*k*P6QN60laW}In&rf{=;!0{W2h?FvtZ3XLYSk?T->Z0V;dNG zRz>JCu`*bxWZ^*zs2u=1rvLm0xcpx*0~B2|Rnf08Lg+7;0n7hlj8M(g(aFNj_MfH* zRkZ(tj(&uKH_x2M5Ze@KmHqBlUS6C?D%O*fm6T$u+pa4;Rx z;dH&sQ9;tr9_v9Ml0Aqmn>hVA#@<`|L47jSZgD9wvaiDW^a>rXiwy zav|T(8eQqO_3^pKdY210lSRpeY)uqdOs(C~Lw`tRV}Bv}Tk3!|e8u|B zdFVMn(m*a!7t|@8qn2=p_zPnIa3{@Plbk1MoxNwIjZNQJls|8uuJ!pfVKh_k2#=$Z zI*D}3dkoPyD)>RPipPo_N}i{m8b3fOcN>qO!W&?kD0PD{x+FO==}g?{1boiJMYK)~ zpnyL!3gx$qtn?BhR;z`fltE!Ml{$(C(Zd1a*$b1R_yrsM%NY^bsVl5h^GJxmp%96v zP2mRv)IQmESN@_N4L?gM!3|lMw-lSQq-LUKflB*N;9Dj!6WSz!k!X+DQT0lM$s>-* zgt=P*Bv`|R;ZE!-*+z8iTgBNDka!{=h|^XPG&r|9rd-c*Bp~*{$Z~|ZVZvpkKxB7u zA?xzD*MFVc6-0rq2I`O!*sKLkWowlagjlY_%$dnp&*FyNTBF zRkR8*Mx0p57{0ih&VIod-;w=lRgB98y5Aliu`nSOcsiJ8UC^&pF-;ql|; z{T$N&b$J$fzy^=|Vvuq*{=gRQG5&Y_JhGTCGB_HWwdL}hq7h?8^`Fz%hq*lPQH;#C>qKDP9OSkS2FeNB;v6& z)oGf3l!v+#8rDsi`B8YjbfD(znuP}<%v6xy}lCl98avnSZ+2XhIWU-HL( zay#0M^`t2$o-)=37qX@TgF1kwCCn(YA1Mz?)vl&ndD&E)Ja_&Iq19cy>g^S=X0d)> zvNO=&2K8Ry+>!f9 zV(1Ap4Mz}HNjAfqh<>O%VasrPL#OajK&jN3V8|IgmA7c*1KQI|s|`#}y8nb^If7DW zs1<4k{k;s+{th$-3*c!tg%#bV)W>`~qubKnDdny|ZeGMfnP7{pIgOG%{yf}Zx*>dIkoQddt50%k!V%fv(-~Qq^N~9Rs-x4CL8}vjsS-&yK zbid1W$Y(-?)o+vj$tYN{@Gu#X);my^=|3BZ{J_euKpkdB3h6X4!aTH4_5uq8eZ@_i z34%@UL7YYkwBv&K2Uz`I!3HWgl9N6_&rFL3{xykKW*>}cw2`nM5!Q9C!=f9Bj| zCr$t5IyurakFnTH(^wiV*hii0s;wzhNKPCo7@kp1Y9zvnUp%3aM%!WHrkxT*@d>R! zuE&{4D2|BB_cZcEQECSnyogr%z2Ww@>+yXulVj7*_YXK@01i_rRt#~hES&Ku^{80c z(#~iBQl+93_zESP79%w!mU=Et>v%3U#$#vw@sI9Z<~?bgYLzMnH`O$pX*rpr`z~Fd z?!G&6k;7<<%nw=-qP1rA>Pe&@Zff8nZexu@L93o(trML_v(gGF-E(1g_97oz4K}xja_Y0ktgCw8ZV+%0`X)GJC2X{b@5++t=yE+sa4L#HLHow#kPbL^*w$w zk0gnsd-zmG3+x9gl5*Uv9YuFrH3S2C-?6ZwORJ1o& zd%gMuk;bb33NXA{$rftQE;(}reQb7A4&yh)7<@>l)p;T%(SFliaFH(kGwC^WliS_6 zIiXm+EO49kolgk+cqr5&OHjEQC<mhwdtnTN0nK(4ET? z++x^#e>#G(<6(o7hesI(1V}7mbPfjycZ&hFFoknPEB_n;G5nK9(@oLGns`Q53426w z29^SZ9uQ22-;0sZA0Lc2JcLnOf?!y1-Z%Uas!O~)LaI+*iVor~TuTG?8g0PUhy4kZ zIZOuarD+-c2JzpVoWDw)H_n<~x-U+S95fKn*I+r2y`!C(i=m?lgYjRMIo~a;O&R`^ zs3vOX{5LiK?Z-cz<6kL%l;;J%JXzM}LX!m(B0;EyRcXP?yrC9|HDFR=f6w*_*>yr$ zP@g6jClyCuVNAL2rgR6glonv}`y=kV*W1kP1jjkYG%l9dj<5p89xbQnOIP7l|iwS&BPXuQHkm<`&;Rj;8Zune0ndoxgc(hHA zTux?xOvGETAR}br$P>C*R&On@bRO0Ic9X!xS@POl=d9umEYs$p=9>)_5HX)G{gIKg z|A5YTd+Ua!k zad%a!*_ph&*O7w4;Mlb_C6@zoB5Dcj>eGdBOg`V`fdg8dCh+}oQuZ~4))w8YF}J5+ zz(*&WQOC8IpCx+EbA|bFKBHK@6e5vnTEzpqwUnY}(lZTFq^AtiMTNo2Q%K|Fnn~JE z48R{e1I`WPx-uicBDl#1HQ$lusagM83P02nG(^$e{}|%QuaoPB_;#l!2#Fy@AqCT0 z^kOY)kBp?>Or7m^msC~#oRLGwS4o9VidsucntCd(9>^RHY*;ck5)UPq#$O$I1-HZ~ z3-z$%5)JjHB#M*AKZ6^wdStML^zm%qSKD%lD!d@dPr_>$2eBi7bXPDoN3p=XmqvDk zTec6rB(6KQAK9*>lty#nD5hIYX}d-4AZ1d3O10>TQwOmP!{=LL!iy;+fgN=xJf6SRN^58a*CxL>0cY^tu|8e+QMmy9G2b=mQ+Rb7vFR9MAV zN-_K*mhk?Y^XFk}Xk%flZ0hXdXlrWne;&i^Z<}991?i(17ne@rnT$FRCUQBod87se z16&UN%gb0i9@2-qT1J!aBI7g#>;qN*&W=$?jKF=bPhgz0g%2@EBB=0qeQIj*@z>{UJdmt0RRHJ3$ZW(lC%yr((2gMpRiRJ9aX)E2wIlTnwKK%8#%NC;nT3$UR=8uw zUoPeF164@LTpcNjs+j?`IsCA8Mv8_R147sYip zv+{l`Oz>6{_8~QpnUO6tCvZ_!lsN>;!#Rxl4mDpWEJyljz2k>Teo8LaKP=X9d1ybF zhVby|#WW`gl|Mm=U@bV_fkL%0gP5E%h)xIhbDjeblUE=angl@M~wWluIV^@!j%$q9lV+6#1^33D@6;_|o+Sqh7*Xdpeu=C(m=Z zv+E5_vT-9p!7ga1QyXd#v&y&7WEIk|W-YqOM!3ZgCRJlmt7vl^n{a{( zL-$3CV*i1eg$vm?)OP3H(3ps(S+N%K55&(<&rN?xbc;XhZkz9%huyauuP^Vn{QkGC zNJ3bL{hXm(hRn#!E0n}D!LwqndVPU`Ss+0~!!2}rk1(+-=2s8{gGokzs;W5TT8uP^ zpB7wOg^shc$sm3srksVI|JDh$?pdvJU8KBAR<=5-*KO*mfNNm}rHqA3r(*(xX@W5e z$2_O*Sz4!ca{EQggC>P$m3o{kyM*y7&$z|caP0pqgvQ}Dq|uBQ7d0#Kc1PXRc2NA& zB>mUjz;V^J#J5w(_U{NbFGFgL6V=DvSfh*D^WU8iobOF}W(IQ?bT_tC;|%K=Bwn@Z z;{buKP5mu^Wt$s1bUmNqB3)If{n^cBV6nMVMp1NBZR_5T@tF zp+n%IqM#W0zW72rfN6oE#TlocL7n3(g~(dztbxwo=}NA?(eFK?p;YD53AzSY#}dK^ zj*>_v9J}Jg8lzqD2@QBFAW7{dDdT0JugWx%v-uzfaD-bB5T5=-O1{dp91ZJ~Y|zht zPgG!8v^||8P3V^bG2MYc07iU=_l@bTng19T=$%g|Rg}_khI})XAj}plVt^W_dzRLE zdbLYHvGP>v1ap|Aie>K>RRF z8(`9e{_eGAyg5z>?!z1{>PtY~M(nVVKfMwL)8LAk)29qV<8PeNut02(=QdSyC%K8Z zIP}RlO?A_PKO$lFrjKgL2L$pDoC+0ZbFM0gzdfuYaDUflgO*7tP~;#+Ueuk&{B@9X zQ{+{dF@7}jhx2+bL5Z7kEuWbd*%Ny%SsSI5I*M{|4Dp9{Uk-WJFP8$k*PXk@h4b&) z89us~o@CL`s&ve7U;L9+fv$wLyb_a+q#J9O{=tdy)`GA)r2ah`YG|JgW2)exM<}z_ zv$I8G`W_cFPe+v%rdZzW*_!}P43E29jyP84;1D;sbVh^iYKFkj*9uoczMR|D zijy2A&6MA2NGxw&c=op*WR|ZPpPsSnd$rf;*R}_H{JwNFnSRwTWnJIu2p8Qx{|?pQmOkAT-uJL#!253+yrXp^UgH zhm3)-vN5*DoqTH46#)- zzD+1&sN1_hl-U0obV22i{RRzwEa8yeS_k)5YHIWRo=ZXkfF#OW z!4K|p-3jJfyU(ILkx^Kd#|^8`9PHm9cv*>~0ONpGK`dn0l?ZOKJQYCs%?)Nuas(~h zP3LpXx^fzM)i!^>tZWTgz3Y;tNbO_7x`PKmzEA*phmQnjIF8t;#m$_H3L(~Ch&2v| zs;Nj)wsoKC>l;+&L%x=u;VF(hF+bgGGWH&MIvO|836ZD#`~h$?Qa~m87Hc3i+Sa2? z#QG7!85VVIiHFMXiy{1=86RA|g}`_>m+;=!c6!Ex;aIAfF22|gM~mtLJ7KPoJ_6|f zlk||oSW>^1vun4e{YQ8ECVHLc`kt(?qFmv=rv|()arVVvOUljpXGPVj4DHRgOv0Qa zw8)cX-Ul%k#|;(hX~WbdUMmI-h1;AOKcL?*d0a_i{z*(|Q%^8OxL0vX!rzL}FpFo95e_WZ?^Dju{@%8>3+Ar~Of2C5v z|E2gO4Q)-n=!_zEwocB5w$A@_wafmd`&XlaZ{D?|S(jFg2JH%`sc|$i0)jR%9zrYMAZG3;OS(Vu@CESee7trmc}{7(g#DcgQ<0|skX<9$(l_8Ul5I9 zWfX^Xsovf{U>DoIFo=wHJ9!ZjJ(~6_x)2_5n(aM0x@dGq zE<9GkbU8YBvDA#hYoruTTtZXcG@xMFLNzqma8XoKa&C*A6y4tN^xP~cR8#{y*e)h| z`Ts;87hAJb!WW#@S^FZ%%gF58IMr-(e|Y@)G1GLZe(j1rP?E=$tn2HogY9~=IxF`Z z%X6^l!L+M@Dl2jANRz}H@-DcENwjy0(W#EvvR{ZY*zf@*1rBwm5-oJ-6Ip(H%AiR+ z81bM#9!V$aU`i<}T{DE}Sm1iH-k5+s1Cd+(>G6cIkb8P6+3Y1>k45(0c7dm8 zT~6Uu0*6?Tc<6aNog-ckDrf^1BB@(eQQuRPxKW;1tUzoLV+A=QDa6hoWJg`JJD4Ap zRZlEg9EXXwXwy5Ekq4JH==%%&qV&VQ>fYwR0Mh1^w|+A*d0*|RbH%(?N4KrELu=RTNA6&I~J$D z@6wc~vvbdHkA57&(i`GX8$m%21aMKS|8jeHlt{b_jIv$k4-r_If2nhmK10G6i?|p+ zfh*c1DFB>N62k2Z3fKPKB*-o4(pJIHPm~A$OKDndpagjqbC;2P)z7 z6%N^$O^+4$TjFc(-HggG#X4Eg9vI4)L11E~PVxGNLjPEM$TpbRu(okZqaWGz<8OzP zQi&aZ@!~!zez?fF3gBv=F(!e!J_WE(dJLtiik68=xdi(<-ne3F=bZi{jbZk{hi>x?~ znm}<1&7z?cPgsAk#N`wz!i|!O1+}47RI<49f&%(0K`)|A ze!_n#bKomM3;fS9Qp(2O+SJDMi#q@J`}Tjv$bVF5wu+qHSBCbnqHsxSm6FU$7WOap zCY28i$t47%4$p-tER{qP3(T~#Ge|I2Z&t~BL;C<%{+gr5<+>_BYFHzs9IXihoj0otqEc&j1G1_`QO)RsEnQi-WJAP&s6&S*dX)vId(j2qQn-U1_{T)22s z!~z!EUzMH=k3@6M$0hZj){E^5W{pD=aUdLaz@!ugiJ?hCe>L7orTW+>es}vm0cEir z0VP^LbXDxjy{)qxgD+By>Y3%+LIcvxf_rv-RMl{(QaA^%J95dD5dXoMF2xUX!kc2- ze{({RM_#$suh42;n$K+3&D5FI(gwi&t-P3`3MX?xD|RbjFPRYj=rIWD#(nu_%NeaB z?-P%LW7gtvnB=sTPML2@92W?UDg%K{zNpA(@WVXcbO%HY3;$OYnFvXdYdX~CM#{A6 z9r$DM<>dyhLa>#G6w;D1$Ga91e+Yg;{j>HU4R1dXzz995%JG z?CN^tLXv#Uj#%<&>X?^Ax4hZd3&eM}xLnODk|TZ99WK>WBCnrkQn|yBMFQtuqDed26 z;0=3Ov)w1{E}ME%HO5-_Vxnbi`RIQE ze7#j|!AceV>^=0sCna9CdzHs!sdPcexA)uno7NP*wAQhGg)A}#AH?YpSV&`(5R5$V zUF(H&f}dBeVQtO7^oL3$hm!Q!VEnQj2n(EzubAMO_m*TlP+!Q!5z^)ON8le)EQYXp+&F z)x)jG)jvXA@Tc(SVwqp70#Y3i6!jBB%NV3cEzC7YGKfrNvMg_*eq=AY(P~M|Xi zJ_QqVc@}sCa^dy-P>&~j4L(yb@)7sV#P+IQu2N})_Cm)LKU1yTAto|WN?-_c2hdYZ zPW1ds%5^vo(MkBahDLl{L;uZJ#IhDfU;Yaoe^c5&Dl8>&O}<|cDfE+ya!w6g!Cegn z6?|bB)^5RFWCvXd75))cO-F@NGcqF1G@r?H8}vzW_&88;hbyz0hv(Ms_R>{Q-v7&cF~W3YwOzHmet=ui7*JH}ym+oVVC$O2&9iQ%JkL^NzA-wbT3<_mJc< zzu}W0yNSKz^7>N)wL1A=)JKR67QzqZSI8S3HX!%)9ew?im$)-!xqI0_kXgNa% zd^ps>k4-hzw8wFZLpt?!phHU z2~;DTHs*To{m@?Zke?AV(E1}-(@BiaHV)2UL68Oq1VYdKpwT?BaLaG_yIQ%u(Q<0m zhRFp#nQv7tPImo^vuMp|PLS@`r@IaHZ$II`+o%7ZcDO~VE6RUW^x461 z!G`J}V5SbR11OL1qD0mSwSYp}@uJX~enpYMBxu!CRo*AeC(!OEqZISwAc8H-XA_SO zGk>^Xu!*#bHJ?ka!-woOzMhY_C+IC~43W~2+`v5Qrz=6Y0V8+HPzj=F16EPBPHcEA zSVP=`{tPI?xw>LuNzO%M@OhX-xZfn#Pwv$BmfuO)e)Xcjv0Yn}o1Fr@q&RNZ7207$ z8iqFa;G=4aTlo^@Z*^?@7nU61=w4$>eyk&_pLSc(55)CbvOgcdw4_F78Jf{S(6yPG zF5R>@VasHC(m$>;dRVVr4}XU-h6DtPh!59>0gPrvckX&~$U+5qJH`PgiQ=Kt2O(}s z`b-ujOh4pK4-#zwM(4H=XD&gBF)2&-h-T^Rm;iRkOWr(MAE*AU1L^_yMywbdR7{*8 zG7!=T-oSQMAj2c-2~Q{o7AkND=TiI-iuCOV&s2ZZPZzK-v7Ef`6Ef?%_|5tYg>^>9 zi))EuF2?dxrSXGQ<(fcTdBXUMB9dkKp3V=d&?Q9vbUl`7kLb*8dMXQU>aJ1j z&U3_UTEztOdhIS4j~f89G+o9muM=FLqFOx`L=+up4VO`7jh<)~mL$(8O8+)Wqw1q` z0+6ChTDYxO#`Y{iyEkT{`c0$iq$5pH#wvA=Iftgf(FZ~-YZIzHJ zsgT*U$aV*V$Y7Wlm&^1L{@x={u`5+t7{$@Kk?S5b1r^z zrAOK7SuJjDZ3(dcu*1v`0|DPk9x~7jK zhBo4twANp*1JgAqO(|MM)F-~`2|mj%91|*2q*#{W+5qV9KiK&`Ao2PW?dOS%zW4QQ zUE|YC82^jJ^Y!EfNJp*I)$YXJN4v(OPTGe9Dq5Y z@s6pbvwZcmXyXP?xt0U0i^5fwsSA6@Y@)=9G_C;yp_=QW)F)2`IzS_{PN`LSU3Er# zdPfwpl}rhgovYb$TWgU;=Zek@d{or=&jwYs(S>gnu-qKuaJK;ot=!E?z5bo@XPn8Q zBf*CG6-&mbZWP(FxCmrJIDNz|%_kmGMs*D*qXplH#+1+9<^K9SM-S&t$qQ{niE_mGq$zrZ%C# zZxC)NTpVQ2y;kKRQl&Vok&~y;qz>bqh68tF*=1^(>z3SO|Rh%|x& zL%%BrjfmzQM}X!X9EaW+(n9uDYJg$^Ee3wMoe>-cW4l!xsL7iz2-^Io-kIbyeo^vU zZa%4yiXuc>ZCP$09dvu3%^4+Q?STDzPYd^-NMirWyhZAj{W{WXy6%l5;#`uLv5^`q9^Dg?C?B& z$-naX;Y_4_)ut`fVl{4eJ|)%FAXM0+Jo(~(pPG%8Xo4HjAzKx})5!dA)tFDV>dSv6 zjsJaUMpdF|HQ26D8B<+}ctxZcIyiJtuQxB7<>hck_Hu|)w`tFDT_Fc+`oPp0wiYp} z5*_gj9Ezp4qjR9RJaUDf7;&T`yZi!)1#O5Za%24Zl@*u5~6YnU&U_w4H`$Uvb8|)A4 z)(&T*uGF(V!hvewUnWOi*H+hWxpJ`e)<3T&vl_gHUw03eE`e;f17bncZe|>$2Fhb; z)nHnqX<&3!k1~XpU|Rz+v1Q>?L#ajBQJ6&9x_-H}@?w=UlM@$MK8-Vs+|A{Q%{{!`TDYi^9>`9!9lxOu%#Fb{?)Pb! zKclfjbfHEIOIS-bHLZ}G+EUiQB`dKgibfa`F-`CKZe9%L-Mvmr%sKskjJ;!Yq>I)y z+MRTqbdruLwr$(CZ5th@W81dTu{#~xwrv}?dY|vR=bU}tarZk$)t~zJ)U!C(oNEb} zTot~BRwRrz`}PsqLb)B!4>`i?qx^$v%q$yaTbNA%v~AFG)xDQ-|@ zo&5Pv!d>Ix2SfYGXKI#3wdGuHw&WgZdeYpuyxI*d5DZOqp+q17kQ2Kby-@d2DLbf&b!y+v0xq zNfG^2Ujv_--y?;ckH??&H}PG-JE9bq%&v-Jo*+BSL5&y#G_^ka(r948%l3bm+aI zFT)+GBNZDg>kNr@BvvszA{y6EIMDQME-0Aa2EL(Po!abwnA|51{Pz9;7M+MVi`90v zaK_Ebr%F>L+dMsCxH6)MpdLMPZX}`%?&ESU-`!zVD6t@eX0X}6waw&r$a%EmP7bM% z-nvchNE~}PmCQO=k66Eiws4$CoYXC@`Kw!e2fwNi z1U}TthjUi2}8-l8bQIIyqAC5+-(rKudGMI^yb zMX0|7mS^ozxfW(CBD%bBWfEzZr(uQm`@CHTqg(uyE7(hNhBr~Mp@QHl??8Ak+-+Zi zyQ9NOJg&Y1*AT)m&D>HRO*1{9Xeg52)|(&58zHM=Y;<)@<^^cPebEXQlqHqvqN}`9;BQBp{YGV+A%o zb{F%lGK=ocb6z;&Lf4FKY?4cRaT7MTAof6#_{vFHm({$GQ+@Ez1jw4D|BjZPN!?=t zupCXc z6>A8YoexvShxLb3ro=y&ISx!^nHL=cFhDwe$R{_10FMu;AA@(cJosCo28SMnk`8T-|+T1Pl3+fzZ|74jdL;IoK zHSg)nLeE6W$F+OZvYa+~LIrH`c%FE+PfsM|=hoo%Orm%-f>`6V+LppC0FH%g0E#}G zIa>rFMifDXo^p?20kc+*GhDH~NEZ@ZPY8u;*%pWha)mjd#~5saiEF?)XbMyp8a6YL z3Af_+7J4v#?Z&-{Sy+exE=8DD$c1V>_`+o=_?hTWhLOzS4s;RE3COv-9*DfBRTI$2 z=OG`o_5Ew4r-RG;xuFF9A@PxZJg*b?L(9eRPwKZFM}kY#I_z(h_1>@p=BN2f&}oMd zPQpHZmDYp^FF{3*ENQ$m2A@dHl#Xzl17tX$-i+W9K<&O2e=>(dh!K~>1Nla`3o>s; z^C~!HjTP44kw=X20bNM25ov-!YToY8B9-gUGmj!=hK3a9MrVGecR1LZqH2S)WtPEU zwkEP7>Lm1=FSPHsptV5Y0{+{6u70eOf^x+r4P`_f8>zZ}hNw_&3ALv>KdofBF*m_H zMa?vvI(;v3xW+{C+_|yyY;6|O32}|iMVG{8-UvpaDuvqYdPhY}@|^m}GTuB%O(RBa z)h2~7crW)(Ey*4hWSqC;DQ7FlV?E^tK@YUTz1WhqDoY6Fbv^xR!u!sDve^D0>gDg7 zzT3dO@JBEs`oGBw|8{5vV-sVCKR3Ak2SQt6{F2NHA9B!#_;fQp_%fd=ne?H+H-w_^ zN;#+r6s!d$7GJ!pC6nor3sL1NeP|;xT2hmFn*wz+T6}`|1I< z6LVH-w??HCn~POmV5yg57+eS7YQBl$zt_wKxy%rgTMQ_Z)^*bj)^fJ~H5p%3ExWDU z<}KYi5VMgCir!(kShl*XY|XfPtfNXt#j?kT1^e$6LAfb9IasoDHi!+fF?-9;+ZfO{8SpT7g;-HPxpo{ z!PEeK|ILWzq>fNqc`5-pLL_fUnTV`4Y_=W=OJYSDTvnPh)PzoRU5-5uKi_bz zeJ$16=YVw8FLVL*JWo%rM*z$bybLz@!;A2+qnIuz*Xbvk^Vd8 zi9a89|L8ZLh8`yS;_hlL{Ux1>A>zZQweXUNWv?&<#%M7lb{Nfu?7>%&d)(>Sdu@ha zbIl4=SUb>a-3!8>XET5uDe>k#sT|jx#A-)=Y@eV_Q)0sOrP5$p{HrSRMSpVL1jZWFdZG0pBG5$_QkC zGD07EjsNJsGJDA#`-}os!6KO_A{^+q@N|qbtc)OMn{`4D4D_5;;a0 z`&Fr)MN;8`<4jrR`lM8lVyR#11hTRtw|c!ZA-gRQvD%S=XRJ4AI88I5IZm=U7~)mA zm&GhI{rR>o3bEgGW=qIp9^1N^hrWw4Kfl6VJ)`fD2-IJ=S4OrV9;*|)&g3M*3dKz`C z*T`&7y5wvW1i|xus*hH0)oXc0x6F#nybDxiCytkx%3*B6%oGA&OJYPDuoTKmaK>%q z*Mb|u-4~H5!Yy0_y~2;-49!$#%q#UQcQ>|Xrrt(o-PkS2z}WSFTtsL#^3bH@|>aN0L}^8Aur`zmjsfeL_4HW@KBh3bd}=yN@>E-FarcmqIH#m_k0hd6e6ryAf9=G8L@m2K=5`0U2pGKgCb-nZ1C6sS4^ z_tgwwsEwZ>G0d>?uXr>rKUo8Qb_P7q>BoLWnx_exuM1blw}EM&0~z^Q_Arn4%SQqY{&CT4bc&w*#AB_-uZl*Cd9E5AgcD=!d1F{e)Vo4j z%2Q+PQj=f!^UyUa@Op65!A@!mhmH=YcOA6lYa?Mwbxa1vA%zRZYu(miu$R(<#*twj zctX!(SJqf?nplgMYcV zlI>rB*nbgH3KP6!XXKFkvsWVFMBLKzx;-)TDlip-Lk{^2QPB*+({dP}b(@sQ$WKmL zzCDq7!yxJA`8;7Ugt1Jn%uFExo06n!e)M z%v!Z1Kg~*7RCX2s<&GNjCXx&MfnyYO}tNU(6nXs&xuYOvP zHT~>~L8yL5cE)^EG&xVBIa9_BywRl0=0&7rhb_f({1LszH*bUxpKTooN;+k zD#{qk<6>q+;{)8XI1gk^B@9|QX)b!rdz@3FiyDJd-S}nwh0Yovm-fpSNTk?+)mt&Z zbZ(V)Xj?p9XisjKE92t)$_px#amjj60z#|w@+7m40Z_%l>d zX@(G84nNyc^_!9s?mV%v#nSZ&l@PoE&xeEul%=K8V`6>LD{YyFdI{_3C|tn3jAr_W%+sl{{W(&v~SMD zItK31ldnWYC7DI?p}=h+q_rDewJkqmc)}OaEl3e_RrrzB9fo6(?7Bkx*)t%7qT3kV zP0YuxX32vn6 z+F3>AzuhS|d%EnR;^QJ+L#3h!#;V#W@0i{l|JO0TC1BT`r92M-E z#3mEFMRIT6Gr>j5R@PlWe$ULyx!2sIy|Ee4QZ$pk6`P%iT zxDhOUIU`?8QPT{of(-5T*6@#2NL4}lX|na1DCM6S2OV~8_1dW(+W(qDwa|EmJ8cLO0{9BynZ%_5aOM#w8@dy1A;{l z4VyP&S*jXtah~|b?c=m`F5`}ox;Uxp`pj(L#%2;X>pkrRLaMiN)v>-QR10kC+u6%b zL779J%K)gZbyoq>G(8&Lv&C*6NK!H+NHC!RI!Ix_Ge21_mMT(Wvx@x8m)xog5RAX! z1!bsq#t6WFM-*5Wa{g0Y=wxPV^#4x5^_~7EsLoW%*(EYeY^q z_q#)y`chmCRE97|r=rop%q^=L@e+>WM;| zvf78IBG+?_9So;Ttp4VqT`V5wp(TA>?fbQOz%wt9ZBSDE{x_lp?+^QcNuZ%E01b`h z9}Lae%E|n%yz>9KY@Dd1Df`#a_a-@wBoMGN0^!T$bAe<@113B~OJ-&;@o?r%P^z;q z$t3MsG~{frOH+WZD~qqI`0iY<&vv%lfmON+E1Wnk$3aFa`-bPuSl0XN+Zk*p)xKfK zwh6L!bDuPa2nmuevM*K-a*@YWq}3Pbo=b<)`t}-S8ms*#=<*f?Z{pvr&x)TFSZBmS)P%eX6cwcPw6J zJBIfvH6TP`6>PIgNm zK*tc5BMhMvFrFBaoIGHpcn*X*a3q(6a=3?DTvrg~1{WfMY_R!Oqpuf1JG3Yhetkc% zPq$dbKW+QiBu#%5*Xjps1wFoEK3-rxhGV@zY%5HBcT$8ONZHO}Wax&Fx-2wJ7Z5&2 zG4kc?z}tRUF`$ovTq3T0DD4L2;1$A%4qZT^%2_l@ELz_2{;AYbO72Apr_z?t^CAxQ z(C=Cp4cKxX*x&tm2(_ghg8lJ?g4`@6=pmwKY;oP9YvIQyK(t3RmdToGArafHtaVe^ zah|{W2=m|RiqnG(7aZ7KWdNmS4F6jn`LC4qZ~v&Tr%JF?E>J@*ToV`(Mg;j*lUGVE zrcv=ZwAxx#tM)YR47GBC=aDgjmMfjFo#@(PoA*k##IdoVK12%#=pMjG3>2AVy+7XF zed>fH`E^OK%?}FRf_@zr+KT9CxG1@hFKwqEk)Cb?1kp023r&(2rb8238hQn|m|1z7 zs(XQqfiZhQTD4lB60WiYGGLu=Jc9%c8oeP$BS>8@CX2X9+AyCi{VB!kPGBx!QRayU z^(R!8fmyk96sGW+ft_@DtHl@{WUgIM7dq=Tv_Ea>@vwkBWqFFEg9@Rn$MoQkh6szY zcNJUaykw$~knA*_?kv?^NKEeJlCh&Q4}11cX9n1yaWK67I2bxs79 z)>19_8rt(UR?gzE>-F+Xj>Djdvg;ocYWeBcQB--@*aV(tC{y6_LbM!aY6nkT0Pt}( zEY^PE)&77Gyk{Y;0k||cRm2%1FT#7aw$j}S4%Jqr>I7===+WX-#zx6oKY^iqcEwOb ztx!8~uiKPgIijGS*UbFHUQFCmzSd7hmo+{pu~pKv=9|Qv70duCBY5?XkQPNbE5a+1 zRq$X*i5|^Kll<*IqnYo0N~ZV}jyzr{}f*MbxoPl5#;K1h5#B=U&% zK$-3-3TDrt)xO0qi$DfvkJPESUUYNB13@L@q!&RP*P;H$2Ye*bz?V!?%gZ-qPhNKf zJS_-ZZ?F$-FrPF-AJOpHM>v`?eKh}7M?MkPXgpnvg(HfgUjjm#Q4@A6cQ|E-f$68P zOKnPb+#DOCknrLQgi`qG$|wZylrELMT4&^5R4B@r$UP@ekl)?eW+0sG*R!Su(U>?c z=et~dKDd@Qnc&W#x{6Cji&>Oo_^@V2%b9p|jB=L4K2_yz*f4u#nBv{NMmr^nWg{(7 z#8zcXaPTEMPFF_~y#1YUPqVU_1@x+1pn&=xI9JktGS9y{oBwjFLS=17BxQiN42$)0 zwKQ)4o&{mwPbWnT7(YFW!T{v$0u+o<*g3?;A&sP^Qxg`<9379X3A^^KWpqFvy2l9Y z?*Lt29@9FerR9Pl*Vu=QoAVc*i5H#&LR#IA1_(Wx4ZsM;}0@usa@>0qoYREsmi3> z7*ioUdDi2VAWi!8qJw5>-_h@dK_{p6PEARb8t!#Z`R3?L!Dkmscjt#0ol<1n7xh-M zdQMCA(ze2U;uET0^4y9|Af=L|Ru;{ME?1r#g(swjN{>~9ze~4#&5*z77-FdPDmPQl za;r`NDgqNnT8nNqsCQA=(s8~TjO4P)!R>%WwNtMvjE=-tjv3n)wq_k<8vEbd;gSm6lecOuu>IO3HU&PlFS6}ydc;0 z5Dd1La1Jw=wLA^|O+jI}VyNB`nUP8i%cAyi(hm<+G~7dYXOsbZfj%Y^rS`ypuo63R=~?n< zfQ3EjN{&cvom;0PJ(()kka9NNF02h36i?LLO>8N=t|ubh4alO$e317H0z0f7R%pTW z-D56M{0;Ln_>hga>iBy5C_Q+2GuL#+2J8UEfMEDbn@@J}u?#K}AZDqiA!ez+OyxM# z7==Egn%4mafQsCq0jb6t5GnTfz+s2=9;+W6;xg!oMD9u+5|^B^xmLm#vG|JTc0_m| zRy1)t-!$7+1G85LWC;QvLNQ|@@H;<Zd~mh$Dj`^?!R)^>{H zZYj`(Io^dvFPapEq3M@VmMKqnDHaxD_EVcfe#Q!#|1M){G8n%|9DPZi@DA82d8Fs!wa=f3f*h4F@XJ{#=IQ|d*n@Cb?f z@=EU6?M{$!)BClXcRk!E{B^_em+(7o(B_0**TI1?dI0d(-xA*bClpWLqjo2*i5j1h z?ZyudxUmC1)M&lKUs)DVpD+b4bvK`4UbA0Zli$Jqokag2-DqRm?KwcCJ09rr|Byug zfRq0NsQpLk2V_`sYsN@W=ehp&PlgPX^O{cqS z&d`Ph(3hBVv~fC`jHhOLdHA@2Rfki9LQxUX`w5#T!BQCt50phQW2=MDT)DPsqgW$? z;S1(YL;H&a2RmzmRRta_e_t!{x&><;KzMMQF&|?NCVUNcm!EbaX|AYrWts z=n^01!TNbV@um%$3!#9p-_rcUrzjzN#y%rG8U_Hxb-@99%~*`v&ewOYX8{y;_e?0d z!^xOfRlW&ULR(*z$X5~tqk$tQ;R8UW`3d?c1&=_TM0Cg+rJhD%-;hoGm|`jjv3d%g zY-4(mxB%Z75u73?kak-{_a^QrWfnQFH0910;e7^m#S@zA$8xkR-)GvksdI&FGB|LU zuE>6a``_=|TfC9_&%`?!NU-?dyl)Y6V=JToitdSjQ7n)%q^Db*wH-cpXMQs?Kh~nc z*(^l)R;C0+jw~m?&I+Vh>@7|$m-d?C6XRWVLR`v+)TK`oF%jX7n9?4Mj*hFJMQ3kx zfVu`1MKW_~1P6wFjdpf5FvR3!$ubz|t_my*jp`lTjefKj-ns z4(U~`&F&A=uOoHG&Ru4RH92d1ra1rF49&&6EABucxRn`Qx1N5aVW7bs6Dy_5(Ed{g zC9UpeV%EdD)(!w+guf9N%Z77!3b76qS-N+_LJj=+Qw9PG(pUP0xwA%%I92~iJ|33;}tuR*K|KEvRY zYtI|>{=CRw^BrQXjbXs5>GA}^S2DxEJjq1n?J6W$(1oc2pLR*tXB!ZcBIndp^Sy{v zbL&d2{z{m=g@BnBgE8#5;~1gfL9ec1p?MatiKA-T2qibz<^+mumU9H`9_>|4fwpJT zGoC4&*T8!o9Kdogc-`H9)Zc$X$Llku<{wi^2b$79R0@BE4r${*h{)e;X$dF>Mdprg zcDB^2{Y35oRnO#%8V=!V9vDD@k6#F;l<*L0Jzd%^WLW$yJ22r#FDP!ODE_&WMEqpT z52_9IbMAxDmi(uyo0adMCMIjEgG5j0n;1}k zFl$XpQGpkts!fKyuv87)KYeAq(+Q@+BH>Xds~5(?f>*i+y$D)X+P@2mnP&y zA@^?++evZX#syn4-pUe3DJ zqylw3XTNOh$6=9dobRpQf`GHxP1##gD*+}L8w-_Ioql<>?+M8<3kF%583WTtc_D1y zP~Y#fEHIt^>b4&OxcA>Oev<#xl;jX!3#mV(oPc>=^6YeClq)Q*1rKuGl~*x2;!jM} z<&HDPxJjVR5vvg@M_>mqtvhx2vELy&$QTB+&tP>uO1-dme@3a0b1JEoS%up+-v-yX zjs6ZLyFtx2kw7!USeOC)Rwhs`w##`7vL#Z^W#X596?cN%fl(o;O`>s?3HHh@q%iC( zRDx=<4?YB(Z?At_p5rxt2)*B=t$(=Uo8g&Fsnq>_iPqp-AM=qPOwFBP88;@gZ*R7)z!j!#Lh!qrkpNKKAX z2JIyqqZ0wI+I*eP+f`!CAtUrBTZPldL)$|;@|7|)n(Q|aLKh0;X+;$Q{~Uny8egjr zFS!Un2cV|__oEg7q5cfyGI|TK!Gr&_BWXDH{0L{|k|W9B`Qt@ZtXgd;XI+ z0u(t&^!yPyh-+HLn{j8$f_33k@K2V9v4Z^!gO<2xVxFh2iM7_atob5*+YND<+dI@~ z5tf%ooSyk++L5}nw$OBd_Ni?!MNE%8kS&QiLXS9fj%Yqkjdamjwthu-fnSMicee;O0I6qQ-zU;xk z)15Ce=-qIQckub5uVBgd0yG`DZRe+d=maWlcL6WE?(xhFZ}gCH;hSv2SXh`xf4m^( z+(FehPnyGJbXnmx|IGjV+#P`Zxe(Hi2eFs)2BRkD4Q=CZ4OJp`8ErAJnd+haM{>~r zA9r9(9m-Wp8Rgx!G2Jbb#at4^TEje-FTK#*-1nSGS}~-EIR*hu>zTpL9D;<=KFI<) zY`dF)29kgx4;6)9sce$K!X6Z*3wyN-PTsByZnY%CV}rqVef2@dB+hea;U}wY%fZJ7 zP}O{}=5g?z{~h;pb=sV{T2Qp89f8f19VHKb+KSMP_>`waPqBTQ+1IdrmZ{0`iOssa z7Qvp(?PG+mmd%n(*+@;_!^}XDvOB1R3rsqELm}1b=7C#z!*6`&@X)hQ;}!{A-qoVu;PT< z5)H!M@`pLp%M;_T6NT}Wg=DQGR_E|1Mu8>C@z+$yLr^0xos7uUkvJBMaxRKXt;iZ> zaH0T=e6X-)j~?!+NL!X$fxj} z5dqQOfc!-h|0!W#8%GHHz@E%0SIn($+D6S-SYcU#s-XIOw_`T2|GuVx=UeoiulvYc zac{f?=C%ceaSe1=ooRFiqFYJbh>Qwr6uXZ>;3PHiA|n>%+!<4?hoaz{VZI2CscFl% z@UDV!H$vz*P4l#%I$f^wnCR_o>SA7YV++|i{0O6Uw!NpY=lH9{1E zj>8FOaSOVQT)a}H_iR1MR}l>QnNEeaEig7Ey`NL6@eL_AV?fL36$5g~KPee`=5iQk z-t6eB8F-I}p%T;dVitS1cX@%%ipw$+`|aA2;btVUKtD{v-a25VsMAm=kgYj+5?BE= zNkk0LCOaOp3bMuu*CyMBv+nxLOu)v-)KrpT`>F@YbBBy5%1w8aw6$XnlBu=6UoI<8 zIv@`mN=(P_1>iGg7{QmR7Wb9MGEW~*X)~aNp2VSv(Q;S2GO2B;$M*_9**^7px2yr? z9YZU^PqxYLgLs>q`UJT7R_=%N^v$Sf%+`jskb4>!%L1UJr%4@=`VwG?qA@fS&r9 zM)MunoPI>HLTy`!&Yb=vH7{^cRd(TW&aVI-!x^_mlQhicfM1lOGI}hAi)`9p-&cpq zo*+d@=tZH$X><`04Wd{2cxEFJ?eOK6Z23wI*;;Mr$_)8;@6WtPW^bfETj3jk_rR4a z^6!B%viBd#Sh7M_1p! zU*Bj4KG?D%x5?foO2N0u3^SC4)QQWtE7IyP#$6NU!rCB#cM0n9s3@MtQDqM%p?~cX z+619Mr)#lf<=njvni23|u?A&y6i3`7Wa+!{$=;aF9kr4iYW4Fs;jpO`g9UA{IL<>x zt?k<{p;S6xy+lo)oe_7l(QB2S!1lQ9>NzEaZDoD_DzWF#@*R%-%2Z7cqJT9~!ihMv zf6%Gdpx-P>KeJXXKzQx}PhW3Em#-#eLxOcs?Aysik*l?bHNq zAn*9BsYAYq#yT6pw)iqJ+(}J)2(kWe&&hQjZ8q+k{$px~LwJTAtUQUdgM;M#E8Mf0 zxMjw#9>`_Gxg7qg3)P$Pw$5;h*@BD}RA&ITis?t(zOvW-I)8mJ={_2Ay6cl+?&kb6 z!LE*>&@1VgUo$Y}>kg~wBo5F6b~h1N1qVok5X(B-=GrNi0^@zX3}bhT!=Y>OHF39Z zu*3E)(!+?TJ;I8fJSbdY)=0cR3{qH)c;ax~IKTMEql5HO2n?$#&;1Z23{sTjHGpDN z-~f*GU#PmoM=O!mL>Vh+JxGVEjSbRSYv%2B76mbyaQdPyT91~mz(`S(wuPt!sb#u{ z*uX|=K*r4YDGv#WSd2fRPC0X`$hW1PyX5%2f7ZCsuij7Ml(&yLr?8`FaFi22Loey( z5UR$pJgk~Jjcj0pi%|thoccXeS{(ZH4W=%)@CkuJSdlo*Vrq7G3sYX&8lqtZstCrJ zEnUc^%?tx84Lq(|XWFV$Bz!*+Ra#N<2D^mqi_Kdl3K!y(nNBTQoTfI!9p zfu+M>S~XNU@e*o=d2FU=2f})ZC9}9m1GHbsf;ug!-6t98&=(xY7!WIt5#tBFiTPGsOI+ZWs?kEjZJE*C8r|GoMRQBFyOQQos zG=O6#pf6Xm!_>7ysc+IhlZWEKRoO($cwV#+4y%hMEb!BLA3IN{v(Dz*7f*Sz%NAs< z&#SWdil7S~z8id<$w46So5J57`w})RHd}NyN1z_V>&aEe+O|OcNuUgCo(9EZ6{*v>5_+bmZl%6Uw8GQAOiDH2KJ+zS z@*Em&#FCDrr#5>(18UVek&i}l186ja2@(&@dM%(M*lJPXR~k?+99nr%_aL4r8v*HB;Aatl~RC-u3YtdlIQ%MgpaZD~^Fe{fv{U)W#2B00Sk zOaxC9Rpz%kH;n%HzJ)K0fZQJ*>-{m^=3 zKK&XIF2Idw6$V)~;6dE?Qc_z=p5#iNMI4q-EVudtUMvjrir@H}<_@8nVz&Bta<>7B zjVAzJ(hpRLKk??`3vCaT9V%R=4~rl*k6*MzP_%ePdiLMst@&SVwiAJ4+zTK>=pO`g z|E~T12ShzH@&EDwQ3V8`$wI<8c9+dLYdUM?PRKaDIh<>>1S;8B6Xs4>Na2N5q~;Fzn; zSLf*`;%jateuEFsqcB2XP-_#_x07@1u03;?X=tV8vcX;Wb>DWsNFCH=+KqP2E@(sJ zw(JQ+QXz*k^qo{6U%jZWy`3a*xLevWo1;{n1Q3@ZgVEi{%3v)`=N>yB+y=dplR1T> zN@LnT3K1Taj~?T4CzWlw9A#u0TisSgiq?cmgkhWIL3)&I0X;F8s+rP3CIHp22P3jq z|D;3Kw=fUXud(nK{@{K#`*CD3%#Glq>aq6@GXO1$)A}kboJ)D;R`xq6T8VG3B_ho1cTP` zIIJRKnbo8FiMRR32q^L=*hnx&t)E3wD*`cy(5j0Nz8{YRy6gh0rN*kZF^uW729!YW zlTOKWbn80^?~smAXXP|l%)HXA^|--L=+y?`q$n??SC2oBJNY$1y>4q=T3?H7qOV&2 z;El};^=#pA%|Ut%>->qbSO(z&w$bB-Qn~ZlMEnzT-1g|(-xv$4;vBjSKoB_@$aVb( zGMu8hwYinP!~bCCg-LIUn8JX8-!S;9-SQe1)kXs!8mtzQ&xlhO?4XPUGS(?0vn*S)+&Z<@i=56be153=AvlC8-HThLIN znQUKsc#r-4_frpwr;vSzqK5J`C3J<86meQUt0ldOAL^8N%3KnH z?@?A+F+QTWme^y~0=kiM*Z0@_Mc6#{HAXWOD8@?-f!59X(yX9fuR<(YZz#h5Ps zKoHfB1(E;?j^Hhewo9pt>IE@GQ?6-s)drLyOSJQlSsap>VddivN>voqSJz?(9oKU# z4w9l+MthVUlBz9gBqS@6B`s4&P(_d%dfee6#W>+#%&`@|*htZ_tXJ6S=3Mlbv%NGO zte5_sl{y;w;G_l~;NHm96HlekTHB{q6XX{wnt=z?a9O1(#7L!{~(go6tq@9$PdGERG|E}Y39e1YDISUdp-Sdr8qC4-J@>)n# z*2r2()q(g)v#jza12gMgFLn3q&LL}FZc>)Zv{nmZOAsnwrQGT++M?ymiP#V?@4;QsuI(`-H(k@ivgD){rbp(IKCV}>z>g5ly`9toLW^uG<>9iWuvY8K$ALsOylid4fGu$NS3*06$ zhd7Gxhd7R;2R|NKkr86-eM=v~A2t(37A7MWAV&%#NU)etegb5hCCFYaxye;k zyAggZlpzxhaF8N%7I=W#6 z6Z=1Z`+OjE>UiemVlJWH=IV-oVl*052j(jp$XE_;MWobW1YITtHPKh-3(bqzsr0eK zRRWN2WEjUSoAEf&E~`?)9eQJa$-}uV4UUMcZvbZWhSSI`iz*_47vGKhAi5(Byoh@jr8o_(34IpsU~R2)ONby;`*7x za8mrvhRD|4apA>igJrC>uP3QA=P{h&9^9!ke??E21j`8527aZUOsbLckm|ZBZ0KWi z#lye)Y?a~qfk3H^E0eAMYxh!b-=}XU-}Q4tQcvef5>I0eP7OMAAxnQQji3u8OO@Uh zELivzx`qwc9eQm~XDm82u42w!Mp`;6W0KYgT=YhZPKyagoLG5tUQhqm)KkPd#Q_(t z${qAmIr&+6zx@1&atbYM6eZ~l~TI`lO;nE?w^Knl_ow- zVGnzcaM-MUoY+#nLv2nMn!lIQtEA$?ITcAU$Od!EW=&;-C)&q@!_%@x=v{UX#nMfY?_2rUY0{#X4)-w-oiEHkB3&cH$xew{81fvDya2ws(%fbgv6e$^i4|_#nREMkVAh~{}Je=x@J@?ROb$>z*aQa~f zh|IE;EW1%<8qKlCALM7+L4h~=bpiM>C?=rD)y(~QmCg&}$x3nzFZS3o1f?`9*engg zTGa2J%{u7QPeYXT%g(kpL&r_)&&?6{3N448NnxI8Q+UT!v!E6}KTs4WU8Duyz(PfM z(s6T*F_yVb+)Y3LdN?w<{@GEOZ0iw>&b6)kDQzirXk6;F+l8(jiJ!A^##p5~9CtZo zJM^!$)dDVzPj4RYclbKLXE(%o!a{D~nqg;kmGv1lHvBAta`7mt5pnToUZXKNBXqL! zz&H{3T%@LbiTRxx`Y@mmPpYV85CN-w*e9N_*)Lw}WMHoK8g>+n8-Yk%1mekC%BGptisB>xg{PGzVYM-cvN(wRdgqh z?y17=IjU^olwaNvC|~Mgqhs$B#$7VDD~*&2C_OS{CRe+u2qdRa+bgH!1=x~pX-cFJ zJUxsa!&h`ikM7CB9&v)R^-;XGi=mhp?=Hg0xH7EY0%YF*quKZqdArY73L}BdMh-Cg z0}h2IvM(y%q5Lj@Z0-<+8{ z)rwO=zD}C0J(D^e^}}Jt&x@d~r9Dc%q8xkm1PlAtrm#M&wH#!;jC3xd309NPogxH4B zL6^}()pbs(r%iM*~vFjbZ zh-w1t0Wo4Y0Rg zcLg|n8bHjzrORUbQQ{dW*{RzAmF^svrc0dYtVzBo;F9Q<(nWQ}z%%LnssR7{#pk`P zH=Fp}1N5;cg;2+LBa7u@rBPabk2AwSu^n3>iq}8`iaI{*5-jV%jw9{j%l*-VY|T<4 zj9{KJ@eRvXH|o$q$sOtJJt|G?12*AW!Y?uOb+P&tF=UwAOMjh4bhN+gtB0?ig{y!g zvI}5;@ek9%|7+R*eV!&U&Qf-T4mn7-Nn22W#jNE5B!Tl60)8YdowR_MXIZ1T(%bnL z#fa%5hiQpdDk7S1xIl#sS#RhHe;9{et-;e{#)Dfl_6G0j`sc;|)r;hN7f01+*D9v?o|Z5)Xh{UL#2nUi4wi z3l-~mbOwm78a+VyaMI(Pd8@!&^T~`%2ZrnFPe< z%`F+@Z}^eh(rX|+!;?Jm%&oj_+&L8OA{Gx8# za{UjCch{GirtKrvYHE%2ATym|k;)MmYKCNQ1H=pw14IJ{l|eTv+(s4=7t52ca%ZS_$nS$cOBvU3!zr(eUE3+|rgX`AjRw*aX6$)nTl9ebXok zXvl?^vHP-0FbOgIsR<}yzDGLD{d8Xsm8FcC9CjxS&mU4vN?k)|nWrbjBuP8s%}9M2 zv+YPo=t}Js6ELGj+I!Ew*<9c@qmNpwX3TqffBAPo`DZlDuaLaX1bp$hz!hQS{~6Yd zUG%M-|I$^^3g|nU8wxn++ZdWD+n783tBkBvvixh+uV7PUr6!+*{FL7#m9lyt0U0!i zZ-EAGC?CO8$`M0-_y~VS5wU-jd{^fa|T9_hb+g57RR;? zAI~T7O#+kc5W#T#AQ*=hK%W^FG|dn(+5muN;E)NYPY78xuXz|@Wjm4GCe0wxx03F* z`RhVoMGy6__QA|JJ4)F6K8yaHCW

Ipf{)WewmVA_lG@ zgccLEAkIF7VOUy5GRONey+aB>QnTV38MJ9EnsnGLvQ=jK$SVD=BVkFiu|IS+G!@qf zWspvCvk-B~ytk;_o;7Yw5hDtzDtQs zNxD7s*?kszqLXMK_t`>h#z~kK0R1tRZ|d;7LvUj946^B14JPWBy=JpQp2sg%XjHQ(pL%KwB~eI*GDY&mCEjl9VA| zAKZ}BHZFLEl^9CeP-UD;Q!|YdG~5@EbUKOt6VY}esx7;jlGwJwU!yO$cq^cskIBeE zJcKcs=a%pHzxp7elTD!|Zvc7GDp<%u5N{h=EbJna% z5{krjbR@HlEaS0AG(IVw`+yG1D)E~n2=eTx0{J}oBVdqJ=zI7fKARi?y>VKAvqdkG z?4VL+FIwDvV1XCDxvp3%zED=J6SU&Kx(`JWref@1$3Vx%-4=OXiJatG(LBlPe3oT& zg@_St=&mx}k{hkZF6n=}9vm`SFBdFO5Jvd7V`zVOJ#iZsTf@Ix@!#&(pysBBrHuaZ z%f!X>JEQo|g0aRv0eq&hsY!o4auvyGz8vaYxKd>KrgU=#rZu>>^kw7{EPj4uDlt5* zz5j=bgZ^J3F>*J3F>*+je$r+qV70wy|T|J2q~+;(t#qI4YNJqr$l(_fe2;I8|ZT`37)_396pl+pW;Md3e z4=>8#um*WQU+pJ8lmT~>dvadtcl;#%ci|U${IqEbA&&+0uUwV4NYQ1SgHMRXIOrw)QA4$7x3mdCV^Mdt(XuDU zCb`&HWib`y#kRDLB&A(*<8D!@5+%InrNbqV)S7==HJeGgT7(J%I8FZ$@TysVY}J(X zwV7EV>yW*-QRKZXZ6rm9%AjCy*-_rf5+QP^sdCZQa4T%0hO|x}gVC%TwtD(y(i_Ux zE&*E@DL1EkvIr3wgM?^Mc5(+O>3kp#0SZkS(d5-`5F&(ie2L+6kr^7swq$~e42)Ze zUs0m#Cd9OHt~Si5Qc-;%448OSRW*&<-Z0Zgo#^Mr)5qwUGDWWINs#ktv}Uywr9)d3;Lw!PtmK-ywmkJqViuXxGn!w%ss^`Os@-TI6clcXAPYU9UZ{h1*)ohn zT64=|z7`+M<*pPoWfrF;bZVhG!hLMKAOQZ4b#I|UU1Db|3;LRgDC87tbXrgu|8VKt z9eaxf?i*l%8AnxT31%b?KwgHd|u{GlVcMa@K{%;h0TvS2u9AT>y6?~m@7xBv9^ z;N1efYku=bUN_h7P*y7y^C@yrh6~jZLG*rb<<&Y(b$0DC9Ez#GkKJb(iOWM5 zBa_Hyz$EKM_+htsY}#@^3F6WA*|JgvnWYf?r;~CGo6M&EZl{{week_P+H8HagJCD;G?kz8asDn+}^qtVHzfC{ZFD52A64HKs)kqb8o78rkT+?JkyEZ zAa|`VlX@bzmHQx*-SP%3lx-bblGa(OTFjt7UEZGdU%9t=smd^4}~T!X0p=%}s%k6Xw?QRe^wi3TK~4C8nKBd-!DDym_xn2v+mu zL=t#xHnL46icv>@-V)U`SC?D@Ym~b{1jwCi{5{w74w1stdN8nADC=t=JC+aNly}joPg!i2pUipDlJ!V%5%Bj}Rx#LAjPfoys>H`1fBMRUfqq_)F#H*x) za|0LUTng*D6OZqOMXeI%Qf)WvMojW@i1d-KWgjRQWumjW>`%r&3=qAHw-HRA#r7(Ut(Nbj%?>uI7Qw{wE6{2=J(&L-`BjGjR3x!QivmYj% znI4WPFRQU__D7Km?dNhnN&xrF=8}y$mKNxoUzO*T#sYtBfhjB3xT5G$#u_KYAF{HV z5C1?&A>rTO`JEjTt&T=NYH1NT^EEkEhz#7=9!!bN)f8i&dm2tASHZHHCQXw^D9sav zU7>owBRHz|P+-t!O%$@{y!7rlT)mX)j0~wW1dQPbltRvJ*_1LM=XGw<2ax3HfXL^@&=dXcz~)A^Q`5?~`&PU0sM~hY zX=k?SrP{VN)g^XxWv9iAW&29D0wOT4OC-PJ150e-TId03TI^$cM*mA!eBJcu1LoP# zjKJ*H+RJQ*$oC~a`J(^9N$u!TwQ&RCyTF&zrjNw=*Lj$QHNi@*I8zdqW*~)PL>a)2 zPu6S}km1OBuW8mXqqR$+5j1*Zpp6YpGFSD zR?|MAe%gsI+Ia3uUqsU3^V$7ruh0Wn$9Ot=*c+3SQ78V*;htXm6DzXFkF4Voz9JpM?UW?eJ*XpvS$Ugw3d;`L>s z6bbC$S0ROobrInp3%!!OYlWlCMg(OGD{EO@TNAskWg+&_mdz~|uP&b%<^t>b% zF>2Dipim3eT3+zS&8&o{#aHWoz$y=fX|;_#Sng$*3o6PMi=W<&=vOCFWKLzOK0BCz zSrur|h;Y)|g=mcd#yz3IAa}+BGfKbGex|%X95++AG!jx8byL`SVC@>=^RRUC8sVDn z?<T0I`?351 ztmM>2cP>ug?&gTxDflk6WI4G+XEyF^-nuMfJv6RoH8Xc zx&}i_sYG`btbcbZNTViI&7_$VH{J#IpcHX}(!jjk-AVO-zkeUS!1)9F0E3IpNqksh z{$sQ2!l>=pX0fU+gsoRc(5z@=;?ars#kPmkMW2PlSF4n^v*p0d)k%@vp+y5ChXv1;rD@dK$9cS$1Jwp$08?y4^7%%@!*TJ*s|X@2(bh zPiCL)@HVK1!wz3Yc6$+7e25x)B{Vfzl1M~>#4V9viX26Y9;|y4(}6eqt(SX#68X==nb(la&8u{gFiO zXru!oNu`j_>J#kKtl6zb{CHve|mgPRq>Rh$sD^PlOiFc?0^Q7{2BzVtpud zKIma?b~3%#wU*c0^9^(Z#>1Wo_$vb1Mz?8c&=k?R+BiSVhu3Al7Z4H_{KkS->5|5H z?oDuD!H#iTK*NGOC0bcH_m|>Ku4N0=4|_OoB#5ejI|6~M;HW~OC*7Yj{+7lO$)Wg4 zv1!;2uAxV&QoD?QWCD^h6xqp1-CAfr&IZlR*n$7?;Z~n7H{$3nHUwpM#sqk z%~q%_d)|^wdVWFFj&MLTw{gz-2I>O+4FLj^8`ChW-kGRhBY)w&L>*E(E^v6shL1dJ zw1wy)bpw1LlR!FQBJECMg!!Rl9A*2Vdy(j}tO3TnL^?j|)$Jy3i$Fz9kDo}*Rsmpw>bYN zwg0ch!cC+{^!l?;JP(YSJv#H^hF0?ifbYlcX95jpe#XhR8BX zc9ax1Qw{Ym3Bm*?7TZ$WtWhSAQBShYk!?MHrm>!oURw%0Kt6~+KFmn8nyR-lU11bu zwBL9A%W2O<_W%4G%>$a*OJfvcBp4u~y&NU3y)9cA&=_#SqygZMQ0tw@TN`fn$$q)e zM04Db`+G?bT;X@&1xC7V%RLjK28P;Ta@ho*ivR1+LAoA@k54m@s>eK}`%7sB&32{n z#2%Em-dv-j*uvr%6IUK-^Dh2s@Kgk8>Pn*lD)meWD%wfN;1N|o2! zT!0Rvxiz=H7~0Xql7YJ=TDoP4Kj~1+G+LI)%CgP}k!pguz5vVZ%BdySH2Kr@n~4d7 zO_g-uO4^Y7>BaYDqYW1dI$%1%?5sNSw_EGMI9On<99Z04AWKS!QyMe%Tm`zxyG3mf zdE2Y03ppckQ4MURV1d zH^`vjo`aq*pKXw9?>U5BUb@{Bp> zq4rA3m8^c_{kN^^C*z(oBLN}vJbeUFmkrugbL!k{gFok~1wn6-T?Mn8f$|74Zpuw8 z91b|vsDn-*Nl`c*^uGx}m@PC<*Jp0@^KC#dqUS+Rblgotu)N2CGFIN6bH`aAMo~w) z%R8LI9-ttTtL_h(57B`%C3DZf3fySbK}Wmk)?X_tu>lU|o)F?a9;}@MNGt&%L(X*r z6n%7Pf$^6NajMSlXG}3rW-9IuWc}s)tkB%QEmPDCFq3A0IUDcR&GJeaPqnfE4xeJh zSB1YRSSz%X03+_Frz01wjp9H+IcZj^2&k;0VFPa`S9!vf4@st8p0gSN~+x#NXN&VO*pAB5uU z`Bw|dulauOqTT>eclX7dTueLezU{PPD0`ZT5D?hlgnGImra)1*$JcPSzSRucUYPQbrG za_tTURD?MH^a_3qr+%263p+Nq>p1Q_SQQcRRhV%+u|Y1PZKj zJRyDNkimgTR2w3-`Jg03iWCzg_eZ6ppfKzm8AO1RGOY^kvrAUDB?F?>gNImELueX~ zCE+@&e$fyKQ47PXG;%_1l`-omV%3(zDYuXXPpD2oP&mbthT=#ZQYB2MMvzt<0*0!L z+|K`lO#5GfNp{Q;3DD1u%lK1urTlLKlm9zo*< zQ13xm~O$kfc%_lYM5?|2N&0@%iEP4df7V05u3j5<;YH zC}8U8)IRX}dKKk9ndpOW9vZo?h!Z;+%AQpWzxMR`2SBWxXkmT;?kQWbN8GMK3HPEp zDR;a_V0s=Nq){I;C$TY6<2f-)`-)ixE}`1sUmR{Map6RZeRmgJzctZ=M0c@#;l#A%&%lU3oMA zo3W|0v;F_-5W3=l_E7%2z;d#ENY2ql8xm+rWy)ZR8ejOwg6f76JzljRTqv_OfwjVN zVm~mlyc}>d1dfK0s{zgdHc$#E__-HZDDOX9woe}jfc>6o=dfHTwY+_Oef8g&eV%qQ zKh9<`pW$*&O~yd9UxNVp98$qs&OZ+RduniKQq1DS#Ee;Dxhet)$$k`PhRwdxZ|Yaf z(*WMO#008+wu&9MH!JgHGgwYnOx!O7yWj@2^6>JNO*k42^F_;3x+$@NJNV>(TJ+a9&Jj|aA}fy z)MUds3B!upKND-RMS1+y4^gz19}hoLzyB*0t-*$Na-_kAcT&!D4J=jGgf(K`L`)g; zhk1)#wAenxdR)rl4&iLh?2hhi&XU=0K|Z+|ZN`{6ZVSN5nYJKrJ2rD+C($%QCqXPS zqTe&^L=h{oQ5qRL8E|%Jh5gj1H3kaeR@-gg{EHOUn|Od}W}6b~%$i*#48#UGW6Yg5 z?}@;hcLvU#d=Mh1^9O^;YMf=?sP-KtmlET`0h#^~o58d>eBKmWZ{`6;EDB3^oQws} zBL%f?ge=;ETsLTixg&P|F*=p`jiLx=wbRrlZ9I?T+<{_y=+x}#1s#&!eZR&7rzjOS zctf)*u$>2UYy6a6%$-GRoc<$fo)5crp<=FEN1aXj+Ija=PAA41ldtdeHwFJt9^&nZ z@JoGYoCQE_P#ihid6Ov5J9S4pVy>W^_!n)BQ&{A?*9qWL^}3z`^OT3piV>_|4a?2j zjHFrCiYp?;#I$~lXW|MPQurR(DG^&5r?P7#QR=)&==x8YjZ`0o*qEG_oySz*W!4Lb zb0B^NNymvgI)J7EPEOq73>u=`KHz2vY{fZAO+9`nm3sQ&Wh*6R zJQ>P2NnJ%BxN@3*NxTO^SR;qmk8Lo~h!z{?HI#TOyJDVv;(hgPvJz%5wAhh{{3QVcTU{9=}H)7$8%x72WtsKW@G&rRNo5#TQEsM zr!dj;$ADmiyWTmO0w$EVbT<(fK5vO>d&D-1{TR-T$3<3<*;=}0bMp@ug`1uA&V**Q z2|@G(Z~}OL+X`6dc_q>ZRBz%ud5X>4d(fDumy>)Mvc8e-@1`B;6>yUlr z^WfGLYDZFw4a0?z{wk7+-Zwy#&9tD~QeI*%9C4B``t2q*(l&-e37@9eEDVh-VsRDY z=4(V3GdN~F@r}uA41W zHY4w}rut5tjE;BQ%WspwQ5wNPg%)`rE~`^GSPgfVk#&3^RAB$qjOmH$L=YBd~q z$#AyGr#<7qcy>OH+!#JN@e3ee!=Nreem4n%KSUnq11e@5C`IfT8{@3Zf^N0SADp&vc{eGu@~A z(h*?4n+0(_(gx>)^Njg|&||&Zd&>v9Q|5Q@&G`0bJ}ml)`7M0jAJcd06ji5euMFaP zaF+EW`wRoyZ~TDgUW~0yCH3cpx!KFp^;;YLZ{<$2OVuI6|lhvYhY*%1gnMgoCWI ztV|-x^HWIEq8-5YQRtx-k_l*70E7Z%Sw@&oKl_S}JOb*P!cTtOC@8up>>|nL8IY2} zDxWVS`|#!W zw8Ab(YY>I^37-_DzHjoxek)K!l@_NZ^?w+x;1_r_1B#F~tUlsjB(F_g0JeU@!~A zbqd2{*@id~G;CO>e5+g4e;!Hg&GuV{b%+$9-$Ymj8P!sq1!;IWTc>yw$vjfOYk46=Gf5siFmvhW8FTX7H?I3D9~Peg^HiWoWwlA-x82t;>{rjq(>d#R)!b8LpE5EYwf%Z1^qb+Uj~=18-q%2Bx~ za+NR1Ej^p5Vq$bhA}b@r+AbZ6&q=I=I>!Oa)($?^W}I3hW6haTOza84+p|UWv&O_@gx6$9A~CJrE?+(zRB;{h-Oke z{VQmolPW4+Ns&*cK6;ljhB7kny+I?KPXl{@97?FheE70Nz%7+9J}rC3ii_WlD$jGB z$VTMxT84B&sbERr>a}R4A0#vj)%@~NK4lj2+%os6sqHCvjrDpd7xQRpjao)TtY~9Z zQ=GTZsGg&SHmd+pme~~S+^ymb=R6$5weWD(vL84+Qo7hI>`(_vE!Z64G58m?G1!K| z%F1lG0vOl==Ft*V^v8gB(L0kC$}Q>&PB;Q`Sxbh5nHg&mTvyBCTn-!`|LF=^E@_xKbew< z7EVijR-sIX#B=DN!Q5QNye*am95`+M_LN!`H{X!qzYPYl`#yX{)2o%VGy3>V#boXg z7Z|Ml#}mGIoW%EtDxqprn4laiC;n%LG|UB$!m>RE2#zGJVcc1^{Yhktja&Mi1-9@#P@$pw=+kxjz6 z>U&;ban_)y-HDT2)4>(jH;t9nLHitj z^jN#W$Lk>AQqh0MBJhQJx{6#k0hVew*$Z?#e&Zic+<8`}RpoN#s(1?otJ9K8`#(iG ziKqI4*QAHC%;H&iW$Uj$1IPE1gH6-+3)xF68!wAdHAA!uB(4d;Nntgsv`JYVGW!|* z$Lz3=a=PW$43jCxhF#WjhDC|J#PWSP%DI1xT_I)jAlM&p6=o5oUHwZN{cf%G#QU>^ zh~$AfUzdX&CKTz{z0}PNjdQ&dKLkxby-*)#kNMgn{of>Br;-7V3hr9zDZiFJJO)Pl z3I%HH8=YeX8F?2TW`3jgI5}nT^t}pQClh^P6Er^5auVTz7A-UR{wtD%;nnfG!0^WB zcN&(2rod!(p6L^KKt-~J9NtFZz{@B~aL-Xz)id;)GeS34Xv!4eZ0nmIZRrwt;(@WR zROvzC9#O%5T%0v4BJFpR*io}aEhVI$~ zBK04EJ)?HX)FbxIO>=+KGIpT+LIOaK`5S}xFBegMcZoiuvhBNk(!QYje)a-UPs6k2 zwv zqIfcfvZz`0MxOI($deJY9^udUvmE2g-_INv2CYZ>0%k%zw~i9u%^uJv?*QH}6}SS0 z0LsY>9ZQlf>cH2J9e4t@O_uL^RUEx%BPw{mt|=mTa8%58Rm^r!>~rcT~(*znb_i5tr8=*tR_%#o>N`(rIeCeT?1U*_?cc^b5MNV zZDI?bTv?Xbl0u>SoC#_zH+oQV8fr3~N2q$gUjr$fz>y&?Tx=!792Y93x?_T$L#ax4 z;T1g2i#h##9=`Q@sj@=jS{l~cVWpi%OXTD@dZv7S|}QlP?@R=tE-p_NpgWg zsgzo&f3vGjq>@M9S}M62241>Q-II-#O0Fdbw=?Qa+@YG7OKAQBTgy;N&6ta8DxOLu z7VD6yk0o6KGr7Vdk#E?ywKJv(zSHv?T#sq#<^w?NSgWOxBYmK!&mpuB2EFtW>p@ zw~!wsv~7E8X(fQ*l5>!8kRjJP2aGi!L1eTES3X#C@5?G^516#DWtX~zEdIs4DHqPy zz=JS77rCiWCd_{$EPpFd>c$*6FLCJU0Has14~G3~rIBA78gkAJQ1OLBuc+%YJ*NjK z`C`;6eS@l3g&9P=q3YNRYgjGr<+Zvw1l53U+Dry$+k6_d*8thI!~}NQ9vGHfxxA!J z!#}Ui1gN$;0e09S)i&q@*;zSKTOc@TMP<^v~gh(4wQ1U;<` ze?FhGc6r{NUbcJC5!O})<)6~_%-^eSvU~|X?7l&MqlRa~tJd(XH`};aj20>51ctIh zFE&@K%D@^pU+LIX=tf|zqwtD#Lb9}2O)cd1U9T^u*VvBAtzV=UU5#w7ucVhs`9Q>7_NH4sc~)W^PT`@ z|C<_w%|5shIsxliJsXtH_R~4k2~Ojx>l>coxs^JR(%Ih(T;U`by~ycwtZ+u8cfKCQ z$$`8@-wK(0B=_jthF3r3yP@a%F}f7r<$KEjNaY1QpP_m5>O~-)M&11Wgz*vS1z$OD z+w=Ma-pm(>&U&D5Z2E%ZFYS$pyRbh ze<%fM=VR0i(t04|mPv2N!~^r}g3npdiJ8U?oBSIw`Hq;dkkw+=%23pllUZgU$B}Qu z*dt5Kkz-!AYL!uaf~X=w#I4>P~TPER}*yhh~b=WNigZ$b#(yblCI$lap{IhJds~Q zY`LbJ*dw1Xy9u**$zEZP7+L^(mv1#Uv(F)H6UEvsS(44GGw*MQ_}|lDIsWT^|Bw>f z{O*JNuTxlkn*MnBJJc5_d*cTtKhw_0FGSrYc%bxmUD(M zTnsOxiQVO7;;v(DDz{*!*DM0OFy=%Xu_4A795I?D%GPmOyc$6ZCPCYqLeG;pDb_k?b_h?O5bNo<>nTc zbE*q@J!J1{6&pV$)Fq9OI~wbo*j_qc*j&z=Z)q3cGzeR!VL`Y@fN0Q&^?5PjyM-(7 zkugE@BPH#TICA??l-?h3SnbO!Mc9+i44@mKx1!=-Qg?9*ChvkNM&c`m`t1$oQ;vcY zhf9lq>xsK$K<#-cMr?>+<`MgKmJgf^d%i?+5?hZ9Ehq*&X3*} zR+U(!y<%-(r>YFLdMKv;s)@jGjW5*R7hO|w(d;_Krh*w3DgB<0+HAS|%cZ^^9c5LQ z#FJ1%Vef%$FR)VOqO04HQOmAC6SiY;bTfG|y|*G{Zd6x5>zc!?wOO1^Z>Khc6bcqmG&&vMu>@ z-}WefwTgP5P_kF6z_;8Ck98gYqIN~O<=PM;?*B8w&@M!$LL)5 zMq;X0seWrZM#zw5S-OKm^+^p%^-NFU5sJW}Vk^x460)VC`0p#tP2HI0Oxkw;` zLd#Kb=ItVYoCkRXUA$fV{*Ys3ITv=x93r=S_&^HCVjrA#D@QM(vaxHhfl*qeZL{Gn zu5bU_+^?^^x@or7l{0YcHfg5IjN`1UwKZ^Y!O`Fqa`c!bl7pq(E4h?*{g|au@Vmti zm4>;#tyR)GO2i<?HP zCUGW4dC5U!5!e)Rjbhf(Gb!#=WIA;%gOCLn49Xfu==qWfCV-4(6itfT3)DQkl=o(_ z%g{-(+zZ4!pOpDW+XB3RddC5xh`*}SP5pv2rj&hxB&+lp2{-kpsJ`hROet1B z6P&jJ%z8e>GU)FqRQuwEy_CvmWlot!l#40s6IfF0^R*KhQnAd!xn4+nG7kPm4x5nVIl7Nm3b3y;h?%bey}n8;LG4S%zV-qCNP?D?vWG+SNv?b}Af=rrnOzkm7PI$wIu>u0*<@s7P{E@30u*r$AmA6mNB#xe@8vezx^4O616d}KUnp@ zoIH~$TeN%^=UJXneln{&T;nZz0YyJc7G0<-R4Kk#}l~A zM|;;<)eqo$=?Kg0Z0G754BG4r^A6+vvC^c+b=}iLq;8mvd4G9@x4U*f0Or6yycWjy zxRFI<<(=~CJ?ba%NDhl@NFCMOLFMHgnNHf|9iDD$_sq;X*yJ5-ob9;56_5uwECjW$ zj!xg(b@e47-tO{j@*WOQA%e*4i3UW%Uo8JS)m?6KEa}_KHKAsT|Erw9Zrp}Hd7fcG zygkBKWGhU(HkpF}T$U{fJGI6fDro3#%9$mFbt^;ZRYpYE0Zx9pC!-cuGyi;ik{wle zYhl*#r@NxFJq=$s0!mi>QRHA`{Zb(>VLktO*rK$90(sfE+lzX_*m)rrD;fn|Uz4&R z8owt;5D*G8V#XHJkWj<3u!)w=YG9HY17>AyMg9_-oWRa(!kI0Bu*jHz#i|673ru2H z{IJSdZG-MG8pF3B4AL~ZClbeM1f#-e-1IMegk(gI7!!Z#08}iPS7se=FTJ3Q)Zocn z%czo2Xc9F;#wc7ala~*n3GJ*)kx60da6Fes2CX*$T;RNI?}AR(FL;QfV6+AH4Z z^JnRLbwlqIEJG$WP4^?7#w;#v!TZ6aK&%;qyLp%OI$x(yCTDr6NqVQIZJ5$vWBKul zc>pT|WhVI2IWtbHEEsEPG3a$*cZO6bLxq)}kTFFAo#Vv3UFgyD{hf=-JX%YaUR`6a z&|#{YCs%WD>N#fLNjVa7I<4GmZHKNKGn&;3M(kirceryL;bVK?W6pao)g&o@^@xsr$ zO_oP9&zcib`4#)yeYCEL>E~0G*1s3G5})YQFdJQ~QHBt&z6@%+YzzxyfSV2s`(0TE zxr1m7^`hyhX+kuvxv!?xyhzW zSDRPuauIX-nH=)MeyRkElqj0 zG)>}^^!ce4kDPmaW&(D-1g{=h&r5MK#b%+unvnc=XEhzp~cU@J&*hzMriZ|lhll=(Q4D8|9B<#g1X^@;yPPw9vOG7dM6iYzA#3m&nL@S5weUUF_YmNr)G(O(Pih zbl__v-kx1+vV9ENhJB@9x{2)C-6=Ym>Mp2;W=nPz2I@DB>DA6@(bGS4_LvEWBBOg#YI;xSFj;5m zay2;tv4Ejgjc>DeIp!M(vtX%G5Z=8hbCZ%ChRMRCo*3n(baT2y*kbTo7Y z>0jk!3y^S;*IMM|hLMijErJ=X;_OLh2J-!A#L1&PEhdoD81ibV%1l^E!@pic;E%(x z0BSF^jOgi%`i1Zbs=ck0O#3^X(Z1)2J4ergpTvZhDx6*eg;y^SjTDr$ZTDIFzd6;=4I zV`SsxtqWN8O%_#Z>xEJqV#?Zsl(xp@X_jPflAk~!v-!g!LCg)(84?P8&}eOC_a##d zXpqk3h(|FFC@~pAuK-!24hh57u|mTTZQE)KipEhb)gsC|q$F-l%9!L!v}gk}Bp-MTHm>s%V*i1ykRePod-?Rrk(Sy(v$Y9C;{g#dWWKf-)ozJ(l_O8VBC()0Csir_z_iljZYO?Tsu`TNwNr9h8*(pO$vuV!K@j%VAaLaPARt?s4Cc%}~ zpKLxvy!F2@j&$cTL-=pe41{`C#BNDFJZG@d3jeC8YjF*jIb1VPp*!N!nwcg#$YTl1Tfy*x-AhQ1^p#Bl1`0)k*&#+qERzXJ{%MYRR^3GB6 z1u7msD;`MJAV6U(Ec2ICAanr{SV%n3>#1pbfNYv>$K`^8HTGh0P3xKZ`jUmLwXC$i z2n8N|v{~sQmU*+XKj%53INs;p3)|b^t@lrxwdX&*Ydv(zsU?Ewyd$ImDmzb7&m{&=<*Tu@(;1WE$U$G&MG z<0KImR+s=`i3NY0yoHdL3&8ggEU-}|xF<8mIP3QiLUf;fzTHHP4Bn@Mxjv806 z94yw~!ivPyjc6buS*}71;Zj<~f4NBdx( z$@Ls>o{N0x;NZ?>KbMZBKTp77!Tg2FWmr0b7ac3_$cjzCW(31UA~qC$W_Z6PrNl0{ zW3W1Rc2Swy*JM1R;j%!;*FTDiT9nP0QS25oX<+&&weRk1XM8s=GP?)H$Jbmo!#=~t zd2JSiSjRiXp(d>-%Uc{3cT4Ep7fDrn&08dY4sXcEyx`z*8jT#Cb+by(Q z&d-!ds}MTMJP|4Gz2Bfi?RSqcd@D?D=+$a}$PfL@Y zHuvH1Zy(J;A{R?eTH`H?zl@Re40`i7XgVu5mJb$C3&S0Mi9fe z7|-f#U7>Z<$qdTM*mAqY5O~6yqERPOLWGyVaF!l;`il;r_G3zMF{5Q}mQY3-1ug~F zl)SV*l7OY@mguEt1@(rvLh?Bw~bQ>f*J@Khn+P5BPva&GJ4xlLzSocAePP zciY8pDC^bzN|>b?;>Dr5Pjnrd z+4+VG_D)#LtZ@&9<$Sc1)dPd-My#s2fmFurNlnQS^qB|36jDBjbHnAx9Qj)O< zotd%PxPBF-xO?$NnM_%BRHW>S8M)+(EMuchl!ML)ioSj`UxdIjCFI$aZA z*5m=HE-g^Wo2*fE{|{yFz?f;fWeLX>+qSKWQ?YF)72CFL+o;&8*tTsusTkk$p3^;Z z-ZRtP^ZkYEUK?xQd#@#)(?saL6aX+b+t$z6Dta)dAJLMc9oZ;wUC*rA-lI%mtt$9j zY+@PdhNxjxLL~$HW;5p#*mTdXwx7AN+=9nC$S%XgXM8EN6@xwrlshVKqA(+&lvY4h z*_k|aZ@tES;2z3zopAg+GAMC0(JH2NSvP!hNzw>KO|_5_t&bWV>;~WQ4`2NasMuA* zhZD6f!zpCr=lrDj@`;S})PQ7{tGItsT zI?Ct-HHAA1$*E91H2p|w;Y4b|2F*awa!lTGR8Wg5q1QY*@0pa(95PSt}#fO!;E!nLO$`DHVgddC=pC3e=2j8`YiXqEboa-n`<9|;r^yVz{!nK^6WZ?UZ{z9)* zt)i5-rc`*V)wmpXS+qG@O*?3`^;6C2`%qTyo1|yEAL`&}}-Wk4sQ5u1Nk_s2p6LB3ywk-Y~v1^6&yx z&;pcn`J27$X={(WT)6?u2|C2ley()erS^LQpRvzzyTbJOm_AM7w=K?li`2K<`s6HH z?LPCUw5O}GeJQf^x4A~-#tie8VrUYzX!|yjn2S_RFs!@o@0ZQAcBsF#a!&nFCVpg% zr`rLcuZ+77WqtJgs|wd&9gh4FJ9QyITdoN(HvF%InEu(}s2Vt!8~n5~cKqk?Fj`eh zNlOLw6Mj@e(8KQsR0_yrHIe^M^GLeJ#+2q1>^wAK&ub#wzFyY+w!Fnt4h!$QNi5T% zeWgyu81I|85QQPl?AfX3gJ;lpswLY?T=?CB;Pi`zCoW6x^L0yaPlC_q1yp5RBwDP#RI+^ha6pd$~DS-2?-dYVyk&5~mI)oqQIg(P*a)KW90zC!;Ws zRaLRrtRm;*Xwz12;VnbRS!_+`@R%F8lB8lo){4_Atz(KSvqI=BhuYwy?(pj8UAj_} zh(D?dy&jB*(rd|WN~?PNnwV&~iL0^C_R@pWHDR5jw%&^-S${7{vm~&gEV;Qe+fMmJ zD#VYpzX!|8__QeqQJNl3)7DH)HQkPllc?t(V8?${ol{oXlnz&YZ<`kXYG*!WA#>xk zjIRpGTUcRNvUu_!=QlStm)10=ImgsmR!g|AI%ea^7S}LIsZSSQ4e!X7g@@AD2xsLA zHbGzZPBh^%kDhO&j3Z0T88@w$zHX?-m_QZkkAF_$G;}FCnPFmOHzvE|O_)zraE$LQ zf5HYyG_k2C#g!{cE`UE^>3^a9WnLEBm=c^+S@65AZy+eiV7|O%cmd}XER-eKs*lS& za^XyE;b%(_)=Ibzw&thWAw;ubsGBV2N`y5;!ir%Yh9}&`Fg>Ww-5wA*+`!Dwo}nay z8XWQ63<7gdENRP?x|l0Wj(|dlS37N?{?>`2EVg7Ut2o)^Zv~yn$W*r% zQt6!JTdmTFV=INkZFsqyyw=536D8u?7OSm&W|5UC3%>1!IJW!Hx^MWb1z2=DP>(h3M_Sl7!}3}QMkvf?@!yVy|JIet zw|5vhbS0$M2Sa^Mwf860;6by2k1&ge=gxG7l)sC+nsNYyVnO>Q! zVs39{?fl1J8{VqCyg(D$uAamt^nNvUM-`bI2E)nDs1<>Ps$JLi<)V40QPTtU4kKJ8 ztx*C_i$d@(=AlKK5Q`Q$9h+PT+zrjs#B#sJUtwd(Gv$a&9i7kG0x^@;`re^ zt2E|h4~#QCS;%+AxiNtka=nvuQqtzgsEM3XvyKC!Ls^hN`v&RXUV4OR_JCgZD{RPx z$towXyR#8qr$Fmn6`V}Ps5m1<)>}fHKW-UB>kdWh&adTonkO1z^b{i}UC+InP9C|N zYU^#JD!wl@#qFd`ONUvv0Jbb-l%9d>H?%$&!(Bi^;am-K&gZ`!+@tA5)13mitP6n4 z{#O@S|CZyM)OGAoma%x36KFMbqnLIGjZkhaHR=m@KqPur{QMWf1AuY9?{FE=RawP1 zEmf+*lM_iOeTOqoC^64qoneO}bM_U70S2R!IbjW4A2l@Lnt$qeY_iR6+-~`;JK9{k zar$t0wdr~7diC--HTL;l!S4mF&*F1kO0*xW8Z3jkzgv_GksVq|0O6n;<$2pkpfd7o z7mg~1~tKwA+V){~` z_8fD4dtSlQG1Py~H*KU+Rg1_l-m>XoK_8YY{ZMDG-S+1fn!dGvY(E8K0oy8UN4k4r#%W?iKE`5 zf7HmG$yWs#X2WbHXF4bPtt$9;=G*CPF`2ogIS=4G>_9XWwNnmX(Y%j-gc9h$6%H(v&d6!x2`KtUjT@5(4+6YakXZm5T-U9j2Y$&W?ey=t`!O7F! zoAbnQav01D>(G4O+rKF?OdgHfB=;$^WsM=niTqabg{*mgQ#KC32f-X1z4>p%dR8NGRh z(~|`!Z~ldxquvrnup0r1xErFJLT1V@LMW|Tl|FW!9tZ@9l|WgBDXC{DA4xjxow=&= zvD(V3rBKI0$)Ocj>ij6Cv>x7jsM1B!w>b_Ws-(F?1+t{65Lg))V=-eDI5_cVtgZcB zZ~q;A%KYe<(e{KQ5~7ATt3u$j3IQl8SeAZ-j#k3m<5tRAb9N7QR^nKid?PO76n~_j zz2o(5u8gFn30}LQ9E1i8K12dTh@;~1o*R3-oP`ukV&ldMtHfUx*`CsP`UA#+M0BP> zjml;tJd-O*&&5IPUNV9N@RHAHK6Ja^TS<3G-c|dq?KJw(yl8i+t0h`vc!Es@;1ct8 z{C;?!I_$J=<{_(z4o5-xv`MT|f2|VQ9;u#9C{Br2)NQuY%gGP^Rx(#PWXDU>Tix6w zYxgg&Q^dznVm8U0s=0X)u~mawbOwDo-fU4z2{_L^l(-gNk{6ZeGd{|l86r>fggPtk zFsL-v_U7z|O|N{EiBc$fO!*v{NZ1w`ad+lgCrezicooiEZ6(E3Y!~-VKl9CBP&tc& zfMKOGQ>R_}Od{#0y^BP@I5QH6&^W`WSz~*p_%uv@KYY!+!dP8_+$6VvpdWY6-U?`*(k2{O4s+jx}Nn36M2q;6-v zA!{3YI&28edrthFkhoV)-X5=7{Dx~o&8!K8+bz~gfFEj-Pf#kqN^H&RP9SWWw z=RQtQ__p~z|Ihtp;ezFzE?_y*3^8Ni-yvxMCVYMBf~w#f*xyIyqL&D)( zL~VmuF71VJ@|W>}Zt6HH=%usi;~q};a5H=7`oQ)@rLl_xS&||;r)h5;ZEGF1H;dh$ zsW6%@-HV#$)A_MZ_Z+h&xHyY*v#fGVbgPOlb!K6P-*hZxo+EY%NBbME>9kF|!yU!h zQRoA#+&;@j3R$c;Ok=|UT`UzZp>xHQ2?fRIys(p-WnwFH(#jpF0j)T_jZ1rdgJu(H zzUnw_PttYWMQ$NS8G>j21X5XcKi`icHrZbidrM5Jr@!I#a%;#@U65gm=Zf=NjVH8? zT4*rx&7-UV%Hx8Bn#HfJLf?UvJXD37|*6n)eX6<%^Y2 zVQiE$A~9s36P$ZO&`OuQnB3==!Vht(eLeuaxm*-GIjZDQX~dcPa8KB7l> zvw?#@li2^3+2A9=pHE8eMvk18$svmL@4v5|Of>CG`URcw^wBN!1U~zQGyCS5K7%LF zEn`$l=dOa(ZY_iVgicsR{9F%NKIUKUkk{oud<}w@0rMx8Szhc{rIb)rHq4)CW_i%( zBb~gZ$>7&=*abo=ZS%4}j(I^XunUQ#NyYi>6T#(lpd#H9)@8o4SoD+eC#=af_&BGT zO}9dB+NlM;eI>)KE}GKb#b|0`g=DFh+WgVh>+X@cIewnlmKvAXAU5byu~aEipf)-2 zdq$7Gip_W>XZg%=-Bt|XG16k z&~ZyUliX$=Y6DwsMHZ6SzQ43>C9xr}&mAXvAC}|WzY`FxN+oRnSx~06+fa@mF)=;O zHm*(gwsO6+s`Wa2bYN@5Gs_O)U&#=gkGxDoI~Yst4WO|U*CFB>N!B?S!*?izsTkyQ zFviFbZjoRU-1$>0E#TJR53a50)vy5B`qm z5>^Pm4}@(s^d8%UHT2tRhz~gusVMvx0>z1I#GqTJJ49JmFeX#i7d3WG+M3=;1{`ZS zdH(Fbb7CZJ7bgOMj0zoq6aUQv`Co3=|B@*-W)N_2FmV50CQtv6-uWjxPFB^j#Zf{0 zjIp(}Z6T#IN6z>G3N@%f;cV8%>I~Ir1DbE6ldzLel)t$`@rd34pXpq55Z~P+5}`~= z3g&(aDy}c3EXZ@)6Dv4T+0wk<8dF8NpU&ynWqXvBZus@Ko$CwihLTAw%7`HVc3trd zw5+bJHY#0z9TJhrX06*BO3l{?QsX_bhn`6V-m==-&nSUrj!x1#zNQ17TZY*~?3tpj zWpYau2^&cU{sbnA*=&7LQk3ip4KllsqBE8X$BmK7Em~*AVKN%gK)w%?LUKPhRU3~8 zsl!G$pN`UsA;Zh;66H2qdv{AV%wFYH0GvpNy}q7lqA-*wVra`SOV?{8N*G6bSoA}0 ztnncGE){1^mz_Q0fHRxgIQr*MtxPkoX%AJ}I>;?N>~iapNE?;4x$$9xB*@fN3XDe) z>|S%O$Z>*pc+cwbGI{OFDUeQ=JIQ&{#pZy~6Ghb}tM!GKSSTgfLPukfHR>d9Im5iU z;ds8&*wx4jxRk8G8i; zNxCy~Vg;(a!=HY-qbisnm?4+^rPEK!{oriHsxL6WiRNXyq7HTPWo6d)w(HRK184v5 z=5FA*=9q)y(5kG`y9FUw+H*JPTT3@wQ#9&}HxLC*FuW>N`q8^rEWMmdOIXj2{*J>= z=#FzH+GC&4$k^<0#_@(k+~n=jN?F`lWj)ezvGdg3T(dTB zB6;0tT035@hTaoO_RmxopTABx@T}p>T28~9bMN|?8Wz}7gM}zE9z#Mx0&K{PtgIzy zj`=XfY#vVH+_HrwVnq|PQ%ct-FC6!oM7Nts9u{Q^M*~GPgPgEI6AS?>0Y7|uBzV~m zYXnc`eS4m8IKAAG4`6N*vjPHOW)O!hjZT~3Fo(f*ELbzZhOyx&E{&o`-w*Hxi^SNZ zay!r$d_%97xkN@bUt?f+)nUqnzJ=3@o(CwVJ?dA>!-@s}^Z@@<&1xghlEy?JySeLoM%uL{v4c@`eG^ zGhzgqp*}J;aH9))fm#+fF3_)0)F99aw#U1E>6DsahM^j6L$H~u*NL~6m5gH-&0|!` zZj{EUOu%XGi6o$lLV97jtixrM{PhN0w%39fvm6C>5$Z(Y5fa}648`NZH0rF5`t^zF zqW&W~Ov)`{ipuRHlt%cAO4>RTjh`xV zB=G{_J?jf7E!0ZqR-do?GwbL4%;h>$i3^I5Qj5m7F!Etr^hd-dPlw|24cq+&^p|g| zqSp1_pSCfjs|5c4*V8ipS5LdPwp2*y!2~y$_kTXE7X`xOe?D!>&%l5y1C!6(7n9J< zr`YB1K*KAy28HMO$N6%0)57!-jsbYE$N?+~D6%I5#K)IwVkD|Jzm#Js!sAPWT-uKiLwa}ky_6!x|OTGj%O8r@mFXU!7rQWcVw0~!kzI=I{``-ZUC;gBFZ-9) zSW0^dk}UwRBY;BrH)E3jqeu$bTH66;$Bwo(|MIlaN>aA-KM+6JT`Vcm_yqMjwD1RA z)=JEAbg6K|fK(!W5K}6)wT&jUN?z`)@H(7ypCJ6u=I|5Nf+8JACkRf{`JFGRJl5O5 zvj1}Q=Hl|Sd~M4QgnGjmXg^WP6vW+^M%>7{f_0!Dt}oyQgN@E2Zm2t)pnl&+droC)SAFM7nuzIoo9tN*jqng3YQ;CuDeQ)qSzn#? z8wC?bmaz7(n$KrO*{WgY%_n;gFsckJndpv6Ox!B!6C)-Omy80La(Oenrr4f~4PeE` zKHwwD&$j-FLr1WTm)}V2}2QawA974%>xzMB;VboGHy0tb0^+rcA z`6q)_z4)<@0Yth`%&lQqvLufDk)RTvpmMJ>lm-yE3e=kTq5@PFwC~s9RD0OfC~PRE zIpS{gWWb4yN|Px`uQ_z-51rkpBo2CHC+fqP_@j@au+nQR_7n*vH3=n0u0`Kt<3@A1 zgOI-S=i-HXi#!(|5d6Gwj5Sr?8>4v5?EGvoTD;`{J9cds4pqTGfq=e200FW7_X!t( zU0X+UCu3n-XTZOYe*ti^l9U{Z0_rC{%fq339Z19;4BFZ+c@bUBA8&$|)R?+ZS0OGz zM8!($zxaW^{JC9hqHr)W#3fjnsy`Hl9IqA>e?Zzy@ou|&ALn>p)ogG30JVmi0tYdk zg?=-n9nz4lwVsRo2Fx=+8pvU3&rkvaslO0v&S$F5^YeBk6f9SQK@mifI2#>N!apWS zr<_Z4RD&skO^K+l%+J=Iv#l{soQ?^f_}z=MCCNKp%eWH8ZEiK$imRWJd`EADN6zSY zE*+eG1APYC#k$IDEaC|a!tpSoQRMKU&Qv9ixm_(S< zIGNT|RG-Le%wbe%NJJHEAxVc3eCnt&fm3Z=lZ8eK0vs~P!DWlG8WSzjzQ2qMM^$C# z3JQ$Mv%*S^ZkWeSAoiu*1eL0VJ8PYF3$w03K{Ix;#yZ2D0^eN%xOpM{IV^X}pufzf zwTgOIJOwtU^F+CFuKkA^$6UgmCKXw&*)p}e)c=hxyAqp5jocw>lVYxOQfJL^M3 z$vrdd*EU_}h#BTlXRBRnw$UUt`UEtcu6jRhPOaNmfDJJ*_EkW$@rhgeV10UvuEq;G zJ13+^&s6_>fdckny#}@X;LU6=ZnjEc+jIVNx2>a~mmY_6M<)GY{x;O}OyvCuNGEST z`vYRvOaKG&m340_q>fFmcTi2^P6fc2Hu3?nJB{a!OqJ@0+$O$5rcAt!I$P%zKL~$Q zBy+0;MucE3_*Fy|n{YMIC4mIhoxmrGIE?Ac1vl`0chf5f3AkveL(pPkgPiS1bwrYT zUf)Lw|FQVtgJp4#OmiBucCh-}1e7&vge`It7pGevjjjX^)Hb(mjTo~Q!kjcO6( zX2UCKYudu2?*i1C6r9==SYPq{7kRUw%$=QD2LrvDT%EI=IRo-#9Tx4c923V#l#aD1 z3uGdYu$;dT{vK6@{2(nLfT;Qe{7(GuY13a7;U7^YYGrHS^tYfIRRjbTZ>$aTs&G`i zfIYf2mtc}cpguXPs&FKcO1q^Xj11f9iqkvL2dL}ChPsWmS@Mr$RgLNo%5hJ?!y8mh0RupjQ7kqya{JQJ}y4Dy8kMxWY1#Hu_itVLj6cO^Czvd4kqErs~rT z9VvnUk3e__BH1jDh{)+*-J!Jp7?q*MbP@6k(Lj>0u`xkQcj71&3jxKaR#BIpmzv+C z5(W&qSn`*=Q4%^N13H0`6io0Q@iz$Y7~UqlegZck{W5LW>^~v9)y0#?s4P6=zlv8` z=I^WeU?=U*N@yCoqcO?4uqsU48$e=_zu0M?Y>h`F{4!jZr2Y4eD@^EFn^k38SJj)S zkZHJ8`l~Uk2V1d}JK-#~2)zg1I~r76o9U+CtsQ~yHTr9R{ZTIHFz5L`*Q}r=$FIG~ zTA@q+5(JHV%5t60v)L0;*SSlhf;@^0&SN_2Shd#vgD2j~^0sgRS;GO_W-+Tp-F2Hl zIod8UWSr8BBNhgmp167!*^{d~VE1dy5K#n<1& zCR@<&L$3-5vM-i54*l_l1e79oc*Xnl zhYx8SSkZ8YpvS}p5$};Ir6fbi=z9Wl*7*6a?;|I_yq&J}CBMRA7SzDZR)y@o38Bir z``uxC2PqT$V#ZV67F5}43K}X(TZjCa5@Q9gG$I+#%cmk`gul!vEeOUxSd#Z!xxZd+ zRw2lVitt@9ReBero3cRO$R6@(COQGP<|TUaHbBq9@kG+m?2Lst_Q{^Mx+`svWXqiFWoss5gfW zEAL_Ie{vCAhw*&WKOhaSrHwOpt;k-gpEcl-bE{fEQE$O+!LkIQnm^MpiH@g_vtC?E zsVdR1wBITCQQc`#<#ferK~vwG&@)RpSASN)?4+aLzHX)U$7HgDCH^h^kWI$r7!3Km z{#*#!2cwNY&TJVbn~owb0|PuF+F-{v`a)mH6<>Y=UT1rL)zOJYRgyJ#?5&RV}^D*PYk4ESCzkxbabC}YmoKi z6^e{e=-CK1m)MIdWE#*# zBUt!_pa>ANuS`djaZwOrXMe@)3?*|0YMghGM9D>=8mjvZf+HLjD^sxZs%|uU%sR{``jE`;{gT7( z_}`teh2YKz!v#m~d}|Dz9QgJJFiJ^l{oHc!Wr_}#-$fPp@>=ODY&!leYB?^?J1qfG zy99_@=Kr_$QrgzW^j||(fautMh4;DZ@zIz;T=RY14HYV3j=0@a6rA z+k@tnDFS~8t5{acw33EfQBs#A0;d8oenD4iU>q;v4%_1Xkr6#Z=6ZMa*dV^xAvWb83sa8H(yC$Z!KNdlB*EuMuVr%vn#(yaiDM zr^i*$|FW}~z3+@O+Meo0(mC|CL|+0!C0VfpmtD)bUiyZxwCOXhaji&d`VFu2_t69I zP=6k>jr%$Xj93zTz_(8Qb(qcP(9(@u2-#HGoU!$%>`>Xd^XJUL#XoO06trkvr9nSl zr9I7Z>3zpnw<3bb@4+KM3}#^8a=Il_(-;O~glCZvelVW6Zji+q%MqYA^_VJa4}GV0 z(pF@Ol|X}`EN=}t2T9#Jf|)lfqr6R$AxKiha@&M!kxR@`n-z|f$%Ol(i>mB38d%ny zQ@QHMy%no#IzXoNBa{OEF+Ahs!K1pHh%uLcBcWdhTapHEWV<_=BxTM9p>^TC;zm& zu;|p2;}LAR(Kl{Jk5FWseol^2%-;xA{4-=eC<&6vfxGG*nC#_P+)OrtDK11pO_8iU z1CLxwZg#u zy8vIv{(?&bg%7NH*C#uk(yKjTWv?v$%VnLcD2^dVl*Xn=*H3JP;)7Y2C_w^+jU1H~y-NExTQ9%ofWu z_s&B+EeIAQIw3}$NlrY-kj66Ib0Xha@|`6hw9%$C1A*RKBOuG+#+r|lSAdv0_c`W1 z&T%|GuBq7uzS!#u;8}8rlSf}_kAefwRL6)RrTxL z5sT-s==51|RCEH0Y6xkPrWf}rtP4F(iV;WNCV-VWBG3=*PD8?~ zssQ#=s&+1HfD3sF1Il!jaXa5AO{hptft8QM_|s3=!mmwfWX@Ck6hUc`c4WaZ{&TFs z;?TZ{xw-&Vt&om#J7<=fX%O^PfnX@<3^Gfexo$aJA*^BUyHPG& zJPjqNHYQSeuzUSC^=FQw$$^zlsHwTMd)27+kAKtiPevLD{{cXw9RQ8r|A#{IA7~UZ zGXUJ909@DqwVEhx+8_&{enK?UR<0}7@s~YotzFTl(5V(em0%{%ZgbLK)$065u z=xs3YdsO0$go$Pc+%AQ%rfJ2YzzSCn-X}S?T_3a30X`5u-{kwe;moay^9UKL ztkJl!UFzuYgfv5-m4uMBB-9l#idqu~au!6;*!vZ8T|EMN%UnRa7xx9`(U}K?mY*(8 zX80ZjXORVTxQs&vNR}P@g+luHG18qOiub;UQ|dVL-WENz69t%d%;t-ioN;$39sARK z*vmt$Us3h<>S0oMEn^5!W+byCw4%s5Q*J%Dg^n#ppFv$a{_gKg`DnB!&Z@QQ$^+xC zCwto96sn(;TQ9WP4{?|FpQ#Dd7+6b76sFxRmc;iyF zR~Rc^Xc3H_I%dTaPc%Gjr54y zM7NNBJ^*L1fi*zuA-)Og!k&|=AyTvnq5T%`?SXK|DYOEt*9fNw7bA^kM=|NeFx{)} z;sL&E*fUoBlIZ|6e_kB6{wZwv9lqpyKWrvkvd7dM39sq6+{#^Rg!X`_7H&f_RcO3! z3BR~HQv2&8u4*J9{>*Q0Oo6k)118c$&ur{qo^fxXyBEY?QS3dzNO?IL6!Xl5%o4-5P#<+IShbRB>*Tj0igV!hG+i)%KyvoY~2Ph{pHPUwg0(M5~QmL znL5|lgojh=>Qb0E1c(DE4cInoDcFZf#=Vf+t4o_mEbjo~5% zNr92MjmL@f+li~#T)i&fl|ejkcdG-!eA-GGEG_8fIx1Wl^$b`Y0dyPK{P;3}dT7C(i(?OVTw}f$R z+wr{FKa^X4lXG7$7SG>xZC&5el-d36+?Ha9_!-UBEi1CJkA zI2iI?I^YjI7g0Dev|x&fsmXL!Tb1wo`yE^l@Rj+9J_#H+_%G}7mATqz8FNfU7UeW- z#TD`11XG2GY*d%Sw$eV6v~!2=$gt0TsfX_-9?d`sAV01D7R1GZ#I06Ief0<+RH5F72kZmyUuDz!CBhh zdrGHRnA*GIBK%VR9@256ciq_s6dCOSM(_%-FUKbhd zI?(&;4P=90J5UQ$J}Aw?>PgP0KJv?Xv5H6{z44@4%l4V8881H7OsV0WwELYynog1N zMPk-bfs-w8r8>+{TBErYH;n(87;7DUx-7(4vkXg_WHDUjq_i^dktSnZx%w;>L5D6_ zO}?>KRPi1gFh>6c#-nD_sfnq| ze}M4^))T8yZF)#RKx4DAmE}rriW96k7PT}Sl~swpgig|)D)eu~ROJ;|N8T&Z0E5Cc zxObOnIvgy|B!8a@GUzMx|a{pCq@yjLf7%_(%9nL>6f z3b-##6{k;h4FmJ`GlA==+%qNROGxd39u*;#uu&R@^JCL z;6vw+az8e__yjZcnP@{QwD|=2I~;|qPop^iaFhqY@&A#@{QD5%e_`<-MS9E6j!H&L zZ>{x^I4>^B`79WyE^c z7G6ga7n6_s<>hOjM|(LTd>l?nN(oD)!IThdE6L%wl>EMhxIt0$l!azgZjB2`9o1dN zi9f9vFd=^|zQe9DA!xWo1P9p#_@o&^>feWqBeWT6Zdh%CETS;mmt zTZTj8+lPxK4z`#%(9I65eh?ENJ8PwYJ?xezfbfwEiZ@dM?dH9b>{q5 z?-otfX6-c_N3H4(j%&+%4{l~I9qVX5kp|0Y*#j4LqMa%wH@+zVCr;0Yu=|HHa|s6{ zBdT!k@B?IbG4a`NW=lX5_1%Pj!aGn?Bm}Du2R>(~e5s$N$E( z@4~fDp?$-PNa6kQifXxJT694mFaC$g6fyDF%Hl6=uD zxX=Qvk8$qaDKILzw!(JWtSM-Z?;{lfS<)L4UxB%8AzWdkVGqDz5aMXeytOfr&j1|e z?H?S5bR`gKYA?-^S77t?-;7}5z<NXG?3MX;A658b{JlP!!YoF1PFsb-A;%RncyXgLWvMcHLx_8PHiml`}n*- z=p#I#9@NDL2G!578(UGW43#jl=9@D+fooV98HCNF?x~`4?^TY}VxmJdM|WnU5dxJgGa#bD`Pgo=gL93VoCeLE&7gG1llbVe#bVvA6uvUiWb^>rZpOdimNZ+z@;s9mT+KQi8$12(b zWFgsKXVODC5j3r1wR~EAg(LRsJb8*uT|MUj?VDDT0Ud~viodu`a>MP8_1f+k(^g@xL{6$|{X}m=qS0UR1m?978UVy@-lfiaq+n5+lS_1MQYjHL5FdMG{IIMbi(--(=?-NvX`w z*{`JGa!e9V!xaoS!{-+norIgQT`9|jw!{h{JZoYUCU%KIywYE!_+1+w+% zg^bE>N6>6aazHTy?R3^%u_0QxLyZ1OJX&|ndm{|zQNlmfD?f6rW699sR(-nF8tYcw zR+rz(V$^7X@lTGAl9u)b-A{K8n{%d3NzjeR-aLS;=aS%ct*>IwYHrvG2pbVeb!-v+ zc=(iob_T&(2{7uYXPfYzw74DYdgwchT@=crYha z8yU9nOb#1mZ7gaXZ{9j~Fx8x?##&z*{vsVO{!+uN%i5e zpKg{I?mL>I~wGR3M~1nIAz+KD%62dIfsfU5=E4C>~R_^D$JnB zeB&kbsl+&tyxkQ+%|^DtDWwS;D%5STaj-+?{CIz6zM=&g)bz+ohMlEYqDAU?H6|WQ zdaP(d4xv0%Tfjip73UaAS(WlUxhu=~%SG>?ChMc^#ugywcklTn@Z_)yGtM_xZbeP$ z&kTO6*@%n3OyS3AVBAbtjIKHr5_^K})uEh15Y6n|V_4u+12ojeWWQT$@RF%LkH=6b zs;U#Pwl+DVo)RO}L!s%Mxa@~gPwjR@087K*t|}-MDc>`7 z)5-h5r;ru_5UQ&;a>qXl9r-a2*^?lHkuJcDlmd}q7L_fnse zBM_&`F#98Lu5a(X(Gs733?{bj4ArPq?g^ny>uV0$-e{ps3!<3O;+mIyaie{|@x=f9 z(b*C9gwzg)sjyFP&#kU`2L&c|^*bx%4F=FHHyb>TWcFz!JdY(BLDE#GCuqKo?a|o< z?%!+wc2A+!U}j647}4Ff>s8XiYId5O^6)H*yG5o>vDiS0^s~kJ=<1tjmh=}ALHquw zOqOwO;dDq@U8CwFg%%?m?bIK`*QWn(W>RPsn4Q2ed@HQulijjQH-tih!gsF*N4#po>K*IWR0S-j>fQ!u)0;Hz zo^?KfK|0EqP+ncR9XWYEonCw&58laYlP7HI;Z&ZVf4aZagDD8j_6f*}@v#X+(V{~Y z!b!?XThMtV8)N6!pm2*bwqljs0zBqe9-`!pV-?80{|fQ-Z_FXy3tSQF9!BUD(xe!j zN*&2AJlGO4nx3?YpA-Y4!Yk$^Di*Vky3sfzqYX`xjq6g9)FbyiY)s^mJjle!EZg_whIaLO3X-%pTb;dD=E+$`eu zn+GFn4Mq#C9u-`+3Gs=5<%PR4(3QRh%J49;KY6R4an8(lW=17D!4#Oj0?Np6vOjsH zb?P@c;lPqae83gZ+X80YgpLsMY?z78%&&>duK?@(F%!8SLcdQV4e^TISyz(lc+9dv zkmSB1i7-6c+@i3ZGD;VmYYo_Jzy7DI*3$#qysgbAe9Qy*9mGGex`-Kn3toGdT z=6LYV>F^25DS-9V1Y0b}Jc}u*#FbpK;DaHlvtMCW8a!bnlwrDz{U}YxSqAh@llu%z z$=W3w@0JM3fYNp@{ES!dL|;`UU*07L)hd{Nlkc=cBstmvs&insl$@VMBgCl|V&t@% z%rrLGNRxG!^-!&^4=3|7(^fPjhFr|lNn$!HqT!XYbSeg00=;V9RW~|S<++m2?J_jw zH6-g-_@I`=ZNm}MVpW+#7rI>g#Kk}h1--?e?Oy3!-};d`^d*ne|FkJYIABH~xx!*zhw7VXV&JV|XO$l50)6E0JJI?1`_ zgfWfTE@GO%|Dnv~gkQhxb8qOBWom%;Ce*ujykw_8W?#UDGNT_CtQv9hq15|O#8M9; zXT3~4W~sL`DP@d$&^r zDR0Z62q1o@*f(uHa!ghhw16NKk0||(LtvWkx|dA1NmnmpET$2f(qADI4vOmT=TOnRtrb0%QoFT3QpjrU?$Y?r5EBc`8^DCjR;*)R@Uu zGLUNX$}RoRSXlbSQRDL4$W% zy`X#b6%@6We%CT{uLtJ3Rou1!kRJdYTJ`%IftQ<4N9PnJ;-$AN3f+AzT@-*Rf(+5b zgebfVt0j<}?vqCV=JYAC(7TUu0d$3eGar^@&rD~$tSuI2RQ7O#%0^9f`}*+aZOa*& z=5hOlp>|zkA87__&QvDt)xGep6F+n#p`U0NC4<;JAN<1Ljdhyz8D#N&Z&)w#jLx{?^E#%mQCkKUAS-7rITBd`!so-mYve5YiY?J)*RM}vtGQ?z4iXQiLNEyf z=w;H*4FaG_1`Bn}H0zJx?;*aK;s6utykhUu{h~2`DmyzWq`pDk~ge2P} zXHa`!PDp)A`j#97cTUkSKOh1fY29M|aT4KWPK6x$rc0v*2cLGWwt1=CPUoFs+wFSd zrqJA}Y{)m;FFN|hV7ZpHO|$x0zoh@I!S2GbtRG_C*%eRAtKZtdDsn^v_dXnZFdXxG zwN`ES!#hA);UNZxo!@=tHdxMn5wSYzkaf(ZIl3v$zwLt2%ML2~%BmEQ=3IQC>&QpI zBzLbmtrzCB~Dc5~q^s66lf+B-11r z2GZ`G3Bv+Ku!XEcm_mtPDCE<`EkJcqL*6?RVD@J{UU zaJr!vmT%JI5)IF1e!-oa;}02tv!m+sK^!YKn}K(IIA-2k*bQRpja+qMOUa4N_ zqcOty$T}ZS^b_XAFA46QhVIFPRZ2EheAz*iHiR%oP!F{nvS5$p_zVIdnw=~NbQ;T4 zbAB-ea-ssNvyv0Ix5XWf768Rl&kRAVbw>ze074Qjcq?H3)H8WdWBF0B2{0K(UVa)k ziMv`UrW(hKZ(1Hge%$#*fy0JvvaTj zKxZ+h2x=@o0;F)a!ypkn&;Y+pwQr@0)O_FLo5y1$v_ouJs%Oul`ZZeQtI9F6swr-k zf<%~lvQUsuvzIz3fwcZZbEwl0mG(MUSM=69@<|Fe6*YcKP1zsW#SJ9!oEHo%~YEg-(9tjlZhjpi=X3!>X^_X=&rwt=DNgH9fS`1Kz8g&(ae0-K-+y$|!Kcy63xP#%lceU5(C#(5 zR>jnzzADp68<^PQyoorls^I>>(Wrf?y67SszrK`iu_61&v6-t;5}!Va0FBpQd*wK2 zp5Gh>HB+;js%`M9zA4Zr#;Eg(#lIJLw4)x{pKrd@c9>$x9=>MWk;Jy4o#UO+Gu+8D9_sJvPZ+W{2PkQsRS&tJDlxUi1ly96FF?Be`p-nW~#_S&E-(~^N_MTy# zZZ{`qZS$^PlvI&ZTjPK}+q}exwPU9A8pAEZrn?@L+1TPP=WNYIJV%D7ySDChZ%{^4DxU}WGMrbrpYK{N(iKdZA)#3vpxS&~%iaa;j+aSe2*F zgW(4DS8fi}%QRR~S-=YofhjXf%v5OfZ zqm|kCBYN$7F z1Fv!Ym@(7RuGJ)Aj!dj~Fh=qDR|Trq8ixI4*-}Q8pamys7FmxoxT{t^T1eC+pbps) z%~l?q+nU&1fBH0?dt1~2YXJ~4^~~{ycgReE?x+BAc5}g_Unu=r>dw%nz!_8kCOaj$ zGl7JIlNB&w>X|>NvGT}*<#+}L$u59K9>g_^|HTuFc!N<(Po2ir)sagcI%;#UnRg1K zNwtwnicaDtAe|imirrjw@0$mtxzaRlGPgFQxzsc_wetum*Q6B?p5<5;(p+pBH=R2f z6#&R`mOh#icTish%(GBp_xCe)N3qg5*Sa1mS~qbiG>=3}=mguk*~C)7{dOPAn~0gB z`uwI^$O?Z}Nutm5GH&?DgLPx4Df(e6Ia<<(k@=D~x((^m05>Hd^7}yDb(C(P=U9%# zZ-q8gvrV6WD24pRMrzc~4In*cBrF&h|9@m7DHBsW7fUnC|B&=+R-3U$m%wyOmmS zST99FE!&%TjqS6W{%sT{7b0UF)3a&Iot}x3!B{<%s1}jHzK1*$?X_Bm)3%qzq26TG zAvVPJjny!HPo;IUc2ykh9r?2MS4MFY8t=ersjuWQ1GXxvKstDfk}!HGBn^CpEvqk@ ziSJ3xdvmgtbLHBX4TrpZNR-X_mranRMa3&~@BlT5H4Wcw?M_;a62|Vzb1UPh=F-CL zdS~U`-_b2HU7msH-h|al8RFvW41qPdLL6sDRKF><$%&czLY7?r3}3IMNBd zHAoH-t!Z>e{i(yNy*v3bNqT2X#*_XDRkGKj3U=)Gck|cwkD=v!GWQ`Xoh~;g285Mc zMTjFcW-4AS9qPP52Xn@-W>Q?r`I3{v+pS41#CO^cVF`N_4>`-2K7uX4k^wMOg>Dw2xkgoR%^NvRBi%*;CLxx}9HyEq-f zGFEw`IjOU{ow?#OZZ#uI`IcB@$KWNyr5Vt(Zf>eq1AkgGy6fJ^RryGCM(Fo&u`pTc z&8lT>#F{_dfX$>H-yR6(ej-+wm~une78HJklKPpf1LzQLyZ`u>AJ4hCFNb<%Im{dC zGsasnGL(;K^{VZNv$>cca;<|V?p072l=+5Rnz=a?hzQ{HA65LRaB_dTvjaV1NwSm^ z@m8#AU0)+hT8Xx;NZwn5=d)baF{`4Nzr8L^&d+Fg$vpt$ikHnKn|d}&3cR=;lxyT;EUdR3GnJIQr5fEcYAY zpX;JT=KiDRpw)alC_MSkW%|F9!GEJ)lKa!W>YLs6JU~X?gqQ+;SX8m!9cunv$jJ}^|1rUWCNPBSt_Y>knpTxw%po)9^Gw&Hnc3U^ zak@R2Ra?5q2WPFA0=nt0E<8(BCnm!&88xp(HY}$xBZgoxPX;MtsYZZ!tkCx1o1)FF z-OjT;PRvo?qZjd`t;`rBp99~rGPkVN+P!t5Ho9v2g4F*e>-QUb}e1 zfpUE6$U@a5YtMph%(FOEfj0>~nFiTW$R9i-j`9+y$F8~q2*D3|^ren6qiRzuDRI_X z@Hsv7KH4cY`y7{&&Kjfax}a{yoKkiaJ)=_sVx{T%rIC1rh>_8c5W92Mnr!k&`v*Qo za%`ozMUF4#bn{gVvnmR+78b$>n1=}`3xdg`WUJI2wu<6Oz#vZ;Gj-$yCUc~OU&Ycg zm9nHd6ub&oTY?0by7^-^s$tO?&?%Ib8MkCgK|b1&vio!VLgt&*J;9dh$ORWgHh$uT zFQ1KF5E9o$$)J*yh@P=5FZi1d!V{CajC7&jyo&Q{Rb|D>Nikh@M=)@arqS6yi`&5S=#S#Y}v&@wJW!Ml=i($VwXscp;h8rLWuIS=)BRLs4-*U5*(W6$+FI2nv zXxbUtvhYhl93xP?(@Gq_r#S}B4Ff+Ik1iB0sDw#UKfD!b5hJvwFE~aJW z+=8;E8IxN(FADz_;@b{=@am6`??(Y2-PAzHb@8dIw5qhV{G@aU7kmUl?s$UFxrh8y zh~Z6MXLbok@cUFNlt{~=$KLafs{|yY=V*y+?V)@7`cWY1K37G!4iHJ?f)PVb$D?50 zIb_qpmw-kbEepdQdZT2^vaxyE-E;A9%j`kST*qZFb&i(iI+Za}!Pi{U{wAkJ(rSS2 zyYGC#pW15cIFo5wT(hW_)p+%5a6TeTC?F~A$xLjlkm9Ct}x5Fg%u)JO3r3BBlTC` zeqgI|2pBS7%+j#sStVJ8^17p-P#hqim=d$i7&aC3ObVk`K(joU=P|;IH;M&zsQDpJ z(hv%7OMHI;ulWV>2e=!fY~*N4BsWOZZxHuGqlrnd!6p27!%nV%5iwc z6I+mMWy7Me!!zmzy_)MQ=RZ?!H-x&n1qiswAmDQRFXONOP8#)h&Se8}?(84Vy=aod z`@^|Ge{pW1^kIu*%eZx zrra0${senT1-`RhtEe3)dpBxO{}{uS-K}7yH$K}y+=glSTWH}Hnm)+D*kZ98B$mqO zma>xWy1ZjhQ_zb2+%rlGQt#2uWb+OnYFwnJ>{x$Q%6kGPoL+CrlW|zCE;v%$a}Ef4 z*@j6?3MiwARgksrK0;_z%aHpX%?zZe2|R~I!}a4ay5oa`puPy z>6sT)4a=gu~I>_&fvf?~VDd|FD6dtIBz>%eSKI651NjOI_ z+ET*V^e5*0yZt#}q&*&iz(SX`GQu%a+bgC8s|d4~q?28=*1-%+r2x^vE#M}ebSy<) zhZkG}zkhR9i}POvruDu$d}bi*hJ&#Cp9Q9WC*6P3QT<=wO5w>W3(sS~ClZlY&KBWCWyti^)tf1A zd$Yd@SfCyo#*F>Y&@~gxl=NfSXtXkz4u+F*Q%97sk~3!VX=Y3!`H$F$u zZ^6FpAO?Rw|LAAm7hFq!fK33>u~gxA(qH@qT!)VTiWWee8)10*w`gJE3NFlN{${AL zze*0ZYbTpQ3{I|haFYWW-!nc~yY1rqkL1+CB@~-SC+>v9x2_CE%3QjOz#&~aTHHDO z%5nWrf5xw;os?(S>X4lLX(GLgvWL~A<@wUBn9WkPd{g$M6{Pd?LYNmnl$63KNwS$F zg#288DY@C`uh>i%?IK%LYYcbng5jV)N}hsS`Fl|xuhm6&7+>VHEshdm^dc%i{on^k zbvn1P2ohf5R?kam`+g^m17-*}%dKbe2z%P7t?tovO;`FC}I2o&NuiS^1 zt#2=#ci;&-`<1gxg?HfU6KP4XVQ?jm(8vSrm~4KuLi??K_=uLnnHd8rhB8ehxk{b- z8nl;#N&TL;HTxu^Ia!@%;6*zwX0nzU?|Q@(?ER|g2PKpU{boJh479d9I)R29uKAY>_F`AdeC<1@mh#hSj5rcy ztUh^SbdA1RF$FGM{4f$rvuGznkt!|!q9hj7!82D`5}GQ}fN`K2Q1+`;fl?PcqE2V= zAxs%2UU~?k&d~*YaC|}kV(doP)}?b5UbWlu7|atEh}!vRME!6%@IdFm5aI244X zEDosGADnWlz%uSloM_#9)TqsNheQCAYpy3cGwULyWaj=7=LsPlfzBv$T93oUn}TOq zhoq)86^(0qUG4}zYopErlHmQz@IA?qO)HwWjn=7Sxt@}=SW|1cT7_h5_2o!y&$+sq z2Z89m2g|l^`>ZD}WxoRFY&fKKTo>eIT#w^yV=(eKLD_frS(K8iZRBA}noM->g!yZi9A*`RETJqnn|;(;7dilNUM#=^5}?Y?zPF(XzH z#7~wmteXi+OR~R_=4I`T4dBhEk56QNL*xj!cD070W<{`3kn~b7X`7VIhW(mg$~adUN_wgucx+B#Syz-nWHVI1{g} z&?0PYj|hQ(uH1hsn0KWS%y-4FG;Y&_=xxc5V^{j3p_KlQYui6>z17Es#Tw9Cp8)s2 z548T9T6LMAbM*g`gG8j9kZ61K~VjG-+2R7@Z8*H@ZS1F9$O{;()#w5Ql} z!m%TrRh!C;{Shr-aeC=tP6pf?$wiS_^FB7P+yIy1K!;Gh zhngq7d5&((u$%h<29fHW1<1h^!!@I#=lgnxR_;?AGla5<8okS`IV4KsE%e5IhjlKO z9Ixa~c0Im*^c&O1S}Q8V(96!Lx7i2$}Z-OzNZB zB(hMD!5p6^>=9C1v6I|*X44LyL-y_!Z%(C^^AH!#-ZR5)Lkn)>N{SVrU#9)hQAubl z_s!p9&ahg~Ueb=U-1z+`sct6-e>k!Q?JYyoZ# zc5uVLv&6}JB7Uiyhc0@;Hr|k9WxDe0wrGp~jb|>c@W`(?N5Kg{MNBJf+0X(1Dn7a?`Rc${K;QXd_6T5Rbt~Kk9UkUJSLBR&$Viij__RHAlTRY*M*I zLdg}QI*gWO>gt+b?}2LV62n3gs2MH(FvZCfp6J>B;9fmyxk2Av&7)N5ze zh`gh}@hH=Y9)8J=gpas*6eAEBIaJTMErWsXz8%(Cn3)bS!f@pUb_TZe1ZM6H{_gj( z49mb#Ma=QZ71B%m=)rJ_lB~W+Z!i8&jRAqfN4N|hymH@ox*RWxhfJ&$LN=U1SF8Q^ z1M)6~8Z5d##NvvwJUEsDkKynS(VweLvQtZ*1(q@c zFdwyUuu}AwE&{8`=^h&?z|{xL$+Z=|wFr?-PTN*zvJf=0X6Cd#s?wWT5?rJA5H%@O zr6Cd~-h+qoJYG4cat$hz^Z<|j^8y|np^e=;NytFRJrp_#Zl4{0gAY?N3#m{*xj2-Q6+5tjC+n-<+xt629|{Xv;R#|9CN{b5fGMnR8%YX@s%&|iVkFT^Firwd z0cVI%J%vac%@Q%Jp)UNM7YZlN0p=prO;aUzTK7o4Npy=ERfU_t_%Qb3cY4-Sqoj5` zlc)kiQBGI$6kJ!OrB;)1NugKFb5Gh$3$nzIxxznYU$w}5G)X>D?y zeM`NARaZ%@;2^T1&x0)Th4c~GEOxtYDDEa3V$vfpm*Y6Y88NRo>CAyrVOu|>a0hpw z7I9kPOHA!}<{8=bF}PV=E)~oRi$8hVv9g)Vb_C{LVMV&nOlAzQL3mS;#(pG84@ZFb zttJyD`Oq{9FQe;>^DD~2)Wjc;4P&j)DjuCA-^9ozr)OUdI<;-CF6Q(aytTW9oJw*N zsL{WWkR}~bZHmR$Q^;32x-EvrtxQ~oDC5fKCM&gUtWh9pUo%@)jTT!o8c(b8@WieO zH>(DF9rERvgR?oxztjW=;Z3@m$s2dCS2bG9?xeFQ-~~ebj5N zs&B@p4yT8x(I3y_~kEGQ3J+Gd(z0Sgp{V!I}*x%n8 zyoOpIo;03Lp886e2224Cu_G*ax<&0V`PM0@Ya8MocAw@pu<(kUaOGf=sED&BELMdN zj_t&Nq>^4Zbtk?a!OUGnyuN*G0wlo-V@s+Q=B>iKLmfNnUuW#8kp~wKwww8T1 zmzLyG3a+@bA-SlE&mWVxT;~#EmW{m!yq3=uBCEjF>UUrt3SfkW;$i6%i6T^+>}Q6^6sx*m>DO9=Wsu6Iro5e(w^aNBz%9YVF`fHL^7hJ z`1CzM1-i7!-p0npg7KDYEN5QG=fhVv2XO`>1^w1>I?1MZVD z3aaeHsOfVX31KOl;&mhR9Jm}Mg+g9VJD;!3-Ue)7F#6>4hVb~*%!AHMW@eIBlk=({ zwbtAIsxb3c>B*dm=jR|bK-#(lB>0amqMc4I;NrKO=4euIZH23*0Dn48b67To6|FN> zOUtE+Ja%)|4a>~2lIf|Y%+|xT&3kNYTkvP^k&>F)04PYqhumnZy6M^y<}_N<=!wsZ zB#-#K7HIuIpw==Z-dwxQ_u^bq0w2-%6GSKabYZZLpr8qUDwBJ;!-U_gqCh(c?tK59?6DPFmI%xU9pEE9 zAxxgrjANLxsW&hn4iQ^{t_`~e`BQL35~v%$b%lHjsrES#_JA7|UI}#z%zeGXVa4@g z=ymEN$EY39qsFKq=LpQ4$)-KsxQ!C*0+PosuPX18=}s#3De9LUnYPC))|5HWHJZ$4)qbW;#SL({Y9qAqxQFz~%|N&4rxy3h zO6Te4%T?*=j942(kc>|fYaK0IpLESjPfxGdKj!_uN9Y!DUV*Z@i-H^J+5^|^tf}-Y zQ7vqWY>n6^8%~j&E1m*T1_57e*eE+UrLC?MH81uNR^}1!z+;sx-C^94Y~eWRtWHFJ zJ8C1AeoT+_{*LSseB3vOOrNYEUGfqt>Gh{b!kNYai4y_O!BD*B@43Owq*0Swh?B^5 z*r+mPjQ!T+L!n-da*2nOy{xDozGpDH5(bNm>aLz;O8%8y6g7o@m~(h;#S`!BqDkWo z{eLmumhKPaH4PHPL)2Uh&58S8iF!uR|EOjZxnlL`KTp65PFd&3l8|~S8$@P zUP+%+s-XGb*-OT|Q`meyA+mOYyU%*8%dDtjp3@?nb<%;93$R}dy!9n${lvo9_2cO7u`|2DJ?03*E8<4j8>HH>%e-qq3eOCG9?SoFZ$NL1)6aQsTZKAg? z@0#Mh8tpe-w@XK8<-X2PS`x9!kJR(d`vqXgnMbtTwos|zudJHwei=*3_)*K)$(o|#^blU(_d`Bo#KY)wzbo5f(!0iDjOD%Z;+Se|IiBx;b$*JBF#Ja=tzVr{p-1&NhqgSW z5Ve*>e16#LR@A@BCU|zl{PB%zAHGIV^SX1~2(%0@f1gs!`WjrjDcuzwCZ%;H_3p<& z37B8yP5ObUUPE+vt5Dp*F_-D`;%lx8mm}|ZXQE~-^}Cy;L9<6_u&Lj-7BqyAi*WF5%eB$slxFkg^+f>`PDZW+!yWK8dEMa?d+zgCKn>lfTwjK-tNh9sY@_zCQO)0Q~%96l=&^@w;q zi%_rCmQ!RF^!qq|h4PHJhw6y)I*bC{Mu0)8#`oyWC&8Z^e#0G;{1u{CBiotEGzcJ-9k=qD)vO)l1->kZ3}zi9j;St3wc5xc2aGNJPS-TQhgEhL^=$o`XbC7 zduyDMm;Vdn&@+XV>Whfyhr?qk#=@?UTb2o0s$M})%)@l5USaNa2*RLcp4|ueCs*WO z(0=Q%y=NiY@F#7njyVQ-0ixS!O#v-_jK=Vq>?dtM6CDhfeuhu41_4e#-_tcFaQJ>4 zwQ8Ur;}!eh8yww}4lnm5xgmW@*aAB4xb%8L{<9kdulcJb{yFL_!L)ei=d|ojHz2}+ zgY|aW5pKF>Zl}p>|F_oOkn!$CNB^yRIofZ&A84zRMLcJats0^EIVpFt!gThsCj5?- zAfRSa%6q~pz86YgR$5(tV2tr8;`pCc7tb1+LkFT$6(WY^U>reTF*W-0HaioO;i6stoZjA1BKhmf;snJFyRn zY7c#M{K$VfN!w4CXSr$=fs1c=F6+24{`8b=j=*AC5M{4%_xGk%{Lram7s;1ZFD@k# z-EwI1`ON53d!t%Qz^>U3%kI?W7Ew$Gy))ayX@EtFYuV|?I7}?r-$v{0ovs}LF3#-D zTXW*uXmPYVVbPZHHr8_$nWzr=sN(*}sa729^=7e$^mJiD_la6K4D@T2c)dKjv^6$B zT^1Fn`RS4{@NGxu6KxUw6P=#{!EUXkKhxZHevq99>m((7q=dbra;6$Jpn@HwBBioS zQA%M>aZG_tkxHRXu}s0mKsUu2ra@-qn%Yr}igngX!Ivfg-{9=?g}_g9&>S#?orI~6 zLHYmwc|>&FMtO`4o8;0R*=0#XHNquML*45sbJ$jCt4s0TO$dn1Qc3)%p=XFWWyDOY z1Nbpo<###}cnUq2^*bYkb4LNZ*6wnW{Hys7#`E-}*lqKdNDV_UE#zvLgNaw+nri~dN2Pdp8jjf}=w4&0@jNFjoHW!f`0u z5H~*_5N77I7@&_xIqlp*b?k&_o^tG>0!+mN;>?^D0BrGqTr*li+{@Nn=zNq?+}`W} zsa$8+Lj(&h6+UzFL;UX!rJg{V2`OtXRz7p~Ls@GsiWw~tZf->LwBvi_xUyYMzGLMH z?t*T{y#4AD!0QjEs2@F=K+}}F{4nDifNRQKM40j2nY+k(FQSAj;d7Wy+b`RGPiinrLvK8CX9J+-iqx#0%sR~Rg=;s~D-Yrx zaxY}Xy8an%!IF*5g2RX>QnOi+!eHjkpA&j`K(aq4Hi~y;Z}6?ANBj`YvyK(5Iqa4l z%sfEioj*Yak=kN)#ff>{Tf zo-d#S;p}hYw|_3Wk0&4Z=S=RB!|iv*4@Q5EIpYEG|9o>-{+}U(4y=aZHyyzpgOlni z#LjYQEW@Oyus7x-GS7Zx2aVV^Ch+|`Xv998%Y~2Mi~OtXqUC9<&A79vj(h(+zG7}p>DfiBAqT=^@K=MSE7SL>>U3C!mm|H^yh=~V;oM{hp;;`mQ<|~VL za{KE+!yj&x@5f%ZNa`+V^XE}dl<1<cpUG5l*Fe^ZeEvWbSgW*@}&N`>G55?)lfgBhTLa%8u-|NmWY z-TvC)=U-~MHR+%o5!FClGo_Xy!o~DhkeJ^{P?U)@F%POFRn|&}{K&{PF&{pF-0qKMGTVO0V66k;A66h&!R`g)L@BwYZ&9Rjiv^7mGRTI(_z7(8Oc2`D{-4y2OGB;^zM#yls{}lzKbApU^8jx8KM8oK1h#B;6s-HgHHC1LVqA+)$CL_s>vA@IcQVv& zq*y%Vi=&Ipwq(y!rq8L}6spUamw~H}#-?Z0QLm8|%~rcJU0jkQ73QZ$`(pRl{v=cWeq0J_8#A;19P)=tUT5C-!6KyQ4vRAz@Ry-pg$t|iAEi9}v zSH83?`+S^gV1131%b`_QyAo7qWs{jc8~x5qkd#$-UfGo87ME5iHf@5TsY;`;o|ZMT z3RSf!G)cFUBg}1oHv9`etns&|HZ5A+L2#=BBg;#*{HNaXIoxceK6^_jHBOcgecdx& zcWG|lkvMDCrbP{@SIsDCF!S#akF?ytmY`b)Z|X zJY}qD<$^FpO{woism2AdSjgd0LO&ao1R*?EIe1XR#q z%nU;tIap;SVBUCTAD1O$;EGO43dxAISi6Z*Lxt(4ttDd)dt)?vCQ|E5~cZ% zh7mN-ftaVf_0!ihjt_4aA3~MU*n>1sZ7^+g2C)U7(Rc|~qSlTOYDZc{0t|-1ymmQk zFxx&~I^=K`uy5WyeKF@-p1!+RSU%O*^eJ0zY=9c{_Zt! z+P?maF4vvI{(4{eIY0NE= z?ex=lJNkm?9r-3wAWbug0_iR?T652MZU`su#5|I+B$Cv}D1baSjl#(D;NsdS&7+0* z#?Cxk;u%0R`7GIoyYF0U$ejnnwf}2MZ@{Ss&Eyg?ZyxBx0LKL@P!@dni)d$Ob$s8Y z0g#vN#B)mI#_g>e_hrMGAT2lCT5G}nPVpUY;wwCCyfJn&qE5qYh}H<<9ZoLZU~r6x z-7Y%oI~vmqInHkw93|Kh@(;#>Q;KVlF~qRqodL{r{hGuELu5Fc;3E-`q;v-O2?qCY zI7MhNIp8B1kfbyQF)~bh;3FZB`}qNh2?qG6OxL~}ruVyv!s>z1AiufGcCblJbvpuD zMPn#ktkhzfv#6w|t{yV#!!YvG1f8VP6&k7XGfiM*nA)v=E1e@ZttOEALs{O8*0>W8 z26QWrz0#cJ`*3%h?F_gH;kiV7fU$JPDj&=`wQbI<$aw;6R)_XV%GQy*}LIx*6@XyD|e`iYI`MCU6^EK4?a3 z)af15A;}?QR14_9w^fQyW2y$kEV1$RrM`3Fpfkl>K>c-J?boE<<8fBmWN!KVj}k>>QT ze@G|)*%Zgku82bpRDT%)sfGTt>5{yuIcP5@lYdthtAe~bK>|%AMXVP1xBAq|hdl63 zjFyKl{R`#Ik+2omIB4CsU=l0P?v9=7AFt_Oz(zhXvMEWjG3&o7j&M)HK`N^>jsr4R zGwpjaxjTFP{9iv9d}>uIPLv}FL##N&I8eh#NDgCQ*9$Bl3A6zh^R$yzN-6|dwrALL z`xVjt=sJTB^JzZjvCZqGSHVw=_D(a-Rz^R%xAY!$dt zZeJ9B2q1K9oV;jxu688K(iiiW`XHY#Q_FgVi}u-X1=kIm{zPGXmz#a2`J7`A?mJEy zLU&5x68^Sr6u->RtjvpII%hUILzzKvEOx*sRM_-y+^`^9#B_(u>oQor+ZsEWHiYWp zU1&RLN0~uPT~n$Y-J&IQxwGcQjhrry1!j78M=v@y)~z$xPO*s4RoE#c@&nb(sNbC- z===3zgo0TDFxqkWn3m4PjETbzVb%PiCm&Re!OSpvNp3T%Vbmo{QOVndV7SQ=M`^Uo z!@s+j1qddWv(Z-X>PA>XbEvWO5ZzirVj}|%!Nfm7hcL-9FvU*(KK@4b%Fp}a@vt(}8M%HZ~P&)m;q{AF`RT*Lov5-q8X&T=O zgeCOx!WIyqN~18Gs4))Osl}9{lE9;dHl6th7TV|05uUAYLgp(vx}3R5q}Ns;`H*cGxsfA)hibq9CaDR<5D2n= zG%(wRH_97}GK@T++ap_sC5~s~_$IqF!ITB0L$N|j6%SPdL^IXQmP#L)4++HWBo#Db z3|I^Xz=VxIh>h2g2y-`HBUzgn20WpvlPm9jM02@kc7`OsA&7hmhplwa-(f&)=M-n> zEX*3jV+dQYxKL_l8J48LwfbTib~3SUtjQj-QsCbo%)FL~YTJQ^Iy(qM^@>=54N;7} zC;&wG&@8}`tm44}o&LFB55B1OUrl8_43o;_LD-!7A7z$*!{&dZ5B>*qhQ6=BfzXM8 zWvKHTT{f13gP8c?kH;~=&R-tK?yq1yVuXDj`=JzYAYHpP;RKht7B$1tiVcgoncGpe zy&3Rtma;>(n3e}g5r%SBo=|5raAPt>RLzCpdSc-1kkYqZ3}RYQQQ*Nstn?Z#q4Nj6 z3QQP3AVx2}HcoN&0(3XnZ6_15n5x&g=?HEa3%C+cR+;fKe=Bw9`<2jRXa`U#;)@xCqNg8g=sXN-#fiO9=Pi1;ug3)Z~ zEw6K)(Xf90)vIER3^96TmMIh zIw@5=tOl-626#PksrL#IJ{f((zUIT>-$y=tKuD%VNcsvH;^cKoul_Ix^IgP*T=|sO z$OVDf9ftfTQvJy*$|A3#LwdwUc41bw;0a^Tac{o7N!v1Ye!C zdRFxF)sF~OzXP{XKNCd!{L-~CHu|mbQ*sN*R_I27GQ5{>9--6ZuHC5D)&_P>zFAix z7~>rIO#LH5JHOvI&J((tPcvhv9-ScO{2b;@=FrIo+xR zI;a+CYg{O}QL?bE+(OsQH0MXX2?-^p%F`mg5d5yVS;>e0T8td9L^3M6hH=^mLMFNO zCu%RS#q;3IMSDqKV%kv8B(Y*Cbr?fj&uW9fYUf}J9vQ)6Db*|tEJuNnCX#HL%&&ptT@7fRfq){r7V#x!=Q|5H1gqM?(ErLn7x zq0_$woi%B%&VRBRz3auR6gD!GRhl0NF|$eqqmVJQUkYKdAVOPIJuNmVWI7Ve2F+A3 ze298b@CjMtkncbGJ7zcngm7(C&G5~CO)L4&<^B4KKeH;wVc2N0kI)P7e%!iy1HAIM zU)leDzh@2j?7rs5-rJE?O=8vU3zbtR(?yDA+HTahTjct-&_43-wbDl}=<@d_|-k0V3)EVb1- zp|V3;EBukWm5=fyJyi!&k(?M;P@LWQQPZSi6lmHU4#*Gf#C=bsB;7uGPwWK7qQ?V{mBZ?8SD|41H^MGl5_CedQ zwU|aMqeo_AV*SKBYWfIIxdE{&kxh5BH#FfUBrbE^`7^TAf z{c9)amJ)OZegA6(cwGzJ>KD=HlVD{aYj(o#C`e8s(AtFXdr3M`R-#*s`Gb&{Hevi> zlV1t>P;dDW2`I=ep;x30;OlZbT~~oUW6bKD%Mg|9^MOeg+%?{u5jVKqU?Ra&Zvy3T*RHeNa?|NV1C97U+iNKK9fVgVv@z zeB1b@H?*tGeQM?xQ`o2>@dm#SB$e)SG)Qe49(z@v2>P68g>f{BKPKcsdPwXc=ywyi zrQ)Abrk7ygO&ESb!iI6Afj_qYj^ZKWcO8gZAu!Pe^Uwj|-29hvJAs2Q!6c+HfkOI} zUl)JB%z)4nG-tKGXX{~H&0fpFyq|AIQb1h{dNXmry_oYQl~`-H_{IOw@Q?O$omJx( z+fx=T)v2_}RooNW{4*B2CYQIvF2kJ`o4m>w+v`uX=4a*CoO=JcyT8@g=B<2F_E)1S zC-rCj+R*Hh-1w3>-TV`Q^m^5fHAi1Cbg!M(Yj!X7=WIH}v1yVyt@ZboNZFVzG2ihU zy)h7J_xUblUljvx8*L(`tNZ_2L;sn{5E1k(?Kk~YlvYV(g1!) zv}7VIN-cZrgp_Q=x(AL#F@Wf#JXFCb%!xOG)iriPo9$w&Z%oo8)iho|-l()D8=5%i z3Q27)?1|;Y-ee2CRWV|4+UBkwfF1>Dd7DJh{{*`*_mX2P4j z^dHJzgUI3&iI?goGL8D!m^)_E$TS}71pJ&xf76|RWEw1(D5-%q@^eBBt42}Tm82vV z6_%{*45UzPxkX27_v$QJn~1{DN9`ZVUK96_ug-e9tEOh-mAbqSP*!y1s?#Ukw=8Zs zU+JQT%VL_AX{b>b>IO_hTLKtL;q+!OL5iK(3T&F5%vv%ymfHVRHOpxIDt1<7)lO}o z0w&VSOkEaE`>=Js_#-xD+2qnFexrgbq=F}l(@R#T#&r3gJI zIhnSDl2ARmoES^XU24b%+5Ip-q}%p=ZD{?h>@ygftG)(!*g;QE6JGQt}mO^$a%mV8RWm2oq(l=|PtK zBqfHs#60a=+uivaNl4V4)~Ml~8-AsgW6T*-T(${AZ1NKPkr`zB1Z$Ra%3K&ZhG{ku zsbq4{Lq~PoRKFQIqBvuncimVi6?L{{bhCG6^zv;R*=r-Hw>D*E^R@Kc5(e-zM%Tt{ zG}S%(x!pFR5ByqNbUndLIXy`M$w|bqYMe|O-w_MCji8-vPW_yhQ3#@YQq3?*&s=X&79|!q&2yY+-o@72OlH6FV7;6U+Xl_E;-IKHAScq?1L_H4k71X+%F-+s? zPO+hfE3lmXb7E916gLjaP}7=;{gA#x+|fy~FQ=1(d{ef|M)>0Cw3U;~0zcsA4nUoQ z;&kx*_er(0%L6~)a|giAaoUAo(U;w{F-`U6_@kQ(p`9z;ms5muZ&>T_ME8Dw?%Kj7 zZXEzGA3;#xvPo?(6tg3K2fspBFj#uX#=7qf-ZR+mf!H$&|H$l@;T+e!F(Co@xQIVG zCV@7_4zYehc(|OXfXbiVCwH?+7J2`is0=39O*;U z`y>RfN>FkW_-6!yOY>)n{#Ymf7?H5n7>oOw!~{v#8<()hoFC5RBpreO1l{HLvDoqV zlZluDQdwEVq6$d(Rj&6HP85)#{C_|nqkRV*o}dr z!!o4|Xe&~=0kO_)$Zq62MC{FMl#)Al(bbRtD z2G#?I*^k8BdUngXAHQ}7OOvD5rmDet8{g-_d0PVHe{=s;3AFKWl#r`4`TBnV{eSSr z)N@qxbl!su<>I?+p96sU|Wq>R=%;W2R(KKt5?cA|xpo zGP4nDw4g;P%OYbYJRcvC5lRuQJ!LcueMCSIH2*WzeZ_1U27>qf!Em$&gMOFi{o9|O z+}zv(<;CUuw}*$@i^_Mu=Vc8Ujp_I=-)A}?ULXP=A|P!n)PZ`47oYnIAHwrcV@BSD zhad=XUdKKdGscThCQeD`h$F^vq@*HJg(O@OuP9T%kyVm~WLz?UkW0#W0%mr=g>*K# zOVEoU2|(@@d1RKvLTWKy;c_(Zh0rB@({mBJy62Vzqwfj2^VFw(1slJ z6=aeqdsiErk+C*gAc6wdI_m4jlZ@&~Ba!(AVa!GK&~x`tL)k?*s4gjQ?Gi25&a?>W z`k{G-%48?%NxMiJX6MhiQuC6SYuHWqqBLd^ol8qVZEC}dcxp)Dq|-AYw)@-mh!Zq0 z!%7V1@H`vNs79P9DWzQL4_It)DBn!e=vp|VaYbtT^1*v102q>+Xo=P7HY>JzSY+l? z-=-#o-W*c|NjZ&3V^%~0#~+i5c|Y6YpUmTD?J-FOLnV4c{OvYWaWGa zGStaZMHWEHZ8N7MCkMoyVuCpR8TuGZyk2k+A0sXao#sQuSvQFLw@8dkHES(t@-`D! z;394E)f`8O(x-emuZ;)vBl!`$z%wShY$8p6@K;G0CVyVmR9e=iI>U^n3#sE})l2Jb zs>D%P8z6$+74}MPK)gsxh-IQJotl5lYO}-$*CJmrVLe`*;^vWn?rp4Gp?F`AF-ohV*PCF zN)JKzMTq6EKQ}rz@WM-=1h0D{uVWBCMkNsTuZ9F$uCSVpnow22 z)|?);q#5Zs7?*C#5pYzP1U^ly7GyuWKJCsWWZoMR@uRot)S=KjG`*0Y{>``pr51P5l|Kl|bK4|lW0`Lx&NgGR zvavj_w$Kc-Xa>TkYzS^vW%`A_*!HT3b5{cneTUG8lL17f_y~^b8|46Q3BibG2aGO+ zL_1<~g3Ox&G9|wnc3cnACyRup;PI+!#e_5E5pd9Vs^~a4lA4kEOg@rcYiQ)y8KRbU zZ*7}0QTh`uln;!NJpT;kM_`>^C@o%W@yPsN0cM{ywisHZs*HG*u$=%se|3gLs3X0-{@OxXrbG=a`g&FzL5tyge7(RV5R#8@1b;F61 zl-?eCO4CXMpgv{Ir4@{QKSEKH{gI15jfHg2cHgD60avfj>e!{U2>=QrkCVp|e2k0k z*g{-p_?>S!iRE$BY?2k`jq}&x6op3ffNFIJp1&c9EZ1G`>IlW6Vd$|olIQhMX&9LS za-=AFw!)kX0~|n@$C7=li{#kx2H?@0aRauX$aA5XY^T}_c?EFMp0XGL2o9ZYjJZ&} zxZ-v0_noaZXE;FQBW5!voqI4Gyb03XeN+$rt(PxaFtvjc)P5Yte~JHcVrU;pH$Hx0bcm~m!1Dims?Wtynt z{k`4C{q=WDNPTS#8mE023u~Y73zbmkO>zMIf$$5Na1+oSdUN5 z?I^nQ*XwA2g=nu|MsJV@z(;V>SJoNk!R<2>tkE8J>xe(11n(PXh#5RH7L0r33+!CR z^1ukut{8CTtdHCk_W?d;|818(lmQ=0U`blNKOTsiWN+jQroHK(zU3E=lj~`gta>Dd zsE*?yMsP}y12G-L@(KyoWe|MfR46P0XtqEauV2RSjtJSK5q2an5U z$Wns?0}B8RBZwloUf$!z<3Hot#yQ7zI2F-w*l)Et9gdXnJnxK~V(aT${6K%}<+$zs z$o}BJ$w|-q`n>T0@nI{00K@B%YZb=L?uEC^HvnifDMMULSiI%*I|A23Ke4YuVgWJ1jKMgFj1dcIIS805-QSTq-uC?;wJ z(}ohV0*d3S4BPT2TaF*oG1`cPX=6Cv9h5i~8N#;fs%~`V-DE8a?6PcHQxoFCs|zMe zEph>Z#X0)5R95SvGaHhfFoheAM#`(DsDrr65UeUvG+{tW8YVuP!#(2-@fL3DsDuaB zc5szz^p3V4Plaq>?iz;=3Tal+o`Ht3a0&dsHdlz5eL~rRN;LFcpy%&_1pslr4lu6WLfwczNDi)pK z15t{NmA}&=MegsmcI}yNV%m|shz>oZMm_^?t=c(u_^=hyv@@=oK)w+1sgFICW{giX zk)?2x%Z@bFR~8!fBTb|iw#?z?YPd^svix|xvDy=;D5#I%41+7;Gr}rMz%^rtxNMZ| zOFjwaqs5gYt591eIcc_}#F3i^$)Hw*MFXBaehHakp&1Tt*CMX#q318gZ`(2xS8*`j zzBg1(2%El?LTZq%fqamy2`$Jih%JaLNG!-8Q=Er?5_ggHZ$90@e=|W)NkU0PNmY0F zM0N8Mcxi^P@KJX?U<7?`Q1Jamz}oA0>sqQ!8N{Toi1vHoltQW5$hd(P;Aa^=>Lgxd z74nr*7VF@a*KKbI2|a|v>-zGZ4v{Wkr*(3s#ZTZU4d&JGL$nta<#`X=dorx zo;f+$O%$Av^Nivu-VG`%`i|c6k>x0HxKA&<%frB|Lk@e&(wx**>-Iq!xJvM9$6BH! zJ$i*cTswEUFAY`w{c$PK5Gq0TmW3Ndbp^3H8?*9#ROC(uF6}lX-I(lo^RZcGrXr`$16ZQ&1Eilar%_C0YHKez~{FBo=oK9>`wa$XF)V6)#>bR zoYUfs@%R08$UH6MQSRy#MMu-PpMz!rmuA_s7JL=$XK- z6u4`{_aI}v2;7_r;_dU`#-?ldi?&w3Gp}D!EMugahb5j5f%J{2f~rQ$B`BM0|J8Sz~`UbW5TZ|&fegg zF&Eq;1N<=}k0WsS2M2^BN?tpXRjpY|ygvY=KPqmmRW3K~uiu(EUI#pLG)r?4u3rohWV|QabJR2jq$EEKP6;AaH(p8!7C1Pn#S7*;@hT6C}&T19q{wq|f4GJ<^ z_r0&bUysn+%Gr>%U(pntptdsB2>)Zf3bY#y>p)4B!LBCy%%JzyUgr#pZ@Xt zojZCo+w1>Y#)*U;=5IdDVQ(3)y&I|;cE=Bj;^i5Ui`cf$jEn{59!e3iY!H%t$1j5O&{Q4 z#2x5S?6@5K49rSwsQ3~$S0O!^UFcVdvw^f;PBVkY7AA9Xn zWtX)HWZVy_&DwNw=e&Uz4X?z;&clxhX-wn;Cq_6wzl5^md6L(N((`cgb$)TSH1=Hq z!NSeVLPaD2dCp{LiT|`x&2JXSjmbU*i|X#d0+vwBTRg)jxi4l<>-nk2QmQ(DS{{4G z#Ku&F?c~>rfp-$?DZQr(JcFS&7&E#6wLIac8JpSBAp2xv5>}d}ZEpqH>?7g(QCE~i zHd(a+ojOi{R^-vF2-uQc)tp(chI;MV7vAAPrX2u*s7B;EN3wi`M~iA;Ni~+-OF%R2 zV_Z6hveRd2Hnrth({nf~?I`|%Z0$_MXoY=$By7O$Nn22={CFRN4oSYm zZ8|qvp|77}mLL&wv%9v#hha(&5}r3BpD%pOBHnxyo1Kb7#3JKcvO-C!S+q}9mE3d9dP|obA&g9;-ok!}(~7~fX+d1RTUyCu zt8iQRY+8(QSW`Vzm$B9~^{z>PjQNzIabp+@`a+phBwS9?Q?1|$O z7cTfTE48OXl5_YgzHxu?#bRncC;UaHeQqERhuv;AZhcgn+A+Oy-SV>8F}RY`QtFq| zvAMFOqWpX9J*K9DrI?@QS2T{IwKdLyJY+5|sX=iokd;tJu^q|*5|$XJLZd1@{veRl z@J4_Tm=p{wktxqtjPV9S*TNIcE5{#%&m;XgBTi0IveJ18gb%P)rRJ76V{hE2lsOgY z_~hKiUvw!F+3fq;lZaL&UtWZN{SJ1-x_lzuw4j$13}#Wfi3*>QkxU99=$P4+S_Y2B zPjO25(2uP+BUtAabpH-QPpm36M1`5Bo6%I2uL+wqd!eY=blw=VLKKpL&I==cA{&Re zYa+H@>72W1@M;R>d_YyMDm{{b;%bI&*6=16{sOzIZNB1$(j{d z@zVm4aP0rlW1csCTjAXn^G;|{H zgW>}Dkp}{vuk^y5;zE~eJ@b_5#0$eY#Ge5)6;ZUNKw|dj60NCHkt}$2nPRO0^9oj( zbyw-daq~>pNzUKLDIaiEu(}JXoJ?pb8F09UDv9QF*{KWFhn>}hom+w=*~<&OszP47 zf^ukPMxb!Po?c0XWurN|M`&kqlkhbBFlWuEl$WdZ-L z$Wbpp^)E~-6e6p8TuKU-@mHYVIs5QsHXTg=z{D6oNm_x1PIVHQYtMEnOAt@#~OTJf7`mO{xJ zZ7^+Gi5KDY>4GoObozoX*|dmN8!HXgQvpDn3@&kmTEtqJ!|jw?M8eN9vcP4c5;ANj z$v&!m<2|Y#<1I?a!_gM9{3*iWzOaAV+Nr<6tw|cxnYHhCr7V_jvM?aO!7rh) ztF;oRP*TCeeT<^SVP+Xt#EfY&VSZXJJo)42M16)sOe2R($8U{Ls_*kJ&jJ2!51H;$ z=${8go=E)tmg!cRfog6W*vB_agJb5w$v86yg(2`vHasOXcfODoG)GfQE-;b2n+1gUnTdq&<8~q|&HewZ#_8^=&8#53h9(Y+Ri^Y#>2BJgP!)*(^ouryyJl-ZY;M+T=%ASzFHO_lAq} z#fNW7gY~FoBq_o=>*T{6Y_)Oq>>zVOYjUHN$8Dnq=~i5=da?`7Dh;}$FGd;4>SX=PimirnY!BwU}1@$RM~dSOx7qp<&lv=9GMy4!IL4Dbf2JQ zEG@T;u*nc}l2mDjTV-d3^76uGhV2p!; zE5b}Z3G3>j@@X}@jl1e*@bO@q+UFmvAm^?)v3i~!g3md4YAB4~H*+{!U+KwtilyHS z@(m{7sk}6ypjC~0?f~m0HRi;)#IMeI*WEp3gC)bd?5f%r@7M_}3^t-%;nU1>gMf{__0%b59_cWgJBx85n>APj~Y@aAY`E)bMgql5q+LH04$`9CWL1ewutcK#P#`> zGnQ=w1Iq%R@_iy_E%76u(UI}0&)3|HN zN~-c41>Mc}KVM}$-G#`X3TGymxT6|hH2JafV&a+u_Cj9kulwUFa1YC{`7hrfI?QJ6_7v*3m##RREZb51UI_KnQW9bEdYsD3`$o*kd%#KMTR*-z$JfFE^V!h ztPQECy+G=Y%&}WQ6?#%7=aj^5U?*Kb*>XU+rk-#-l>&-EuiNHm#66e^&w^_SPbFf( z>AV+j>}epTK4or~nfZQq<^9ax`_rSuqonui?N9+|kkayOBq&M;o4Bp!`)fz_Q1vY= z2;FQB!@O~vL!M-wgr3w(^P#PxwV}PF#i7l{-Wm8*=j}_23dioaqx$kH-e>WhdC(lj zpoRsfTdgTP-cg)eTJ5bM9(_950;$B{5*voun^qvnXA8nU48oVs>)Hti|qSn`KUy#WhGK>~G+Y_vkNo zAEU?1i084bPupQWiE6(a>@B-)vhs>=-!0vo z&|;oS4OTaXzfhZHkQ&R2CU0TjJ{XN@Q)7FZiRG~YQ{T<6v0ZWL%HSTmaO0GN z?2uTh*)%CXqFdiaJ}dKpXB-vRdLI`QxRJ@=BbHgi+-Q*v-PL08(#AYx``oymR>7lY z2s0tuZwR_iQBq<8wCbvBhGm3hj%9{rfn}0unrS$0tUU_nTO0)7k)*<`bM?TQb zSLt^@Bb_@{XE$GXjOTDD><;u z$aKcz@A5{G-)djVh_*n^J!J#6se)U=0cp(nU?Z9dHbI`Hg1pc9W6uo$se!>t0z;81 zfEvSEq5%&o_W}L**~b`C-q~D) zlf+p*d#oLA04vpHLu^JF(n5BIi^f@9g!9l@UiWAVVPAHPt1c2CK?IQEDib-vBmz)* z50C;}h%G2WL>w^kSWaCIB9D;t{h`_JVd=upP$S*ZnD7w~MZ2y9*3k||UELj1{vzw? zM0zs6fjC64wnmjgu=3@@tro&fSSkoxk~nKK^JgT?^*|NGu1wGoO z9*6LABH+t7M${h-vsbkniMSspu&2fMG|50HXS{b#XxK9l`g~wkv1k_2jyupwf6hhw z-AGM2M@TuRnU15I^lWfaBK}os7}F<&V|dB0PMQwAnEh02`U~ctUv}&SN5P)oTITt! zW&hdP^Iux_KT(`nm4CeMdYOM<5e3OWTWN2UN&%UG!uMK9T0!lFED1snL0N66t_?&? zpr@LdFNiR7KP|{GLESeyE7IFVnNDC#IOhdTeuln`WllQZ8qqWNa z>*LY^2!&D-Q&4({4vJ_Cy@8x4hKHCxb*_K4IRx@s%D5+gOp<>~*{o)ZW{Z})=1qes zX;<(^j%R=#5(3%Nq08S#$pMVlq~nH&I#EgxZhK3yX>HUwbewTWNCq4(H9-Y!no6AG zfn4hwN+0g+b2%I>v02K}k*}O=qf0>=C`<){O!1!TjP_#h>NB(9g&5-`9c$+g$?5M> z2=)@3sMLKOm?bNvX&Q83U8f|NRHt?bBj-2|+-p%K-SY!P@ zN0o0S%i*ha8K&Gk#J9Sr5mnn()~Bm1EwtH9aw1vTaMa07bsyy3tH88go+~|a1|cqa z$Tg$Zk_phYE0rx0RDd?yUWj|5cuI5LXc(y?Qns?afjMJc4k|=**|JFAJfSdNp~R&k z58eF<7yQ)KCCgGgi)`cd7r#rqp29+kMh)2AjjtF>t(S_1TTRx0_GdXRjg%hMNpiMN zxb=#5Jt%DF^s)MHz|LTxGIu#D<^4)|v|W*{`Etrg^n>uvjzieQd-@%e1WUkcm|ko< z3xUoH7%7fU8Vy;&i8aJDJN9>J8+&VyNt~O>0f{F7ih96|CuG7bcW_sfE*hj8>p$(j^?}?)VmI3%}KM7%sDG;`4p%Oe~&P zF4TWToAY^A(p=OaP{(&!(_KnOUR?6p%~=4yOo!f)aic)=38+&;Lwe?EOLaiI+Qs(< z+yStObcwI)9pLvsmD`a6CfkHHvb2*VP+1tCC184Q;&5G4xn5sd`PFc|k?zVq`y+vLCFo8^ZTh`hE5Hg5h(ha8@) zw6WZ;{^8QopD_lq7|0{>;hF>nNcqdRrn~S2upG~FogP<1IF^2L@#)W~16hpZp*%a^ zKscIzayfW%#e;CV`~~PUNI>mPEkZx;1AaTdfO5K4a{|!9QDQ0N?@v@B?k&zZh4RuZ zmk^8SnWTqkW+rNp1q!-@i;mLIc4H+_A~D+bO0?Km*GtCf?Fy0Xrs7{n1K7_MWJE^~ z_?vG*ELCEiqd$&cegfHbAkm#md=Le&FIpB$^(Ows6wJ0u*~~Yv7XY6-!9Hd`OW&LY zZuX+(Z1(DKR(%C?@S^HnQXHTsyHd8_BME1|z>O)myTu=IV51No<3l=QnRKeML5g}{O{MEv?s_(B ziP+wn#(nAH>z{QD?GEk-$v1$a_zj@^XQ=SMbnM^YC+j-jCU{JsJ^#gKtJVUzP~&ze zkkF*&VsNqIU%JvTq0ON?`M;WNlkFNa%qPuNs6h1Zf-t)Fz?Hi8LM!t@;ut|$-cLAZ zUJtSz_}`9_6?)D*|4y4{=K`kJXU1T^?A>SIUUvOGzU1~!{cn8{fZ*6tIAiyrU=@r#p$8W+ zXAC`m3^rlr4&L#GHDT%_?u&Us4NhXt?6+tzc17*8!Pc2@#_z)+u@7XE-Jy3~2f`4) z?&l!4LEd`r@gZI8B|+?9?1R1{4ocv+T?NL2Q+~fgqjqQog{I&AfVb$ZMbYzli%E}W zmR`%NpQVeO8cT?a!%94Ri>Y4Mx6W2fq?H5S=R!)wRg%!5CX$tT$PL-NZ!&F5|X)XFJ=csVD54>+7C$myjPi6s` zt&HSmRGzOl30o6W_jPoI4>4sPPAl3usS&Hn?Np59Pi;Bd+|aX`soMP989!IbTsKyg zAIn13kWYx*W|Nm;4cA7m^oE^0UL$XfK#hb{1jxo-XxajIWiGSJ;ZgXEs5t3mMkpj+ z;wX`$btMn292$9n$UU_A3Xc?fxW+;$7LFe#B}Evbm#lO&P++NyJSFgo$0=FY9OBQv zF4c&djO^DSwAB%(N>a~<;GU0TH!*sU#K9f&TxaU^oyRI)JL(3e5TdzO9L2!Inb4-h zmlU@F0iUL~<)AXrQzUmYQ3=^MODPo1Dc zoWXE^55-n-#{4t0&TEf`!S_3>a%Ba;U)8b;SwG+x$20}H+U*Ex?`?#O>?JeV5e%+* zS#1DW?|YKDUO?q-tGkj~|16%NvPohfzjB1b$71^{IG03l_3J@-+FrUuNsfHBI?a9x zO)IZ@2TtVVJ>>vf&eUDK)4De>+R@~+MG(?h+5=Tv##`=jB5ELOKlRd>PM zLY<$cDbXAFh1)0nM8=k!gkalDDmiw-TSiwpiM~6)H#7^&(AL(qj?}=11Ng5MslSv7 zI52ziFG4M7Q?0XJxBHR&`E;H;_f?EJnp4QC8pP%z3i zdElzX0Av`?4DdE2%Hlvb+5Aj!RHD6tKyC8+Sa4JlMPX1lSwo(yF>p~ZX)8k(lr<>2 z_5h4PFV?v+Fn1vvdc`n7E;w5Y5WD(Ku$H8GdR)A_T@V63pLix8CGQX}oYfb>PN&-| zGoDAQvf#rj6CSkY#c3yDTMOW8+#^mrTMMFVSSNt|L7Q`q^aj@SrE8)aht>^+KSKSm zSTm*zt$Wk3k0sN-=9N*jT5~xMy3hKm2@{>XQ>_HSrj{^I8JE1krj|611?P-VOH+*d zj59#Q)`IIAaL5U2d#b;|HCyvYIH@JXgJGK^G4;-vliKVOc?esd^I>_)Jc?z!YJqmG zyT5eGxTz(_qro-v{VT$=$~6OtYs9s@N_ol?N79h*aMqeWhJXe)_7H01}Wza`u zrEfj?&4e-^Bz5c`dgHF3J%pElFV`#g&10SEiQf#P_VIc>%hkSL?pH4xdNt(gJztKs z>b*HDQ*&S#5) za5x|8n|64n8e1K`Zy{qcU*sQi)YHZ{zPsQ-F7T*qCm$wg>!uz^eP)Lr+?~4SxlUGR z?hB7vWjCrqpL#Xgwwj#?FEwf>-&3pllw8ciGo{S-B+3a5NH3&>pEaD32fn7jjDVm+ z`>TtoYl^A&l_GGYVv_Sjth|ddRhb%F^8@9tCDpBm)vYU;tPceKdFUEQ{GvPhz6_?I z{cq0e{~Eggf}GT(%h}?Hp^olu*t74@S4d?e3(E*BlDn(4mdu?5vsz`<9gvqusVGYi zj_j=ATy48{!`q!hDDqFVwhQA|3L%oc3nH_rZXY z`Frd6(!JZ`#q#L>XHj7H3kV2ep9IQ%(1mzP8ZqdRn3q8aj6UKn2n^1(n^K5Gm#~QI zJ4FUH$t#IfDom72i*Q^z0W{V$@rdkVG8t9U6Dl0l{( zj$XzQyf&$ecz_M57G`d)>^y6kL9ngJMLb|EAyEl@En&gctxz>XW7^7$Kb~)zilpYq z0#&7GSKeZ1!b%LdLs_OYk&eooyn>$QEy>s_EVno<3!tsMxDk{lkLB$i=Iwo-*^#A2 z`?R|`uQj@Si7bQj-e|48IMQZcp|y-ksK2_-r1R|H{3-DeW(+l_w7SWz{k*;Rp35lx z(#CVionE8fT~b|HRhqO~TWC^AGUpj=ZkA(oOo?_4d_5>lP9kX1!0M1Gjon08$1WjT z6yO0}(p5rtT(^g7)@&A=7R2hyRYQ+dPdNbBOtqV#i%4i)2`;wCf;!;cYPU;u(hN>h zLchmCei`dE%?gg^Zb&HZ0O2e?dBT`d$8mBs&S!w03Tri% z*B&~d`kF~~XW4p$$JE&ejYb=&RXP^Y&>zT0K`UXOvDlPT`kN(@Taa;%DULTyFa=U3 z?jj$&d^$uQ$07Z{F)^eL15{Y@gH7L@$>64=Xu!{B5NcX1v1#Siql*^E+p#Zm67Rmi;VKBkBwqz z+kTd%G4~0&My&R+FDdGv(3pVx+)~wZEbknzV6;%x#S;5ck8qBqv?!;@)i*>lC^FD?&=)NZKmLyNKyAFCkf)IxWq((UGs~NhvNa}PrLU^dI zgONb`(Kjf_&EJJIh*@HSuQ)&I7eOOB0zO|Gy!}@vDH~z!0_i`04i$ zxz&NOp%Bf0A=(25?}|asgf0=aC=PxL8h3Zv-Ad!_nb4l7X0juL&I4^C@;RSk6hWBar=W<`!3p=amU~3X?0E0w5L(C z+&G6W_(ohDzMO}?@-&m}$Aer@vv-{Fjet#lTwYNw017+>y24g)i-J(hZeUpF9j45m zHIbP1AxvZx`C)A`_&uJ$>Lau@W}J93nyo{GJfD4^dlUS4^Gr5(-p)XM1ST()hA z(vIUidIYwE{yMNb9qvTV;L)Vnao6t>_;G??$ENeM%ah=BYQ>RGTOj_W3Bj%y{hB-e zB^tqQsiXu~yUL=MhsFuUGs%efSexS15a4G1~j3O^-5mPle9=15-dqVX6X-NBdq=wpgXs17nh zJ{HV7JnmT>gJ8^7pky0JvTac>Bc8uckhN2=bs&r9Q32r{LP;?H5!kZinooT)lpG>& z0b57G^qTtVU+{k(8PC@KE_~mPbMWu6LHQpqiK-5c|Cb`6H?cKxafwxy`EI7f1WZrb zI}%A{r&-8I15sGnpwUYTL89UdO9N9W!EdqO9M~Rj^f%C?5`baAJ5nJ-#NoawMd*!U z9)c;$?0o*Y<~Yo3@c;AY9j*`GJxZ}&Z3u1&Z7b!24y_gK3>q6O^kZxPFKAHp4kqFe z_YE*f+uSj{4-zh1=4zRUjw`j^YVk{ew=TcLG(g}0CCJ<3s$E^M8#EYCg(sii15ZSK z>a6oHkah!1jQ>0~b9~p4#dq5VBvwIRY4+6IP(?vjbIJ(+*Bg(}U(GLs>y)Mj#~{Mn zcM|e88;cCO?3;PcyFn7`-wGqNsPDSaZoVhO(`w!Ge8rV?ADYK z1SE4n65>p_-joOaDR(Nd zpQ=u1tHMY)4S76?lxhpP#^eVUP*&Eob}Z~@r%K~xde^h#!F%4EY9Igd35H?6yJmc^ zJFUq6xATpvm!p~Kzq@FcXu3udYGDR0l)`Algce00%*lmtdL%MKVDl zv!t5&%)|wJz--?`~H3 zr^4WGwm*Hr+OTbRB5yyZL;aoh-H7~;gy8&Wqy32oahU%!qY4bpnt7@WGKd~949B(V zzNW%_QFr=X5A?R*;UM@$?~Z?@n<-ZQ?S%az8r)?5Qw9@15%!f-atoR6q5JB9vE#Py zuls5M_a)(2ZLQV*_5;L@EQPHssXJ4Wc@Zh{Hx}8Ihq>|W)g=?;PK#dRcH+Ay>AG4k zQ*s`Vghk`8mS8n&dACOCW4i`Y7nv)@g=}J;1L<*9R^;1=Vv`43 zxebu6Ks3e#>y@lSI01{aYPbThuHDmSc5xrx__tPSH6AFuu}VT7r@ zUnZ}8SeI;gipnaR(sx5CqeUa{In@UtxF_iKJ8+jm|o%eFOmgM%2HtJ%TwD%^PM zt7%cL$o6$u!D2SdCazdk$^Dp@OF_$tmgK2Bt+vA4_eQSRKFcWkg=$1+osXh%-7X={ zv`%a3A#n}t=#)G}owygCQ2kJL%=VYj<-s`t>M=_2zcg*OTv3!*dJ3X3 z*OJoYG=gnPh>yu+;*K>XZ((uwI_rH=CPhrs%`!g(Z<5|hH<{5SYsY+af-f!Sw+(S} zIx%SBl3~z--G85)OO%U=`}H$5G1AdfweOCFVDiJoqKAn?1XJMCyRsZ zb4k(2MMiU?n%IF~PyGQhSAl84A?Ry&9Nb#D2@3n=S)cbn>fsYC_TT(NKEUdlD{-Th zYGHB?E;pCd;<%VS-lwN11w!gYu?m)v`aLR@)voR1x*l5S%$yZ+YIGFAQn_&1_*zwR z`h;s1u`1b{t8eai$I&YJEHx z35sZ-fgf!uj5zr898 zollW?yk|UPO?|fhI!3gIGzDuFR}vr{N>T?gg7i1IYCEhZ8BxLp)>`QzZI)byi%dRw z<^)*Gwm37Q3~9`aCaK9$9fB>%ntjEx69CS_?exqQZF>3Knz#5+hE<^mJIDGhFbLHc zGgiIT6}Jz=75b1@C%r6JD_cSm^%JwadLvh}l!vf#1*sImUas_oRANJU^2BYz+F-sF zTYt`qe|gethvL+$S5YE_o7%Q+{vNZ?H(a`sJa0$And}IoynU^!0Hmde6B~_oDbm3_ zDwq&wi5gAv3RR!qSFBbtiG&<(wl>< zR9M>EY3ePmynT{(eVx6%rC}A=R90I!G-{pAmDSeH+Pc@^`!&@{JDc5BZ@tyTG+oS+ z#m3P>Gqb}oSPyih+nFXg&rxVZ-tND=&P*?0dZRE4`Vd8-jibZbtK5dezpY7x-c@tY2DM|IMqi|LlDCyiJpUpUfGP6<`es3|Q! zQ7^n$cOpRi_t7Fi3@&QjI%C-&7UQgHM30|~zlDc+6mFNSP)rxvK)m#=%?5vvZ&Ja?WG z!rfcqtK}_6yrH4a1R-ykf;UEzFq$U>)3s3WEWB`2%*u>^t|mwP!05*GnlHRaQ%o~E z!UKV8ITeaEJFsZU$-TSD1ABj^VI!-nv~;%rCcec+7{b+Ik@(r1bwl6NQU z#=O6~llm`4A1M6s-B*^IgZt@MWSp_ndjNi4(3eANo(Gb7m_vxXK}DW$a7Q%wBT}BI zTSsM*^5!v~Kpd#O5jp5k`y%PWg~0p(d`G)Qh@F-V+|6+s#7v~$&i7Z&U%nv(|WlOs@4egmhu zN&SfJji-_dJw5>JW#0{3%cY6=qIzZ&91+z*(Y?9miOi$35j;MTMhkp=V?@5+-;Tqk zID9+z**-S(jYqCJnn@d#-5sFWvKpaQ)M_ zZ9s#_Oqs85u5MF@*eRx@Nig4ckhCX7GhgIk@vzhs$vXXSnjyX6b$&(D*{k z1#fxgk5NT>*oPvCN-6P^eO!gp>~rP|7+^pKR~+4cI2?rE?YpKNiRY~C4ZwWHG(Jn~ zgz7s|zQP{ex_6-2J2&(XA3V^ZXYDyJ{Q)iyen~JuFsT6fn2h6|jO?BqenH25QReKM zLLUVDWf<}4k!iNC+86Z|V0Pe|72WYbpLFnEn>ZHc^*sDI7KxWgU_DyZ4FwL|7_A! z#%;84M(a-$Gxjav)o|JnIAl`cjONk#amQ868P_3u{@`jz9Wjg*+EpBA76h(f&k@XO zLkL#wFoo%vAicO02Z_LNNc-G3mU*A7`C)q99D}^{Hy?P%Rk`JlNP$LI28EQ_0{P z=Z{Bl264Z*Ln_E6YEl%|g z-Vw_xJY`Sz(#^xHIq3MtHPKN5v)u?}bgn4E#JW(YDFabcjB<9uwk_Fjig-Oj_@a{& zA9l8j+W_zI@lPwBCeF91>1tS|DrxSdp?O&vrht_@Rnb+DEsw7#!z*2O-wgWfV$8+{ zZnm3gqpFhSv(|9JJ0d6lLr0~F$5v>9E<;HH8q!p74Dp7mcH)LdQ~3L#UKJj_dK0It zVBMg2{h$!vd7(cL;0uNDo%3Xwz9Ha;5)`euBH&Hvts%OEe-DNF652s@nRDhlvs)I* zDCn!Rn*!u<|8)NdTvPRsXMO1_mMMhF@M!Hoi9#Lg>}`h%X6fEZCvpERTXJg3B0YMV zF=g>BJ;mkYO~udG1l2Wo^rPk?h5VPXgXQoKIx+lgHmdyohR4o7MvslDvBTx@9}`4A zSx`@zT;K0o9yzsQ=BI>w&0@a45iWzsKN0dhiJLmjD4kc2y4O^#khj3$gFhsUo=3VY zQ$fSQjcXJ2TrXyd-ZinCZ$|H>TeSv~mL;RJm*&5yB~!;jD|=^LmYPPj4c4Gl&atIV zW1OXICm`KOD;jE}kw077$*sYU*AR+-kg^P52N8y!-X(KEOD1_~;7{WxanD(JC~z$k z`{6Lx)mbw|bB^yh<%q(kiJ-Q1hW^7}C9k3Ol^zJFnAoghdK3S z1MNIFE9WiFJnkgjrG%PEd`YYRMJE^F^jlK=&)F?Mjvn?bWSZ5Vy^3U8Ge#N_3le!d zsGObg)vEd*{{QSX{iSY*HHJ$`^lcm44*9=vn^f(r?d;v{{yR-GWmg$V5oKUL6cu5e z1?9TCB}JaJR%V$-n892@D$y*GbiM4||6(-!V$jU%tTFs|MVWKDsW8EY znNe8xxAgsR7Xy!&SZfcsm+SuiR6&chHB;Cxig z)H@ZRJ4X^Z0g0w05kpF%s^xYC8VRj9G*lf3Q;kF_&#H-^JuQ@%XdPn4ERI!;jY4fo zLR^KBg07iW(0s{A-n*2k{fes@LE@?OXK9s685b1Mfdu+93yY4)MPkW0XItfklI9YG zNcW+dMlgQM8;tTah>)%!-ZH`bhKZJ;3OT|}RF)v@ntqy!WO39dT>A&fl|%cSd};hS zsvipBcu01d6o?ONae;M9L^mS#a?4oNYl#&_mrq5{C{OA!aprn(J>TRF^4WR`Rq85| z|9JrKseF&98gB_!82=akhmB;uxRMfCMXeIOUCpDc&cbG0-DD4v7-Oz~!aJ4xE**1AQA(O;WqdpOFB)@^yWs$IHIWYZ zY9gM1aH5()VtNu$jqnr*#t38rkHdR^OC%uWIJty@$GxMOZwuoz%Z!=9*=rpu;?@VI z{Oty#7wZN1jz&O(IlN{@r5(V;8}R^y8Di9dzDcs-M`%}3epZC! z*%IlpaRU{ib6O>LpgOfS6_KbmY!JrRHQlMP?k3|0I^5JPP0qNR4-SJy=yw+v9owYI zIMw{E5`5heVLG+J?TzKwe(h&Is%+Cm6zG};)$#X*hu2oZS#`Y`?Y1JphsgT6M_ zUuFqWwX<0(g4(zt5F)a!Gd8YudF@ye&GS7cd?*zpg{Xt!`4+AlAC zkgnSnLor=%*#C|=cJqAJzYy2-jky266!YH^_ut5bDc8zKf*1q&p~wjHEGXXoiz+`< zmZn%{l|Y=q3hzVzLL8_Z2e;jIM{(uv{P)A~i{RPE!g$}acq^}G4myw^YcjKq-ECjL ze&d(T@cjNhU+@4=iMK-hlMh3{o4XS_`moik5cf|aeTcuLO_3OZ)1llVMla8U4%<`RYTg|nS#1f=P*OIzs5Pr)itCAF` zu#O?#GC`QFa}vgRJF(7&w@UCsI*H0sC2@~11Co2Y?nwFE*eer%v_*M9Hd+*@uPSk! zRciq~6+MZEbw3F;%dcPXJDIDaTwNl8mbz+axApR|?eSm6QW%#cA zk6|+Hcmrwff>gBGTY0JK&INXOLT1eH#WI5 z8~Jq;KX@_5^l!k?$Zz8@w*;jmdG?KO(cR;S{|#`W9uU?fzWONA z5A+!ega&JT%1Bl}z-cq$1qd_1@CG{l2Any~2I|*}kQ_@QT{cdjVsuWk!~t}N)}{h7 z^@a_?*p{X{HTQC2F97Zf!;$you;aAvu{g|l{tv)u#>u%lZu}E)-2VWa z&_4lZ^k0B0{a3)zxYp@4Kz#$Qe4o?uFTf$bT@humLdQQe|102jV!FQm1#o}qF0C)m zw9)nLL|Gh0iy&>q%+Su2CXmI^sS;1t5K$`()4lpE6RAv(}? z=r2}?X2Uf@;J{&BW?6C?O0mYW1y&X+M=^fAJ*%qjmQ+x|i1rHlx)B+u%dSJKIa2Ik zua-C4nlVIQd^&@$Lp2e4MQOxk#E}h=UXQ^P)}jT*T-$LIZGfcswOVE3UY&Pz4Zl2c zzkX1+XWPhET(R_oU+y02(jieVSFgB1#AwzCcP=9J8}U?l^R|t-`SwTtX3_FhATax`5Gefs7bpZd!?)@oY=EQ)a@C~ z#mZPu$4CC^Ggi7GN{r$3u-6cLBibHoJwhNOUDjX1AZ`XP`sDSLo# z4TrlZOHgrNkFjv%(tP6MbA(KY2}wvND}u~)0&}pWagvF*z~g3z9r9BjrY8U-MK{8c zGN5NpkKY8@F-_6Ho9GNT;2SC_y-W$bfb?%yKzhi)`OjJ6c$ZJ_B^9|L>Ai1qk{oNs zIOU``PZ;BvkmIu$$=mfC_tZPd2ZQX9`Dwxp2S>RW8I zjY;|=HODa_N7ESNH6cgU7~?r1N0%7lnnU-pF-JWiN81}2b02ZheZ~urFS-*+P&AY+ zI(NiG#&3LMPI^;L>|?*GL{x6ZMSikEj>|K~t&`%w8{t6TiLE4lG9G%M9Cc6}ywZ-{ zmxUa~V~lIR)?ISi8B}AW=Kn@^Dh+4girvE}$n65JOklf&eTV+z#sgRR5Xc3ezHciZ z>yPE@N)HOaB=mu>w21%aewLaEsh6p4FnMb3%a=JVvVM_|kOi~wol;IA|8uwhEBGK$ z8?x4Y@Ae!p|C@UF--FM8uzzAx=G~D+aR&O6ZL(Q(Enq?XiHerUEG=oEqDHMOkt^t8 zGgOnCX>Z`9TebR^T6ZqK8t<)%$qcal$w@bxVSUF{P?){ zGT-L<|9pLc0H_^I1I-LZo?GvnI^_zq>1>i4 z*haw-Gn_i)Ux)MpqqUp`h7*g5w^X*v1K0V92d7>A0t_@Q$A@4q5iB2zt3X$p4AocW zRoi~JeLK|NL+tCW2V1*K=5wwT@oCh_6o?~!usy(U6lfc1qtBcM0$Po9Kw&$SAM+VT zRzaeWFL7On$c^5lMZ9RCMm{iHiJ$kscP{PEH^Y`K2huBq<{#%Zyi=lY7MPEO2!#R3mG15zX2xu>X{ z5&Q8zTQCh@It+J@JuAt{-z-~Zi4DyN%bU2pbA2ciRmi_zH_z2=9ISb9lw|^PlF(bf zrKA1$&SF5x%)VVa;!?KBPWaSdBxQO^$6Lf2|87_7>5$&~Q|l)j7{spn&*vR)oew%( zmvGRi)vj1zrK_oc54yl*53+osVZ~N}ZX%ein!(jhTGD7oQA9Qr12%AWn+`}+?6w1E z>^=Z;@OGPxz%tnM11P{l!^zBa&OmpVwYY)Ja_1iq9aqm8$Jeh{h#DS^qS#m-9-;x@ z&m+%r)qcf(AJt#5=J28SK@I&X}XabLWMIFfkkDEmu(=QJ`)Zr2E7xHiYFX*U|)_hMx$ueY&1iq6Mv$ORa7i3@hjBug;kP% z{(*H`yEQPyAKMCodxxYy&mUhY)zA%kIRLKht4UVAkX}^HP~RG7_+nt3)E}!G_VK~> zt3X!%9F3SqbDsS4!xe63^imb~{rperAAd+F1`Po4eU1*`;AC&^YUpG_Z~B+N zoZ(+~^7Mamn)??LN2;2wI+i$!pO}Ig2_qx@*ceN-EpiK)NLC-2Y&1k#S^yvkDShh^ zQ$p({ow=q{R^GDz3jLSSoaLNk|BHBQFLPZ3)hI3g^PI2ejq~Z;F7EI5kN9=~HN#Oy z%%2!+#vUl*Af~XWl+{am%MGNaym8~Ndcwk9R*o?TkzwUnd6ph^2jH;VSbi%5#v74? z1{m}|FFK)ssTp!6x!l%|+SE_g4eIBT8)ts~iAo+Mm~5x@Pua@xin@<7TQ7JFqRCP&VU|l4&|#Ow7SYP~cH$kZ zy~YV9WfvH`)lO@vU3RfvbhC8B!VSk9W20Uyhymii_^r5p#n69SE61O$+(G!>ha_j5@gPx4Zt)#qcl(w&1)1o=*)B zhkYDiMR&lRxf)={zk4co+V690$@=|y7Kc?Jxc{U)mwm8P(D^f0*U;lp_9!>5AsePW zi9G)CnDV1sFuc}tE-*69_P~_(N9p`_C~H!^JB8+l1OYc&EnPQ!L%R5%Fp58=`v*0S zV2NVaBj#dmjg36<8IhQ`2ECl{9V_J)jqxMbIUY_K%eVo{T=LJ2eUQ@5Z8XZ}!o7;BpZtsJ9|39D51Jkc^1JWHt`&4`=4mkLZ zjN_x@Iubx9iHAh9@lMo{);cB~8v8`kqps|BEdmF2XuAraE(GJZ^p1|pu(AT^;^#tn z(7Dk;*wa982T|DVAdh!XZ2`nSx`+-b_0@J1FxSPACXYrgMs{2{`B6--htgVf$_Xtl z5_)MVK_%wSRuQ+y3l&w z9Q4+bkw%7R5vNK?OthAoerxO`5+fo$6}@y<+;rYHXgc?qY9*x;-~T42nf|N9fiWQ4NImr-EMI#@wo= z#xQuuR?P05;bU=BS|$7G+l+P5j5n-{R9j$P7AHhq-QRqPxz){xVRp$3T%$ALJqrl! zWR>049!3}*{-COT^PxL}yNmh+dJ~Z)qBsKi z63Gpb7vcLM0>VUagc1xdz6+i{B<5tTld6`Fz1Wml`TXw6SrYY${D3KMi(``vCe_7d zI{iwGKnNm|b3OxpCTGx@pt96Nz6a2EzK@Lve{Cb2OYst(-Bq$RHq-u!T141T>ul-- zZ(FUin(ND*eXl~v?kq@`wGvz!;*zz*3Q2sIuPQJ{eQ=arj5E|{n^!KZOfpLGUCOxq zxJ2>hpFR6gQ)=xYArb8)Gfj&HzT8lsXV{w_D&41@ksZP^P`T=(o#}w z87AB}QA?p(4dP=ZPQvb@{j5_dird$>KajUj7Fmz(FD zd8{$rGNDX0W+Dtm0?UmxC5vY7POWqy6m)6|4jL%AZbvU^s9TH#mJ4gj2sip@SIQVA zH>>6a8+JMyNkTh;rRcIWq3+%3Q&&ozA&*>|j;k^Fwi1WU03UedR+Q(B-cN;epk7qk zZPi~B)C?G}*tI78VSNJO#JK$` zD^3kE?HhFF2c3Aqr=NI2Eu+VKR?qeRfOVPW9R!?8A?^ke!J!@CI;cFQV{YQ3di-F@ zYmYglJ@UNgdny5@eJ$WgyHVWvWNr);266Ym9s2I~tarz?!QvF|MqeVZJEXXcuPx3c z4`w7MHOBFNE*vz<<*rQ{<~;K=GR=5CFCl=&1^yY{krZxC2djz?JJ(D?#439PUWl-K z{+FEcuk#ueDDTeDZ*H*5_g+BtuQ{cqJ-x7@v$3IxrJcEmp^KrYor{yFx|5}gsng%t z!OFVI%K|98+aN;HB@kLDHAMtMP$(XtJ_p8Qjl^*r`=`PZ#*oTbWV>9ylpo>m4uj_+ z;P_t8g88TJugb)@5XR0QZ+5eLPjh<7-=01`-~k>orU|1XX}lcdLnrl)8B&c;DrCZw zLM@@0(ab>KtLt3Wv6#4a;(*S@AAm-u1X0$s>{MvM4Lw^Q-VQg@Km%_|3lJwhfTokt z+4Nr>tfU8YAglWX`jA*Y#cRKC`MoY~Rx~jyLh`itoQegmw?&n2z+?j>;Wkj)&pTHO z6uGN;Zbkd3zg7u;@nVXF0}WGpp_l7Hm?TF-!Ib78Pt^84d;(*J#Fm9JNm}*oSWE_| z?WB}!qf?Y8sXXtr*Hz`(5u9jgiHm#Y3ftdQO_m-!_E_R0QsnGW8HD2+L0f9*>han* zosE?+QMF^X5zXtvr@)W4WX@C3VEbY;FG6pRk)qZW85o0zV!JbtG5qGgxo=(Wy09x& z`?0ZE90){=-XjMT>`(v8fVdH&{f*Q_@N42uT=vs~NeXS9ZtWw%{Oa_E^Ac>m=K*$z z5|{W$27maq2Ahrs3mE_T4%y2TM0=?rjFq|$SxS(>}Lq8a|oYra>sK#HQuhUlNv|D z_=tCrXD-I+jH-$oa{Gqu!z6_+3s=h>ua))Y+7W1!)HEawASr=d$S(yK4~>HJsbHFG zyaDN@-op|-YsNS6Al^qVTtCUmug3NMCF`IslJC9+!yLPS4ilQD za_F+akG|;cho?}s0oBc8@gR}KAv<>ljmeyXzrY5BH%`v9ATr6Y&1$F=Xy{u75H@@c zm7k)2hfjvN)9irY3VKf1`(V8FO!vl`KTMN`LG|Y+?@!-E157rth`_W!_fKhP)M*9Z zpIzRD0Ii4ve6QrI(p-xWsx_TUE9E(C*mPt<^SAr_6K6kmP0o)6$lRCY^tO97BbE*+^o27 zB3z9D=_R|`dVzDUC=%F{1{&f)r;Q0BMvE9tq$xGQ6*jk|U${@W+$3D1=))vp4{d%i zi2P=J6DRsInXH~{Mf9X3W&gqCDfST6tNZ>R4!I^Zq0O1!aVz$_9{zt$x00!$$v?uC z+T~xqWPf&9&dIh@!-QxH1%kJd!qORzij`(j7#^5aOjX5(teogrvfPCdqgLi;?nD7HQDpCpBV^ zj1r-l@r1B2AvH0vO4Qabgk0`Hu``jaLsVP_@w*1{l&7X*3i zmZhW_(+U578WS&X%DD~6Ab;g{?<-cv5vg|WF@ z;)HcI)k5MTvfUP_xeQ?+W|-Q^#e55UV+)he0b76U@$fHPN$#OS6di4!|ys z;A~|`panprf$~|p4=2_SbLOm{XPn9!=F^G{Evu06f_iL)$w}i*pxni{3!~?u)pAzZ z4uuBfbJP<1a-mT1BW{E@W4ur|qi~S(lpc8W3C&!HkRRxnTs(4(?^w&OPXY+KtQ8%! zgRe;;>8RhrV7-~*7LzB;f97>ys~Gyr_FZ)n?!toD@6m?MZXZt{sBrU!Wy7U@+k)Qi z8@<6)HMO=EVAI`pd&EnbW=j|D`|2n-K;kbrre74%UsM$(qs%W_46c~b(jHl88q;M> zX2Pw{`d|_s{3VcSY=yltMn~NdB>yei{{Umnb0gxZx-)f9wW^kyt(`+5n!fn!E$Snz zcrhbr-XZX{do<9eZXeo5a&Wbh9IEKhjl(zTS$22k;UpCn%cy8bijUe4^JJi~wz=HN@ExB@6&BwYMZ`42FT&^akyS$Y0?YMSw^(rpbg*AVKp#OfP^)G7a#H+cmH zbIc`ULuNN{tG_X-6NU-w6Lo;YUT6-jbX-1i&l$+%5Qc zVt|X{X?A!+Tew2xk?NLP3eF#sdx!6Ou{zWL_bogi4QuJ{H|-arnX8pt6icER5BTdHmzR{TOui?v%|?*8!c5Z(RM^ZnN0nO_6|h< z_$}AW5xxcP1Q%Y;cUR0YlX^4)r{r<>O7}49(`<3G_viDTJfPY_nj_o?=s^SR@Eya> zKy-+_WAfe-r+vgpbqH&X(@r|!Jw4xX=YT?jBen;@J@i#)h!SPo0UjHN6mogv_*H0# zW=hB=GWi1so`VVp9uvt`*}9$GcKf?!VZ-UxT+A7p=}b25LCUtLYy3nuHoAQMJ1eIkd>|96Pr+>t<)&iY!+K z?YhfMjb$9+BX~HX+qeaDE;i$-C-vzR*a=a59Si26s^5A38Z+Le@~DmLCQUkk7YN0@ z)qG39{WUITD(&}qYZMX5t%XV1$MdG(=TSP3CM^&c-t2F5mBh6d6vGxTHE2fKrDxG)yHYOJv<{bPv zDb03@Ut?PeYjNg()W#XGyNHV;aWTR0q7mFU`;ra6??19tvJ~K4?EkpTg zi$Tkqa#S!;1lCS4IEpl@Y_DF@wbt2pPOmfqF|ZbBQsAb=5Y|Mc<=%@j-Ie(*kS<#- z)zgy4{@kk=bZz!s&^|}U~D)PSH`F%XPXZY`cCLgTOt z8Ve|X*@wJvu9{;!k*_ls+je9VGw(OuqTpcy0b%X3abM$F?R$EqR}?@PD)}5gYRE?2 z=KL0R>5E{O=#%WGx*mSy&$|dLP17Sxk?I$ERhPeS0*_A6A<7g3!t|zk(`?Sl*p3-9t3&NQW!$j*xRgilsZmuG~YIa!GuJR^lrX z(L0JnIya)hpQTu&JJxS#h*w@M_06e!W}urR1Mw(|X6DUW0fA5cS&8tAk@OiW`Xi%` zsu9oZmk)lkYUm3CIZd7_L@AEw3t?~P0Qi1O)-WsAH1a972RL<0cO(?=E^E#5Os8=3 zKAoQsB7gC*X@LwPXNFKz(=ggKhc${L8s~^ePxzasB$hfQIS&7!?hpZW3J}HgsBTtAQ45{ZARdql5 z`}+VpMnn!o3`G<&;o5svLnd9^nh(t7oZ2*-;C^geMJ=%Z-0{c-J9Q5UKEDb?h_+!GzIB|$X_pc0#e49mpIP(OXYe$tVgc<9C<_YB0E;-M)H!0o`QW0G1z~TXl9t6=0DE^*YgEad@0W11 z{YmfMO!rCeV)8Ao3&Oy;hx8!QRjNZNF3|J+K{M$qP94?YYDXA+{^>G3#mL5dr8TLJ z`8fJLDdaje#i$;p{>fgw!wD>tor*#bBPRR(Xg2CjkT$80>XUHFGHO%c2pney|jB=%)L~{^q6kb9pWQzBshr<^}ujo^P>->8|D4cFC;P&5>g(5 z13}OSj&@Xd%8Y19P+E@+YZ)Pag$4j{QXHiQh;ULI#r<*kw>yaT8^yXcVcla#x`-F= z6ojJT+Q5cuPtBUqnNi?L*z8Y&hQdl&tf9k#?%lxJPfI#DFEMR!4+L}LuHeERQzLDG zyg z#SU)vs&-2pDd}dKZb`zDAEGs8Q8uckxh5e$;%a8sTNL2JKxn>) z8dF0Eo=0*=mYrQ-z1ULYyCP(b=4Bm5$J8@dobAl=GxppjDpt~EbS@G`Iqz9pP0d1) zn%{aYoAq)g>j|9LWx#?ezcccD=Y&jVu^3IOc|p7OGVy>#7e{up6vM3)MNS?@x13{5 zvfg#cG8e<^7x5AvH9m~klK@YS8<()Ko6OSHYNRb<-iMY;1X3xLyu*1)>wySM0X_7u zX%*k0(adQ;s;)bbT*oBnG9%78<;6%-B)^(N$xo3XdDTxCesxC_`AQG0`HBtzY}L=8 zTh-K4H3^Qg!}M2F(%+F*bh04gFx=&d=|V00?%*v8R~_3BdE8awFxWfTDxX;WiuW{m z#t7_Pyi|FoB-zD>pgiOU?Nol@=*y?(dwf!V;()T<4n$G=$EA_<)Ecq;6Yj)O>-SYr z$2(cuI#F;S{gv*`KSy)y4)beyqF9*ui%-Pa`MW(7uz!is=1N*^N%FAiMD{D~HV~z*`jbNk3UplI8!jiETycfzX zk9j_8YHQM(&jFgPA!0y^JJ%dSi?7|qjJ|9kxmc`dO|LDJ&fF~4h!%N7U|mO(&$~%% zPU)HfNs*AxQ&w^3>2&I0OB9I5i?$RdAs!zl8&=|@iCS<&RM_I^E8csaF?IEMNIn~zER~ge~0j!MfcojjkhRRf*ML6g0oRGw~#eXlN zcJaHIz4On{AM!stNhN=ctxpxNFe?cS_KM*Td)3{?VXkf&xa+DwTX3Z6txjJcezl3H z80XZGasmHJMR1_Q={ZNd-p55aG0u!)jKweB)Jj4;(_YO1v94=5FnsfinEml#$ZcS= zU@KtD@@|nM>rbF%!H3SESUX1qWc(@2iBU3?iNZJcu6mcM?!nOyF zEgJ>;7-#HfMFx3x&l`s+G6h4Ot?h%{uqra?);8Nxjhp&PvPu8ztNbz3PGbOOs)e996ZgCH&kP(LWw8bt@tr-y z+?{P>_VS6dM0SW5eBzWNJrt8@bKDql%QxndMc?p=TYhbyIL#RBALSdD`JL($r};@O zZ^Rb5wR|dVB)5!#mD|R+!WBKX?|>FxxI!5#=r(n3n{4sCO@46gyqSFWhB~LH6Sc<| zx0!5Fn0vBRpX&GUj?37@$)8qq1i7^rXO5JmQ=hZya zU9e<5wtm2Rr2X^zxn@1Oe9XG9%^V5hQx`>o{%W0*suQd2H_DmK7%9R*)oInaqwyC7 zQ$BTZkij*)^FkvtZK$RLKXOuYjEOeJn;R}(Zo>c&~@R=04qm6 z&f+lBMI%Gytpm%MA!ZIc&f*lq4V^5drhbGnX1@bXzZ*@0_Ho%!ifrM$i9aIlnVH(% zi)_I^a9h)%-9x0ixj}P*J^#<_7~6(lks~rZ{$B^zh3YK$F_w)e;{7m=?}*KfyC<} zpBeucA|iv3&LGhlkP0PKBa3N}A{?^{`KnRuh-8IqXKZJfGlPm}s&`0v3o))y^~lSm z?3w*6nm~(YvPPfQ3_mm0Jrrsa`nDl50@o(in_!FD-XwDbUmn@DY4!kxj_}T))050n z<~50CkkyIcTwn+gQ!IJMCa4nRh_YssQ0a9*#w*U^0!U{Faj$5CD~MbAV+5lZTFRcr z5k;T~v~x&S)jq7E%KPor5Yc3q*AZoP%fPxKdgxR&FuX!Nhn7wtlM?c9b_}72LcADu zz2bhgLERHfp$HWR0ggyq1#%1JjX*AC3LW~8Kv0z;8mgotqJr5S%^R#(G_~pI1}y3e zfC{u>7xl$J1)53J98D3fAXxilR8$qh)%1l_R0YbuE#k=tQ@(H5n}R!Bfq2qvHNJSp0Z#890 z$6ZSnTd9-Hb@h3vOKUL}i1J1o^AZiEnz}VsD;(jPc3Q{~79OGBrF_bD1E;-`-pj?k z08a!-5rga%siH`v!rOdT$fJx^=g_4#`!3)-L}}_&DM7oFl*Gh+z31H`E)K!WI)TV5 z3!&JL_#-fNG-5`vI6Xo7L5?v-ESBjAXPG%j2?ww__QqBOea0}1<|p}*OM3`JJVPvb zhM{@?8md55KRJDk*(Q{wL9lH={)hjV44+$FkkIckpz8biAIpJ%odfPC`*l7rFfd^- zIX5sjH!wIcu;-EEa*!-ZP&&Q>aB9yNgAK&zmB$4%=q#`NnSqd?*y8X|k zqGOfznH&`{FvJd=1pOqflJr!Kw229VSXFKjNaA1si9|m+BfYLZemehu>Xd|SjCD8l&DnW&e!aDnmr%QKh5g{xZO>OV2#4$8IVS+)|fWNB?UGGo`O+@yeXqj z8r&&Tylg~6{Ct)~fg2;b;5H`pE$9B~mXx@i5~$)G3j3;Pa+6rt3-^t0SV#+8$Bg&V zb0P5Jt3Tc-4NOOCYmlw@EH@r9 zigEBkgvpWbEj*uT4oShqH}ES9d*Q!Ri6N)iZhhwUb^@KXd>yVncvL*RzyEn1 zzS&Bw^43{0D3sUfG5?vu@+@nzsfE+ZvG!`c<{xkod%Hk~Jj=6PF41T!Fm65PGt8)v zQPCJ6N^oyPb+2&hSXW@p5nPxrEU&wx8uyq&C)x1cj#iMQ*CnX*k0&N`tbrnzM^>nsL6qBI`|Ew1v*7>l5T3 z>sjXq{6-pK%hU%ZCSMR$9c!W2Sm^}izch76EHvH?&VPm2#akkivDyN^#hArew-K&M zOKoN{MIpJZgyCjo(4aDBC8Hxwvq_TJ#I5|eOk%G)791Mm`XB*`lQn+~GCr;?0*a+< zbCvF{G5=7{eOWWDjNY<3UsqcT9zhm&OE$MsqvO2T2unTUOa0h+RC`v*DkS=#NT230 z&Q1D1l)ZC*X6>>q+#TDtZM$RJww;dE@g3Xl*tYF-oQ~5mI<}K@KkwRW?PvAg>zv>F z$NT`-oY$-|s>Z0Qq>0;9me(ROu*f1QH__Gc-}4KFw8(H@*62|(>TO7^X)2o_#c#-Y z3kW$ynK>3EUkRK*(0Q5j@=@1RZAT($+_uQkz3UXj(3ruo(Y20fDB@L^!A1JS&{GY| zTj3%XtCkF@)q7{@Ld`}isJ0?Nbi|MmDm1d&3djdcW6P+v%X_!-}(X3lwL5(u=dxS%(~EEg2z z6riQ$-D#3nk&eq3`M;^Oe4R>)97uR!Rms>GQQVVkr)`=%ZZEW)Wr+zZ9HK%vLKq_M z_%(`sey_Tu#bHp#rldPAC_$E8E!F1Q^&lh+D&m%kaxa?maG_n3%DLEZW%`_)V2;9e zOJ_-b!%yPYqfT{%VGt}T_mk&sp7fJVZbRP~qq|7w=3Px6n|?>%2Il;a32JFmb~=pS zxyf?e_7gv`>C23te1o>14!XvDxp}86JWM!m3}T0ZG3|CJZfa`fbj{rld=E~Gd@1!0 z9$_>n_~N)7!lpzbhRwIbhb^|FDa?s~m23v-;qh+mdc^S}<{{SG{(_>yIUaHH;*KwHO}A2uB+V^flEsi4qFN3?FRk`2Px0oAb93kgiXXSx{Q(7G4PC zLJ3|M(K^T~%&t+}H=O&mz&=-xrQ_fKrS}mJXV2E*5Rqz__i)BT5n&7wxi#pd^o|0fb}YyM`8;Ld8Wm46*bI}gJ&F>x z6U;;}LJ$muK8?p{!z@R5c0n3^ld?jeK6 zsVWIOH)n&(Z=c_w`l?ebXK+wwVK!Qml9!@`#Zi9%D-q%_3aF zQfzZO(!Q9fzbm#BI)y4iXQPpwde$Tz+7JCs{?Jy4$lFx>fsnZdnXgJ7VLLsTXR-J_ zZnt7tTX{j(3q+0L__;nun-K?YA_wk`kI&H<7U*imwBSIy<2tw$~rA|WPg04c&ZA}IX z7v>L!Uxn7)r0wv?twwyE3yVeGa?1n?I+y{s3z7h0Jc)a>-3C+_RT<3S}9xt#4NS0u7aJY$a@0$vlqQ`?iw}lYFCTd72s4(8R@apt(Cw*W*8)Y+)G- zI*GUDDY}f2S1|Zx0uOZJizQhc7=-?)bZ0BN$kcNjtHG0C@he!>bp+HldOLs@>zV&{ zbbv~xlo9Wz!ToC(f2ow=U!yqB|gTKLxUX5otwNJI8+j;D0kW z0=K`&8-qB+d*IwU$Uj-y8AbSlUom8bPOyUfaLWCxIvr*c*uWsa{$ds z|N4;1X7)e|`(I=xIcZG=*A;E#OAna~u@+1SQloC8w#{e}a^#}4j@`h}0umij@=qso zsh=*qMgz7S*13DXE{8O7v#FVuu}4Y-ZW*t~u3l5vLXaGNmT!2MF4|tF-u2&aMsj=E zV)LUeg_6MLefxb&$Jph}jeQ1Po;%CNs<2v~Cbyi=+(x$S zlZdaG#nV~SI5n9xRk5m@%ow%SA_8_$PatWRZnL%J(HbIxEo^Mermm|zmmYGem(_>v z(NKr%YV_^2^~nzxobk=^Tld*;Vs!YCJn!!ey$uo#kj)BFTWh$+YKar6-gHDM>>wvbbhV^BmSS8V1?z|ztb)mXjw*e>m zg4~XwrmYigPpA6VOiTrZ4H|qmht^?$aV_e?9xeyku7pM1T%A|@PAJ8NQ_(-61DMOb2BrjA4`Oy6w+zHJiRh~r*p0`_@YYv9BbD?mQs(d5p%$sHCyLH zpL}Xv(6(YJM4k{Lyd=+BV&|P&{IiYBK@&uazW$> zpCmtEQeNrre;x73^^Zj@W7ACZSyeC0P;76C>WK|W;zk8a%_yat`g3eN468}X;rmM#Z9 z;3^X5g@{}wnh67nul=Uxv6}|izVg3@1(f2AgWC9?AGmswyu`Vjdj-RKu;|PTm~Loj z;^Ffl>WzMg0_#px;qH6fBDlw=0t1kPBCiy_0tJWQZ_kpD?Mr(4B?gvK6rQ=Tm7`~s z@duwd_m(<`NRJ8A(3P>F3)0avWePH7bhEPl1|=X(MW4 z^lBGQBAtZ}+Y`corUV^kASKyknK`MY%2ugio>}Mz7B@de&E*SLrv%)*<1_ZN$cc!J z?m$HL0&w!a%V`_)nxjjH!v|FmTFV^Iz%cQ^0_sq@)P_Kf+(B5q=cu$*o6--CN6&OB zZWZwWBMXxz(q~&O=3|*JR*^<8?bS?dMU}63l&mhHfa0bKoDukpr+nwBI#;{m8fjUK zY@B4sS=$9exB$Q$TzQjlOkP!;fHXtb{JNPRIx`7X7H0>Ze6&WiAa-lY+)a#8Iykll z);&Odq9$d#n>8p$$V>Tlkb0;gCEMJR(Zo3;Jv!b3kj}3(X&Q{*bGa>?qg+`s0_J64 z+4P&o$w-#{PHPqq+D?3-6=8@7wYXAEPOG>8+kCrlUvY6|NIEs8h`%v6*WyUC0Q~UK zQ+Y~DjJGJ4#p9)Mu}PZKU2sT$na0foQHaJVX<%`lbYcjKgUUL6WC+&B2`5ZrwWdI+ zZbFtpdv8Jw9T_i$xnc+Bz;sgMc2O;$0NPP+Xswla7ayJTsygD~vO7YjwQ2_|rsDCF zyXyK7KK6sEPZ%zZK))|w!$!_Fi)Un3HZ<@FD|hr!b;#mTcNi2Mv2Bj=l6>g_9e%$3 zW@Kh1jm=CB3qlZlHSRLm%TT8Zxm#`y?YZB=b4u6*GiU<+mPQ*!I$VR7LuF|Q)o;4qd}KpEVD#4fW(z`7FCYP#&7iL z)UZlO^;L(?+7Sv$RGYozEKPP@3ZI`c7V(`bH)<8u5l^C>UbOkXMlGZ;g4KL0D&3d# zH7t7G+iT4E`s|?$8a){^w{=lC%`AwC(gS8mIs1(&{I@p3pGV+XDs;;(Y2g#oz7a}r_v5Z1E z7uvxV$eV*GraYX{iE6({lJu$Z;HAmgZp5OKYV!`nAUhkop}u&H{Y0)`S9p${tr>RO zo^>{ZRf|Q)%X~F6cK26gNLUwnu^7AASQdRe92?2mSM4Nv>(U=th2tl|;+8#HeIX9eiY5sX@PyzrEn_Aq)S zcjy49k{0^cmsaU&v7bTkjX8NAd1U)uSXEd;xNog4#!;_1f`n{YgJckSs3bD$R?qD1 zbou9$Uvw@}_KQ+UjtWbksW|yiQ5R)p!%EYauS)eykNIK}D!s*C8NL;y>{=aSJ8oO*mp-(lv3vR~-J#Ma~} zIVk5lFiDnJ9xvj6F!PJDA!RluYo{XQRi`vbd51mR8gK=>LbyAYqnV=rdd&gujtSZ- z5#Aab=@MRY`ANma;l?y7ZXR@5=$K3BT0mDg%guf+z7Px{427_dI^R=rNvJbQLo_|w zx*RT^h{8<*`cONbNF01iKj$6s-S-v zG1XE`>t_5^UPq++p83KqjP>ncuXr?n&%Ww}ILlY!7ulNFEmSZ<1}a!ajNps?{4sE# zmhlH7_oLV|*E+ej#Pj*q;~y1akMgp9P2hXl2d0Mq<6Zr4Rr#U>preKv4e-%FdgSjP z<{^X{l}dy)+j`r4Sx+)tN*u3egi|IoywDds@>MK9{IA6f3KkFr1v~u=^70=!H+Ns; z41VS4f3h{&?1!qSD5evQYd{)k497-ofUDD6i9Z(*$M|OX58d2+V z?z78t`)Lg~oM!?HP*rmqw0dYJULbd9lp0gbrf^tlP4FTN1FR)Hz`+{SDTf!Ilx~LG zb_A1W@W;JocDn{gF`dG@KObT_jo3l6xBh5%Y%ixCMf98kyxOf_Lgx5~vkhFwt}6yr zXU`K)#}Tq{4a^;?7@)b0GKe&m;xGB7b9oGY@Ihi6+YEl!0E>!>RmLmW_?%z($-Hdx z*)Uc=Ky3DU58YZ@EUP}t001`39~Dlf3^rTq@`*P{h>J+eOMI_9*3z>Jk#usMtiO4L z?s1WD(zJJB1u^wLgI!~p)Ki-|8_2L(@gE6BC;u_-skTv2h`@$f=3vlpb$|S8V`#fl$ zd&p(SWb=Y*XC$3AGd-P?PS?26=JRD&27~d6d!$X+O zj_JVV(X~`9UT>!CcQduXxEPyeXK5`n=`q}n=k1(bqKG&&AMvc2&HsqhJ$62|*zY3Q z4vA|nAaJ)8hH7=8V-UO6 z9AN*5+!#FTY?|&>m;C0OLUvnT7Zp*9blR@s=BzGGBfhaQA{vYUN{xSZr0AqD;;U$R z=vkiJL}LXwSEJOXIdsb>aawRHSfq%+bLJsAqO8%r2Wj#G-M$kX>Wm5XC^Y%pz(ZhC zM_d>~EYeY^%yf3PxB8Po3uj}xA-C!R z&?W*^KmO6;F=p$-zZsP(Q+%E|qi1BuXb0;zc#IHKFV}v?_ebhmqjm^d<)Mi0m`l)Q zv8EwzA*XE2=nEojvyg@2@-y{XLeM@T2O>LARTs>Hnccs0)%(Yfj)|ilEj81zh$$}6 z?ynxEVFi#&8yS#l#M;#Ww`T2csLzbr!*Ds$_KCslg33wiA$;vlpqyr1%4*%z>j_QB z35MqtMpKSDJMizH|2=fmmdf|Z0`L47kZk|QaP;@k9io1sg8Nr@2hwt_trT>ua3p7u6CnmGoH$u3f@? zkEwI>8=|Aob?1w=!zbRu^&db#@H-@M>P>tdA?e+6=uKzTH4DZ3*ML+f><*^B2{Gsk zNe>M`RQxB3bbaG@@6WPVM%v>1n-7|uq;>yMU;_d6Y3t{hXZ z>Xd*BZ(n2nJbO?o#GaVojjqO;Ayx?8}GNt;A+R0&Jq4Ixa|{)*hQn@ z^oPXReY~xXBXT0;ycX$sv#yL7GlZs!5U_R+Ia5Fsr4Nq0nQgME1xMQoE)oD8QQNj< zY1%K6W^L@8Xl+dl+$vfYl2@4{>nMK4%)V&i%DsPn4YS~?6%bMxxYjE2hc|-9Aj-4 z)ZE}Y%7z*Z+PIct>HPWcVzX6WK@r6kpTx@olkAK!%d%j>9^M-AUQBHxXL^Wi`Sw!n z$OZ82A79CkYUif(zc*!^Q6v0TSC`8`2ay-Pue5K-M*CHDwk@}@qIxw|yAk7f7rx!` zvz&?hDXL;(&or}aR<{hy-ByYGNVF2}LRdK=&n&?@3vIQ(PE!r)UTshvKP1IkL}81o zK=xtrs}QFz{k_PR*#gPnytqLX5+a@w;dGW<*@>O>o3tv)6BWX&SDHNQU=1-&)E+U3 zug#?x&ywOzMU~?q$6?7GRF%Xrt{Yr5mpt$H2_@1gr{2vvZ=(yYPlRU%ebD)*2h_(6 zua56{Ru$YKJhzqc?2-jHv{cx}h*sC9}HH_x9*!K{Z0?L3F8 zDDze<@;czIYH;qd#C32M<=aiL>0IBl8Y#3S+0bs+s$(T|M>=*y zf@VIR&huOZKjhYa?|0p4%(-=s>kUWfiB?Ub7Ftw+M!%u0i>NG!4tAToJ)F&v7{Spd zfn2I(o$G=4(m_@1nxF_)Og*UOvITR$g>$!zcb6c}&#C~f*NdwOoRa*VR4lek2r(yo zPf=Z0(Ze0UGbSoDX{@E{CH~VpLH1(+%vI9sn`F?diqrvUCJW}mqwUF=-yfkEY(`SX9ayH^1(qrQ zq#!_*!0cb8%74_GT~)1A<`vQSYjiAq(C7kp7+?UOe(IqO7Wu2wekY1}DF{X>A!C=q zf1`c}>3I~wr)K5Z)v$O~ig_p^F4PPi^PTWLTz5{rewlvA{WP_e96^vJQ-FI|)b@Rc zgh7gx=7$-&22)D$M(es>atAc{(%yEvkE2MSJn(AygH9CHpx)W@R+I18S6;*4& z7K4b_kV{m81@8qm%h1wJ)o8k#{c0ta30%0EHnv;3degxV?-=5r*zE%vA!jyTSvZ{Z z^O=TR`Rq4rxe%D)oDMZe4idACQR%DC_1kn|X4up^jWYT5RCp>mK@-6(=IwBh5o#k0 zOTi8GL+sRi%x0cb-VxPF@DAdY^EdpfhNQ+~n)`TTtX0=(vi;fX^6b^{0(rsEs$mDs z?yxTkZod~g5|r*_*S?~oVe`nKud!$J4obBZg*(f00rr`1QS?+@R2?%dI2(~4I`y2T zhZ_w}ZB@)m3UOjYu(p>&^<&0d`9HPxC+~4PQi)^ znUz7`Zm-X7>s;TbMpV$unYaQ|;D&Ha*!_f{oZfQXqot$Aj%QNTCOE4v&ZoS?YL!Fl z(RYPHn)K%PBDTMFK683)^Bd-e+JrQ-O9*^AymxPJfw1Lc6eqh<9`*6h2;Q<0(+cz+ z`b}+>qbi6(8h~1gfVEM8_7RTSHdF>0cRam0_1VvqjZbS;=-N{{-jWFhsG@_{Wc|$L z=t?AA{MrJ)P?~jK9uDgjY`Bx=78m>b;%-AxM~+%HL9KCiM#r!6KIpZ$g&K!VTddSZ z{h&g}2=eApHb$(@W;pw9^WX<>x8VnS9{mdh_=MczDr49HaeYi7pPziNo*nTn-C6K% z+*u5x?%Aq@(pqk{pNH=p!san6NUuJhU8_o5lS1Hhs178Ti#$be)Ytr$^b1){uL$x( zV80`hy63a%5Tw>415ag=_EW}m7=(6V<~|GnG&D*Z=#Z+vl*BRa|56aWv?JCpST_;) zM(nX9@i@tN`}@mG-7RRgOo9Vy2WR|-pg2!UviU2Gobqf**-?mOa5qt)yg{Hn;0SkE z66qwv;L9WW_`+-vYyNwEkXwr7Vc7Y%;N~vyGwQuS6gWuou)1m91cNBY!TvpkQ20sk z(L()^oa`-3WJeaT+$)3Zx4$iz|4Ul15urJu1f~t$K)VF>AGOMVD0^n6|N3wLuAvmE zOxXX`)4$8*x|>E(n3oqTC}Sgu-%=ci9}8coh*s)>KD#kk7eQ;H5fikf@(A)%QWTv| zvwo`p$$hwNErNom?$URv>u{ZS_x~FMTN?n6pQt&f)SC>VH6dIHWrP9T9~Ch(J5yWU zH#cKSb?viT(R5h->xaruF18-uc7j8ABwxquM>rV}tH)a(9C{*-Be= zc(eO3M~&NQ4e@P{VIX^0^S162uwm+VSLw;Ds@<2{oZDY+osZxbU}$BHq^Xd+eD@(= z;L68vdqxa%tTTn*gc2Sv-XYt1SYyY`({KZbr_t&s^37tn+^?l$e^#_?M$+CC)Ry#7 ze0VOz>cx7@qhN@`b#_nxasoA52-aj(3^v-rD~3yADl*#e4?2NhFitUgBIFoV#Gudi z5A~jMli&jfJTZG4rKNx;t*lOo8;-IMvP@O;c@1elOMCBfv`3OZGs1iiAqtJaiu;xq zk*4%JVS#%*)hWj`q*FqX8bnrGE)ze{mqMqHO)8ts5fsNhU;3x97Xl^|sHDuT#T*J$ z#HkMMJ^ZMKltz^ZmAbQkmKoxAZ5zuAY)t^x+moci8&u0~H8Y z!Q|#BsIyf{qC^sf;41Uafx0)e6lgxd@-ffQIAyOUFOV*oEE$0&H0aO|NvoZr_%*eG zOO(SLtT+@0ObY%DqUJ(#r7EgLqvX#F6W=0x{y>P`0?%UzAVQn~5#s-O+x|}4i&S;~ znjrDsEQhO2vZTHDZ7HEqwby$QlS;ohkdfz{UYJg@oK@iV^nAs+`-1n-^kw(3<>HgMqGUe0HVRBV^y+?V`T@nSh>A3;A@IrT zIPPxLgNW>iGu^IhYy)I4XvkkF^-#8othE^lZ9KYN3#xm8vZQr^EpWW41Pebx`Wr%eTe+?8r+lO>RigZ_+j@jm@zfL zEbG|jhYN>ilMxqv%_|b%_Nff6?(5=LOP5(V2koyz)mX2H7T6bJyipG}=m}ix*tDaR7$eM7>Du zGzp6whZHRnEVlDe-bNT^sLT=gV9YLS-7Xw*z}n%i`Z3*XhB6|uQWL1?;^}8Hc6a|} zhZr_vQ%tJ*Ffa`0tItM!Xg=ksgqKAi-AU6U?w!R{o>p9Y+mi@Yx>oXUfu(N29$07Az?^eH5*`GzXkizbp{67@agAt> z(sQ)YdaCkwJ_Z$a_Iq^tm(NnV3s=hiC0%i!bnp8VMC2diyurp^@&RfsNxb4Z@)HEa z$l%Gt_tQ!0!~}^mEjaC!5U1tSQ|^havguu_TeU}D3rM^`y7TRrJq343N*jE*g%gC# ze74BOoQFXy1|XS4_d#mLc-T}^KmD2`au4^41?$8_K}Xz7U8XXY-YV_+Llu_I2s=mu zhU`Y*gY!Q^x4o6Kh*)1|w4>2-weRp3ejHh9;(lriR9!K8s^~e}khF z6rhcR%wO?O!yh#_-um>%S;|Tq^lX4IGz5g9KO6L-^H;70;U(kIcvz*c{@2Q$&iFh#LS zmdOP+9a=WKlQUSoieroc;WD%IyBPCD)d5vbi49MPUm^uo%dyxgD5#`~FL3=T4aF+) z39}0m*#!~yT?;hu^}00aYE^YLS`bT+;(g!j8nN?9Yk4#FQ!wZfuyzj7+@$4uShZt@ znRIv-HZ843IB;mR7BxT-iJ$aVKYqSM4il-U*RA|s_U2F%FxGq}bQ)E_4(NAMb65ea z*hXrS`c9u}s`*ZAy_%*@z=Xyl39AQ2VFR9|T1n0&TO+;sjP&|_`H1WX_*GihI1pFk zkcKLQ@#^8?>q^FuzDjd6n(J*;;r&+2G_vpK!|s;{@r>wTkb!Ur%=I$0rBJFqxgUiV zM;%LuWc}*W5MGB6!+|@xA!#>pbfL+Y=FWx_Ozz-Xoz| zwFA^bjU!_2;K&&8Ws(gMZ^7dL>N3R3EG}lF=ZRaI05UMDOVW^uLcL=NQehOl@B)@+ z%Y?n%G=uE{w6hRa4@Bh>BrLBquatKv1MVC6ZU*CVZ;vS=fZkV6ny z?Qzb+22s!k@=&V7G#pTlpq>^NEhUOhL^7Lr$DY<($U7c^a2(X%a8Ia|Z#k@ZrO=o{J@bj?v-NsOwhhQD1XIYhC*+50{sgZ{W404JAaL2h|F3uS?{MX- zzUF{thV~)n(6E7!l+vtdZ`Wquk_ui!6(*?@yo%A-qzN3f?5S9f;fTj}X!d6-^W4 ziZC%oQD#0B!|vB#AR)7#z9{hMe}Uqp@Nlv8EhaDI)=M)XvY2 z&o0^lXXF63qgjYuks~u=8nKG2W~p37L};jW7JqLwXt_(Nwaex+Om8-#*4)5oA_;QZ z_>GtrFL-mhw1(yZxU1zh9JB?WSc~~hc`LZiArer~j&AAxOHl@191t4Klq{VnP0Y`S zb<{}D$~U@{+}CP$b@xqgue%jLdd9Y1gH950tLoIXZ(#|j|-WLSloCJB1FsfzwrF#VM z#cuHMsx$StCA4GC!EkI2o}B?-z+%xu2;4Rk%7Vy7yV-bycbWxadR^Prs9d>n6|BUh zdgs#}itUh)vK8)+Vl%L_u-bZ($QQdNNOZLO>6uha3T~KAdQu@$>&*CCBzDV5YHy;7 z4%@exgdZf%Rt?WraE0ypL~UwuCy9kOL3xr?tL;NZAruyhGAW#fU0iMCKk1qHa(wDlJRk*l{Md21$UHpzcX0kk;j5AotK>?8m} zFPSJ!Hkr7kpm!#4HiyvR*J||!NSE{SKwsE9LuFu6cgi8RBb!r1@E3V;>p9rrBGB$FY0s1pOY%~ zwd=%>mYKNdk_2w(ya$)D`V^kTkA%{Y$WHvZ&!JTib!;3lHtch!!`&)Ht-$E!V6rY+fy)yAsEh73Fp5 zXOCCc2o{8W+>!kBxsxo15NSX9bv3fPTHILBDS1b#m=^x(mibqSgpsE4FEMx@WM939 z<2eC7ej8XYuXiSjZ}29UlVDl_Ame&$t5L@7RJ&H>164*?(7zShWx%Vx293+lO*^>> z3ot?CGrTe?7ZjiY{;XYM+a21&xe!pDMzz?dQa>i=06UN8Z zESjmk8FMuDqdQ#XJ(&m9ef!n=k|uZf$`*#4*NkM2ft}HDEv!@{T0h_Lp17yYdjv-@ zox)N(V`xn;tjjUW({(dd>_8OAy(Z;U-4yDNEgD8EHsn0RDlF~Lm{dyR$r2Z<;`(uA6dwIZF_1XcdAi0X)q}Owuk_1Lre1t9xj6th;j~WXtFjc%>t5sjCrdoTUwV49$ zj+qm7@6ktYPT2f5J>S3Xk)A$higpi(#y*-faZp_<7@9Dwo?P(I`@z~=7)FVF}os&M+c@@Pe3Nc@&_xF zGqSfbH*meE zf$~U>bN4T9=NFUx6V6YeOqO}zZg4MaNPVAOM|B#nnc<+)3QP)0z(kdZl&D^kXRZdQ zOH`A^yYvl^m)TUZGZO={=yjbyM&QkeX1*@mbU8|XXXX96*mex(u^-@cJUPB4X&*rj zyRSt(Be3)Iwb9F090D^d9fcpC)NF}bjys@a3cdte|B5CmCymiFPg<*r42ki%8xDrN zL^&RAGRSJ?p&*eLfbIq6EOU~wGl7`ygnKyJw>F)nV>5s0J?d!Nk_N{!C3Q zK&@&C>$mplw=0}AHtr5hat9qI(W>_fo2w0;EeSq;ic8ez9F!C600YH6^3MiVhM7fc zPsDE4p3-aq-gT*(uhYmrEyJ&%m_q8b`!i!3b4qVV{&#=d>+)CCtR5iTo&ii(;{JdA zWPfLf$;vawQgfM@mrHRWXmWN}784V~xV5wM)y3n+` zU(kMs)xv=fG!n|k&9}c5@&UhFw}LGsqp&}Jdq3wsN5C0uSc2dP{fKMe8c4Y9Q`z16IIsSqO~b0T{RE3>i9`zv=1;JYQLZb6!g61ty|>=- zu$Pm_p|v=SD5}MUPCaxq%j+ilK8X&l>JXl%-J}=LR}8B*p*N)f*}cnviNm<4y*1Gk z+a$$#w)hsozb}cHaCRa)ipeaB9GM3z4hM?0;KV)5=%z+tg}($g{4s(Y@SXxsW|pTW z-#A_r3W+h(==K9-wwJbA^Bw{H9rCfzp$3o_nId{dvWbOU5V*SWjt;*d`_I=AE0%EK=C3 zuIQVQ$KdP=b`=Fdw;(TaiR)Id_^JvE>D!N(dB91Dcfc8fXK?U$xjygy;bm1x zM%dp1x_!2RkV5kRfRq2~qf=Rv2R2UfR|I~^A`E2=aQh85zfSx^O%IjwNjPSS6Nt0XR$ile!Sn@VESX0cBJ)X47Nvt zaFB86ae0i70n3#r=mBj(_J#?~(0B3d;msgL>R8qtxTRb_uc!C8Hf9E+&%XDJk$^_9}CNg&(^*~X|;IA_f?X3c@UFV>XI zieHu)r9{1mUmb)LA)5g>R8H&HQSTrUH+7CEEbg>1+VoUZQ-~>(T z=s}Wm6le*8bL7=+spGLmi8T2u{X3M9U2Q^@RL2-8qxM*1{XKHzE*#`500{xXjuOqz zHggJ8mu#I#I(kHIAz#HHNWU{EN&|JtAbsnfnjim9>t}XgBzyr{F!27kAAh#g7OC1P z00qBq=jun5B8D`e;2dDC4vGNA@V-az%OGmQ-niZt8FyA`>5g?*alaG;U6SxGy@Y0+ zCHMn&_=(Gf7QmX#)J;~)-O>f&m(QwKvB$<##-%!UlO|3Zn}E@%)ICDPP;j0v@e18&04Ky*0GhzwTMqT29|0;NhY zNqjlH4&oSYF-?qm7~M8N%2bB0@nk+d{9ox9%0xa!rB-Optzwf> z;L-_4G)!+$qRewj@ki=gOC_+dhJ)jabcp6kycJy}Wm0z|HBISHgOqA&dIYecx zt#{TwQ+5Hq?rBE7MfzL`p;q-l68c`ovP|`R28=JpWoBn*Kl!*@q#E?}e0-{n)Pr}j z9bt}L!^z~GTbJ7+xQ4czn^#mcDrHhbgDy)UuawsCIIQ89SSB#4_<6H_-+Qf1K0<${ zz?cf{9GhKDnuApTM9T_00=A#NRG@Nq9 zR+~!^MIDG@z$UVhrSnLdR8F$VO%lN;D}&W!Ln_u6-otHmuq@uIa)mXs^`yhtdF^v~ zv42dQ+en=E+N`QcaB#9V#Pcf4j)2tjpv<_M))N0Hj=;w!=bLdt)e=7M(Gb?ev+Fc* zT`Th1O>zjSbs7RCru*PO7UDnRH8L}Y|3&m`NHe`QhcTE9o%`E`)8+P4P8^qxfvIpFQZbcR&#w3A1WQl5HkV^&oAHwx@QDoHecFS4 z*aB2R3wco6j!93Vl15~44Um{a!;m9HCdHhvyEy|bM#et#oedPVgy8BjQx8lJrLOEM znHLpKBGL4H$NuqcDq6ts!;!2wR>r4J%F$lc{p1hZ@F6GGzAx}L8UTaepWyh9cC7!_ zPX7UpA^)6&jxh(2tn&{OrvDb7600dDl*cFNWLgYLgTVUOZ0ByBmf$kCF#E9=G$o1c zI!w3~`?WI@peWoMy1uav)J&ZfIQ-t!Z5unEQ#RWCKg zP@Gx#q>QDi70f(}4Ym3r0uSNJc-)^-_IYx#DQJMJW?WiTIAzzUatSI~$mqV2VX-8O zyvO6p*|SISFELj^WW!gdryN(aPM)N0G3H;t47OP%e@S=zl4b`uZNqQ~Sx~#sC}#`q*bT>@zft-cI_b9JBKo6gf7FTpBgZIBa812p zS2=l0VsDT-CF2$!Nq6H}6_tLev8p)`6OOd0cmv}Q=xW$43cF!<58h{yMcFX>Nuk$K z65aZ68l!^BD93&2;n6BaEjhqNVA&cI1yG8z8r_Kj;F+_nr$Qn!%lsZNad4S5*W+%V@d+!1;G*bS0mx zHAL>ZHZ>MZ0Pn$Ul1#>?a`|Wzy#yBR|#>AOd6^vFLOlD}NAz*$Xf8fL+dX42v zl-|Mk2vhWwAnITD(FB-$i8FjeG1fdcQ3Qo(hf_uGW9mivsTg6{Dx(m{@^F;LyYF0; zb%-ZqPKev4e+=@r)3mtPZ0pX|3nnW_z`gQ4kUoF#zE+gl@(k?J+oYB7d+ zy5kOV*to5_lRiI~S?c!%F_A1onV{;x5CE8?$itr`z1HUV5Lg|>ykgOOiVP+CPy-C* zTHq&;v8I5E63>AH6Q|dWf}SIeq@%W;MrYex3bzHJrP< zp?rdp6aEcNah&26Ms>Ld?h@K*xg=?Up~BG8qqt$aN~z}T$(?VYmDaJD)XFS}V;M zKlKmdrf;(zD}yRgKl+I+L{{$4FvT{pC(JESK(5}E(G}OWtBMg8;k$ErEOPm0>|jXN zR66;ghB&OzyGDaOSTfHlI1$o~VKAVbQ(ZvEbR#tLyb2T_1b4=Cs~vue*4H!_TB103 zHBljH*lsQcdR3Wgk_W8pJ<%M(dYc%%iPldiua0DWfPHcH!ABO9jfnm=pSFOjk(-p& zp-ireKCCy=(RguH*8lctY4#Rcl*bv)!0Q0({q~d@gmJy{!D<)ld$!RYov^AQ7>+nq z7h-Fs{XS_p+Ll*+w<7FbDySbZ)?xbhY!=_39=XkM;b{4>$+G zJQnL1_siKs*gfX`-QS@@De~`Z?61b_5-{+6GGGW<0(!4${vJXc z{%f|18KaPk%U3I7R~IuC%db}UHvd$lv(@!9fF|q>PH5~zc^N^m{eqd*6jP|^e8Z3w z4wA;%V0D%Jkn(IGuC8zuOrjP9aV>UeSf~g z#|yEIOQ5d=LBOV$ovwp9A#%{T9%vcr>hrfLBA6L6`&8%R1^Ipxy^or%R~pk`B@O9b1-}=t z$f{QCx%gsthRoOIZs~(kZwAXUy53d!Rn0m9OXNQPhq1SeiZj}>MG5Zi?(XjH?(XhT zxCVC#PVnIFP)L9vg}W2n3GPndaZcZU=XAe*_uesfeLriAPxe}S&9&y7)O+rjR)V0| z_)juoJW-luKwl2awQN80_Ei&CQPK5Z?G?IS~?!)`mfRFT-vEOlx zJjvj0?!(&EeqybXe$q((!%N3b-%&I_wn7!o)op#hbnr38<}r(i4^i8d6yfBQtyWlH zWEPxcH)o9J87ri_#(X`)fVDu}^GSb4mNo67uFU(P7wIScH~NNPWttOq2g$zJ96;=% z&hQi32O)J~elOAv#gJ+h^}ZPaVHkE6M_6nhCmbiugsne^)}@5`oDvN}A$pd8H5Ns7 z7^&zlDo!K4p;Eg?K7(*}p-`PGwtN1(RbS-1{pFo1YeDGOV1S-#R{{g^AjTZgA@KN) z&A5<-+GBXm(79_|AQ86pQPw$eADh;8t$#Q-?jcaohyD2veH~hM9iH6un$t_aSZJJ( zWp}8CDoA($d@j@xZP~xXT`gvC&?2{31$*v*`4Ot`F3N*YQLY7u9zR|NaPl6L)-;P+U{9^OA z`|nhG664bBL=&uGN=lXc9Mw+C>J=e#;z=(#cv{h6kK}8QF$oNvu%=p_#_6%hX$D|6SHTwzTO>Kz7BSKzn zEsD?PlTy9a5x^nx_3K|`Q-Vhi%A|R;VZTt&B&D;NL`+v?XdJsFHOC#}1w!-gYn>xf;Ov!;j^N&f!H#;*VDepw$?>n8 zbq>v24Y2XU{N-dItG8oMn@+a(Kv0x&YMSP?nnDDtJWb#x|^0I5d3fW$KTw^DOEUt%nS z6DC~VsI(BqI$YWQ8Q0-nY()s~#>ocOSHp_$8t6(c=E}1YCacy)5759f*;!;i)AkP) z>`*x6TgBa_cM;skG@7^Grm z^0~o-EnJW@L;c8XRNU+=;sOg4wec*+5g`kRmW6E|p*pDysNp2i0VH@3E(0h;>0oHH zcFBqmA@7Ox_aVr4zHumNeuhrlu$MZ8qPAZ@plW%<#z(*~maL^Lk|7ttsJy(tx9z z-37ir1B+#(UvB*Y)e-Dsy(3P;kd%XZN7E*Z(|3$Etq3ixq=bQ zWvuZy>DY{h7m_qaG2Cqp2^Jq5(|zyY#)9O_6^;c6xjXRxy7wNwDF#S=?mLmsJkR?- z@4f$it4h8KR#vVOE{=}>lxh5r8_&}=P$7`Pd>>lbY#>ILfUV6*8Cp0n7r@1U#e|h( zQ*Nm8YpSWe&yIXclRbCHXDAK1D`ZIz)vOGvJkQcYaC8jO(97m?f0*#@ zanHj0xSzfZ0+StBnvIF^!l(B1*wG-;_?|HkPv{)Q8YiIM$q+T|F+oOA>f3SdPV{&c zVYrE6_65a55L6UNg*1+@jT?Fa)JsfY1z{^FH>$GbPHM8XY0(`a>6EZ%s4>@TW=h#) zpV=s`dD!4VLmT{NZ5i60#^iw-D3zMW9#7xMbtNX?i{mtk8|*Tx#Y?1H)+#kYCqFIy z8zr8`E;WwsD{j7x0AwOO5KZdSMYymi7mW@&%GcxGV07|~H?mSLTnI&y32=ve+j*Emg_{e4=v)KW#MNbWhwlD;TX?l5X77 z-l!{^I^||FT<4P4qxe{$g`NJpZEB&Lkd1WAydNDfNSEW^ziMMjfJj7zLVp^~bc-kP zU3`40iqjG=L*G6}`*WGS<|mAhP0nnsQbPx}>H=Qgp4o|Ur4vww?VJ>_<1CRJ$x1Z2jxM;Wll$`r~++@5!)tQD#Gjo{% z4P=C$h{cziJ!$i)<~93XvT{caa(P-fSVSl;lLo33ttljtK(Valp4$Yx$Q&SbmQawe z(85{xA8BEhv4fRAuv$)CtpuQf%J#B!eJp1rS^ZE!+u8#BcFxjewWC;dGe>83!%876 zH-YYk2JHr>BQ2LWZn1|RibGUC+(vt-4r=(P;BLL%9@=nRXiE_8hrkMo+tja=In z0lK}OesVv1UGW$RGakXa$G<%7bBV1!+HpxUkWBgsUK0ddL$v&rXCNWxgdT-f9Dt#8 zr;`}gGAz!jl3gM0M|-=2Si*?9Vxih1CkTStA_I4mCnkS_&PF-Szv(yd@KJw7K%_L5 zFiG5!)&50PIG-vmGxNr><01eiQpgdH>U#*=fZWo|TGu!(+vFVIM6B3Q{oSg&eY(yp zeV+?kt7T8pDRe}7Hi}!W2|qYZSUO%D_VY}X9Jn90`UPU~$56VCn>RnfUwGi~s}G{I z3TmY7-6%o}{51_9;#_WFmxtnWsvDxuwNd;NMF>y(Lgf7>4s4Gk=dO-)a&S}ZlL^He zf_O66q{zqXBU}t`Iv8UDDFKvC>K`kO=q5bS3K8Xs(byoNwJx-~qcK|EJuM-|WQ8It zm9LrtT?|3&nbR16#4286N}Up_pMAlD>xXYs1|Q-O224WC_3D174d9F=TFsuntR!dA z`qs@Kp_|h?c|k7dM!3XR(izs|>E9r@e`-JNWyVh;gMm>}gMrchUxlXs2t~EJ2)c&D zp6}C5XAuXXsMz3?g_+5aKS}R^OpJ{2s^O66O~lAI3YiDs%f{!sfx0P+3w5cyPV?MK zISc8jL#?l*m1#@zNV0`qr=7`|Jc)a}ENz~1GU&rfr~G!=J?Hrxk8Y2BP_=jWdluFg z6ImP|&(ojR*Ij{vAmm;@e*M_LPwsTaNxLj1PobDNVTOkAyWECLSA(STC12U1Ntws5 zOysYr=!{c#$JM(CLEHgS0}NuCJ587-i&s?(CaJrpJR^_Khf z3RgT#h55i-Lc_72dy*#v ztSd=b?U$S9%Y8}UOpp(4PnYL{hi(iTD=}e_fJq3FwGF)JVr%j>(7W zLe)}eR4v9&u;;3pw@sFg$755sK1F6oY1(C@0I(|n6I8kEB`-K4Ckc@d z=H;4~`OT2M@a3A_{k|9%B%<11SU?75>5UpwVBxXhDFj;Yc#OpYiDjv3RvI`a92OC! z5;Vu+`BJ_0tovmprG5IU^8FKF;+HDW2)wKteXRODdOIGLac6Dcd}JuisZ+bJ#T-V= z_f{DD12Uub`+SBW01ipNn_5?OC(xsnD@G)nrn(KlV^N$9^bbw<59Bv8?iXDg1>M8W^kjkcdvXv(Zt;7836)$?+ej` z%Fb8fWsK`b0YeyLnT+YIi5)Cvs9>*+3pm!&W@CFv*Q>eD|2eWx?*Fv1vq zrw0CZwmC{Xq}2yV3C)A~)qD{qp*ey~Vk!pvGn=cIUwxpMZCp#?)kHB^M<83if@Rd~ z)C@!7c#F?gRu1fx$IRW0RwQH0HXYE~~XWNU%U9(iZZGvspiB1uxLphemPI@a$;qS!_oIYb}m_~ zw%6f-(M=pJfe?>w52NH_5?1C&r^~ezXU>fKo6N5MPs%l^=7H7;NKHeBp-Z;e$&X45 zziH*2yYQ(x8p`e+(S;n~=iMneoSGGL-dEh5pnvn(Ux^ClMSmAy8qLApAFao-BO1V+ zH8T|*CcRifOU{TPBeJmq_5h=u`XJX17qH5#1k-q(j|FcIiuXlFem5Ysb`j61{6j2hFKpKJT~s zV_sUnbe1}g8=<(ogqK<~NLs%jW4HN9A^~XY5vI&Dr-bjcSec;D)u~tR zCs;S@mB(Llq)o?f7o}{}qEY@h!<^9RxvJ#Pc`{p>`EWy(snV|eTA@<>mw!VV#^a4R zf473uJ83U|PGURQ(~&d#?+O|`vYWp49}BU46u3~fJmhAPV=wNA4qS?w8*t0vF-9o- zZk_V4jUUmN-qDEy$IN*bW&Zn4UQ#sZ*@E1;M2H~%ubkOoQRgev-&(Sol((C)ex~Fc zO^}xzwaX<7TporV9@vmw+$Fdh{bE)xAILj6SbLkC>T9h~bB-2W7-f1&z0D0~?fp1WMg`eXzUyapjHf5xFvg7%MR;D5y1)$Jf%iEENH`|3cjo^JT;4_em zYU4}1WSMeWhx=&l*t3_tMWMqx7Ms=)Hge|DXJ0m;cr~6dFO|ic0QBOnffVW{OS#vc z{Y~_n&d#Fk2+gshstw%+;TY+2r>*nsRbsMUsu0YUFrEQ=_H71_e^9R(1-QAb4&~tg zJPHV#K!?QI3K@w`{$on@71)+qpr6$$;2T~~I7-LK&@q4yOw%n7zU~z3+7cv`jihqW zKex)zS)o-bgGo`wHC$OaKaUu62eC)`E4JQ@PWb7)5G+o+Y?4)76+pOeO4igB~#7sDJHRvWXkE$Z(@i{<@6^#8TFy$4E(-Cn0D$@&_+Ch zJ2WOrq|`PQaSkJaaYc=C#l@;fVZ_>gQ7%86P+!c&t;*K0(2~jZo54FG)LYCIsa|zE z@y~k^)_SGH(7b2ks>cq;-8D=E_dp(`J=nYqr!I^rQ=JounFCZL$xt ztfeY^32()j_9|)+3_-D-y^x1N@SYkK<{_v1?qXJ_kl3H58xB8|G0>QFB*(F5#TVZJ z3y~+WET5e5$Ow&!(}I5T3`4;fD$hZT3X=XyF-{vWoD_Gw%If1PPs~!B zEn=mU%$w%kya`E$!k%c$r){n{c%vT8&_&{Gu2GG9DSV(vKyBBw=rwrGXdI7S`+sm1tj%%?}F`P*0>hYhcg@UQ{yE%P*|FvXW7u<3uFd( zwb@{*nRgOhZNaNc1JM)+Qw|htog3_kEq+DNG#m=z)66aqG(}Xm!{`_?A+RpUg3%-jhmPWl9&;TL_)psuY{_w1{Lfwy+giSuXTkK>`p%aj7>d=cNbV< z^@kXHN6XAZv%U>NURCo~P9qbL8xWC}M+VTqx7wIbd>a zFS{-3ac|f+-CTJ7SIF>67yG9FuTdtE#~X$vwoAgGQM|SFiJg(4mb}N+0Pcp>56alM zsU;V>I_A0uk%(+puHoFADT~v+xsMQYeE&z7_h#S7fC93f5Vx+F(<=$hJtoG1HOGl> zcxMJH(FODptG<2ujE7-2-$Q@>j`*dQC0TW^<|)frGf0E==Ek|(h8eKCcOMQBgfl*Z zj4+aDH@+2hS@b>K>cOnnh;ADlYg^)_gx|jWsbW=s%i0hCu)Q`^}pJ3RgCIXx_S`mBvkpn%eBEc(<9Z4Gt zIha042Hc_D3i(y+#bdCiU$7fYDX4RGZU;kA@P@pj`vEzP@yt9_s$#H3w$!G)v-I_% zHcztrM_pI+7~NS?oqS@7QMY}hg&ggKkpRbG&AuxX|0uI>k`n(QwGfC}C|>IhmU|{@ zMww*FO)C=tsDMXm>azX1`$*JafxHs+tYEl!7Vh&f2o8Nk%olqR*r|i-+!1UfEckxm zz=Wr$#hxkrB~LiU&kvl;Z>}`avlBO)2yw27ZNVKRQW||fS}#MqkUlN9(S_)FTUN<1 zU05ej(8-~=p;va%thm8fcHyo_6eZo+yC5Wh;8|{XlE}LdI0W^YgaI<}IgTZ4;L=!` zw7fXhqG%4*rv!vCvsH{Ep2Q)ZP%#!|Hf9@7g3s@U+5!3)-TMMo@ApWmbq9IkGD*@A zo+}`qpnaeRJqb1aLFro!F^05V!c)(g980GI=X%P<^w&8(jG>46coZ-nm)7VKE8cy5}d0mPSDX7S!#tKw8Ao{K13AOA+O{zpk%?c?Fj z`ia&ReWG<#|C^HdzX}Fx8@aDZVhZK(s@05n3a_@%wNu&^dN~fyfFmjC%SuQ{5DwR_ zC1JvkG@a3oWF#Me{UsB;V)2n(4Z(~2hdV0ng}s&DSjEGYTj@skW3Kzz4e`Z&9SOZ`- zQWRniGXts8s0354bj79mF(R+IimiAbai!<8gd$fWwdV0sq>4*3J1480MbxUPClzs+ zl(-%>*S0NO*bfQui6SG+*MRs&i*;Bv_T6i|01snQZ0TbPt#T5rI%JE16e{eV_gOes`!Xa+)0hsI6PJ z4xK`|3c49Jn-MA6S%*lA-x2xYO;%Yb>vYOo^*=%+pr8{e-+qwB5e^7QB$h#P{J{*Y z#$!igH5z6`z$*UDozPjh{P5(Zzwb}c|ES9duerq`)T@z;v30-nBk+2*8&2c|-Nm5L z$Y7bXTZy0>-FGIEEVf7NcXq2X3LQxdW>#c7qtXUn%gc3~3;lZ?&wdQ8N9u+gATJZf zFjY~LCYm35r!4DAfr|Dp>Ymu11!)6qYMI;()wqumJuUn@mRiIJqhBBueZpw7`<>o= z&{-8Vl`9)j^hz!9G5&ps&0U0sLuXb=;2OBelqdL2dRs2gF(|bAJ{! zz9&Z!0W>zNM8S)iA&8NAwk?P--W#?_$5!(PP4UsnoI=Cau@$6?ud*n7F8m^aHk35F%b%GAK5Vk6~9(@f{c}r8CB5_&CEr z{G!PH3U5J!d$fYigJA=AVIKOfg|1tE{THk+UWGNx`#N92HEa$Y@|XGU&!xqIWX?Bw80IqxF@^Zt9dTT);Q$nXsFNG0iv!z4n|D@R_d1pQn!K_Oh9I$vf1 zlA$gZ1*)f>{HSzvi(Qwz1fVX(l=>i3*mQWzBz-!5(c_wc|9pj*YG_3FfsfJg21h-O zZCVhGj9N|{L_BSDLWOpyLDLO>)%JJ{;~GwGndzEl?J`FU*Uvn7J%Y)?Pm_zq^+ced z8QEnJaV-3|CZ|vtsC);V@GW{1QC9XDU0w6rH$yl&e&jYIxXeH}2IfPW{~mJEiG(2V zKB=)<2w-5$|8vNZw6pNAb8$9v^Zn;ou-QM&oBjifOVGCS{}ey|N~2J&1k*VKRvPSR zpAC*>nF_8iu7GeXZh!!#S9Z)vBx}=e8HzcWE~Tco5zB~0lK+AhUM9NU^DOud_7OI{ z=YqN=Aoo}iFw*@=IJ)qi_M`dr@ps<_%;BmQMQcSTnB8M^o}HE++k3+aTG=fL#~Go)HQCb$P`WxJL5ibmzdxk0}1J6Ms3 ziN2Uh>6Xq7pa+F~W(lm(vGT)%eMa~*2PaSf{lxc7I8P7u@WwfcxY2W7wKk-3$Is96 zi-^B{0H~R>Rc0IOo5Cs~vQ1X?ZK)tT#b3U`o7U3E=dDHW$dr~qlp4bpkZ z##u=XqiPm|UH(@s9?A(M!tZog*!$60oQ`OP>jIHG=n;?KVAfaIi7Qwu^wow0XrhG5 zN;VYr(P}s44nuQi>#>(H9YM}er;Q;Q)Y+{|O$%RU8{v<|6T4YED6{tCPD$7+ z)|p86;zOHx%eMumMxSK+hTDH^V>AZDPGcHMrp7D4Gw;QQR-1Q3PE$eVw+6%apl)8G zk7t4(F$7E^XI&(OvSw4#rvAmrN0HY}hNv>S{5IS|$4byBH{=PmwH+Dm%Tc^&q3j|L zBWcPbN0qSsbbLi%^nRnzx&}VCoK7?opv{MR!Pyfi8{Y~SLVZI zo{iS}IwT0#77whFiW6V1r}0YOS}Dc@ZdN;J|E$%&17W~wUDyby;I#42333rHBbsZf zo^KTd2dquF4&@RCA<)HrkDM$t#dw9-Ij*cg+jee^LWLr1api_q`JpCxmH?Uv_bEev zp>w{dz?BlQ;y71q7Pi}`<{1<1UwW|{QCv-xsY@T@uD7)pL8=|IqLsN)7FbZE|4Ye{ zd)dxA_=Jl&$PvKhRugtG^K?(Q*QUNZJRSz68?jhY{j3Dop-PKYqcox~o81A}clcKh zyzf6_iFS@oI|z6Df|4PF+MsZSns@b1=;r`;aXo;&nM?XvC7ryLEB)oUXEI-l4%7MS zrMqrTSMNejtRs>9*W(Gr1is`TD`r%_P;`+S$|z>+1M*%{u@8b+BaX`yf^c}7;3b>9 z;r4l>MkRv(xX=aW;ZyhEcvOQex+a`n&)O9rhwJW6!t7;!()`l>|Nn7H8Orm@-q^ixKhv~h7 z1pjnELQPqQ3CE%5Qe1ZJ?We@Y0C)}ylhgK9@pve&)vd`K@;G$qVJ^sYYdg@Xe^?6~ zGNWIyA2T3_r*x!5B!QZ~VXc!NWwNJBf zq$Bj&u0saD<(chuEWT;fvpzdHs+)PE5ZrsxEaoYzKfM3j?EgQ`wfKLH^gKSPNC}@) zAQb;|l2I~qm2k8&bNv7xz=MHwC`mOnHAxk4>Y9Ac+3&P)GT>zaN)|I*G;35zljH}KX-Z$Lsa9rWL$NgG&zORAn*)3zi~yO&=#v^ zm#vH~rYAPg^5P$J?*i5FZf?yGt>+N}4Hio6sW@tNv@A-KM9H8a;-I}WXp2O(KAchu z1&hDG=arq^6a7vvnpb!C2^abvLX;SmL3{&)$5a_J_v>9>g|_`$puQ1d3s$GzB2z7w zxF0z6D5aif6UAM2x=zE`4g$FfekyrKIPEAsKsOB#&Z*bImTitF>JXbgt2Zxrqm~2Bgg-2(^{hcdQ3bXhSrxR8hR%b7Lq(f0T!}f0`>8N z+ib`9>^vD&iu6YXEIll^*nyV5m725yoLKc6o5+)l-owNu1)P5+<^f99>2cOY*1N~_ z#NlUI@;6rIa<@MSC?yoz~V8QY*`e)$lk`U=0De|ZfPLvd3^3H%W+-2idG5V&B zI~SZ899miI*v#xSBlOBhqdG1x^B$x*`Yt*;dWxfTY^CxTYqIq`BR3PpPFl3sp_MGi z4sC#37E4q%=TL!X?ITXc-|N7~mZJ*(Zy;B>g2XF(1J{>$KA|5Pbc7w1WAEpe5zq zg`!|hj(@9bJmtiM(eR`=W?-Re+;g;Y- z$vcniO9lbjA7$Jgh61Inpcas*LcNp#o~^&JhIh1&G<#VkO^tJ4gF)Oakr0nc@b?j< zwb3T4h?et+I)T0*H-Qt@J6+CS#T4$VvvGE~W_(rU6lKXxDViAhUx8l9lDC0sio(Kn zm&a-OsR(MGn4JjCJ08bNjh1BjEfRuxc^^8G%K5r!o4i{Q!B)!2zYR)e#$J&)oUme* zf@kC^%VOr!uz+nso#|{C+_1m3e-~!1H& z1XFR4IgR2r(i&`K3WfIte`>bkDIwt=i;~+x_48Lk(A=eA&CG@1Llx{XT6L7Mp-$<3 z(fBsMd1u=z4{Z-ikYF-|LtaPQ9?OCi5K)h1XhHC^Zku2o6`;}A)-J^W4bc_dt|uyL zr8J9GzY7c%z{LXS^m#uS_o1|xZwnKnR+#pdO}#-9rgVjgJF8I7Wk}{&M;@^HW5|2~rz|iI+Oyw^pD6Oo(K{I{fJ;2Ff}H_AOgt&WNvH58#01h_Gsakj5}YzccN z{pY{(AKV)maE^pR$ndi(*y}t*tiA2(P5uhgYCRuR!OEB~zm!)6x%N%x6TfIaG%rVe zRagm=_~nf6B1+M!v>+hshx0dMStLSr>k5+UK0#&sC4qp`-JPekUgH%ya35$+yi^py z`6-xIeQZEzXg&^SXpWGP)D?O5#2!jQ>|^IxVg`P3@$w>~I>(7Tjo~AAr@SjkaUAA+ z(oQ`)?ty_CM!d)o<5VT%`AwoTjGKGC#P2=ya$95MeGWj2ba%v3EPbzNN_?88F+UOx zZ$HEqMELbk#Z$#JAlyVc2;QY6uonNk5-RT~#Rb$L6tE4T*_4EJDa?6~`tvDl z;%o`KB*Po;&N~L@SQ4FmjSR4(B3XpR$kJAJpj5F6?`mbOJ<92@Fa&50i3%Xl$qqFZZ)T;v!R@MgLX0znm9OHANlRd;k;l*_ysPYyyQ>sl z959PmAuaw(SWCqxn!dovCT8^(z~?j3hv}!F71L;>O&i0dTEV3nf{RUxj3p=U6ARu5 zJ46R>pQMV6He_ZvEcL?N4hp%~h<4)b4S629L5JC)dc9o{O_4QL6z@Spmq?D{&5q)g zKQ>3rYKf7soaUYOI3m!el&f6tX|& z(8Ms1(xL`zTIXnE4FMIIazMfQWn;PL$wiJP)^F>4?YWjx=e!x!#?*_+mIKV=0~t2G z)RUYm4r>M0RQ3Vok0DV7{h{Z^_1( z_l}R8;13(h1951@)_m}XZ@&Ly&4|6rx3}a`;$-qSe;=l8MC3^Ix`AZ3BT^wv6}Kb< zRK`(~WOmwVQg8kAF%Z+eEL?3C;M}P+1OfmD)|C8`klBA22s+D?&XgrN7cy}s zC2{AB5~EY#<(AoLoPhLlW~fR_m6m6??Xok{JVM?cdwAlcDSlJO{C%G4c--*62%37H z?s$ATQ&0(n?v=(v-2M9$9COZVwo5OFU2-ReLDC{yLKAzv$xHyyL1;Se0TgVxBY!*-4nTwFJ_FI4|VG1-HsbP@f`(s*oN5JlvTSCR3 z8p_!hKM&WxV`u$HpZIcKX@uDFQx-K>H57qK|N8mq;>1>lXt=F?g-o&-E)!N>#G7LK@Hd|D97YzR8rs<(215(z zeRC0uv(2L?Lr9NKCEaJv>4IFn!z`%nN0o!#dCgJ4aglQ=v)|hP{g*)jC`dY_#+CyqUo+H2lK zfoUYgEN@UMwsKZOd24#Fa|kczpZFYBoJVJmtP8JS$jCWA7KO5P6E9VCds^ozUHpMY zhj~U%Oi6PaUxaz>$7;EHs)naUp0YJ#9#g|tZ5h3owT&Bn`m#C3`q4&%w&TvDPA6S| zp)!<^o%qoGMaWA;v~`>Ull*CieercRl-+>9&Ic_<4?vW|3;&8(cc#I#zDAwU#R4!i zRpBu8t~|dJusKrZOObPw;AqAuSo^bzptand=qS;18m}6u>>#is1X#J(qpEm#6rL=d zxcu-FUZWCj=>*~)L!cXFc_QzZBFt@elg&xL?*{|YkqUY5{qM5<<{w*A-1ukrR1(K~8)IPOjVcYKQI@%g+9bv?}7+4jmxU zm;rQ;!_F3pV`o9+aLQKVvFah0Q((*CCTBwXG2fEbU3doghcnrrOS3F z>WM^qMGIn0r}2iG@vUC}JqY`qghkIM%T&r|FNM1F2}&ZH=~^yMzfUCN={l4O+IW9e zD-x2?Fl-|Oa5;ieNBDC+MTR=xqsXS32jBj{U$!fk8 zH4Wtd3K)!DJnE`M@WcOpn4OW~WAR zqqD+gJdR$*%*v=FGRzw@7I_PO^0&HL!wq4Z@s0BwogdD;k4kZQZ#Hz|yu+ifk&*VZ zaRnVY0d@yE*Sh7sc>c0Hikf+$x3f(e`>4mH^eO(rd?djWp1ro0F<{CeB6GkHm)3fN zEF%WGzWt_}J#QzkDB1pgV%8<2Ke3UGMrQ$bDiiIZ@zhw3{uC#s@-eBi9c{UFbM<=! zE{FHR{eh{3;YIwAGE%aDJMywyIPzw)JHAd?r?*~7|3$2?jLC0}^L4wTyp9sYSt-{r z4aNfw=JkVXqd2re|BErA=h3;AfgAciLLWI@q_6WnOpNw7yHZv=-b&tf^Wd5LE1|qu zl>4BOE(CY?t|*m6<*)wtZ#m6ct3}4PR_9_<^d$3M0qtbB89ey)LseA5f;AlVOOW{$ z9qMLPb+%^&-Gg`xQ#)-ul1+@5bogoGhbIcwpO2CluR8oI%6SectT@R7=?#xAZ31?e zoRNJ^a>w~%qZzSQ>ezQM7BQ%(4JddN&(}PjjFe;Xjqs*Hnds8qf#ji?z1x6ur2%`# zVJ+LCX;T=lA~>QGd`Q(@sqkOak{gLD$jv+;0Pza!-B)z>xU%8<35WYGYT%mbw!ERt zsN0blr2kX3$JxEd*`XrW@>!mgyUP~Fl~!wb4CMOO@J3i}C8uXcvyhVf>M&jxi zqeoBFX~5gYCQn#~P+`I-qFP62!QbW_VKa#Rf!!Ro8cHRx z7D&lqudS%9qee^HV9W=X*6ZQp*Z5uVQCvV{?`3%4d3y*4-dDqrFkVR~YT&lC{3Ky_ z41-Zuv*B|8*3MUO=PiX`A~=%?Z|L`s@Oo%pnKahL+$oI)tTSdS@!uKW>&+#F?s9fy zQp9kj1cp9k>1!lnmGjJL%en5Dn1kW(%uqU0koRC)pXDNo@jIo$OcX|kFY5a{lW_IsRE^({ zNSBb{cIBy(zZREh_k3o_kYUIAhXf5^{er?!97KvT@UW$#lxiG%La`0>i0&nC- zhPG+Eh74uvG@Dmy1WNwdY{>O_E;J_5D8}D|0l=+A;TCRL|Mkb+@CkqOr5Sx?zT4Tr zwe%$D_sp^Zu_2mId53BlV8|vYWA5_mb>Sx6>SU{oQy90)2I6v8KKJ35Y_wGW%p!m0eS6qc%URgP!8WTsM-=GRq&hk zY7ox+J5zw(s-!Q#)> z7L?FiyHZGE_crZz>nY`Gtf1kxJ{js8&#-l->K;?3Yc{i)4gRk$FkM0?NdT*f#Ah48 zL3bWYfzR`;R;Wq?vBU?7EP~zcFg)7~!xzIL*7GFoGc1HCs&F+s31jkhg(9D7kKOaR z1U)@@dKL<;%sm*lWXV#4PD`eby43cXOodVz2E;JZj8I5@LhO9e9l+=d3CD9#o3IxOv9NM8 z$X?G-*hxBcA2|>Aq&f4#w4hsc(i-Ak%OK}!mSAd=s2VtHknqxtxiBtq@xN_z_u4-! zT=K&{onJes(;MFqrMQ4Tbm!6Csnau9tEN#R3aQ=~D7p=xk>HuIcO_z2f@SzkoMOSE zJ%$uL{>9Ns*SiV(B6YwAA}lXuc^CI|cjLxSkhJ&-*I}}Juy5Hil*>(i)l!pxUt6i& z#*`xfZOK_Hoga78`%jf+Dm01)dt+{kpJXc86vjth8l&R@*NIV@c$fR-aB-*h#h&Ns zM%t=V1(`UIc5q{4W>gf9Y-; ze;P)6K@&@V;+I8l`wP3~N4cO~^DR(l=tP%?G_)sDK@F%$@^3Dv%j55M3i*#8TxHSL znBu<-tnHQI4TBifUPduy5iKlHLsn06^iz_*H2`trTJ!T4ns9UENQYgajxw>S$~&zN zOW4_?#fdP$0H$A)iDgkJ!q{g9k4s~u=w6=X>`DhmW2h=${>bCuL84+m(O8vIXEw00 zv$C_Y1%q)QP(W}%AV5GQSzDPx%%33=isDH_E0d0bdZGSJt@|HH{2hi_;~fkb7~}sD z)cto|$y#kES3@hTubXF&8$U;_Q*$1G3E>%YN=ZEoFVe0N)8Bvq7MGe{;AF@ zXUwl+2)bwux=;+X>T6}K0k$4PB(-B@r5tH^GJssQ-dQ{uqTDIoch@1nkjXoGf%~QP ze43O%eCnwGwEyPqbJtOBV9@jB@)npYgf*APUI^;$3Rdq0m@rN+F_Q4v;&w!7-yZWG zzPc=o*|;}(wA}N>d__jGmAoY}A}K*{OC+}-s-$v{FA^JOsE;hS)bF%V+Bj#aj3}$$ zBtu^W$rp;71gXc5toUfharW;3NG2c*aUr~3jV}RmWP(mu@LB8ohl)$uw!~RY#K0Gh z=dZtAG_SU@N3F(kF!lH1zIA%j`$XN?(YMB1x;@xh`K>c=S|r3}t;h;nS$XRZ#-BMT zy7-!ul{C1Os7|P8*O+&ThzP6EmDV(E{2D|u|LIhEPQKxXkbWF0F8FQ|-iCEc_fvBW zXG6CMQCv_!&AN8o@*~kL*}Mf?-l|sJZXvr&G&NAPui}Wk>pl^J?x*V1zB^{TvWc0# z*}ayO=#NT7+_TQIUR~=))9VCrZ3{fvZ|~;*w;ll*)-q zQJTJB^2i=h$mWtnzgK#Ef6Qx^IsKe7;!=kdN6J=#{+?F`fAATN;^=RyqGfF9=WKP2 z6u%KDnr(GbN4_oIdBsz}? z5+rSEY9E8+=dhK7zsKx@mIaI|r%&w2FjrVaCWB_i7xYBa+j{5_{5_F2p6ih+Cr_Lg z3joL{-5ex*Nwd-PM*-bYOQIu&$eQ(RH=SDJPW!+Gu0GYyUH+cLBM-q#pNpkyB*Kgz zJ)_QNYbAS70SXy7o`i#K5WLiVgg8@hde-5A>ce!uzrvJzc7~=<#;r=hI%m@VO*CsJ);vn zk(F}JdqRa%hBFE9(d{Wzx9ZYtULxy~maXZGCDze(*SZz|aXmz|MTCTz3qi5To7jLD zzw^BCrYFEdcXg8;g%f#x7@w!K9JO*$O<+zELm}J7>>9;qKvRky234)QyI=+dTn=3| z&wM<%8Ea|QHr`{Lipcdx<8~Iv>B?N}FaRXIBM&W4$`!{gLPL|i;-te{pU?-<(eqnCi_3 z%ck(27P2<~h?cv!VCBix?|Aa%Ptglgx9yxBB=6LozroGhyiD)mqojPHa77fG=Rv6F z*BCC38U#!8y~he~Bta9D2N6rqAn)P}_TAFpeUPnBkuZ(A|0GZmN_A2m8Y`qMr`E?G zDvz#<^5RB~5<8q32*nf(*k>%QrJU^~;!oaEe5QVGbmw?DGsh%i9QH<^4WaK`M}$yn zj!rW3=~iCtk!%^i>Og(Mm~G$jepYN`UUz~tw4Q-AwkG?-E+PGg-Fn2zK4!&DLLlTv z;bcFjxOjwapR{TPY21vbhZDQwQv_Ci$fINbmG2||JN~YpxMh4WA&ex2p+Gcce1l|{ zI`?EZ1d}yoCoooPv;s{igvuIZAxXz?E*)RNtH+1Rc28d?5YaXfecNrzEwIHWH}dC{ z%ag+#_~+qP}n&aBL=)XUS|_r5;o^||+rvG*SkBjSr#Yp%KG4|)%$8egiJR14WZcdsLI zEjtpBkBtoEpO@vBP!l4PW?Yds6+1;{Ero$qM8_RL3SvsEE)}nUStT|ZHp!qB$yT7V zuZ29^|JxI>A`1@U9&>I?O@v*xAy~Ix$33m<3CikDCHwuy&Io*4b|2??cLe?(Z)dPn z>Aqd+0KYxnSO3L$0J|~>dXgXelHV#j z<-6|D9rzQ>XQ}BeIco%e1r=Rc%bi#785ZEzFiN<2vukjknjI&X1d=o*&)4HGs?k5g_5z#0h17#}^(z z_y)i`tmg3Uf`nx=ZbFAL<9dXBv?4VwM1%5ERq|NbyJSB*+#|Rm*kWDo1RFM_qx#lk z=p@<#+r@wtV--xee0nRLSTp;I29q|pZ$5etyRDgg5(m;0W51yvX&Yytw%b7{O~Xtc z$~8-h-{8)%L*r<=T!9tf*loN5;v}W* znG!`tzgj$I1rjz7|I&}T-T5RgKE>cO*k+1V-9ajyO`SS?eJ!0@e1NVmgNH_a2Rf7* zyfj+n4#z08rW`R3E<$2$*AWm*sG2YrHnp7=R$_|2JBmpW`jZ->O!M7>+}&}=mYcPk zf`ng9NFp_!gH?Oj2X>$}caMm!jKbXgHz;ZZR`&=zRXCRKpfD^cjk&szhA=3<#S7*H zl`2c6VU)qC@etPXox}jWd!+%e9EPpWY8QjCkR{AtLs1s3;#H*1ZaR9|^>e~zU-32A z&uy0S2`|ZKlGsoy`x@cRMa-yJ$c{~`E(Y{NhbY%ayg;o&*Kfe1t4Vvr-!lnJPxcir zB$cyl6HdzZBjLXoj(M>=F6J1=C`oU-5-a8Xde~n5ks>S z0dOU>&mONjUOUTjoky`ua#8+^j6b)~{0g!;B^8R=g>fA#ldD5pH`z8t?;=+wMl>*a z6Htk`6&f;V2lgslW1tD~@~fKBVM3I`_#tqs=O%f$}@Pw@#~O|_7i<89@(E|%SaWNjR}UkWECC!Na(~W% z)hQ6JRZbnMQHvlwJg`XwRmC270;2?zDT16O$ae&b&B81R1|`~RAP6{%gh;izDKZB3b))u$!06n^Jd%a%E_ zXV?IvDl5{=4x3x2D+7Z{_Q|@Ek1eicnV7NxBJTI0CF>|&*7N=SmA!vLk;v@f93f{O zu+Q9eoV<+n^dHiIJJ(PF?Cg(KTU7$JUm zTZ+?76|!IfCx(SgQLNy<77ai-Vn`ArFFw*Qasbmy2-u2dqJqLHtCpNHy0YJ+yj?gQ zrbK0Z&5V<1pgKN$s9gL8q_ld!wujr5x(f{@P-QFLHHO<2-_d$&3HgYN`H1zop?b^p zH2`hEZn&D>WTiXG%ruxz)?qF*;T9OH6oU)`{G#K}P<1NKxvv=usO+~!F^z^#YhIJL z8f+8D#oTO+8V})M zMi86zmscW|4PUEJ%?cO5zCs)H-~@5vZ5y%UPK;gd^)tZig}DOUB&mF z7)fES;lzcnHnI7Gyjm@Rq5ExN=hJnFq*b0E4I40Gso76Hmf&*1edtL+DEPBFD`)uG zZLdaYDHs$Tv4MirMU5+ewa#qiXi~j|vhHDBuem_utyN~(5KE}rcl4P=owMfAbyTX| z7IQrLi;q7+cdwDMpl#ZMMbo-BWC(c0Dvmn(aT_@qAe~GPks}aX`l8)zQX*-8gf7rL(Hhi{4 zzgD#OW7=x8Ku-AQ8_T75Pq3ClMld6e+HGd=&4IuF3G4e0e&t*LU~~t;ftXt(SpGga z)OYED83%;{($2zNbS&R6y*lA)`>A@VdO9103G7+c zceEO-*2o^!+n+V-+N=#9BM`VHhE`;I~e6+4^5FwNi2G(!m_gk=ZfOys=`0V&yd`JK`c z`!uCud`FWnF6*193xST6_7Z<1Pkz#Dp$Y6`UNg*Q7ujk{En8Ma`kS-K^mlSFB^>L+ zE)~i&C!>VRn6|xbgZsV;8TX%P&phlrI2l*jGMmYr#5xIZ$B~?x{953S)HNqd(CSYL zbA7;Voee-Abxl!l?$+(NGO?TTXoC87Mz2DeEN$Xcu4oT+=>}fZP`c0heJwKB*~Xd{ zjhqV^%TtNb?A4-3e%IQUii-Ef%A-v_4jDa?sJOl!LupR$(`6X00;LQ+T^aqk57X@r z@>9(Le>6^FkCct=@O7`60Om_>!^G`ZmXS!=WyK8QM)My#z&Bf)DTH=8<%uBmjC)3g zbt=xDm%vlXtuDM&g9U|=hI5rnx9Fb}70k_1h)5l;JH+6Ax+HU?HRPXaXYuUHw}+&t zJRaX5==`mp-r)yV-d<3UjrVQ5zfg&KjPSy|4e)4ReI6u^na4aDb@!}++$6C70_7M* z3Y!mXt@?Y}^InUBh1^+8Z{iW{F~86tNH8HIN-(8}5R6%C0s)Q_4&SpdLcd$VoukZe zFBeG-Q4uVjq{~Vryn)_v^i#o#;LPe}H;}s>gkn?Pv_o|9 zrR;e@Gh(`M4}o5`M)E$5Wl2THjaAPE8m-9SFoh@bAqti2{55HGy-M~}Ik(fTUsZB@ zGZv)TPZq*=vhE7*qE)ARq!@!+rO`+WDU)1(BN@Uu!6Qe_-nHcotGN~64K;fKf7jsP zkUQh-jD~)J&PKQ4pnrKHZ{8=ZOThPa9FPsdmfvBJ)FTUqD0GNtK$LiXz-Y>qaRz_f zM?}9OIUyMH1pf>IcW+dj+|7yP83ksF>`7=2*whw0AHT%^{Fh)8SiOzQjPF{R;(Lqh z--(X@yH@^BQtN+iQxvJ_C@n~%_%TCsY7&7g zfF+=ae?fl!wCi*b6YaX4hyIm#uqLx!+z2_zk!Cw{o&CUb!s*5K`f)NM_rvUtC|Fn8 zIUjt*kVX4O2;bKJf~t^-Koi7UPNz)reY-6{PW4dQDL{}btY%o(wN?U>* zJ=}1P+W9=TqA10w!<>v!tVwqIYW&*o9vbiiF>J!B8zI482uuEg&_L8?w+wAb z3x@t&mh>gUk_D)R#?lBQpfP{F(*+Z*X)*xG{n^&rJvqPZX$SF7I$Q|?x|KR?pU zecIj|{02Q3FI#6=eqthRt-oB=86%$C=asRM)T0HaNgru#%2Vl@Dy50taLy)ft`==< zB_Z93rmIt0bQ|A2e$ith{hDbIh#r5`Et08IeSpTvu|(+OM{SuGFa}Vtijn*9 zJTF-HJ`EGV{pjB>jl?^rgLjJCcQ^iJX^d=xeJblCM)HlMm}9dR#V_!#Mj8$j;6EQ; zntgM?5Qj+85(mfxTA%C0oTQBu6wZGO4C0I1(kuX^dJyI#Vns_4$ta0FND>glt(Yqi zz!Z-gKt3B}3IsyZa1}XGNb`0UbyHPdoOuoh(o=*X1{g#o3?*_N^Ioa=;tEk_o}Yij z{Vz7xFTrr%+=f?mVsmuA@|)fR)?JS2y-tV{_Aqd>`N#!w5ua@%hNNu~YhYmFvzycK zT>4McEo>PUpGA#cswrIsd`uSl*G3Y{M97$UEp&&m1;@6aRpGivC~k z{}LdlNv}{?F5%q&Ojq&4|LAO#;J= zsZ05D{XSR}0*QDzR}z8}N%1$R%Ae^$NHGI24>F$5@}%%s_1x+XP}j=wU&>vsVhZu~ zxmZzGUN>zcC##=NC!ari*_O2rZ^s1Da%?6y)En!JjnewyhL#Zd(P4tlF?$YuGeT&; zNEDc?uNWdP$K}cNFv5#|O<=PIU-~ZQ9*32~3@My+(k-g#+F`d->|SB1DUMh$Wn_-0 z68>^mid)H_+gjy@5YGFv!4nON+ERf|W$Dst`J&LZ76zOR@g;A5e!vpF=!p+JhGQ32 zNM-~`3aG_olulv$`-rzPBNA(_%@c@So7CS}^=`snev6jkh2)}4K&6OH4F|nBkBf&> z>0Zk?&cNyI&8CX^{`JV!yO7jhyG{)GNXQ0=%W2<)26Bjl7>cE|(6hQ(g`aqocFdh9 z*_l5-gETR}>MdfFQwX|8o3ed{tL*fEzTg%`k9m>+ z(Km%%UHMh(9rk>M*$9a(p?BhJVe7>EW9#{V(=!wL4K1dZSuAEqldKB_U%& zjwogY7((jCJqj)cqQNx^w;9MgS(pM2`oSQKbVjm4(K-i!d5Vd4oC9mP%y$EdwVm|6 z4|k!^cpwHt?Au`OS)Y`459VnH`YNP zB`r)oSXK`v9p^df(nggP(;aUcj%Lq#%;@-no3QTj?oUmSwb`UD({5d}A8+zPh9FO5 zdmuJBbQKn1_Po9l`*K(32($cS%6_*F0W+NFCO^Vu-Wj}ST(cG>4qy#GQ`j(0ZbjFL zZUxc6;POj>wHcoBC@7m#%~%fp+S$k{g}k)ftXA=`YGT=_BC#1JJ?_7GfQ=L10#D6b z6Jhp}4s5snbMl}$^qmC!I8atc6hn4jnm5apr|G-cTrFM|akQn+a}le%(#QU{;HW%p z1;3|gFezk z=B*n{Au-QUch7qvCYXVXX$CD}+|Gn_US&CbFSMRKYV3_^qtjDW&tA7<)f~trobgn> z6@MEPel!tWbsp>@mQj(%8{biOWE0|AtJsuf+Ge>j;`@a3Gu(gLmfxNKVY*2ud+9RF z(QhXhfOxdfT~=vBsYAc)=B+ebzJBLz=c|rkYsY95nX(c}GRKBu1(P!sVK!!3AM}Mj z$>RS`uWz*{C*E*MH$4hApm6+&M?%rTK~4A@VI=v`NMbBH1cF2f9#Q%akI1Q6HF#{H zwQy>EO!A2Q3|_-eyL+<&{4H&n_D_jCaC;Vq>O=GW!`}sA4FTF)5shB;i?aM_UQT7# zqJh8|*BSzcbaJRpoWHl_@6kc7^GNZahJ|HxV&u`=?;xJ0Jt^=s1sd5iH3cf!kz#m; z1gpW&^Caw(z#umvMu;O;5qi6ReW7{I5Mc$hriP1uv$4FpjLZvpqPQ~il0}iH38NoY zgQechI)V#Yr;9TN0OlOfxN3}HL@>>VTGn03$iYh2CdvH_AwG{uI5zxnw}o7q_=8q3 z!Z_@=TulgZZ}y>ikjP&Ma89&B+^!zb6dEor(zQyM52n)P2IWJVL71XAi~{mr7%xzJrRt zakO{qg#J!U0v$`UB_Ol@9G_ z))(FJluxJ+ob@(l)Y<^ldouvOp%GN?=gdq!_^;4{QSX4?dV{869vAAe@`G#d3w}!4 z!tivzk)ypcejn{KH_rIH8!sJN#=mf|)BH z-uE~DQL7x1xh4HsWWw3l8o5_h(+pS2=YQa}NUfz#2Mp;+XaI{e&w|57b3BMsN^?93 zw>b19mAfV|YZ$6V>PDd{jfx5lP@XC+G7*GXHR{KJC@t}D%UjDQb#|7c&5!cS7pDf8 zIhC%;jSHBEv1@}eAYtPLo_P$U?;`$cd2j_-m&M$e!mfOi!d?o!jvb>;?ukmcxY__M z#!4k=BYmVxZ%#Q2yQ8!4$a!E{#33O1o!ei%GjW0SAk?74BujU?7-Q5`!d@ct?@>5> zKLhHhW{7)|vwtg>aqurN?sOkZB!*`_C3}rb&Oz#^!G*qBYNZFyx&38Paiy-zKd7$& zZ6#Rz!YEqZDBDITT()%rZ@w@mt%NFnfjeZpBr*+2|3Q?iz2W(e1WW zxLcDe7wavwUEV_7Q_Zt?a$yxD&VrJj2klWL8Ec9mss6257A^C367JG!u8DskVdS|b z6yOLwe^7ql((pdR=Fy`BQD7(H7P}%MwjX=dMH+;QZCP&)LhL?*P#1(OPaV7qaQNX& zYZJXgew@`nOquu+APx5%Qs@2x317jv2cWyk@I`L43K!pw1=t3Cosx^zA;5<~k@JpzPor)z99BftF3aNB`%tM;dSgf%IJh2YyS%|0X*? z#>Lv%;=k4etVM}D1q!Vq>YOi7k#}2fEC!L}d_H17P`}|i zoQcGSg=w*Gm3HkteyhvDa8%gvu0Q^+?#eKJezq5Pqh`B#q=n<#cWh_pGpF0NP0#zg zHyA<4(GTy`JK?^{@Sl@+gcBhi_>O!uFSVl#iVIk<1-c%_X{1}tG83kuHz(N18WxtS zoK|S?8Lj}QN9#PReX0P*ky7kwEMclOJ%DA3pf39amoSCh;!~ArRjC%YW}Rf3{Wguo zlFk&9`z4vl$tXdgv)r5M5~HVn6q{zBr%Hp(Gp8_78vk;(`C7SZjd2TZM0^E0a~UsK zjRO6}48|&1K+m8|b7T6CPKGQ(^_84zw_}QATVyoU8y5jKm@ZA*0GvnAdppeTzE9!q z&FP0=-)b%MOy>gR=r()MElwtGXIJ?4sj07_m5DIs5IEQgS1xgXgU~;ZHG}ptzxkH4 zidF1f(9Mf9KLR!TbSma6&s;*_WYk$UkGO@#yi=YCj-Y<2gEmhUtIV^*_yUo8;x%w? ziy=@Y``;2Hh+q^5YWEonsPimKIlC9XwMxS%GBrg|w(syUv@b6* zi05_CC#WJ8I>hF~x}O4r%;)sZr^VcMmW&1vVucXQrRImTESVzYn|HEe4`BQZ+^?2? ziD}QSDeafq0a(ar#t}RI1?DlcV?aD0BBD1ol_dnYx49BEwDkB6Za1mnpu0q%&@NcE zShOS~j+Co=gk^h_6)=j7=4@`j0LnW=tejlZP;MxqDab-|?rhxJbR)KYAkBv(DQK4i zeik7tS}R9;$`Mj?D1=^knGyFJ_IVjQ=EPpdc?c5l5^zH<00H)fZ3;!ODg9Cf_Rpy( z0Tj`c&@NGlDW>y%_KZE@E5iKq^Wj(uI+Lxv%IHi9jM11X`Q4)egZQwS{T2Hnq`P)o zy>G^D0ynn!4;)Cn^rPzil|NL6zIr+Bt6?(-U_H+fEz=W87G=;mLbQNVD>x`cDYm2K zN%3Xrh9ZR02^m+Wmn86(_wr6#uk#|MuYhb5$SD2#uID zFc`c!&>|Th5-{V|@r^{MY4Be8wmW5AS}ABQJU%7ICVR4kM-)3v_7?;xt7eR>4+JhP zoq8r7lQ_HJfs@ik@Q=Ir7KD_Wm=FUQ0M!6?qX~XwhJk$k^2 zB9Z^?KKMT_?Z0yXs?@FAzLQ3_5}MQE;b@in7c_N+)N&g|b}A04xO4A1J1G9MB9^B~3=n#?|%zY&6Nmk9q1QMx~rAjBJ* zt}in8M+K-TUwXd@rkb(zL~7h!bflX}C;5R7%V7I33Co{v7M9RPtZ8lB zzHxY3$x@;$^ObO0V|h$j@o*1!Le#QH6+xa8h21e(czGJ&dopfFSfxqBnJ-&!u+%v^ z35=91YXLgN1)xyMx?ETS(y)n4nws~fsyL%L8^YNQPxKC2YHt@KwG-AHSDrc(u+xpa zlBub^e^ND2M%C&WevAw(crt?i0TCa*i@Tn?YeTF_QIlz4nl%$=@bzonr~yJS;vs49 z;vz$(N?bqqyCeT`Yb;Td3#(Z>4#SzyhnZf3XBYe^X}ANUlAgr0XeIrunOs&Bj#iOG z7|+CfKrKp}My7*ASV}o1LsD5SLv9eK>3Vsw5|hOdbS*fbUp$IP?GD88wD|J{DO^84 zy{9HiPFTX(=@A}lEi*9hOO)#bsXWEpiH8JTLYTKrn#tUF6%}%xVCon`m(ePvCG~6q z6I6oI)Uwbvksewz2un00C3Fg%?+D z5qUogesfqI-TpK;eq8C~^2?D!$Z^r?%lwFiQxN8`#Ba})Ed%JVlEoJ&gAIdpMMNHl zo2EZmy*JuWcJk?|jZ{O^`Ri!i#ZF|FE zHE*swx>R}|=fXraY@sQYnFnZY@|DQVZ)Vc9)hC;_D@rp=Eac_a_0jcoQ6f)@(L}rg zB`eP;Na?49m+S5p;zb~rLDR@gxn$03Q>7-fWlkgW>PS9xuj=a;R4M2ah52&N_XsC2 zC77g*MY2qUvXg#6?wI`9sOUfP%poHbAkVDn{Ida-DCD}9aA_>hI5o!TcGwa-ZDMaV zySCqAi0v)1(KS@TC0YLV&Djv1ziMgzW7B;`F&jvcYy_%mi2AW=UBu7DPq3$fMS7-`KT~`y9_w2o2!Z~CEK>ojI8j)6ZEN5JAjV*ONPQ(lZqwjS5s2(U(OS+Y6q*r<-)(}l@;uW zP~@j?szJVT*IDOXr8a+_lU#2MIg2?sQJ&(2PdkhUaQqI~?+Qd8B$5(wDAY9aS5s)! zBqlz$hK(ZC#O!icnEkUy8uAA&FXM$@9qE?0=e!uzO^}m-6u^2+h#E;TT>X|8N(P+055gHdS!_!VnTu@zu|jFLGP)Fn^|s)Oxc@8_;y$TCMH)wN+>F3TUuN132-Pw#oyf@Mb;$Z0XViX|~l| zcR_Q`6%qfgHr9?Aafg-U3p^DK-QDo@-_RHTAbl%~rUN^Di?r_FZ5#E!`F^_Cm^fM( z{eM2AQ3^UzK!PZ|1=rO!TBbXCSiH()b4ZU!qV$3Up}ZJEysRCv8=+Uj9AY08{`seQ z-w@>R>+;e>c;3m6bgyY%x8sYq1LR)3WowL7Y+OfQ*o=@jA|b}Q{MjvG{^zhcc8&EsxVQ0v-D zTcaJeE#B2ZQs#MudV4MViEmtrF(E7(Vac;FXYxF!FX0BwwK}%9Ue|0M7_BN*#u)M? zI#KK6=p{_q4Yw)Q?86)w0av|3>;2^cIQKBvU-SJ8tQelhtbuan_XW8Fsh2;Lpqd~8 z^HrP|QKuNxD56$DFCM|cPRq_n4C@~G0pS4dHHUHS`^ZiOZ(y%tf}bIkYm~!5EW#!e|S;!2!`Y1WKLmfW~JsxAIcj*DvOTwuA`;3HRt+ z82B*(As``9|9ryVA_KxedB_T_X`3YI$3t1%0)?toO|*PJ@XZ6lL*dWcHFGepP_B%I zY}_nttX6E6Y`3mmTbkZZ`Py$>dz@~v#N#u@)SsWVe0wszj=6Wxr@Y67A6&OC$B>>;wCKrXcx}?bU3mLrJ_?LGq_C0`tc?;C+e>v%FUY>Pfs5 zMdlKu2f>5B=>cB2F&}Q9kv;|c`NvC#YD^|a_``;NCEwB`eX8`^8PoKKFr9ykwp@7w zJ!9(rPDr0!NZ&{Rl+iEJhTX5^TYe;8>OD6mRRm)i@_kXqC}MUGlJeNP@J=KEQ#C;j z231<5aoF&fdVmw({X@!dMBcbK@}OIOWJc+_III603BJsqITU=Er#Y6NsdNegV%%Be zzLT-$#V^_P!O(*YQZRyylgV>}P9*8n2V8ZqJ4GHyIuu6e8G;W(H=39_DDmcgFiB{V z%H#@NA`v8(v2__(CgzRm`J_yS&T)~tnpAU4n1H{5BIpyd7HuLaqYSIOjY7kGmiKd# z_&VnW6W)#E;wjLWYPCJ38u?2|O%jb_!?gXd>{8BAkzPZ?+rnCdV7?Rz9g*NPQZ15=GQ$pV^yjg6 zvAL^sbL5Z*#9{6+%Nfh4!cv2f3mfsC`RrAvTT!$_)YOpMQcbO#<;cezVOzN*37Va55n%)I zA8)9<)4!8NxNH$hlXfNRrRluQmoCU@oQZS_M5VKyK8du8 zYXDSnyp`_=a0mNCJ^lqYihdI>wydagO(b8&xI=`@!n2KWKZRte%EVYmxkRRov0F_k znmYdoh_LER&e61x&wGmKl!Pg9=Gi}D1%mL)Dy+sNxGU$&^6N-(zdPgV+>~TF^BO2# z<22fiJCSIk$rc9qjPtRYllT_{@qYBJi}v3&30j#c^<@X*vHV@spVkKhQwmPEMnG~y zv>buzOD-)RRM8t7*D7naPyc+UMm} z2P`|NOZP`An&bwPydUQ?-8Wj7wqBHV-c$REPL{v_I}^?@P-=qf0~`6SsjhG?hyRT8 z!4lW|BoQvKu{8&&F~ELIT#DmZVeCe&-ukb(v->pF$~x`&c4KkH)<7ld{&TqCvr>5_ z1KM6%3hxSKLRy?|Z7jpiPpgLhBS}`8L2b`0weg25pLU&u0L}UwBmFU#9QTGlCpf5o7O|_5>{cVEF%q*PE;M5B|GucjoM%A_eajZojKhE@u%(j z*EtenW!)lNVHN2w+n@|RQ%JS6`2=R7UTc!K!K>fTgS z0p>^6q9AjhBAv?+e~MfRwg)3p9bvn6;<04JIkuKg+KQC?B_yhJ3ZI6N+bvg~m8-Q` z5SmZsgnfeJtSzl4uf&DNEA_PHJ(q%8Em?*W-8IA5usn&TvdFZu7*aKaa}Xn@n^aJO z#oP4hHG2D6)2IQGCbTX(QR>IkI*@dFoUE(Rp5yxLn{?sXO1E5SzYr1JUe06%Sw{Ru zr89#(FG@Njo)!!g3}a>$__t_-y)cHouU+_(uQb1n$+oob&N&EbI;U{U)Mb1Pr`%az zLdoU;kpjy><%3kx`%lHNA_*HYpIm1TmKaxuG>U@G6ULOtpf+8lHoxe{C%dJ#lhE)7 zmGVT*zwF{7=M=^}^x+1*ZH5icm!`r5xab1`MX+p7Sakb@*PL0+_97c(vG~VyPRb|f z39Dm1&c;?wRrY!%xV6rleFiv_xIhkn!yBaJ3%j(zB<|L_zXy~-J3&i=)ykRHdo;&&61UuS} zvrA{$c(OBF8S`RHS$f&oT4-CYck!!<;#n06-Ro&b$^_Z>3r6_|KABohp8oybQ`od! ztE`i+5~0>P5zDmY^6YfiKV2hv0OlB3qfpg(%0oZ-{0ZD}q&p`jY#KEWye~B?nJDN6 zNf-QS%TkLa%4^RWovcidtCyQ>ZK^|oc-5en8j{aIX*wH!5%Z?St zs=uCVm=mzMTpeFZ+lLG?4=bOjVfc${*QeH=x~>kJDR!FJqlms;sqa%eYdMgFKNW`7 zy#Gy<-?+UV@)k(bIOi1Rp+eovHg>tdwL6Z6NB8$4$Wm+>YU;9B(xxI|=pL6R2X_Ft z3e&lf^?-u%Ls~Q2{V`v*Ss0$sODYk2!NEGeJ%R17o3*z~wo!UrcXf4*{upL{TpFra zmDS~GPKclkGNN-J!E|88aiwJepa*I4&u6o7hEpA2N+76(xlh;FqiCxvnG zkHoeyExt0AS_Se4Yp*K`&x?5Rqw7~Q+p3(5K84PYCh;A<=yGnx`Tx4Ox$8fFoHoVl zo^3MWtxJ2W%m6HQyVuF62qzh7DXznor+sNcss)bkYoFJ(bFr`hr^By~In!ADtwp>ImeFQu42Ju&z9w*gig{7fa?Ol{24M$Jm>6-0yDhD+pmR?})ySB7 zc$5Z3N?AtL7_Q=Mq7qkHE0>$! zvI2RXNIJ7Me?^W=eNU?Jd1i&xa$(1_z*+AG@$rdrH18L6gIRNI3uG@W}`l)yU|E*i?g%(38%)!htD3?IO$nL{u3Xeux{v3-LJ zrPKNCKT6lsTO{Pe2_pb7nVW}oqToC~V>YflK$X&|&Vf(^QZ?;j@T68>?0W}zUcspu zX|<6@_jycti8J-a^-aM}%kDqz2LY$fK)6iS@mUkoK|zm$iB04(1`H+ZN~!OP7QYnjq1R3l zeTjgfv%l7><5hD6NcCUSs0LmDb;G2ugO;G~c_KZ)sIsYOqNHRGX?y*lq9cxu9Gmo3 z;n1%(v-i+tozd7#A3|+ry$m`g<0Js50uLa0O- zy0!N6#vkD^;}jf!GO>M47<5oe>Z_p`MJ`p>>$BAQ$eD8Rvyu=}ZwUDJN}oLjLK-5H6Hu zC@QX+D#J%UIJn*tzg@Gx^Z~v6U9*a>A|(1}`2bQ2JD`Kc z-go+TAkvW}$BTQ$Ff1zt?Au!>?(u31?Zijz0{^u&k^9EPk=*yO>`y@i&u|-|I#qiL z&Jl38?ywQ=2ZPsGi*Gm?;*n1OwCHEUqZb5Si$!P)mAo(cxfIN&9e~j+aPkyz+Dm9X zVxS%KR*O6`H#EfWZ4XDZO#m*1R{QlfS0R;k&Eu&KfOzm zHBj)#hF9Wt2l9bZa^~hfPP%8I#+vN_dRuA5mhDE{8&O^4zUG2iUybX&<$|!|%o}lI zpXWL8a1l)Px3D58PfpgOV$?r5XT(fB=@n=(df=ApU$n3YOXZ_-(N6xa^rX1sq zVf#Wy=JmaWm zmtC{;&aiPadsxX`NbK4^-JjJ4j1wPhr&|-A5X(8LBP^k7J>nMj-k< z6Wd`p$p^+z7Rft-uQzg&r>_hD3Mk$k1k=d>R*L4ol_IMDS#6LvFtYk46aOc8LD9wfzdU?V ziaOsjOa$JA>Mh$X%~H@R{30sLGJyjpKX7Rn_$W47i}{g_Evc^7OSXyXJ2ML*DgQA3 z-}s`b9XbScJTFXoY0M{+n_eC+cj&$1owT{X%R!-M8a-_HMSp^ouXj!s6n~_LwTGz% z?u&5j45_;cdldR2jb|C%2{-cW#b|v{D1Wxf)COK`vmCl6*5vc{zYQB+7@8OfFz|s^ zlO%GDr|9h`#KFK1jV7ei*axyBwLk2j|2(_R_M(-<$i_|Y=MO*>& zGDmeU0ca^P{+#G}^Q*0LzIphAdBptGyuL05!_C2~?tv?8c>T=^fimv*H@P3`9@Q{5 zoqb${4IO4ipcR2nUvu9tl#FK=XPT_gSew&}!$D&rpOjjc8A0@CfJx(P9<8q#L4XNu zMuABcPZ@%pl3~Z-TI>VOo8kk`;yZ(AaT}-TA2%q_@pt@Qfq*?UVAjUTq`x@9Bc(q8 zg%%WHEOEtq(1k4E0Jz1^UX1Jm!3UT$Oh=Oh*bxm^=EGlG^~dqolKm_>no?;me*h~B zR{uPBvJIlssQotTm3(t2$^U=c>HkWDs8Ty~`wq4Jl5uTF*plWDl7JAGkbuaL85KiR z?zImb&AFgu|FpS(y8;akDB&nG$P>#R(}$ zxQM?EYa@h*B7x^&B$@S@ZNH(!jpvhPCH2cx(_jH>92*qXBp&o*>crUEH&)M+Z zwn2H^t@oF89!pia#oC8zCiq8Ky@z&^gG}E=E8PJssNH_>_h>OeQgbR!>6WeCq_bdG zr;|MIXz#OSXX%lp0i`p>78HM1m@E4OimzVLdOF-`~0iEv1S+aQq43aX!9w!tG?x@Y%!G0{A7c7~ap)h6zlTJKVCm66;7Fd@;3 zN_1Fuc?i+C2-CN>U#Rj3iZdWwr%p|{tdE<42v{CU#WUYdSD2xMzf8O)5{nJUEPv)V zG}7Vc8W$1*0Qq ziG1MVe4>t@y_xSaPoULxI)K9ZJZcS&XEi}ayTt&h6I?@^TUY7ymm{$LIo=*5N`I;S zOP9|sG{4njiyCk)&Kq^15W)sklBKvPXw2;pDa0X4xj>-q`4ET#L(1LCdJ_jwBc6Jc&Nf7*kT0;9nCEp;I`uP=`Hph{P`ywEI`bW7`Ks`~kS} z_9Xp%FrBnfOy0Olwa^~hV^bEe?dNjX6t&Ggrc_6w0}7|Z38#%Uh}UO8|L2Hfvyh)t z`xn6sAJP45~4!tf#3V~9e^CT+nR#QPiMPe3O5!UNS; zMC>kmi`i#RTHAoy7d>yfr*G7M|Jw5}RHdh9kR$zXs?zYcJNw`4uFD%Ze)|o+-Fp9O zJD5_NQA1Wk`P5}fAT($kj9)a@YHAXKKne{rMCb3}haQfl<Tgs3-K-^nOIJ-(J^ zFE|i2*!P+vS(SqOynRaQ9I2&SjW&3qjdy}3sZB+inycl?Mn-MnbMX;(Y8huiat8O& zTA8aDLuesAkCPcDAwcI`!j=I-qoI_kGid?FrL9v-zKT_Mw(LZGTDi5mk9I1lBFn#_ zU=79vY^vXNO_d`}V-Iad1$RlaSPc}<1M{hJ2J_kb0%k>vD|6}f<4x%*??sYlM|4Q1 z-+uq;9HYO}^aWOAsgXJJ&%5n$F5GYdoB>VQbhL&yun;>AEC2e8%|X_PoN`T0t+{mu zOaX4Gvl;?wzA4HQKE^7Ma7^B|PGxAG4m|w87@Iz3G{sXWMlg4u-1w6#Vd`ZzL2v`D zkhfjU*zm!ZT51N*qY&-_Hn~c_Po416Qf!W;;>zgwUOsjo=((Nb`#NxH3N;wCv8C+WKCabW>D|8@goWIdn zXsA2QQsOPkDme{@D>)?$W0aA#(ik_bI?JdyEzdw}MmoXZlUg-%>r31pzzI%qP!&SC zpG8n5bs~LIfq_&b!zH;Le?D2!Y-r)Nos4CX&^eZw;bW17UF4i?jYWE2T2mL(oK`Gd){G4F%QqEWbRzBwcuevA@_YJP!o)2uvhA(;KWPhxn3I_#;}$3q{aU zoN(5KE)oWbWQh7(fgt~RGqEIjg0(&5rIMv~=Ac%eUXB3!GldtmggT%b3W`kDMoi>>Z;kjkc}bs@S$|+qP|c#aKZ_6&n@Xw(YFgcBNueoQji5zU=dzbKBng z?sMDyx7zwW=X}TLqxWa1YCd4|ZizePqWDW+lX8Wtfo4hGLY8;haR`uy#b8Z|_skJG zozU2m)WkNz?@;_wh;9PM(A3^VBLtt1XG2iX^Tc8z<537Vq)9k^g-8XY<0CSgaL1OE zimM1Do$$DPyv#X?Fn!l8BzKY z!w!XJ(fJq=QDhyuWON*bg(4d15}}gUgqbdnm~nL+;F)1 ztP91LU2cL4`F8|aFEG+4c~I|bgX6DZzbcnsw%xWV@3LO>)bEi0TAnIErDn7$F(=8`+y9D*y9br|nSVXzY) zEehcxJ9tPUhGSmPm~Ng>A&#Z@<&Wq=egBI07i};v?f~B}kXkrj)6t?t3HsARs?Zp| z#*QxrA44Ufiyt#lN>fWyLBP;{y_a32S+6uzu6S;wLVMHt+Qn{bB|4cqpVn-z#t0y{ z6{UxTDXA-8U6NQ|`4ib})cDHHuy|BxrK#I`z#-nGp}%=4mX5l!7+c*+(J!3;nIKUM zz`4ps+fmHajWsEC7ssc?KH{(w%b84~%I0FX{me)J-#t={d_<|ghc8G@PNitlXR#a~ zO_m@GE5w|Inr%n&R9o3E>QUuyKOsQh=<3NfK|&xnj9bCWk#6gb)7Rm347EF)O2skb z%m65IE5CJDCAMd2wWmf}*hHtGOt%86o)3a-QHki1b-7@~e-bQH9&gIBAhI#w75c)b&RmK)XCsepSq;LON7b2o&HWUJ5~#G zv4c>|tUIa5&5&aX3{=>@uyWpF(8qPqIp%6PzjhBv7(bChjwWa8oFf$<_`_y2LeGXo z&Qyf%0!xX@HNjSEn$Yj0EHm;Yi#bpQD4>YOrbIfq(q zH)0=6DDj3>Xjfn=2#cO2tBZZ96{o3aiF#KZm)lu=1W=r-bNCIXvIateepRt5ES|B9 z^D?SotvbetfLhKVf7@|pC*QJSQXoQqf}PJ(a`K1m_t-*>6mb#I3V`Y%`R*)}JuW#q z-JH*{==(6Yi>yYI?vbhOaRIy4%{oP$e~Zo%LgRVdD#asK8>qOVjoFhj+*EtIlE){*{(I~g>Bur?~nrU#CkUbd^X>I z&2u-T<|$Dz)tDYNxk(+Aa>}$0xhKND{3h)YsWQH)6>q;flS2NCyVr`KNq(eMvrjc~g!sWD@ z%L+=|4;v%UrO=1a2i418r5J(x$_OiiVWVUeaok{?A)M441SM@}dkdCbtGNi$?EIW? zN2EQ93yDtQ0ByiAC9|Mc?48gpd17nc?aej)=@IwALNzU(ZIAqEMfUdY$)UcmgWW+a zohzq9fQ_r@5~^vKL7K1{NiSo)J=QfFXZpu@M3?_g%#@ zPK+;39h~wc7fTEQ?D*i{rW(FN3yTbx3xoO^k}ml_LFajd%|sN_5#VNb!vFff&zcl7 zEPbj>W1lgS|LuWya(6Yi{EUVFx7hUG5=2RgzWSmF#^{Is#>mQ;Ce0qEBn=~4ZInS& zOFzN{iJIjIH1Pu0Fb`lscA?Uj-WtLRIC8U&eCXu?ScDr;^RsE>P5bq6ez|@zYi!&H zo<8!ae<#F{L`Bkwd6Af^1))izsK2oi4j@>Or-Qmf!qJFib$(o@oAxgWS=2=3ta1Ux z<-2NYj_GPg=DO~UYAT}&GGFCVtB>B%#JzO6-MNS7h=tFHewo8qRfAD_I-Hia8qywe zyryKbL(EK6jpW*%y>(e3bY20&O@USR`mdPFOf*`xIxe@BRkX2%9-Qio0Iu;z4R>iz zPntC?d0cUKnr{@_V>52*32MnlII8Ie@8ovvmTHEK4*s@!DelIc6FfXRw|~m-HHL#D zT*bcS4zd7+;z$d*Lj2tSo*)DlI{s4hyO}+F-5HX2ArQ{VcrZn1DD7MYcEPs&&9mfQ zlvwVGi=O~)(uCQV(*aXw?#?NMDcCw2Xo}Dc*;4DLSayqwFoCO$DKVCOwYHu7sg~97 z=%5R%nu+INHmx6t^>q8N3uw6$VCAMpxoS`4; z8T>AeDsBL6TpU7ZQTvPE-MIv`p!KP-2@>kmKAj(8wnR~$6biXgNhT`DBsQax6*NAC z%7@ooUSF#MSwW?>W*+K-C?4ca$ZcD#`Eo<21CCCGT`teNHxs!i&ayScxLfu>?G&&L zYS$0$DXF-AS{veq_(k!Z1Q_GI2M;Fw1Igv|Zi*X_lZ*QFElFc4De9XV>lP^DM`!#z zysV^>d=Ev1A(*wkTr4S5@dza84gSC04bL!oPnFL!3Gb&d{D1N5{d2hLpKb54nu_Y^ zq9}ez4D0m_IKcrnDsLi*`BJDDZ(m5!Vx=UCX!Ni+Da3Vbo3b|S89IFKg>{VDy;S7I zX*G!ipTOUEZD*a3-r1LYhe zhrhd{;9YxZ!sYR(SZKp1=}I}8%{7YVPPHgpC?jwIG0+JM&X}tj#hM1zCu1|y6pQK^ z!{{S3Op6Uf3x|nKasyl-J}ZQ(WV^ z$XL5V+xt=4ZFD}n9%qUdW@r0cQQ6P!+V%A2I%chE252*ey%veo*$r-6*~f9D7oF-Z z+A(Y(6ZRu}*#iVeu1bK5gl_vMaZZ52CbFy+g5^ANgstigRylo(j-s*FTnBQn4gb(V z0KsrRr+iHu&FtIet`&h?0zQ_w=bdVjj#|OddDJ0Xcx5gXhbLUJnl(C$Xxeuzqsa|S zYHGDG2JzV$1LX-DLO-0jPd*``G^mrjh+j*r(W01b zz^UEVIQ}s<0tYNd4Ea)Qpy2}SVy*N@u; zLi;6&^|uJrnTGR7+JY{X0E*1FO^>-2yILq+VZ*QLI*^{jb~K&cB95W_>J-|MrRL)! z5iO1MQ4r1a&A&AH=j+kkBo5GWb|m>~nj*7mdngzeU&KGA_fZ6YGpWQ6g!`Qg80kGO z1gB`}Yzx=uk4bBm-H_TtX0tSK8$}|f86FG^*dWs0=3G`s3hjV$mxx}bN_~JBiR?z+vWyR!;&!SW7$c} zI)bMqwi(-n4o2qPg-#~+ju%q~%hnZrAXKqAX)O-%#r2t4QVhh5`aN1jF!b7SK}bU~ zz0{c+FLkC5JpP6Mi>vr+tg$}UUd%7fTB_*r zvdhzI8~^Y974dhl_SibI6Oivo%PYM2Ko1L6{aW;^O!PeXyv5)X1~R$MpfxH3IlZ~$ zNM%fR3@7dx0=Au|(Ut~d%antoChi(sFh?D3W=}s#gyK011iMuNyTJqi%D67&&z5)L zk$YxGHamP}Z;@W6mj`w5L!cB7dqp*J;m}Z=7sgX z#k-uYJxCN1yq&>Ze1J;IQb6q*M;|WNL}P$!#PXcRi*Eaz?uo#7Y)$9DBC%Ff$Wo?aX1V7xy}*nmy7&g8*}8t%^Cr?yKv1>_$?3>X1CbejnoA?|ZB$#q)4 z?0&1lDRFh^>|kjx0ko@=u_JKeIAxZ;&(+ry0So%+lgr&2>{m4|^5=My=b>U-ZTaSe zjPJGATg+7NYZTQLcd@wP5F@#N)mO3@+#5vS-#fze9%d!>`s_z!3;2m~ZiEzjhC695 zqZz9+9@`@&xA*+?02%*@U6Z-QjG1qfAO>rXkUxPo6ePy z4*8k^CD{HO@2d-fYSj`VOAPAoQ>Ed}+CRb^^y+>1#1gag5Y*_*uqU1}U*}|u@{b08 znwW55q^A@voWLtcmAt<)v!HyBG@+m)^do-XmA;FIC@MH6mCE60xiK&k?s?}&MeGUk z9khn)S=uhJaicKH_4)~-!Ezx4D3FNf$;j)J+>qPmksV(fQJp=G{UK~jhLG0|#4!YQ z#Z?-L;S}MBANT~HgWV}7tnvii9U*O(9i!;_2V~VAxi`W_Xrh{d+#9F`$d`iQG?CRr<%Cx+8~D@Q|XKg?I+)u&g% zK4m^vcBtEc7!hERqkCbooUy@UM_QA9T7%SgKMdcG{52=Dh4gG&i zY~Pibmr@-P;Ar%Q3(fRt=rQjDqgg||Wl1HPk$VX@zzLduI<#89?g-ylr+a@wpRs>RhDxeoNUddSLfddT`|+}HQw~rXc@kp->8% zj)DnoAR7n>YT%FBw3Ti~3eis^tRP4$(6H;8Nf`ZEx?b;9=0?M4>Ji*^^u;6A)ZTDI z&4Dc$zNifI455Lsj24H=b^)s^xA!%QSO;T#B^#>k_g2cr6{PuZ9S@urZypCq{o5Rt zHmK5aIeAz``vs>SY3H=IN;MtDunUzq!KqZF>KyRv=%=k%4`VoSf1BmSWTK=$YC%E> zH%x5;tO1yOLn%P}#Xi7F3#EPQ_YJ~=I6_;szjZFbbno4#4<@_My8wg=zfm{*Acz87 zE0Bhs|76#e2;L;rh$)2$UVC^71Rd0+`Eox-DWX8XI5@9?wGNJ=Z3OeC5wU|M=_A!E?DWbHCs;yU?3IFY$SbX4P6uyYz0Xghg8O)2aPiMrCl zZk)fzsl8;K`tOmax7I`3j%{es(od zOpV|_t6as;Dwp{`eoX)8?EXJ9iGM!6u^O_Ul`h6R-)27x1VWgkh=^*_z!({vDXJK$ zOnteS>-7qSxQ$)9?6iU!7PRs^Y^@QGen~rlfcG`D&S9SFFNJ`5hyu0KQ~$HaUjMr9 z@6Qi}{V;57nJjBCxQ`ZFqu{WtkN9Z`B5G1_;%s3BT%rTwu;ge`lrgNpBSnx$`);*c z^p$O#)nN!D!J?Urg?y?mgIiVpk-OvOrr7F|oMu%mpi7^+6%aPp%o4&r$%4_29-@{%1&X&JC#W8F`Qd!HG|zq0n~%l zADZk{A}ZEh%qDE=uh+mnPEZ}eEdDT8iQU6QsdnyBn1ixC%B0_mV?kV2ujKWlq!2a5 zXy!(+4;7`&nQ$NZi^hX6UDCw4)qzJUzS&xTjz>?g39-A-Kw_SX7%sZaGO1-mzEGZ; zD?diyKTU5S3O|C$LC&z75Ckhgb>|-7RUQw%{`sv^8%z%3_~fF|qz`9@l))V}8Yc~@R-qU@`{%YUIL11xO3+1ia`^X+kZvH9O zcc8i{v^r)~z1>4xbzm>Fa$+W&?F3fxaYy|QGlwloubnN{PLn>Sx;XI;5hcJes0-2+ z_Dq>y8}4UnosYiD{k?=ZD4$9%6?!z2V!t554pb36UO1>k6xMEQF6z~fG&U!Asbwi3 zMdd1Sm*}nj^ZTNE@XJFYNb8$lK{0<&Qa>9Pc;0d=#S>7tsZ{e#?}2Z{6JWQge6Oki0lcn zAX4N?f(0)IYMVSaDp4X6&OOvWzlRh&lICJGMiDKrIC0uWp#MzgD^ntL40ce;_|r=33Ybuopx&{Z;L7Rpe|UY5bolj1!3%pg7ewqJ z^y#(zQ0~u-?ZNNtq+Ggl zmupwr1RO14z9=!`Dxa0smfjiaIVL%tSW!`vc2Z?cA{;FnG;$`WA)1RQ18VrAx@zoN z3jANs&0x1F`D7VVcA_{O5_c}AC^%v7?e3aenV91oHD1*X06Iys!qH)CS?C$x6g? z%uH{1prbSxekUy%C=nXfA_D;8v&Ddr_7J;;jh~a85xm-i)S(ns@x zWFyeLVdYxoj9}fUG+=Qpm{-jAhx7^y7Js8$2(Gh9NPD+~ie>(OOR_VJ^B`$6>>@zS zPpxa+kYHfSH=^+qk7Xzg7On@uJANQr>G zTrHaTXd5ptwdsIR?0YXi4`0OUw-}3pQ}&8tzfziLh+l~kmB|WVKQnxp3ToygQ`5h# z8?Y#MC!l54k@?ZsNQc{C(d&fN(Rjf!|JikGtu{?|t03KPgYys9#^{bp!z388V?!F} zsosH!lS>zzCoeaFfP_`gK@SL0B|tBaqqhO2VP^NsHh9Rz7->7>IkD^zdfCX*AE%f) zj#;P~t|XFpNDX9p$q!u3m+UxXYt|#=u+7l&#CuwFSM3OPGw&nA35le|AY&S!Or&#R z73Ipo{h+>~jCL@*v z9@$+{_9TEXe+k~1+FX?}mXZoL#KqKjOSu_;;d7gBRojHN)$Ot!K~)w*)D4V9?)A{# z_AU`msKh^eZ3Do%xg^nCkJWZ+z#!B!(3I`Rjp=ZiYiEwszy+l>T8{H@4QbiwdDLWX zGRdLTIaaSU3V0?Jfyrh5mZ9*9IE?!t)@qw^56*x@c2nB!)%54Dlq|G5`AvIKuNcyv zuCCg&RZDZZCs~d;^M zZKv0u8nDc9Hm7{ku~f~}6EG~KkOIT*dzJ8JTu7ctbPDjn*2{#yu8!s$gM50}Wn{f? z>&h}W_52#>p)9|qE^^`Dz2u58A@l^wWiQvq_khlVOJ6#2ZyBdn{e|z*CAJL~RFuAT z>DKZr{{F)k2eC{YnuYfq{sGf@`oiaJ0siAvd2RH5&&s1f2kCXt(Zy5lE2$D(`o<-- zr*KD}boC)c={;Bco?ZhA(ZF5mk35 zg|^65#o^9y$W3D35UzG$yW^>ENOK!8@+28M6h>Wv^Ehp$>0!FEo@?@tI-xwPse3N2 zXJnN~YR1zE3KpaFVO@@U{1GiW(u;E}tn<=WB}fK$};ES=OIU6>UdXR0l)y0m4C+N|kmkW=!PC!--+#eVnPjH~%UM2( zBOE^e@%rVh;fD`I6aAKz8qN;xOm4{>w907j*V%cLS@s~KW)%howH8&54H`T^vU}<= z*B<^8)jSu847s~1E81nTOH{5ts3Wf|k<#MgvXR@{47kmEv0dNBQ)b8Y5Vr?!T1PMO zh=j$G)_dea4c}f6fDbZikn79R?^nF&O+U1?MnT;^YU-}3Ak$xpO4S~F*4*QZU@;<} z0evEoIUZFrZIa95Ndxy&vpq3bH(aS4c#~SQWjl?7Twf~g3&A<&x@G0gN&ha-wI5NY zS>n_aSPF^(SK9A;?MsTV81J2OvAll~oC!vqU_IuLN9ak}3Wa;m=UAZ&26)Wpn8`%H zyEixc442ZMyM%6yqU>Ab%G*q2h6s|IV0cTj)D;HfGiGe(8~!Th?wMBMn|!<$IQ$!6 zBV6d_uYfDua9}K{fC{z2Wl!Dv+?_RuQbMYvPo3qEW8doDm=Ty&p!8dY)oy(|yz9IT zh2L`TqJS)!%B5CndY$Inww$Df0U*< zr}(sJ)3k2E4U?2_T5LG}q%v))a6rYpiin^wf{W5r74|`LhY>pYl^wuz20l z6}0FZ9qjwe)AADPJwI=`HZ&^G`(<$kj)I*P0|95VhOG#H7NLzy*h@< ztb4dop-0%^CN4b|_hIm$k$vmo`pY2fkQbfpZ&}{%LLVLc<-ss4VuZ&;OWz+1bWK=4 z1%zx6TiiekGM?DM9|1(GHCADTCWgep%1pTv6t57mU#=f-QU3UJ(SDRe?J3evpsbHL*g$jy}_? z{@(s&Hw(}!s1jqz-4u@0M0vFsoRTV(?}nqnJN zQy@_tP%1#ImiApD&RmBZndTzGMyM-n_^IIVLV}9g6@mNRC(yieZ?3@7km~*xe!%|Vos7aATs1j7mzsj#Xv^ToMEe%%<%1RFh4Ok z=;rAjq;8^7lK>Fe{|p-Cd#%^M;^t%*cVRNZE#jKrk!41fyj6?MW<|h zHl#aLQ@Kuws&kPZ=5DVkBtoPsy{-wm((q;0yWE4`uqNUG$aC9sy#&mdUuptYyR9>l z4t_>@j9&O1oCQ7}bd3hE&-Fa;76lO%5$qE&IZD(5Y<8hJE(-6I5>zhWaSWLhnB3x+ z*C-!!B;(38#H8!!o&qNbs#!O_9+ofr zqg*k ztfK96OByW_uyPW$PT=sqz22%-I|~y7L|`$0bC~_6`W!nIR|2hu&9zYFEGQ^Q41%h3 z5@W5r;mOTkp*|gMhsaVTMFU@^mq`8L0Q8+mjB}?Oo=i?e`s-9wm$Nieeiy#Rkov}O z(Yp9OKyK&DF7XgjWkoCI`c)#c`h+2F$RbT*Yf6DGM(8C7J45n@DYrDw3$=+M+xYf00R{hD2|MV4>0#X8n=A>c z;76kw)H#?ciiWNDg>{*b%g z8D9-$@2rewi;XCKg1L>j&&c0zvfJYFeIX95{DLh!^$g(jwuBh!dDZR<#aQa!a13#^ zzoVs!Sr%755iK>Y(`Lh9Dw==mc``zMfwYt)8K1l|x$;YvmRRP79R5J}?bX#d{}cUO zey90tU7uJvaYa*i%RWNqw`T`c)riKm*a!v%SUpm$B&o1rKR&f1IJ3V{>yOj-m0M{#^BXg1ZGPs*BuQ;XI3@m zI#0%aJ6L=HRuu?b=#P0Pz8}WEAJ~i$?k7I<;)125C0)9q>{|ajr->Y}?eEe^IS%E1BoJ->*|5P6so#A7JXcvX{>k<9*JI5;}OMZz-1%?fkG zJEMQGf5xoiAxF3|9r_z zm7}R@eL}lpZ)XXruja)R#iprAan*vRGpIaPO^KYv^17 zy6FbUW>Uo@HCT;&eP#2hZG|+OVSlMs^ilS|v5RXZY>P=LT2I0|YT>&2K^wneJ`(OlRJr;uomcn12a`$spZm4+$kdU>=b! z*AyIp$uQj;g9)9+S>o)Z-MVxm#|*H7aIv8ct^FdEz#X zM#$-{8^5=VCgs#){o7lRT8-E>_(zN@r1rv2m?A4Sj0tFm6I8ns8CI6QR8I_mRL6s( zu}vR|3DcdT^(x)vT|oFbtr)cnH1H`9mmnC>uIj4zGYk3=DXQeQet|dl4s#MluJBVH z?_PSfO)e|WdV+-jSJBDSg2XC*!s3d9rTA=17p8Pq#>!egE!0J(a>G<;S+7x_zTi$S zDHW6vSbi1V%kCL;{Su>zrkSg6M3s)cPy-}NGp;I;W2EcB#ay{kh4u8oJp1(<~e1%WU+XCBWx@Hh`>WaI3`zMp^ zKe$eXw1NVQpJ~0<&+GiJ8Lt1C{>WQ81I6u4-Q4~~IZynI>WO~hM%P!E?9=KXQ6WPo zw1r`+v`0*0qIO5%DAJ9*xDBOn);zeI^wFNF-w@DZ217ruw4?xg&4w6cjF?LWobdNWn4!N3@q)UV@btS=owN`1sbuM&8vI1 ztK87W7Bp`~4;6jeDV-xfd?>Tn{HE*Gx|=FB%*Se_yMj!M>9Wk4mdoMqBUi;YZYov# zLH{7|=S zI#-><>uauHY8yKN&t?E!p@NmYj)G)R*3_S=M3p)qJ-W8HvEYvMmLyR$6V&dSj%!0q zAw2Rv6V*+CfMbtHm}=~e`1aPHw%^cXGPtQ%Pt6D!g_riFd9e|~uI}Z8u59zQLl-`( zgln55`4rv@3)UDm0S+vg`k5#{2@pNQ-v2lQ2n%h%vHSwm-;uOxeS_WQ5<*S&!fCN} zB(a15d8Q$S;~rd6tWfE~ik4x*+op~l=|+dpY}7b(c>|T%RXAm@a&C$(((xeybWJsSPQbEf`Ft%=N5nm`4=4ew;e&cF3p* zSi{@SS1+0&!c9u0CLXj#f!mlX-d|HUG2cI)pW*wdTG1oOu}5(a&}mHk@L(}4izckZ zxw2TdqINwHJaG~kw=3PMsQ3oC7{UyOn`44&tvHuI@j850Av4S7k2QMttEo7J$P)T% z$ha%)Nt2D7VPm!P2MFw#^GCB?w->!ys{o5$GY*cPQeCl!o`DEI8a{+7!7$T}LP{Z5 z_xP+BHh9f^&JgmS!zo=brIv;K^HerXjBip88HY&mS#?ybx2~xfbdhD>kJ) zR~m>9xXLXd4jG;II?8sY8N5WRz8ksvbBd*?a{bJEQ~PqG=@Z;%#Vr;0JPQdizgofZ zc9mBi>H_cJeeoP1?7Pan|9(Ni!{lcOA+~mTr`ZjV#GJi7F-(4;qyA&a5OPt)ti8+x z{t+{KI4DTIy?TePmR4sNaSxIhF--Tg{I}k#h@YzP9%2?L`)PwEjP-#Sc6eaB?sD}b z8Y(8?xTOw$X0`Q0`+PnbU(I@(PN}da0S461KduFL*ja_g6lzN|Ds?d^h9YE-hzw~T zQFGS6Ls{e<;7o0!BSa|E5T{hHvh@`m0sY?+Yh#$?X8!n!^HnHd_maQCR%~I1+=dcI zgt%<@!n4{Z>5j7+f9}hgS`6V=F1=B@x|pp)yrT4`EzV1XLTxbKcu-;&a(hkmdkjoBtMu**i` zxcASYphYwSz98zHO&(C$OD7LpmUOM0&VX{E*l;YSz-zm%Omj)~^CC zb~cwCYrOpA*O#IC>U}<*@p{?yXx#VlarM{O=;>sh`peWnABRDW_zoUnnYq4@_3H0- zq|L*Pdp@CH{DU)V&aD%%p0F$+hDjEIV=CyFV))qI_p9-e3%p~BT^pd?aFoJV7RmD< z$tRq^LoU*DV%<<}FAd%qs<&|8@y>QFW%gLmbuA;lZqLs3$@^<>pb)S9s&ieO+7@-V z)5NYmUvKQyNjovJ%mOs000rW6ZJe9{1FXm7IuY;Pgk*Ej;Y^{O@($r4JHC; znB_Vf=&?YmDH|Vm5{nTt!hs)}J**x2elQmTUyt8RcyQ{_>r+zdQ0uuRHW&jV<%3P_ zzKJE)vTceP(CXpArWbHpanSrykACpdW}(`dri-~73jR4zgLOaDMRpNgtwVx$UQn4@ zYs1n#kVxleDeaiwTp{C7Lm|I(t~7yZGeJusxkQ3}6f6ECxv+Q>WYu=-)YCCvjg+xF z^E;Kt;i9-iZ*8Mlpo37RppOj=ma~;Quy&$kKrL$-vFL<$_5{}|uYU^E*W&e(2Q5T!{k!TB+eRKb2?o2848|$b`z&jQ!u4~#cYmmdqUD$~%E)mszhCjfG*o!K?4erPBqMc3)NY#Bt zxPdpL#fiMRC9#|mXuCXBj82A4A_Mh^fgA2;aXOY-=!eQO)*CR1szhvJiNxLtxYUiFE zWC6zt8d&D%O;vAiie!@b8~Ktvvh8k`;h?KM+yitW*7^9{T%{;7st@@ePX8tFlPYdZxbjL`jALE=uP+xw=7hp+wV z1@1pJ+-iWJp@fEnAty%Bw$aWnVIld0w0ufg8Tc1k<#(1`;)glZkH)62r+ExK2mOl| zqmYGbD@QtVU2_#f$ydGT^|7g^P}nyNxnj&EH@)dm^0a3zb&D1(sE;{(ysMqNY{lbu z7!))imUC5BShicMCS%+wyR2Imx{;_X0BIRFOiWo0&2vU80%o27iB1)ic!mb9GD6q1 zoRmdRZGl88TBb=^Rqv+}9iwsd>4%5qo4Ccr6h5#{4x-x$g{3hpUcU`W+s0{2+ZvW6 z+=dsC{@(@l?jQO-{!bX{Bgb@CH!n1;N--bxD-|rNNvBn6N*w+SJ1PEyg%~-(GBnwjoHqGeZGoET$gi*CC9;#gL1kn*Z zB^r@x;xckp*w{NojSA6&8%*)B5Hp0fCAS$;4m;hJOpD2SGuhYQhZe$}gK^vV$mbb3 zWnW!iTC_^HvJq?n1UaPiTeQ(~spx*pmk|KxU2*TCe;wZg?GTthM3BU1x`^P1*BLC@d zrRsb5qY_T`?ab|R4=?LW9HMX5q~JhVlNbWY6{%!bM9~cO*cHila%-tXI7OZ6cb|SE zGRlI;q|^B0Eq!CQmZ;f%dQY1>?vJ8E1&ZM9;n;#5WO-Vx&HpgGEv!6<%+M z5=@r(V?5`Gr!VR82AK67k(TXc?cCcWj`l#0eybSo!lwl1@kf?B2s3o>>Q2G@n{Lp6 z|8UGADn!>4ZxV&5tDRQgZNX3m{KPipcAg!j$&jGk^m*19(-a!H z!#3o?iPoOml;uL{xUbJ#tErMBk5YQ`*Pelrq{*2#)#a!-o9egzS4FYpuddkc*+qlR z(bqiv&HH@>vR$y+z#vc(BpvSmt-SK=Nhm~3Ee4tVnbehwPM`p+ZBmArM*&TOrprv zOdB|wfJ|k1eiznX2dALfL=BAz&4Yl86moJ^>V!wRoeS}D`}>Dr=3d~0=6%tNKzvbs zHE|w~G7}4n&~x^MrVz5kLx`q%HIi!g7t zC|<#%XIVU7o&KN*1-L%Exvj6yj&>FM#NWRPo!y9oeGr4)qV_>Ua776iP@cn`Py(;) zQ}x3u9r-f9dUpkBmuG~~#CxN`$>Fy+sFQp|n3ZK8qI--haCw=W!e%%&lN zG^`N}&HG5eFdLr&7YsK4raeH;Kb?B|p@;tkI^HJGzvzyY&+w7R8O>gf!;eSfC zAT7t9I6hCPPI2rSYzO+{`px}R@)Y{B?eN%+Q~}}hYru%sduCqu@JM$bZSs|6x~3zC z!qqOmXyxj5U4SV|AAblywCZZi6|>4}gMw~~owS28OoK|9PD@p!p)g?2N~mcDbrhXp zgGOzJnP-=g;4m1Se{GsnK9W)h#U0Vn9z1JkMs$hk?xn%dzhC&(XPB&;0q>?$CkEWN zmppYByaDV3>lkLG(K%AHP$rvsYY!|1?(gs1+#p7ThM9@$%3^2Ml+p$wP<4VGTbHPo zo2w@}c(B1+?bFEqpS#2VTXL%dKZjN3|L_L= z_l7q0|B?*^#o^`CN@{2@g;C(j{|3>i8MDxl0v3vK6k3pb5igo!9J{73lW`Pd`as`J z$qI#@PJ+LWd^hQC(%&pZJhVKT$#I+I&G0!szH<8YbxU$U0z#fjfkB!^E>mZqGLmzP z!ZS z@l)1nM2MWYM8;>SA8~xZ-+{t>b`|$a&#?ezxA$eCl=g1SYgP>D#5<8Lz6L)i5|f+t zni&;DaaRULko|FUTFQ+ag4OV8C#P!i%fQixUutaHTZDcDX+c_hsICNJwf>sOc0XbC zhmHA{C#{IiU$;>8K*dPpz z_CyM_At%kobJppq<;Nq#CL(p;>?va?+NE1O_b`#CG2jpDDWV~a?eM}_!wF|Wvj0H6 zK&>{ye5ne5OXhWV;dEB+2esVN!zC5*Oe0$2owB0BTwAk9aAlX2F|PzGXTl0RaHG&i z>Qy5wC%~`RCg{iYSpXQ73o$lrBNzsgX|Bigj}ul5*op?LBM9`2b5=3%RGNyf@hBta zw~hOs^J-wctn>yp?uy&|zOTG{CtD7@pXd{~mRrYcdd!D6cAo!t1oA(y1;i1*8M9ua zPEnu|wZ|z`2011qdZb;I8zSJ;%3p3Lzq%L;#nNkl-cImpUuPRmntnck|LdrgKI)Z*n^dcfMJPcJn{V<8|2~(T$*#)i2yE;02@9@t{<$C#!0rK4Cu3Ea z1GjpI1uAu_zRX3uDIjPZ;A(LD;X?!~?p=HqITTBwu;(1dUVa-^k$EM~?)(U0y~F9k zHYb=E;0$G;Oks+P;9Oq3jc0GS(knVR@f~x(rNJ%z91)K>HkB~^U<8+FLHDDQo5F8y zjk{PBSKMrrha(Hmor%+zuev50`gZ~ydE_XYg@T+H**@(A8=D;Z$jr$urW+Qxy+hDA06v*VvVOcxR_jO32O=i|(F=oIY6x!Lm%k>Rr4HsZ7 z={_*$^JJ`qNfRf(i!($m9(|&3benYArtA0{`;KT0h6FOA*1?z(5+nTy0&($2?9q;R zNn62Kv|Xl$85S!0RmxsXMg(yHIO^n6c4Fr-Q%6va8#sLOvDH zVs%>y8~+{h&Ry18GD7v`i?P+0FQorpr~H53;%OgPp#JdkM-J}z)w6DD&GA^AJ#|A9 zU-VwJlCxG_Kt)js(oeSaQ#b351{J*_{X2X4QnvdTukcfT5aNuOMiDNcAxMq+|H zO;(veA3@I&xgb+aB8i3TW`N@`%uj^CJ)nlA$Q(cq7h$IyD^v=!isaxA?ks0mAV`Qq ztW)&i7vMQ2k@W4JhB^RA$g<70rK`zg`0MVinz)031m(Av1lB`a(j>$ zLXfhjs^HP|RJnF4`6;+<68D^NUnOo!Wj#SLlk}|A>-g2V8Vrfq;#DC?+Wwq^Bxw#g zLV}{*dC37wp0xtuQT7`rR%wJeF1~2EFg!z zCxNOg>OwpoL0<1Z^P!y95x<7yO-Vnd1mRKg({TGRLtdX;QKvRx)!lc+=g*a=eJ4TrsCb?lelJq+#>90TGxkZmir{>d1|+h2II4rRV3;j zbCC$ReWwjwcJ+4Q#4UWfHmv$Hd)$F_&+E=d_nAtLaJ?^(#Z59DOd2PQk95o%+I&ph zek&K{9YG#_w-4pZOBu`kn!ul(6cVgWI&DHC-`(b;Otklm!$Temb?@feNf4{gTguoP zh;Tx8axeTE$FGw#tauwQrqh$rIU2u20xMhPa0(aNDZYh#vPSe#CiX=(>+KRe`JA=aC0c1rj)Q0$9zmQMIJQS2%F-XhkU zc-BVv)h5=PeD(_b6%-+e5Bi=QghS~8t)e3RH$WY}%tEuFq_MIlH|wvaPrXliSN+gd zQ%gMyGW?^JwjeMW^=th+ToGe0e3YnW$dZcv%GQD2i^Ql6Vvy&~RL=4f@FpmDlDvtkMQ z;~=TvFi;xS*jhLUq-cTQXn|v~DodySvkn!p$eK__L{Iilo2f^&LS3b_CAR>i%v}8! zsyVg871^UJjI$(gEiFj|D6AFVI{4ZuB8S3eJ}j@gQnA{vDI2h@6B$(eP(rIH&K(LX z7zg+Dq|!E$6gF5mB^h6AOxlN5QEbXHg=0NeUVi=4f9kM%iguIs$I)`R#qNRStkgVh z4fU*~ucElh=C>Z81&RUA>1^RuBx6VU+}Z!&^ceQR36c#V=p$CQ7(t`r3L%&k;k8ez zK*<Q)z>pmNeD(WL^E+4$;8bwOT<*0NYEeoYuI-k{0Lj>9@#$SnMjKY$5qF(qpho zis39`{_@s-sDG?(bff(5_t;6Aun8@Rc+bb0R@UVsQN3F2DxJ9{q}8a1w9X!F=J+tU z05$_94+0!0XM5Mm7Izl)^JZC{0H*bg9)1}W$sD!-WgTpI5s-hKc+7H9@>LHjIPlhY zcZoT<>3#pazl;ZRS3#|%s&;aWU8OahEWm_0XFT@I8*cVX6Vr$$yqRtI8KgT$=^xDW z(W7)5!HE2KI;~b6RE(A$9&|AUz#9X4k%ZJb&_50^;b}vvtc6Tq41WAVpb!A$p$J77 z^C^ZUtNV9+@bp~j78yga4Clxbr=poI(=7AidtZt!PW;)%D<-T+BmsP0u#LJw_<%RS|aM6W25++tlD8b4qBU*T|_>!274$ z)QG_rntVHmz-_sYV7~9}Qw?=XNi_ULR*KLNg_yg&arvwIyUxOQL7#awD@7mpn_#7$ z*}z|>Q}Fw(K^CZO+@cNl`Ajml_(Mvp(OrRXUO2;?{k4>ZezKAuLE5^!cjxMq5$%o! zz1FNit=z;v-QFhlmrm}Ar6DH$>e#_rYfe|NO@q1rTElD02|twy7n0N+nz${gKUgl{wOm>$LX9qThk z^@a=vPL-p%UXFN%` zM`4qb{8D$jhIHQd>>TvaG|!l851FU>F!efH{AmXfS_OoyjtO|ay~JCVJFKjMSquL{ zSm#nwsFQ}`Yq)O^De6pf6zcq29QM5bT)FL-f;pA2ei?7PIw+W~BOk*DfQ}v#3mkc7 zp(3WR0Z!P-d+Mfr-$B{dKt~59l-eTkd3oBagCZGC9+4x- zcTB5~_Jlo)R56E|)~18uQG`QD$=E?G`Z;F16Oq#sgDYFDf@P)t$xiy)CCQ<(cxp28 zTu9@e@5f@Se>z;4h@Ng+S48kYYN#hY2lRi9Qs7{rs1NNjcBf)irvPl1$ZeNe zLuX+^+*>VBT|e2M=hOE6Vg7udXd&rI4V|Hn8>pPDwf+-hUcoTD4847r zW{jm*0p1i4iE9yRG_S}rR=>;~I{yaaB)!X)gA&hDNeg=Ur5SmW)F*vw7-`02mLI{e z#gL$MzSs+DKGV{GcCdKw@)BQhe=1PVByFBUd--7V&Pz`sSwKW>O6|vF>U#wuAW$$v(w)i_+85*12Ir}o-ZaOsWZ0u9lIcAM4@=@% zwq}c7(178ezvtVpfQ|0hLSC!5Nxzd7%4y>TaZ18UAW6!eXa*}edAUs+8(jmiFRGx0 z1(p77YJYA<>7?I3J#!)KlM`RDE4+m+9GFO-56Z91+`vG9gv;NXLoZkO8bGv6!5zOs zTl)Ib7#hJhhR_@`IfrzQ;#xv!oa&BM2hkjjKxdU3hAU`fXasznS=}9eTb%w0ymJ8$ zLM+?QRH`wDEYpj}DNm}Xg`E?@p14tIGw&*+c^U{BPwTYp-f9W#qG8?5sF_umXce!P z=%V3@AwNwvs)5T8{=sZz>EyZo_f$R$IqCURFEd`A9diJd}I_{`R}$SU0#1-M4{L6}yhSzEG1< zPvbp`QrsU3`E@{HDvHRPLBBxM@6WjiphU_qz&`aa#X;}rm`! z!zI2aUhi_fy4d~h2%aads$MBO^0kX1JqZFMB?6tve4ki(Si5F0I~=* z3ON@;J(n0h)W8Cp6Ate2zRSWOQ$FC+g>{bO@c?o6oTE9*AL8<08H1u;LHjHUA`M`M> zj~H3(9qFfUxahL+JSWcco(679mQTDxj`5z)TFl{61mjV+2!o`3pQ}Pxf7#&87|l)I zJHt<#ob_5?(5`5?0F&hT1>E^|e0lv)8TS?QBrVI5lj1*Rq8!8fOGy$;59k&LUDa7j ztC-@EM>I9>2V(M`@JWy!pocK*n%5ZbI^}8pT8ublHbSn_G-G&Rq%Yy%gAKDWSDx6R5gzVoXt#fJMIKXnbe)%7m=A!mx5hOt`? z%QtT*;izkr_2wDq4gfeDyWF3^#hO*FG1=ss424djL0o&>uh9~0gf~#Mbhcn5)OGZ2 ze7MO$Qd`-x4*i56@mn$}v%VSZbJ*bLF*M;m==mP`Q2&%Fe@_g9S9{8i(vq5nirkut z#BOHEGVB?h5|MXPC1U+?6STM$ee+SNwg9kFNt*jy?QenEoGH zT2LB7-^r^b9O+$jjMXVZ)WvFa_}o1{@{>B}-d7t#{t2Hvx*sS@$44ygXgpX$16)o` z4JY!fw~v~9ZI8Ytx)YeQn(*$I&mkOfe@`Hho(91>((V!T9hTV;Kgo3XAvE0Xd|M>3 zG!x(IHtly>qr}?q@!{J^YZT0R+fAP<;gKHX7f9+;%*Xo0fg_1(NZph&YEZpy4rr@cHwGN(yG52{1RppnxKSr9rH$fI zS1~2t)toaW!c@0!D$@4fLMXW5Bt_FF4jH)Rm5dKL&bNcIcHUyDt8iN>IBBBqmqppVooL1#d9FcU!?j!5+ZamP+3_D|vT)pMs_ z*5%6YgRg~?YyqUm4(fyn+h(Z7Tm;|)8Piqp z^5mVX&Xr4;t1`;u{Zu9uC}*gml}a3|&gCdasE*1MgH&i`DT7sL6-%V5xTOm+wB6bz zjNA^O0Erig;fkXNiQ!5TkE19`fFUXw`4R?gw_1soj$72k(T7n5CBPJwj6z9`cFUgv zZf&<#i35)VEP&E>qDiUZKb5Qk`Mvg9m4ZQ!gB1Wv4^?uh;tc(`0L&x}-C}4cCxbXS z8A2a7$zih0OlZlsc_O)lqkgOO_;hG0Cxaw;dtddB(7=N_r(8wy!{dI<%#iS6 zn&^QC0H%M&n990(MlTXpEw0M$%8b};D1cEaV|TzK{{c0PR>`Q!3pZ7sYz3>%o|^jup-)OWdK+1Cpx+EpXM-(qB=XlH|86TENQ%ez9L4X>6# zShlb|6gZJ-zx6d{vUmV$f%YA$=L&FzY3%pEa^jy19vBW1)zNMgH=%ZJOH;D|1B={F zYtDkKtc=@tsG@{^x0mCY^m28a3+24Wce>Z>#>*=-mx`^dQ^PgOOU?$oiVM!VA9lP` z2^8^Kjd^APWLO@Z-Ta#F#7BeJbq~aHG*+S9(l%UPxaV@|^VN92d)05K zJhRl~n&oj}5O6p_N!!Ez7>w6jPxz_qV0xFSPis}9&=YA{{T^pIU|IApxt}LFWrywR zYjk$#>t~Z2z|PY9#xp#ymbzkR4ahZ5rl`8?NUNImYTM|#8O|S_+fNZ@-BP^sk_Git zPcyHuT$V?j!I{-BYaN1ZwDuS(>P~f7#NwvNxlZSt}&@_=D_g z$M$r9VAHXhdA3b4F+uwJ3pY##UA66C$FYi_!dp~f7u|JqF zJpLx*{n-`@!$g2ZFzDWZiMAc&HRLX(#}hiWEBHqq<6gUv%nB<*_~2M3gBfHJCW*9V6BgDsOiT(t!F3@dA7)Vvw` z-<4j~RoUYkWE_6+KHrP?WuGgI1@ID#T-iGy5r2sL0OkD)wTw5s_o%d}-`G*uQbYx3 zJfig=bDKq=YZ~H#4v3Uq#0;%7_&$>Ody>0uZ=0jE#PL~$cPfM8Jo;v?CElbs@8h@9 zt4PT@6ccbN1^2YHH}rk+DD`)s4^{Z-k^22;2xJwbzocU|x(IiH$95ax@XfgLE$kG| zc-7yUBoP(m@4}$zTxy;aIR-%PT%(vr^QF2|G!{QW;KrofL+U-p=icp5WQW{fx)01# zPH?m=7)sbLaS0X$8~O28y$M^Gr=gEz!i5XTnmo5?Rbej`gY?7&DYRGJ#hRN>XlE+= z=5F@|KCp{m5FdMLO7R)Sz;pdjDg9YGP{;V1gKDfu*=VR#Q$4Y~Ar5~_GHP~|NP)^F zmH~{`A1%WkrTd3$=cvM&niIx|u=lt#$<&aMTgr9$E>&7Y!tFD$ zLYcd;T-q+BR)|MoT4xmgPU=9d!{qnWZ&Y%C#l6&#TD%FwR2o{eLTPJ4^?CvIL1k?p zPaS*Lz}|sc*=~oCRTxupg`8(|`36(6i3QJ{YvUwSwh8YPNLIxY_5KQk4AxZCHTCX_ z$drB-?n#fRO=|KThcXr)GhUf5Lx02&zNgTpVz+8wyqIed3j)B13)rRYIEe% zi7S;+sxbFw;XzCsk729F0v@A5&>A`^Q%!yF_^MF5@wjD_T7~ZU2z>#LLXqxloZg}B z_&;b7v7pp3hG0re1}tN|p?Rv5d&86$oVgs`e8UuQoVj9M#yCB6d#QLoJCeQxJE=Oq z5vd@xeuiKwOcTa&{U|dzdbJVyU|Xp&zY*ym%A*uk@I8qjwO$4b)QAk&x&(t&G%0Du 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¨>gq-;Wj30|}A*CN2eYmS7i$fH43nNqgfP(}>h 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%0D1H6m$Z+>m38s8SEP5u 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 - 4.0.0 - - - com.carrotsearch.randomizedtesting - randomizedtesting-parent - 2.7.9-SNAPSHOT - ../pom.xml - - - junit4-ant - - - - ${java.home} - ${proguard.java.home}/lib/rt.jar - - - - - org.apache.ant - ant - provided - - - - org.apache.ant - ant-junit - provided - - - - - - junit - junit - jar - provided - - - - - - com.google.guava - guava - provided - - - - org.ow2.asm - asm - provided - - - - com.carrotsearch.thirdparty - simple-xml-safe - provided - - - - com.carrotsearch.randomizedtesting - randomizedtesting-runner - ${project.version} - provided - - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - ${version.maven-surefire-plugin} - - - ${project.build.directory}/test-classes - - - **/tests/** - **/it/** - - - - - - - surefire-it - integration-test - - test - - - - **/it/Test*.java - - - **/tests/** - - ${project.build.directory}/dontinclude - - com.carrotsearch.randomizedtesting:randomizedtesting-runner - com.google.guava:guava - - - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - org.apache.maven.plugins - maven-dependency-plugin - [1.0.0,) - - copy-dependencies - - - - - - - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - ${version.maven-javadoc-plugin} - - ${basedir}/src/main/java/com/carrotsearch/ant/tasks/junit4/package.html - - - JUnit4 ANT task - com.carrotsearch.ant.tasks.junit4* - - - Listeners and report writers - com.carrotsearch.ant.tasks.junit4.listeners* - - - Load balancers - com.carrotsearch.ant.tasks.junit4.balancers* - - - Events and aggregated events for reports - com.carrotsearch.ant.tasks.junit4.events* - - -

${project.name} v${project.version}
API Documentation]]>
- com.carrotsearch.ant.tasks.junit4.slave - - - - - - - - de.thetaphi - forbiddenapis - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - package - - copy-dependencies - - - - - com.carrotsearch.randomizedtesting,junit,org.hamcrest,org.ow2.asm - - - - - org.apache.maven.plugins - maven-jar-plugin - - true - - - - - com.pyx4me - proguard-maven-plugin - 2.0.4 - - - package - - proguard - - - - - - - - com.google.guava - guava - !com/google/common/eventbus/SynchronizedEventHandler.class - - - org.ow2.asm - asm - !module-info.class - - - com.carrotsearch.thirdparty - simple-xml-safe - - - com.carrotsearch.randomizedtesting - randomizedtesting-runner - - - - - true - true - false - true - ${project.build.directory} - ${basedir}/src/proguard/rules.pro - - - - - ${proguard.rt.jar} - - - - - net.sf.proguard - proguard - 4.6-customized - system - ${project.basedir}/lib/proguard.jar - - - - - - - - src/main/resources - - **/*.jsonp - **/ideas.txt - - - - - - - - jdk19-compat - - [1.9,] - - - - - org.apache.maven.plugins - maven-enforcer-plugin - ${version.maven-enforcer-plugin} - false - - - enforce-proguard-java-home - validate - - enforce - - - - - - ${proguard.rt.jar} - - - IMPORTANT! You must set proguard.rt.jar or proguard.java.home manually for obfuscation. - - - - - - - - - - - - - diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/BalancersList.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/BalancersList.java deleted file mode 100644 index 73dc98d1..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/BalancersList.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import java.util.List; - -/** - * A nested list of {@link SuiteBalancer}s. - */ -public class BalancersList { - private List balancers; - - public BalancersList(List balancers) { - this.balancers = balancers; - } - - /** - * Adds a balancer to the balancers list. - */ - public void addConfigured(SuiteBalancer balancer) { - balancers.add(balancer); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/DiagnosticsListener.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/DiagnosticsListener.java deleted file mode 100644 index 37cda0ee..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/DiagnosticsListener.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import org.apache.tools.ant.Project; -import org.apache.tools.ant.Task; - -import com.carrotsearch.ant.tasks.junit4.events.BootstrapEvent; -import com.carrotsearch.ant.tasks.junit4.events.IEvent; -import com.carrotsearch.ant.tasks.junit4.events.QuitEvent; -import com.google.common.eventbus.Subscribe; - -public class DiagnosticsListener { - private final ForkedJvmInfo slave; - - private boolean quitReceived; - private Task task; - - public DiagnosticsListener(ForkedJvmInfo slave, JUnit4 task) { - this.task = task; - this.slave = slave; - } - - @Subscribe - public void receiveAll(IEvent e) { - task.log("Packet received, slave#" + slave.id + ">" + e.getType(), Project.MSG_DEBUG); - } - - @Subscribe - public void receiveBootstrap(BootstrapEvent e) { - task.log("Default encoding: " + e.getDefaultCharsetName(), Project.MSG_VERBOSE); - } - - @Subscribe - public void receiveQuit(QuitEvent e) { - quitReceived = true; - } - - boolean quitReceived() { - return quitReceived; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/DuplicateResources.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/DuplicateResources.java deleted file mode 100644 index 08a4f72d..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/DuplicateResources.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.tools.ant.types.DataType; -import org.apache.tools.ant.types.Resource; -import org.apache.tools.ant.types.ResourceCollection; - -/** - * Duplicate nested resources N times. Useful for running - * suites multiple times with load balancing. - */ -public class DuplicateResources extends DataType implements ResourceCollection { - private final List rcs = new ArrayList(); - private int times; - - public void addConfigured(ResourceCollection rc) { - this.rcs.add(rc); - } - - /** - * Set the number of times the input resources should be duplicated. - */ - public void setTimes(int times) { - this.times = times; - } - - @Override - public Iterator iterator() { - return getElements().iterator(); - } - - private List getElements() { - List elements = new ArrayList<>(); - for (ResourceCollection rc : rcs) { - for (Resource r : rc) { - for (int t = 0; t < times; t++) { - elements.add(r); - } - } - } - return elements; - } - - @Override - public int size() { - return getElements().size(); - } - - @Override - public boolean isFilesystemOnly() { - for (Iterator i = iterator(); i.hasNext();) { - if (!((Resource) i.next()).isFilesystemOnly()) { - return false; - } - } - return true; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/Duration.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/Duration.java deleted file mode 100644 index 1ba02b72..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/Duration.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import java.util.Locale; - -public final class Duration { - /** - * Format a duration in milliseconds to a human string (in English). - */ - public static CharSequence toHumanDuration(long duration) { - final long MILLIS_IN_A_SECOND = 1000; - final long MILLIS_IN_A_MINUTE = MILLIS_IN_A_SECOND * 60; - final long MILLIS_IN_AN_HOUR = MILLIS_IN_A_MINUTE * 60; - final long MILLIS_IN_A_DAY = MILLIS_IN_AN_HOUR * 24; - - boolean longTime = (duration >= MILLIS_IN_A_SECOND * 10); - - StringBuilder str = new StringBuilder(); - duration = emitOrSkip(duration, str, MILLIS_IN_A_DAY, " day", true); - duration = emitOrSkip(duration, str, MILLIS_IN_AN_HOUR, " hour", true); - duration = emitOrSkip(duration, str, MILLIS_IN_A_MINUTE, " minute", true); - if (longTime) { - duration = emitOrSkip(duration, str, MILLIS_IN_A_SECOND, " second", true); - } else { - str.append(String.format(Locale.ROOT, "%.2f sec.", (duration / 1000.0f))); - } - return str; - } - - private static long emitOrSkip(long value, StringBuilder str, long unit, String unitName, boolean skipEmpty) { - final long units = value / unit; - if (units != 0 || !skipEmpty) { - if (str.length() > 0) str.append(" "); - str.append(units) - .append(Pluralize.pluralize((int) units, unitName)); - } - - value -= units * unit; - return value; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/ForkedJvmInfo.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/ForkedJvmInfo.java deleted file mode 100644 index 09156616..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/ForkedJvmInfo.java +++ /dev/null @@ -1,174 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import java.io.IOException; -import java.io.Writer; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import com.carrotsearch.ant.tasks.junit4.events.BootstrapEvent; -import com.carrotsearch.ant.tasks.junit4.events.IEvent; -import com.carrotsearch.ant.tasks.junit4.events.IStreamEvent; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; -import com.carrotsearch.randomizedtesting.WriterOutputStream; - -/** - * Static slave information. - */ -public final class ForkedJvmInfo { - /** - * Unique sequential slave identifier. - */ - public final int id; - - /** - * The number of executed slaves, total. - */ - public final int slaves; - - /** - * Bootstrap event. - */ - private BootstrapEvent bootstrapEvent; - - /** - * Timestamps for diagnostics. - */ - long start, end; - - /** - * Execute these test suites on this slave. - */ - ArrayList testSuites; - - /** - * Complete slave command line invocation string. - */ - String slaveCommandLine; - - /** - * Execution error if anything bad happened on the slave. - */ - Throwable executionError; - - /* */ - public ForkedJvmInfo(int id, int slaves) { - this.id = id; - this.slaves = slaves; - } - - /** - * Return the {@link Charset} used to encode stream bytes from the slave. - */ - public Charset getCharset() { - if (bootstrapEvent != null) { - return Charset.forName(bootstrapEvent.getDefaultCharsetName()); - } else { - return Charset.defaultCharset(); - } - } - - /** - * System properties on the slave. - */ - public Map getSystemProperties() { - if (bootstrapEvent == null) { - throw new RuntimeException("Bootstrap event not yet received."); - } - - return bootstrapEvent.getSystemProperties(); - } - - /** - * PID string of the forked JVM. May not be available or may come in an unknown format - * (Java 8 will have real PID support, supposedly). - */ - public String getPidString() { - BootstrapEvent event = this.bootstrapEvent; - if (event == null) { - return "(?)"; - } else { - return event.getPidString(); - } - } - - /** - * Command line string used to invoke the slave. - */ - public String getCommandLine() { - return slaveCommandLine; - } - - /** - * JVM name (slave). - */ - public String getJvmName() { - return getSystemProperties().get("java.vm.name") + ", " + - getSystemProperties().get("java.vm.version"); - } - - /** - * Slave execution time. - */ - long getExecutionTime() { - return end - start; - } - - /** - * Set the bootstrap event associated with this slave. - */ - void setBootstrapEvent(BootstrapEvent e) { - this.bootstrapEvent = e; - } - - /** - * Filter through events looking for sysouts and syserrs and decode them - * into a character streams. If both {@link Writer} arguments are the same object - * the streams will be combined. - */ - public void decodeStreams(List events, Writer sysout, Writer syserr) throws IOException { - int lineBuffer = 160; - WriterOutputStream stdout = new WriterOutputStream(sysout, getCharset(), lineBuffer, true); - WriterOutputStream stderr = new WriterOutputStream(syserr, getCharset(), lineBuffer, true); - for (IEvent evt : events) { - switch (evt.getType()) { - case APPEND_STDOUT: - if (sysout != null) { - ((IStreamEvent) evt).copyTo(stdout); - } - break; - - case APPEND_STDERR: - if (syserr != null) { - ((IStreamEvent) evt).copyTo(stderr); - } - break; - - default: - break; - } - } - - stdout.flush(); - stderr.flush(); - } - - public void serialize(JsonWriter w) throws IOException { - w.beginObject(); - - w.name("id").value(id); - w.name("jvmName").value(getJvmName()); - w.name("charset").value(getCharset().displayName(Locale.ROOT)); - w.name("commandLine").value(getCommandLine()); - - w.name("systemProperties").beginObject(); - for (Map.Entry e : getSystemProperties().entrySet()) { - w.name(e.getKey()).value(e.getValue()); - } - w.endObject(); - - w.endObject(); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/FormattingUtils.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/FormattingUtils.java deleted file mode 100644 index 888fc995..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/FormattingUtils.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; - -import org.junit.runner.Description; - -/** - * Formatting utilities for consistency across code. - */ -public final class FormattingUtils { - /* */ - public static String padTo(int columns, String text, String ellipsis) { - if (text.length() < columns) { - return text; - } - - text = ellipsis + text.substring(text.length() - (columns - ellipsis.length())); - return text; - } - - public static String formatTime(long timestamp) { - return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ROOT).format(new Date(timestamp)); - } - - public static String formatTimestamp(long ts) { - return new SimpleDateFormat("HH:mm:ss.SSS", Locale.ROOT).format(new Date(ts)); - } - - public static String formatDurationInSeconds(long timeMillis) { - final int precision; - if (timeMillis >= 100 * 1000) { - precision = 0; - } else if (timeMillis >= 10 * 1000) { - precision = 1; - } else { - precision = 2; - } - return String.format(Locale.ROOT, "%4." + precision + "fs", timeMillis / 1000.0); - } - - public static String formatDescription(Description description) { - return formatDescription(description, false); - } - - public static String formatDescription(Description description, boolean fullNames) { - StringBuilder buffer = new StringBuilder(); - String className = description.getClassName(); - if (className != null) { - if (fullNames) { - buffer.append(className); - } else { - String [] components = className.split("[\\.]"); - className = components[components.length - 1]; - buffer.append(className); - } - if (description.getMethodName() != null) { - buffer.append(".").append(description.getMethodName()); - } else { - buffer.append(" (suite)"); - } - } else { - if (description.getMethodName() != null) { - buffer.append(description.getMethodName()); - } - } - return buffer.toString(); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/JUnit4.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/JUnit4.java deleted file mode 100644 index f4b3e833..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/JUnit4.java +++ /dev/null @@ -1,1912 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import static com.carrotsearch.randomizedtesting.SysGlobals.*; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.RandomAccessFile; -import java.io.Serializable; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.nio.file.*; -import java.nio.file.attribute.BasicFileAttributes; -import java.text.SimpleDateFormat; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.Deque; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; -import java.util.Random; -import java.util.Vector; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import com.carrotsearch.ant.tasks.junit4.runlisteners.RunListenerClass; -import org.apache.tools.ant.AntClassLoader; -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.Project; -import org.apache.tools.ant.ProjectComponent; -import org.apache.tools.ant.Task; -import org.apache.tools.ant.taskdefs.Execute; -import org.apache.tools.ant.types.Assertions; -import org.apache.tools.ant.types.Commandline; -import org.apache.tools.ant.types.CommandlineJava; -import org.apache.tools.ant.types.Environment; -import org.apache.tools.ant.types.Environment.Variable; -import org.apache.tools.ant.types.FileSet; -import org.apache.tools.ant.types.PropertySet; -import org.apache.tools.ant.types.Resource; -import org.apache.tools.ant.types.ResourceCollection; -import org.apache.tools.ant.types.resources.Resources; -import org.apache.tools.ant.util.LoaderUtils; -import org.junit.runner.Description; -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -import com.carrotsearch.ant.tasks.junit4.SuiteBalancer.Assignment; -import com.carrotsearch.ant.tasks.junit4.balancers.RoundRobinBalancer; -import com.carrotsearch.ant.tasks.junit4.balancers.SuiteHint; -import com.carrotsearch.ant.tasks.junit4.events.BootstrapEvent; -import com.carrotsearch.ant.tasks.junit4.events.QuitEvent; -import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedQuitEvent; -import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedStartEvent; -import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatingListener; -import com.carrotsearch.ant.tasks.junit4.events.aggregated.ChildBootstrap; -import com.carrotsearch.ant.tasks.junit4.events.aggregated.JvmOutputEvent; -import com.carrotsearch.ant.tasks.junit4.listeners.AggregatedEventListener; -import com.carrotsearch.ant.tasks.junit4.slave.SlaveMain; -import com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe; -import com.carrotsearch.randomizedtesting.ClassGlobFilter; -import com.carrotsearch.randomizedtesting.FilterExpressionParser; -import com.carrotsearch.randomizedtesting.FilterExpressionParser.Node; -import com.carrotsearch.randomizedtesting.MethodGlobFilter; -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.SeedUtils; -import com.carrotsearch.randomizedtesting.SysGlobals; -import com.carrotsearch.randomizedtesting.TeeOutputStream; -import com.carrotsearch.randomizedtesting.annotations.SuppressForbidden; -import com.carrotsearch.randomizedtesting.generators.RandomPicks; -import com.google.common.base.Joiner; -import com.google.common.base.MoreObjects; -import com.google.common.base.Strings; -import com.google.common.base.Throwables; -import com.google.common.eventbus.EventBus; -import com.google.common.eventbus.Subscribe; -import com.google.common.io.CharStreams; -import com.google.common.io.Closeables; -import com.google.common.io.Closer; -import com.google.common.io.FileWriteMode; - -/** - * An ANT task to run JUnit4 tests. Differences (benefits?) compared to ANT's default JUnit task: - *
    - *
  • Built-in parallel test execution support (spawns multiple JVMs to avoid - * test interactions).
  • - *
  • Randomization of the order of test suites within a single JVM.
  • - *
  • Aggregates and synchronizes test events from executors. All reports run on - * the task's JVM (not on the test JVM).
  • - *
  • Fully configurable reporting via listeners (console, ANT-compliant XML, JSON). - * Report listeners use Google Guava's {@link EventBus} and receive full information - * about tests' execution (including skipped, assumption-skipped tests, streamlined - * output and error stream chunks, etc.).
  • - *
  • JUnit 4.10+ is required both for the task and for the tests classpath. - * Older versions will cause build failure.
  • - *
  • Integration with {@link RandomizedRunner} (randomization seed is passed to - * children JVMs).
  • - *
- */ -public class JUnit4 extends Task { - /** - * Welcome messages. - */ - private static String [] WELCOME_MESSAGES = { - "hello!", // en - "hi!", // en - "g'day!", // en, australia - "¡Hola!", // es - "jolly good day!", // monty python - "aloha!", // en, hawaii - "cześć!", // pl - "مرحبا!", // arabic (modern) - "kaixo!", // basque - "Привет!", // bulgarian, russian - "你好!", // cn, traditional - "ahoj!", // czech - "salut!", // french - "hallo!", // german - "שלו×!", // hebrew - "नमसà¥à¤¤à¥‡!", // hindi - "áŠáƒ!", // inuktitut - "ciao!", // italian - "今日ã¯!", // japanese - "olá!", // portuguese - // add more if your country/ place is not on the list ;) - }; - - /** Name of the antlib resource inside JUnit4 JAR. */ - public static final String ANTLIB_RESOURCE_NAME = "com/carrotsearch/junit4/antlib.xml"; - - /** @see #setParallelism(String) */ - public static final Object PARALLELISM_AUTO = "auto"; - - /** @see #setParallelism(String) */ - public static final String PARALLELISM_MAX = "max"; - - /** Default value of {@link #setShuffleOnSlave}. */ - public static final boolean DEFAULT_SHUFFLE_ON_SLAVE = true; - - /** Default value of {@link #setParallelism}. */ - public static final String DEFAULT_PARALLELISM = "1"; - - /** Default value of {@link #setPrintSummary}. */ - public static final boolean DEFAULT_PRINT_SUMMARY = true; - - /** Default value of {@link #setHaltOnFailure}. */ - public static final boolean DEFAULT_HALT_ON_FAILURE = true; - - /** Default value of {@link #setIsolateWorkingDirectories(boolean)}. */ - public static final boolean DEFAULT_ISOLATE_WORKING_DIRECTORIES = true; - - /** Default valkue of {@link #setOnNonEmptyWorkDirectory}. */ - public static final NonEmptyWorkDirectoryAction DEFAULT_NON_EMPTY_WORKDIR_ACTION = NonEmptyWorkDirectoryAction.FAIL; - - /** Default value of {@link #setDynamicAssignmentRatio(float)} */ - public static final float DEFAULT_DYNAMIC_ASSIGNMENT_RATIO = .25f; - - /** Default value of {@link #setSysouts}. */ - public static final boolean DEFAULT_SYSOUTS = false; - - /** Default value of {@link #setDebugStream}. */ - public static final boolean DEFAULT_DEBUGSTREAM = false; - - /** Default value of {@link #setUniqueSuiteNames(boolean)} */ - public static final boolean DEFAULT_UNIQUE_SUITE_NAME = true; - - /** System property passed to forked VMs: current working directory (absolute). */ - private static final String CHILDVM_SYSPROP_CWD = "junit4.childvm.cwd"; - - /** - * System property passed to forked VMs: junit4's temporary folder location - * (must have read/write access if security manager is used). - */ - private static final String SYSPROP_TEMPDIR = "junit4.tempDir"; - - /** What to do on JVM output? */ - public static enum JvmOutputAction { - PIPE, - IGNORE, - FAIL, - WARN, - LISTENERS - } - - /** What to do when there were no executed tests (all ignored or none at all?). */ - public static enum NoTestsAction { - IGNORE, - FAIL, - WARN - } - - /** - * @see #setJvmOutputAction(String) - */ - public EnumSet jvmOutputAction = EnumSet.of( - JvmOutputAction.LISTENERS, - JvmOutputAction.WARN); - - /** - * @see #setSysouts - */ - private boolean sysouts = DEFAULT_SYSOUTS; - - /** - * @see #setDebugStream - */ - private boolean debugStream = DEFAULT_DEBUGSTREAM; - - /** - * Slave VM command line. - */ - private CommandlineJava slaveCommand = new CommandlineJava(); - - /** - * Set new environment for the forked process? - */ - private boolean newEnvironment; - - /** - * @see #setUniqueSuiteNames - */ - private boolean uniqueSuiteNames = DEFAULT_UNIQUE_SUITE_NAME; - - /** - * Environment variables to use in the forked JVM. - */ - private Environment env = new Environment(); - - /** - * Directory to invoke forked VMs in. - */ - private Path dir; - - /** - * Test names. - */ - private final Resources resources; - - /** - * Stop the build process if there were errors? - */ - private boolean haltOnFailure = DEFAULT_HALT_ON_FAILURE; - - /** - * Print summary of all tests at the end. - */ - private boolean printSummary = DEFAULT_PRINT_SUMMARY; - - /** - * Property to set if there were test failures or errors. - */ - private String failureProperty; - - /** - * A folder to store temporary files in. Defaults to {@link #dir} or - * the project's basedir. - */ - private Path tempDir; - - /** - * Listeners listening on the event bus. - */ - private List listeners = new ArrayList<>(); - - /** - * User-defined {@link org.junit.runner.notification.RunListener}s. - */ - private List runListeners = new ArrayList<>(); - - /** - * Balancers scheduling tests for individual JVMs in parallel mode. - */ - private List balancers = new ArrayList<>(); - - /** - * Class loader used to resolve annotations and classes referenced from annotations - * when {@link Description}s containing them are passed from slaves. - */ - private AntClassLoader testsClassLoader; - - /** - * @see #setParallelism(String) - */ - private String parallelism = DEFAULT_PARALLELISM; - - /** - * Set to true to leave temporary files (for diagnostics). - */ - private boolean leaveTemporary; - - /** - * A list of temporary files to leave or remove if build passes. - */ - private List temporaryFiles = Collections.synchronizedList(new ArrayList()); - - /** - * @see #setSeed(String) - */ - private String random; - - /** - * @see #setIsolateWorkingDirectories(boolean) - */ - private boolean isolateWorkingDirectories = DEFAULT_ISOLATE_WORKING_DIRECTORIES; - - /** - * @see #setIsolateWorkingDirectories(boolean) - */ - private NonEmptyWorkDirectoryAction nonEmptyWorkDirAction = DEFAULT_NON_EMPTY_WORKDIR_ACTION; - - /** - * Multiple path resolution in {@link CommandlineJava#getCommandline()} is very slow - * so we construct and canonicalize paths. - */ - private org.apache.tools.ant.types.Path classpath; - private org.apache.tools.ant.types.Path bootclasspath; - - /** - * @see #setDynamicAssignmentRatio(float) - */ - private float dynamicAssignmentRatio = DEFAULT_DYNAMIC_ASSIGNMENT_RATIO; - - /** - * @see #setShuffleOnSlave(boolean) - */ - private boolean shuffleOnSlave = DEFAULT_SHUFFLE_ON_SLAVE; - - /** - * @see #setHeartbeat - */ - private long heartbeat; - - /** - * @see #setIfNoTests - */ - private NoTestsAction ifNoTests = NoTestsAction.IGNORE; - - /** - * @see #setStatsPropertyPrefix - */ - private String statsPropertyPrefix; - - /** - * - */ - public JUnit4() { - resources = new Resources(); - } - - /** - * What should be done on unexpected JVM output? JVM may write directly to the - * original descriptors, bypassing redirections of System.out and System.err. Typically, - * these messages will be important and should fail the build (permgen space exceeded, - * compiler errors, crash dumps). However, certain legitimate logs (gc activity, class loading - * logs) are also printed to these streams so sometimes the output can be ignored. - * - *

Allowed values (any comma-delimited combination of): {@link JvmOutputAction} - * constants. - */ - public void setJvmOutputAction(String jvmOutputActions) { - EnumSet actions = EnumSet.noneOf(JvmOutputAction.class); - for (String s : jvmOutputActions.split("[\\,\\ ]+")) { - s = s.trim().toUpperCase(Locale.ROOT); - actions.add(JvmOutputAction.valueOf(s)); - } - this.jvmOutputAction = actions; - } - - /** - * If set to true, any sysout and syserr calls will be written to original - * output and error streams (and in effect will appear as "jvm output". By default - * sysout and syserrs are captured and proxied to the event stream to be synchronized - * with other test events but occasionally one may want to synchronize them with direct - * JVM output (to synchronize with compiler output or GC output for example). - */ - public void setSysouts(boolean sysouts) { - this.sysouts = sysouts; - } - - /** - * Enables a debug stream from each forked JVM. This will create an additional file - * next to each events file. For debugging the framework only, not a general-purpose setting. - */ - public void setDebugStream(boolean debugStream) { - this.debugStream = debugStream; - } - - /** - * Allow or disallow duplicate suite names in resource collections. By default this option - * is true because certain ANT-compatible report types (like XML reports) - * will have a problem with duplicate suite names (will overwrite files). - */ - public void setUniqueSuiteNames(boolean uniqueSuiteNames) { - this.uniqueSuiteNames = uniqueSuiteNames; - } - - /** - * @see #setUniqueSuiteNames(boolean) - */ - public boolean isUniqueSuiteNames() { - return uniqueSuiteNames; - } - - /** - * Specifies the ratio of suites moved to dynamic assignment list. A dynamic - * assignment list dispatches suites to the first idle slave JVM. Theoretically - * this is an optimal strategy, but it is usually better to have some static assignments - * to avoid communication costs. - * - *

A ratio of 0 means only static assignments are used. A ratio of 1 means - * only dynamic assignments are used. - * - *

The list of dynamic assignments is sorted by decreasing cost (always) and - * is inherently prone to race conditions in distributing suites. Should there - * be an error based on suite-dependency it will not be directly repeatable. In such - * case use the per-slave-jvm list of suites file dumped to disk for each slave JVM. - * (see {@link #setLeaveTemporary(boolean)}). - */ - public void setDynamicAssignmentRatio(float ratio) { - if (ratio < 0 || ratio > 1) { - throw new IllegalArgumentException("Dynamic assignment ratio must be " + - "between 0 (only static assignments) to 1 (fully dynamic assignments)."); - } - this.dynamicAssignmentRatio = ratio; - } - - /** - * The number of parallel slaves. Can be set to a constant "max" for the - * number of cores returned from {@link Runtime#availableProcessors()} or - * "auto" for sensible defaults depending on the number of cores. - * The default is a single subprocess. - * - *

Note that this setting forks physical JVM processes so it multiplies the - * requirements for heap memory, IO, etc. - */ - public void setParallelism(String parallelism) { - this.parallelism = parallelism; - } - - /** - * Property to set to "true" if there is a failure in a test. - */ - public void setFailureProperty(String failureProperty) { - this.failureProperty = failureProperty; - } - - /** - * Do not propagate the old environment when new environment variables are specified. - */ - public void setNewEnvironment(boolean v) { - this.newEnvironment = v; - } - - /** - * Initial random seed used for shuffling test suites and other sources - * of pseudo-randomness. If not set, any random value is set. - * - *

The seed's format is compatible with {@link RandomizedRunner} so that - * seed can be fixed for suites and methods alike. - */ - public void setSeed(String randomSeed) { - if (!Strings.isNullOrEmpty(getProject().getUserProperty(SYSPROP_RANDOM_SEED()))) { - String userProperty = getProject().getUserProperty(SYSPROP_RANDOM_SEED()); - if (!userProperty.equals(randomSeed)) { - log("Ignoring seed attribute because it is overridden by user properties.", Project.MSG_WARN); - } - } else if (!Strings.isNullOrEmpty(randomSeed)) { - this.random = randomSeed; - } - } - - /** - * Initializes custom prefix for all junit4 properties. This must be consistent - * across all junit4 invocations if done from the same classpath. Use only when REALLY needed. - */ - public void setPrefix(String prefix) { - if (!Strings.isNullOrEmpty(getProject().getUserProperty(SYSPROP_PREFIX()))) { - log("Ignoring prefix attribute because it is overridden by user properties.", Project.MSG_WARN); - } else { - SysGlobals.initializeWith(prefix); - } - } - - /** - * @see #setSeed(String) - */ - public String getSeed() { - return random; - } - - /** - * Predictably shuffle tests order after balancing. This will help in spreading - * lighter and heavier tests over a single slave's execution timeline while - * still keeping the same tests order depending on the seed. - */ - public void setShuffleOnSlave(boolean shuffle) { - this.shuffleOnSlave = shuffle; - } - - /* - * - */ - @Override - public void setProject(Project project) { - super.setProject(project); - - this.resources.setProject(project); - this.classpath = new org.apache.tools.ant.types.Path(getProject()); - this.bootclasspath = new org.apache.tools.ant.types.Path(getProject()); - } - - /** - * Prints the summary of all executed, ignored etc. tests at the end. - */ - public void setPrintSummary(boolean printSummary) { - this.printSummary = printSummary; - } - - /** - * Stop the build process if there were failures or errors during test execution. - */ - public void setHaltOnFailure(boolean haltOnFailure) { - this.haltOnFailure = haltOnFailure; - } - - /** - * Set the maximum memory to be used by all forked JVMs. - * - * @param max - * the value as defined by -mx or -Xmx in the java - * command line options. - */ - public void setMaxmemory(String max) { - if (!Strings.isNullOrEmpty(max)) { - getCommandline().setMaxmemory(max); - } - } - - /** - * Set to true to leave temporary files for diagnostics. - */ - public void setLeaveTemporary(boolean leaveTemporary) { - this.leaveTemporary = leaveTemporary; - } - - /** - * Add an additional argument to any forked JVM. - */ - public Commandline.Argument createJvmarg() { - return getCommandline().createVmArgument(); - } - - /** - * The directory to invoke forked VMs in. - */ - public void setDir(File dir) { - this.dir = dir.toPath(); - } - - /** - * The directory to store temporary files in. - */ - public void setTempDir(File tempDir) { - this.tempDir = tempDir.toPath(); - } - - /** - * What to do when no tests were executed (all tests were ignored)? - * @see NoTestsAction - */ - public void setIfNoTests(String value) { - try { - ifNoTests = NoTestsAction.valueOf(value.toUpperCase(Locale.ROOT)); - } catch (IllegalArgumentException e) { - throw new BuildException("Invalid value (one of " - + Arrays.toString(NoTestsAction.values()) + " accepted): " + value); - } - } - - /** - * A {@link org.apache.tools.ant.types.Environment.Variable} with an additional - * attribute specifying whether or not empty values should be propagated or ignored. - */ - public static class ExtendedVariable extends Environment.Variable { - private boolean ignoreEmptyValue = false; - - public void setIgnoreEmpty(boolean ignoreEmptyValue) { - this.ignoreEmptyValue = ignoreEmptyValue; - } - - public boolean shouldIgnore() { - return ignoreEmptyValue && Strings.isNullOrEmpty(getValue()); - } - - @Override - public String toString() { - return getContent() + " (ignoreEmpty=" + ignoreEmptyValue + ")"; - } - } - - /** - * Adds a system property to any forked JVM. - */ - public void addConfiguredSysproperty(ExtendedVariable sysp) { - if (!sysp.shouldIgnore()) { - getCommandline().addSysproperty(sysp); - } - } - - /** - * A {@link PropertySet} with an additional - * attribute specifying whether or not empty values should be propagated or ignored. - */ - public static class ExtendedPropertySet extends PropertySet { - private boolean ignoreEmptyValue = false; - - public void setIgnoreEmpty(boolean ignoreEmptyValue) { - this.ignoreEmptyValue = ignoreEmptyValue; - } - - @Override - public Properties getProperties() { - Properties properties = super.getProperties(); - Properties clone = new Properties(); - for (String s : properties.stringPropertyNames()) { - String value = (String) properties.get(s); - if (ignoreEmptyValue && Strings.isNullOrEmpty(value)) { - continue; - } else { - clone.setProperty(s, value); - } - } - return clone; - } - } - - /** - * Adds a set of properties that will be used as system properties that tests - * can access. - * - * This might be useful to transfer Ant properties to the testcases. - */ - public void addConfiguredSyspropertyset(ExtendedPropertySet sysp) { - getCommandline().addSyspropertyset(sysp); - } - - /** - * The command used to invoke the Java Virtual Machine, default is 'java'. The - * command is resolved by java.lang.Runtime.exec(). - */ - public void setJvm(String jvm) { - if (!Strings.isNullOrEmpty(jvm)) { - getCommandline().setVm(jvm); - } - } - - /** - * If set to true each slave JVM gets a separate working directory - * under whatever is set in {@link #setDir(File)}. The directory naming for each slave - * follows: "Snum", where num is slave's number. Directories are created - * automatically and removed unless {@link #setLeaveTemporary(boolean)} is set to - * true. - */ - public void setIsolateWorkingDirectories(boolean isolateWorkingDirectories) { - this.isolateWorkingDirectories = isolateWorkingDirectories; - } - - /** - * Determines the behavior on detecting non-empty existing current working - * directory for a forked JVM, before the tests commence. This action is performed - * only if work directory isolation is set to true (see {@link #setIsolateWorkingDirectories(boolean)}). - */ - public void setOnNonEmptyWorkDirectory(String value) { - try { - this.nonEmptyWorkDirAction = NonEmptyWorkDirectoryAction.valueOf(value.toUpperCase(Locale.ROOT)); - } catch (IllegalArgumentException e) { - throw new IllegalArgumentException("OnNonEmptyWorkDirectory accepts any of: " - + Arrays.toString(NonEmptyWorkDirectoryAction.values()) + ", value is not valid: " + value); - } - } - - /** - * Adds an environment variable; used when forking. - */ - public void addEnv(ExtendedVariable var) { - env.addVariable(var); - } - - /** - * Adds a set of tests based on pattern matching. - */ - public void addFileSet(FileSet fs) { - add(fs); - if (fs.getProject() == null) { - fs.setProject(getProject()); - } - } - - /** - * Adds a set of tests based on pattern matching. - */ - public void add(ResourceCollection rc) { - resources.add(rc); - } - - /** - * Creates a new list of listeners. - */ - public ListenersList createListeners() { - return new ListenersList(listeners); - } - - /** - * Creates a new list of user-defined run listeners. - */ - public RunListenerList createRunListeners() { - return new RunListenerList(runListeners); - } - - /** - * Add assertions to tests execution. - */ - public void addAssertions(Assertions asserts) { - if (getCommandline().getAssertions() != null) { - throw new BuildException("Only one assertion declaration is allowed"); - } - getCommandline().setAssertions(asserts); - } - - /** - * Creates a new list of balancers. - */ - public BalancersList createBalancers() { - return new BalancersList(balancers); - } - - /** - * Adds path to classpath used for tests. - * - * @return reference to the classpath in the embedded java command line - */ - public org.apache.tools.ant.types.Path createClasspath() { - return classpath.createPath(); - } - - /** - * Adds a path to the bootclasspath. - * - * @return reference to the bootclasspath in the embedded java command line - */ - public org.apache.tools.ant.types.Path createBootclasspath() { - return bootclasspath.createPath(); - } - - /* ANT-junit compat only. */ - public void setFork(boolean fork) { - warnUnsupported("fork"); - } - - public void setForkmode(String forkMode) { - warnUnsupported("forkmode"); - } - - public void setHaltOnError(boolean haltOnError) { - warnUnsupported("haltonerror"); - } - - public void setFiltertrace(boolean filterTrace) { - warnUnsupported("filtertrace"); - log("Hint: report listeners have stack filtering options.", Project.MSG_WARN); - } - - public void setTimeout(String v) { - warnUnsupported("timeout"); - } - - public void setIncludeantruntime(String v) { - warnUnsupported("includeantruntime"); - } - - public void setShowoutput(String v) { - warnUnsupported("showoutput"); - } - - public void setOutputtoformatters(String v) { - warnUnsupported("outputtoformatters"); - } - - public void setReloading(String v) { - warnUnsupported("reloading"); - } - - public void setClonevm(String v) { - warnUnsupported("clonevm"); - } - - public void setErrorproperty(String v) { - warnUnsupported("errorproperty"); - } - - public void setLogfailedtests(String v) { - warnUnsupported("logfailedtests"); - } - - public void setEnableTestListenerEvents(String v) { - warnUnsupported("enableTestListenerEvents"); - } - - public Object createFormatter() { - throw new BuildException(" elements are not supported by . " + - "Refer to the documentation about listeners and reports."); - } - - public Object createTest() { - throw new BuildException(" elements are not supported by . " + - "Use regular ANT resource collections to point at individual tests or their groups."); - } - - public Object createBatchtest() { - throw new BuildException(" elements are not supported by . " + - "Use regular ANT resource collections to point at individual tests or their groups."); - } - - private void warnUnsupported(String attName) { - log("The '" + attName + "' attribute is not supported by .", Project.MSG_WARN); - } - - /** - * Sets the heartbeat used to detect inactive/ hung forked tests (JVMs) to the given - * number of seconds. The heartbeat detects - * no-event intervals and will report them to listeners. Notably, text report report will - * emit heartbeat information (to a file or console). - * - *

Setting the heartbeat to zero means no detection. - */ - public void setHeartbeat(long heartbeat) { - this.heartbeat = heartbeat; - } - - /** - * Sets the property prefix to which test statistics are saved. - */ - public void setStatsPropertyPrefix(String statsPropertyPrefix) { - this.statsPropertyPrefix = statsPropertyPrefix; - } - - @Override - public void execute() throws BuildException { - validateJUnit4(); - validateArguments(); - - // Initialize random if not already provided. - if (random == null) { - this.random = MoreObjects.firstNonNull( - Strings.emptyToNull(getProject().getProperty(SYSPROP_RANDOM_SEED())), - SeedUtils.formatSeed(new Random().nextLong())); - } - masterSeed(); - - // Say hello and continue. - log(" says " + - RandomPicks.randomFrom(new Random(masterSeed()), WELCOME_MESSAGES) + - " Master seed: " + getSeed(), Project.MSG_INFO); - - // Pass the random seed property. - createJvmarg().setValue("-D" + SYSPROP_PREFIX() + "=" + CURRENT_PREFIX()); - createJvmarg().setValue("-D" + SYSPROP_RANDOM_SEED() + "=" + random); - - // Resolve paths first. - this.classpath = resolveFiles(classpath); - this.bootclasspath = resolveFiles(bootclasspath); - getCommandline().createClasspath(getProject()).add(classpath); - getCommandline().createBootclasspath(getProject()).add(bootclasspath); - - // Setup a class loader over test classes. This will be used for loading annotations - // and referenced classes. This is kind of ugly, but mirroring annotation content will - // be even worse and Description carries these. - - // TODO: [GH-211] we should NOT be using any actual classes, annotations, etc. - // from client code. Everything should be a mirror. - testsClassLoader = new AntClassLoader( - this.getClass().getClassLoader(), - getProject(), - getCommandline().getClasspath(), - true); - - // Pass method filter if any. - String testMethodFilter = Strings.emptyToNull(getProject().getProperty(SYSPROP_TESTMETHOD())); - if (testMethodFilter != null) { - Environment.Variable v = new Environment.Variable(); - v.setKey(SYSPROP_TESTMETHOD()); - v.setValue(testMethodFilter); - getCommandline().addSysproperty(v); - } - - // Process test classes and resources. - long start = System.currentTimeMillis(); - final TestsCollection testCollection = processTestResources(); - - final EventBus aggregatedBus = new EventBus("aggregated"); - final TestsSummaryEventListener summaryListener = new TestsSummaryEventListener(); - aggregatedBus.register(summaryListener); - - for (Object o : listeners) { - if (o instanceof ProjectComponent) { - ((ProjectComponent) o).setProject(getProject()); - } - if (o instanceof AggregatedEventListener) { - ((AggregatedEventListener) o).setOuter(this); - } - aggregatedBus.register(o); - } - - if (testCollection.testClasses.isEmpty()) { - aggregatedBus.post(new AggregatedQuitEvent()); - } else { - start = System.currentTimeMillis(); - - // Check if we allow duplicate suite names. Some reports (ANT compatible XML - // reports) will have a problem with duplicate suite names, for example. - if (uniqueSuiteNames) { - testCollection.onlyUniqueSuiteNames(); - } - - final int jvmCount = determineForkedJvmCount(testCollection); - final List slaveInfos = new ArrayList<>(); - for (int jvmid = 0; jvmid < jvmCount; jvmid++) { - final ForkedJvmInfo slaveInfo = new ForkedJvmInfo(jvmid, jvmCount); - slaveInfos.add(slaveInfo); - } - - - if (jvmCount > 1 && uniqueSuiteNames && testCollection.hasReplicatedSuites()) { - throw new BuildException(String.format(Locale.ROOT, - "There are test suites that request JVM replication and the number of forked JVMs %d is larger than 1. Run on a single JVM.", - jvmCount)); - } - - // Prepare a pool of suites dynamically dispatched to slaves as they become idle. - final Deque stealingQueue = - new ArrayDeque(loadBalanceSuites(slaveInfos, testCollection, balancers)); - aggregatedBus.register(new Object() { - @Subscribe - public void onSlaveIdle(SlaveIdle slave) { - if (stealingQueue.isEmpty()) { - slave.finished(); - } else { - String suiteName = stealingQueue.pop(); - slave.newSuite(suiteName); - } - } - }); - - // Check for filtering expressions. - Vector vv = getCommandline().getSystemProperties().getVariablesVector(); - for (Variable v : vv) { - if (SysGlobals.SYSPROP_TESTFILTER().equals(v.getKey())) { - try { - Node root = new FilterExpressionParser().parse(v.getValue()); - log("Parsed test filtering expression: " + root.toExpression(), Project.MSG_INFO); - } catch (Exception e) { - log("Could not parse filtering expression: " + v.getValue(), e, Project.MSG_WARN); - } - } - } - - // Create callables for the executor. - final List> slaves = new ArrayList<>(); - for (int slave = 0; slave < jvmCount; slave++) { - final ForkedJvmInfo slaveInfo = slaveInfos.get(slave); - slaves.add(new Callable() { - @Override - public Void call() throws Exception { - executeSlave(slaveInfo, aggregatedBus); - return null; - } - }); - } - - ExecutorService executor = Executors.newCachedThreadPool(); - aggregatedBus.post(new AggregatedStartEvent(slaves.size(), - // TODO: this doesn't account for replicated suites. - testCollection.testClasses.size())); - - try { - List> all = executor.invokeAll(slaves); - executor.shutdown(); - - for (int i = 0; i < slaves.size(); i++) { - Future f = all.get(i); - try { - f.get(); - } catch (ExecutionException e) { - slaveInfos.get(i).executionError = e.getCause(); - } - } - } catch (InterruptedException e) { - log("Master interrupted? Weird.", Project.MSG_ERR); - } - aggregatedBus.post(new AggregatedQuitEvent()); - - for (ForkedJvmInfo si : slaveInfos) { - if (si.start > 0 && si.end > 0) { - log(String.format(Locale.ROOT, "JVM J%d: %8.2f .. %8.2f = %8.2fs", - si.id, - (si.start - start) / 1000.0f, - (si.end - start) / 1000.0f, - (si.getExecutionTime() / 1000.0f)), - Project.MSG_INFO); - } - } - log("Execution time total: " + Duration.toHumanDuration( - (System.currentTimeMillis() - start))); - - ForkedJvmInfo slaveInError = null; - for (ForkedJvmInfo i : slaveInfos) { - if (i.executionError != null) { - log("ERROR: JVM J" + i.id + " ended with an exception, command line: " + i.getCommandLine()); - log("ERROR: JVM J" + i.id + " ended with an exception: " + - Throwables.getStackTraceAsString(i.executionError), Project.MSG_ERR); - if (slaveInError == null) { - slaveInError = i; - } - } - } - - if (slaveInError != null) { - throw new BuildException("At least one slave process threw an exception, first: " - + slaveInError.executionError.getMessage(), slaveInError.executionError); - } - } - - final TestsSummary testsSummary = summaryListener.getResult(); - if (printSummary) { - log("Tests summary: " + testsSummary, Project.MSG_INFO); - } - - if (!testsSummary.isSuccessful()) { - if (!Strings.isNullOrEmpty(failureProperty)) { - getProject().setNewProperty(failureProperty, "true"); - } - if (haltOnFailure) { - throw new BuildException(String.format(Locale.ROOT, - "There were test failures: %s [seed: %s]", - testsSummary, - getSeed())); - } - } - - if (!leaveTemporary) { - for (Path f : temporaryFiles) { - try { - if (f != null) { - try { - Files.delete(f); - } catch (DirectoryNotEmptyException e) { - throw new DirectoryNotEmptyException("Remaining files: " + listFiles(f)); - } - } - } catch (IOException e) { - log("Could not remove temporary path: " + f.toAbsolutePath() + " (" + e + ")", e, Project.MSG_WARN); - } - } - } - - if (statsPropertyPrefix != null) { - Project p = getProject(); - p.setNewProperty(statsPropertyPrefix + ".tests", Integer.toString(testsSummary.tests)); - p.setNewProperty(statsPropertyPrefix + ".errors", Integer.toString(testsSummary.errors)); - p.setNewProperty(statsPropertyPrefix + ".failures", Integer.toString(testsSummary.failures)); - p.setNewProperty(statsPropertyPrefix + ".ignores", Integer.toString(testsSummary.ignores)); - p.setNewProperty(statsPropertyPrefix + ".suites", Integer.toString(testsSummary.suites)); - p.setNewProperty(statsPropertyPrefix + ".assumptions", Integer.toString(testsSummary.assumptions)); - p.setNewProperty(statsPropertyPrefix + ".suiteErrors", Integer.toString(testsSummary.suiteErrors)); - - p.setNewProperty(statsPropertyPrefix + ".nonIgnored", Integer.toString(testsSummary.getNonIgnoredTestsCount())); - p.setNewProperty(statsPropertyPrefix + ".successful", Boolean.toString(testsSummary.isSuccessful())); - } - - int executedTests = testsSummary.getNonIgnoredTestsCount(); - if (executedTests == 0) { - String message = "There were no executed tests: " + testsSummary; - switch (ifNoTests) { - case FAIL: - throw new BuildException(message); - case WARN: - log(message, Project.MSG_WARN); - break; - case IGNORE: - break; - default: - throw new RuntimeException("Unreachable case clause: " + ifNoTests); - } - } - } - - private static List listFiles(Path f) throws IOException { - List remainingFiles = new ArrayList(); - try (DirectoryStream s = Files.newDirectoryStream(f)) { - for (Path p : s) { - remainingFiles.add(p.toString()); - } - Collections.sort(remainingFiles); - } - return remainingFiles; - } - - /** - * Validate arguments. - */ - private void validateArguments() throws BuildException { - Path tempDir = getTempDir(); - - if (tempDir == null) { - throw new BuildException("Temporary directory cannot be null."); - } - - if (Files.exists(tempDir)) { - if (!Files.isDirectory(tempDir)) { - throw new BuildException("Temporary directory is not a folder: " + tempDir.toAbsolutePath()); - } - } else { - try { - Files.createDirectories(tempDir); - } catch (IOException e) { - throw new BuildException("Failed to create temporary folder: " + tempDir, e); - } - } - } - - /** - * Validate JUnit4 presence in a concrete version. - */ - private void validateJUnit4() throws BuildException { - try { - Class clazz = Class.forName("org.junit.runner.Description"); - if (!Serializable.class.isAssignableFrom(clazz)) { - throw new BuildException("At least JUnit version 4.10 is required on junit4's taskdef classpath."); - } - } catch (ClassNotFoundException e) { - throw new BuildException("JUnit JAR must be added to junit4 taskdef's classpath."); - } - } - - /** - * Perform load balancing of the set of suites. Sets {@link ForkedJvmInfo#testSuites} - * to suites preassigned to a given slave and returns a pool of suites - * that should be load-balanced dynamically based on job stealing. - */ - private List loadBalanceSuites(List jvmInfo, - TestsCollection testsCollection, List balancers) { - - // Order test suites identically for balancers. - // and split into replicated and non-replicated suites. - Map> partitioned = sortAndSplitReplicated(testsCollection.testClasses); - - Collection replicated = partitioned.get(true); - Collection suites = partitioned.get(false); - - final List balancersWithFallback = new ArrayList<>(balancers); - balancersWithFallback.add(new RoundRobinBalancer()); - - // Go through all the balancers, the first one to assign a suite wins. - final List remaining = new ArrayList<>(suites); - Collections.sort(remaining); - - final Map> perJvmAssignments = new HashMap<>(); - for (ForkedJvmInfo si : jvmInfo) { - perJvmAssignments.put(si.id, new ArrayList()); - } - final int jvmCount = jvmInfo.size(); - for (SuiteBalancer balancer : balancersWithFallback) { - balancer.setOwner(this); - final List assignments = - balancer.assign( - Collections.unmodifiableCollection(remaining), jvmCount, masterSeed()); - - for (Assignment e : assignments) { - if (e == null) { - throw new RuntimeException("Balancer must return non-null assignments."); - } - if (!remaining.remove(e.suiteName)) { - throw new RuntimeException("Balancer must return suite name as a key: " + e.suiteName); - } - - log(String.format(Locale.ROOT, - "Assignment hint: J%-2d (cost %5d) %s (by %s)", - e.slaveId, - e.estimatedCost, - e.suiteName, - balancer.getClass().getSimpleName()), Project.MSG_VERBOSE); - - perJvmAssignments.get(e.slaveId).add(e); - } - } - - if (remaining.size() != 0) { - throw new RuntimeException("Not all suites assigned?: " + remaining); - } - - if (shuffleOnSlave) { - // Shuffle suites on slaves so that the result is always the same wrt master seed - // (sort first, then shuffle with a constant seed). - for (List assignments : perJvmAssignments.values()) { - Collections.sort(assignments); - Collections.shuffle(assignments, new Random(this.masterSeed())); - } - } - - // Take a fraction of suites scheduled as last on each slave and move them to a common - // job-stealing queue. - List stealingQueueWithHints = new ArrayList<>(); - for (ForkedJvmInfo si : jvmInfo) { - final List assignments = perJvmAssignments.get(si.id); - int moveToCommon = (int) (assignments.size() * dynamicAssignmentRatio); - - if (moveToCommon > 0) { - final List movedToCommon = - assignments.subList(assignments.size() - moveToCommon, assignments.size()); - for (Assignment a : movedToCommon) { - stealingQueueWithHints.add(new SuiteHint(a.suiteName, a.estimatedCost)); - } - movedToCommon.clear(); - } - - final ArrayList slaveSuites = (si.testSuites = new ArrayList<>()); - for (Assignment a : assignments) { - slaveSuites.add(a.suiteName); - } - } - - // Sort stealing queue according to descending cost. - Collections.sort(stealingQueueWithHints, SuiteHint.DESCENDING_BY_WEIGHT); - - // Append all replicated suites to each forked JVM, AFTER we process the stealing queue - // to enforce all replicated suites run on each bound JVM. - if (!replicated.isEmpty()) { - for (ForkedJvmInfo si : jvmInfo) { - for (String suite : replicated) { - si.testSuites.add(suite); - } - if (shuffleOnSlave) { - // Shuffle suites on slaves so that the result is always the same wrt master seed - // (sort first, then shuffle with a constant seed). - Collections.shuffle(si.testSuites, new Random(this.masterSeed())); - } - } - } - - // Dump scheduling information. - for (ForkedJvmInfo si : jvmInfo) { - log("Forked JVM J" + si.id + " assignments (after shuffle):", Project.MSG_VERBOSE); - for (String suiteName : si.testSuites) { - log(" " + suiteName, Project.MSG_VERBOSE); - } - } - - log("Stealing queue:", Project.MSG_VERBOSE); - for (SuiteHint suiteHint : stealingQueueWithHints) { - log(" " + suiteHint.suiteName + " " + suiteHint.cost, Project.MSG_VERBOSE); - } - - List stealingQueue = new ArrayList<>(stealingQueueWithHints.size()); - for (SuiteHint suiteHint : stealingQueueWithHints) { - stealingQueue.add(suiteHint.suiteName); - } - return stealingQueue; - } - - private Map> sortAndSplitReplicated(List testClasses) { - ArrayList sorted = new ArrayList<>(testClasses); - Collections.sort(sorted, new Comparator() { - @Override - public int compare(TestClass t1, TestClass t2) { - String s1 = t1.className + ";" + t1.replicate; - String s2 = t2.className + ";" + t2.replicate; - return s1.compareTo(s2); - } - }); - - List replicated = new ArrayList<>(); - List nonreplicated = new ArrayList<>(); - for (TestClass tc : sorted) { - if (tc.replicate) { - replicated.add(tc.className); - } else { - nonreplicated.add(tc.className); - } - } - - Map> result = new HashMap<>(); - result.put(Boolean.TRUE, replicated); - result.put(Boolean.FALSE, nonreplicated); - return result; - } - - /** - * Return the master seed of {@link #getSeed()}. - */ - private long masterSeed() { - long[] seeds = SeedUtils.parseSeedChain(getSeed()); - if (seeds.length < 1) { - throw new BuildException("Random seed is required."); - } - return seeds[0]; - } - - /** - * Resolve all files from a given path and simplify its definition. - */ - private org.apache.tools.ant.types.Path resolveFiles(org.apache.tools.ant.types.Path path) { - org.apache.tools.ant.types.Path cloned = new org.apache.tools.ant.types.Path(getProject()); - for (String location : path.list()) { - cloned.createPathElement().setLocation(new File(location)); - } - return cloned; - } - - /** - * Determine how many forked JVMs to use. - */ - private int determineForkedJvmCount(TestsCollection testCollection) { - int cores = Runtime.getRuntime().availableProcessors(); - int jvmCount; - if (this.parallelism.equals(PARALLELISM_AUTO)) { - if (cores >= 8) { - // Maximum parallel jvms is 4, conserve some memory and memory bandwidth. - jvmCount = 4; - } else if (cores >= 4) { - // Make some space for the aggregator. - jvmCount = 3; - } else if (cores == 3) { - // Yes, three-core chips are a thing. - jvmCount = 2; - } else { - // even for dual cores it usually makes no sense to fork more than one - // JVM. - jvmCount = 1; - } - } else if (this.parallelism.equals(PARALLELISM_MAX)) { - jvmCount = Runtime.getRuntime().availableProcessors(); - } else { - try { - jvmCount = Math.max(1, Integer.parseInt(parallelism)); - } catch (NumberFormatException e) { - throw new BuildException("parallelism must be 'auto', 'max' or a valid integer: " - + parallelism); - } - } - - if (!testCollection.hasReplicatedSuites()) { - jvmCount = Math.min(testCollection.testClasses.size(), jvmCount); - } - return jvmCount; - } - - /** - * Attach listeners and execute a slave process. - */ - private void executeSlave(final ForkedJvmInfo slave, final EventBus aggregatedBus) - throws Exception - { - final String uniqueSeed = new SimpleDateFormat("yyyyMMdd_HHmmss_SSS", Locale.ROOT).format(new Date()); - - final Path classNamesFile = tempFile(uniqueSeed, "junit4-J" + slave.id, ".suites", getTempDir()); - temporaryFiles.add(classNamesFile); - - final Path classNamesDynamic = tempFile(uniqueSeed, "junit4-J" + slave.id, ".dynamic-suites", getTempDir()); - final Path streamsBufferFile = tempFile(uniqueSeed, "junit4-J" + slave.id, ".spill", getTempDir()); - - // Dump all test class names to a temporary file. - String testClassPerLine = Joiner.on("\n").join(slave.testSuites); - log("Test class names:\n" + testClassPerLine, Project.MSG_VERBOSE); - Files.write(classNamesFile, testClassPerLine.getBytes(StandardCharsets.UTF_8)); - - // Prepare command line for java execution. - CommandlineJava commandline; - commandline = (CommandlineJava) getCommandline().clone(); - commandline.createClasspath(getProject()).add(addSlaveClasspath()); - commandline.setClassname(SlaveMainSafe.class.getName()); - if (slave.slaves == 1) { - commandline.createArgument().setValue(SlaveMain.OPTION_FREQUENT_FLUSH); - } - - // Set up full output files. - Path sysoutFile = tempFile(uniqueSeed, - "junit4-J" + slave.id, ".sysout", getTempDir()); - Path syserrFile = tempFile(uniqueSeed, - "junit4-J" + slave.id, ".syserr", getTempDir()); - - // Set up communication channel. - Path eventFile = tempFile(uniqueSeed, "junit4-J" + slave.id, ".events", getTempDir()); - temporaryFiles.add(eventFile); - commandline.createArgument().setValue(SlaveMain.OPTION_EVENTSFILE); - commandline.createArgument().setFile(eventFile.toFile()); - - if (sysouts) { - commandline.createArgument().setValue(SlaveMain.OPTION_SYSOUTS); - } - - if (debugStream) { - commandline.createArgument().setValue(SlaveMain.OPTION_DEBUGSTREAM); - } - - TailInputStream eventStream = new TailInputStream(eventFile); - - // Process user-defined RunListener classes. - if (!runListeners.isEmpty()) { - String classNames = runListeners.stream().map(x -> x.getClassName()).collect(Collectors.joining(",")); - - commandline.createArgument().setValue(SlaveMain.OPTION_RUN_LISTENERS); - commandline.createArgument().setValue(classNames); - } - - // Set up input suites file. - commandline.createArgument().setValue("@" + classNamesFile.toAbsolutePath().normalize()); - - // May or may not use dynamic load balancing, but if == 0 then we're for sure - // not using it. - if (dynamicAssignmentRatio > 0) { - commandline.createArgument().setValue(SlaveMain.OPTION_STDIN); - } - - final EventBus eventBus = new EventBus("slave-" + slave.id); - final DiagnosticsListener diagnosticsListener = new DiagnosticsListener(slave, this); - eventBus.register(diagnosticsListener); - eventBus.register(new AggregatingListener(aggregatedBus, slave)); - - final AtomicReference clientCharset = new AtomicReference(); - final AtomicBoolean clientWithLimitedCharset = new AtomicBoolean(); - final PrintWriter w = new PrintWriter(Files.newBufferedWriter(classNamesDynamic, StandardCharsets.UTF_8)); - eventBus.register(new Object() { - @Subscribe - public void onIdleSlave(final SlaveIdle idleSlave) { - aggregatedBus.post(new SlaveIdle() { - @Override - public void finished() { - idleSlave.finished(); - } - - @Override - public void newSuite(String suiteName) { - if (!clientCharset.get().newEncoder().canEncode(suiteName)) { - clientWithLimitedCharset.set(true); - log("Forked JVM J" + slave.id + " skipped suite (cannot encode suite name in charset " + - clientCharset.get() + "): " + suiteName, Project.MSG_WARN); - return; - } - - log("Forked JVM J" + slave.id + " stole suite: " + suiteName, Project.MSG_VERBOSE); - w.println(suiteName); - w.flush(); - idleSlave.newSuite(suiteName); - } - }); - } - - @Subscribe - public void onBootstrap(final BootstrapEvent e) { - Charset cs = Charset.forName(((BootstrapEvent) e).getDefaultCharsetName()); - clientCharset.set(cs); - - slave.start = System.currentTimeMillis(); - slave.setBootstrapEvent(e); - aggregatedBus.post(new ChildBootstrap(slave)); - } - - @Subscribe - public void receiveQuit(QuitEvent e) { - slave.end = System.currentTimeMillis(); - } - }); - - Closer closer = Closer.create(); - closer.register(eventStream); - closer.register(w); - try { - OutputStream sysout = closer.register(new BufferedOutputStream(Files.newOutputStream(sysoutFile))); - OutputStream syserr = closer.register(new BufferedOutputStream(Files.newOutputStream(syserrFile))); - RandomAccessFile streamsBuffer = closer.register(new RandomAccessFile(streamsBufferFile.toFile(), "rw")); - - Execute execute = forkProcess(slave, eventBus, commandline, eventStream, sysout, syserr, streamsBuffer); - log("Forked JVM J" + slave.id + " finished with exit code: " + execute.getExitValue(), Project.MSG_DEBUG); - - if (execute.isFailure()) { - final int exitStatus = execute.getExitValue(); - switch (exitStatus) { - case SlaveMain.ERR_NO_JUNIT: - throw new BuildException("Forked JVM's classpath must include a junit4 JAR."); - case SlaveMain.ERR_OLD_JUNIT: - throw new BuildException("Forked JVM's classpath must use JUnit 4.10 or newer."); - default: - Closeables.close(sysout, false); - Closeables.close(syserr, false); - - StringBuilder message = new StringBuilder(); - if (exitStatus == SlaveMain.ERR_OOM) { - message.append("Forked JVM ran out of memory."); - } else { - message.append("Forked process returned with error code: ").append(exitStatus).append("."); - } - - if (Files.size(sysoutFile) > 0 || Files.size(syserrFile) > 0) { - if (exitStatus != SlaveMain.ERR_OOM) { - message.append(" Very likely a JVM crash. "); - } - - if (jvmOutputAction.contains(JvmOutputAction.PIPE)) { - message.append(" Process output piped in logs above."); - } else if (!jvmOutputAction.contains(JvmOutputAction.IGNORE)) { - if (Files.size(sysoutFile) > 0) { - message.append(" See process stdout at: " + sysoutFile.toAbsolutePath()); - } - if (Files.size(syserrFile) > 0) { - message.append(" See process stderr at: " + syserrFile.toAbsolutePath()); - } - } - } - throw new BuildException(message.toString()); - } - } - } catch (Throwable t) { - throw closer.rethrow(t); - } finally { - try { - closer.close(); - } finally { - com.google.common.io.Files.asByteSource(classNamesDynamic.toFile()) - .copyTo(com.google.common.io.Files.asByteSink(classNamesFile.toFile(), FileWriteMode.APPEND)); - Files.delete(classNamesDynamic); - Files.delete(streamsBufferFile); - - // Check sysout/syserr lengths. - checkJvmOutput(aggregatedBus, sysoutFile, slave, "stdout"); - checkJvmOutput(aggregatedBus, syserrFile, slave, "stderr"); - } - } - - if (!diagnosticsListener.quitReceived()) { - throw new BuildException("Quit event not received from the forked process? This may indicate JVM crash or runner bugs."); - } - - if (clientWithLimitedCharset.get() && dynamicAssignmentRatio > 0) { - throw new BuildException("Forked JVM J" + slave.id + " was not be able to decode class names when using" + - " charset: " + clientCharset + ". Do not use " + - "dynamic suite balancing to work around this problem (-DdynamicAssignmentRatio=0)."); - } - } - - @SuppressForbidden("legitimate sysout.") - private void checkJvmOutput(EventBus aggregatedBus, Path file, ForkedJvmInfo forked, String fileName) throws IOException { - if (Files.size(file) > 0) { - String message = "JVM J" + forked.id + ": " + fileName + " was not empty, see: " + file; - if (jvmOutputAction.contains(JvmOutputAction.WARN)) { - log(message, Project.MSG_WARN); - } - if (jvmOutputAction.contains(JvmOutputAction.LISTENERS)) { - aggregatedBus.post(new JvmOutputEvent(forked, file.toFile())); - } - if (jvmOutputAction.contains(JvmOutputAction.PIPE)) { - log(">>> JVM J" + forked.id + ": " + fileName + " (verbatim) ----", Project.MSG_INFO); - try { - // If file > 10 mb, stream directly. Otherwise use the logger. - if (Files.size(file) < 10 * (1024 * 1024)) { - // Append to logger. - log(new String(Files.readAllBytes(file), forked.getCharset()), Project.MSG_INFO); - } else { - // Stream directly. - CharStreams.copy(Files.newBufferedReader(file, forked.getCharset()), System.out); - } - } catch (IOException e) { - log("Couldn't pipe file " + file + ": " + e.toString(), Project.MSG_INFO); - } - log("<<< JVM J" + forked.id + ": EOF ----", Project.MSG_INFO); - } - if (jvmOutputAction.contains(JvmOutputAction.IGNORE)) { - Files.delete(file); - } - if (jvmOutputAction.contains(JvmOutputAction.FAIL)) { - throw new BuildException(message); - } - return; - } - Files.delete(file); - } - - private Path tempFile(String uniqueSeed, String base, String suffix, Path tempDir) throws IOException { - return Files.createTempFile(tempDir, base + "-" + uniqueSeed, suffix); - } - - /** - * Try to provide an escaped, ready-to-use shell line to repeat a given command line. - */ - private String escapeAndJoin(String[] commandline) { - // TODO: we should try to escape special characters here, depending on the OS. - StringBuilder b = new StringBuilder(); - Pattern specials = Pattern.compile("[\\ ]"); - for (String arg : commandline) { - if (b.length() > 0) { - b.append(" "); - } - - if (specials.matcher(arg).find()) { - b.append('"').append(arg).append('"'); - } else { - b.append(arg); - } - } - return b.toString(); - } - - /** - * Execute a slave process. Pump events to the given event bus. - */ - @SuppressForbidden("legitimate sysstreams.") - private Execute forkProcess(ForkedJvmInfo slaveInfo, EventBus eventBus, - CommandlineJava commandline, - TailInputStream eventStream, OutputStream sysout, OutputStream syserr, RandomAccessFile streamsBuffer) { - try { - String tempDir = commandline.getSystemProperties().getVariablesVector().stream() - .filter(v -> v.getKey().equals("java.io.tmpdir")) - .map(v -> v.getValue()) - .findAny() - .orElse(null); - - final LocalSlaveStreamHandler streamHandler = - new LocalSlaveStreamHandler( - eventBus, testsClassLoader, System.err, eventStream, - sysout, syserr, heartbeat, streamsBuffer); - - // Add certain properties to allow identification of the forked JVM from within - // the subprocess. This can be used for policy files etc. - final Path cwd = getWorkingDirectory(slaveInfo, tempDir); - - Variable v = new Variable(); - v.setKey(CHILDVM_SYSPROP_CWD); - v.setFile(cwd.toAbsolutePath().normalize().toFile()); - commandline.addSysproperty(v); - - v = new Variable(); - v.setKey(SYSPROP_TEMPDIR); - v.setFile(getTempDir().toAbsolutePath().normalize().toFile()); - commandline.addSysproperty(v); - - v = new Variable(); - v.setKey(SysGlobals.CHILDVM_SYSPROP_JVM_ID); - v.setValue(Integer.toString(slaveInfo.id)); - commandline.addSysproperty(v); - - v = new Variable(); - v.setKey(SysGlobals.CHILDVM_SYSPROP_JVM_COUNT); - v.setValue(Integer.toString(slaveInfo.slaves)); - commandline.addSysproperty(v); - - // Emit command line before -stdin to avoid confusion. - slaveInfo.slaveCommandLine = escapeAndJoin(commandline.getCommandline()); - log("Forked child JVM at '" + cwd.toAbsolutePath().normalize() + - "', command (may need escape sequences for your shell):\n" + - slaveInfo.slaveCommandLine, Project.MSG_VERBOSE); - - final Execute execute = new Execute(); - execute.setCommandline(commandline.getCommandline()); - execute.setVMLauncher(true); - execute.setWorkingDirectory(cwd.toFile()); - execute.setStreamHandler(streamHandler); - execute.setNewenvironment(newEnvironment); - if (env.getVariables() != null) - execute.setEnvironment(env.getVariables()); - log("Starting JVM J" + slaveInfo.id, Project.MSG_DEBUG); - execute.execute(); - return execute; - } catch (IOException e) { - throw new BuildException("Could not start the child process. Run ant with -verbose to get" + - " the execution details.", e); - } - } - - private Path getWorkingDirectory(ForkedJvmInfo jvmInfo, String tempDir) throws IOException { - Path baseDir = (dir == null ? getProject().getBaseDir().toPath() : dir); - final Path forkedDir; - if (isolateWorkingDirectories) { - forkedDir = baseDir.resolve("J" + jvmInfo.id); - if (Files.isDirectory(forkedDir)) { - // If there are any files inside the forkedDir, issue a warning. - List existingFiles = listFiles(forkedDir); - if (!existingFiles.isEmpty()) { - switch (nonEmptyWorkDirAction) { - case IGNORE: - log("Cwd of a forked JVM already exists and is not empty: " - + existingFiles + " (ignoring).", Project.MSG_DEBUG); - break; - - case WIPE: - log("Cwd of a forked JVM already exists and is not empty, trying to wipe: " - + existingFiles, Project.MSG_DEBUG); - try { - Path tempPath = tempDir == null ? null : forkedDir.resolve(tempDir); - Files.walkFileTree(forkedDir, new SimpleFileVisitor() { - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException iterationError) throws IOException { - if (iterationError != null) { - throw iterationError; - } - - if (Files.isSameFile(dir, forkedDir) || - (tempPath != null && Files.isSameFile(dir, tempPath))) { - // Do not delete cwd or an explicit java.io.tmpdir folder underneath. - } else { - Files.delete(dir); - } - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Files.delete(file); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed(Path file, IOException e) throws IOException { - throw e; - } - }); - } catch (IOException e) { - throw new BuildException( - "An exception occurred while trying to wipe the working directory: " + forkedDir, e); - } - break; - case FAIL: - throw new BuildException("Cwd of a forked JVM already exists and is not empty " - + "and setOnNonEmptyWorkDirectory=" + nonEmptyWorkDirAction + ": " + existingFiles); - - default: - throw new RuntimeException("Unreachable."); - } - } - } else { - Files.createDirectories(forkedDir); - temporaryFiles.add(forkedDir); - } - } else { - forkedDir = baseDir; - } - return forkedDir; - } - - /** - * Resolve temporary folder. - */ - private Path getTempDir() { - if (this.tempDir == null) { - if (this.dir != null) { - this.tempDir = dir; - } else { - this.tempDir = getProject().getBaseDir().toPath(); - } - } - return tempDir; - } - - /** - * Process test resources. If there are any test resources that are _not_ class files, - * this will cause a build error. - */ - private TestsCollection processTestResources() { - TestsCollection collection = new TestsCollection(); - resources.setProject(getProject()); - - Iterator iter = (Iterator) resources.iterator(); - boolean javaSourceWarn = false; - while (iter.hasNext()) { - final Resource r = iter.next(); - if (!r.isExists()) - throw new BuildException("Test class resource does not exist?: " + r.getName()); - - try { - if (r.getName().endsWith(".java")) { - String pathname = r.getName(); - String className = pathname.substring(0, pathname.length() - ".java".length()); - className = className - .replace(File.separatorChar, '.') - .replace('/', '.') - .replace('\\', '.'); - collection.add(new TestClass(className)); - - if (!javaSourceWarn) { - log("Source (.java) files used for naming source suites. This is discouraged, " + - "use a resource collection pointing to .class files instead.", Project.MSG_INFO); - javaSourceWarn = true; - } - } else { - // Assume .class file. - InputStream is = r.getInputStream(); - if (!is.markSupported()) { - is = new BufferedInputStream(is); - } - - try { - is.mark(4); - if (is.read() != 0xca || - is.read() != 0xfe || - is.read() != 0xba || - is.read() != 0xbe) { - throw new BuildException("File does not start with a class magic 0xcafebabe: " - + r.getName() + ", " + r.getLocation()); - } - is.reset(); - - // Hardcoded intentionally. - final String REPLICATE_CLASS = "com.carrotsearch.randomizedtesting.annotations.ReplicateOnEachVm"; - final TestClass testClass = new TestClass(); - ClassReader reader = new ClassReader(is); - @SuppressWarnings("deprecation") - ClassVisitor annotationVisitor = new ClassVisitor(Opcodes.ASM8) { - @Override - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - String className = Type.getType(desc).getClassName(); - if (className.equals(REPLICATE_CLASS)) { - testClass.replicate = true; - } - return null; - } - }; - - reader.accept(annotationVisitor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); - testClass.className = reader.getClassName().replace('/', '.'); - log("Test class parsed: " + r.getName() + " as " + testClass.className, Project.MSG_DEBUG); - - collection.add(testClass); - } finally { - is.close(); - } - } - } catch (IOException e) { - throw new BuildException("Could not read or parse as Java class: " - + r.getName() + ", " + r.getLocation(), e); - } - } - - String testClassFilter = Strings.emptyToNull(getProject().getProperty(SYSPROP_TESTCLASS())); - if (testClassFilter != null) { - ClassGlobFilter filter = new ClassGlobFilter(testClassFilter); - for (Iterator i = collection.testClasses.iterator(); i.hasNext();) { - if (!filter.shouldRun(Description.createSuiteDescription(i.next().className))) { - i.remove(); - } - } - } - - return collection; - } - - /** - * Returns the slave VM command line. - */ - private CommandlineJava getCommandline() { - return slaveCommand; - } - - /** - * Adds a classpath source which contains the given resource. - * - * TODO: [GH-213] this is extremely ugly; separate the code required to run on the - * forked JVM into an isolated bundle and either create it on-demand (in temp. - * files location?) or locate it in classpath somehow (in a portable way). - */ - private org.apache.tools.ant.types.Path addSlaveClasspath() { - org.apache.tools.ant.types.Path path = new org.apache.tools.ant.types.Path(getProject()); - - String [] REQUIRED_SLAVE_CLASSES = { - SlaveMain.class.getName(), - Strings.class.getName(), - MethodGlobFilter.class.getName(), - TeeOutputStream.class.getName() - }; - - for (String clazz : Arrays.asList(REQUIRED_SLAVE_CLASSES)) { - String resource = clazz.replace(".", "/") + ".class"; - File f = LoaderUtils.getResourceSource(getClass().getClassLoader(), resource); - if (f != null) { - path.createPath().setLocation(f); - } else { - throw new BuildException("Could not locate classpath for resource: " + resource); - } - } - return path; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/ListenersList.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/ListenersList.java deleted file mode 100644 index fa3ff507..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/ListenersList.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import java.util.List; - -import com.carrotsearch.ant.tasks.junit4.listeners.AggregatedEventListener; - -public class ListenersList { - - private List listeners; - - public ListenersList(List listeners) { - this.listeners = listeners; - } - - /** - * Adds a listener to the listeners list. - * @param listener - */ - public void addConfigured(AggregatedEventListener listener) { - listeners.add(listener); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/LocalSlaveStreamHandler.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/LocalSlaveStreamHandler.java deleted file mode 100644 index 4dd74da3..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/LocalSlaveStreamHandler.java +++ /dev/null @@ -1,296 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintStream; -import java.io.RandomAccessFile; -import java.lang.Thread.UncaughtExceptionHandler; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; -import org.apache.tools.ant.taskdefs.StreamPumper; - -import com.carrotsearch.ant.tasks.junit4.events.BootstrapEvent; -import com.carrotsearch.ant.tasks.junit4.events.Deserializer; -import com.carrotsearch.ant.tasks.junit4.events.EventType; -import com.carrotsearch.ant.tasks.junit4.events.IEvent; -import com.carrotsearch.ant.tasks.junit4.events.IStreamEvent; -import com.carrotsearch.ant.tasks.junit4.events.LowLevelHeartBeatEvent; -import com.google.common.eventbus.EventBus; - -/** - * Establish event passing with a subprocess and pump events to the bus. - */ -public class LocalSlaveStreamHandler implements ExecuteStreamHandler { - private final EventBus eventBus; - private final ClassLoader refLoader; - - private InputStream stdout; - private InputStream stderr; - - /** raw input stream to the client. */ - private OutputStream stdin; - - /** character-wrapped input stream to the client. */ - private OutputStreamWriter stdinWriter; - - private final PrintStream warnStream; - private final TailInputStream eventStream; - - private volatile boolean stopping; - - private List pumpers = new ArrayList<>(); - - private final OutputStream sysout; - private final OutputStream syserr; - private final long heartbeat; - private final RandomAccessFile streamsBuffer; - private final OutputStream streamsBufferWrapper; - - public LocalSlaveStreamHandler( - EventBus eventBus, ClassLoader classLoader, PrintStream warnStream, TailInputStream eventStream, - OutputStream sysout, OutputStream syserr, long heartbeat, final RandomAccessFile streamsBuffer) { - this.eventBus = eventBus; - this.warnStream = warnStream; - this.refLoader = classLoader; - this.eventStream = eventStream; - this.sysout = sysout; - this.syserr = syserr; - this.heartbeat = heartbeat; - this.streamsBuffer = streamsBuffer; - this.streamsBufferWrapper = new OutputStream() { - @Override - public void write(int b) throws IOException { - streamsBuffer.write(b); - } - - @Override - public void write(byte[] b) throws IOException { - streamsBuffer.write(b, 0, b.length); - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - streamsBuffer.write(b, off, len); - } - }; - } - - @Override - public void setProcessErrorStream(InputStream is) throws IOException { - this.stderr = is; - } - - @Override - public void setProcessOutputStream(InputStream is) throws IOException { - this.stdout = is; - } - - @Override - public void setProcessInputStream(OutputStream os) throws IOException { - this.stdin = os; - } - - /** - * A timestamp of last received event (GH-106). - */ - private volatile Long lastActivity; - - /** - * Watchdog thread if heartbeat is to be measured. - */ - private Thread watchdog; - - /** - * Client charset extracted from {@link BootstrapEvent}. - */ - private Charset clientCharset; - - @Override - public void start() throws IOException { - lastActivity = System.currentTimeMillis(); - - pumpers.add(new Thread(new SimpleStreamPumper(stdout, sysout), "pumper-stdout")); - pumpers.add(new Thread(new SimpleStreamPumper(stderr, syserr), "pumper-stderr")); - pumpers.add(new Thread("pumper-events") { - public void run() { - pumpEvents(eventStream); - } - }); - - if (heartbeat > 0) { - pumpers.add(watchdog = new Thread("pumper-watchdog") { - public void run() { - final long heartbeatMillis = TimeUnit.SECONDS.toMillis(heartbeat); - final long HEARTBEAT = Math.max(500, heartbeatMillis / 5); - final long HEARTBEAT_EVENT_THRESHOLD = heartbeatMillis; - try { - long lastObservedUpdate = lastActivity; - long reportDeadline = lastObservedUpdate + HEARTBEAT_EVENT_THRESHOLD; - while (true) { - Thread.sleep(HEARTBEAT); - - Long last = lastActivity; - if (last == null) { - break; // terminated. - } - - if (last != lastObservedUpdate) { - lastObservedUpdate = last; - reportDeadline = last + HEARTBEAT_EVENT_THRESHOLD; - } else { - final long current = System.currentTimeMillis(); - if (current >= reportDeadline) { - eventBus.post(new LowLevelHeartBeatEvent(last, current)); - reportDeadline = System.currentTimeMillis() + HEARTBEAT_EVENT_THRESHOLD; - } - } - } - } catch (InterruptedException e ) { - // terminate on interrupt. - } - } - }); - } - - // Start all pumper threads. - UncaughtExceptionHandler handler = new UncaughtExceptionHandler() { - public void uncaughtException(Thread t, Throwable e) { - warnStream.println("Unhandled exception in thread: " + t); - e.printStackTrace(warnStream); - } - }; - - for (Thread t : pumpers) { - t.setUncaughtExceptionHandler(handler); - t.setDaemon(true); - t.start(); - } - } - - private static class OnDiskStreamEvent implements IEvent, IStreamEvent { - private final RandomAccessFile bufferFile; - private long start; - private long end; - private EventType type; - - public OnDiskStreamEvent(EventType type, RandomAccessFile streamsBuffer, long start, long end) { - this.bufferFile = streamsBuffer; - this.start = start; - this.end = end; - this.type = type; - } - - @Override - public EventType getType() { - return type; - } - - @Override - public void copyTo(OutputStream os) throws IOException { - final long restorePosition = bufferFile.getFilePointer(); - bufferFile.seek(start); - try { - long length = end - start; - final byte [] buffer = new byte [(int) Math.min(length, 1024 * 4)]; - while (length > 0) { - int bytes = bufferFile.read(buffer, 0, (int) Math.min(length, buffer.length)); - os.write(buffer, 0, bytes); - length -= bytes; - } - } finally { - bufferFile.seek(restorePosition); - } - } - } - - /** - * Pump events from event stream. - */ - void pumpEvents(InputStream eventStream) { - try { - Deserializer deserializer = new Deserializer(eventStream, refLoader); - - IEvent event = null; - while ((event = deserializer.deserialize()) != null) { - switch (event.getType()) { - case APPEND_STDERR: - case APPEND_STDOUT: - // Ignore these two on activity heartbeats. GH-117 - break; - default: - lastActivity = System.currentTimeMillis(); - break; - } - - try { - switch (event.getType()) { - case QUIT: - eventBus.post(event); - return; - - case IDLE: - eventBus.post(new SlaveIdle(stdinWriter)); - break; - - case BOOTSTRAP: - clientCharset = Charset.forName(((BootstrapEvent) event).getDefaultCharsetName()); - stdinWriter = new OutputStreamWriter(stdin, clientCharset); - eventBus.post(event); - break; - - case APPEND_STDERR: - case APPEND_STDOUT: - assert streamsBuffer.getFilePointer() == streamsBuffer.length(); - final long bufferStart = streamsBuffer.getFilePointer(); - IStreamEvent streamEvent = (IStreamEvent) event; - streamEvent.copyTo(streamsBufferWrapper); - final long bufferEnd = streamsBuffer.getFilePointer(); - - event = new OnDiskStreamEvent(event.getType(), streamsBuffer, bufferStart, bufferEnd); - eventBus.post(event); - break; - - default: - eventBus.post(event); - } - } catch (Throwable t) { - warnStream.println("Event bus dispatch error: " + t.toString()); - t.printStackTrace(warnStream); - } - } - lastActivity = null; - } catch (Throwable e) { - if (!stopping) { - warnStream.println("Event stream error: " + e.toString()); - e.printStackTrace(warnStream); - } - } - } - - @Override - public void stop() { - lastActivity = null; - stopping = true; - try { - // Terminate watchdog early. - if (watchdog != null) { - watchdog.interrupt(); - } - - // Wait for all stream pumpers. - eventStream.completeAtEnd(); - for (Thread t : pumpers) { - t.join(); - t.interrupt(); - } - } catch (InterruptedException e) { - // Don't wait. - } - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/NonEmptyWorkDirectoryAction.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/NonEmptyWorkDirectoryAction.java deleted file mode 100644 index 71e36ad4..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/NonEmptyWorkDirectoryAction.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -public enum NonEmptyWorkDirectoryAction { - /** Ignore any existing files in the work directory. */ - IGNORE, - - /** - * Wipe the content of the work directory clean if there are any files in it. - * Failure to delete any of the files will cause a build error. - */ - WIPE, - - /** - * Fail the build if the work directory is not empty. - */ - FAIL; -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/PickFromListTask.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/PickFromListTask.java deleted file mode 100644 index 828477bd..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/PickFromListTask.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import static com.carrotsearch.randomizedtesting.SysGlobals.*; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.Project; -import org.apache.tools.ant.ProjectComponent; -import org.apache.tools.ant.Task; - -import com.carrotsearch.randomizedtesting.SeedUtils; -import com.carrotsearch.randomizedtesting.generators.RandomPicks; -import com.google.common.base.Strings; - -/** - * An ANT task to pick and fix the random seed in advance (for selecting - * other derivative values, for example). - */ -public class PickFromListTask extends Task { - /** - * Nested value element. - */ - public final static class StringValue extends ProjectComponent { - private String value = ""; - - public void addText(String value) { - this.value += getProject().replaceProperties(value); - } - - @Override - public String toString() { - return value; - } - } - - /** - * Name of the property to set. - */ - private String propertyName; - - /** - * Allow the property to be undefined as one of - * the pick choices. - */ - private boolean allowUndefined = false; - - /** - * Random seed to use. - */ - private String random; - - /** - * Values to pick from. - */ - private List values = new ArrayList<>(); - - /** - * Execution ID used to permute the pick order for lists of identical length - * and identical seed. - */ - private static AtomicInteger executionId = new AtomicInteger(); - - public void setProperty(String propertyName) { - this.propertyName = propertyName; - } - - public void setAllowUndefined(boolean allowUndefined) { - this.allowUndefined = allowUndefined; - } - - public void setSeed(String randomSeed) { - if (!Strings.isNullOrEmpty(getProject().getUserProperty(SYSPROP_RANDOM_SEED()))) { - String userProperty = getProject().getUserProperty(SYSPROP_RANDOM_SEED()); - if (!userProperty.equals(randomSeed)) { - log("Ignoring seed attribute because it is overridden by user properties.", Project.MSG_WARN); - } - } else if (!Strings.isNullOrEmpty(randomSeed)) { - this.random = randomSeed; - } - } - - public StringValue createValue() { - StringValue v = new StringValue(); - values.add(v); - return v; - } - - /** - * Execute the task. - */ - @Override - public void execute() throws BuildException { - validate(); - - if (allowUndefined) { - values.add(null); - } - - long permutedSeed = SeedUtils.parseSeedChain(random)[0]; - permutedSeed ^= new Random(executionId.incrementAndGet()).nextLong(); - - StringValue pick = RandomPicks.randomFrom(new Random(permutedSeed), values); - if (pick != null) { - getProject().setProperty(propertyName, pick.toString()); - } - } - - /** - * Validate arguments and state. - */ - private void validate() { - if (Strings.emptyToNull(random) == null) { - random = Strings.emptyToNull(getProject().getProperty(SYSPROP_RANDOM_SEED())); - } - - if (random == null) { - throw new BuildException("Required attribute 'seed' must not be empty. Look at ."); - } - - long[] seeds = SeedUtils.parseSeedChain(random); - if (seeds.length < 1) { - throw new BuildException("Random seed is required."); - } - - if (values.isEmpty() && !allowUndefined) { - throw new BuildException("No values to pick from and allowUndefined=false."); - } - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/PickSeedTask.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/PickSeedTask.java deleted file mode 100644 index 1e74ed9e..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/PickSeedTask.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import java.util.Random; - -import org.apache.tools.ant.*; - -import com.carrotsearch.randomizedtesting.SeedUtils; -import com.carrotsearch.randomizedtesting.SysGlobals; -import com.google.common.base.Strings; - -/** - * An ANT task to pick and fix the random seed in advance (for selecting - * other derivative values, for example). - */ -public class PickSeedTask extends Task { - - /** - * Name of the property to set. - */ - private String propertyName; - - /** - * Picks a random seed and writes it to a given property. If the property - * is already defined nothing is done. - */ - public void setProperty(String propertyName) { - this.propertyName = propertyName; - } - - /** - * Execute the task. - */ - @Override - public void execute() throws BuildException { - validate(); - - String seedValue = Strings.emptyToNull(getProject().getProperty(propertyName)); - if (seedValue == null) { - seedValue = SeedUtils.formatSeed(new Random().nextLong()); - log("Picking master seed for property '" + propertyName + "': " - + seedValue, Project.MSG_VERBOSE); - getProject().setProperty(propertyName, seedValue); - } else { - log("Seed property '" + propertyName + "' already defined: " - + seedValue, Project.MSG_INFO); - } - } - - /** - * Validate arguments and state. - */ - private void validate() { - if (propertyName == null) { - propertyName = SysGlobals.SYSPROP_RANDOM_SEED(); - } - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/Pluralize.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/Pluralize.java deleted file mode 100644 index 27b3cb5d..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/Pluralize.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -public final class Pluralize { - private Pluralize() {} - - public static String pluralize(int count, String word) { - if (count != 1) { - word += "s"; - } - return word; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/RunListenerList.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/RunListenerList.java deleted file mode 100644 index 2b389b21..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/RunListenerList.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import com.carrotsearch.ant.tasks.junit4.runlisteners.RunListenerClass; - -import java.util.List; - -public final class RunListenerList { - private List listeners; - - public RunListenerList(List listeners) { - this.listeners = listeners; - } - - public void addConfigured(RunListenerClass runListener) { - listeners.add(runListener); - } -} \ No newline at end of file diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/SimpleStreamPumper.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/SimpleStreamPumper.java deleted file mode 100644 index cb6125c9..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/SimpleStreamPumper.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UncheckedIOException; - -public class SimpleStreamPumper implements Runnable { - private final InputStream from; - private final OutputStream to; - - public SimpleStreamPumper(InputStream from, OutputStream to) { - this.from = from; - this.to = to; - } - - @Override - public void run() { - try { - byte[] buffer = new byte[1024 * 4]; - while (true) { - int len = from.read(buffer); - if (len > 0) { - to.write(buffer, 0, len); - } else if (len < 0) { - break; // EOF. - } else { - // read should be blocking? - Thread.sleep(250); - } - } - } catch (IOException e) { - throw new UncheckedIOException(e); - } catch (InterruptedException e) { - throw new RuntimeException("Pumper threads should not be interrupted?", e); - } - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/SlaveIdle.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/SlaveIdle.java deleted file mode 100644 index 9fa61bca..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/SlaveIdle.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import java.io.IOException; -import java.io.OutputStreamWriter; - -/** - * An event published when a slave is idle and waits for new suite classes. - */ -class SlaveIdle { - private OutputStreamWriter stdin; - - /** For delegation. */ - SlaveIdle() { - } - - public SlaveIdle(OutputStreamWriter stdin) { - this.stdin = stdin; - } - - public void finished() { - try { - stdin.close(); - } catch (IOException e) { - // Ignore, not much we can do. - } - } - - public void newSuite(String suiteName) { - try { - stdin.write(suiteName); - stdin.write("\n"); - stdin.flush(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/SuiteBalancer.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/SuiteBalancer.java deleted file mode 100644 index 3ff7b227..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/SuiteBalancer.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import java.util.Collection; -import java.util.List; - -/** - * A test balancer schedules test suites to be executed on a given JVM. - */ -public interface SuiteBalancer { - public final static class Assignment implements Comparable { - /** - * Test suite name. - */ - public final String suiteName; - - /** - * Slave assignment. - */ - public final int slaveId; - - /** - * Estimated cost; informational only (depends on the balancer). May be zero - * for balancers which don't use cost at all. - */ - public final int estimatedCost; - - public Assignment(String suiteName, int slaveId, int estimatedCost) { - this.suiteName = suiteName; - this.slaveId = slaveId; - this.estimatedCost = estimatedCost; - } - - @Override - public int compareTo(Assignment other) { - int v = this.suiteName.compareTo(other.suiteName); - if (v == 0) { - v = this.slaveId - other.slaveId; - } - return v; - } - } - - /** - * Sets the owner task (for logging mostly). - */ - void setOwner(JUnit4 owner); - - /** - * Provide assignments for suite names and a given number of slaves. - * - * @return Returns an ordered list with assignments. Any suite name not present - * in the keys of the returned map will be assigned by following - * balancers (or randomly). - */ - List assign(Collection suiteNames, int slaves, long seed); -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TailInputStream.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TailInputStream.java deleted file mode 100644 index e9f0783a..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TailInputStream.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; -import java.nio.file.Path; - -/** - * An input stream that tails from a random access file as new input appears there. - * It's a lousy solution but we don't have access to real interprocess pipes from Java. - */ -class TailInputStream extends InputStream { - /** How long to sleep (millis) before checking for updates? */ - private static final long TAIL_CHECK_DELAY = 250; - - private final RandomAccessFile raf; - private volatile boolean closed; - private volatile boolean complete; - - public TailInputStream(Path file) throws FileNotFoundException { - this.raf = new RandomAccessFile(file.toFile(), "r"); - } - - @Override - public int read() throws IOException { - if (closed) return -1; - - try { - int c; - while ((c = raf.read()) == -1) { - if (complete) { - return -1; // EOF; - } - try { - Thread.sleep(TAIL_CHECK_DELAY); - } catch (InterruptedException e) { - throw new IOException(e); - } - } - return c; - } catch (IOException e) { - if (closed) - return -1; - else - throw e; - } - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - if (closed) return -1; - - if (b == null) { - throw new NullPointerException(); - } else if (off < 0 || len < 0 || len > b.length - off) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { - return 0; - } - - try { - int rafRead = raf.read(b, off, len); - if (rafRead == -1) { - // If nothing in the buffer, wait. - do { - if (complete) { - return -1; // EOF; - } - - try { - Thread.sleep(TAIL_CHECK_DELAY); - } catch (InterruptedException e) { - throw new IOException(e); - } - } while ((rafRead = raf.read(b, off, len)) == -1); - } - return rafRead; - } catch (IOException e) { - if (closed) - return -1; - else - throw e; - } - } - - @Override - public int read(byte[] b) throws IOException { - return read(b, 0, b.length); - } - - @Override - public boolean markSupported() { - return false; - } - - @Override - public void close() throws IOException { - closed = true; - this.raf.close(); - } - - /** - * Changes the semantics of tailing so that from the moment of calling this method on, - * hitting an EOF on the tailed file will cause an EOF in read methods. - */ - public void completeAtEnd() { - complete = true; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TestClass.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TestClass.java deleted file mode 100644 index 14fe3a3e..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TestClass.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -final class TestClass { - String className; - boolean replicate; - - public TestClass() { - this(null); - } - - public TestClass(String className) { - this.className = className; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TestsCollection.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TestsCollection.java deleted file mode 100644 index e502391b..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TestsCollection.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * A collection of test suites and extracted annotation information. - */ -final class TestsCollection { - List testClasses = new ArrayList<>(); - - public void add(TestClass testClass) { - testClasses.add(testClass); - } - - public void onlyUniqueSuiteNames() { - Map unique = new LinkedHashMap<>(); - for (TestClass t : testClasses) { - unique.put(t.className, t); - } - testClasses.clear(); - testClasses.addAll(unique.values()); - } - - public boolean hasReplicatedSuites() { - for (TestClass t : testClasses) { - if (t.replicate) return true; - } - return false; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TestsSummary.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TestsSummary.java deleted file mode 100644 index 8a923faa..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TestsSummary.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import static com.carrotsearch.ant.tasks.junit4.Pluralize.*; - -/** - * Summary of tests execution. - */ -public class TestsSummary { - public final int suites, ignoredSuites, suiteErrors; - public final int tests, failures, errors, assumptions, ignores; - - public TestsSummary( - int suites, int ignoredSuites, int suiteErrors, - int tests, int failures, int errors, int assumptions, int ignores) { - this.suites = suites; - this.ignoredSuites = ignoredSuites; - this.suiteErrors = suiteErrors; - - this.tests = tests; - this.failures = failures; - this.errors = errors; - this.assumptions = assumptions; - this.ignores = ignores; - } - - public boolean isSuccessful() { - return (errors + failures + suiteErrors) == 0; - } - - @Override - public String toString() { - StringBuilder s = new StringBuilder(); - s.append(suites).append(pluralize(suites, " suite")); - if (ignoredSuites > 0) { - s.append(" (").append(ignoredSuites).append(" ignored)"); - } - s.append(", ").append(tests).append(pluralize(tests, " test")); - if (suiteErrors > 0) s.append(", ").append(suiteErrors).append(pluralize(suiteErrors, " suite-level error")); - if (errors > 0) s.append(", ").append(errors).append(pluralize(errors, " error")); - if (failures > 0) s.append(", ").append(failures).append(pluralize(failures, " failure")); - if (ignores + assumptions > 0) { - s.append(", ").append(ignores + assumptions).append(" ignored"); - if (assumptions > 0) { - s.append(" (").append(assumptions).append(pluralize(assumptions, " assumption")).append(")"); - } - } - return s.toString(); - } - - public int getNonIgnoredTestsCount() { - return tests - (ignores + assumptions); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TestsSummaryEventListener.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TestsSummaryEventListener.java deleted file mode 100644 index 426624f0..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/TestsSummaryEventListener.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedSuiteResultEvent; -import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedTestResultEvent; -import com.google.common.eventbus.EventBus; -import com.google.common.eventbus.Subscribe; - -/** - * Create a summary of tests execution. - * - * @see EventBus - */ -public class TestsSummaryEventListener { - private int failures; - private int tests; - private int errors; - private int assumptions; - private int ignores; - - private int suites; - private int ignoredSuites; - private int suiteErrors; - - /** - * React to suite summaries only. - */ - @Subscribe - public void suiteSummary(AggregatedSuiteResultEvent e) { - suites++; - if (!e.getFailures().isEmpty()) { - suiteErrors += e.getFailures().size(); - } - - for (AggregatedTestResultEvent testResult : e.getTests()) { - tests++; - - switch (testResult.getStatus()) { - case ERROR: - errors++; - break; - - case FAILURE: - failures++; - break; - - case IGNORED: - ignores++; - break; - - case IGNORED_ASSUMPTION: - assumptions++; - break; - - default: - break; - } - } - - if (e.isSuccessful() && - e.getTests().isEmpty()) { - ignoredSuites++; - } - } - - /** - * Return the summary of all tests. - */ - public TestsSummary getResult() { - return new TestsSummary(suites, ignoredSuites, suiteErrors, tests, failures, errors, assumptions, ignores); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/ExecutionTimeBalancer.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/ExecutionTimeBalancer.java deleted file mode 100644 index 4ece79bb..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/ExecutionTimeBalancer.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.balancers; - -import java.util.*; - -import org.apache.tools.ant.Project; -import org.apache.tools.ant.ProjectComponent; -import org.apache.tools.ant.types.FileSet; -import org.apache.tools.ant.types.ResourceCollection; - -import com.carrotsearch.ant.tasks.junit4.*; -import com.carrotsearch.ant.tasks.junit4.listeners.ExecutionTimesReport; - -/** - * A test suite balancer based on past execution times saved using - * {@link ExecutionTimesReport}. - */ -public class ExecutionTimeBalancer extends ProjectComponent implements SuiteBalancer { - private static class SlaveLoad { - public static final Comparator ASCENDING_BY_ESTIMATED_FINISH = new Comparator() { - @Override - public int compare(SlaveLoad o1, SlaveLoad o2) { - if (o1.estimatedFinish < o2.estimatedFinish) { - return -1; - } else if (o1.estimatedFinish == o2.estimatedFinish) { - return o1.id - o2.id; // Assume no overflows. - } else { - return 1; - } - } - }; - - public final int id; - public long estimatedFinish; - - public SlaveLoad(int id) { - this.id = id; - } - } - - /** - * All included execution time dumps. - */ - private List resources = new ArrayList<>(); - - /** Owning task (logging). */ - private JUnit4 owner; - - /** @see #setVerbose(boolean) */ - private boolean verbose; - - /** - * Be verbose about estimated times etc. - */ - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - - /** - * Adds a resource collection with execution hints. - */ - public void add(ResourceCollection rc) { - if (rc instanceof FileSet) { - FileSet fs = (FileSet) rc; - fs.setProject(getProject()); - } - resources.add(rc); - } - - - /** - * Assign based on execution time history. The algorithm is a greedy heuristic - * assigning the longest remaining test to the slave with the - * shortest-completion time so far. This is not optimal but fast and provides - * a decent average assignment. - */ - @Override - public List assign(Collection suiteNames, int slaves, long seed) { - // Read hints first. - final Map> hints = ExecutionTimesReport.mergeHints(resources, suiteNames); - - // Preprocess and sort costs. Take the median for each suite's measurements as the - // weight to avoid extreme measurements from screwing up the average. - final List costs = new ArrayList<>(); - for (String suiteName : suiteNames) { - final List suiteHint = hints.get(suiteName); - if (suiteHint != null) { - // Take the median for each suite's measurements as the weight - // to avoid extreme measurements from screwing up the average. - Collections.sort(suiteHint); - final Long median = suiteHint.get(suiteHint.size() / 2); - costs.add(new SuiteHint(suiteName, median)); - } - } - Collections.sort(costs, SuiteHint.DESCENDING_BY_WEIGHT); - - // Apply the assignment heuristic. - final PriorityQueue pq = new PriorityQueue( - slaves, SlaveLoad.ASCENDING_BY_ESTIMATED_FINISH); - for (int i = 0; i < slaves; i++) { - pq.add(new SlaveLoad(i)); - } - - final List assignments = new ArrayList<>(); - for (SuiteHint hint : costs) { - SlaveLoad slave = pq.remove(); - slave.estimatedFinish += hint.cost; - pq.add(slave); - - owner.log("Expected execution time for " + hint.suiteName + ": " + - Duration.toHumanDuration(hint.cost), - Project.MSG_DEBUG); - - assignments.add(new Assignment(hint.suiteName, slave.id, (int) hint.cost)); - } - - // Dump estimated execution times. - TreeMap ordered = new TreeMap(); - while (!pq.isEmpty()) { - SlaveLoad slave = pq.remove(); - ordered.put(slave.id, slave); - } - for (Integer id : ordered.keySet()) { - final SlaveLoad slave = ordered.get(id); - owner.log(String.format(Locale.ROOT, - "Expected execution time on JVM J%d: %8.2fs", - slave.id, - slave.estimatedFinish / 1000.0f), - verbose ? Project.MSG_INFO : Project.MSG_DEBUG); - } - - return assignments; - } - - - @Override - public void setOwner(JUnit4 owner) { - this.owner = owner; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/MergeHints.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/MergeHints.java deleted file mode 100644 index b9ab9ad7..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/MergeHints.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.balancers; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.Task; -import org.apache.tools.ant.types.FileSet; -import org.apache.tools.ant.types.ResourceCollection; - -import com.carrotsearch.ant.tasks.junit4.listeners.ExecutionTimesReport; - -/** - * Merge execution hints emitted by {@link ExecutionTimeBalancer} to one file. - */ -public class MergeHints extends Task { - /** - * All included execution time dumps. - */ - private List resources = new ArrayList<>(); - - /** - * @see ExecutionTimesReport#setHistoryLength(int) - */ - private int historyLength = ExecutionTimesReport.DEFAULT_HISTORY_LENGTH; - - /** - * Output file for merged hints. - */ - private File file; - - /** - * @see ExecutionTimesReport#setHistoryLength(int) - */ - public void setHistoryLength(int historyLength) { - if (historyLength < 0) { - throw new BuildException("History length must be >= 1: " + historyLength); - } - this.historyLength = historyLength; - } - - /** - * Set the output file for merged hints. - */ - public void setFile(File file) { - this.file = file; - } - - /** - * Adds a resource collection with execution hints. - */ - public void add(ResourceCollection rc) { - if (rc instanceof FileSet) { - FileSet fs = (FileSet) rc; - fs.setProject(getProject()); - } - resources.add(rc); - } - - @Override - public void execute() throws BuildException { - // Read hints first, preserve all hints. - final Map> hints = ExecutionTimesReport.mergeHints( - resources, /* keep all */ null); - - for (List hintList : hints.values()) { - while (hintList.size() > historyLength) { - hintList.remove(0); - } - } - - try { - ExecutionTimesReport.writeHints(file, hints); - } catch (IOException e) { - throw new BuildException("Could not write updated hints file: " + file, e); - } - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/RoundRobinBalancer.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/RoundRobinBalancer.java deleted file mode 100644 index c00a3ff5..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/RoundRobinBalancer.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.balancers; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import com.carrotsearch.ant.tasks.junit4.JUnit4; -import com.carrotsearch.ant.tasks.junit4.SuiteBalancer; - -/** - * A round-robin suite balancer (default for non-assigned suites). - */ -public class RoundRobinBalancer implements SuiteBalancer { - - @Override - public List assign(Collection suiteNames, int slaves, long seed) { - List result = new ArrayList<>(); - int i = 0; - for (String suite : suiteNames) { - result.add(new Assignment(suite, i++, 0)); - if (i >= slaves) i = 0; - } - return result; - } - - @Override - public void setOwner(JUnit4 owner) {} -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/SuiteHint.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/SuiteHint.java deleted file mode 100644 index 56d10ef6..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/SuiteHint.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.balancers; - -import java.util.Comparator; - -/** - * A suite with the cost hint. - */ -public final class SuiteHint { - public static final Comparator DESCENDING_BY_WEIGHT = new Comparator() { - @Override - public int compare(SuiteHint o1, SuiteHint o2) { - if (o1.cost == o2.cost) - return o1.suiteName.compareTo(o2.suiteName); - - if (o1.cost < o2.cost) - return 1; - else - return -1; - } - }; - - public final String suiteName; - public final long cost; - - public SuiteHint(String suiteName, long weight) { - this.suiteName = suiteName; - this.cost = weight; - } -} \ No newline at end of file diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/TopHints.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/TopHints.java deleted file mode 100644 index 12037ef2..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/balancers/TopHints.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.balancers; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.Task; -import org.apache.tools.ant.types.FileSet; -import org.apache.tools.ant.types.ResourceCollection; - -import com.carrotsearch.ant.tasks.junit4.listeners.ExecutionTimesReport; - -/** - * Display the slowest test suites based on hints files. - */ -public class TopHints extends Task { - - private static class Entry { - String suiteName; - double averageHint; - - public Entry(String s, double h) { - this.suiteName = s; - this.averageHint = h; - } - } - - private static final Comparator byDescHint = new Comparator() { - @Override - public int compare(Entry o1, Entry o2) { - if (o1.averageHint < o2.averageHint) return 1; - if (o1.averageHint > o2.averageHint) return -1; - return o1.suiteName.compareTo(o2.suiteName); - } - }; - - /** - * All included execution time dumps. - */ - private List resources = new ArrayList<>(); - - /** - * Max entries to display. - */ - private int max = 10; - - /** - * The number of entries to display, maximum. - */ - public void setMax(int maxEntries) { - this.max = maxEntries; - } - - /** - * Adds a resource collection with execution hints. - */ - public void add(ResourceCollection rc) { - if (rc instanceof FileSet) { - FileSet fs = (FileSet) rc; - fs.setProject(getProject()); - } - resources.add(rc); - } - - @Override - public void execute() throws BuildException { - // Read hints first, preserve all hints. - final Map> hints = ExecutionTimesReport.mergeHints( - resources, /* keep all */ null); - - // Could be done with a pq without sorting everything... - ArrayList entries = new ArrayList(); - for (Map.Entry> e : hints.entrySet()) { - double average = 0; - for (Long v : e.getValue()) { - average += v; - } - entries.add(new Entry(e.getKey(), average / e.getValue().size())); - } - - Collections.sort(entries, byDescHint); - final int j = Math.min(max, entries.size()); - for (int i = 0; i < j; i++) { - log(String.format(Locale.ROOT, "%6.2fs | %s", - entries.get(i).averageHint / 1000.0, - entries.get(i).suiteName)); - } - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/AbstractEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/AbstractEvent.java deleted file mode 100644 index 4488c4de..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/AbstractEvent.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import org.junit.runner.Description; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonToken; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; - -/** - * An abstract {@link IEvent}. - */ -abstract class AbstractEvent implements RemoteEvent { - private final static char [] HEX = "0123456789ABCDEF".toCharArray(); - - /** Type is recreated in constructors anyway. */ - private transient final EventType type; - - public AbstractEvent(EventType type) { - if (this.getClass() != type.eventClass) { - throw new RuntimeException("Event type mismatch: " - + type + ", class: " + this.getClass()); - } - - this.type = type; - } - - @Override - public EventType getType() { - return type; - } - - protected static JsonWriter writeBinaryProperty(JsonWriter writer, String propertyName, byte[] value) throws IOException { - return writer.name(propertyName).value(toAscii(value)); - } - - protected static byte[] readBinaryProperty(JsonReader reader, String propertyName) throws IOException { - return fromAscii(expectProperty(reader, propertyName).nextString()); - } - - protected static String readStringProperty(JsonReader reader, String propertyName) throws IOException { - if (expectProperty(reader, propertyName).peek() != JsonToken.STRING) { - throw new IOException("Expected a non-null string for property: " + propertyName); - } - return reader.nextString(); - } - - protected static String readStringOrNullProperty(JsonReader reader, String propertyName) throws IOException { - expectProperty(reader, propertyName); - if (reader.peek() == JsonToken.STRING) { - return reader.nextString(); - } else if (reader.peek() == JsonToken.NULL) { - reader.nextNull(); - return null; - } else { - throw new IOException("Expected a non or string for property: " + propertyName); - } - } - - protected static boolean readBoolean(JsonReader reader, String propertyName) throws IOException { - expectProperty(reader, propertyName); - return reader.nextBoolean(); - } - - protected static long readLongProperty(JsonReader reader, String propertyName) throws IOException { - return expectProperty(reader, propertyName).nextLong(); - } - - protected static JsonReader expectProperty(JsonReader reader, String propertyName) throws IOException { - final String name = reader.nextName(); - if (!propertyName.equals(name)) { - throw new IOException("Expected property: " + propertyName + " but got: " + name); - } - return reader; - } - - private static byte[] fromAscii(String ascii) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - for (int i = 0; i < ascii.length(); i++) { - char chr = ascii.charAt(i); - if (chr != '%') { - baos.write(chr); - } else { - baos.write((hexValue(ascii.charAt(++i)) << 4) | - hexValue(ascii.charAt(++i))); - } - } - return baos.toByteArray(); - } - - private static int hexValue(char hexChar) throws IOException { - if (hexChar >= '0' && hexChar <= '9') - return hexChar - '0'; - if (hexChar >= 'A' && hexChar <= 'F') - return hexChar - 'A' + 10; - if (hexChar >= 'a' && hexChar <= 'f') - return hexChar - 'a' + 10; - throw new IOException("Unexpected character in binary stream: " + hexChar); - } - - private static String toAscii(byte[] src) { - StringBuilder bb = new StringBuilder(); - for (byte b : src) { - // Pass simple ASCII range. - if (b >= 32 && b <= 126 && b != '%') { - bb.append((char) b); - } else { - bb.append('%'); - bb.append(HEX[(b >> 4) & 0x0f]); - bb.append(HEX[(b ) & 0x0f]); - } - } - return bb.toString(); - } - - public static void writeDescription(JsonWriter writer, Description e) throws IOException { - JsonHelpers.writeDescription(writer, e); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/AbstractEventWithDescription.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/AbstractEventWithDescription.java deleted file mode 100644 index 35564b09..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/AbstractEventWithDescription.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; - -import org.junit.runner.Description; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; - -abstract class AbstractEventWithDescription extends AbstractEvent implements IDescribable { - private Description description; - - public AbstractEventWithDescription(EventType type) { - super(type); - } - - public Description getDescription() { - return description; - } - - protected void setDescription(Description description) { - if (this.description != null) - throw new IllegalStateException("Initialize once."); - this.description = description; - } - - @Override - public void serialize(JsonWriter writer) throws IOException { - writeDescription(writer, description); - } - - @Override - public void deserialize(JsonReader reader) throws IOException { - this.description = JsonHelpers.readDescription(reader); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/AppendStdErrEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/AppendStdErrEvent.java deleted file mode 100644 index ceb10d2e..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/AppendStdErrEvent.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; -import java.io.OutputStream; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; - -public class AppendStdErrEvent extends AbstractEvent implements IStreamEvent { - private byte[] chunk; - - protected AppendStdErrEvent() { - super(EventType.APPEND_STDERR); - } - - public AppendStdErrEvent(byte[] b, int off, int len) { - this(); - chunk = new byte [len]; - System.arraycopy(b, off, chunk, 0, len); - } - - @Override - public void copyTo(OutputStream os) throws IOException { - os.write(chunk); - } - - @Override - public void serialize(JsonWriter writer) throws IOException { - writer.beginObject(); - writeBinaryProperty(writer, "chunk", chunk); - writer.endObject(); - } - - @Override - public void deserialize(JsonReader reader) throws IOException { - reader.beginObject(); - chunk = readBinaryProperty(reader, "chunk"); - reader.endObject(); - } -} \ No newline at end of file diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/AppendStdOutEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/AppendStdOutEvent.java deleted file mode 100644 index d1447fc2..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/AppendStdOutEvent.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; -import java.io.OutputStream; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; - -public class AppendStdOutEvent extends AbstractEvent implements IStreamEvent { - private byte[] chunk; - - protected AppendStdOutEvent() { - super(EventType.APPEND_STDOUT); - } - - public AppendStdOutEvent(byte[] b, int off, int len) { - this(); - chunk = new byte [len]; - System.arraycopy(b, off, chunk, 0, len); - } - - @Override - public void copyTo(OutputStream os) throws IOException { - os.write(chunk); - } - - @Override - public void serialize(JsonWriter writer) throws IOException { - writer.beginObject(); - writeBinaryProperty(writer, "chunk", chunk); - writer.endObject(); - } - - @Override - public void deserialize(JsonReader reader) throws IOException { - reader.beginObject(); - chunk = readBinaryProperty(reader, "chunk"); - reader.endObject(); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/BootstrapEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/BootstrapEvent.java deleted file mode 100644 index 564de8b4..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/BootstrapEvent.java +++ /dev/null @@ -1,158 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; -import java.lang.management.ManagementFactory; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonToken; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; - -/** - * Initial message sent from the slave to the master (if forked locally). - */ -public class BootstrapEvent extends AbstractEvent { - private static final List GUARANTEED_PROPERTIES = Arrays.asList( - "java.version", - "java.vendor", - "java.vendor.url", - "java.home", - "java.vm.specification.version", - "java.vm.specification.vendor", - "java.vm.specification.name", - "java.vm.version", - "java.vm.vendor", - "java.vm.name", - "java.specification.version", - "java.specification.vendor", - "java.specification.name", - "java.class.version", - "java.class.path", - "java.library.path", - "java.io.tmpdir", - "java.compiler", - "java.ext.dirs", - "os.name", - "os.arch", - "os.version", - "file.separator", - "path.separator", - "line.separator", - "user.name", - "user.home", - "user.dir"); - - private String defaultCharset; - private Map systemProperties; - private String pidString; - - /** Preinitialization with local machine's configuration. */ - public BootstrapEvent() { - super(EventType.BOOTSTRAP); - - this.defaultCharset = Charset.defaultCharset().name(); - - try { - pidString = ManagementFactory.getRuntimeMXBean().getName(); - } catch (Throwable t) { - pidString = ""; - } - - this.systemProperties = collectSystemProperties(); - - systemProperties.put("junit4.memory.total", - Long.toString(Runtime.getRuntime().totalMemory())); - systemProperties.put("junit4.processors", - Long.toString(Runtime.getRuntime().availableProcessors())); - systemProperties.put("junit4.pidString", pidString); - } - - private Map collectSystemProperties() { - List propertyNames = new ArrayList(); - try { - Enumeration e = System.getProperties().propertyNames(); - while (e.hasMoreElements()) { - propertyNames.add((String) e.nextElement()); - } - } catch (SecurityException e) { - // No access to the full set of properties. Try to include at least the default - // guaranteed set of properties (maybe we have read-only access). - propertyNames.addAll(GUARANTEED_PROPERTIES); - } - - TreeMap sysProps = new TreeMap(); - for (String propertyName : propertyNames) { - try { - String value = System.getProperty(propertyName); - if (value != null) { - sysProps.put(propertyName, value); - } - } catch (SecurityException e) { - // No access. Ignore. - } - } - - return sysProps; - } - - /** - * Default charset on the slave. - */ - public String getDefaultCharsetName() { - return defaultCharset; - } - - /** - * System properties on the slave. - */ - public Map getSystemProperties() { - return systemProperties; - } - - /** - * Returns a PID string or anything that approximates it and would - * help in dumping a stack trace externally, for example. - */ - public String getPidString() { - return pidString; - } - - @Override - public void serialize(JsonWriter writer) throws IOException { - writer.beginObject(); - writer.name("defaultCharset").value(defaultCharset); - writer.name("pidString").value(pidString); - - writer.name("systemProperties").beginObject(); - for (Map.Entry e : systemProperties.entrySet()) { - writer.name(e.getKey()).value(e.getValue()); - } - writer.endObject(); - - writer.endObject(); - } - - @Override - public void deserialize(JsonReader reader) throws IOException { - reader.beginObject(); - defaultCharset = readStringProperty(reader, "defaultCharset"); - pidString = readStringProperty(reader, "pidString"); - - expectProperty(reader, "systemProperties"); - reader.beginObject(); - systemProperties = new LinkedHashMap(); - while (reader.peek() != JsonToken.END_OBJECT) { - systemProperties.put(reader.nextName(), reader.nextString()); - } - reader.endObject(); - - reader.endObject(); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/Deserializer.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/Deserializer.java deleted file mode 100644 index 14e1818e..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/Deserializer.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonToken; -import com.google.common.base.Charsets; - -/** - * Event deserializer. - */ -public class Deserializer { - private JsonReader input; - - public Deserializer(InputStream is, ClassLoader refLoader) throws IOException { - input = new JsonReader(new InputStreamReader(is, Charsets.UTF_8)); - input.setLenient(true); - } - - public IEvent deserialize() throws IOException { - JsonToken peek = input.peek(); - if (peek == JsonToken.END_ARRAY) - return null; - - input.beginArray(); - EventType type = EventType.valueOf(input.nextString()); - IEvent event = type.deserialize(input); - input.endArray(); - return event; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/EventType.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/EventType.java deleted file mode 100644 index d362d4fc..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/EventType.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; - -/** - * Events (messages) passed between the slave and the master. - */ -public enum EventType { - BOOTSTRAP(BootstrapEvent.class), - - SUITE_STARTED(SuiteStartedEvent.class), - SUITE_FAILURE(SuiteFailureEvent.class), - SUITE_COMPLETED(SuiteCompletedEvent.class), - - APPEND_STDOUT(AppendStdOutEvent.class), - APPEND_STDERR(AppendStdErrEvent.class), - - TEST_STARTED(TestStartedEvent.class), - TEST_FAILURE(TestFailureEvent.class), - TEST_IGNORED_ASSUMPTION(TestIgnoredAssumptionEvent.class), - TEST_IGNORED(TestIgnoredEvent.class), - TEST_FINISHED(TestFinishedEvent.class), - - IDLE(IdleEvent.class), - QUIT(QuitEvent.class); - - /** - * Concrete class associated with the given event type. - */ - public final Class eventClass; - - /** - * Initialize with concrete event class. - */ - private EventType(Class eventClass) { - this.eventClass = eventClass; - } - - /** - * Deserialize a given event type from stream. - */ - public RemoteEvent deserialize(JsonReader input) throws IOException { - RemoteEvent empty; - try { - empty = eventClass.newInstance(); - empty.deserialize(input); - return empty; - } catch (InstantiationException e) { - throw new IOException(e); - } catch (IllegalAccessException e) { - throw new IOException(e); - } - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/FailureEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/FailureEvent.java deleted file mode 100644 index 831864fd..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/FailureEvent.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; - -import org.junit.runner.Description; -import org.junit.runner.notification.Failure; - -import com.carrotsearch.ant.tasks.junit4.events.mirrors.FailureMirror; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; - -/** - * Generic serialized failure event. - */ -public abstract class FailureEvent extends AbstractEvent implements IDescribable { - private FailureMirror failure; - - public FailureEvent(EventType type) { - super(type); - } - - protected void setFailure(Failure failure) { - if (this.failure != null) { - throw new IllegalStateException("Set only once."); - } - - this.failure = new FailureMirror(failure); - } - - public FailureMirror getFailure() { - return failure; - } - - public Description getDescription() { - return failure.getDescription(); - } - - @Override - public void serialize(JsonWriter writer) throws IOException { - writer.beginObject(); - - writer.name("description"); - writeDescription(writer, failure.getDescription()); - - writer.name("message").value(failure.getMessage()); - writer.name("trace").value(failure.getTrace()); - writer.name("throwableString").value(failure.getThrowableString()); - writer.name("throwableClass").value(failure.getThrowableClass()); - writer.name("assertionViolation").value(failure.isAssertionViolation()); - writer.name("assumptionViolation").value(failure.isAssumptionViolation()); - - writer.endObject(); - } - - @Override - public void deserialize(JsonReader reader) throws IOException { - reader.beginObject(); - - expectProperty(reader, "description"); - Description description = JsonHelpers.readDescription(reader); - String message = readStringOrNullProperty(reader, "message"); - String trace = readStringOrNullProperty(reader, "trace"); - String throwableString = readStringOrNullProperty(reader, "throwableString"); - String throwableClass = readStringOrNullProperty(reader, "throwableClass"); - boolean assertionViolation = readBoolean(reader, "assertionViolation"); - boolean assumptionViolation = readBoolean(reader, "assumptionViolation"); - - this.failure = new FailureMirror(description, - message, - trace, - throwableString, - throwableClass, - assertionViolation, - assumptionViolation); - reader.endObject(); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/IDescribable.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/IDescribable.java deleted file mode 100644 index 91c11893..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/IDescribable.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import org.junit.runner.Description; - -/** - * An event that carries a {@link Description}. - */ -public interface IDescribable { - /* - * TODO: [GH-211] we should just pass over the essential information about - * a test, without exposing Class, Description or Annotation instances (which - * are problematic to serialize, initialize, etc.) - */ - Description getDescription(); -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/IEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/IEvent.java deleted file mode 100644 index 0119d289..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/IEvent.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -/** - * An event/ message passed between the forked JVM and the master. - */ -public interface IEvent { - EventType getType(); -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/IStreamEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/IStreamEvent.java deleted file mode 100644 index 3a5720d2..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/IStreamEvent.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; -import java.io.OutputStream; - -public interface IStreamEvent { - public void copyTo(OutputStream os) throws IOException; -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/IdleEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/IdleEvent.java deleted file mode 100644 index a89dd422..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/IdleEvent.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; - -/** - * Marker that the slave is idle and awaiting more suite names. - */ -public class IdleEvent extends AbstractEvent { - public IdleEvent() { - super(EventType.IDLE); - } - - @Override - public void serialize(JsonWriter writer) throws IOException { - writer.beginObject(); - writer.endObject(); - } - - @Override - public void deserialize(JsonReader reader) throws IOException { - reader.beginObject(); - reader.endObject(); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/JsonHelpers.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/JsonHelpers.java deleted file mode 100644 index c029b853..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/JsonHelpers.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -import org.junit.runner.Description; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonToken; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; -import com.google.common.base.Objects; - -public final class JsonHelpers { - public static void writeDescription(JsonWriter writer, Description e) throws IOException { - String key = createId(e); - if (writer.inContext(key)) { - writer.value(key); - } else { - writer.registerInContext(key, e); - writer.beginObject(); - writer.name("id").value(key); - writer.name("displayName").value(e.getDisplayName()); - writer.name("methodName").value(e.getMethodName()); - writer.name("className").value(e.getClassName()); - - writer.name("children").beginArray(); - for (Description child : e.getChildren()) { - writeDescription(writer, child); - } - writer.endArray(); - writer.endObject(); - } - } - - protected static Description readDescription(JsonReader reader) throws IOException { - final Description description; - if (reader.peek() == JsonToken.STRING) { - String key = reader.nextString(); - description = (Description) reader.lookupInContext(key); - if (description == null) { - throw new IOException("Missing reference to: " + key); - } - } else { - reader.beginObject(); - String key = AbstractEvent.readStringOrNullProperty(reader, "id"); - String displayName = AbstractEvent.readStringOrNullProperty(reader, "displayName"); - String methodName = AbstractEvent.readStringOrNullProperty(reader, "methodName"); - String className = AbstractEvent.readStringOrNullProperty(reader, "className"); - - List children = new ArrayList<>(); - AbstractEvent.expectProperty(reader, "children").beginArray(); - while (reader.peek() != JsonToken.END_ARRAY) { - children.add(readDescription(reader)); - } - reader.endArray(); - - description = Description.createSuiteDescription(displayName, new Annotation [] {}); - - for (Description child : children) { - description.addChild(child); - } - - if (!Objects.equal(description.getMethodName(), methodName)) { - throw new IOException(String.format(Locale.ROOT, - "Insane, methodName does not match: %s, %s", description.getMethodName(), methodName)); - } - - if (!Objects.equal(description.getClassName(), className)) { - throw new IOException(String.format(Locale.ROOT, - "Insane, className does not match: %s, %s", description.getClassName(), className)); - } - - reader.registerInContext(key, description); - reader.endObject(); - } - - return description; - } - - private static String createId(Description description) { - return "ID#" + description.getDisplayName(); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/LowLevelHeartBeatEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/LowLevelHeartBeatEvent.java deleted file mode 100644 index 232e5efb..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/LowLevelHeartBeatEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -/** - * Heartbeat for reporting long running tests. - */ -public class LowLevelHeartBeatEvent { - public final long lastActivity, currentTime; - - public LowLevelHeartBeatEvent(long last, long currentTime) { - this.lastActivity = last; - this.currentTime = currentTime; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/QuitEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/QuitEvent.java deleted file mode 100644 index 6e9f58df..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/QuitEvent.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; - -/** - * Final message sent from the slave. Also signals orderly shutdown. - */ -public class QuitEvent extends AbstractEvent { - public QuitEvent() { - super(EventType.QUIT); - } - - @Override - public void serialize(JsonWriter writer) throws IOException { - writer.beginObject(); - writer.endObject(); - } - - @Override - public void deserialize(JsonReader reader) throws IOException { - reader.beginObject(); - reader.endObject(); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/RemoteEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/RemoteEvent.java deleted file mode 100644 index 2bc49bd8..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/RemoteEvent.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; - -public interface RemoteEvent extends IEvent { - void serialize(JsonWriter writer) throws IOException; - void deserialize(JsonReader reader) throws IOException; -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/Serializer.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/Serializer.java deleted file mode 100644 index 506fe40a..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/Serializer.java +++ /dev/null @@ -1,190 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.Closeable; -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.security.AccessController; -import java.security.PrivilegedExceptionAction; -import java.util.ArrayDeque; -import java.util.concurrent.atomic.AtomicBoolean; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; -import com.carrotsearch.ant.tasks.junit4.slave.SlaveMain; -import com.google.common.base.Charsets; - -/** - * Event serializer. - */ -public class Serializer implements Closeable { - /** - * Should help in ensuring the right order of stream writes. - */ - private final Object lock = new Object(); - - private Writer writer; - private JsonWriter jsonWriter; - - private final ArrayDeque events = new ArrayDeque(); - - private volatile Throwable doForcedShutdown; - private Thread forceCloseDaemon; - private AtomicBoolean forceCloseDaemonQuit = new AtomicBoolean(); - - public Serializer(OutputStream os) throws IOException { - this.writer = new OutputStreamWriter(os, Charsets.UTF_8); - this.jsonWriter = new JsonWriter(writer); - this.jsonWriter.setIndent(" "); - this.jsonWriter.setLenient(true); - this.forceCloseDaemon = new Thread("JUnit4-serializer-daemon") { - { - this.setDaemon(true); - } - - @Override - public void run() { - try { - while (!forceCloseDaemonQuit.get()) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // Ignore. - } - - Throwable reason = doForcedShutdown; - if (reason != null) { - try { - SlaveMain.warn("Unhandled exception in event serialization.", reason); - } finally { - Runtime.getRuntime().halt(0); - } - } - } - } catch (Throwable t) { - SlaveMain.warn("Unreachable code. Complete panic.", t); - } - } - - @Override - public UncaughtExceptionHandler getUncaughtExceptionHandler() { - return new UncaughtExceptionHandler() { - @Override - public void uncaughtException(Thread t, Throwable e) { - SlaveMain.warn("Unreachable code. Complete panic.", e); - } - }; - } - }; - - forceCloseDaemon.start(); - } - - public Serializer serialize(RemoteEvent event) throws IOException { - synchronized (lock) { - if (writer == null) { - throw new IOException("Serializer already closed."); - } - - // An alternative way of solving GH-92 and GH-110. Instead of buffering - // serialized json we emit directly. If a recursive call occurs to serialize() - // we enqueue the event and continue, serializing them in order. - events.addLast(event); - if (events.size() > 1) { - // SlaveMain.warn("Serializing " + event.getType() + " (postponed, " + events.size() + " in queue)", null); - return this; - } - - flushQueue(); - - return this; - } - } - - private final AtomicBoolean isFlushing = new AtomicBoolean(); - private void flushQueue() throws IOException { - if (!Thread.holdsLock(lock)) throw new IllegalStateException("Must be holding a lock on flushing."); - - if (isFlushing.getAndSet(true)) { - // We're already flushing, return. - // SlaveMain.warn("Flush queue already flushing", null); - return; - } - - // SlaveMain.warn("Flush queue start", null); - try { - while (!events.isEmpty()) { - if (writer == null) { - throw new IOException("Serializer already closed, with " + events.size() + " events on queue."); - } - - final RemoteEvent event = events.removeFirst(); - try { - // SlaveMain.warn("Serializing " + event.getType(), null); - AccessController.doPrivileged(new PrivilegedExceptionAction() { - @Override - public Void run() throws Exception { - jsonWriter.beginArray(); - jsonWriter.value(event.getType().name()); - event.serialize(jsonWriter); - jsonWriter.endArray(); - writer.write("\n\n"); - return null; - } - }); - } catch (Throwable t) { - doForcedShutdown = t; - break; - } - } - } finally { - isFlushing.set(false); - } - // SlaveMain.warn("Flush queue end", null); - - if (doForcedShutdown != null) { - // We can't do a stack bang here so any call is a risk of hitting SOE again. - while (true) { - try { - forceCloseDaemon.join(); - } catch (Throwable ignored) { - // Ignore. - } - } - } - } - - public Serializer flush() throws IOException { - synchronized (lock) { - if (writer != null) { - // SlaveMain.warn("flushing...", null); - flushQueue(); - writer.flush(); - } else { - // SlaveMain.warn("flushing failed (serializer closed)", null); - } - return this; - } - } - - public void close() throws IOException { - synchronized (lock) { - // SlaveMain.warn("closing...", null); - if (writer != null) { - serialize(new QuitEvent()); - flushQueue(); - - writer.close(); - writer = null; - } - forceCloseDaemonQuit.set(true); - } - - try { - forceCloseDaemon.interrupt(); - forceCloseDaemon.join(); - } catch (InterruptedException e) { - // Ignore, can't do much about it (shouldn't happen). - } - } -} \ No newline at end of file diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/SuiteCompletedEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/SuiteCompletedEvent.java deleted file mode 100644 index 0162e00e..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/SuiteCompletedEvent.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; - -import org.junit.runner.Description; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; - - -/** - * Serialized failure. - */ -public class SuiteCompletedEvent extends AbstractEventWithDescription { - private long startTimestamp; - private long executionTime; - - protected SuiteCompletedEvent() { - super(EventType.SUITE_COMPLETED); - } - - public SuiteCompletedEvent(Description description, long start, long duration) { - this(); - this.startTimestamp = start; - this.executionTime = duration; - setDescription(description); - } - - public long getExecutionTime() { - return executionTime; - } - - public long getStartTimestamp() { - return startTimestamp; - } - - @Override - public void serialize(JsonWriter writer) throws IOException { - writer.beginObject(); - - writer.name("description"); - super.serialize(writer); - - writer.name("startTimestamp").value(startTimestamp); - writer.name("executionTime").value(executionTime); - - writer.endObject(); - } - - @Override - public void deserialize(JsonReader reader) throws IOException { - reader.beginObject(); - - expectProperty(reader, "description"); - super.deserialize(reader); - - startTimestamp = readLongProperty(reader, "startTimestamp"); - executionTime = readLongProperty(reader, "executionTime"); - - reader.endObject(); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/SuiteFailureEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/SuiteFailureEvent.java deleted file mode 100644 index ee9c1bf5..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/SuiteFailureEvent.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import org.junit.runner.notification.Failure; - -/** - * Serialized failure. - */ -public class SuiteFailureEvent extends FailureEvent { - protected SuiteFailureEvent() { - super(EventType.SUITE_FAILURE); - } - - public SuiteFailureEvent(Failure failure) { - this(); - setFailure(failure); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/SuiteStartedEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/SuiteStartedEvent.java deleted file mode 100644 index 4399aa7c..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/SuiteStartedEvent.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; - -import org.junit.runner.Description; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; - - -/** - * Serialized failure. - */ -public class SuiteStartedEvent extends AbstractEventWithDescription { - private long startTimestamp; - - protected SuiteStartedEvent() { - super(EventType.SUITE_STARTED); - } - - public SuiteStartedEvent(Description description, long startTimestamp) { - this(); - setDescription(description); - this.startTimestamp = startTimestamp; - } - - public long getStartTimestamp() { - return startTimestamp; - } - - @Override - public void serialize(JsonWriter writer) throws IOException { - writer.beginObject(); - - writer.name("description"); - super.serialize(writer); - - writer.name("startTimestamp").value(startTimestamp); - - writer.endObject(); - } - - @Override - public void deserialize(JsonReader reader) throws IOException { - reader.beginObject(); - - expectProperty(reader, "description"); - super.deserialize(reader); - - startTimestamp = readLongProperty(reader, "startTimestamp"); - - reader.endObject(); - } -} \ No newline at end of file diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestFailureEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestFailureEvent.java deleted file mode 100644 index a5c63fbf..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestFailureEvent.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import org.junit.runner.notification.Failure; - -public class TestFailureEvent extends FailureEvent { - protected TestFailureEvent() { - super(EventType.TEST_FAILURE); - } - - public TestFailureEvent(Failure failure) { - this(); - setFailure(failure); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestFinishedEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestFinishedEvent.java deleted file mode 100644 index b4f1c7c3..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestFinishedEvent.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; - -import org.junit.runner.Description; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; - - -public class TestFinishedEvent extends AbstractEventWithDescription { - private long executionTime; - private long startTimestamp; - - protected TestFinishedEvent() { - super(EventType.TEST_FINISHED); - } - - public TestFinishedEvent(Description description, long timeMillis, long startTimestamp) { - this(); - this.executionTime = timeMillis; - this.startTimestamp = startTimestamp; - setDescription(description); - } - - public long getExecutionTime() { - return executionTime; - } - - public long getStartTimestamp() { - return startTimestamp; - } - - @Override - public void serialize(JsonWriter writer) throws IOException { - writer.beginObject(); - - writer.name("description"); - super.serialize(writer); - - writer.name("startTimestamp").value(startTimestamp); - writer.name("executionTime").value(executionTime); - - writer.endObject(); - } - - @Override - public void deserialize(JsonReader reader) throws IOException { - reader.beginObject(); - - expectProperty(reader, "description"); - super.deserialize(reader); - - startTimestamp = readLongProperty(reader, "startTimestamp"); - executionTime = readLongProperty(reader, "executionTime"); - - reader.endObject(); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestIgnoredAssumptionEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestIgnoredAssumptionEvent.java deleted file mode 100644 index b1b27bf7..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestIgnoredAssumptionEvent.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import org.junit.runner.notification.Failure; - -public class TestIgnoredAssumptionEvent extends FailureEvent { - protected TestIgnoredAssumptionEvent() { - super(EventType.TEST_IGNORED_ASSUMPTION); - } - - public TestIgnoredAssumptionEvent(Failure failure) { - this(); - setFailure(failure); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestIgnoredEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestIgnoredEvent.java deleted file mode 100644 index b0fd89be..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestIgnoredEvent.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; - -import org.junit.runner.Description; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; - -public class TestIgnoredEvent extends AbstractEventWithDescription { - private long startTimestamp; - private String cause; - - protected TestIgnoredEvent() { - super(EventType.TEST_IGNORED); - } - - public TestIgnoredEvent(Description description, String cause) { - this(); - setDescription(description); - - // For ignored tests, take the current time as the execution timestamp. - this.startTimestamp = System.currentTimeMillis(); - this.cause = cause; - } - - public long getStartTimestamp() { - return startTimestamp; - } - - public String getCause() { - return cause; - } - - @Override - public void serialize(JsonWriter writer) throws IOException { - writer.beginObject(); - - writer.name("description"); - super.serialize(writer); - - writer.name("startTimestamp").value(startTimestamp); - writer.name("cause").value(cause); - - writer.endObject(); - } - - @Override - public void deserialize(JsonReader reader) throws IOException { - reader.beginObject(); - - expectProperty(reader, "description"); - super.deserialize(reader); - - startTimestamp = readLongProperty(reader, "startTimestamp"); - cause = readStringOrNullProperty(reader, "cause"); - - reader.endObject(); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestStartedEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestStartedEvent.java deleted file mode 100644 index fd749e84..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/TestStartedEvent.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import org.junit.runner.Description; - -public class TestStartedEvent extends AbstractEventWithDescription { - protected TestStartedEvent() { - super(EventType.TEST_STARTED); - } - - public TestStartedEvent(Description description) { - this(); - setDescription(description); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedQuitEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedQuitEvent.java deleted file mode 100644 index 7060becf..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedQuitEvent.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events.aggregated; - - -/** - * An event dispatched after all slaves have completed their jobs. - */ -public class AggregatedQuitEvent { -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedResultEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedResultEvent.java deleted file mode 100644 index b0524458..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedResultEvent.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events.aggregated; - -import java.util.List; - -import org.junit.runner.Description; - -import com.carrotsearch.ant.tasks.junit4.ForkedJvmInfo; -import com.carrotsearch.ant.tasks.junit4.events.IEvent; -import com.carrotsearch.ant.tasks.junit4.events.mirrors.FailureMirror; - -/** - * Aggregated result from a suite or test. - */ -public interface AggregatedResultEvent { - public Description getDescription(); - public ForkedJvmInfo getSlave(); - public boolean isSuccessful(); - public List getFailures(); - List getEventStream(); - - public long getStartTimestamp(); - public long getExecutionTime(); -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedStartEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedStartEvent.java deleted file mode 100644 index 7bcce329..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedStartEvent.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events.aggregated; - - -/** - * An event dispatched before any slave starts. - */ -public class AggregatedStartEvent { - private int slaves; - private int suiteCount; - - public AggregatedStartEvent(int slaves, int suiteCount) { - this.slaves = slaves; - this.suiteCount = suiteCount; - } - - /** - * Number of slave processes. - */ - public int getSlaveCount() { - return slaves; - } - - /** - * Number of test suites, total. - */ - public int getSuiteCount() { - return suiteCount; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedSuiteResultEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedSuiteResultEvent.java deleted file mode 100644 index 74c1ed16..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedSuiteResultEvent.java +++ /dev/null @@ -1,310 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events.aggregated; - -import static com.carrotsearch.ant.tasks.junit4.events.EventType.*; - -import java.io.IOException; -import java.io.StringWriter; -import java.nio.charset.Charset; -import java.text.SimpleDateFormat; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Locale; - -import org.junit.runner.Description; - -import com.carrotsearch.ant.tasks.junit4.ForkedJvmInfo; -import com.carrotsearch.ant.tasks.junit4.events.EventType; -import com.carrotsearch.ant.tasks.junit4.events.FailureEvent; -import com.carrotsearch.ant.tasks.junit4.events.IDescribable; -import com.carrotsearch.ant.tasks.junit4.events.IEvent; -import com.carrotsearch.ant.tasks.junit4.events.IStreamEvent; -import com.carrotsearch.ant.tasks.junit4.events.JsonHelpers; -import com.carrotsearch.ant.tasks.junit4.events.mirrors.FailureMirror; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; -import com.carrotsearch.randomizedtesting.WriterOutputStream; - -public class AggregatedSuiteResultEvent implements AggregatedResultEvent { - private transient final ForkedJvmInfo slave; - - private final long executionTime; - private final long startTimestamp; - private final Description description; - - private final List tests; - private final List suiteFailures; - private final List eventStream; - - private final AggregatedSuiteStartedEvent startEvent; - - public AggregatedSuiteResultEvent( - AggregatedSuiteStartedEvent startEvent, - ForkedJvmInfo id, - Description description, - List suiteFailures, - List tests, - List eventStream, - long startTimestamp, - long executionTime) { - this.startEvent = startEvent; - this.slave = id; - this.tests = tests; - this.suiteFailures = suiteFailures; - this.description = description; - this.eventStream = eventStream; - this.executionTime = executionTime; - this.startTimestamp = startTimestamp; - } - - public AggregatedSuiteStartedEvent getStartEvent() { - return startEvent; - } - - public List getTests() { - return tests; - } - - @Override - public List getFailures() { - return Collections.unmodifiableList(suiteFailures); - } - - @Override - public boolean isSuccessful() { - if (!suiteFailures.isEmpty()) - return false; - - for (AggregatedTestResultEvent e : tests) { - if (!e.isSuccessful()) { - return false; - } - } - - return true; - } - - @Override - public List getEventStream() { - return eventStream; - } - - @Override - public ForkedJvmInfo getSlave() { - return slave; - } - - @Override - public Description getDescription() { - return description; - } - - /** - * Execution time in milliseconds. - */ - public long getExecutionTime() { - return executionTime; - } - - /** - * Execution start timestamp (on the slave). - */ - public long getStartTimestamp() { - return startTimestamp; - } - - /** - * The number of tests that have {@link TestStatus#FAILURE} and - * include assertion violations at suite level. - */ - public int getFailureCount() { - int count = 0; - for (AggregatedTestResultEvent t : getTests()) { - if (t.getStatus() == TestStatus.FAILURE) - count++; - } - for (FailureMirror m : getFailures()) { - if (m.isAssertionViolation()) - count++; - } - return count; - } - - /** - * The number of tests that have {@link TestStatus#ERROR} and - * include the suite-level errors. - */ - public int getErrorCount() { - int count = 0; - for (AggregatedTestResultEvent t : getTests()) { - if (t.getStatus() == TestStatus.ERROR) - count++; - } - - for (FailureMirror m : getFailures()) { - if (m.isErrorViolation()) - count++; - } - return count; - } - - /** - * Return the number of ignored or assumption-ignored tests. - */ - public int getIgnoredCount() { - int count = 0; - for (AggregatedTestResultEvent t : getTests()) { - if (t.getStatus() == TestStatus.IGNORED || - t.getStatus() == TestStatus.IGNORED_ASSUMPTION) { - count++; - } - } - return count; - } - - public void serialize(JsonWriter w, boolean outputStreams) throws IOException { - w.beginObject(); - - w.name("slave").value(getSlave().id); - w.name("startTimestamp").value(getStartTimestamp()); - - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.ROOT); - w.name("startTimestampDate").value(sdf.format(new Date(getStartTimestamp()))); - - w.name("executionTime").value(getExecutionTime()); - w.name("description"); - JsonHelpers.writeDescription(w, getDescription()); - - w.name("tests"); - w.beginArray(); - for (AggregatedTestResultEvent e : getTests()) { - serialize(w, sdf, e); - } - w.endArray(); - - w.name("suiteFailures"); - w.beginArray(); - for (FailureMirror m : getFailures()) { - serialize(w, m); - } - w.endArray(); - - w.name("executionEvents"); - w.beginArray(); - serializeEvents(w, outputStreams); - w.endArray(); - - w.endObject(); - } - - private void serialize(JsonWriter w, SimpleDateFormat sdf, AggregatedTestResultEvent e) throws IOException { - w.beginObject(); - w.name("slave").value(e.getSlave().id); - w.name("startTimestamp").value(e.getStartTimestamp()); - w.name("startTimestampDate").value(sdf.format(new Date(e.getStartTimestamp()))); - w.name("executionTime").value(e.getExecutionTime()); - w.name("description"); - JsonHelpers.writeDescription(w, e.getDescription()); - w.name("status").value(e.getStatus().name()); - - w.name("testFailures"); - w.beginArray(); - for (FailureMirror m : e.getFailures()) { - serialize(w, m); - } - w.endArray(); - - w.endObject(); - } - - private void serialize(JsonWriter w, FailureMirror e) throws IOException { - w.beginObject(); - w.name("throwableClass").value(e.getThrowableClass()); - w.name("throwableString").value(e.getThrowableString()); - w.name("stackTrace").value(e.getTrace()); - - String throwableKind; - if (e.isAssertionViolation()) { - throwableKind = "assertion"; - } else if (e.isErrorViolation()) { - throwableKind = "error"; - } else if (e.isAssumptionViolation()) { - throwableKind = "assumption"; - } else { - throwableKind = "unknown"; - } - w.name("kind").value(throwableKind); - w.endObject(); - } - - private void serializeEvents(JsonWriter w, boolean outputStreams) throws IOException { - final Charset charset = getSlave().getCharset(); - int lineBuffer = 160; - final StringWriter out = new StringWriter(); - final StringWriter err = new StringWriter(); - WriterOutputStream stdout = new WriterOutputStream(out, charset, lineBuffer, false); - WriterOutputStream stderr = new WriterOutputStream(err, charset, lineBuffer, false); - for (IEvent evt : getEventStream()) { - try { - switch (evt.getType()) { - case SUITE_FAILURE: - case TEST_IGNORED_ASSUMPTION: - case TEST_IGNORED: - case TEST_STARTED: - case TEST_FINISHED: - case TEST_FAILURE: - flushBoth(w, out, err, stdout, stderr); - - w.beginObject(); - w.name("event").value(evt.getType().toString()); - w.name("description"); - JsonHelpers.writeDescription(w, ((IDescribable) evt).getDescription()); - - if (evt instanceof FailureEvent) { - w.name("failure"); - ((FailureEvent) evt).serialize(w); - } - w.endObject(); - break; - - // Flush streams only if there's interwoven output between them. - - case APPEND_STDOUT: - if (outputStreams) { - flush(APPEND_STDERR, w, stderr, err); - ((IStreamEvent) evt).copyTo(stdout); - } - break; - - case APPEND_STDERR: - if (outputStreams) { - flush(APPEND_STDOUT, w, stdout, out); - ((IStreamEvent) evt).copyTo(stderr); - } - break; - - default: - break; - } - } catch (IOException ex) { - // Ignore. - } - } - flushBoth(w, out, err, stdout, stderr); - } - - public void flushBoth(JsonWriter w, StringWriter out, StringWriter err, WriterOutputStream stdout, WriterOutputStream stderr) throws IOException { - flush(APPEND_STDOUT, w, stdout, out); - flush(APPEND_STDERR, w, stderr, err); - } - - private void flush(EventType evt, JsonWriter w, WriterOutputStream wos, StringWriter out) throws IOException { - wos.flush(); - if (out.getBuffer().length() > 0) { - w.beginObject(); - w.name("event").value(evt.toString()); - w.name("content").value(out.getBuffer().toString()); - out.getBuffer().setLength(0); - w.endObject(); - } - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedSuiteStartedEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedSuiteStartedEvent.java deleted file mode 100644 index e58e930d..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedSuiteStartedEvent.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events.aggregated; - -import com.carrotsearch.ant.tasks.junit4.ForkedJvmInfo; -import com.carrotsearch.ant.tasks.junit4.events.SuiteStartedEvent; - -public class AggregatedSuiteStartedEvent { - private transient final ForkedJvmInfo slave; - private SuiteStartedEvent suiteStartedEvent; - - public AggregatedSuiteStartedEvent(ForkedJvmInfo id, SuiteStartedEvent e) { - this.slave = id; - this.suiteStartedEvent = e; - } - - public SuiteStartedEvent getSuiteStartedEvent() { - return suiteStartedEvent; - } - - public ForkedJvmInfo getSlave() { - return slave; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedTestResultEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedTestResultEvent.java deleted file mode 100644 index 5025e8a4..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatedTestResultEvent.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events.aggregated; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.junit.runner.Description; - -import com.carrotsearch.ant.tasks.junit4.ForkedJvmInfo; -import com.carrotsearch.ant.tasks.junit4.events.IEvent; -import com.carrotsearch.ant.tasks.junit4.events.TestFinishedEvent; -import com.carrotsearch.ant.tasks.junit4.events.mirrors.FailureMirror; - -/** - * A single test's execution information. - */ -public class AggregatedTestResultEvent implements AggregatedResultEvent { - private final Description suite; - private final Description description; - private final ForkedJvmInfo slave; - - private TestStatus status = TestStatus.OK; - private List failures = new ArrayList<>(); - - private List eventStream; - - private boolean hasFailures; - private boolean hasErrors; - private boolean hasIgnoredAssumptions; - - /** If {@link #status} is {@link TestStatus#IGNORED} then this contains the cause. */ - private String ignoreCause; - - /** Associated {@link TestFinishedEvent}. */ - private TestFinishedEvent testFinishedEvent; - - public AggregatedTestResultEvent(ForkedJvmInfo slave, Description suiteDescription, Description description) { - this.description = description; - this.suite = suiteDescription; - this.slave = slave; - } - - @Override - public Description getDescription() { - return description; - } - - @Override - public boolean isSuccessful() { - return status == TestStatus.OK || - status == TestStatus.IGNORED || - status == TestStatus.IGNORED_ASSUMPTION; - } - - public Description getSuiteDescription() { - return suite; - } - - @Override - public ForkedJvmInfo getSlave() { - return slave; - } - - @Override - public List getFailures() { - return Collections.unmodifiableList(failures); - } - - /** - * Execution time in millis. - */ - public long getExecutionTime() { - return testFinishedEvent.getExecutionTime(); - } - - /** - * Execution start timestamp (on the slave). - */ - public long getStartTimestamp() { - return testFinishedEvent.getStartTimestamp(); - } - - /** - * Raw {@link IEvent} stream received during the duration of this test. - */ - @Override - public List getEventStream() { - if (eventStream == null) - throw new RuntimeException("Unfinished test?" + suite + ", " + description); - return Collections.unmodifiableList(eventStream); - } - - /** - * Exit status for this test. - */ - public TestStatus getStatus() { - return status; - } - - public String getCauseForIgnored() { - return ignoreCause; - } - - void setIgnored(String cause) { - assert status == TestStatus.OK; - status = TestStatus.IGNORED; - ignoreCause = cause; - } - - void addFailure(FailureMirror failure) { - failures.add(failure); - - hasFailures |= failure.isAssertionViolation(); - hasIgnoredAssumptions |= failure.isAssumptionViolation(); - hasErrors |= failure.isErrorViolation(); - } - - void complete(TestFinishedEvent e, List eventStream) { - this.eventStream = eventStream; - this.testFinishedEvent = e; - - if (hasErrors) { - status = TestStatus.ERROR; - } else if (hasFailures) { - status = TestStatus.FAILURE; - } else if (hasIgnoredAssumptions) { - status = TestStatus.IGNORED_ASSUMPTION; - } - } - - /** - * This isn't a nice hack but it allows associating {@link TestFinishedEvent} and - * {@link AggregatedTestResultEvent} by identity. = - */ - public TestFinishedEvent getTestFinishedEvent() { - return testFinishedEvent; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatingListener.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatingListener.java deleted file mode 100644 index cb4e1ba8..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/AggregatingListener.java +++ /dev/null @@ -1,184 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events.aggregated; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.List; - -import org.junit.runner.Description; -import org.junit.runner.JUnitCore; - -import com.carrotsearch.ant.tasks.junit4.ForkedJvmInfo; -import com.carrotsearch.ant.tasks.junit4.events.*; -import com.carrotsearch.ant.tasks.junit4.events.mirrors.FailureMirror; -import com.google.common.collect.Lists; -import com.google.common.eventbus.EventBus; -import com.google.common.eventbus.Subscribe; - -/** - * Aggregates atomic events from {@link JUnitCore} to higher-level events that - * contain a full summary of a given test's execution. Simplifies reporting - * logic. - */ -public class AggregatingListener { - private EventBus target; - private ForkedJvmInfo slave; - - private AggregatedSuiteStartedEvent startEvent; - private Description lastSuite; - private List suiteFailures; - - private ArrayDeque tests; - private ArrayList eventStream; - private int testStartStreamMarker; - - /** - * @param target Which event bus to repost aggregated events to? - */ - public AggregatingListener(EventBus target, ForkedJvmInfo slave) { - this.target = target; - this.slave = slave; - } - - @Subscribe - public void appendToEventStream(IEvent e) { - if (eventStream != null) { - switch (e.getType()) { - case APPEND_STDOUT: - case APPEND_STDERR: - target.post(new PartialOutputEvent(slave, e)); - // fall through. - case TEST_STARTED: - case TEST_FINISHED: - case TEST_FAILURE: - case TEST_IGNORED: - case TEST_IGNORED_ASSUMPTION: - case SUITE_FAILURE: - eventStream.add(e); - break; - default: - break; - } - } - } - - /** - * Detect slow heartbeat (long time without any events) from the forked JVM. - */ - @Subscribe - public void slowHeartBeat(LowLevelHeartBeatEvent e) { - Description current = null; - if (tests != null && !tests.isEmpty()) { - current = tests.peek().getDescription(); - } else { - current = lastSuite; // may be null. - } - - target.post(new HeartBeatEvent( - slave, - current, - e.lastActivity, - e.currentTime - )); - } - - @Subscribe - public void receiveSuiteStart(SuiteStartedEvent e) { - assert lastSuite == null; - assert startEvent == null; - - tests = new ArrayDeque(); - suiteFailures = new ArrayList<>(); - eventStream = new ArrayList<>(); - lastSuite = e.getDescription(); - startEvent = new AggregatedSuiteStartedEvent(slave, e); - - target.post(startEvent); - } - - @Subscribe - public void receiveTestStart(TestStartedEvent e) { - tests.push(new AggregatedTestResultEvent(slave, lastSuite, e.getDescription())); - testStartStreamMarker = eventStream.size(); - } - - @Subscribe - public void receiveTestIgnored(TestIgnoredEvent e) { - Description description = e.getDescription(); - if (description.getMethodName() == null) { - // This is how JUnit signals ignored suites: by passing a Description that is a - // suite but has no children (so isSuite() returns false...). - return; - } - - // Test ignored is not emitted within start...end space with default JUnit runners. - // Try to correct it here. - if (!tests.isEmpty() && description.equals(tests.peek().getDescription())) { - tests.peek().setIgnored(e.getCause()); - } else { - receiveTestStart(new TestStartedEvent(description)); - tests.peek().setIgnored(e.getCause()); - receiveTestEnd(new TestFinishedEvent(description, 0, e.getStartTimestamp())); - } - } - - @Subscribe - public void receiveTestAssumptionIgnored(TestIgnoredAssumptionEvent e) { - Description description = e.getDescription(); - if (description.getMethodName() == null) { - // Don't record suite-level assumptions. They result in ignored - // tests that RandomizedRunner reports and JUnit runner ignores - // as if a suite didn't have any tests. - return; - } - - assert e.getDescription().equals(tests.peek().getDescription()); - tests.peek().addFailure(e.getFailure()); - } - - @Subscribe - public void receiveTestFailure(TestFailureEvent e) { - Description description = e.getDescription(); - if (description.getMethodName() == null) { - suiteFailures.add(e.getFailure()); - return; - } - - tests.peek().addFailure(e.getFailure()); - } - - @Subscribe - public void receiveTestEnd(TestFinishedEvent e) { - assert e.getDescription().equals(tests.peek().getDescription()); - tests.peek().complete(e, new ArrayList<>(eventStream.subList(testStartStreamMarker, eventStream.size()))); - target.post(tests.peek()); - } - - @Subscribe - public void receiveSuiteEnd(SuiteCompletedEvent e) { - target.post(new AggregatedSuiteResultEvent( - startEvent, - slave, - e.getDescription(), - suiteFailures, - Lists.newArrayList(tests.descendingIterator()), - eventStream, - e.getStartTimestamp(), - e.getExecutionTime())); - this.suiteFailures = null; - this.lastSuite = null; - this.startEvent = null; - this.tests = null; - this.eventStream = null; - } - - @Subscribe - public void receiveSuiteFailure(SuiteFailureEvent e) { - if (suiteFailures != null) { - suiteFailures.add(e.getFailure()); - } else { - receiveSuiteStart(new SuiteStartedEvent(e.getDescription(), System.currentTimeMillis())); - suiteFailures.add(e.getFailure()); - receiveSuiteEnd(new SuiteCompletedEvent(e.getDescription(), System.currentTimeMillis(), 0)); - } - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/ChildBootstrap.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/ChildBootstrap.java deleted file mode 100644 index 1a7a20c6..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/ChildBootstrap.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events.aggregated; - -import com.carrotsearch.ant.tasks.junit4.ForkedJvmInfo; - -public class ChildBootstrap { - public final ForkedJvmInfo childInfo; - - public ChildBootstrap(ForkedJvmInfo childInfo) { - this.childInfo = childInfo; - } - - public ForkedJvmInfo getSlave() { - return childInfo; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/HeartBeatEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/HeartBeatEvent.java deleted file mode 100644 index d37c3c46..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/HeartBeatEvent.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events.aggregated; - -import org.junit.runner.Description; - -import com.carrotsearch.ant.tasks.junit4.ForkedJvmInfo; - -/** - * High level heartbeat event issued to report listeners when a forked JVM - * does not repond for a longer while. The {@link #getDescription} method should - * return an approximate place where the forked JVM is at the moment, but this is - * not guaranteed (and may be null). - */ -public final class HeartBeatEvent { - private final ForkedJvmInfo slave; - private final Description description; - private final long lastActivity; - private final long currentTime; - - public HeartBeatEvent(ForkedJvmInfo slave, Description description, long lastActivity, long currentTime) { - this.slave = slave; - this.description = description; - this.lastActivity = lastActivity; - this.currentTime = currentTime; - } - - public Description getDescription() { - return description; - } - - public long getCurrentTime() { - return currentTime; - } - - public long getLastActivity() { - return lastActivity; - } - - public long getNoEventDuration() { - return getCurrentTime() - getLastActivity(); - } - - public ForkedJvmInfo getSlave() { - return slave; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/JvmOutputEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/JvmOutputEvent.java deleted file mode 100644 index 6ca98b36..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/JvmOutputEvent.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events.aggregated; - -import java.io.File; - -import com.carrotsearch.ant.tasks.junit4.ForkedJvmInfo; - -/** - * An event emitted when there was any unexpected JVM output - * from the forked JVM. This can happen for internal JVM logs - * or crash dumps that bypass System.* streams. - */ -public class JvmOutputEvent { - public final ForkedJvmInfo childInfo; - public final File jvmOutput; - - public JvmOutputEvent(ForkedJvmInfo childInfo, File jvmOutput) { - this.childInfo = childInfo; - this.jvmOutput = jvmOutput; - } - - public ForkedJvmInfo getSlave() { - return childInfo; - } - - public File getJvmOutputFile() { - return jvmOutput; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/PartialOutputEvent.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/PartialOutputEvent.java deleted file mode 100644 index 6b778ca3..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/PartialOutputEvent.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events.aggregated; - -import com.carrotsearch.ant.tasks.junit4.ForkedJvmInfo; -import com.carrotsearch.ant.tasks.junit4.events.IEvent; -import com.carrotsearch.ant.tasks.junit4.events.IStreamEvent; - -/** - * Partial output emitted from a given slave. - */ -public class PartialOutputEvent { - private ForkedJvmInfo slave; - private IEvent event; - - public PartialOutputEvent(ForkedJvmInfo slave, IEvent e) { - assert e instanceof IStreamEvent; - this.slave = slave; - this.event = e; - } - - public ForkedJvmInfo getSlave() { - return slave; - } - - public IEvent getEvent() { - return event; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/TestStatus.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/TestStatus.java deleted file mode 100644 index 0cb40156..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/aggregated/TestStatus.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events.aggregated; - -public enum TestStatus { - OK, - - IGNORED, - IGNORED_ASSUMPTION, - - FAILURE, - ERROR, -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/mirrors/FailureMirror.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/mirrors/FailureMirror.java deleted file mode 100644 index 0dbd73c3..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/events/mirrors/FailureMirror.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events.mirrors; - -import org.junit.internal.AssumptionViolatedException; -import org.junit.runner.Description; -import org.junit.runner.notification.Failure; - -/** - * A type-safe mirror of {@link Failure}. - */ -public class FailureMirror { - private String message; - private String trace; - private String throwableString; - private String throwableClass; - - /** Was [@link Failure} an instance of an {@link AssertionError}? */ - private boolean assertionViolation; - private boolean assumptionViolation; - - /** The test {@link Description} that caused this failure. */ - private Description description; - - public FailureMirror(Description description, - String message, - String trace, - String throwableString, - String throwableClass, - boolean assertionViolation, - boolean assumptionViolation) { - this.message = message; - this.trace = trace; - this.throwableString = throwableString; - this.throwableClass = throwableClass; - this.assertionViolation = assertionViolation; - this.assumptionViolation = assumptionViolation; - this.description = description; - } - - public FailureMirror(Failure failure) { - this.message = failure.getMessage(); - this.description = failure.getDescription(); - this.trace = failure.getTrace(); - - final Throwable cause = failure.getException(); - this.assertionViolation = cause instanceof AssertionError; - this.assumptionViolation = cause instanceof AssumptionViolatedException; - this.throwableString = cause.toString(); - this.throwableClass = cause.getClass().getName(); - } - - public String getMessage() { - return message; - } - - public String getThrowableString() { - return throwableString; - } - - public Description getDescription() { - return description; - } - - public String getTrace() { - return trace; - } - - public boolean isAssumptionViolation() { - return assumptionViolation; - } - - public boolean isAssertionViolation() { - return assertionViolation; - } - - public boolean isErrorViolation() { - return isAssertionViolation() == false && - isAssumptionViolation() == false; - } - - public String getThrowableClass() { - return throwableClass; - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/gson/stream/IOContext.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/gson/stream/IOContext.java deleted file mode 100644 index 52a6959d..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/gson/stream/IOContext.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.gson.stream; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -public class IOContext { - private Map context = new HashMap(); - - public void registerInContext(Object key, Object value) throws IOException { - if (inContext(key)) { - throw new IOException("Key already registered: " + key); - } - if (value == null) { - throw new IOException("Value cannot be null for key: " + key); - } - context.put(key, value); - } - - public Object lookupInContext(Object key) { - return context.get(key); - } - - public boolean inContext(Object key) { - return context.containsKey(key); - } -} diff --git a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/gson/stream/JsonReader.java b/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/gson/stream/JsonReader.java deleted file mode 100644 index 5963da18..00000000 --- a/junit4-ant/src/main/java/com/carrotsearch/ant/tasks/junit4/gson/stream/JsonReader.java +++ /dev/null @@ -1,1597 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.carrotsearch.ant.tasks.junit4.gson.stream; - -import java.io.Closeable; -import java.io.EOFException; -import java.io.IOException; -import java.io.Reader; - -/** - * Reads a JSON (RFC 4627) - * encoded value as a stream of tokens. This stream includes both literal - * values (strings, numbers, booleans, and nulls) as well as the begin and - * end delimiters of objects and arrays. The tokens are traversed in - * depth-first order, the same order that they appear in the JSON document. - * Within JSON objects, name/value pairs are represented by a single token. - * - *

Parsing JSON

- * To create a recursive descent parser for your own JSON streams, first create - * an entry point method that creates a {@code JsonReader}. - * - *

Next, create handler methods for each structure in your JSON text. You'll - * need a method for each object type and for each array type. - *

    - *
  • Within array handling methods, first call {@link - * #beginArray} to consume the array's opening bracket. Then create a - * while loop that accumulates values, terminating when {@link #hasNext} - * is false. Finally, read the array's closing bracket by calling {@link - * #endArray}. - *
  • Within object handling methods, first call {@link - * #beginObject} to consume the object's opening brace. Then create a - * while loop that assigns values to local variables based on their name. - * This loop should terminate when {@link #hasNext} is false. Finally, - * read the object's closing brace by calling {@link #endObject}. - *
- *

When a nested object or array is encountered, delegate to the - * corresponding handler method. - * - *

When an unknown name is encountered, strict parsers should fail with an - * exception. Lenient parsers should call {@link #skipValue()} to recursively - * skip the value's nested tokens, which may otherwise conflict. - * - *

If a value may be null, you should first check using {@link #peek()}. - * Null literals can be consumed using either {@link #nextNull()} or {@link - * #skipValue()}. - * - *

Example

- * Suppose we'd like to parse a stream of messages such as the following:
{@code
- * [
- *   {
- *     "id": 912345678901,
- *     "text": "How do I read a JSON stream in Java?",
- *     "geo": null,
- *     "user": {
- *       "name": "json_newb",
- *       "followers_count": 41
- *      }
- *   },
- *   {
- *     "id": 912345678902,
- *     "text": "@json_newb just use JsonReader!",
- *     "geo": [50.454722, -104.606667],
- *     "user": {
- *       "name": "jesse",
- *       "followers_count": 2
- *     }
- *   }
- * ]}
- * This code implements the parser for the above structure:
{@code
- *
- *   public List readJsonStream(InputStream in) throws IOException {
- *     JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8"));
- *     try {
- *       return readMessagesArray(reader);
- *     } finally {
- *       reader.close();
- *     }
- *   }
- *
- *   public List readMessagesArray(JsonReader reader) throws IOException {
- *     List messages = new ArrayList();
- *
- *     reader.beginArray();
- *     while (reader.hasNext()) {
- *       messages.add(readMessage(reader));
- *     }
- *     reader.endArray();
- *     return messages;
- *   }
- *
- *   public Message readMessage(JsonReader reader) throws IOException {
- *     long id = -1;
- *     String text = null;
- *     User user = null;
- *     List geo = null;
- *
- *     reader.beginObject();
- *     while (reader.hasNext()) {
- *       String name = reader.nextName();
- *       if (name.equals("id")) {
- *         id = reader.nextLong();
- *       } else if (name.equals("text")) {
- *         text = reader.nextString();
- *       } else if (name.equals("geo") && reader.peek() != JsonToken.NULL) {
- *         geo = readDoublesArray(reader);
- *       } else if (name.equals("user")) {
- *         user = readUser(reader);
- *       } else {
- *         reader.skipValue();
- *       }
- *     }
- *     reader.endObject();
- *     return new Message(id, text, user, geo);
- *   }
- *
- *   public List readDoublesArray(JsonReader reader) throws IOException {
- *     List doubles = new ArrayList();
- *
- *     reader.beginArray();
- *     while (reader.hasNext()) {
- *       doubles.add(reader.nextDouble());
- *     }
- *     reader.endArray();
- *     return doubles;
- *   }
- *
- *   public User readUser(JsonReader reader) throws IOException {
- *     String username = null;
- *     int followersCount = -1;
- *
- *     reader.beginObject();
- *     while (reader.hasNext()) {
- *       String name = reader.nextName();
- *       if (name.equals("name")) {
- *         username = reader.nextString();
- *       } else if (name.equals("followers_count")) {
- *         followersCount = reader.nextInt();
- *       } else {
- *         reader.skipValue();
- *       }
- *     }
- *     reader.endObject();
- *     return new User(username, followersCount);
- *   }}
- * - *

Number Handling

- * This reader permits numeric values to be read as strings and string values to - * be read as numbers. For example, both elements of the JSON array {@code - * [1, "1"]} may be read using either {@link #nextInt} or {@link #nextString}. - * This behavior is intended to prevent lossy numeric conversions: double is - * JavaScript's only numeric type and very large values like {@code - * 9007199254740993} cannot be represented exactly on that platform. To minimize - * precision loss, extremely large values should be written and read as strings - * in JSON. - * - *

Non-Execute Prefix

- * Web servers that serve private data using JSON may be vulnerable to Cross-site - * request forgery attacks. In such an attack, a malicious site gains access - * to a private JSON file by executing it with an HTML {@code - - - - - - diff --git a/junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/js/jquery-1.7.1.min.js b/junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/js/jquery-1.7.1.min.js deleted file mode 100644 index 198b3ff0..00000000 --- a/junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/js/jquery-1.7.1.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v1.7.1 jquery.com | jquery.org/license */ -(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"":"")+""),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;g=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
a",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="
"+""+"
",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="
t
",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="
",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")}; -f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&i.push({elem:this,matches:d.slice(e)});for(j=0;j0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function() -{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file diff --git a/junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/js/jquery.pathchange.js b/junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/js/jquery.pathchange.js deleted file mode 100644 index 5e878032..00000000 --- a/junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/js/jquery.pathchange.js +++ /dev/null @@ -1,111 +0,0 @@ -// Plugin that provides a "pathchange" event on the window object, notifying an application when the URL changes -// This is accomplished by watching the hash, using the hashchange event from HTML5 or a polling interval in older browsers. -// In addition, in some modern browsers, HTML5 History Management is used to support changing the URL's path without reloading the page. -// This plugin also provides a method to navigate to a URL safely, that will use HTML5 History Management to avoid a page load. -// Everything degrades gracefully, and supports RESTful client development. - -// Browser Support: -// Chrome - Any recent version of Chrome supports everything. -// Safari - Any recent version of Safari supports everything. -// Firefox - Newer versions of Firefox support the hashchange event -// Firefox 4 betas also support HTML5 History Management -// Internet Explorer - IE8 supports hashchange -// IE6 and 7 receive inferior hashchange support through a polling interval. -// Others - Other modern browsers probably support some subset of features. - -// This plugin was authored by Ben Cherry (bcherry@gmail.com), and is released under an MIT License (do what you want with it). -// Some of the code in this plugin was adapted from Modernizr, which is also available under an MIT License. -(function($) { - // can use $(window).bind("pathchange", fn) or $(window).pathchange(fn) - $.fn.pathchange = function(handler) { - return handler ? this.bind("pathchange", handler) : this.trigger("pathchange"); - }; - - var my = $.pathchange = { - // default options - options: { - useHistory: true, // whether we use HTML5 History Management to change the current path - useHashchange: true, // whether we use HTML5 Hashchange to listen to the URL hash - pollingInterval: 250, // when using Hashchange in browsers without it, how often to poll the hash (in ms) - interceptLinks: true, // do we intercept all relative links to avoid some page reloads? - disableHashLinks: true // do we ensure all links with href=# are not followed (this would mess with our history)? - }, - - // call this once when your app is ready to use pathchange - init: function(options) { - var lastHash; - $.extend(my.options, options); - - // Listen to the HTML5 "popstate" event, if supported and desired - if (my.options.useHistory && my.detectHistorySupport()) { - $(window).bind("popstate", function(e) { - $(window).trigger("pathchange"); - }); - } - - // Listen to the HTML5 "hashchange" event, if supported and desired - if (my.options.useHashchange) { - $(window).bind("hashchange", function(e) { - $(window).trigger("pathchange"); - }); - - // Hashchange support for older browsers (IE6/7) - if (!my.detectHashchangeSupport()) { - lastHash = window.location.hash; - setInterval(function() { - if (lastHash !== window.location.hash) { - $(window).trigger("hashchange"); - lastHash = window.location.hash; - } - }, my.options.pollingInterval); - } - } - - // Intercept all relative links on the page, to avoid unneccesary page refreshes - if (my.options.interceptLinks) { - $("body").delegate("a[href^=/]", "click", function(e) { - my.changeTo($(this).attr("href")); - e.preventDefault(); - }); - } - - // Ensure all the href=# links on the page don't mess with things - if (my.options.disableHashLinks) { - $("body").delegate("a[href=#]", "click", function(e) { - e.preventDefault(); - }); - } - }, - - // Call to manually navigate the app somewhere - changeTo: function(path) { - // If we're using History Management, just push an entry - if (my.options.useHistory && my.detectHistorySupport()) { - window.history.pushState(null, null, path); - $(window).trigger("pathchange"); - } else { - // Make sure there's a hash (going from foo.com#bar to foo.com would trigger a reload in Firefox, sadly) - if (path.indexOf("#") < 0) { - path += "#"; - } - // Otherwise, navigate to the new URL. Might reload the browser. Might trigger a hashchange. - window.location.href = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":" + window.location.port : "") + path; - } - }, - - // Simple feature detection for History Management (borrowed from Modernizr) - detectHistorySupport: function() { - return !!(window.history && history.pushState); - }, - - // Simple feature detection for hashchange (adapted from Modernizr) - detectHashchangeSupport: function() { - var isSupported = "onhashchange" in window; - if (!isSupported && window.setAttribute) { - window.setAttribute("onhashchange", "return;"); - isSupported = typeof window.onhashchange === "function"; - } - return isSupported; - } - }; -}(jQuery)); \ No newline at end of file diff --git a/junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/js/script.js b/junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/js/script.js deleted file mode 100644 index d5216e82..00000000 --- a/junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/js/script.js +++ /dev/null @@ -1,1240 +0,0 @@ -(function($) { - Array.prototype.peek = function() { - return this[this.length - 1]; - }; - - // Constants - var OK = "OK"; - var FAILURE = "FAILURE"; - var ERROR = "ERROR"; - var IGNORED = "IGNORED"; - var IGNORED_ASSUMPTION = "IGNORED_ASSUMPTION"; - - var statusOrder = [ OK, IGNORED_ASSUMPTION, IGNORED, ERROR, FAILURE ]; - var statusLabels = { - OK: "OK", - FAILURE: "FAIL", - ERROR: "ERROR", - IGNORED: "IGNORED", - IGNORED_ASSUMPTION: "IGNORED" - }; - - // Handles for UI elements - var $table, $search, $tools, $console; - - // Data model - var data, aggregates, project; - - // Application state encoded and parsed from the URL - var state = { - view: "", - order: { - columns: [], - ascendings: [] - }, - search: "", - filter: { - pass: true, - ignored: true, - error: true, - fail: true, - withoutoutput: false - }, - highlight: "", - - encode: function() { - var url = []; - process(null, this); - return url.join("/"); - - function process(property, value) { - if ($.isFunction(value)) { - return; - } - - if ($.isArray(value)) { - $.each(value, function(i, v) { - process(property + "[]", v); - }); - } else if ($.isPlainObject(value)) { - $.each(value, function(key, v) { - process((property ? property + "." : "") + key, v); - }); - } else { - url.push(property, encodeURIComponent(value)); - } - } - }, - - decode: function(string) { - var s = string || window.location.href; - var split = (s.split("#")[1] || "").split("/"); - var decoded = { }; - outer: for (var i = 0; i < split.length / 2; i++) { - var path = decodeURIComponent(split[i*2] || "").split(/\./); - var property = path.shift(); - var target = decoded; - while (path.length > 0) { - if (!$.isPlainObject(target)) { - break outer; - } - if (typeof target[property] == 'undefined') { - target[property] = { }; - } - target = target[property]; - property = path.shift(); - } - - var val = convert(decodeURIComponent(split[i*2 + 1] || "")); - if (property.indexOf("[]") > 0) { - property = property.replace(/[\[\]]/g, ""); - if (typeof target[property] == 'undefined') { - target[property] = []; - } - target[property].push(val); - } else { - target[property] = val; - } - } - delete decoded.encode; - delete decoded.decode; - delete decoded.push; - $.extend(this, decoded); - - function convert(val) { - if (val == "false") { - return false; - } else if (val == "true") { - return true; - } else { - return val; - } - } - }, - - push: function() { - var prev = window.location.hash; - window.location.hash = "#" + this.encode(); - return prev != window.location.hash; - } - }; - var wasDrilldown = false; - - // This function will be called by the JSONP data file - window.testData = function(d) { - data = d.suites; - project = d.junit4; - - var descriptionsById = { }; - - // Index descriptions by id - var htmlId = 0; - for (var i = 0; i < data.length; i++) { - mapDescriptions(data[i].description.children); - } - - // A hack to handle suite-level errors: copy them to the tests array. - eachSuite(data, function(suite) { - if (suite.suiteFailures.length > 0) { - $.each(suite.suiteFailures, function(i, failure) { - suite.tests.push({ - slave: suite.slave, - startTimestamp: suite.startTimestamp, - executionTime: 1, - description: { - methodName: "", - className: suite.description.className - }, - status: ERROR, - testFailures: [ failure ] - }); - }); - } - }); - - // Link object descriptions, split method names into semantic parts - eachTest(data, function (test) { - var description = descriptionsById[test.description]; - if (description) { - test.description = description; - } else { - description = test.description; - } - - description.packageClassName = description.className; - - var methodSplit = description.methodName.split(" "); - description.methodName = methodSplit[0]; - description.methodExtras = methodSplit[1]; - - description.packageClassMethodName = description.className + "." + description.methodName; - - var classSplit = description.className.split("\."); - description.className = classSplit.pop(); - description.packageName = classSplit.join("."); - }); - - // Link descriptions in the event list. - eachSuite(data, function(suite) { - var testsById = map(suite.tests, function(t) { return t.description.id; }); - - var hasOutput = false, hasErrors = false; - $.each(suite.executionEvents, function(j, evt) { - if ("description" in evt) { - if (testsById[evt.description]) { - evt.test = testsById[evt.description]; - } - evt.description = descriptionsById[evt.description]; - } - switch (evt.event) { - case "TEST_STARTED": - hasOutput = false; - break; - - case "APPEND_STDOUT": - hasOutput = true; - break; - - case "APPEND_STDERR": - hasErrors = true; - break; - - case "TEST_FINISHED": - evt.test.hasOutput = hasOutput; - evt.test.hasErrors = hasErrors; - hasOutput = false; - hasErrors = false; - break; - } - }); - }); - - return; - - function mapDescriptions(children) { - for (var j = 0; j < children.length; j++) { - var child = children[j]; - if (typeof child == 'object') { - descriptionsById[children[j].id] = child; - - // Assign a short HTML id to the element. We could use the one - // generated by the runner, but we'd have to map prohibited - // characters, the id would be very long to. - child.htmlId = htmlId; - htmlId++; - if (child.children) { - mapDescriptions(child.children); - } - } else { - children[j] = descriptionsById[child]; - } - } - } - } - - // Table definitions - var tables = (function() { - // Common columns of the aggregated view tables - var aggregatedViewColumns = [ - column("signature", "string", "", true), - numericColumn("count", "Tests"), - { - id: "result", - label: "Result", - sortable: true, - sorting: function(a, b) { - for (var i = 0; i < statusOrder.length; i++) { - var s = statusOrder[statusOrder.length - i]; - if ((a.statuses[s] || 0) != (b.statuses[s] || 0)) { - return (a.statuses[s] || 0) - (b.statuses[s] || 0); - } - } - return 0; - }, - renderer: function(value, html) { - html.push(statusbar(value.statuses, value.total)); - }, - type: "result" - }, - numericColumn("pass", "Pass"), - numericColumn("ignored", "Ign"), - numericColumn("error", "Err"), - numericColumn("failed", "Fail"), - numericColumn("time", "Time [ms]") - ]; - - // Filtering of irrelevant stack trace lines - var stacktracePackagesToHide = [ - 'com.carrotsearch.randomizedtesting.RandomizedRunner', - 'com.carrotsearch.ant.tasks.junit4', - 'java.lang.reflect.Method.invoke', - 'sun.reflect', - 'sun.misc', - 'java.lang', - 'java.util', - 'junit.framework', - 'org.junit.Assert', - 'org.junit.Assume', - 'org.junit.runners', - 'org.junit.runner', - 'org.junit.rules', - 'org.junit.internal' - ]; - var stacktraceFilters = [ ]; - var regexpEscape = /[-[\]{}()*+?.,\\^$|#\s]/g; - for (var i = 0; i < stacktracePackagesToHide.length; i++) { - stacktraceFilters.push(stacktracePackagesToHide[i].replace(regexpEscape, "\\$&")); - } - var stacktraceFilter = new RegExp( "(" + stacktraceFilters.join(")|(") + ")"); - - return { - methods: { - columns: [ - $.extend(column("signature", "string", "Method", true), { - renderer: function(value, html, row) { - if (row.test.hasErrors) { - html.push(""); - } - if (row.test.hasOutput && !row.test.hasErrors) { - html.push(""); - } - - searchHighlighterRenderer(value, html); - - $.each(row.test.testFailures, function(index, failure) { - var lines = failure.stackTrace.replace(/\t/g, "").split(/\n/); - - html.push("
"); - var filtered = false, filteredOut = 0; - html.push("
", escape(lines[0]), "
"); - for (var i = 1; i < lines.length; i++) { - var currentFiltered = stacktraceFilter.test(lines[i]); - if (currentFiltered != filtered) { - html.push("
", - filtered ? "" : "", - ""); - filtered = currentFiltered; - filteredOut = 0; - } else { - filteredOut++; - } - html.push(escape(lines[i]), "
"); - } - html.pop(); // the last extra
- html.push("
"); - }); - } - }), - { - id: "result", - label: "Result", - sortable: true, - sorting: function(a, b) { - if (a == b) { - return 0; - } else { - for (var i = 0; i < statusOrder.length; i++) { - var status = statusOrder[i]; - if (a == status) { - return -1; - } - if (b == status) { - return 1; - } - } - } - }, - renderer: function(value, html) { - html.push("", statusLabels[value] ,"") - }, - type: "result" - }, - numericColumn("slave", "JVM"), - { - id: "timestamp", - label: "Start", - type: "numeric", - renderer: function(value, html) { - var d = new Date(value); - html.push(zero(d.getHours()), ":", zero(d.getMinutes()), ":", zero(d.getSeconds()), ".", zerozero(d.getMilliseconds())); - - function zero(x) { - if (x < 10) { - return "0" + x; - } else { - return x; - } - } - function zerozero(x) { - if (x < 100) { - return "0" + zero(x); - } else { - return x; - } - } - }, - sortable: true - }, - numericColumn("time", "Time [ms]") - ], - rows: function(data, aggregates) { - var rows = []; - eachTest(data, function(test) { - if (!currentFilter(test)) { - return; - } - rows.push({ - id: "t" + test.description.htmlId, - signature: test.description.packageClassMethodName, - result: test.status, - time: test.executionTime, - slave: test.slave, - timestamp: test.startTimestamp, - test: test - }) - }); - return rows; - } - }, - - packages: { - columns: $.extend(true, [], aggregatedViewColumns, [ { label: "Package" } ]), - rows: function(data) { - return aggregatedRows(data, byPackage); - }, - drilldown: function($row) { - drilldown($row, "classes"); - } - }, - - classes: { - columns: $.extend(true, [], aggregatedViewColumns, [ { label: "Class" } ]), - rows: function(data) { - return aggregatedRows(data, byClass); - }, - drilldown: function($row) { - drilldown($row, "methods"); - } - } - }; - - function drilldown($row, view) { - var search = $row.find("td:eq(0)").text(); - $search.val(search); - state.search = search; - state.view = view; - refresh(); - } - - function column(id, type, label, searchable) { - return { - id: id, - sortable: true, - searchable: searchable, - type: type, - label: label, - renderer: searchHighlighterRenderer - }; - } - - function searchHighlighterRenderer(value, html) { - if (this.searchable && state.search) { - var s = state.search.toLowerCase(), sl = s.length, vlc = value.toLowerCase(), vl = value.length; - var start = 0, found = -1; - while ((found = vlc.indexOf(s, start)) >= 0) { - html.push(value.substring(start, found), "", value.substring(found, found + sl), ""); - start = found + sl; - } - html.push(value.substring(start)); - } else { - html.push(escape(value)); - } - } - - function numericColumn(id, label) { - return column(id, "numeric", label, false); - } - - function aggregatedRows(data, aggregateFunction) { - var rows = []; - - var counts = aggregate(data, testCount, { aggregate: aggregateFunction }, currentFilter); - var times = aggregate(data, totalTime, { aggregate: aggregateFunction }, currentFilter); - var statuses = aggregate(data, testCountByStatus, { aggregate: aggregateFunction }, currentFilter); - - if (!statuses.aggregate) { - return rows; - } - $.each(statuses.aggregate, function(signature, statuses) { - rows.push({ - signature: signature, - count: counts.aggregate[signature], - result: { statuses: statuses, total: counts.aggregate[signature] }, - pass: statuses[OK] || 0, - ignored: (statuses[IGNORED] || 0) + (statuses[IGNORED_ASSUMPTION] || 0), - error: statuses[ERROR] || 0, - failed: statuses[FAILURE] || 0, - time: times.aggregate[signature] - }); - }); - return rows; - } - })(); - - // Initialize the table - $(document).ready(function() { - // Create global aggregations - var counts = aggregate(data, testCount, { "global": global, "byStatus": byStatus }, noFilter); - var hasResults = keys(counts).length > 0; - - // Generate markup - var $results = $("#results"); - - // Results heading - var heading = { }; - if (hasResults) { - var numFailures = counts.byStatus[FAILURE]; - var numErrors = counts.byStatus[ERROR]; - if (numFailures > 0 || numErrors > 0) { - var h = []; - if (numErrors > 0) { - h.push(countText(counts.byStatus[ERROR], "test") + " had errors"); - heading.class = ERROR; - } - if (numFailures > 0) { - h.push(countText(counts.byStatus[FAILURE], "test") + " failed"); - heading.class = FAILURE; - } - heading.text = h.join(", "); - } else if (counts.byStatus[ERROR] > 0) { - } else { - heading.text = "tests successful"; - heading.class = OK; - } - } else { - heading.text = "no tests"; - heading.class = OK; - } - - $("header > h1").text(project["project.name"] + ":").append(" " + heading.text + "").parent().addClass(heading.class); - - // Update window title - document.title = $.trim($("header > h1").text()); - - // Results table tools - if (hasResults) { - $tools = $("
\ - \ - show: pass \ - ignored \ - error \ - fail\ - without output\ - view: packages \ - classes \ - methods \ - console\ -
").appendTo($results); - } - - // Results table - $table = $("
").appendTo($results); - if (!hasResults) { - $table.addClass("no-results"); - tableEmpty($table); - return; - } - - - // Console output, invisible by default - $console = $("
").hide().appendTo($results); - $console.delegate('.label', "mouseenter mouseleave", function () { - $(this).parent().parent().nextAll(".out, .err").add(this).toggleClass("highlight"); - $(this).closest(".suitebox").toggleClass("highlight"); - return false; - }); - $console.delegate('.out, .err', "mouseenter mouseleave", function () { - $(this).prevAll(".side").children().eq(0).children().eq(0).add(this).toggleClass("highlight"); - $(this).closest(".suitebox").toggleClass("highlight"); - return false; - }); - $console.delegate('.test.label', "click", function () { - state.highlight = $(this).parent().closest("span.test").attr("id").substring(1); - state.view = "methods"; - state.push(); - return false; - }); - - // Bind listeners - $tools.on("click", ".views", function (e) { - if (!e.target.href) { - return; - } - state.view = $(e.target).attr("href").substring(1); - - // If the search seems to be a fully qualified method/class name, - // strip the the last components to match the view type so that the - // "no test results found" message does not appear. - if (wasDrilldown) { - var split = state.search.split(/\./); - if (split.length > 1) { - if (state.view == "classes") { - strip(split, true); - $search.val(split.join(".")).trigger("drilldownUpdate"); - } else if (state.view == "packages") { - $search.val("").trigger("drilldownUpdate"); - } - } - } - - state.push(); - return false; - - function strip(split, splitIfUpper) { - var method = split[split.length - 1]; - var firstLetter = method.charAt(0); - if ((splitIfUpper && firstLetter == firstLetter.toUpperCase()) || - (!splitIfUpper && firstLetter == firstLetter.toLowerCase())) { - split.pop(); - return true; - } - return false; - } - }); - - $tools.on("click", ".filters", function (e) { - if (!e.target.href) { - return; - } - var filter = $(e.target).attr("href").substring(1); - state.filter[filter] = !state.filter[filter]; - state.push(); - return false; - }); - - $table.on("click", "th.sortable", function (e) { - var newSort = $(this).data("column"); - if (e.ctrlKey) { - // If the ordering already contains the selected column, invert - // the order. If the ordering does not contain the selected column, - // add it at the end of the ordering array. - var matched = false; - for (var i = 0; i < state.order.columns.length; i++) { - if (state.order.columns[i] == newSort) { - state.order.ascendings[i] = !state.order.ascendings[i]; - matched = true; - break; - } - } - if (!matched) { - state.order.columns.push(newSort); - state.order.ascendings.push(true); - } - } else { - // Sort by just by the requested column or change sorting order - var currentAscending = false; - for (var i = 0; i < state.order.columns.length; i++) { - if (state.order.columns[i] == newSort) { - currentAscending = state.order.ascendings[i]; - break; - } - } - state.order.columns = [ newSort ]; - state.order.ascendings = [ !currentAscending ]; - } - state.push(); - return false; - }); - - $table.on("click", "tr.drilldown", function () { - $table.data("source").spec.drilldown($(this)); - wasDrilldown = true; - state.push(); - return false; - }); - - $table.on("click", ".stacktrace", function () { - $(this).closest("td").toggleClass("fullStacktrace"); - return false; - }); - - $table.on("click", ".stdout, .stderr", function () { - state.highlight = $(this).closest("tr").attr("id").substring(1); - state.view = "console"; - state.push(); - return false; - }); - - $search = $tools.find("input[type='search']").on("keyup click drilldownUpdate", function (e) { - var $this = $(this); - typewatch(function () { - var v = $.trim($this.val()); - if (state.search != v) { - if (e.type != "drilldownUpdate") { - wasDrilldown = false; - } - state.search = v; - state.push(); - } - }, e.type == "keyup" ? 500 : 0); - }); - - // If no failures or errors, show package view ordered by package name. - // In case of errors or failures, show method view ordered by status. - if (!(counts.byStatus[FAILURE] > 0 || counts.byStatus[ERROR] > 0)) { - state.view = "packages"; - state.order = { columns: [ "signature" ], ascendings: [ true ] }; - } else { - state.view = "methods"; - state.order = { columns: [ "result" ], ascendings: [ false ] }; - } - - // React to path changes - $(window).pathchange(function () { - state.decode(); - refresh(); - }); - $.pathchange.init({ - useHistory: false - }); - - if (window.location.hash) { - $(window).pathchange(); // decode and refresh - } else { - // Push initial state to the URL, only if the URL does not contain state - if (!state.push()) { - // If the URL didn't change, we need to refresh manually - refresh(); - } - } - return this; - }); - - // Called after UI state changes to refresh the UI - function refresh() { - if (state.view == "console") { - $search.hide(); // No search in console for the time being - $table.hide(); - $console.show(); - refreshConsole(); - } else { - $console.hide(); - $search.show(); - $table.show(); - refreshTable(); - } - - refreshSummary(); - - // Show which view is active - $tools.find("a").removeClass("active").filter("[href^=#" + state.view + "]").addClass("active"); - $("#results").attr("class", state.view); - - // Show which filters are active - $tools.find(".filters a").each(function() { - $(this).toggleClass("active", state.filter[this.hash.substring(1)]); - }); - - // Update search box - $search.val(state.search); - - // Render and scroll to the highlighted element, then reset highlight - if (state.highlight) { - setTimeout(function() { - var offset = $("#" + (state.view == "console" ? "c" : "t") + state.highlight).addClass("highlight").offset().top; - $('html, body').animate({ scrollTop: offset }, 700); - state.highlight = ""; - }, 250); - } - } - - // Refreshes the results table based on the current parameters - function refreshTable() { - table($table.data("source", { - data: data, - order: state.order, - type: state.view, - spec: tables[state.view] - })); - } - - // Refreshes the summary box based on the current parameters - function refreshSummary() { - var counts = aggregate(data, testCount, { "global":global, "byStatus":byStatus }, currentFilter); - var times = aggregate(data, totalTime, { "global":global, "bySlave":bySlave }, currentFilter); - - var $summary = $("#summary").html("").attr("class", ""); - if ((counts.global || 0) == 0) { - return; - } - - $("

").html(tmpl("\ - #{tests} executed in\ - #{time} ms on\ - #{slaves}.", { - tests: countText(counts.global || 0, "test"), - time: times.global, - slaves: countText(keys(times.bySlave).length, "slave") - })).appendTo($summary); - - var html = ""; - if (!(counts.byStatus[FAILURE] > 0 || counts.byStatus[ERROR] > 0)) { - if (counts.byStatus[OK] == counts.global) { - html = "All tests passed."; - } else if ((counts.byStatus[OK] || 0) > 0) { - html = tmpl("No failures, #{passed} passed, #{ignored} ignored.", { - passed:countText(counts.byStatus[OK], "test"), - ignored:countText((counts.byStatus[IGNORED] || 0) + (counts.byStatus[IGNORED_ASSUMPTION] || 0), "test") - }); - } - } else { - var h = []; - if (counts.byStatus[FAILURE] > 0) { - h.push(counts.byStatus[FAILURE] + " failed"); - } - if (counts.byStatus[ERROR] > 0) { - h.push(countText(counts.byStatus[ERROR], "error")); - } - if (counts.byStatus[IGNORED] > 0 || counts.byStatus[IGNORED_ASSUMPTION] > 0) { - h.push((counts.byStatus[IGNORED] || 0) + (counts.byStatus[IGNORED_ASSUMPTION] || 0) + " ignored"); - } - if (counts.byStatus[OK] > 0) { - h.push(counts.byStatus[OK] + " passed"); - } - html = h.join(", "); - } - $("

").html(html).appendTo($summary); - - // Status bar - $summary.append($(statusbar(counts.byStatus, counts.global))); - } - - // Escape a string into HTML. - function htmlEscape(str) { - return String(str) - .replace(/&/g, '&') - .replace(/"/g, '"') - .replace(/'/g, ''') - .replace(//g, '>'); - } - - // Renders the console output - function refreshConsole() { - var html = []; - eachSuite(data, function (suite) { - // Check if we want to show the suite at all. Store this information in the model. - var showSuite = state.filter.withoutoutput; - var outputShown = true; - var insideTest = false; - $.each(suite.executionEvents, function(index, evtobj) { - switch (evtobj.event) { - case "TEST_STARTED": - outputShown = currentFilter(evtobj.test); - insideTest = true; - break; - - case "TEST_FINISHED": - insideTest = false; - break; - - case "APPEND_STDOUT": - case "APPEND_STDERR": - if ((insideTest && outputShown) || !insideTest) { - showSuite = true; - } - outputShown = true; - break; - } - evtobj.shown = outputShown; - }); - - if (!showSuite) { - return true; // continue the loop - } - - html.push("

", - "
", suite.description.displayName, "
", - "
");
-
-      var emptyOutBoxIndex = html.length - 1;
-      $.each(suite.executionEvents, function(index, evtobj) {
-        var shown = evtobj.shown;
-        delete evtobj.shown;
-        if (!shown) {
-          return true; // continue the loop
-        }
-
-        switch (evtobj.event) {
-          case "SUITE_FAILURE":
-            html.push("",
-                      "
suite failure
"); - break; - - case "TEST_STARTED": - // Add a content wrapper for the test... - html.push("", - "", - "
", evtobj.description.methodName, - "
"); - break; - - case "APPEND_STDOUT": - case "APPEND_STDERR": - html.push("", - htmlEscape(evtobj.content), ""); - emptyOutBoxIndex = undefined; - break; - - case "TEST_FINISHED": - html.push("
"); - break; - - default: - // do nothing. - } - }); - if (emptyOutBoxIndex !== undefined) { - html[emptyOutBoxIndex] = html[emptyOutBoxIndex].replace(/outbox/, "outbox empty"); - } - html.push("
"); - }); - if (html.length == 0) { - html.push("
No console output
"); - } - $console.html(html.join("")); - - redrawConnectors(); - } - - function redrawConnectors() { - var tagHeight = $(".outbox .tag").first().height(); - $(".outbox").each(function() { - var $box = $(this); - var $tags = $box.find(".tag"); - if ($tags.size() == 0) { - return true; - } - - // Allow repaint before drawing - setTimeout(function() { - var $canvas = $("") - .attr("width", $box.width() + 20) - .attr("height", $tags.last().offset().top - - $box.offset().top + tagHeight) - .appendTo($box); - - var ctx = $canvas.get(0).getContext('2d'); - ctx.translate(-$canvas.offset().left, -$canvas.offset().top); - - ctx.beginPath(); - ctx.strokeStyle = "#555"; - ctx.lineWidth = 0.5; - $box.find(".marker").each(function() { - var $marker = $(this); - var $label = $marker.next().children().eq(0).children().eq(0); - - var offset = $label.offset(); - var x0 = 0.5 + offset.left + $label.width() + 7.5; - var y0 = 0.5 + offset.top + $label.height() / 2; - var position = $marker.offset(); - var x1 = 1.5 + position.left; - var y1 = 1.5 + position.top + 1.5; - - ctx.moveTo(x0, y0); - ctx.bezierCurveTo((x1 + x0) / 2, y0, - (x1 + x0) / 2, y1, - x1, y1); - }); - ctx.stroke(); - }, 0); - }); - } - - // Renders contents of a table according to the provided spec - function table($table) { - var source = $table.data("source"); - var spec = source.spec, data = source.data, order = source.order; - - var html = [ ]; - - // Get the data - var rows = spec.rows(data); - if (rows.length == 0) { - tableEmpty($table); - return; - } - - var allColumnsById = map(spec.columns, function(c) { return c.id; }); - var orderColumns = [ ]; - for (var i = 0; i < order.columns.length; i++) { - orderColumns[i] = { - column: allColumnsById[order.columns[i]] || spec.columns[0], - ascending: order.ascendings[i] - }; - } - // Last implicit order by signature, makes things more predictable - orderColumns.push({ - column: allColumnsById["signature"], - ascending: true - }); - var orderColumnsById = map (orderColumns, function(o) { return o.column.id; }); - - // Render column headers - html.push("
"); - html.push(""); - $.each(spec.columns, function(i, column) { - html.push(tmpl("", { - type: column.type, - id: column.id, - sort: typeof orderColumnsById[column.id] != 'undefined' ? (orderColumnsById[column.id].ascending ? "asc" : "desc") : "", - label: column.label, - sortable: column.sortable ? "sortable" : "" - })); - }); - html.push(""); - html.push(""); - - // Sort the data - rows.sort(function(a, b) { - for (var i = 0; i < orderColumns.length; i++) { - var column = orderColumns[i].column; - var ordering = column.sorting || function(a, b) { return a > b ? 1 : b > a ? -1 : 0; } - var o = ordering(a[column.id], b[column.id]) * (orderColumns[i].ascending ? 1 : -1); - if (o != 0) { - return o; - } - } - return 0; - }); - - // Render table rows - html.push(""); - var rowStart = spec.drilldown ? ""); - $.each(spec.columns, function(i, column) { - html.push(""); - }); - html.push(""); - }); - html.push(""); - - $table.html(html.join("")); - } - - function tableEmpty($table) { - $table.html(""); - } - - function time(id, code) { - var start = Date.now(); - code(); - console.log(id, Date.now() - start); - } - - function statusbar(counts, total) { - var html = []; - html.push("
    "); - var left = 0; - for (var i = 0; i < statusOrder.length; i++) { - var status = statusOrder[i]; - var count = counts[status]; - if (count > 0) { - var width = (100 * count) / total; - html.push(tmpl("
  • ", { - status: status, - label: statusLabels[status], - pct: width, - count: count, - left: left - })); - left += width; - } - } - html.push("
"); - return html.join(""); - }; - - /** - * Aggregates the data using the provided aggregation function - * and the provided set of key transformer functions. - */ - function aggregate(data, aggregation, keys, filter) { - var a = { }; - eachTest(data, function(test) { - if (!filter(test)) { - return true; - } - - $.each(keys, function(id, key) { - var k = key.call(this, test); - - // If undefined, treat as global key and don't create an extra holder object - if (k === undefined) { - a[id] = aggregation.call(this, test, a[id]); - } else { - a[id] = a[id] || { }; - a[id][k] = aggregation.call(this, test, a[id][k]); - } - }); - }); - return a; - } - - function byStatus(test) { - return test.status; - } - - function bySlave(test) { - return test.slave; - } - - function byPackage(test) { - return test.description.packageName; - } - - function byClass(test) { - return test.description.packageClassName; - } - - function noFilter(test) { - return true; - } - - var searchTargetsByView = { packages: "packageName", classes: "packageClassName", methods: "packageClassMethodName" }; - function signatureSearchFilter(test) { - if ($.trim(state.search).length > 0) { - return test.description[searchTargetsByView[state.view]].toLowerCase().indexOf(state.search.toLowerCase()) >= 0; - } else { - return true; - } - } - - var testStatusToFilter = { OK: "pass", IGNORED: "ignored", IGNORED_ASSUMPTION: "ignored", ERROR: "error", FAILURE: "fail" }; - function statusFilter(test) { - return state.filter[testStatusToFilter[test.status]]; - } - - function currentFilter(test) { - return statusFilter(test) && - (state.view == "console" || signatureSearchFilter(test)) && - (state.view != "console" || state.filter.withoutoutput || test.hasOutput || test.hasErrors); - } - - function global() { - return undefined; - } - - function testCountByStatus(test, current) { - return addOne(current || { }, test.status); - } - - function testCount(test, current) { - return (current || 0) + 1; - } - - function totalTime(test, current) { - return (current || 0) + test.executionTime; - } - - function getOrCreate(set, key, created) { - if (typeof set[key] === "undefined") { - set[key] = created; - } - return set[key]; - } - - function addOne(set, key) { - if (typeof set[key] == "undefined") { - set[key] = 1; - } else { - set[key]++; - } - return set; - } - - function keys(o) { - var a = [ ]; - for (k in o) { - if (o.hasOwnProperty(k)) { - a.push(k); - } - } - return a; - } - - function map(collection, key) { - var result = { }; - $.each(collection, function(i, value) { - result[key(value)] = value; - }); - return result; - } - - function countText(count, noun) { - return count + " " + noun + (count == 1 ? "" : "s"); - } - - function eachTest(data, callback) { - eachSuite(data, function(suite) { - var tests = suite.tests; - for (var j = 0; j < tests.length; j++) { - callback.call(this, tests[j]); - } - }); - } - - function eachSuite(data, callback) { - for (var i = 0; i < data.length; i++) { - callback.call(this, data[i]); - } - } - - - // Inspired by jQuery Simple Templates plugin 1.1.1 - // http://andrew.hedges.name/tmpl - // Dual licensed under the MIT and GPL licenses - function tmpl(tmpl, vals) { - var rgxp, repr; - - tmpl = tmpl || ''; - vals = vals || {}; - - // regular expression for matching placeholders - rgxp = /#\{([^{}]*)}/g; - - // make replacements - repr = function (str, match) { - var m = match.split(":"); - var v = m[0]; - var t = m[1]; - return typeof vals[v] === 'string' && t != "raw" ? e(vals[v]) : vals[v]; - - function e(content) { - return content ? escape(content) : content; - } - }; - - return tmpl.replace(rgxp, repr); - } - - function escape(string) { - return typeof string === 'string' ? string.replace(/&/g, "&").replace(//g, ">") : string; - } - -})(jQuery); -var typewatch = (function(){ - var timer = 0; - return function(callback, ms){ - clearTimeout (timer); - timer = setTimeout(callback, ms); - } -})(); diff --git a/junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/tests-output.jsonp b/junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/tests-output.jsonp deleted file mode 100644 index 146e2f80..00000000 --- a/junit4-ant/src/main/resources/com/carrotsearch/ant/tasks/junit4/templates/json/tests-output.jsonp +++ /dev/null @@ -1,677 +0,0 @@ -testData({ - "junit4": { - "tests.seed": "B19FBD1BB1231191", - "project.name": "Nice project" - }, - "suites": [ - { - "slave": 0, - "startTimestamp": 1331889914622, - "startTimestampDate": "2012-03-16T10:25:14.622", - "executionTime": 109, - "description": { - "id": "id#com.carrotsearch.ant.tasks.junit4.tests.TestBeforeClassError[0]", - "displayName": "com.carrotsearch.ant.tasks.junit4.tests.TestBeforeClassError", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestBeforeClassError", - "annotations": [], - "children": [ - { - "id": "id#method(com.carrotsearch.ant.tasks.junit4.tests.TestBeforeClassError)[1]", - "displayName": "method(com.carrotsearch.ant.tasks.junit4.tests.TestBeforeClassError)", - "methodName": "method", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestBeforeClassError", - "annotations": [ - { - "org.junit.Test": { - "timeout": 0, - "expected": "org.junit.Test$None" - } - } - ], - "children": [] - } - ] - }, - "tests": [], - "suiteFailures": [ - { - "throwableClass": "java.lang.RuntimeException", - "throwableString": "java.lang.RuntimeException", - "stackTrace": "java.lang.RuntimeException\n\tat com.carrotsearch.ant.tasks.junit4.tests.TestBeforeClassError.beforeClass(TestBeforeClassError.java:9)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n\tat java.lang.reflect.Method.invoke(Method.java:597)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)\n\tat org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:157)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.execute(SlaveMain.java:129)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.main(SlaveMain.java:202)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe.main(SlaveMainSafe.java:12)\n", - "kind": "error" - } - ], - "executionEvents": [ - { - "event": "SUITE_FAILURE", - "description": "id#com.carrotsearch.ant.tasks.junit4.tests.TestBeforeClassError[0]", - "failure": { - "throwableClass": "java.lang.RuntimeException", - "throwableString": "java.lang.RuntimeException", - "stackTrace": "java.lang.RuntimeException\n\tat com.carrotsearch.ant.tasks.junit4.tests.TestBeforeClassError.beforeClass(TestBeforeClassError.java:9)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n\tat java.lang.reflect.Method.invoke(Method.java:597)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)\n\tat org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:157)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.execute(SlaveMain.java:129)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.main(SlaveMain.java:202)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe.main(SlaveMainSafe.java:12)\n", - "kind": "error" - } - } - ] - }, - { - "slave": 0, - "startTimestamp": 1331889914744, - "startTimestampDate": "2012-03-16T10:25:14.744", - "executionTime": 2, - "description": { - "id": "id#com.carrotsearch.ant.tasks.junit4.tests.TestIgnoredSuite[1]", - "displayName": "com.carrotsearch.ant.tasks.junit4.tests.TestIgnoredSuite", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestIgnoredSuite", - "annotations": [ - { - "org.junit.Ignore": { - "value": "" - } - } - ], - "children": [] - }, - "tests": [], - "suiteFailures": [], - "executionEvents": [] - }, - { - "slave": 0, - "startTimestamp": 1331889914756, - "startTimestampDate": "2012-03-16T10:25:14.756", - "executionTime": 18, - "description": { - "id": "id#com.carrotsearch.ant.tasks.junit4.tests.TestSysstreams[0]", - "displayName": "com.carrotsearch.ant.tasks.junit4.tests.TestSysstreams", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestSysstreams", - "annotations": [], - "children": [ - { - "id": "id#ok(com.carrotsearch.ant.tasks.junit4.tests.TestSysstreams)[1]", - "displayName": "ok(com.carrotsearch.ant.tasks.junit4.tests.TestSysstreams)", - "methodName": "ok", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestSysstreams", - "annotations": [ - { - "org.junit.Test": { - "timeout": 0, - "expected": "org.junit.Test$None" - } - } - ], - "children": [] - }, - { - "id": "id#ok_sysout_syserr(com.carrotsearch.ant.tasks.junit4.tests.TestSysstreams)[1]", - "displayName": "ok_sysout_syserr(com.carrotsearch.ant.tasks.junit4.tests.TestSysstreams)", - "methodName": "ok_sysout_syserr", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestSysstreams", - "annotations": [ - { - "org.junit.Test": { - "timeout": 0, - "expected": "org.junit.Test$None" - } - } - ], - "children": [] - } - ] - }, - "tests": [ - { - "slave": 0, - "startTimestamp": 1331889914769, - "startTimestampDate": "2012-03-16T10:25:14.769", - "executionTime": 1, - "description": "id#ok(com.carrotsearch.ant.tasks.junit4.tests.TestSysstreams)[1]", - "status": "OK", - "testFailures": [] - }, - { - "slave": 0, - "startTimestamp": 1331889914771, - "startTimestampDate": "2012-03-16T10:25:14.771", - "executionTime": 2, - "description": "id#ok_sysout_syserr(com.carrotsearch.ant.tasks.junit4.tests.TestSysstreams)[1]", - "status": "OK", - "testFailures": [] - } - ], - "suiteFailures": [], - "executionEvents": [ - { - "event": "TEST_STARTED", - "description": "id#ok(com.carrotsearch.ant.tasks.junit4.tests.TestSysstreams)[1]" - }, - { - "event": "TEST_FINISHED", - "description": "id#ok(com.carrotsearch.ant.tasks.junit4.tests.TestSysstreams)[1]" - }, - { - "event": "TEST_STARTED", - "description": "id#ok_sysout_syserr(com.carrotsearch.ant.tasks.junit4.tests.TestSysstreams)[1]" - }, - { - "event": "APPEND_STDOUT", - "content": "sysout" - }, - { - "event": "APPEND_STDERR", - "content": "syserr" - }, - { - "event": "APPEND_STDOUT", - "content": "-sysout-contd." - }, - { - "event": "APPEND_STDERR", - "content": "-syserr-contd." - }, - { - "event": "TEST_FINISHED", - "description": "id#ok_sysout_syserr(com.carrotsearch.ant.tasks.junit4.tests.TestSysstreams)[1]" - } - ] - }, - { - "slave": 0, - "startTimestamp": 1331889914800, - "startTimestampDate": "2012-03-16T10:25:14.800", - "executionTime": 93, - "description": { - "id": "id#com.carrotsearch.ant.tasks.junit4.tests.TestStatuses[0]", - "displayName": "com.carrotsearch.ant.tasks.junit4.tests.TestStatuses", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestStatuses", - "annotations": [], - "children": [ - { - "id": "id#failure(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]", - "displayName": "failure(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)", - "methodName": "failure", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestStatuses", - "annotations": [ - { - "org.junit.Test": { - "timeout": 0, - "expected": "org.junit.Test$None" - } - } - ], - "children": [] - }, - { - "id": "id#error(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]", - "displayName": "error(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)", - "methodName": "error", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestStatuses", - "annotations": [ - { - "org.junit.Test": { - "timeout": 0, - "expected": "org.junit.Test$None" - } - } - ], - "children": [] - }, - { - "id": "id#ignored(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[2]", - "displayName": "ignored(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)", - "methodName": "ignored", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestStatuses", - "annotations": [ - { - "org.junit.Test": { - "timeout": 0, - "expected": "org.junit.Test$None" - } - }, - { - "org.junit.Ignore": { - "value": "" - } - } - ], - "children": [] - }, - { - "id": "id#ok(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]", - "displayName": "ok(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)", - "methodName": "ok", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestStatuses", - "annotations": [ - { - "org.junit.Test": { - "timeout": 0, - "expected": "org.junit.Test$None" - } - } - ], - "children": [] - }, - { - "id": "id#ignored_a(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]", - "displayName": "ignored_a(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)", - "methodName": "ignored_a", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestStatuses", - "annotations": [ - { - "org.junit.Test": { - "timeout": 0, - "expected": "org.junit.Test$None" - } - } - ], - "children": [] - } - ] - }, - "tests": [ - { - "slave": 0, - "startTimestamp": 1331889914811, - "startTimestampDate": "2012-03-16T10:25:14.811", - "executionTime": 15, - "description": "id#failure(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]", - "status": "FAILURE", - "testFailures": [ - { - "throwableClass": "java.lang.AssertionError", - "throwableString": "java.lang.AssertionError", - "stackTrace": "java.lang.AssertionError\n\tat org.junit.Assert.fail(Assert.java:92)\n\tat org.junit.Assert.assertTrue(Assert.java:43)\n\tat org.junit.Assert.assertTrue(Assert.java:54)\n\tat com.carrotsearch.ant.tasks.junit4.tests.TestStatuses.failure(TestStatuses.java:24)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n\tat java.lang.reflect.Method.invoke(Method.java:597)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)\n\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)\n\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)\n\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)\n\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:157)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.execute(SlaveMain.java:129)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.main(SlaveMain.java:202)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe.main(SlaveMainSafe.java:12)\n", - "kind": "assertion" - } - ] - }, - { - "slave": 0, - "startTimestamp": 1331889914829, - "startTimestampDate": "2012-03-16T10:25:14.829", - "executionTime": 14, - "description": "id#error(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]", - "status": "ERROR", - "testFailures": [ - { - "throwableClass": "java.lang.RuntimeException", - "throwableString": "java.lang.RuntimeException", - "stackTrace": "java.lang.RuntimeException\n\tat com.carrotsearch.ant.tasks.junit4.tests.TestStatuses.error(TestStatuses.java:29)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n\tat java.lang.reflect.Method.invoke(Method.java:597)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)\n\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)\n\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)\n\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)\n\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:157)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.execute(SlaveMain.java:129)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.main(SlaveMain.java:202)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe.main(SlaveMainSafe.java:12)\n", - "kind": "error" - } - ] - }, - { - "slave": 0, - "startTimestamp": 1331889914845, - "startTimestampDate": "2012-03-16T10:25:14.845", - "executionTime": 0, - "description": "id#ignored(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[2]", - "status": "IGNORED", - "testFailures": [] - }, - { - "slave": 0, - "startTimestamp": 1331889914846, - "startTimestampDate": "2012-03-16T10:25:14.846", - "executionTime": 0, - "description": "id#ok(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]", - "status": "OK", - "testFailures": [] - }, - { - "slave": 0, - "startTimestamp": 1331889914847, - "startTimestampDate": "2012-03-16T10:25:14.847", - "executionTime": 45, - "description": "id#ignored_a(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]", - "status": "IGNORED_ASSUMPTION", - "testFailures": [ - { - "throwableClass": "org.junit.internal.AssumptionViolatedException", - "throwableString": "org.junit.internal.AssumptionViolatedException: got: \u003cfalse\u003e, expected: is \u003ctrue\u003e", - "stackTrace": "org.junit.internal.AssumptionViolatedException: got: \u003cfalse\u003e, expected: is \u003ctrue\u003e\n\tat org.junit.Assume.assumeThat(Assume.java:70)\n\tat org.junit.Assume.assumeTrue(Assume.java:39)\n\tat com.carrotsearch.ant.tasks.junit4.tests.TestStatuses.ignored_a(TestStatuses.java:19)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n\tat java.lang.reflect.Method.invoke(Method.java:597)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)\n\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)\n\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)\n\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)\n\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:157)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.execute(SlaveMain.java:129)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.main(SlaveMain.java:202)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe.main(SlaveMainSafe.java:12)\n", - "kind": "assumption" - } - ] - } - ], - "suiteFailures": [], - "executionEvents": [ - { - "event": "TEST_STARTED", - "description": "id#failure(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]" - }, - { - "event": "TEST_FAILURE", - "description": "id#failure(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]", - "failure": { - "throwableClass": "java.lang.AssertionError", - "throwableString": "java.lang.AssertionError", - "stackTrace": "java.lang.AssertionError\n\tat org.junit.Assert.fail(Assert.java:92)\n\tat org.junit.Assert.assertTrue(Assert.java:43)\n\tat org.junit.Assert.assertTrue(Assert.java:54)\n\tat com.carrotsearch.ant.tasks.junit4.tests.TestStatuses.failure(TestStatuses.java:24)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n\tat java.lang.reflect.Method.invoke(Method.java:597)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)\n\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)\n\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)\n\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)\n\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:157)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.execute(SlaveMain.java:129)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.main(SlaveMain.java:202)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe.main(SlaveMainSafe.java:12)\n", - "kind": "assertion" - } - }, - { - "event": "TEST_FINISHED", - "description": "id#failure(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]" - }, - { - "event": "TEST_STARTED", - "description": "id#error(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]" - }, - { - "event": "TEST_FAILURE", - "description": "id#error(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]", - "failure": { - "throwableClass": "java.lang.RuntimeException", - "throwableString": "java.lang.RuntimeException", - "stackTrace": "java.lang.RuntimeException\n\tat com.carrotsearch.ant.tasks.junit4.tests.TestStatuses.error(TestStatuses.java:29)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n\tat java.lang.reflect.Method.invoke(Method.java:597)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)\n\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)\n\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)\n\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)\n\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:157)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.execute(SlaveMain.java:129)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.main(SlaveMain.java:202)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe.main(SlaveMainSafe.java:12)\n", - "kind": "error" - } - }, - { - "event": "TEST_FINISHED", - "description": "id#error(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]" - }, - { - "event": "TEST_IGNORED", - "description": "id#ignored(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[2]" - }, - { - "event": "TEST_STARTED", - "description": "id#ok(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]" - }, - { - "event": "TEST_FINISHED", - "description": "id#ok(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]" - }, - { - "event": "TEST_STARTED", - "description": "id#ignored_a(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]" - }, - { - "event": "TEST_IGNORED_ASSUMPTION", - "description": "id#ignored_a(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]", - "failure": { - "throwableClass": "org.junit.internal.AssumptionViolatedException", - "throwableString": "org.junit.internal.AssumptionViolatedException: got: \u003cfalse\u003e, expected: is \u003ctrue\u003e", - "stackTrace": "org.junit.internal.AssumptionViolatedException: got: \u003cfalse\u003e, expected: is \u003ctrue\u003e\n\tat org.junit.Assume.assumeThat(Assume.java:70)\n\tat org.junit.Assume.assumeTrue(Assume.java:39)\n\tat com.carrotsearch.ant.tasks.junit4.tests.TestStatuses.ignored_a(TestStatuses.java:19)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n\tat java.lang.reflect.Method.invoke(Method.java:597)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)\n\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)\n\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)\n\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)\n\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:157)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.execute(SlaveMain.java:129)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.main(SlaveMain.java:202)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe.main(SlaveMainSafe.java:12)\n", - "kind": "assumption" - } - }, - { - "event": "TEST_FINISHED", - "description": "id#ignored_a(com.carrotsearch.ant.tasks.junit4.tests.TestStatuses)[1]" - } - ] - }, - { - "slave": 0, - "startTimestamp": 1331889915015, - "startTimestampDate": "2012-03-16T10:25:15.015", - "executionTime": 90, - "description": { - "id": "id#com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription[2]", - "displayName": "com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription", - "annotations": [ - { - "org.junit.runner.RunWith": { - "value": "org.junit.runners.Suite" - } - }, - { - "org.junit.runners.Suite$SuiteClasses": { - "value": [ - "com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub1", - "com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub2", - "com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub3" - ] - } - } - ], - "children": [ - { - "id": "id#com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub1[0]", - "displayName": "com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub1", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub1", - "annotations": [], - "children": [ - { - "id": "id#method1(com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub1)[1]", - "displayName": "method1(com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub1)", - "methodName": "method1", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub1", - "annotations": [ - { - "org.junit.Test": { - "timeout": 0, - "expected": "org.junit.Test$None" - } - } - ], - "children": [] - } - ] - }, - { - "id": "id#com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub2[0]", - "displayName": "com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub2", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub2", - "annotations": [], - "children": [ - { - "id": "id#method1(com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub2)[1]", - "displayName": "method1(com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub2)", - "methodName": "method1", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub2", - "annotations": [ - { - "org.junit.Test": { - "timeout": 0, - "expected": "org.junit.Test$None" - } - } - ], - "children": [] - } - ] - }, - { - "id": "id#com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub3[0]", - "displayName": "com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub3", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub3", - "annotations": [], - "children": [ - { - "id": "id#method1(com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub3)[1]", - "displayName": "method1(com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub3)", - "methodName": "method1", - "className": "com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub3", - "annotations": [ - { - "org.junit.Test": { - "timeout": 0, - "expected": "org.junit.Test$None" - } - } - ], - "children": [] - } - ] - } - ] - }, - "tests": [ - { - "slave": 0, - "startTimestamp": 1331889915049, - "startTimestampDate": "2012-03-16T10:25:15.049", - "executionTime": 0, - "description": "id#method1(com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub2)[1]", - "status": "OK", - "testFailures": [] - }, - { - "slave": 0, - "startTimestamp": 1331889915086, - "startTimestampDate": "2012-03-16T10:25:15.086", - "executionTime": 4, - "description": "id#method1(com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub3)[1]", - "status": "ERROR", - "testFailures": [ - { - "throwableClass": "java.lang.RuntimeException", - "throwableString": "java.lang.RuntimeException", - "stackTrace": "java.lang.RuntimeException\n\tat com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub3.method1(TestHierarchicalSuiteDescription.java:40)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n\tat java.lang.reflect.Method.invoke(Method.java:597)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)\n\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)\n\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)\n\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)\n\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runners.Suite.runChild(Suite.java:128)\n\tat org.junit.runners.Suite.runChild(Suite.java:24)\n\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)\n\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)\n\tat org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:157)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.execute(SlaveMain.java:129)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.main(SlaveMain.java:202)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe.main(SlaveMainSafe.java:12)\n", - "kind": "error" - } - ] - } - ], - "suiteFailures": [ - { - "throwableClass": "java.lang.RuntimeException", - "throwableString": "java.lang.RuntimeException", - "stackTrace": "java.lang.RuntimeException\n\tat com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub1.beforeClass(TestHierarchicalSuiteDescription.java:23)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n\tat java.lang.reflect.Method.invoke(Method.java:597)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)\n\tat org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runners.Suite.runChild(Suite.java:128)\n\tat org.junit.runners.Suite.runChild(Suite.java:24)\n\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)\n\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)\n\tat org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:157)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.execute(SlaveMain.java:129)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.main(SlaveMain.java:202)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe.main(SlaveMainSafe.java:12)\n", - "kind": "error" - }, - { - "throwableClass": "java.lang.RuntimeException", - "throwableString": "java.lang.RuntimeException", - "stackTrace": "java.lang.RuntimeException\n\tat com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub2.afterClass(TestHierarchicalSuiteDescription.java:33)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n\tat java.lang.reflect.Method.invoke(Method.java:597)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)\n\tat org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:36)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runners.Suite.runChild(Suite.java:128)\n\tat org.junit.runners.Suite.runChild(Suite.java:24)\n\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)\n\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)\n\tat org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:157)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.execute(SlaveMain.java:129)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.main(SlaveMain.java:202)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe.main(SlaveMainSafe.java:12)\n", - "kind": "error" - }, - { - "throwableClass": "java.lang.RuntimeException", - "throwableString": "java.lang.RuntimeException", - "stackTrace": "java.lang.RuntimeException\n\tat com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription.afterClass(TestHierarchicalSuiteDescription.java:46)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n\tat java.lang.reflect.Method.invoke(Method.java:597)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)\n\tat org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:36)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:157)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.execute(SlaveMain.java:129)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.main(SlaveMain.java:202)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe.main(SlaveMainSafe.java:12)\n", - "kind": "error" - } - ], - "executionEvents": [ - { - "event": "TEST_FAILURE", - "description": "id#com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub1[0]", - "failure": { - "throwableClass": "java.lang.RuntimeException", - "throwableString": "java.lang.RuntimeException", - "stackTrace": "java.lang.RuntimeException\n\tat com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub1.beforeClass(TestHierarchicalSuiteDescription.java:23)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n\tat java.lang.reflect.Method.invoke(Method.java:597)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)\n\tat org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runners.Suite.runChild(Suite.java:128)\n\tat org.junit.runners.Suite.runChild(Suite.java:24)\n\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)\n\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)\n\tat org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:157)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.execute(SlaveMain.java:129)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.main(SlaveMain.java:202)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe.main(SlaveMainSafe.java:12)\n", - "kind": "error" - } - }, - { - "event": "TEST_STARTED", - "description": "id#method1(com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub2)[1]" - }, - { - "event": "TEST_FINISHED", - "description": "id#method1(com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub2)[1]" - }, - { - "event": "TEST_FAILURE", - "description": "id#com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub2[0]", - "failure": { - "throwableClass": "java.lang.RuntimeException", - "throwableString": "java.lang.RuntimeException", - "stackTrace": "java.lang.RuntimeException\n\tat com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub2.afterClass(TestHierarchicalSuiteDescription.java:33)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n\tat java.lang.reflect.Method.invoke(Method.java:597)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)\n\tat org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:36)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runners.Suite.runChild(Suite.java:128)\n\tat org.junit.runners.Suite.runChild(Suite.java:24)\n\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)\n\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)\n\tat org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:157)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.execute(SlaveMain.java:129)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.main(SlaveMain.java:202)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe.main(SlaveMainSafe.java:12)\n", - "kind": "error" - } - }, - { - "event": "TEST_STARTED", - "description": "id#method1(com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub3)[1]" - }, - { - "event": "TEST_FAILURE", - "description": "id#method1(com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub3)[1]", - "failure": { - "throwableClass": "java.lang.RuntimeException", - "throwableString": "java.lang.RuntimeException", - "stackTrace": "java.lang.RuntimeException\n\tat com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub3.method1(TestHierarchicalSuiteDescription.java:40)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n\tat java.lang.reflect.Method.invoke(Method.java:597)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)\n\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)\n\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)\n\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)\n\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)\n\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runners.Suite.runChild(Suite.java:128)\n\tat org.junit.runners.Suite.runChild(Suite.java:24)\n\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)\n\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)\n\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)\n\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)\n\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)\n\tat org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:157)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.execute(SlaveMain.java:129)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.main(SlaveMain.java:202)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe.main(SlaveMainSafe.java:12)\n", - "kind": "error" - } - }, - { - "event": "TEST_FINISHED", - "description": "id#method1(com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription$Sub3)[1]" - }, - { - "event": "SUITE_FAILURE", - "description": "id#com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription[2]", - "failure": { - "throwableClass": "java.lang.RuntimeException", - "throwableString": "java.lang.RuntimeException", - "stackTrace": "java.lang.RuntimeException\n\tat com.carrotsearch.ant.tasks.junit4.tests.TestHierarchicalSuiteDescription.afterClass(TestHierarchicalSuiteDescription.java:46)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n\tat java.lang.reflect.Method.invoke(Method.java:597)\n\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)\n\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)\n\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)\n\tat org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:36)\n\tat org.junit.runners.ParentRunner.run(ParentRunner.java:300)\n\tat org.junit.runner.JUnitCore.run(JUnitCore.java:157)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.execute(SlaveMain.java:129)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMain.main(SlaveMain.java:202)\n\tat com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe.main(SlaveMainSafe.java:12)\n", - "kind": "error" - } - } - ] - } - ], - "slaves": { - "0": { - "id": 0, - "jvmName": "Java HotSpot(TM) 64-Bit Server VM, 16.3-b01", - "charset": "UTF-8", - "commandLine": "/home/dweiss/Applications/java/jdk1.6.0_20/jre/bin/java -Drt.prefix\u003drt -Drt.seed\u003dB19FBD1BB1231191 -classpath /home/dweiss/carrot2/carrotsearch.labs/randomizedtesting/integration-ant/ant-junit4/target/test-classes:/home/dweiss/carrot2/carrotsearch.labs/randomizedtesting/integration-ant/ant-junit4/target/dependency/junit-4.10.jar:/home/dweiss/carrot2/carrotsearch.labs/randomizedtesting/integration-ant/ant-junit4/target/classes:/home/dweiss/.m2/repository/com/google/guava/guava/10.0.1/guava-10.0.1.jar:/home/dweiss/carrot2/carrotsearch.labs/randomizedtesting/runner/target/classes:/home/dweiss/.m2/repository/com/google/code/gson/gson/2.0/gson-2.0.jar:/home/dweiss/.m2/repository/commons-io/commons-io/2.1/commons-io-2.1.jar com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe -flush @/home/dweiss/carrot2/carrotsearch.labs/randomizedtesting/integration-ant/ant-junit4/target/test-classes/junit4-slave-04421343907870964512.suites", - "systemProperties": { - "file.encoding": "UTF-8", - "file.encoding.pkg": "sun.io", - "file.separator": "/", - "java.awt.graphicsenv": "sun.awt.X11GraphicsEnvironment", - "java.awt.printerjob": "sun.print.PSPrinterJob", - "java.class.path": "/home/dweiss/carrot2/carrotsearch.labs/randomizedtesting/integration-ant/ant-junit4/target/test-classes:/home/dweiss/carrot2/carrotsearch.labs/randomizedtesting/integration-ant/ant-junit4/target/dependency/junit-4.10.jar:/home/dweiss/carrot2/carrotsearch.labs/randomizedtesting/integration-ant/ant-junit4/target/classes:/home/dweiss/.m2/repository/com/google/guava/guava/10.0.1/guava-10.0.1.jar:/home/dweiss/carrot2/carrotsearch.labs/randomizedtesting/runner/target/classes:/home/dweiss/.m2/repository/com/google/code/gson/gson/2.0/gson-2.0.jar:/home/dweiss/.m2/repository/commons-io/commons-io/2.1/commons-io-2.1.jar", - "java.class.version": "50.0", - "java.endorsed.dirs": "/home/dweiss/Applications/java/jdk1.6.0_20/jre/lib/endorsed", - "java.ext.dirs": "/home/dweiss/Applications/java/jdk1.6.0_20/jre/lib/ext:/usr/java/packages/lib/ext", - "java.home": "/home/dweiss/Applications/java/jdk1.6.0_20/jre", - "java.io.tmpdir": "/tmp", - "java.library.path": "/home/dweiss/Applications/java/jdk1.6.0_20/jre/lib/amd64/server:/home/dweiss/Applications/java/jdk1.6.0_20/jre/lib/amd64:/home/dweiss/Applications/java/jdk1.6.0_20/jre/../lib/amd64:/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server:/usr/lib/jvm/java-6-openjdk/jre/lib/amd64:/usr/lib/jvm/java-6-openjdk/jre/../lib/amd64:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib", - "java.runtime.name": "Java(TM) SE Runtime Environment", - "java.runtime.version": "1.6.0_20-b02", - "java.specification.name": "Java Platform API Specification", - "java.specification.vendor": "Sun Microsystems Inc.", - "java.specification.version": "1.6", - "java.vendor": "Sun Microsystems Inc.", - "java.vendor.url": "http://java.sun.com/", - "java.vendor.url.bug": "http://java.sun.com/cgi-bin/bugreport.cgi", - "java.version": "1.6.0_20", - "java.vm.info": "mixed mode", - "java.vm.name": "Java HotSpot(TM) 64-Bit Server VM", - "java.vm.specification.name": "Java Virtual Machine Specification", - "java.vm.specification.vendor": "Sun Microsystems Inc.", - "java.vm.specification.version": "1.0", - "java.vm.vendor": "Sun Microsystems Inc.", - "java.vm.version": "16.3-b01", - "junit4.memory.total": "62259200", - "junit4.processors": "2", - "line.separator": "\n", - "os.arch": "amd64", - "os.name": "Linux", - "os.version": "3.0.0-16-generic", - "path.separator": ":", - "rt.prefix": "rt", - "rt.seed": "B19FBD1BB1231191", - "sun.arch.data.model": "64", - "sun.boot.class.path": "/home/dweiss/Applications/java/jdk1.6.0_20/jre/lib/resources.jar:/home/dweiss/Applications/java/jdk1.6.0_20/jre/lib/rt.jar:/home/dweiss/Applications/java/jdk1.6.0_20/jre/lib/sunrsasign.jar:/home/dweiss/Applications/java/jdk1.6.0_20/jre/lib/jsse.jar:/home/dweiss/Applications/java/jdk1.6.0_20/jre/lib/jce.jar:/home/dweiss/Applications/java/jdk1.6.0_20/jre/lib/charsets.jar:/home/dweiss/Applications/java/jdk1.6.0_20/jre/classes", - "sun.boot.library.path": "/home/dweiss/Applications/java/jdk1.6.0_20/jre/lib/amd64", - "sun.cpu.endian": "little", - "sun.cpu.isalist": "", - "sun.desktop": "gnome", - "sun.io.unicode.encoding": "UnicodeLittle", - "sun.java.launcher": "SUN_STANDARD", - "sun.jnu.encoding": "UTF-8", - "sun.management.compiler": "HotSpot 64-Bit Server Compiler", - "sun.os.patch.level": "unknown", - "user.country": "US", - "user.dir": "/home/dweiss/carrot2/carrotsearch.labs/randomizedtesting/integration-ant/ant-junit4/target/test-classes/S0", - "user.home": "/home/dweiss", - "user.language": "en", - "user.name": "dweiss", - "user.timezone": "" - } - } - } -}); \ No newline at end of file diff --git a/junit4-ant/src/main/resources/com/carrotsearch/junit4/antlib.xml b/junit4-ant/src/main/resources/com/carrotsearch/junit4/antlib.xml deleted file mode 100644 index 7f279515..00000000 --- a/junit4-ant/src/main/resources/com/carrotsearch/junit4/antlib.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/junit4-ant/src/native/com_carrotsearch_ant_tasks_junit4_tests_Crash.h b/junit4-ant/src/native/com_carrotsearch_ant_tasks_junit4_tests_Crash.h deleted file mode 100644 index c23dde5c..00000000 --- a/junit4-ant/src/native/com_carrotsearch_ant_tasks_junit4_tests_Crash.h +++ /dev/null @@ -1,21 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class com_carrotsearch_ant_tasks_junit4_tests_Crash */ - -#ifndef _Included_com_carrotsearch_ant_tasks_junit4_tests_Crash -#define _Included_com_carrotsearch_ant_tasks_junit4_tests_Crash -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: com_carrotsearch_ant_tasks_junit4_tests_Crash - * Method: crashMe - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_com_carrotsearch_ant_tasks_junit4_tests_Crash_crashMe - (JNIEnv *, jclass); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/junit4-ant/src/native/compile-mac.sh b/junit4-ant/src/native/compile-mac.sh deleted file mode 100755 index a2d2a070..00000000 --- a/junit4-ant/src/native/compile-mac.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -CFLAGS="-I /System/Library/Frameworks/JavaVM.framework/Headers/" -gcc -m64 ${CFLAGS} -shared -static -fPIC crash.c -o lib/libcrash64.dylib diff --git a/junit4-ant/src/native/compile.sh b/junit4-ant/src/native/compile.sh deleted file mode 100755 index a5098ce9..00000000 --- a/junit4-ant/src/native/compile.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -CFLAGS="-I ${JAVA_HOME}/include -I ${JAVA_HOME}/include/linux -I ${JAVA_HOME}/include/win32" - -# Linux, 64-bit. -gcc -m64 ${CFLAGS} -fPIC -c crash.c -ld -shared -static -o lib/libcrash64.so *.o - -# Linux, 32-bit. -gcc -m32 ${CFLAGS} -fPIC -c crash.c -ld -melf_i386 -shared -static -o lib/libcrash.so *.o - -# Windows, 32-bit -rm -f *.o -i686-w64-mingw32-gcc ${CFLAGS} -shared -o lib/crash.dll crash.c - -# Windows, 64-bit -rm -f *.o -x86_64-w64-mingw32-gcc ${CFLAGS} -shared -o lib/crash64.dll crash.c - -rm -f *.o diff --git a/junit4-ant/src/native/crash.c b/junit4-ant/src/native/crash.c deleted file mode 100644 index a7a72936..00000000 --- a/junit4-ant/src/native/crash.c +++ /dev/null @@ -1,9 +0,0 @@ - -#include "com_carrotsearch_ant_tasks_junit4_tests_Crash.h" -#include "stdio.h" - -JNIEXPORT void JNICALL Java_com_carrotsearch_ant_tasks_junit4_tests_Crash_crashMe - (JNIEnv * env, jclass clazz) -{ - ((char*) 0)[0] = 0; -} diff --git a/junit4-ant/src/native/lib/crash.dll b/junit4-ant/src/native/lib/crash.dll deleted file mode 100644 index 1741dec4d0db1a33c72b72caf48a0b98a10b339a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64956 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 Z0yjW+_GEf7z{x6%r7c;5)nr%Ze*j{GMvVXf diff --git a/junit4-ant/src/native/lib/libcrash.so b/junit4-ant/src/native/lib/libcrash.so deleted file mode 100644 index 5b9576bd0f00560a4f520436c8a76f76607f9bc7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1475 zcmb_cJ#Q015S@!1Fod8G(S^cv4uXRy7GI*VjT2%y7>FZ<0ERcc_ik@ZY>6TgBfXn_Gjlt8?{@c1wZ7qbo;b@$M#x5Z6yZP4 z*-TOLl9hriNG{2{diw9ECFV(%B*`bSbBF_b2oopLJg59uK8xJLL(^gDtnq#3GXQ(h zlcV*NrAwZQkyL>EvJEfE?=jyS;jsw6jG6Ato6qN~L6RS$3E#E2i`@tEtC(%IbGx$@%t77D&v9X=sUT`r@ZTKxo015IE7 zz^^&BZB{C`^M&2kFf_xf^LB8l;_t&o68YaQ@Rm(;E_@Hle3*JQ5cipH95ybBt zgebAzMB4S;o=?*j(JO^ltnx)K7M zi|gUp;W^>iA*Zn}2h;$h`YR4nbMrZV)bpRv>E7#+KU-qY1a_P&1q7pSJo~PR0IO zMouQ*<04s{b*`Iw(me3=8klhIm7{k<5uE+q-7uKR@6T{a4!YkKb@%c8()LzG)MmX= bF4a|IV`HbrG&&rlkWTkR{la) zHWFL>2us0EBp&C?L$7WuY%K0c&Yai1-@WtQ)pz^$_z?wA!T?ZD-bj8D0yqVgGJsC< z2?YRgIkCFzwtjxRW!0Wv6DHJ=GcFsVV-y`P_v)W`shBtG@|SQOsV?W@L@W^t=6=@P z#H_iMr$O!gc6>a|-xSm$hL|H78Qik;oZ)qA@hUZVTnGOq;siPK#%CkWCl}`uGs%Fv zfUlZ(?r&t?i0*G|rEHYEgIw(IW;aI2)0S>$#^b}A2UPH;K6*Z0|EtmYd_Q_>7du5Y z7EYQ;s;eBmt zDHLJMR@VBiDLAX|>6p&vFs)lw-mwkcN@q|v9dvYi$Hwh~nRVi%-)+anX%?L5%FYD? YCc|*o7_l*$iD5fC_dFq3V&rf9lNcBce1#+!i~ ze~L%$8vhP1-1X+IzPJ0nvdEHXf|KlgZ@%~5%)EIsZ$Hh{X7jlmp*i%FWK_y0%#){v=Kfhoz&II+`OgLvnZ)oGa8-77FyUS9Xe^VwCe4P1#>l?Gwf<`=wKO zTJSbK)9AEK!wbWXjeIX`w2T*6W4-8IWZrgz4O=qSk8EVBp%=AGL;6LZjNkOEN5<5n z$VAo)EmJ|0*5`K*=XXE;n&0jI*q42MCwl!=1fr`6Q11Op%54>LV;6^p_c)jv%**$! z*XzZxR4x}j=c|_nSJ;4gIbUf-37i}5)PatXyJa0;NX%$WaYXUD;{S%ZYV~n(e7)Wc zZ1-+$Bk;mbvE)8*C+|G!#^n8pWK85n+imOB8Eu$g3sQ>@n%w4gz$OXWkX-9;S#tfB zc@uhVKjyvmMuS{VW7`kxS;RKRlceu6&K-DL7r}kUdqAFUvR=*{dgKMTr~dLb#0LJz z&jfSOi7E07L|#QFP1BwXxSv!G_X6(>J~U>fhhL3d@RR7%F1_peroM+7g2_ z)GgFA)Gg@YUr5Ypfl*?*r(-}_9d3b8MEt-j%wz7fX*+z04KmB$!3&O%l_FEO80|2wDHZ=S+aT+H1D pnP;zFR2H9C$;{Q3rYkkGG&{RGvu4&R)3q6MtjM3iFGGG4zX9oEyG{TA diff --git a/junit4-ant/src/proguard/rules.pro b/junit4-ant/src/proguard/rules.pro deleted file mode 100644 index 135259fc..00000000 --- a/junit4-ant/src/proguard/rules.pro +++ /dev/null @@ -1,23 +0,0 @@ - --dontoptimize - --dontnote --dontwarn - --renamepackage com.google=>com.carrotsearch.ant.tasks.junit4.dependencies --renamepackage org.objectweb=>com.carrotsearch.ant.tasks.junit4.dependencies --renamepackage org.apache=>com.carrotsearch.ant.tasks.junit4.dependencies --renamepackage org.simpleframework=>com.carrotsearch.ant.tasks.junit4.dependencies --renamepackage com.carrotsearch.randomizedtesting=>com.carrotsearch.ant.tasks.junit4.dependencies --repackageclasses com.carrotsearch.ant.tasks.junit4.dependencies - --keepattributes SourceFile,LineNumberTable --keepattributes *Annotation* - --keep class com.carrotsearch.ant.** { - ; ; -} - --keep class org.simpleframework.** { - ; ; -} \ No newline at end of file diff --git a/junit4-ant/src/tasks/Tasks/junit4.html b/junit4-ant/src/tasks/Tasks/junit4.html deleted file mode 100644 index 4790031f..00000000 --- a/junit4-ant/src/tasks/Tasks/junit4.html +++ /dev/null @@ -1,701 +0,0 @@ - - - - - - - - - - - JUnit4 Task - - - - -

JUnit4

-

Description

- -

This task runs tests from the JUnit testing framework in versions 4.10 and above. It to some extent -mimics the style of the default ANT's junit task, but adds the following features: -

    -
  • ability to run tests in multiple forked JVMs (isolated JVMs),
  • -
  • ability to load-balance tests based on previous execution history or job-stealing,
  • -
  • seamless integration with randomized runner - to support a global seed for randomized tests and proper seed reporting,
  • -
  • Synchronized and decluttered console output from child JVMs,
  • -
  • Built-in reporting to HTML, JSON and various forms of plain text.
  • -
- -

Note: The latest version of the JUnit framework can be found at -http://www.junit.org. -This task has been tested with JUnit 4.10 and later. -Appropriate junit*.jar must be available in the task's classpath and in the -tested code's classpath. See the examples below. -

- -

External references: More information about randomized testing. -

- -

Parameters

- -

junit4 attempts to be a drop-in replacement for ANT's default junit task, but so attributes -that make little sense have been deprecated and are ignored. Attributes specific to junit4 are highlighted in -light green.

- -
#{label}
"); - column.renderer(row[column.id], html, row); - html.push("
No tests results found
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AttributeDescriptionRequired
printsummaryPrints the summary of all executed, ignored and failed tests after all suites have been - executed. To get per-suite summaries, configure a console report properly (see below).No; default is on.
forkNot used. ANT-junit drop-in compatibility only. Tests are always forked.--
forkmodeNot used. ANT-junit drop-in compatibility only. Tests are always forked into one more more - forked JVMs. Each suite is executed entirely on a single JVM.--
haltonerrorNot used. ANT-junit drop-in compatibility only. Use haltonfailure which handles both errors and failures.--
errorpropertyNot used. ANT-junit drop-in compatibility only. Use failureproperty which handles both errors and failures.--
haltonfailureStop the build process if a test fails (errors are considered failures as well). No; default is on (ANT's junit has the default set to 'off').
failurepropertyThe name of a property to set in the event of a failure - (errors are considered failures as well).No.
filtertraceNot used. ANT-junit drop-in compatibility only. Reports may provide their own filtering capabilities.--
timeoutNot used. ANT-junit drop-in compatibility only. Test runners provide their own timeout facilities.--
maxmemoryMaximum amount of memory to allocate to each forked VM (be careful if using lots of forks). - Note: - If you get java.lang.OutOfMemoryError: Java heap space - in some of your tests then you need to raise the size like - maxmemory="128m"No
jvmThe command used to invoke the forked java virtual machines, the default is 'java'. The command is resolved by - java.lang.Runtime.exec().No; default is java.
dir -

The directory in which to invoke the forked JVMs in. This is by default the project's basedir. - Because multiple JVMs may clash if they are generating files in the current working directory, one can use per-JVM directory - by setting isolateWorkingDirectories attribute to true; in such case each JVM gets a sub-directory - the provided dir. -

-

- See onNonEmptyWorkDirectory attribute for action taken when the forked JVM's work directory is not initially - empty. -

-
No
isolateWorkingDirectoriesIf true current working directories are isolated for each forked JVM. See dir attribute too.No; default is true.
onNonEmptyWorkDirectory -

[Since version 2.5.0]. Specifies the action taken when forked JVM's work directory is not initially empty (contains files - or directories, possibly from a previous run). The values permitted are: -

-
-
fail
-
Fails the build.
-
wipe
-
Tries to wipe the work directory clean before tests begin. Fails the build if unsuccessful.
-
ignore
-
Ignores any existing files and proceeds (not recommended).
-
-
No; default is fail.
newenvironmentDo not propagate the old environment when new - environment variables are specified.No; default is false.
includeantruntimeNot used. ANT-junit drop-in compatibility only.--
showoutputNot used. ANT-junit drop-in compatibility only. Configure console reports appropriately.--
outputtoformattersNot used. ANT-junit drop-in compatibility only. Configure console reports appropriately.--
tempdirSpecify where to store temporary files. These temporary files include a list of suites passed - to each slave JVM so it is usually wise to just leave this attribute unset - the default is to take the value of the - dir attribute or the project's basedir. - No
reloadingNot used. ANT-junit drop-in compatibility only.--
clonevmNot used. ANT-junit drop-in compatibility only.--
logfailedtestsNot used. ANT-junit drop-in compatibility only. Configure console reports appropriately to get - just the failing tests, their output etc.--
enableTestListenerEventsNot used. ANT-junit drop-in compatibility only.--
parallelism - The number of parallel slaves. Can be set to a constant max for the - maximum number of cores returned from Runtime.availableProcessors or - auto for sensible defaults depending on the number of cores. - -

Note: this setting forks physical JVM processes so it multiplies the - requirements for heap memory, IO, etc.

-
No; Can be set to any integer or: 'max', 'auto'. - The default is '1' (sequential execution in a forked JVM).
dynamicAssignmentRatio - Specifies the ratio of suites moved to dynamic assignment list (job-stealing). A dynamic - assignment list dispatches suites to the first idle slave JVM. Theoretically - this is an optimal strategy, but it is usually better to have some static assignments - to avoid communication costs. - -

A ratio of 0 means only static assignments are used. A ratio of 1 means - only dynamic assignments are used.

- -

The list of dynamic assignments is sorted by decreasing cost (always) and - is inherently prone to race conditions in distributing suites. Should there - be an error based on suite-dependency it will not be directly repeatable. In such - case use the per-slave-jvm list of suites file dumped to disk for each slave JVM. - See leaveTemporary attribute. -

No; default is '0.25' (25% of all suites are assigned dynamically).
seed - Specify random seed for anything that is randomized in junit4. The order of suites - execution and suite-JVM assignments are a result of this seed for example. - -

The master seed is also passed to slave JVMs as a system property (to bootstrap randomized runner).

-
No; default is a randomly generated seed.
prefix - Initializes custom prefix for all randomized runner properties. This must be consistent - across all junit4 invocations if done from the same classpath. Use only when REALLY needed. - No; default is randomized runner's prefix.
shuffleOnSlave - Predictably shuffle tests order after balancing. This will help in spreading - lighter and heavier tests over a single slave's execution timeline while - still keeping the same tests order depending on the seed. See nested elements - for configuring load balancers. - No; the default is 'true'.
leaveTemporary - Leave temporary junit4 files after the task quits. This can be used to trace the exact order - of suites executed on each forked JVM for example. - No; default is 'false'.
jvmOutputAction - What should be done on unexpected JVM output? JVM may write directly to the - original descriptors, bypassing redirections of System.out and System.err. Typically, - these messages will be important and should fail the build (permgen space exceeded, - compiler errors, crash dumps). However, certain legitimate logs (gc activity, class loading - logs) are also printed to these streams so sometimes the output can be ignored. - -

Allowed values (any comma-delimited combination of): ignore, listeners, pipe, fail, warn.

-
No; default is 'warn, listeners'; append text report listener - to get the actual JVM output or change to 'warn, pipe' to get the output piped to system out.
sysouts - If set to true, any sysout and syserr calls will be written to original - output and error streams (and in effect will appear as "jvm output". By default - sysout and syserrs are captured and proxied to the event stream to be synchronized - with other test events (and properly handled by reports) but occasionally - one may want to synchronize them with direct JVM output (to synchronize - with compiler output or GC output for example). - -

See examples below on examples of capturing full JVM output.

-
No; default is 'false'.
heartbeat - A duration (in seconds) before an event is dispatched about forked JVM inactivity. - This can be useful to report hung or very long tests. Heartbeat information will - include an approximate location inside the non-responding JVM (suite or test case). - No; default is '0'.
uniqueSuiteNames - Allow or disallow duplicate suite names in resource collections. By default this option - is true because certain ANT-compatible report types (like XML reports) - will have a problem with duplicate suite names (will overwrite files). - No; default is 'true'.
ifNoTests - Defines the behavior when no tests were executed successfully or failed (either - there were no tests at all or all of them were filtered out). One of the following - enum constants: 'ignore', 'warn' or 'fail'. - No; default is 'ignore'.
- - -

Nested Elements

- -

The <junit4> task supports a nested elements. Some of them are compatible with -ANT's default <junit> task while others are unique to <junit4>. - - -

Specifying classpath for tests

- -The <classpath> element represents a PATH like structure to be used for each -forked JVM. Note that classpath should include suiteable junit*.jar, otherwise your tests -wont run. - - -

Specifying test suite classes

- -Unlike standard <junit> task, <junit4> defines suite classes as -resources to .class files. These resources can originate from any resource collection and -there can be any number of resource collections with such resources. For example this definition -includes all suite classes from a ZIP file (JAR file), excluding nested classes: - -

-
- - -

jvmarg

- -

Additional parameters may be passed to the new JVM via nested <jvmarg> elements. For example:

- -

-
- -

would run the JVM with a serial garbage collector on HotSpot JVM.

- - - -

sysproperty

- -

Use nested <sysproperty> elements to specify system -properties required by the tests. These properties will be made available -to the forked JVMs during their execution. The attributes for this element are the same -as for environment variables.

- -

An extended attribute <ignoreEmpty> is supported which, if defined, -causes the property NOT to be defined in the forked JVM (as opposed to passing an empty property -value).

- -
- -

would run the test in ANT's VM and make the project's basedir property -available to the test (note the current working directory of a forked JVM will not be the - basedir typically).

- - - -

syspropertyset

- -

You can specify a set of properties to be passed to the target JVM as system properties -with syspropertysets. -This target behaves much like the default in ANT but allows a dynamic set of (remapped) -properties to be resolved at runtime. Similar to sysproperty, this -tag also supports ignoreEmpty attribute to work around -bugs -with local properties in ANT.

- -
- - -

env

- -

It is possible to specify environment variables to pass to the -forked VM via nested <env> elements. For a description -of the <env> element's attributes, see the -description in the exec task.

- - - -

bootclasspath

- -

The location of bootstrap class files can be specified using this -PATH like structure.

- - - -

assertions

- -

You can control enablement of Java 1.4 assertions with an -<assertions> -subelement.

- -

listeners and reports

- -

There is no notion of "reports" in junit4. Reports are just listeners -that attach to the even stream and can produce something (to the console, file or otherwise). You -can also attach your own listeners if you like (although you'd have to peek at the code of existing -listeners to get the feeling how this is done -- communication is via events not interfaces).

- -

report-text

- -

There are a few predefined listeners to choose from. By far the most common will be report-text -which produces console output (or plain text file). A plain text report configuration may look like this: -

- -
- -

This listener supports stack trace filtering to reduce verbosity (console output, for -example). For production or integration builds, it is recommended to keep the full stacks. -For developer runs, the default set of filters (enabled by default) can declutter the output -a bit. An example stack trace filter, with default options and two custom filters, is shown -below.

- -
- -

The level of verbosity of the output can be fine-tuned to one's needs by disabling -or enabling test statuses and suite summaries or each test's output. Experimenting -highly recommended.

- -

report-ant-xml

- -

Another listener is report-ant-xml which can produce XML files suitable -for junitreport task (although -we highly recommend using the built-in JSON report.

- -
- -

report-json

- -

Yet another built-in listener is producing a modern JSON output with test data and -an accompanying HTML5 file for visualizing it:

- -
- -

An example of a HTML5 report produced by the above can be seen here, for example. - -

runlisteners

- -

You can attach custom JUnit 4 RunListeners to your tests like this:

- -
- -

Each RunListener defined is added to each class before execution and removed after

- -

Load balancing of test suites

- -

Suites can be scattered across forked JVMs randomly or using a greedy load-balancing algorithm -(and followed by job-stealing if needed). For load balancing, previous execution -statistics will be needed. These statistics should ideally come from a single machine and multiple -executions so that they average the influence of the environment etc.

- -

A dedicated listener is used to collect and update statistics. The configuration below shows -both the listener and a balancer configuration. The balancer uses multiple sources for collecting -statistics (for example precomputed statistics and previous local runs):

- -
- - -

Capturing original JVM output

- -

JUnit4 has been designed to run reports and aggregation of test events on the master -JVM, not on the forked JVMs. This slightly complicates things when diagnostic JVM messages -are used because these messages are printed directly to original stream descriptors -by the JVM, bypassing System.out or System.err substitutions.

- -

In those rare cases when the original JVM output streams are needed (possibly -mixed with what the tests have printed), junit4 can be configured to leave the original -streams on disk or pipe them to ANT's output. An example is shown below:

- -
- -

Should one need to preserve the original output files (in case they are large, for example), -the configuration would then look as follows:

- -
- -

This would result in the following message being printed to ANT (note -the output file name contains an execution-unique element to avoid clashing with other -forked JVMs or builds).

- -
-[junit4:junit4] JVM J0: stdout was not empty, see: /home/[...]/junit4-J0-1058309761ea5fafd.sysout
-[junit4:junit4] JVM J0: stderr was not empty, see: /home/[...]/junit4-J0-1058309761ea5fafd.syserr
-
- - - diff --git a/junit4-ant/src/tasks/index.html b/junit4-ant/src/tasks/index.html deleted file mode 100644 index 35f1ea69..00000000 --- a/junit4-ant/src/tasks/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -Follow to: junit4 documentation. - - diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-apollo.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-apollo.js deleted file mode 100644 index 7098baf4..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-apollo.js +++ /dev/null @@ -1,2 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["com",/^#[^\n\r]*/,null,"#"],["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,null,'"']],[["kwd",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/, -null],["typ",/^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[ES]?BANK=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[!-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["apollo","agc","aea"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-clj.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-clj.js deleted file mode 100644 index 542a2205..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-clj.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - Copyright (C) 2011 Google Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -var a=null; -PR.registerLangHandler(PR.createSimpleLexer([["opn",/^[([{]+/,a,"([{"],["clo",/^[)\]}]+/,a,")]}"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:def|if|do|let|quote|var|fn|loop|recur|throw|try|monitor-enter|monitor-exit|defmacro|defn|defn-|macroexpand|macroexpand-1|for|doseq|dosync|dotimes|and|or|when|not|assert|doto|proxy|defstruct|first|rest|cons|defprotocol|deftype|defrecord|reify|defmulti|defmethod|meta|with-meta|ns|in-ns|create-ns|import|intern|refer|alias|namespace|resolve|ref|deref|refset|new|set!|memfn|to-array|into-array|aset|gen-class|reduce|map|filter|find|nil?|empty?|hash-map|hash-set|vec|vector|seq|flatten|reverse|assoc|dissoc|list|list?|disj|get|union|difference|intersection|extend|extend-type|extend-protocol|prn)\b/,a], -["typ",/^:[\dA-Za-z-]+/]]),["clj"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-css.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-css.js deleted file mode 100644 index 041e1f59..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-css.js +++ /dev/null @@ -1,2 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", -/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-go.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-go.js deleted file mode 100644 index fc18dc07..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-go.js +++ /dev/null @@ -1 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["pln",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])+(?:'|$)|`[^`]*(?:`|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\/\*[\S\s]*?\*\/)/],["pln",/^(?:[^"'/`]|\/(?![*/]))+/]]),["go"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-hs.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-hs.js deleted file mode 100644 index 9d77b083..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-hs.js +++ /dev/null @@ -1,2 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t-\r ]+/,null,"\t\n \r "],["str",/^"(?:[^\n\f\r"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["str",/^'(?:[^\n\f\r'\\]|\\[^&])'?/,null,"'"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)/i,null,"0123456789"]],[["com",/^(?:--+[^\n\f\r]*|{-(?:[^-]|-+[^}-])*-})/],["kwd",/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^\d'A-Za-z]|$)/, -null],["pln",/^(?:[A-Z][\w']*\.)*[A-Za-z][\w']*/],["pun",/^[^\d\t-\r "'A-Za-z]+/]]),["hs"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-lisp.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-lisp.js deleted file mode 100644 index 02a30e8d..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-lisp.js +++ /dev/null @@ -1,3 +0,0 @@ -var a=null; -PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,a,"("],["clo",/^\)+/,a,")"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,a], -["lit",/^[+-]?(?:[#0]x[\da-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[de][+-]?\d+)?)/i],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[_a-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/i],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["cl","el","lisp","scm"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-lua.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-lua.js deleted file mode 100644 index e83a3c46..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-lua.js +++ /dev/null @@ -1,2 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$))/,null,"\"'"]],[["com",/^--(?:\[(=*)\[[\S\s]*?(?:]\1]|$)|[^\n\r]*)/],["str",/^\[(=*)\[[\S\s]*?(?:]\1]|$)/],["kwd",/^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i], -["pln",/^[_a-z]\w*/i],["pun",/^[^\w\t\n\r \xa0][^\w\t\n\r "'+=\xa0-]*/]]),["lua"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-ml.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-ml.js deleted file mode 100644 index 6df02d72..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-ml.js +++ /dev/null @@ -1,2 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["com",/^#(?:if[\t\n\r \xa0]+(?:[$_a-z][\w']*|``[^\t\n\r`]*(?:``|$))|else|endif|light)/i,null,"#"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])(?:'|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\(\*[\S\s]*?\*\))/],["kwd",/^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/], -["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^(?:[_a-z][\w']*[!#?]?|``[^\t\n\r`]*(?:``|$))/i],["pun",/^[^\w\t\n\r "'\xa0]+/]]),["fs","ml"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-n.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-n.js deleted file mode 100644 index 6c2e85b9..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-n.js +++ /dev/null @@ -1,4 +0,0 @@ -var a=null; -PR.registerLangHandler(PR.createSimpleLexer([["str",/^(?:'(?:[^\n\r'\\]|\\.)*'|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,a,'"'],["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,a,"#"],["pln",/^\s+/,a," \r\n\t\xa0"]],[["str",/^@"(?:[^"]|"")*(?:"|$)/,a],["str",/^<#[^#>]*(?:#>|$)/,a],["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,a],["com",/^\/\/[^\n\r]*/,a],["com",/^\/\*[\S\s]*?(?:\*\/|$)/, -a],["kwd",/^(?:abstract|and|as|base|catch|class|def|delegate|enum|event|extern|false|finally|fun|implements|interface|internal|is|macro|match|matches|module|mutable|namespace|new|null|out|override|params|partial|private|protected|public|ref|sealed|static|struct|syntax|this|throw|true|try|type|typeof|using|variant|virtual|volatile|when|where|with|assert|assert2|async|break|checked|continue|do|else|ensures|for|foreach|if|late|lock|new|nolate|otherwise|regexp|repeat|requires|return|surroundwith|unchecked|unless|using|while|yield)\b/, -a],["typ",/^(?:array|bool|byte|char|decimal|double|float|int|list|long|object|sbyte|short|string|ulong|uint|ufloat|ulong|ushort|void)\b/,a],["lit",/^@[$_a-z][\w$@]*/i,a],["typ",/^@[A-Z]+[a-z][\w$@]*/,a],["pln",/^'?[$_a-z][\w$@]*/i,a],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,a,"0123456789"],["pun",/^.[^\s\w"-$'./@`]*/,a]]),["n","nemerle"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-proto.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-proto.js deleted file mode 100644 index f006ad8c..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-proto.js +++ /dev/null @@ -1 +0,0 @@ -PR.registerLangHandler(PR.sourceDecorator({keywords:"bytes,default,double,enum,extend,extensions,false,group,import,max,message,option,optional,package,repeated,required,returns,rpc,service,syntax,to,true",types:/^(bool|(double|s?fixed|[su]?int)(32|64)|float|string)\b/,cStyleComments:!0}),["proto"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-scala.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-scala.js deleted file mode 100644 index 60d034de..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-scala.js +++ /dev/null @@ -1,2 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["str",/^"(?:""(?:""?(?!")|[^"\\]|\\.)*"{0,3}|(?:[^\n\r"\\]|\\.)*"?)/,null,'"'],["lit",/^`(?:[^\n\r\\`]|\\.)*`?/,null,"`"],["pun",/^[!#%&(--:-@[-^{-~]+/,null,"!#%&()*+,-:;<=>?@[\\]^{|}~"]],[["str",/^'(?:[^\n\r'\\]|\\(?:'|[^\n\r']+))'/],["lit",/^'[$A-Z_a-z][\w$]*(?![\w$'])/],["kwd",/^(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|object|override|package|private|protected|requires|return|sealed|super|throw|trait|try|type|val|var|while|with|yield)\b/], -["lit",/^(?:true|false|null|this)\b/],["lit",/^(?:0(?:[0-7]+|x[\da-f]+)l?|(?:0|[1-9]\d*)(?:(?:\.\d+)?(?:e[+-]?\d+)?f?|l?)|\\.\d+(?:e[+-]?\d+)?f?)/i],["typ",/^[$_]*[A-Z][\d$A-Z_]*[a-z][\w$]*/],["pln",/^[$A-Z_a-z][\w$]*/],["com",/^\/(?:\/.*|\*(?:\/|\**[^*/])*(?:\*+\/?)?)/],["pun",/^(?:\.+|\/)/]]),["scala"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-sql.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-sql.js deleted file mode 100644 index da705b0b..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-sql.js +++ /dev/null @@ -1,2 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["str",/^(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/,null,"\"'"]],[["com",/^(?:--[^\n\r]*|\/\*[\S\s]*?(?:\*\/|$))/],["kwd",/^(?:add|all|alter|and|any|as|asc|authorization|backup|begin|between|break|browse|bulk|by|cascade|case|check|checkpoint|close|clustered|coalesce|collate|column|commit|compute|constraint|contains|containstable|continue|convert|create|cross|current|current_date|current_time|current_timestamp|current_user|cursor|database|dbcc|deallocate|declare|default|delete|deny|desc|disk|distinct|distributed|double|drop|dummy|dump|else|end|errlvl|escape|except|exec|execute|exists|exit|fetch|file|fillfactor|for|foreign|freetext|freetexttable|from|full|function|goto|grant|group|having|holdlock|identity|identitycol|identity_insert|if|in|index|inner|insert|intersect|into|is|join|key|kill|left|like|lineno|load|match|merge|national|nocheck|nonclustered|not|null|nullif|of|off|offsets|on|open|opendatasource|openquery|openrowset|openxml|option|or|order|outer|over|percent|plan|precision|primary|print|proc|procedure|public|raiserror|read|readtext|reconfigure|references|replication|restore|restrict|return|revoke|right|rollback|rowcount|rowguidcol|rule|save|schema|select|session_user|set|setuser|shutdown|some|statistics|system_user|table|textsize|then|to|top|tran|transaction|trigger|truncate|tsequal|union|unique|update|updatetext|use|user|using|values|varying|view|waitfor|when|where|while|with|writetext)(?=[^\w-]|$)/i, -null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^[_a-z][\w-]*/i],["pun",/^[^\w\t\n\r "'\xa0][^\w\t\n\r "'+\xa0-]*/]]),["sql"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-tex.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-tex.js deleted file mode 100644 index ce96fbbd..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-tex.js +++ /dev/null @@ -1 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["com",/^%[^\n\r]*/,null,"%"]],[["kwd",/^\\[@-Za-z]+/],["kwd",/^\\./],["typ",/^[$&]/],["lit",/[+-]?(?:\.\d+|\d+(?:\.\d*)?)(cm|em|ex|in|pc|pt|bp|mm)/i],["pun",/^[()=[\]{}]+/]]),["latex","tex"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-vb.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-vb.js deleted file mode 100644 index 07506b03..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-vb.js +++ /dev/null @@ -1,2 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0\u2028\u2029]+/,null,"\t\n\r Â\xa0

"],["str",/^(?:["\u201c\u201d](?:[^"\u201c\u201d]|["\u201c\u201d]{2})(?:["\u201c\u201d]c|$)|["\u201c\u201d](?:[^"\u201c\u201d]|["\u201c\u201d]{2})*(?:["\u201c\u201d]|$))/i,null,'"“â€'],["com",/^['\u2018\u2019].*/,null,"'‘’"]],[["kwd",/^(?:addhandler|addressof|alias|and|andalso|ansi|as|assembly|auto|boolean|byref|byte|byval|call|case|catch|cbool|cbyte|cchar|cdate|cdbl|cdec|char|cint|class|clng|cobj|const|cshort|csng|cstr|ctype|date|decimal|declare|default|delegate|dim|directcast|do|double|each|else|elseif|end|endif|enum|erase|error|event|exit|finally|for|friend|function|get|gettype|gosub|goto|handles|if|implements|imports|in|inherits|integer|interface|is|let|lib|like|long|loop|me|mod|module|mustinherit|mustoverride|mybase|myclass|namespace|new|next|not|notinheritable|notoverridable|object|on|option|optional|or|orelse|overloads|overridable|overrides|paramarray|preserve|private|property|protected|public|raiseevent|readonly|redim|removehandler|resume|return|select|set|shadows|shared|short|single|static|step|stop|string|structure|sub|synclock|then|throw|to|try|typeof|unicode|until|variant|wend|when|while|with|withevents|writeonly|xor|endif|gosub|let|variant|wend)\b/i, -null],["com",/^rem.*/i],["lit",/^(?:true\b|false\b|nothing\b|\d+(?:e[+-]?\d+[dfr]?|[dfilrs])?|(?:&h[\da-f]+|&o[0-7]+)[ils]?|\d*\.\d+(?:e[+-]?\d+)?[dfr]?|#\s+(?:\d+[/-]\d+[/-]\d+(?:\s+\d+:\d+(?::\d+)?(\s*(?:am|pm))?)?|\d+:\d+(?::\d+)?(\s*(?:am|pm))?)\s+#)/i],["pln",/^(?:(?:[a-z]|_\w)\w*|\[(?:[a-z]|_\w)\w*])/i],["pun",/^[^\w\t\n\r "'[\]\xa0\u2018\u2019\u201c\u201d\u2028\u2029]+/],["pun",/^(?:\[|])/]]),["vb","vbs"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-vhdl.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-vhdl.js deleted file mode 100644 index 128b5b6c..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-vhdl.js +++ /dev/null @@ -1,3 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"]],[["str",/^(?:[box]?"(?:[^"]|"")*"|'.')/i],["com",/^--[^\n\r]*/],["kwd",/^(?:abs|access|after|alias|all|and|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|mod|nand|new|next|nor|not|null|of|on|open|or|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|rem|report|return|rol|ror|select|severity|shared|signal|sla|sll|sra|srl|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with|xnor|xor)(?=[^\w-]|$)/i, -null],["typ",/^(?:bit|bit_vector|character|boolean|integer|real|time|string|severity_level|positive|natural|signed|unsigned|line|text|std_u?logic(?:_vector)?)(?=[^\w-]|$)/i,null],["typ",/^'(?:active|ascending|base|delayed|driving|driving_value|event|high|image|instance_name|last_active|last_event|last_value|left|leftof|length|low|path_name|pos|pred|quiet|range|reverse_range|right|rightof|simple_name|stable|succ|transaction|val|value)(?=[^\w-]|$)/i,null],["lit",/^\d+(?:_\d+)*(?:#[\w.\\]+#(?:[+-]?\d+(?:_\d+)*)?|(?:\.\d+(?:_\d+)*)?(?:e[+-]?\d+(?:_\d+)*)?)/i], -["pln",/^(?:[a-z]\w*|\\[^\\]*\\)/i],["pun",/^[^\w\t\n\r "'\xa0][^\w\t\n\r "'\xa0-]*/]]),["vhdl","vhd"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-wiki.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-wiki.js deleted file mode 100644 index 9b0b4487..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-wiki.js +++ /dev/null @@ -1,2 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\d\t a-gi-z\xa0]+/,null,"\t Â\xa0abcdefgijklmnopqrstuvwxyz0123456789"],["pun",/^[*=[\]^~]+/,null,"=*~^[]"]],[["lang-wiki.meta",/(?:^^|\r\n?|\n)(#[a-z]+)\b/],["lit",/^[A-Z][a-z][\da-z]+[A-Z][a-z][^\W_]+\b/],["lang-",/^{{{([\S\s]+?)}}}/],["lang-",/^`([^\n\r`]+)`/],["str",/^https?:\/\/[^\s#/?]*(?:\/[^\s#?]*)?(?:\?[^\s#]*)?(?:#\S*)?/i],["pln",/^(?:\r\n|[\S\s])[^\n\r#*=A-[^`h{~]*/]]),["wiki"]); -PR.registerLangHandler(PR.createSimpleLexer([["kwd",/^#[a-z]+/i,null,"#"]],[]),["wiki.meta"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-xq.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-xq.js deleted file mode 100644 index e323ae32..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-xq.js +++ /dev/null @@ -1,3 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["var pln",/^\$[\w-]+/,null,"$"]],[["pln",/^[\s=][<>][\s=]/],["lit",/^@[\w-]+/],["tag",/^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["com",/^\(:[\S\s]*?:\)/],["pln",/^[(),/;[\]{}]$/],["str",/^(?:"(?:[^"\\{]|\\[\S\s])*(?:"|$)|'(?:[^'\\{]|\\[\S\s])*(?:'|$))/,null,"\"'"],["kwd",/^(?:xquery|where|version|variable|union|typeswitch|treat|to|then|text|stable|sortby|some|self|schema|satisfies|returns|return|ref|processing-instruction|preceding-sibling|preceding|precedes|parent|only|of|node|namespace|module|let|item|intersect|instance|in|import|if|function|for|follows|following-sibling|following|external|except|every|else|element|descending|descendant-or-self|descendant|define|default|declare|comment|child|cast|case|before|attribute|assert|ascending|as|ancestor-or-self|ancestor|after|eq|order|by|or|and|schema-element|document-node|node|at)\b/], -["typ",/^(?:xs:yearMonthDuration|xs:unsignedLong|xs:time|xs:string|xs:short|xs:QName|xs:Name|xs:long|xs:integer|xs:int|xs:gYearMonth|xs:gYear|xs:gMonthDay|xs:gDay|xs:float|xs:duration|xs:double|xs:decimal|xs:dayTimeDuration|xs:dateTime|xs:date|xs:byte|xs:boolean|xs:anyURI|xf:yearMonthDuration)\b/,null],["fun pln",/^(?:xp:dereference|xinc:node-expand|xinc:link-references|xinc:link-expand|xhtml:restructure|xhtml:clean|xhtml:add-lists|xdmp:zip-manifest|xdmp:zip-get|xdmp:zip-create|xdmp:xquery-version|xdmp:word-convert|xdmp:with-namespaces|xdmp:version|xdmp:value|xdmp:user-roles|xdmp:user-last-login|xdmp:user|xdmp:url-encode|xdmp:url-decode|xdmp:uri-is-file|xdmp:uri-format|xdmp:uri-content-type|xdmp:unquote|xdmp:unpath|xdmp:triggers-database|xdmp:trace|xdmp:to-json|xdmp:tidy|xdmp:subbinary|xdmp:strftime|xdmp:spawn-in|xdmp:spawn|xdmp:sleep|xdmp:shutdown|xdmp:set-session-field|xdmp:set-response-encoding|xdmp:set-response-content-type|xdmp:set-response-code|xdmp:set-request-time-limit|xdmp:set|xdmp:servers|xdmp:server-status|xdmp:server-name|xdmp:server|xdmp:security-database|xdmp:security-assert|xdmp:schema-database|xdmp:save|xdmp:role-roles|xdmp:role|xdmp:rethrow|xdmp:restart|xdmp:request-timestamp|xdmp:request-status|xdmp:request-cancel|xdmp:request|xdmp:redirect-response|xdmp:random|xdmp:quote|xdmp:query-trace|xdmp:query-meters|xdmp:product-edition|xdmp:privilege-roles|xdmp:privilege|xdmp:pretty-print|xdmp:powerpoint-convert|xdmp:platform|xdmp:permission|xdmp:pdf-convert|xdmp:path|xdmp:octal-to-integer|xdmp:node-uri|xdmp:node-replace|xdmp:node-kind|xdmp:node-insert-child|xdmp:node-insert-before|xdmp:node-insert-after|xdmp:node-delete|xdmp:node-database|xdmp:mul64|xdmp:modules-root|xdmp:modules-database|xdmp:merging|xdmp:merge-cancel|xdmp:merge|xdmp:md5|xdmp:logout|xdmp:login|xdmp:log-level|xdmp:log|xdmp:lock-release|xdmp:lock-acquire|xdmp:load|xdmp:invoke-in|xdmp:invoke|xdmp:integer-to-octal|xdmp:integer-to-hex|xdmp:http-put|xdmp:http-post|xdmp:http-options|xdmp:http-head|xdmp:http-get|xdmp:http-delete|xdmp:hosts|xdmp:host-status|xdmp:host-name|xdmp:host|xdmp:hex-to-integer|xdmp:hash64|xdmp:hash32|xdmp:has-privilege|xdmp:groups|xdmp:group-serves|xdmp:group-servers|xdmp:group-name|xdmp:group-hosts|xdmp:group|xdmp:get-session-field-names|xdmp:get-session-field|xdmp:get-response-encoding|xdmp:get-response-code|xdmp:get-request-username|xdmp:get-request-user|xdmp:get-request-url|xdmp:get-request-protocol|xdmp:get-request-path|xdmp:get-request-method|xdmp:get-request-header-names|xdmp:get-request-header|xdmp:get-request-field-names|xdmp:get-request-field-filename|xdmp:get-request-field-content-type|xdmp:get-request-field|xdmp:get-request-client-certificate|xdmp:get-request-client-address|xdmp:get-request-body|xdmp:get-current-user|xdmp:get-current-roles|xdmp:get|xdmp:function-name|xdmp:function-module|xdmp:function|xdmp:from-json|xdmp:forests|xdmp:forest-status|xdmp:forest-restore|xdmp:forest-restart|xdmp:forest-name|xdmp:forest-delete|xdmp:forest-databases|xdmp:forest-counts|xdmp:forest-clear|xdmp:forest-backup|xdmp:forest|xdmp:filesystem-file|xdmp:filesystem-directory|xdmp:exists|xdmp:excel-convert|xdmp:eval-in|xdmp:eval|xdmp:estimate|xdmp:email|xdmp:element-content-type|xdmp:elapsed-time|xdmp:document-set-quality|xdmp:document-set-property|xdmp:document-set-properties|xdmp:document-set-permissions|xdmp:document-set-collections|xdmp:document-remove-properties|xdmp:document-remove-permissions|xdmp:document-remove-collections|xdmp:document-properties|xdmp:document-locks|xdmp:document-load|xdmp:document-insert|xdmp:document-get-quality|xdmp:document-get-properties|xdmp:document-get-permissions|xdmp:document-get-collections|xdmp:document-get|xdmp:document-forest|xdmp:document-delete|xdmp:document-add-properties|xdmp:document-add-permissions|xdmp:document-add-collections|xdmp:directory-properties|xdmp:directory-locks|xdmp:directory-delete|xdmp:directory-create|xdmp:directory|xdmp:diacritic-less|xdmp:describe|xdmp:default-permissions|xdmp:default-collections|xdmp:databases|xdmp:database-restore-validate|xdmp:database-restore-status|xdmp:database-restore-cancel|xdmp:database-restore|xdmp:database-name|xdmp:database-forests|xdmp:database-backup-validate|xdmp:database-backup-status|xdmp:database-backup-purge|xdmp:database-backup-cancel|xdmp:database-backup|xdmp:database|xdmp:collection-properties|xdmp:collection-locks|xdmp:collection-delete|xdmp:collation-canonical-uri|xdmp:castable-as|xdmp:can-grant-roles|xdmp:base64-encode|xdmp:base64-decode|xdmp:architecture|xdmp:apply|xdmp:amp-roles|xdmp:amp|xdmp:add64|xdmp:add-response-header|xdmp:access|trgr:trigger-set-recursive|trgr:trigger-set-permissions|trgr:trigger-set-name|trgr:trigger-set-module|trgr:trigger-set-event|trgr:trigger-set-description|trgr:trigger-remove-permissions|trgr:trigger-module|trgr:trigger-get-permissions|trgr:trigger-enable|trgr:trigger-disable|trgr:trigger-database-online-event|trgr:trigger-data-event|trgr:trigger-add-permissions|trgr:remove-trigger|trgr:property-content|trgr:pre-commit|trgr:post-commit|trgr:get-trigger-by-id|trgr:get-trigger|trgr:document-scope|trgr:document-content|trgr:directory-scope|trgr:create-trigger|trgr:collection-scope|trgr:any-property-content|thsr:set-entry|thsr:remove-term|thsr:remove-synonym|thsr:remove-entry|thsr:query-lookup|thsr:lookup|thsr:load|thsr:insert|thsr:expand|thsr:add-synonym|spell:suggest-detailed|spell:suggest|spell:remove-word|spell:make-dictionary|spell:load|spell:levenshtein-distance|spell:is-correct|spell:insert|spell:double-metaphone|spell:add-word|sec:users-collection|sec:user-set-roles|sec:user-set-password|sec:user-set-name|sec:user-set-description|sec:user-set-default-permissions|sec:user-set-default-collections|sec:user-remove-roles|sec:user-privileges|sec:user-get-roles|sec:user-get-description|sec:user-get-default-permissions|sec:user-get-default-collections|sec:user-doc-permissions|sec:user-doc-collections|sec:user-add-roles|sec:unprotect-collection|sec:uid-for-name|sec:set-realm|sec:security-version|sec:security-namespace|sec:security-installed|sec:security-collection|sec:roles-collection|sec:role-set-roles|sec:role-set-name|sec:role-set-description|sec:role-set-default-permissions|sec:role-set-default-collections|sec:role-remove-roles|sec:role-privileges|sec:role-get-roles|sec:role-get-description|sec:role-get-default-permissions|sec:role-get-default-collections|sec:role-doc-permissions|sec:role-doc-collections|sec:role-add-roles|sec:remove-user|sec:remove-role-from-users|sec:remove-role-from-role|sec:remove-role-from-privileges|sec:remove-role-from-amps|sec:remove-role|sec:remove-privilege|sec:remove-amp|sec:protect-collection|sec:privileges-collection|sec:privilege-set-roles|sec:privilege-set-name|sec:privilege-remove-roles|sec:privilege-get-roles|sec:privilege-add-roles|sec:priv-doc-permissions|sec:priv-doc-collections|sec:get-user-names|sec:get-unique-elem-id|sec:get-role-names|sec:get-role-ids|sec:get-privilege|sec:get-distinct-permissions|sec:get-collection|sec:get-amp|sec:create-user-with-role|sec:create-user|sec:create-role|sec:create-privilege|sec:create-amp|sec:collections-collection|sec:collection-set-permissions|sec:collection-remove-permissions|sec:collection-get-permissions|sec:collection-add-permissions|sec:check-admin|sec:amps-collection|sec:amp-set-roles|sec:amp-remove-roles|sec:amp-get-roles|sec:amp-doc-permissions|sec:amp-doc-collections|sec:amp-add-roles|search:unparse|search:suggest|search:snippet|search:search|search:resolve-nodes|search:resolve|search:remove-constraint|search:parse|search:get-default-options|search:estimate|search:check-options|prof:value|prof:reset|prof:report|prof:invoke|prof:eval|prof:enable|prof:disable|prof:allowed|ppt:clean|pki:template-set-request|pki:template-set-name|pki:template-set-key-type|pki:template-set-key-options|pki:template-set-description|pki:template-in-use|pki:template-get-version|pki:template-get-request|pki:template-get-name|pki:template-get-key-type|pki:template-get-key-options|pki:template-get-id|pki:template-get-description|pki:need-certificate|pki:is-temporary|pki:insert-trusted-certificates|pki:insert-template|pki:insert-signed-certificates|pki:insert-certificate-revocation-list|pki:get-trusted-certificate-ids|pki:get-template-ids|pki:get-template-certificate-authority|pki:get-template-by-name|pki:get-template|pki:get-pending-certificate-requests-xml|pki:get-pending-certificate-requests-pem|pki:get-pending-certificate-request|pki:get-certificates-for-template-xml|pki:get-certificates-for-template|pki:get-certificates|pki:get-certificate-xml|pki:get-certificate-pem|pki:get-certificate|pki:generate-temporary-certificate-if-necessary|pki:generate-temporary-certificate|pki:generate-template-certificate-authority|pki:generate-certificate-request|pki:delete-template|pki:delete-certificate|pki:create-template|pdf:make-toc|pdf:insert-toc-headers|pdf:get-toc|pdf:clean|p:status-transition|p:state-transition|p:remove|p:pipelines|p:insert|p:get-by-id|p:get|p:execute|p:create|p:condition|p:collection|p:action|ooxml:runs-merge|ooxml:package-uris|ooxml:package-parts-insert|ooxml:package-parts|msword:clean|mcgm:polygon|mcgm:point|mcgm:geospatial-query-from-elements|mcgm:geospatial-query|mcgm:circle|math:tanh|math:tan|math:sqrt|math:sinh|math:sin|math:pow|math:modf|math:log10|math:log|math:ldexp|math:frexp|math:fmod|math:floor|math:fabs|math:exp|math:cosh|math:cos|math:ceil|math:atan2|math:atan|math:asin|math:acos|map:put|map:map|map:keys|map:get|map:delete|map:count|map:clear|lnk:to|lnk:remove|lnk:insert|lnk:get|lnk:from|lnk:create|kml:polygon|kml:point|kml:interior-polygon|kml:geospatial-query-from-elements|kml:geospatial-query|kml:circle|kml:box|gml:polygon|gml:point|gml:interior-polygon|gml:geospatial-query-from-elements|gml:geospatial-query|gml:circle|gml:box|georss:point|georss:geospatial-query|georss:circle|geo:polygon|geo:point|geo:interior-polygon|geo:geospatial-query-from-elements|geo:geospatial-query|geo:circle|geo:box|fn:zero-or-one|fn:years-from-duration|fn:year-from-dateTime|fn:year-from-date|fn:upper-case|fn:unordered|fn:true|fn:translate|fn:trace|fn:tokenize|fn:timezone-from-time|fn:timezone-from-dateTime|fn:timezone-from-date|fn:sum|fn:subtract-dateTimes-yielding-yearMonthDuration|fn:subtract-dateTimes-yielding-dayTimeDuration|fn:substring-before|fn:substring-after|fn:substring|fn:subsequence|fn:string-to-codepoints|fn:string-pad|fn:string-length|fn:string-join|fn:string|fn:static-base-uri|fn:starts-with|fn:seconds-from-time|fn:seconds-from-duration|fn:seconds-from-dateTime|fn:round-half-to-even|fn:round|fn:root|fn:reverse|fn:resolve-uri|fn:resolve-QName|fn:replace|fn:remove|fn:QName|fn:prefix-from-QName|fn:position|fn:one-or-more|fn:number|fn:not|fn:normalize-unicode|fn:normalize-space|fn:node-name|fn:node-kind|fn:nilled|fn:namespace-uri-from-QName|fn:namespace-uri-for-prefix|fn:namespace-uri|fn:name|fn:months-from-duration|fn:month-from-dateTime|fn:month-from-date|fn:minutes-from-time|fn:minutes-from-duration|fn:minutes-from-dateTime|fn:min|fn:max|fn:matches|fn:lower-case|fn:local-name-from-QName|fn:local-name|fn:last|fn:lang|fn:iri-to-uri|fn:insert-before|fn:index-of|fn:in-scope-prefixes|fn:implicit-timezone|fn:idref|fn:id|fn:hours-from-time|fn:hours-from-duration|fn:hours-from-dateTime|fn:floor|fn:false|fn:expanded-QName|fn:exists|fn:exactly-one|fn:escape-uri|fn:escape-html-uri|fn:error|fn:ends-with|fn:encode-for-uri|fn:empty|fn:document-uri|fn:doc-available|fn:doc|fn:distinct-values|fn:distinct-nodes|fn:default-collation|fn:deep-equal|fn:days-from-duration|fn:day-from-dateTime|fn:day-from-date|fn:data|fn:current-time|fn:current-dateTime|fn:current-date|fn:count|fn:contains|fn:concat|fn:compare|fn:collection|fn:codepoints-to-string|fn:codepoint-equal|fn:ceiling|fn:boolean|fn:base-uri|fn:avg|fn:adjust-time-to-timezone|fn:adjust-dateTime-to-timezone|fn:adjust-date-to-timezone|fn:abs|feed:unsubscribe|feed:subscription|feed:subscribe|feed:request|feed:item|feed:description|excel:clean|entity:enrich|dom:set-pipelines|dom:set-permissions|dom:set-name|dom:set-evaluation-context|dom:set-domain-scope|dom:set-description|dom:remove-pipeline|dom:remove-permissions|dom:remove|dom:get|dom:evaluation-context|dom:domains|dom:domain-scope|dom:create|dom:configuration-set-restart-user|dom:configuration-set-permissions|dom:configuration-set-evaluation-context|dom:configuration-set-default-domain|dom:configuration-get|dom:configuration-create|dom:collection|dom:add-pipeline|dom:add-permissions|dls:retention-rules|dls:retention-rule-remove|dls:retention-rule-insert|dls:retention-rule|dls:purge|dls:node-expand|dls:link-references|dls:link-expand|dls:documents-query|dls:document-versions-query|dls:document-version-uri|dls:document-version-query|dls:document-version-delete|dls:document-version-as-of|dls:document-version|dls:document-update|dls:document-unmanage|dls:document-set-quality|dls:document-set-property|dls:document-set-properties|dls:document-set-permissions|dls:document-set-collections|dls:document-retention-rules|dls:document-remove-properties|dls:document-remove-permissions|dls:document-remove-collections|dls:document-purge|dls:document-manage|dls:document-is-managed|dls:document-insert-and-manage|dls:document-include-query|dls:document-history|dls:document-get-permissions|dls:document-extract-part|dls:document-delete|dls:document-checkout-status|dls:document-checkout|dls:document-checkin|dls:document-add-properties|dls:document-add-permissions|dls:document-add-collections|dls:break-checkout|dls:author-query|dls:as-of-query|dbk:convert|dbg:wait|dbg:value|dbg:stopped|dbg:stop|dbg:step|dbg:status|dbg:stack|dbg:out|dbg:next|dbg:line|dbg:invoke|dbg:function|dbg:finish|dbg:expr|dbg:eval|dbg:disconnect|dbg:detach|dbg:continue|dbg:connect|dbg:clear|dbg:breakpoints|dbg:break|dbg:attached|dbg:attach|cvt:save-converted-documents|cvt:part-uri|cvt:destination-uri|cvt:basepath|cvt:basename|cts:words|cts:word-query-weight|cts:word-query-text|cts:word-query-options|cts:word-query|cts:word-match|cts:walk|cts:uris|cts:uri-match|cts:train|cts:tokenize|cts:thresholds|cts:stem|cts:similar-query-weight|cts:similar-query-nodes|cts:similar-query|cts:shortest-distance|cts:search|cts:score|cts:reverse-query-weight|cts:reverse-query-nodes|cts:reverse-query|cts:remainder|cts:registered-query-weight|cts:registered-query-options|cts:registered-query-ids|cts:registered-query|cts:register|cts:query|cts:quality|cts:properties-query-query|cts:properties-query|cts:polygon-vertices|cts:polygon|cts:point-longitude|cts:point-latitude|cts:point|cts:or-query-queries|cts:or-query|cts:not-query-weight|cts:not-query-query|cts:not-query|cts:near-query-weight|cts:near-query-queries|cts:near-query-options|cts:near-query-distance|cts:near-query|cts:highlight|cts:geospatial-co-occurrences|cts:frequency|cts:fitness|cts:field-words|cts:field-word-query-weight|cts:field-word-query-text|cts:field-word-query-options|cts:field-word-query-field-name|cts:field-word-query|cts:field-word-match|cts:entity-highlight|cts:element-words|cts:element-word-query-weight|cts:element-word-query-text|cts:element-word-query-options|cts:element-word-query-element-name|cts:element-word-query|cts:element-word-match|cts:element-values|cts:element-value-ranges|cts:element-value-query-weight|cts:element-value-query-text|cts:element-value-query-options|cts:element-value-query-element-name|cts:element-value-query|cts:element-value-match|cts:element-value-geospatial-co-occurrences|cts:element-value-co-occurrences|cts:element-range-query-weight|cts:element-range-query-value|cts:element-range-query-options|cts:element-range-query-operator|cts:element-range-query-element-name|cts:element-range-query|cts:element-query-query|cts:element-query-element-name|cts:element-query|cts:element-pair-geospatial-values|cts:element-pair-geospatial-value-match|cts:element-pair-geospatial-query-weight|cts:element-pair-geospatial-query-region|cts:element-pair-geospatial-query-options|cts:element-pair-geospatial-query-longitude-name|cts:element-pair-geospatial-query-latitude-name|cts:element-pair-geospatial-query-element-name|cts:element-pair-geospatial-query|cts:element-pair-geospatial-boxes|cts:element-geospatial-values|cts:element-geospatial-value-match|cts:element-geospatial-query-weight|cts:element-geospatial-query-region|cts:element-geospatial-query-options|cts:element-geospatial-query-element-name|cts:element-geospatial-query|cts:element-geospatial-boxes|cts:element-child-geospatial-values|cts:element-child-geospatial-value-match|cts:element-child-geospatial-query-weight|cts:element-child-geospatial-query-region|cts:element-child-geospatial-query-options|cts:element-child-geospatial-query-element-name|cts:element-child-geospatial-query-child-name|cts:element-child-geospatial-query|cts:element-child-geospatial-boxes|cts:element-attribute-words|cts:element-attribute-word-query-weight|cts:element-attribute-word-query-text|cts:element-attribute-word-query-options|cts:element-attribute-word-query-element-name|cts:element-attribute-word-query-attribute-name|cts:element-attribute-word-query|cts:element-attribute-word-match|cts:element-attribute-values|cts:element-attribute-value-ranges|cts:element-attribute-value-query-weight|cts:element-attribute-value-query-text|cts:element-attribute-value-query-options|cts:element-attribute-value-query-element-name|cts:element-attribute-value-query-attribute-name|cts:element-attribute-value-query|cts:element-attribute-value-match|cts:element-attribute-value-geospatial-co-occurrences|cts:element-attribute-value-co-occurrences|cts:element-attribute-range-query-weight|cts:element-attribute-range-query-value|cts:element-attribute-range-query-options|cts:element-attribute-range-query-operator|cts:element-attribute-range-query-element-name|cts:element-attribute-range-query-attribute-name|cts:element-attribute-range-query|cts:element-attribute-pair-geospatial-values|cts:element-attribute-pair-geospatial-value-match|cts:element-attribute-pair-geospatial-query-weight|cts:element-attribute-pair-geospatial-query-region|cts:element-attribute-pair-geospatial-query-options|cts:element-attribute-pair-geospatial-query-longitude-name|cts:element-attribute-pair-geospatial-query-latitude-name|cts:element-attribute-pair-geospatial-query-element-name|cts:element-attribute-pair-geospatial-query|cts:element-attribute-pair-geospatial-boxes|cts:document-query-uris|cts:document-query|cts:distance|cts:directory-query-uris|cts:directory-query-depth|cts:directory-query|cts:destination|cts:deregister|cts:contains|cts:confidence|cts:collections|cts:collection-query-uris|cts:collection-query|cts:collection-match|cts:classify|cts:circle-radius|cts:circle-center|cts:circle|cts:box-west|cts:box-south|cts:box-north|cts:box-east|cts:box|cts:bearing|cts:arc-intersection|cts:and-query-queries|cts:and-query-options|cts:and-query|cts:and-not-query-positive-query|cts:and-not-query-negative-query|cts:and-not-query|css:get|css:convert|cpf:success|cpf:failure|cpf:document-set-state|cpf:document-set-processing-status|cpf:document-set-last-updated|cpf:document-set-error|cpf:document-get-state|cpf:document-get-processing-status|cpf:document-get-last-updated|cpf:document-get-error|cpf:check-transition|alert:spawn-matching-actions|alert:rule-user-id-query|alert:rule-set-user-id|alert:rule-set-query|alert:rule-set-options|alert:rule-set-name|alert:rule-set-description|alert:rule-set-action|alert:rule-remove|alert:rule-name-query|alert:rule-insert|alert:rule-id-query|alert:rule-get-user-id|alert:rule-get-query|alert:rule-get-options|alert:rule-get-name|alert:rule-get-id|alert:rule-get-description|alert:rule-get-action|alert:rule-action-query|alert:remove-triggers|alert:make-rule|alert:make-log-action|alert:make-config|alert:make-action|alert:invoke-matching-actions|alert:get-my-rules|alert:get-all-rules|alert:get-actions|alert:find-matching-rules|alert:create-triggers|alert:config-set-uri|alert:config-set-trigger-ids|alert:config-set-options|alert:config-set-name|alert:config-set-description|alert:config-set-cpf-domain-names|alert:config-set-cpf-domain-ids|alert:config-insert|alert:config-get-uri|alert:config-get-trigger-ids|alert:config-get-options|alert:config-get-name|alert:config-get-id|alert:config-get-description|alert:config-get-cpf-domain-names|alert:config-get-cpf-domain-ids|alert:config-get|alert:config-delete|alert:action-set-options|alert:action-set-name|alert:action-set-module-root|alert:action-set-module-db|alert:action-set-module|alert:action-set-description|alert:action-remove|alert:action-insert|alert:action-get-options|alert:action-get-name|alert:action-get-module-root|alert:action-get-module-db|alert:action-get-module|alert:action-get-description|zero-or-one|years-from-duration|year-from-dateTime|year-from-date|upper-case|unordered|true|translate|trace|tokenize|timezone-from-time|timezone-from-dateTime|timezone-from-date|sum|subtract-dateTimes-yielding-yearMonthDuration|subtract-dateTimes-yielding-dayTimeDuration|substring-before|substring-after|substring|subsequence|string-to-codepoints|string-pad|string-length|string-join|string|static-base-uri|starts-with|seconds-from-time|seconds-from-duration|seconds-from-dateTime|round-half-to-even|round|root|reverse|resolve-uri|resolve-QName|replace|remove|QName|prefix-from-QName|position|one-or-more|number|not|normalize-unicode|normalize-space|node-name|node-kind|nilled|namespace-uri-from-QName|namespace-uri-for-prefix|namespace-uri|name|months-from-duration|month-from-dateTime|month-from-date|minutes-from-time|minutes-from-duration|minutes-from-dateTime|min|max|matches|lower-case|local-name-from-QName|local-name|last|lang|iri-to-uri|insert-before|index-of|in-scope-prefixes|implicit-timezone|idref|id|hours-from-time|hours-from-duration|hours-from-dateTime|floor|false|expanded-QName|exists|exactly-one|escape-uri|escape-html-uri|error|ends-with|encode-for-uri|empty|document-uri|doc-available|doc|distinct-values|distinct-nodes|default-collation|deep-equal|days-from-duration|day-from-dateTime|day-from-date|data|current-time|current-dateTime|current-date|count|contains|concat|compare|collection|codepoints-to-string|codepoint-equal|ceiling|boolean|base-uri|avg|adjust-time-to-timezone|adjust-dateTime-to-timezone|adjust-date-to-timezone|abs)\b/], -["pln",/^[\w:-]+/],["pln",/^[\t\n\r \xa0]+/]]),["xq","xquery"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/lang-yaml.js b/junit4-ant/src/tasks/js/google-code-prettify/lang-yaml.js deleted file mode 100644 index c38729b6..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/lang-yaml.js +++ /dev/null @@ -1,2 +0,0 @@ -var a=null; -PR.registerLangHandler(PR.createSimpleLexer([["pun",/^[:>?|]+/,a,":|>?"],["dec",/^%(?:YAML|TAG)[^\n\r#]+/,a,"%"],["typ",/^&\S+/,a,"&"],["typ",/^!\S*/,a,"!"],["str",/^"(?:[^"\\]|\\.)*(?:"|$)/,a,'"'],["str",/^'(?:[^']|'')*(?:'|$)/,a,"'"],["com",/^#[^\n\r]*/,a,"#"],["pln",/^\s+/,a," \t\r\n"]],[["dec",/^(?:---|\.\.\.)(?:[\n\r]|$)/],["pun",/^-/],["kwd",/^\w+:[\n\r ]/],["pln",/^\w+/]]),["yaml","yml"]); diff --git a/junit4-ant/src/tasks/js/google-code-prettify/prettify.css b/junit4-ant/src/tasks/js/google-code-prettify/prettify.css deleted file mode 100644 index d44b3a22..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/prettify.css +++ /dev/null @@ -1 +0,0 @@ -.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} \ No newline at end of file diff --git a/junit4-ant/src/tasks/js/google-code-prettify/prettify.js b/junit4-ant/src/tasks/js/google-code-prettify/prettify.js deleted file mode 100644 index eef5ad7e..00000000 --- a/junit4-ant/src/tasks/js/google-code-prettify/prettify.js +++ /dev/null @@ -1,28 +0,0 @@ -var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; -(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= -[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), -l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, -q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, -q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, -"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), -a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} -for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], -"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], -H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], -J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ -I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), -["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", -/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), -["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", -hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= -!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p foo = new ArrayList<>(); - for (int i = randomIntBetween(2, 1000); --i > 0;) { - foo.add(randomAsciiLettersOfLength(20)); - } - final EventBus aggregatedBus = new EventBus("aggregated"); - - final AtomicBoolean hadErrors = new AtomicBoolean(); - - // Code mirrors JUnit4's behavior. - final Deque stealingQueue = new ArrayDeque(foo); - aggregatedBus.register(new Object() { - volatile Thread foo; - - @Subscribe - public void onSlaveIdle(SlaveIdle slave) { - final Thread other = foo; - if (other != null) { - hadErrors.set(true); - throw new RuntimeException("Wtf? two threads in a handler: " - + other + " and " + Thread.currentThread()); - } - foo = Thread.currentThread(); - - if (stealingQueue.isEmpty()) { - slave.finished(); - } else { - String suiteName = stealingQueue.pop(); - slave.newSuite(suiteName); - } - - foo = null; - } - }); - - // stress. - ExecutorService executor = Executors.newCachedThreadPool(); - final List> slaves = new ArrayList<>(); - for (int i = 0; i < randomIntBetween(1, 10); i++) { - slaves.add(new Callable() { - @Override - public Void call() throws Exception { - aggregatedBus.post(new SlaveIdle()); - return null; - } - }); - } - for (Future f : executor.invokeAll(slaves)) { - f.get(); - } - executor.shutdown(); - - assertFalse(hadErrors.get()); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/TestJsonByteArrayRoundtrip.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/TestJsonByteArrayRoundtrip.java deleted file mode 100644 index 27f1ced8..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/TestJsonByteArrayRoundtrip.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.util.Arrays; - -import org.junit.Assert; -import org.junit.Test; - -import com.carrotsearch.ant.tasks.junit4.events.AppendStdErrEvent; -import com.carrotsearch.ant.tasks.junit4.events.Deserializer; -import com.carrotsearch.ant.tasks.junit4.events.IEvent; -import com.carrotsearch.ant.tasks.junit4.events.Serializer; -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Repeat; - -public class TestJsonByteArrayRoundtrip extends RandomizedTest { - @Test - @Repeat(iterations = 100) - public void testRoundTrip() throws Exception { - byte[] bytes = new byte[randomIntBetween(0, 1024)]; - getRandom().nextBytes(bytes); - - check(bytes); - } - - @Test - public void testSimpleAscii() throws Exception { - check("ABCabc0123".getBytes("UTF-8")); - check("\n\t".getBytes("UTF-8")); - } - - private void check(byte[] bytes) throws Exception { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Serializer s = new Serializer(baos); - s.serialize(new AppendStdErrEvent(bytes, 0, bytes.length)); - s.flush(); - s.close(); - - Deserializer deserializer = new Deserializer(new ByteArrayInputStream(baos.toByteArray()), - Thread.currentThread().getContextClassLoader()); - IEvent deserialize = deserializer.deserialize(); - - Assert.assertTrue(deserialize instanceof AppendStdErrEvent); - AppendStdErrEvent e = ((AppendStdErrEvent) deserialize); - baos.reset(); - e.copyTo(baos); - Assert.assertTrue( - "Exp: " + Arrays.toString(bytes) + "\n" + - "was: " + Arrays.toString(baos.toByteArray()), - Arrays.equals(bytes, baos.toByteArray())); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/TestXmlStringsRoundtrip.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/TestXmlStringsRoundtrip.java deleted file mode 100644 index 32595af9..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/TestXmlStringsRoundtrip.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Random; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.junit.Test; -import org.simpleframework.xml.Attribute; -import org.simpleframework.xml.Element; -import org.simpleframework.xml.Root; -import org.simpleframework.xml.core.Persister; -import org.simpleframework.xml.transform.RegistryMatcher; -import org.xml.sax.SAXParseException; - -import com.carrotsearch.ant.tasks.junit4.listeners.antxml.XmlStringTransformerAccess; -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Repeat; - -public class TestXmlStringsRoundtrip extends RandomizedTest { - @Test - @Repeat(iterations = 100) - public void testRoundTrip() throws Exception { - char[] chars = new char[randomIntBetween(0, 1024)]; - Random random = getRandom(); - for (int i = 0; i < chars.length; i++) { - chars[i] = (char) random.nextInt(); - } - - check(chars); - } - - @Test - public void testBoundary() throws Exception { - check(new char [] {'a', 0x0000, 'z'}); - check(new char [] {'a', 0x0001, 'z'}); - } - - @Root - public static class Model { - @Attribute - public String attribute; - - @Element(name = "system-out", data = true, required = true) - public String contents = ""; - - public Model() {} - - public Model(String s) { - attribute = contents = s; - } - } - - private void check(char[] chars) throws Exception { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - RegistryMatcher rm = new RegistryMatcher(); - rm.bind(String.class, XmlStringTransformerAccess.getInstance()); - Persister persister = new Persister(rm); - persister.write(new Model(new String(chars)), baos); - - DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); - try { - docBuilder.parse(new ByteArrayInputStream(baos.toByteArray())); - } catch (SAXParseException e) { - System.out.println("Input: " + Arrays.toString(chars)); - System.out.println("XML: " + new String(baos.toByteArray(), StandardCharsets.UTF_8)); - throw e; - } - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/events/TestRemoteEventSerialization.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/events/TestRemoteEventSerialization.java deleted file mode 100644 index 062c227d..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/events/TestRemoteEventSerialization.java +++ /dev/null @@ -1,156 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.events; - -import java.io.IOException; -import java.io.StringReader; -import java.io.StringWriter; -import java.nio.charset.StandardCharsets; -import java.util.Calendar; -import java.util.Locale; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.Description; -import org.junit.runner.RunWith; -import org.junit.runner.notification.Failure; - -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonReader; -import com.carrotsearch.ant.tasks.junit4.gson.stream.JsonWriter; -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Nightly; - -import static org.junit.Assert.*; - -public class TestRemoteEventSerialization extends RandomizedTest { - @RunWith(RandomizedRunner.class) - @Nightly - public static class Clazz1 {} - public static class Clazz2 {} - - private Description description; - private long start; - private long end; - private Failure failure; - - @Before - public void setup() { - Class suiteClass = randomFrom(new Class [] { - Clazz1.class, - Clazz2.class - }); - description = Description.createSuiteDescription(suiteClass); - - Calendar c = Calendar.getInstance(Locale.ROOT); - c.set(2015, 10, 20, 0, 0, 0); - start = c.getTimeInMillis(); - end = start + randomIntBetween(0, 1000); - - String MARKER = ""; - Throwable thrownException; - try { - throw new RuntimeException(MARKER); - } catch (Throwable t) { - thrownException = t; - } - - failure = new Failure(description, thrownException); - } - - @Test - public void eventBootstrap() throws IOException { - checkRoundtrip(new BootstrapEvent()); - } - - @Test - public void eventIdle() throws IOException { - checkRoundtrip(new IdleEvent()); - } - - @Test - public void eventQuit() throws IOException { - checkRoundtrip(new QuitEvent()); - } - - @Test - public void eventStdout() throws IOException { - byte [] value = randomRealisticUnicodeOfCodepointLengthBetween(0, 10).getBytes(StandardCharsets.UTF_8); - checkRoundtrip(new AppendStdOutEvent(value, 0, value.length)); - } - - @Test - public void eventStderr() throws IOException { - byte [] value = randomRealisticUnicodeOfCodepointLengthBetween(0, 10).getBytes(StandardCharsets.UTF_8); - checkRoundtrip(new AppendStdErrEvent(value, 0, value.length)); - } - - - @Test - public void eventSuiteStarted() throws IOException { - checkRoundtrip(new SuiteStartedEvent(description, System.currentTimeMillis())); - } - - @Test - public void eventSuiteFailure() throws IOException { - checkRoundtrip(new SuiteFailureEvent(failure)); - } - - @Test - public void eventSuiteCompleted() throws IOException { - checkRoundtrip(new SuiteCompletedEvent(description, start, end)); - } - - @Test - public void eventTestStartedEvent() throws IOException { - checkRoundtrip(new TestStartedEvent(description)); - } - - @Test - public void eventTestFailureEvent() throws IOException { - checkRoundtrip(new TestFailureEvent(failure)); - } - - @Test - public void eventTestIgnoredAssumptionEvent() throws IOException { - checkRoundtrip(new TestIgnoredAssumptionEvent(failure)); - } - - @Test - public void eventTestIgnoredEvent() throws IOException { - checkRoundtrip(new TestIgnoredEvent(description, randomUnicodeOfLength(10))); - } - - @Test - public void eventTestFinishedEvent() throws IOException { - checkRoundtrip(new TestFinishedEvent(description, start, end)); - } - - private void checkRoundtrip(RemoteEvent event) throws IOException { - StringWriter sw = new StringWriter(); - - final boolean lenient = randomBoolean(); - JsonWriter jw = new JsonWriter(sw); - jw.setIndent(" "); - jw.setLenient(lenient); - event.serialize(jw); - jw.close(); - - String serialized1 = sw.toString(); - JsonReader jr = new JsonReader(new StringReader(serialized1)); - jr.setLenient(lenient); - RemoteEvent deserialized = event.getType().deserialize(jr); - - - // If we serialize again, the contents should be identical. - sw.getBuffer().setLength(0); - jw = new JsonWriter(sw); - jw.setIndent(" "); - jw.setLenient(lenient); - deserialized.serialize(jw); - jw.close(); - - String serialized2 = sw.toString(); - if (!serialized2.equals(serialized1)) { - fail("Roundtrip serialization failed:\n1: " + serialized1 + "\n2: " + serialized2); - } - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/AntBuildFileTestBase.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/AntBuildFileTestBase.java deleted file mode 100644 index ea0689dd..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/AntBuildFileTestBase.java +++ /dev/null @@ -1,150 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - -import static org.hamcrest.CoreMatchers.*; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.PrintStream; - -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.DefaultLogger; -import org.apache.tools.ant.MagicNames; -import org.apache.tools.ant.Project; -import org.apache.tools.ant.ProjectHelper; -import org.apache.tools.ant.launch.Launcher; -import org.apache.tools.ant.taskdefs.Java; -import org.apache.tools.ant.types.Path; -import org.apache.tools.ant.util.LoaderUtils; -import org.junit.After; -import org.junit.Assert; - -/** - * An equivalent of BuildFileTest for JUnit4. - */ -public class AntBuildFileTestBase { - private Project project; - private ByteArrayOutputStream output; - private DefaultLogger listener; - - protected PrintStream restoreSysout; - protected PrintStream restoreSyserr; - - protected void setupProject(File projectFile) { - try { - restoreSysout = System.out; - restoreSyserr = System.err; - output = new ByteArrayOutputStream(); - PrintStream ps = new PrintStream(output, true, "UTF-8"); - System.setOut(ps); - System.setErr(ps); - - project = new Project(); - project.init(); - - project.setUserProperty(MagicNames.ANT_FILE, projectFile.getAbsolutePath()); - ProjectHelper.configureProject(project, projectFile); - - listener = new DefaultLogger(); - listener.setMessageOutputLevel(Project.MSG_DEBUG); - listener.setErrorPrintStream(ps); - listener.setOutputPrintStream(ps); - getProject().addBuildListener(listener); - - DefaultLogger console = new DefaultLogger(); - console.setMessageOutputLevel(Project.MSG_INFO); - console.setErrorPrintStream(restoreSyserr); - console.setOutputPrintStream(restoreSysout); - getProject().addBuildListener(console); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @After - public void restoreSysouts() { - if (restoreSysout != null) System.setOut(restoreSysout); - if (restoreSyserr != null) System.setErr(restoreSyserr); - } - - protected final Project getProject() { - if (project == null) { - throw new IllegalStateException( - "Setup project file with setupProject(File) first."); - } - return project; - } - - protected final void assertLogContains(String substring) { - Assert.assertTrue("Log did not contain: '" + substring + "'", getLog() - .contains(substring)); - } - - protected final void assertLogDoesNotContain(String substring) { - Assert.assertTrue("Log contained: '" + substring + "'", - !getLog().contains(substring)); - } - - protected final String getLog() { - try { - return new String(output.toByteArray(), "UTF-8"); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - protected final void expectBuildExceptionContaining(String target, - String message, String... additionalMessages) { - try { - executeTarget(target); - Assert.fail("Expected a build failure with message: " + message); - } catch (BuildException e) { - Assert.assertThat(e.getMessage(), containsString(message)); - for (String m : additionalMessages) { - Assert.assertThat(e.getMessage(), containsString(m)); - } - } - } - - protected final void executeTarget(String target) { - getProject().executeTarget(target); - } - - protected final void executeForkedTarget(String target) { - executeForkedTarget(target, 10 * 1000L); - } - - protected final void executeForkedTarget(String target, long timeout) { - Path antPath = new Path(getProject()); - antPath.createPathElement().setLocation(sourceOf(Project.class)); - antPath.createPathElement().setLocation(sourceOf(Launcher.class)); - - Java java = new Java(); - java.setTaskName("forked"); - java.setProject(getProject()); - java.setClassname("org.apache.tools.ant.launch.Launcher"); - java.createClasspath().add(antPath); - java.setFork(true); - java.setSpawn(false); - java.setTimeout(timeout); - java.setFailonerror(false); - java.setOutputproperty("stdout"); - java.setErrorProperty("stderr"); - - java.createArg().setValue("-f"); - java.createArg().setValue(getProject().getUserProperty(MagicNames.ANT_FILE)); - java.createArg().setValue(target); - java.execute(); - - getProject().log("Forked stdout:\n" + getProject().getProperty("stdout")); - getProject().log("Forked stderr:\n" + getProject().getProperty("stderr")); - } - - /** - * Get the source location of a given class. - */ - private static File sourceOf(Class clazz) { - return LoaderUtils.getResourceSource( - clazz.getClassLoader(), clazz.getName().replace('.', '/') + ".class"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/JUnit4XmlTestBase.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/JUnit4XmlTestBase.java deleted file mode 100644 index 8ced8805..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/JUnit4XmlTestBase.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -/** - * A base class for tests contained in junit4.xml - * file. - */ -public class JUnit4XmlTestBase extends AntBuildFileTestBase { - @Rule - public TestRule dumpLogOnError = new TestRule() { - @Override - public Statement apply(final Statement base, Description description) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - try { - base.evaluate(); - } catch (Throwable e) { - System.out.println("Ant log: " + getLog()); - throw e; - } - } - }; - } - }; - - @Before - public void setUp() throws Exception { - URI resource = getClass().getClassLoader().getResource("junit4.xml").toURI(); - if (!resource.getScheme().equals("file")) { - throw new IOException("junit4.xml not under a file URI: " + resource); - } - - Path absolute = Paths.get(resource).toAbsolutePath(); - // System.out.println("junit4.xml at: " + absolute + (Files.exists(absolute) ? " (exists)" : " (does not exist)")); - - super.setupProject(absolute.toFile()); - } - - protected static int countPattern(String output, String substr) { - int count = 0; - for (int i = 0; i < output.length();) { - int index = output.indexOf(substr, i); - if (index < 0) { - break; - } - count++; - i = index + 1; - } - return count; - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestAltJavaVendors.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestAltJavaVendors.java deleted file mode 100644 index 02ad613c..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestAltJavaVendors.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import java.io.File; - -import org.apache.tools.ant.types.Path; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Test; - - -public class TestAltJavaVendors extends JUnit4XmlTestBase { - @Test - public void altVendors() { - String altVendors = System.getProperty("alt.jvms"); - Assume.assumeTrue(altVendors != null && !altVendors.trim().isEmpty()); - - for (String jvm : new Path(getProject(), altVendors).list()) { - getProject().log("Trying JVM: " + jvm); - Assert.assertTrue("JVM is not a file: " + jvm, new File(jvm).isFile()); - Assert.assertTrue("JVM is not executable: " + jvm, new File(jvm).canExecute()); - - getProject().setProperty("jvm.exec", jvm); - expectBuildExceptionContaining("alt-vendor", - "1 suite, 5 tests, 1 error, 1 failure, 2 ignored (1 assumption)"); - } - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestAntXmlReport.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestAntXmlReport.java deleted file mode 100644 index 455bec52..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestAntXmlReport.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - -import static org.junit.Assert.*; - -import java.io.File; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.junit.Assert; -import org.junit.Test; -import org.simpleframework.xml.Attribute; -import org.simpleframework.xml.Element; -import org.simpleframework.xml.Order; -import org.simpleframework.xml.Root; -import org.simpleframework.xml.core.Persister; - -public class TestAntXmlReport extends JUnit4XmlTestBase { - @Root(name = "failsafe-summary") - @Order(elements = {"completed", "errors", "failures", "skipped", "failureMessage"}) - public static class MavenFailsafeSummaryModel_Local { - @Attribute(required = false) - public Integer result; - - @Attribute - public boolean timeout = false; - - @Element - public int completed; - - @Element - public int errors; - - @Element - public int failures; - - @Element - public int skipped; - - @Element(required = false) - public String failureMessage = ""; - } - - @Test - public void antxml() throws Exception { - super.executeTarget("antxml"); - - // Simple check for existence. - Assert.assertTrue( - new File(getProject().getBaseDir(), "ant-xmls/TEST-com.carrotsearch.ant.tasks.junit4.tests.TestBeforeClassError.xml").length() > 0); - - Assert.assertTrue( - new File(getProject().getBaseDir(), "ant-xmls/TEST-com.carrotsearch.ant.tasks.junit4.tests.replication.TestSuiteReplicated-2.xml").length() > 0); - - // Check for warning messages about duplicate suites. - assertLogContains("Duplicate suite name used with XML reports"); - - // Attempt to read and parse. - File basedir = new File(getProject().getBaseDir(), "ant-xmls"); - for (File f : basedir.listFiles()) { - if (f.isFile() && f.getName().endsWith(".xml")) { - DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); - docBuilder.parse(f); - } - } - } - - @Test - public void summary() throws Exception { - super.executeTarget("antxml-summary"); - - Persister p = new Persister(); - File parent = getProject().getBaseDir(); - - MavenFailsafeSummaryModel_Local m1 = p.read(MavenFailsafeSummaryModel_Local.class, new File(parent, "ant-xmls2/summary1.xml")); - assertEquals(255, (int) m1.result); - assertEquals(5, m1.completed); - assertEquals(2, m1.skipped); - assertEquals(1, m1.errors); - assertEquals(1, m1.failures); - - m1 = p.read(MavenFailsafeSummaryModel_Local.class, new File(parent, "ant-xmls2/summary2.xml")); - assertEquals(null, m1.result); - assertEquals(1, m1.completed); - assertEquals(0, m1.skipped); - assertEquals(0, m1.errors); - assertEquals(0, m1.failures); - - m1 = p.read(MavenFailsafeSummaryModel_Local.class, new File(parent, "ant-xmls2/summary3.xml")); - assertEquals(254, (int) m1.result); - assertEquals(0, m1.completed); - assertEquals(0, m1.skipped); - assertEquals(0, m1.errors); - assertEquals(0, m1.failures); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestChildVmSysprops.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestChildVmSysprops.java deleted file mode 100644 index 5a8cc41d..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestChildVmSysprops.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - - -public class TestChildVmSysprops extends JUnit4XmlTestBase { - @Test - public void sysprops() { - executeTarget("childvm_sysprops"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestCrashesAndExceptions.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestCrashesAndExceptions.java deleted file mode 100644 index 3fa34d43..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestCrashesAndExceptions.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import java.io.File; - -import org.junit.Test; - - -public class TestCrashesAndExceptions extends JUnit4XmlTestBase { - @Test - public void slavehanging() { - executeTarget("slavehanging"); - assertLogContains("Caused by: java.lang.ArithmeticException"); - } - - - @Test - public void jvmcrash() { - expectBuildExceptionContaining("jvmcrash", "was not empty, see:"); - File cwd = getProject().getBaseDir(); - for (File crashDump : cwd.listFiles()) { - if (crashDump.isFile() && - (crashDump.getName().matches("^hs_err_pid.+\\.log") || - crashDump.getName().endsWith(".mdmp") || - crashDump.getName().endsWith(".dmp") || - crashDump.getName().endsWith(".dump") || - crashDump.getName().endsWith(".trc"))) { - crashDump.delete(); - } - } - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestCwdConflict.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestCwdConflict.java deleted file mode 100644 index c4792d84..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestCwdConflict.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - - -public class TestCwdConflict extends JUnit4XmlTestBase { - @Test - public void cwdconflict() { - super.executeTarget("cwdconflict"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestDuplicateResourceCollections.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestDuplicateResourceCollections.java deleted file mode 100644 index 2ff9b408..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestDuplicateResourceCollections.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - - -public class TestDuplicateResourceCollections extends JUnit4XmlTestBase { - @Test - public void duplicateResourceCollectionEntries() { - super.executeTarget("duplicateresources"); - - assertLogContains("10 suites, 10 tests"); - assertLogContains("JVM J0"); - assertLogContains("JVM J1"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestFileEncodings.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestFileEncodings.java deleted file mode 100644 index f28ee35d..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestFileEncodings.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - -import java.io.DataInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Test; - -public class TestFileEncodings extends JUnit4XmlTestBase { - @Test - public void checkTypicalEncodings() throws IOException { - super.executeTarget("fileencodings"); - - File logFile = new File(getProject().getProperty("log.file")); - - byte [] contents = new byte [(int) logFile.length()]; - DataInputStream dis = new DataInputStream(new FileInputStream(logFile)); - dis.readFully(contents); - dis.close(); - - String log = new String(contents, "UTF-8"); - Assert.assertEquals(1, countPattern(log, "US-ASCII=cze??, ??????, ???")); - Assert.assertEquals(1, countPattern(log, "iso8859-1=cze??, ??????, ???")); - Assert.assertEquals(1, countPattern(log, "UTF-8=cześć, Привет, 今日ã¯")); - Assert.assertEquals(1, countPattern(log, "UTF-16=cześć, Привет, 今日ã¯")); - Assert.assertEquals(1, countPattern(log, "UTF-16LE=cześć, Привет, 今日ã¯")); - Assert.assertEquals(1, countPattern(log, "UTF-32=cześć, Привет, 今日ã¯")); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestFiltering.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestFiltering.java deleted file mode 100644 index 885569d7..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestFiltering.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - - -public class TestFiltering extends JUnit4XmlTestBase { - @Test - public void classfilter() { - executeTarget("classfilter"); - assertLogContains("Tests summary: 1 suite"); - } - - @Test - public void methodfilter() { - executeTarget("methodfilter"); - assertLogContains("Tests summary: 1 suite, 2 tests"); - } - - @Test - public void filterexpression() { - executeTarget("filterexpression"); - - assertLogContains("Parsed test filtering expression: (@foo AND (NOT @bar))"); - assertLogContains(">foo<"); - assertLogDoesNotContain(">foobar<"); - assertLogDoesNotContain(">bar<"); - assertLogDoesNotContain(">foobar2<"); - assertLogDoesNotContain(">bar2<"); - assertLogContains("Tests summary: 2 suites (1 ignored), 1 test"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestHeartbeat.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestHeartbeat.java deleted file mode 100644 index 2624c1c7..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestHeartbeat.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - -/** - * Test heartbeat on slow, non-updating tests. - */ -public class TestHeartbeat extends JUnit4XmlTestBase { - @Test - public void testHeartbeat() { - executeTarget("testHeartbeat"); - assertLogContains("HEARTBEAT J0"); - assertLogContains("at: HeartbeatSlow.method1"); - assertLogDoesNotContain("Exception thrown by subscriber method"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestIfNoTestsOption.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestIfNoTestsOption.java deleted file mode 100644 index 0a4379f4..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestIfNoTestsOption.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - - -public class TestIfNoTestsOption extends JUnit4XmlTestBase { - @Test - public void allFilteredOut() { - expectBuildExceptionContaining("allFilteredOut", "There were no executed tests: 0 suites, 0 tests"); - } - - @Test - public void oneIgnored() { - expectBuildExceptionContaining("oneIgnored", "There were no executed tests: 1 suite, 1 test, 1 ignored"); - } - - @Test - public void oneAssumptionIgnored() { - expectBuildExceptionContaining("oneAssumptionIgnored", "There were no executed tests: 1 suite, 1 test, 1 ignored"); - } - - @Test - public void oneSuccessfull() { - executeTarget("oneSuccessful"); - } - - @Test - public void oneFailure() { - expectBuildExceptionContaining("oneFailure", "There were test failures: 1 suite, 1 test, 1 failure"); - } - - @Test - public void oneError() { - expectBuildExceptionContaining("oneError", "There were test failures: 1 suite, 1 test, 1 error"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestJUnitCompat.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestJUnitCompat.java deleted file mode 100644 index a5e76758..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestJUnitCompat.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - - -public class TestJUnitCompat extends JUnit4XmlTestBase { - @Test - public void junitcompat1() { - super.expectBuildExceptionContaining( - "junitcompat1", " elements are not supported"); - } - - @Test - public void junitcompat2() { - super.expectBuildExceptionContaining( - "junitcompat2", " elements are not supported"); - } - - @Test - public void junitcompat3() { - super.expectBuildExceptionContaining( - "junitcompat3", " elements are not supported"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestJsonReport.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestJsonReport.java deleted file mode 100644 index 9361e3ee..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestJsonReport.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import java.io.File; - -import org.junit.Assert; -import org.junit.Test; - - -public class TestJsonReport extends JUnit4XmlTestBase { - @Test - public void antxml() { - super.executeTarget("json"); - - Assert.assertTrue( - new File(getProject().getBaseDir(), - "json/report.json").length() > 0); - Assert.assertTrue( - new File(getProject().getBaseDir(), - "json/report.jsonp").length() > 0); - Assert.assertTrue( - new File(getProject().getBaseDir(), - "json/output.html").length() > 0); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestJvmLogging.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestJvmLogging.java deleted file mode 100644 index 22e0dbc4..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestJvmLogging.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - -import org.junit.Test; - -/** - * Check JVM logging settings. Thet seem to use process descriptors not - * {@link System} streams. - */ -public class TestJvmLogging extends JUnit4XmlTestBase { - @Test - public void jvmverbose() { - executeTarget("jvmverbose"); - assertLogContains("was not empty, see"); - } - - @Test - public void sysouts() { - executeTarget("sysouts"); - assertLogContains("syserr-syserr-contd."); - assertLogContains("sysout-sysout-contd."); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestMiscJUnit4Attributes.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestMiscJUnit4Attributes.java deleted file mode 100644 index bffa780f..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestMiscJUnit4Attributes.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - -import com.carrotsearch.ant.tasks.junit4.tests.TestAfterClassError; -import com.carrotsearch.ant.tasks.junit4.tests.TestBeforeClassError; - - -public class TestMiscJUnit4Attributes extends JUnit4XmlTestBase { - @Test - public void customprefix() { - executeForkedTarget("customprefix"); - } - - @Test - public void statuses() throws Throwable { - expectBuildExceptionContaining("statuses", - "1 suite, 5 tests, 1 error, 1 failure, 2 ignored (1 assumption)"); - } - - @Test - public void ignoredSuite() throws Throwable { - executeTarget("ignoredSuite"); - assertLogContains("Tests summary: 1 suite (1 ignored), 0 tests"); - } - - @Test - public void beforeClassError() throws Throwable { - expectBuildExceptionContaining("beforeClassError", - "1 suite, 0 tests, 1 suite-level error"); - assertLogContains("| " + TestBeforeClassError.class.getSimpleName() + " (suite)"); - } - - @Test - public void afterClassError() throws Throwable { - expectBuildExceptionContaining("afterClassError", - "1 suite, 1 test, 1 suite-level error"); - assertLogContains("| " + TestAfterClassError.class.getSimpleName() + " (suite)"); - } - - @Test - public void hierarchicalSuiteDescription() throws Throwable { - expectBuildExceptionContaining("hierarchicalSuiteDescription", - "1 suite, 2 tests, 3 suite-level errors, 1 error"); - } - - @Test - public void dir() { - executeTarget("dir"); - } - - @Test - public void maxmem() { - executeTarget("maxmem"); - } - - @Test - public void jvmarg() { - executeTarget("jvmarg"); - } - - @Test - public void seedpassing() { - executeTarget("seedpassing"); - } - - @Test - public void seedpassingInvalid() { - expectBuildExceptionContaining("seedpassing.invalid", "Not a valid seed chain"); - } - - @Test - public void reproducestring() { - executeTarget("reproducestring"); - assertLogContains("2> Reproduce: "); - } - - @Test - public void assertions() { - expectBuildExceptionContaining("assertions", "There were test failures"); - assertLogContains("> Throwable #1: java.lang.AssertionError: foobar"); - } - - @Test - public void balancing() { - executeTarget("balancing"); - assertLogContains("Assignment hint: J0 (cost 2019) com.carrotsearch.ant.tasks.junit4.tests.sub2.TestTwoSeconds (by ExecutionTimeBalancer)"); - assertLogContains("Assignment hint: J1 (cost 1002) com.carrotsearch.ant.tasks.junit4.tests.sub2.TestOneSecond (by ExecutionTimeBalancer)"); - assertLogContains("Assignment hint: J1 (cost 501) com.carrotsearch.ant.tasks.junit4.tests.sub2.TestHalfSecond (by ExecutionTimeBalancer)"); - assertLogContains("Assignment hint: J1 (cost 2) com.carrotsearch.ant.tasks.junit4.tests.sub2.TestZeroSeconds (by ExecutionTimeBalancer)"); - } - - @Test - public void balancing_nohints() { - executeTarget("balancing_nohints"); - } - - @Test - public void mergehints() { - executeTarget("mergehints"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestOnNonEmptyWorkDirectory.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestOnNonEmptyWorkDirectory.java deleted file mode 100644 index d48ec335..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestOnNonEmptyWorkDirectory.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Ignore; -import org.junit.Test; - - -public class TestOnNonEmptyWorkDirectory extends JUnit4XmlTestBase { - @Test - public void actionFail() { - expectBuildExceptionContaining("onNonEmptyWorkDirectory-fail", - "existing-dir", - "Cwd of a forked JVM already exists and is not empty"); - } - - @Test - public void actionWipe() { - executeTarget("onNonEmptyWorkDirectory-wipe"); - assertLogContains("Cwd of a forked JVM already exists and is not empty, trying to wipe"); - } - - @Test - public void actionIgnore() { - executeTarget("onNonEmptyWorkDirectory-ignore"); - assertLogContains("Cwd of a forked JVM already exists and is not empty"); - } - - // https://github.com/randomizedtesting/randomizedtesting/issues/247 - @Test - public void tmpDirUnderCwd() { - executeTarget("onNonEmptyWorkDirectory-tmpDirUnderCwd"); - assertLogContains("Created tmpfile"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestOomCode.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestOomCode.java deleted file mode 100644 index 10601dc9..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestOomCode.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - -import org.junit.Ignore; -import org.junit.Test; - -public class TestOomCode extends JUnit4XmlTestBase { - @Test - @Ignore("Not portable across JVMs") - public void oom() { - super.executeForkedTarget("oomcode", 5 * 60 * 1000L); - assertLogContains("Forked JVM ran out of memory"); - assertLogContains("WARN: JVM out of memory"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestOomPermGen.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestOomPermGen.java deleted file mode 100644 index 009cbcea..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestOomPermGen.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - -import org.junit.Ignore; -import org.junit.Test; - -public class TestOomPermGen extends JUnit4XmlTestBase { - @Test - @Ignore("Not portable across JVMs") - public void oom() { - super.executeForkedTarget("oompermgen", 5 * 60 * 1000L); - if (!getLog().contains("1 ignored (1 assumption)")) { - assertLogContains("java.lang.OutOfMemoryError"); - } - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestOutputCapture.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestOutputCapture.java deleted file mode 100644 index 4ed32e7a..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestOutputCapture.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - -/** - * Test things related to output capturing. - */ -public class TestOutputCapture extends JUnit4XmlTestBase { - @Test - public void sysstreams() { - executeTarget("sysstreams"); - assertLogContains("Tests summary: 1 suite, 2 tests"); - assertLogContains("1> sysout-sysout-contd."); - assertLogContains("2> syserr-syserr-contd."); - } - - @Test - public void outofordersysouts() { - executeTarget("outofordersysouts"); - } - - @Test - public void staticScopeOutput() { - executeTarget("staticScopeOutput"); - assertLogContains("1> static-scope"); - assertLogContains("1> before-class"); - assertLogContains("1> after-class"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestPickSeed.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestPickSeed.java deleted file mode 100644 index ba64deb9..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestPickSeed.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import java.util.HashMap; -import java.util.TreeSet; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.junit.Assert; -import org.junit.Test; - - -public class TestPickSeed extends JUnit4XmlTestBase { - - @Test - public void pickSeed() { - for (int i = 0; i < 7; i++) { - super.executeTarget("randomsysproperty"); - } - - HashMap> props = new HashMap>(); - - for (String key : new String [] { - "prefix.dummy1", - "prefix.dummy2", - "replaced.dummy1", - "replaced.dummy2", - }) { - TreeSet values = new TreeSet(); - Pattern p = Pattern.compile("(?:> )(" + key + ")(?:=)([^\\s]+)"); - Matcher m = p.matcher(getLog()); - while (m.find()) { - values.add(m.group(2)); - } - - props.put(key, values); - } - - Assert.assertEquals(props.get("prefix.dummy1"), props.get("replaced.dummy1")); - Assert.assertEquals(props.get("prefix.dummy2"), props.get("replaced.dummy2")); - - // At least two unique values. - Assert.assertTrue(props.get("prefix.dummy1").size() >= 2); - // null (missing value) should be there. - Assert.assertTrue(props.get("prefix.dummy2").contains("null")); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestPreconditions.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestPreconditions.java deleted file mode 100644 index ae37b588..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestPreconditions.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - - -public class TestPreconditions extends JUnit4XmlTestBase { - @Test - public void nojunit() { - expectBuildExceptionContaining("nojunit", "Forked JVM's classpath must include a junit4 JAR"); - } - - @Test - public void oldjunit() { - executeForkedTarget("oldjunit"); - assertLogContains("Forked JVM's classpath must use JUnit 4.10 or newer"); - } - - @Test - public void nojunit_task() { - executeForkedTarget("nojunit-task"); - assertLogContains("JUnit JAR must be added to junit4 taskdef's classpath"); - } - - @Test - public void oldjunit_task() { - executeForkedTarget("oldjunit-task"); - assertLogContains("At least JUnit version 4.10 is required on junit4's taskdef classpath"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestReplication.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestReplication.java deleted file mode 100644 index a70fcda6..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestReplication.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import java.util.Arrays; -import java.util.HashSet; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.junit.Assert; -import org.junit.Test; - -public class TestReplication extends JUnit4XmlTestBase { - @Test - public void singleSuiteReplication() { - super.executeTarget("replicateSingleTest"); - - assertLogContains("Replicated test, VM: 0"); - assertLogContains("Replicated test, VM: 1"); - assertLogContains("Replicated test, VM: 2"); - } - - @Test - public void replicationAndBalancing() { - super.executeTarget("replicationAndBalancing"); - - assertLogContains("Non-replicated test, VM: 0"); - assertLogContains("Non-replicated test, VM: 1"); - assertLogContains("Replicated test, VM: 0"); - assertLogContains("Replicated test, VM: 1"); - assertLogContains("Replicated test, VM: 2"); - } - - @Test - public void pseudoBalancing() { - super.executeTarget("pseudoBalancing"); - - assertLogContains("3 suites, 300 tests, 200 ignored (200 assumptions)"); - - String log = getLog(); - for (int i = 0; i < 100; i++) { - Pattern p = Pattern.compile("(Test " + i + " executed on VM )([0-9]+)"); - Matcher m = p.matcher(log); - Assert.assertTrue(m.find()); - int jvm = Integer.parseInt(m.group(2)); - - HashSet s = new HashSet(Arrays.asList(0, 1, 2)); - s.remove(jvm); - for (int ignoredOnJvm : s) { - assertLogContains("Test " + i + " ignored on VM " + ignoredOnJvm); - } - } - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestRunListeners.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestRunListeners.java deleted file mode 100644 index e9c65403..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestRunListeners.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - -import org.junit.Test; - -public class TestRunListeners extends JUnit4XmlTestBase { - - @Test - public void singleUserDefinedRunListener() { - super.executeTarget("singleUserDefinedRunListener"); - - assertLogContains("UserDefinedRunListener1.testStarted()"); - assertLogContains("UserDefinedRunListener1.testFinished()"); - } - - @Test - public void multipleUserDefinedRunListeners() { - super.executeTarget("multipleUserDefinedRunListeners"); - - assertLogContains("UserDefinedRunListener2.testStarted()"); - assertLogContains("UserDefinedRunListener2.testFinished()"); - - assertLogContains("UserDefinedRunListener3.testStarted()"); - assertLogContains("UserDefinedRunListener3.testFinished()"); - } - -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSecuritySandbox.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSecuritySandbox.java deleted file mode 100644 index d660a5e9..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSecuritySandbox.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import com.carrotsearch.ant.tasks.junit4.tests.FailInAfterClass; -import com.carrotsearch.ant.tasks.junit4.tests.ReasonForAssumptionIgnored; -import org.junit.Assert; -import org.junit.Test; - -import java.util.regex.Pattern; - -/** - * Test report-text listener. - */ -public class TestSecuritySandbox extends JUnit4XmlTestBase { - @Test - public void gh255() { - super.executeTarget("gh255"); - assertLogContains("access denied (\"java.util.PropertyPermission\" \"foo\" \"write\")"); - assertLogContains("Tests summary: 1 suite, 1 test, 1 error"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestShutdownHookDeadlock.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestShutdownHookDeadlock.java deleted file mode 100644 index d1cecd1e..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestShutdownHookDeadlock.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - -import org.junit.Assert; -import org.junit.Test; - - -public class TestShutdownHookDeadlock extends JUnit4XmlTestBase { - @Test - public void slavehanging() { - long start = System.currentTimeMillis(); - executeForkedTarget("shutdownhook", 120 * 1000L); - long end = System.currentTimeMillis(); - - // This isn't a strong assertion but it'll do here. If the execution time > 60 seconds - // something is stinky. - Assert.assertTrue(end - start < 60 * 1000); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSourceSuitesAsInput.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSourceSuitesAsInput.java deleted file mode 100644 index c252473f..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSourceSuitesAsInput.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - -public class TestSourceSuitesAsInput extends JUnit4XmlTestBase { - @Test - public void sourcesuites() { - super.executeTarget("sourcesuites"); - assertLogContains("Tests summary: 1 suite, 1 test"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestStackOverflowInEventEmitter.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestStackOverflowInEventEmitter.java deleted file mode 100644 index e2781350..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestStackOverflowInEventEmitter.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - - -public class TestStackOverflowInEventEmitter extends JUnit4XmlTestBase { - @Test - public void stackoverflow() { - super.expectBuildExceptionContaining("stackoverflow", "Quit event not received from the forked process?"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestStatsProperties.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestStatsProperties.java deleted file mode 100644 index 90ad9c50..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestStatsProperties.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - - -public class TestStatsProperties extends JUnit4XmlTestBase { - @Test - public void allFilteredOut() { - super.executeTarget("statsProperties"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSuiteClassesBad.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSuiteClassesBad.java deleted file mode 100644 index 73a550be..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSuiteClassesBad.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - - -public class TestSuiteClassesBad extends JUnit4XmlTestBase { - @Test - public void notaclass() { - expectBuildExceptionContaining("notaclass", - "File does not start with a class magic"); - } - - @Test - public void notinstantiable() { - expectBuildExceptionContaining("notinstantiable", - "There were test failures: 1 suite, 1 test, 1 error"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSuiteDuplicates.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSuiteDuplicates.java deleted file mode 100644 index 292ec60a..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSuiteDuplicates.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - - -public class TestSuiteDuplicates extends JUnit4XmlTestBase { - @Test - public void suiteduplicate() { - super.executeTarget("suiteduplicate"); - - assertLogContains("2 suites, 2 tests"); - assertLogContains("JVM J0"); - assertLogContains("JVM J1"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSysProperties.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSysProperties.java deleted file mode 100644 index 779d653a..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSysProperties.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.junit.Assert; -import org.junit.Test; - -public class TestSysProperties extends JUnit4XmlTestBase { - @Test - public void failureProperty() { - executeTarget("failureProperty"); - } - - @Test - public void failureTypePassing() { - executeTarget("failureTypePassing"); - assertLogContains("Throwable #1: com.carrotsearch.ant.tasks.junit4.tests.SyntheticException"); - assertLogContains("Tests summary: 1 suite, 1 test, 1 error"); - - super.restoreSyserr.println(getLog()); - } - - @Test - public void escaping() { - executeTarget("escaping"); - assertLogContains("\"-Dsysprop.key2=abc def\""); - } - - @Test - public void sysproperty() { - executeTarget("sysproperty"); - } - - @Test - public void env() { - executeTarget("env"); - } - - @Test - public void iters() { - executeTarget("iters"); - Pattern p = Pattern.compile("TestSuccess\\.alwaysPasses"); - Matcher matcher = p.matcher(getLog()); - int count = 0; - while (matcher.find()) { - count++; - } - Assert.assertEquals(5, count); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSysPropertySet.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSysPropertySet.java deleted file mode 100644 index 1eb2050b..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSysPropertySet.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - -import org.junit.Test; - -public class TestSysPropertySet extends JUnit4XmlTestBase { - @Test - public void altVendors() { - getProject().setProperty("prefix.dummy1", "value1"); - getProject().setProperty("prefix.dummy2", "value2"); - - executeTarget("syspropertyset"); - - assertLogContains("value1"); - assertLogContains("value2"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSysoutOOM.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSysoutOOM.java deleted file mode 100644 index 07a6bb84..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestSysoutOOM.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - - -public class TestSysoutOOM extends JUnit4XmlTestBase { - @Test - public void sysoutoom() { - super.executeTarget("sysoutoom"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestTextReport.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestTextReport.java deleted file mode 100644 index 435c5ff4..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestTextReport.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import java.util.regex.Pattern; - -import org.junit.Assert; -import org.junit.Test; - -import com.carrotsearch.ant.tasks.junit4.tests.FailInAfterClass; -import com.carrotsearch.ant.tasks.junit4.tests.ReasonForAssumptionIgnored; - -/** - * Test report-text listener. - */ -public class TestTextReport extends JUnit4XmlTestBase { - @Test - public void suiteerror() { - super.executeTarget("suiteerror"); - - int count = countPattern(getLog(), FailInAfterClass.MESSAGE); - Assert.assertEquals(1, count); - } - - @Test - public void reasonForIgnored() { - super.executeTarget("reasonForIgnored"); - assertLogContains("@DisabledGroup"); - assertLogContains("> Cause: Annotated @Ignore"); - assertLogContains("(Ignored method.)"); - } - - @Test - public void reasonForIgnoredByDisabledGroup() { - super.executeTarget("reasonForIgnoredByDisabledGroup"); - String log = getLog(); - Assert.assertTrue(log.contains("(@DisabledGroup(value=foo bar))") || - log.contains("(@DisabledGroup(value=\"foo bar\"))")); - } - - @Test - public void reasonForSuiteAssumptionIgnored() { - super.executeTarget("reasonForSuiteAssumptionIgnored"); - - int count = countPattern(getLog(), ReasonForAssumptionIgnored.MESSAGE); - Assert.assertEquals(2, count); - } - - @Test - public void listeners() { - super.executeTarget("listeners"); - assertLogContains("testStarted: passing(com.carrotsearch.ant.tasks.junit4.tests.SuiteListeners)"); - assertLogContains("testFinished: passing(com.carrotsearch.ant.tasks.junit4.tests.SuiteListeners)"); - } - - @Test - public void timestamps() { - super.executeTarget("timestamps"); - Assert.assertTrue(getLog(), - Pattern.compile("\\[([0-9]{2}):([0-9]{2}):([0-9]{2})\\.([0-9]{3})\\]").matcher(getLog()).find()); - } - - @Test - public void sysoutsOnSuiteFailure() { - super.executeTarget("sysoutsOnSuiteFailure"); - assertLogContains("ignored-sysout"); - assertLogContains("success-sysout"); - assertLogContains("afterclass-sysout"); - assertLogContains("beforeclass-sysout"); - super.restoreSyserr.println(getLog()); - } - - @Test - public void sysoutsOnSuiteTimeout() { - super.executeTarget("sysoutsOnSuiteTimeout"); - assertLogContains("beforeclass-sysout"); - assertLogContains("test-sysout"); - String log = getLog(); - Assert.assertTrue( - log.indexOf("1> test-sysout") < - log.indexOf("Suite execution timed out:")); - } - - @Test - public void sysoutsPassthrough() { - super.executeTarget("sysouts_passthrough"); - } - - @Test - public void failureslist() { - super.executeTarget("failureslist"); - assertLogContains("Tests with failures"); - } - - @Test - public void filtertrace_default() { - super.executeTarget("filtertrace_default"); - - assertLogDoesNotContain("at sun.reflect."); - assertLogDoesNotContain("at java.lang.reflect.Method"); - assertLogDoesNotContain("at org.junit.runners."); - assertLogDoesNotContain("at com.carrotsearch.ant.tasks.junit4.slave.SlaveMain"); - } - - @Test - public void filtertrace_custom() { - super.executeTarget("filtertrace_custom"); - - assertLogContains("java.lang.reflect.Method"); - assertLogDoesNotContain("at org.junit."); - assertLogDoesNotContain(".SlaveMain."); - } - - @Test - public void errorsSoFarIndicator() { - super.executeTarget("errorsSoFar"); - assertLogContains("Completed [1/1 (1!)]"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestUnhandledSlaveFailure.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestUnhandledSlaveFailure.java deleted file mode 100644 index 5f73cac8..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestUnhandledSlaveFailure.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - -import java.io.IOException; - -import org.junit.Test; - -import com.carrotsearch.ant.tasks.junit4.tests.FireUnhandledRunnerException; - -public class TestUnhandledSlaveFailure extends JUnit4XmlTestBase { - @Test - public void checkSlaveMainFailure() throws IOException { - super.expectBuildExceptionContaining("slavemainfailure", "process threw an exception"); - assertLogContains(FireUnhandledRunnerException.EXCEPTION_MESSAGE); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestWeirdClasses.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestWeirdClasses.java deleted file mode 100644 index 7f013118..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/it/TestWeirdClasses.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.it; - - -import org.junit.Test; - -public class TestWeirdClasses extends JUnit4XmlTestBase { - /* - * Just run an example that shows JUnit's behavior on package-private/ abstract classes. - * https://github.com/carrotsearch/randomizedtesting/issues/91 - */ - @Test - public void antxml() { - super.executeTarget("weirdclasses"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/listeners/antxml/XmlStringTransformerAccess.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/listeners/antxml/XmlStringTransformerAccess.java deleted file mode 100644 index 84d16d66..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/listeners/antxml/XmlStringTransformerAccess.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.listeners.antxml; - -public class XmlStringTransformerAccess { - public static XmlStringTransformer getInstance() { - return new XmlStringTransformer(); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/runlisteners/UserDefinedRunListener1.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/runlisteners/UserDefinedRunListener1.java deleted file mode 100644 index 4a942504..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/runlisteners/UserDefinedRunListener1.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.runlisteners; - -import org.junit.runner.Description; -import org.junit.runner.Result; -import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunListener; - -public class UserDefinedRunListener1 extends RunListener { - - @Override - public void testRunStarted(Description description) throws Exception { - System.out.print("UserDefinedRunListener1.testRunStarted()"); - } - - @Override - public void testRunFinished(Result result) throws Exception { - System.out.print("UserDefinedRunListener1.testRunFinished()"); - } - - @Override - public void testStarted(Description description) throws Exception { - System.out.print("UserDefinedRunListener1.testStarted()"); - } - - @Override - public void testFinished(Description description) throws Exception { - System.out.print("UserDefinedRunListener1.testFinished()"); - } - - @Override - public void testFailure(Failure failure) throws Exception { - System.out.print("UserDefinedRunListener1.testFailure()"); - } - - @Override - public void testAssumptionFailure(Failure failure) { - System.out.print("UserDefinedRunListener1.testAssumptionFailure()"); - } - - @Override - public void testIgnored(Description description) throws Exception { - System.out.print("UserDefinedRunListener1.testIgnored()"); - } - -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/runlisteners/UserDefinedRunListener2.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/runlisteners/UserDefinedRunListener2.java deleted file mode 100644 index a0b585bc..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/runlisteners/UserDefinedRunListener2.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.runlisteners; - -import org.junit.runner.Description; -import org.junit.runner.Result; -import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunListener; - -public class UserDefinedRunListener2 extends RunListener { - - @Override - public void testRunStarted(Description description) throws Exception { - System.out.print("UserDefinedRunListener2.testRunStarted()"); - } - - @Override - public void testRunFinished(Result result) throws Exception { - System.out.print("UserDefinedRunListener2.testRunFinished()"); - } - - @Override - public void testStarted(Description description) throws Exception { - System.out.print("UserDefinedRunListener2.testStarted()"); - } - - @Override - public void testFinished(Description description) throws Exception { - System.out.print("UserDefinedRunListener2.testFinished()"); - } - - @Override - public void testFailure(Failure failure) throws Exception { - System.out.print("UserDefinedRunListener2.testFailure()"); - } - - @Override - public void testAssumptionFailure(Failure failure) { - System.out.print("UserDefinedRunListener2.testAssumptionFailure()"); - } - - @Override - public void testIgnored(Description description) throws Exception { - System.out.print("UserDefinedRunListener2.testIgnored()"); - } - -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/runlisteners/UserDefinedRunListener3.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/runlisteners/UserDefinedRunListener3.java deleted file mode 100644 index 1e22056b..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/runlisteners/UserDefinedRunListener3.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.runlisteners; - -import org.junit.runner.Description; -import org.junit.runner.Result; -import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunListener; - -public class UserDefinedRunListener3 extends RunListener { - - @Override - public void testRunStarted(Description description) throws Exception { - System.out.print("UserDefinedRunListener3.testRunStarted()"); - } - - @Override - public void testRunFinished(Result result) throws Exception { - System.out.print("UserDefinedRunListener3.testRunFinished()"); - } - - @Override - public void testStarted(Description description) throws Exception { - System.out.print("UserDefinedRunListener3.testStarted()"); - } - - @Override - public void testFinished(Description description) throws Exception { - System.out.print("UserDefinedRunListener3.testFinished()"); - } - - @Override - public void testFailure(Failure failure) throws Exception { - System.out.print("UserDefinedRunListener3.testFailure()"); - } - - @Override - public void testAssumptionFailure(Failure failure) { - System.out.print("UserDefinedRunListener3.testAssumptionFailure()"); - } - - @Override - public void testIgnored(Description description) throws Exception { - System.out.print("UserDefinedRunListener3.testIgnored()"); - } - -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/spikes/FloatSampling.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/spikes/FloatSampling.java deleted file mode 100644 index def46432..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/spikes/FloatSampling.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.spikes; - -import java.util.ArrayDeque; -import java.util.Arrays; -import java.util.Locale; -import java.util.Random; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Seed; - -public class FloatSampling extends RandomizedTest { - @SuppressWarnings("serial") - @Test - @Seed("deadbeef") - public void recurse() { - Random rnd = new Random(1) { - ArrayDeque r = new ArrayDeque<>(Arrays.asList( - Math.nextAfter(1f, Double.NEGATIVE_INFINITY), - Math.nextAfter(1f, Double.NEGATIVE_INFINITY), - Math.nextAfter(1f, Double.NEGATIVE_INFINITY), - Math.nextAfter(1f, Double.NEGATIVE_INFINITY) - )); - - @Override - public float nextFloat() { - if (r.isEmpty()) { - return super.nextFloat(); - } else { - return r.removeFirst(); - } - }; - }; - - float from = -Float.MAX_VALUE, - to = Float.MAX_VALUE; - System.out.println("R=" + info(randomBetween(rnd, from, to))); - - System.out.println(info(-0.0f)); - System.out.println(info(Math.nextAfter(0f, Double.NEGATIVE_INFINITY))); - System.out.println(info(Math.nextAfter(-0.0f, Double.NEGATIVE_INFINITY))); - } - - public static float randomBetween(Random rnd, float from, float to) { - assert !Float.isNaN(from) && - !Float.isNaN(to) && - !Float.isInfinite(from) && - !Float.isInfinite(to); - - float span = Float.MAX_VALUE; - // TODO: when there's a difference of 4 ulps low and high may never converge, we should - // select manually then. - while (from != to) { - // proportional selection factor between from and to. - float s = rnd.nextFloat(); - - // Determine lower ends of an interval where s and nextUp(s) would divide - // the representation space between from and to. Then proceed recursively - // until there's a single element left. - float low = low(s, from, to); - float high = low(Math.nextUp(s), from, to); - - // Sanity check. - assert (span = alwaysDecreases(span, high - low)) >= 0; - System.out.println(info(low)); - System.out.println(info(high)); - System.out.println("(" + from + ", " + to + ") -> s=" + s + " => (" + low + "," + high + "), range=" + (high - low)); - - from = low; to = high; - } - - return from; - } - - private static float alwaysDecreases(float prevSpan, float newSpan) { - if (prevSpan <= newSpan) { - throw new AssertionError("Interval should always decrease: " + prevSpan + " " + newSpan); - } - return newSpan; - } - - private static float low(float s, float min, float max) { - // Avoid range overflow by calculating proportion differently: - // s * (max - min) + min = - // s * max + (1 - s) * min - - if (s == 0f) return min; - if (s == 1f) return max; - - // All intermediate results are always pessimistically rounded down. - - float c1 = s * max; - if (c1 > 0) { - c1 = Math.nextAfter(c1, Double.NEGATIVE_INFINITY); - } - - float c4 = 1f - s; - if (c4 > 0) { - c4 = Math.nextAfter(c4, Double.NEGATIVE_INFINITY); - } - - float c2 = c4 * min; - if (c2 > 0) { - c2 = Math.nextAfter(c2, Double.NEGATIVE_INFINITY); - } - - float c3 = c1 + c2; - if (c3 > 0) { - c3 = Math.nextAfter(c3, Double.NEGATIVE_INFINITY); - } - - return c3; - } - - private static String info(float f) { - return String.format(Locale.ROOT, "<%.50f, 0x%08x>", f, Float.floatToIntBits(f)); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/spikes/LocalRun.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/spikes/LocalRun.java deleted file mode 100644 index 3034308e..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/spikes/LocalRun.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.spikes; - -import java.io.RandomAccessFile; -import java.util.Date; - - -@SuppressWarnings("resource") -public class LocalRun { - public static void main(String[] args) throws Exception { - System.out.println("Live and prosper."); - - // make sure to delete raf first. - final RandomAccessFile raf = new RandomAccessFile("shared.log", "rw"); - final RandomAccessFile raf2 = new RandomAccessFile("shared.log", "r"); - - Thread t1 = new Thread() { - @Override - public void run() { - while (true) { - try { - int c = raf2.read(); - if (c == -1) { - Thread.sleep(500); - continue; - } - - System.out.write(c); - System.out.flush(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - }; - - Thread t2 = new Thread() { - @Override - public void run() { - try { - while (true) { - raf.write((new Date().toString() + "\n").getBytes("UTF-8")); - Thread.sleep(2000); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - }; - - t1.start(); - t2.start(); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/spikes/TestStatusesIDE.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/spikes/TestStatusesIDE.java deleted file mode 100644 index b51ebe86..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/spikes/TestStatusesIDE.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.spikes; - -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.annotations.Nightly; -import com.carrotsearch.randomizedtesting.annotations.TestCaseOrdering; - -@Ignore -@RunWith(RandomizedRunner.class) -@TestCaseOrdering(TestCaseOrdering.AlphabeticOrder.class) -public class TestStatusesIDE { - @Test - public void _001_ok() { - } - - @Test @Ignore - public void _002_ignored() { - } - - @Test - public void _003_ignoredByExplicitAssumption() { - Assume.assumeTrue(false); - } - - @Test @Nightly - public void _004_ignoredByNightlyGroup() { - } - - @Test - public void _005_failedWithAssertion() { - Assert.assertTrue(false); - } - - @Test - public void _006_failedWithException() { - throw new RuntimeException(); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ChildVmSysprops.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ChildVmSysprops.java deleted file mode 100644 index 88d40314..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ChildVmSysprops.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import java.io.File; - -import org.junit.Assert; -import org.junit.Test; - -public class ChildVmSysprops { - @Test - public void cwd() { - Assert.assertNotNull(System.getProperty("junit4.childvm.cwd")); - Assert.assertTrue(new File(System.getProperty("junit4.childvm.cwd")).isDirectory()); - } - - @Test - public void id() { - Assert.assertNotNull(Integer.parseInt(System.getProperty("junit4.childvm.id"))); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/Crash.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/Crash.java deleted file mode 100644 index 9d00ac89..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/Crash.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -public class Crash { - public static native void crashMe(); - - public static void loadLibrary() { - StringBuilder b = new StringBuilder("Could not link with crashlib."); - try { - System.loadLibrary("crash"); - return; - } catch (UnsatisfiedLinkError e) { - b.append("\n").append(e.toString()); - } - - try { - System.loadLibrary("crash64"); - return; - } catch (UnsatisfiedLinkError e) { - b.append("\n").append(e.toString()); - } - - throw new UnsatisfiedLinkError(b.toString()); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/CwdConflict1.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/CwdConflict1.java deleted file mode 100644 index 3382577e..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/CwdConflict1.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import java.io.File; - -import org.junit.Test; - -public class CwdConflict1 { - @Test - public void testCreateConflictingFile() throws Exception { - File file = new File("cwdconflict.tmp"); - if (!file.createNewFile()) { - throw new RuntimeException("File already exists."); - } - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/CwdConflict2.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/CwdConflict2.java deleted file mode 100644 index f33de691..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/CwdConflict2.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - - -public class CwdConflict2 extends CwdConflict1 { -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/DisabledGroup.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/DisabledGroup.java deleted file mode 100644 index 95dc8fa8..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/DisabledGroup.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import java.lang.annotation.*; - -import com.carrotsearch.randomizedtesting.annotations.TestGroup; - -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.TYPE}) -@Inherited -@TestGroup(enabled = false) -public @interface DisabledGroup { - /** Additional description, if needed. */ - String value() default ""; -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/EscapeSequences.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/EscapeSequences.java deleted file mode 100644 index aa5124bd..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/EscapeSequences.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Test; - -public class EscapeSequences { - @Test - public void emitEscape() { - System.out.print("stdout: foo & bar"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/FailInAfterClass.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/FailInAfterClass.java deleted file mode 100644 index 3df9f1b0..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/FailInAfterClass.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.AfterClass; -import org.junit.Test; - -public class FailInAfterClass { - public final static String MESSAGE = "This is @AfterClass output."; - - @Test - public void dummy() {} - - @AfterClass - public static void afterClass() { - System.out.println(MESSAGE); - throw new RuntimeException(); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/FileEncoding.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/FileEncoding.java deleted file mode 100644 index 580969cb..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/FileEncoding.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import java.io.*; -import java.nio.charset.Charset; -import org.junit.Test; - -public class FileEncoding { - @Test - public void checkFileEncoding() throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - PrintStream ps = new PrintStream(baos); - ps.println("unicode string=cześć, Привет, 今日ã¯"); - ps.close(); - - String encoding = System.getProperty("file.encoding"); - System.out.println("file.encoding=" + encoding); - System.out.println("charset=" + Charset.defaultCharset()); - System.out.println("unicode string in " + encoding + "=cześć, Привет, 今日ã¯"); - System.out.println("unicode string PrintStream'ed: " + baos.size() + " bytes, hex dump:"); - - HexDump.dump(baos.toByteArray(), 0, System.out, 0); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/FireUnhandledRunnerException.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/FireUnhandledRunnerException.java deleted file mode 100644 index 11856df3..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/FireUnhandledRunnerException.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Test; - -import com.carrotsearch.ant.tasks.junit4.slave.SlaveMain; - -public class FireUnhandledRunnerException { - public static final String EXCEPTION_MESSAGE = "BAMBOOOOOCHA!"; - - @Test - public void polluteRunner() { - System.setProperty(SlaveMain.SYSPROP_FIRERUNNERFAILURE, EXCEPTION_MESSAGE); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/HeartbeatSlow.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/HeartbeatSlow.java deleted file mode 100644 index f944002c..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/HeartbeatSlow.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import java.util.concurrent.TimeUnit; - -import org.junit.Test; - -public class HeartbeatSlow { - @Test - public void method1() throws Exception { - Thread.sleep(TimeUnit.SECONDS.toMillis(3)); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/HexDump.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/HexDump.java deleted file mode 100644 index 3231fd75..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/HexDump.java +++ /dev/null @@ -1,147 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * Dumps data in hexadecimal format. - *

- * Provides a single function to take an array of bytes and display it - * in hexadecimal form. - *

- * Origin of code: POI. - * - * @author Scott Sanders - * @author Marc Johnson - * @version $Id: HexDump.java 736507 2009-01-22 00:52:15Z jukka $ - */ -public class HexDump { - - /** - * Instances should NOT be constructed in standard programming. - */ - public HexDump() { - super(); - } - - /** - * Dump an array of bytes to an OutputStream. The output is formatted - * for human inspection, with a hexadecimal offset followed by the - * hexadecimal values of the next 16 bytes of data and the printable ASCII - * characters (if any) that those bytes represent printed per each line - * of output. - *

- * The offset argument specifies the start offset of the data array - * within a larger entity like a file or an incoming stream. For example, - * if the data array contains the third kibibyte of a file, then the - * offset argument should be set to 2048. The offset value printed - * at the beginning of each line indicates where in that larger entity - * the first byte on that line is located. - *

- * All bytes between the given index (inclusive) and the end of the - * data array are dumped. - * - * @param data the byte array to be dumped - * @param offset offset of the byte array within a larger entity - * @param stream the OutputStream to which the data is to be - * written - * @param index initial index into the byte array - * - * @throws IOException is thrown if anything goes wrong writing - * the data to stream - * @throws ArrayIndexOutOfBoundsException if the index is - * outside the data array's bounds - * @throws IllegalArgumentException if the output stream is null - */ - - public static void dump(byte[] data, long offset, - OutputStream stream, int index) - throws IOException, ArrayIndexOutOfBoundsException, - IllegalArgumentException { - - if ((index < 0) || (index >= data.length)) { - throw new ArrayIndexOutOfBoundsException( - "illegal index: " + index + " into array of length " - + data.length); - } - if (stream == null) { - throw new IllegalArgumentException("cannot write to nullstream"); - } - long display_offset = offset + index; - StringBuilder buffer = new StringBuilder(74); - - for (int j = index; j < data.length; j += 16) { - int chars_read = data.length - j; - - if (chars_read > 16) { - chars_read = 16; - } - dump(buffer, display_offset).append(' '); - for (int k = 0; k < 16; k++) { - if (k < chars_read) { - dump(buffer, data[k + j]); - } else { - buffer.append(" "); - } - buffer.append(' '); - } - for (int k = 0; k < chars_read; k++) { - if ((data[k + j] >= ' ') && (data[k + j] < 127)) { - buffer.append((char) data[k + j]); - } else { - buffer.append('.'); - } - } - buffer.append(EOL); - stream.write(buffer.toString().getBytes()); - stream.flush(); - buffer.setLength(0); - display_offset += chars_read; - } - } - - /** - * The line-separator (initializes to "line.separator" system property. - */ - public static final String EOL = - System.getProperty("line.separator"); - private static final char[] _hexcodes = - { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F' - }; - private static final int[] _shifts = - { - 28, 24, 20, 16, 12, 8, 4, 0 - }; - - /** - * Dump a long value into a StringBuilder. - * - * @param _lbuffer the StringBuilder to dump the value in - * @param value the long value to be dumped - * @return StringBuilder containing the dumped value. - */ - private static StringBuilder dump(StringBuilder _lbuffer, long value) { - for (int j = 0; j < 8; j++) { - _lbuffer - .append(_hexcodes[((int) (value >> _shifts[j])) & 15]); - } - return _lbuffer; - } - - /** - * Dump a byte value into a StringBuilder. - * - * @param _cbuffer the StringBuilder to dump the value in - * @param value the byte value to be dumped - * @return StringBuilder containing the dumped value. - */ - private static StringBuilder dump(StringBuilder _cbuffer, byte value) { - for (int j = 0; j < 2; j++) { - _cbuffer.append(_hexcodes[(value >> _shifts[j + 6]) & 15]); - } - return _cbuffer; - } - -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/NotInstantiable.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/NotInstantiable.java deleted file mode 100644 index 3c30d23d..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/NotInstantiable.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Test; - -@SuppressWarnings("all") -public class NotInstantiable { - static { - System.out.println("Can't instantiate me." + 1 / ((Long) null)); - } - - public NotInstantiable() {} - - @Test - public void method() {} -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/OomCode.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/OomCode.java deleted file mode 100644 index b777f766..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/OomCode.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import java.util.LinkedList; - -import org.junit.Test; - -public class OomCode { - static LinkedList ohMy = new LinkedList(); - - @Test - public void oomInCode() { - int stringLength = 1024 * 1024 * 5; - while (true) { - try { - ohMy.add(new byte [stringLength]); - } catch (OutOfMemoryError e) { - if (stringLength < 100) { - throw e; - } else { - stringLength /= 2; - } - } - } - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/OomPermGen.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/OomPermGen.java deleted file mode 100644 index 5207d806..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/OomPermGen.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import static org.objectweb.asm.Opcodes.ACC_PUBLIC; -import static org.objectweb.asm.Opcodes.ACC_SUPER; -import static org.objectweb.asm.Opcodes.ALOAD; -import static org.objectweb.asm.Opcodes.INVOKESPECIAL; -import static org.objectweb.asm.Opcodes.RETURN; -import static org.objectweb.asm.Opcodes.V1_6; - -import java.lang.management.ManagementFactory; -import java.lang.management.MemoryPoolMXBean; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -import org.junit.Assume; -import org.junit.Test; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.MethodVisitor; - -public class OomPermGen { - abstract class WhoaClassLoader extends ClassLoader { - public abstract Class defineNewClass(byte [] clazz) throws ClassNotFoundException; - } - - WhoaClassLoader cl = new WhoaClassLoader() { - public Class defineNewClass(byte [] clazz) throws ClassNotFoundException { - return super.defineClass(null, clazz, 0, clazz.length); - } - }; - - @Test - public void explodePermGen() throws Exception { - MemoryPoolMXBean permGenPool = null; - for (MemoryPoolMXBean mp : ManagementFactory.getMemoryPoolMXBeans()) { - if (mp.getName().contains("Perm Gen")) { - permGenPool = mp; - break; - } - } - - if (permGenPool == null) { - // No permgen pool? - Assume.assumeTrue(false); - } - - // Just keep on loading classes until we explode. - Random rnd = new Random(0xdeadbeef); - int classes = 0; - List> keep = new ArrayList>(); - while (true) { - if ((classes++ % 1000) == 0) { - System.out.println(permGenPool.getName() + " => " + permGenPool.getUsage()); - } - - // Prepare a new unique exception class with asm. Throw it. - Class clz = generateExceptionClass(rnd.nextLong()); - clz.newInstance(); - keep.add(clz); - } - } - - public Class generateExceptionClass(long x) throws Exception { - ClassWriter cw = new ClassWriter(0); - MethodVisitor mv; - cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, - "com/carrotsearch/ant/tasks/junit4/tests/SyntheticException_" + x, null, - "java/lang/Exception", null); - - mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Exception", "", "()V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - cw.visitEnd(); - - return cl.defineNewClass(cw.toByteArray()); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/OutOfOrderSysouts.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/OutOfOrderSysouts.java deleted file mode 100644 index 921ceb9a..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/OutOfOrderSysouts.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.*; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; - -@ThreadLeakScope(Scope.SUITE) -public class OutOfOrderSysouts extends RandomizedTest { - private static Thread t; - - static { - t = new Thread("background-non-daemon") { - public void run() { - sysout("Starting..."); - try { - while (true) { - syserr("garbage..."); - Thread.sleep(1); - } - } catch (Exception e) { - // empty. - } - } - }; - t.start(); - } - - @Before - public void before() { - sleep(1 + randomIntBetween(0, 20)); - } - - @AfterClass - public static void afterClass() throws Exception { - t.interrupt(); - t.join(); - } - - @Test public void method1() { sysout("method1"); } - @Test public void method2() { sysout("method2"); } - @Test public void method3() { sysout("method3"); } - @Test public void method4() { sysout("method4"); } - @Test public void method5() { sysout("method5"); } - @Test public void method6() { sysout("method6"); } - @Test public void method7() { sysout("method7"); } - @Test public void method8() { sysout("method8"); } - @Test public void method9() { sysout("method9"); } - @Test public void method10() { sysout("method10"); } - @Test public void method11() { sysout("method11"); } - - static void sysout(String msg) { - System.out.println(msg); - System.out.flush(); - } - - static void syserr(String msg) { - System.out.println(msg); - System.out.flush(); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/RandomSysProperty.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/RandomSysProperty.java deleted file mode 100644 index a17381ae..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/RandomSysProperty.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Test; - -public class RandomSysProperty { - @Test - public void test1() { - for (String s : new String [] { - "prefix.dummy1", - "prefix.dummy2", - "replaced.dummy1", - "replaced.dummy2", - }) { - System.out.println(s + "=" + System.getProperty(s)); - } - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ReasonForAssumptionIgnored.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ReasonForAssumptionIgnored.java deleted file mode 100644 index 684c0f5b..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ReasonForAssumptionIgnored.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.carrotsearch.ant.tasks.junit4.it.TestTextReport; -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.RandomizedTest; - -/** - * Holder class for tests used in - * {@link TestTextReport#reasonForSuiteAssumptionIgnored()}. - */ -public class ReasonForAssumptionIgnored { - public final static String MESSAGE = "FooBar"; - - @RunWith(RandomizedRunner.class) - public static class IgnoredClassRR extends IgnoredClass { - } - - public static class IgnoredClass { - @BeforeClass - public static void beforeClass() { - RandomizedTest.assumeTrue(MESSAGE, false); - } - - @Test - public void ignored1() {} - - @Test - public void ignored2() {} - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ReasonForIgnored.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ReasonForIgnored.java deleted file mode 100644 index 5f242333..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ReasonForIgnored.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.carrotsearch.ant.tasks.junit4.it.TestTextReport; -import com.carrotsearch.randomizedtesting.RandomizedRunner; - -/** - * Holder class for tests used in {@link TestTextReport#reasonForIgnored()}. - */ -public class ReasonForIgnored -{ - public static class IgnoredMethods { - @Test - @Ignore - public void simplyIgnored() { - } - - @Test - @Ignore("Ignored method.") - public void ignoredWithRationale() { - } - } - - @Ignore("Ignored class.") - public static class IgnoredClass { - @Test - public void ignoredByClass() { - System.out.println("Hello!"); - } - } - - @RunWith(RandomizedRunner.class) - public static class IgnoredMethodsRR extends IgnoredMethods { - @Test - @Ignore("Ignored method (2).") - public void ignoredAgain() { - } - } - - @Ignore("Ignored class.") - @RunWith(RandomizedRunner.class) - public static class IgnoredClassRR extends IgnoredClass { - } - - @RunWith(RandomizedRunner.class) - public static class IgnoredGroup { - @DisabledGroup @Test - public void ignoredByGroup() {} - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ReasonForIgnoredByDisabledGroup.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ReasonForIgnoredByDisabledGroup.java deleted file mode 100644 index 35276ce0..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ReasonForIgnoredByDisabledGroup.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; - -public class ReasonForIgnoredByDisabledGroup extends RandomizedTest -{ - @Test - @DisabledGroup("foo bar") - public void disabledGroup() {} -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ShutdownHook.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ShutdownHook.java deleted file mode 100644 index 8e1dd9de..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/ShutdownHook.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Test; - -public class ShutdownHook { - @Test - public void testShutdownHook() { - Runtime.getRuntime().addShutdownHook(new Thread() { - public void run() { - // Delay by about a minute. - long deadline = System.currentTimeMillis() + 60 * 1000; - while (System.currentTimeMillis() < deadline) { - try { - Thread.sleep(1000); - } catch (Exception e) {} - } - } - }); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SlaveHangingBackgroundThreads.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SlaveHangingBackgroundThreads.java deleted file mode 100644 index 053476e1..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SlaveHangingBackgroundThreads.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import java.util.concurrent.CountDownLatch; - -import org.junit.Test; - - -public class SlaveHangingBackgroundThreads { - static { - final CountDownLatch latch = new CountDownLatch(1); - new Thread("background-non-daemon") { - public void run() { - System.out.println("Starting."); - try { - latch.countDown(); - // Wait looong. - Thread.sleep(1000 * 60 * 60); - } catch (Exception e) { - // empty. - } - } - }.start(); - - try { - latch.await(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - - // Cause an unchecked exception. - @SuppressWarnings("unused") - int a = 2 / 0; - } - - @Test - public void method() { - // Ok, passes. - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/StackOverflow.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/StackOverflow.java deleted file mode 100644 index c63808f7..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/StackOverflow.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Test; - -public class StackOverflow { - @Test - public void stackoverflow() { - for (int i = 0; i < 100; i++) { - try { - doStackOverflowAndPrint(0); - } catch (StackOverflowError e) { - // Should have failed inside the runner's infrastructure? - } - } - System.exit(0); - } - - private void doStackOverflowAndPrint(int i) { - System.out.println("Stack overflow attempt: " + i); - doStackOverflowAndPrint(i + 1); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SuiteListeners.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SuiteListeners.java deleted file mode 100644 index 9f15f6d7..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SuiteListeners.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.Description; -import org.junit.runner.Result; -import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunListener; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Listeners; - -import static org.junit.Assert.*; - -@Listeners({ - SuiteListeners.PrintEventListener.class -}) -public class SuiteListeners extends RandomizedTest { - - public static class PrintEventListener extends RunListener { - - @Override - public void testRunStarted(Description description) throws Exception { - System.out.println("testRunStarted: " + description); - } - - @Override - public void testRunFinished(Result result) throws Exception { - System.out.println("testRunFinished."); - } - - @Override - public void testStarted(Description description) throws Exception { - System.out.println("testStarted: " + description); - } - - @Override - public void testFinished(Description description) throws Exception { - System.out.println("testFinished: " + description); - } - - @Override - public void testFailure(Failure failure) throws Exception { - System.out.println("testFailure: " + failure); - } - - @Override - public void testAssumptionFailure(Failure failure) { - System.out.println("testAssumptionFailure: " + failure); - } - - @Override - public void testIgnored(Description description) throws Exception { - System.out.println("testIgnored: " + description); - } - } - - @Test - public void passing() {} - - @Test @Ignore - public void ignored() {} - - @Test - public void aignored() { assumeTrue(false); } - - @Test - public void failure() { fail(); } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysPropertySets.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysPropertySets.java deleted file mode 100644 index b0226f0b..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysPropertySets.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Test; - -public class SysPropertySets { - @Test - public void test1() { - System.out.println(System.getProperty("prefix.dummy1")); - System.out.println(System.getProperty("prefix.dummy2")); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutOom1.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutOom1.java deleted file mode 100644 index 3b6f79a1..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutOom1.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Test; - -public class SysoutOom1 { - @Test - public void writealot() { - write("012345678901234567890123456789".toCharArray()); - } - - protected final void write(char[] charArray) { - char [] chars = new char [200]; - for (int i = 0; i < chars.length; i++) { - chars[i] = charArray[i % charArray.length]; - } - - int emitChars = 1024 * 1024 * 25; - while (emitChars > 0) { - System.out.print(chars); - emitChars -= chars.length; - } - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutOom2.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutOom2.java deleted file mode 100644 index cdcc6473..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutOom2.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Test; - -public class SysoutOom2 extends SysoutOom1 { - @Override - @Test - public void writealot() { - write("abcdefghjqiuqiugqwpicvaisuvcipsvcuipqyfpuixv".toCharArray()); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutPassthrough.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutPassthrough.java deleted file mode 100644 index 3eeec63e..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutPassthrough.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -public class SysoutPassthrough { - @BeforeClass - public static void beforeclass() { - println("-beforeclass-"); - } - - @Before - public void before() { - println("-before-"); - } - - @Test - public void test1() { - println("-test1-"); - } - - @Test - public void test2() { - println("-test2-"); - } - - @After - public void after() { - print("-after-"); - } - - @AfterClass - public static void afterclass() { - println("-afterclass-"); - } - - private static void print(String m) { - System.out.print(m); - System.out.flush(); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - throw new RuntimeException(); - } - } - - private static void println(String m) { - print(m + "\n"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutsOnSuiteFailure.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutsOnSuiteFailure.java deleted file mode 100644 index 63d5476b..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutsOnSuiteFailure.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.AfterClass; -import org.junit.Assume; -import org.junit.BeforeClass; -import org.junit.Test; - -public class SysoutsOnSuiteFailure { - - @BeforeClass - public static void beforeClass() { - System.out.println("beforeclass-sysout."); - } - - @Test - public void assumptionIgnored() { - System.out.println("ignored-sysout."); - Assume.assumeTrue(false); - } - - @Test - public void success() { - System.out.println("success-sysout."); - } - - @AfterClass - public static void afterClass() { - System.out.println("afterclass-sysout."); - throw new RuntimeException(); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutsOnSuiteTimeout.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutsOnSuiteTimeout.java deleted file mode 100644 index 394b8954..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/SysoutsOnSuiteTimeout.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.BeforeClass; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction.Action; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakGroup; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakGroup.Group; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; -import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite; - -@ThreadLeakScope(Scope.SUITE) -@ThreadLeakGroup(Group.MAIN) -@ThreadLeakAction({Action.WARN, Action.INTERRUPT}) -@ThreadLeakLingering(linger = 1000) -@TimeoutSuite(millis = 1000) -public class SysoutsOnSuiteTimeout extends RandomizedTest { - @BeforeClass - public static void beforeClass() { - System.out.println("beforeclass-sysout."); - } - - @Test - public void success() throws Exception { - System.out.println("test-sysout."); - Thread.sleep(100000); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestAfterClassError.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestAfterClassError.java deleted file mode 100644 index 65ffa1f2..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestAfterClassError.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.AfterClass; -import org.junit.Test; - -public class TestAfterClassError { - @AfterClass - public static void afterClass() { - throw new RuntimeException(); - } - - @Test - public void method() {} -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestBeforeClassError.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestBeforeClassError.java deleted file mode 100644 index 04318a30..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestBeforeClassError.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.BeforeClass; -import org.junit.Test; - -public class TestBeforeClassError { - @BeforeClass - public static void beforeClass() { - throw new RuntimeException(); - } - - @Test - public void method() {} -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestCreateTmpFile.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestCreateTmpFile.java deleted file mode 100644 index 956e6b33..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestCreateTmpFile.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import static org.junit.Assert.*; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.junit.Test; - -public class TestCreateTmpFile { - @Test - public void createTmpFile() throws IOException { - Path path = Paths.get(System.getProperty("java.io.tmpdir")).toAbsolutePath(); - System.out.println("Temporary folder at: " + path + ", exists: " + Files.exists(path)); - Path tmpFile = Files.createTempFile("tmp", ".txt"); - assertTrue(Files.exists(tmpFile)); - System.out.println("Created tmpfile: " + tmpFile.toAbsolutePath()); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestDir.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestDir.java deleted file mode 100644 index 23986fe0..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestDir.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; - -import org.junit.Test; - -public class TestDir { - @Test - public void createDir() throws IOException { - Files.createFile(Paths.get("touch.me")); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestEnvVar.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestEnvVar.java deleted file mode 100644 index 22448b88..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestEnvVar.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Test; - -public class TestEnvVar { - /** - * Check environment property passing. - */ - @Test - public void testEnvVar() throws IOException { - String value = System.getenv("env.variable"); - Assert.assertEquals("foobar", value); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestEscaping.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestEscaping.java deleted file mode 100644 index 2b7d500c..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestEscaping.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Assert; -import org.junit.Test; - -public class TestEscaping { - @Test - public void checkEscapes() { - // success it is. - System.out.println(System.getProperty("sysprop.key")); - System.out.println(System.getProperty("sysprop.key2")); - System.out.println(System.getProperty("sysprop.key3")); - System.out.println(System.getenv("env.variable")); - - Assert.assertEquals("${nonexistent-1}", System.getProperty("sysprop.key")); - Assert.assertEquals("abc def", System.getProperty("sysprop.key2")); - Assert.assertEquals("%PATH%", System.getProperty("sysprop.key3")); - Assert.assertEquals("${nonexistent-3}", System.getenv("env.variable")); - } - - public static void main(String[] args) { - new TestEscaping().checkEscapes(); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestFailureTypePassing.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestFailureTypePassing.java deleted file mode 100644 index 856d72ce..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestFailureTypePassing.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import static org.objectweb.asm.Opcodes.ACC_PUBLIC; -import static org.objectweb.asm.Opcodes.ACC_SUPER; -import static org.objectweb.asm.Opcodes.ALOAD; -import static org.objectweb.asm.Opcodes.INVOKESPECIAL; -import static org.objectweb.asm.Opcodes.RETURN; -import static org.objectweb.asm.Opcodes.V1_6; - -import org.junit.Test; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.MethodVisitor; - -public class TestFailureTypePassing { - @Test - public void nonStandardError() throws Exception { - // Prepare a new unique exception class with asm. Throw it. - Class clz = generateExceptionClass(); - throw Exception.class.cast(clz.newInstance()); - } - - public static Class generateExceptionClass() throws Exception { - ClassWriter cw = new ClassWriter(0); - MethodVisitor mv; - cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, - "com/carrotsearch/ant/tasks/junit4/tests/SyntheticException", null, - "java/lang/Exception", null); - - mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Exception", "", "()V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - cw.visitEnd(); - - return new ClassLoader() { - public Class defineNewClass(byte [] clazz) throws ClassNotFoundException { - return super.defineClass(null, clazz, 0, clazz.length); - } - }.defineNewClass(cw.toByteArray()); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestFilteringExpressions.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestFilteringExpressions.java deleted file mode 100644 index 95e1bc33..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestFilteringExpressions.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.TestGroup; - -public class TestFilteringExpressions { - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD, ElementType.TYPE}) - @Inherited - @TestGroup(enabled = false) - public static @interface Foo {} - - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD, ElementType.TYPE}) - @Inherited - @TestGroup(enabled = false) - public static @interface Bar {} - - public static class Example1 extends RandomizedTest { - @Test @Foo - public void testFoo() { - System.out.println(">foo<"); - } - - @Test @Foo @Bar - public void testFooBar() { - System.out.println(">foobar<"); - } - - @Test @Bar - public void testBar() { - System.out.println(">bar<"); - } - } - - public static class Example2 extends RandomizedTest { - @Test @Foo @Bar - public void testFooBar() { - System.out.println(">foobar2<"); - } - - @Test @Bar - public void testBar() { - System.out.println(">bar2<"); - } - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestHierarchicalSuiteDescription.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestHierarchicalSuiteDescription.java deleted file mode 100644 index 26bd3b38..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestHierarchicalSuiteDescription.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({ - TestHierarchicalSuiteDescription.Sub1.class, - TestHierarchicalSuiteDescription.Sub2.class, - TestHierarchicalSuiteDescription.Sub3.class -}) -public class TestHierarchicalSuiteDescription { - public static class Sub1 { - @Test - public void method1() {} - - @BeforeClass - public static void beforeClass() { - throw new RuntimeException(); - } - } - - public static class Sub2 { - @Test - public void method1() {} - - @AfterClass - public static void afterClass() { - throw new RuntimeException(); - } - } - - public static class Sub3 { - @Test - public void method1() { - throw new RuntimeException(); - } - } - - @AfterClass - public static void afterClass() { - throw new RuntimeException(); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestIgnoredSuite.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestIgnoredSuite.java deleted file mode 100644 index 2824c633..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestIgnoredSuite.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Ignore; -import org.junit.Test; - -@Ignore -public class TestIgnoredSuite { - @Test - public void method1() {} - - @Test - public void method2() {} - - @Test - public void method3() {} - - @Test - public void method4() {} - - @Test - public void method5() {} -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestInvalidUtfCharacter.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestInvalidUtfCharacter.java deleted file mode 100644 index 4f21d1b4..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestInvalidUtfCharacter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Test; - -public class TestInvalidUtfCharacter { - @Test - public void emitInvalidCharacter() throws Exception { - String msg = "Invalid char: >\u0002< >\u0000<"; - System.out.println(msg); - System.out.flush(); - throw new Exception(msg); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestJvmArg.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestJvmArg.java deleted file mode 100644 index 2ecdef74..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestJvmArg.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Assert; -import org.junit.Test; - -public class TestJvmArg { - /** - * Check system property passing. - */ - @Test - public void testJvmArg() { - Assert.assertEquals("foobar", System.getProperty("test.param")); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestJvmCrash.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestJvmCrash.java deleted file mode 100644 index 6f0053a7..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestJvmCrash.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Test; - -public class TestJvmCrash { - /** - * Check jvm crash. - */ - @Test - public void testJvmCrash() throws IOException { - // Try going into native mode first and cause a sigsegv. - // This will work for any jvm (?). - Crash.loadLibrary(); - Crash.crashMe(); - Assert.fail(); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestMaxMem.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestMaxMem.java deleted file mode 100644 index 00f51343..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestMaxMem.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Assert; -import org.junit.Test; - -public class TestMaxMem { - /** - * Check max memory setting to be less than 100mb. - */ - @Test - public void testMaxMemory() { - long maxMemory = Runtime.getRuntime().maxMemory(); - Assert.assertTrue(maxMemory / (1024 * 1024) < 110); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestReproduceString.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestReproduceString.java deleted file mode 100644 index 6164b8b4..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestReproduceString.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Assert; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Listeners; -import com.carrotsearch.randomizedtesting.listeners.ReproduceInfoPrinter; - -@Listeners({ - ReproduceInfoPrinter.class -}) -public class TestReproduceString extends RandomizedTest { - @Test - public void alwaysFail() { - Assert.fail(); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestSecuritySandbox.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestSecuritySandbox.java deleted file mode 100644 index d27061b2..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestSecuritySandbox.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Test; - -public class TestSecuritySandbox { - @Test - public void accessDenied() { - System.getProperty("foo"); - System.setProperty("foo", "bar"); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestSeedPassing.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestSeedPassing.java deleted file mode 100644 index 63790dd6..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestSeedPassing.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.*; -import static com.carrotsearch.randomizedtesting.SysGlobals.*; - -public class TestSeedPassing extends RandomizedTest { - @Test - public void checkSeedSet() throws IOException { - String expected = SeedUtils.formatSeedChain( - new Randomness(0xdeadbeefL, RandomSupplier.DEFAULT), - new Randomness(0xcafebabeL, RandomSupplier.DEFAULT)); - - Assert.assertEquals( - expected, - System.getProperty(SYSPROP_RANDOM_SEED())); - - Assert.assertEquals( - "[CAFEBABE]", - SeedUtils.formatSeedChain(getContext().getRandomness())); - - Assert.assertEquals( - "[DEADBEEF]", - SeedUtils.formatSeedChain( - new Randomness( - SeedUtils.parseSeed(getContext().getRunnerSeedAsString()), - RandomSupplier.DEFAULT))); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestStaticScopeOutput.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestStaticScopeOutput.java deleted file mode 100644 index 9ac5fa24..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestStaticScopeOutput.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -/** - * Static scope output. - */ -public class TestStaticScopeOutput { - static { - System.out.println("static-scope"); - System.out.flush(); - } - - @BeforeClass - public static void beforeClass() { - System.out.println("before-class"); - System.out.flush(); - } - - @Test - public void testMethod() { - System.out.println("test-method"); - System.out.flush(); - } - - @AfterClass - public static void afterClass() { - System.out.println("after-class"); - System.out.flush(); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestStatuses.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestStatuses.java deleted file mode 100644 index 7e30b221..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestStatuses.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Ignore; -import org.junit.Test; - -public class TestStatuses { - @Test - public void ok() { - } - - @Test @Ignore - public void ignored() { - } - - @Test - public void ignored_a() { - Assume.assumeTrue(false); - } - - @Test - public void failure() { - Assert.assertTrue(false); - } - - @Test - public void error() { - throw new RuntimeException(); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestSuccess.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestSuccess.java deleted file mode 100644 index 0c1853f9..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestSuccess.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.SeedUtils; - -public class TestSuccess extends RandomizedTest { - @Test - public void alwaysPasses() { - System.out.println("Seed: " + - SeedUtils.formatSeedChain(getContext().getRandomness())); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestSysstreams.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestSysstreams.java deleted file mode 100644 index 5d44c3d9..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/TestSysstreams.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests; - -import org.junit.Test; - -public class TestSysstreams { - @Test - public void ok() {} - - @Test - public void ok_sysout_syserr() { - System.out.print("sysout"); - System.out.flush(); - System.err.print("syserr"); - System.err.flush(); - System.out.print("-sysout-contd."); - System.out.flush(); - System.err.print("-syserr-contd."); - System.err.flush(); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/bad/TestAbstract.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/bad/TestAbstract.java deleted file mode 100644 index a560c76d..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/bad/TestAbstract.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests.bad; - -import org.junit.Test; - -public abstract class TestAbstract { - @Test - public void shouldBeIgnored() {} -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/bad/TestPackagePrivate.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/bad/TestPackagePrivate.java deleted file mode 100644 index 04022ed9..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/bad/TestPackagePrivate.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests.bad; - -class TestPackagePrivate { -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/replication/TestNonReplicated1.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/replication/TestNonReplicated1.java deleted file mode 100644 index 926a2d70..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/replication/TestNonReplicated1.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests.replication; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; - -public class TestNonReplicated1 extends RandomizedTest { - @Test - public void nonReplicatedTest() { - System.out.println("Non-replicated test, VM: " + System.getProperty("junit4.childvm.id")); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/replication/TestNonReplicated2.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/replication/TestNonReplicated2.java deleted file mode 100644 index c71dd106..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/replication/TestNonReplicated2.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests.replication; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; - -public class TestNonReplicated2 extends RandomizedTest { - @Test - public void nonReplicatedTest() { - System.out.println("Non-replicated test, VM: " + System.getProperty("junit4.childvm.id")); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/replication/TestPseudoLoadBalancing.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/replication/TestPseudoLoadBalancing.java deleted file mode 100644 index a556812a..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/replication/TestPseudoLoadBalancing.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests.replication; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -import org.junit.Before; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Name; -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; -import com.carrotsearch.randomizedtesting.annotations.ReplicateOnEachVm; - -@ReplicateOnEachVm -public class TestPseudoLoadBalancing extends RandomizedTest { - private int id; - private int jvmId; - private int jvms; - - public TestPseudoLoadBalancing(@Name("id") int id) { - this.id = id; - } - - @Before - public void pseudoLoadBalancing() { - jvmId = Integer.parseInt(System.getProperty("junit4.childvm.id")); - jvms = Integer.parseInt(System.getProperty("junit4.childvm.count")); - - assumeTrue( - String.format(Locale.ROOT, "Test %d ignored on VM %d.", id, jvmId), - (id % jvms) == jvmId); - } - - @Test - public void replicatedTest() { - System.out.println(String.format(Locale.ROOT, "Test %d executed on VM %d.", id, jvmId)); - } - - @ParametersFactory - public static Iterable parameters() { - List args = new ArrayList(); - for (int i = 0; i < 100; i++) { - args.add($(i)); - } - return args; - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/replication/TestSuiteReplicated.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/replication/TestSuiteReplicated.java deleted file mode 100644 index b1159240..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/replication/TestSuiteReplicated.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests.replication; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.ReplicateOnEachVm; - -@ReplicateOnEachVm -public class TestSuiteReplicated extends RandomizedTest { - @Test - public void replicatedTest() { - System.out.println("Replicated test, VM: " + System.getProperty("junit4.childvm.id")); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub1/TestAssertions.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub1/TestAssertions.java deleted file mode 100644 index e6a658ed..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub1/TestAssertions.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests.sub1; - -import org.junit.Test; - -public class TestAssertions { - @Test - public void failOnAssertion() { - assert false : "foobar"; - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub2/TestHalfSecond.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub2/TestHalfSecond.java deleted file mode 100644 index 071f23dd..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub2/TestHalfSecond.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests.sub2; - -import org.junit.Test; - -public class TestHalfSecond { - @Test - public void halfSecond() throws Exception { - Thread.sleep(500); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub2/TestOneSecond.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub2/TestOneSecond.java deleted file mode 100644 index 705eeb0a..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub2/TestOneSecond.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests.sub2; - -import org.junit.Test; - -public class TestOneSecond { - @Test - public void quarterSecond1() throws Exception { - Thread.sleep(250); - } - - @Test - public void quarterSecond2() throws Exception { - Thread.sleep(250); - } - - @Test - public void quarterSecond3() throws Exception { - Thread.sleep(250); - } - - @Test - public void quarterSecond4() throws Exception { - Thread.sleep(250); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub2/TestTwoSeconds.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub2/TestTwoSeconds.java deleted file mode 100644 index 9722ffdd..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub2/TestTwoSeconds.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests.sub2; - -import org.junit.Test; - -public class TestTwoSeconds { - @Test - public void oneSecond1() throws Exception { - Thread.sleep(1000); - } - - @Test - public void oneSecond2() throws Exception { - Thread.sleep(1000); - } -} diff --git a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub2/TestZeroSeconds.java b/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub2/TestZeroSeconds.java deleted file mode 100644 index 334bacff..00000000 --- a/junit4-ant/src/test/java/com/carrotsearch/ant/tasks/junit4/tests/sub2/TestZeroSeconds.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.carrotsearch.ant.tasks.junit4.tests.sub2; - -import org.junit.Test; - -public class TestZeroSeconds { - @Test - public void zero() throws Exception { - } -} diff --git a/junit4-ant/src/test/resources/hints-fixed.log b/junit4-ant/src/test/resources/hints-fixed.log deleted file mode 100644 index de317cf9..00000000 --- a/junit4-ant/src/test/resources/hints-fixed.log +++ /dev/null @@ -1,4 +0,0 @@ -com.carrotsearch.ant.tasks.junit4.tests.sub2.TestHalfSecond=500,501,501,501,521 -com.carrotsearch.ant.tasks.junit4.tests.sub2.TestOneSecond=1002,1018,1022,1002,1002 -com.carrotsearch.ant.tasks.junit4.tests.sub2.TestTwoSeconds=2016,2019,2028,2024,2019 -com.carrotsearch.ant.tasks.junit4.tests.sub2.TestZeroSeconds=15,2,1,22,2 diff --git a/junit4-ant/src/test/resources/junit4.xml b/junit4-ant/src/test/resources/junit4.xml deleted file mode 100644 index a8472ab7..00000000 --- a/junit4-ant/src/test/resources/junit4.xml +++ /dev/null @@ -1,1572 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${native.libs} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${basedir} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - jvm.exec property must be set. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UTF-8 - UTF-16 - US-ASCII - iso8859-1 - - - - UTF-8 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${junit4.stats.tests} - ${junit4.stats.errors} - ${junit4.stats.failures} - ${junit4.stats.ignores} - ${junit4.stats.suites} - ${junit4.stats.assumptions} - ${junit4.stats.suiteErrors} - ${junit4.stats.nonIgnored} - ${junit4.stats.successful} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${junit4.stats.tests} - ${junit4.stats.errors} - ${junit4.stats.failures} - ${junit4.stats.ignores} - ${junit4.stats.suites} - ${junit4.stats.assumptions} - ${junit4.stats.suiteErrors} - ${junit4.stats.nonIgnored} - ${junit4.stats.successful} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/junit4-ant/src/test/resources/security.policy b/junit4-ant/src/test/resources/security.policy deleted file mode 100644 index 24b2187f..00000000 --- a/junit4-ant/src/test/resources/security.policy +++ /dev/null @@ -1,37 +0,0 @@ - -//// permission for the junit4 jar -grant codeBase "${junit4.jar.url}" { - // needed because JUnit requests/ runners don't use access controller contexts - // and the access control domain propagates up the stack. - permission java.lang.RuntimePermission "accessDeclaredMembers"; - // needed for io stream handling - permission java.lang.RuntimePermission "setIO"; - // needed for accessing log files, etc. - permission java.io.FilePermission "${junit4.tempDir}${/}*", "read,write,delete,execute"; -}; - -//// permissions for the randomized runner jar -grant codeBase "${randomizedtesting.jar.url}" { - // optionally needed for access to private test methods (e.g. beforeClass) - permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; - // needed to handle uncaught exceptions from other threads - permission java.lang.RuntimePermission "setDefaultUncaughtExceptionHandler"; - // needed for getTopThreads - permission java.lang.RuntimePermission "modifyThreadGroup"; - // needed for TestClass creation - permission java.lang.RuntimePermission "accessDeclaredMembers"; - // needed for ThreadLeakControl - permission java.lang.RuntimePermission "getStackTrace"; -}; - -//// permissions for the junit jar -grant codeBase "${junit.jar.url}" { - // needed for TestClass creation - permission java.lang.RuntimePermission "accessDeclaredMembers"; -}; - -//// Test class permission: we want this to be minimal! -grant { - permission java.util.PropertyPermission "*", "read"; - permission java.io.FilePermission "${junit4.childvm.cwd}${/}*", "read,write,delete"; -}; diff --git a/junit4-maven-plugin-tests/pom.xml b/junit4-maven-plugin-tests/pom.xml deleted file mode 100644 index f61530d2..00000000 --- a/junit4-maven-plugin-tests/pom.xml +++ /dev/null @@ -1,70 +0,0 @@ - - 4.0.0 - - - com.carrotsearch.randomizedtesting - randomizedtesting-parent - 2.7.9-SNAPSHOT - ../pom.xml - - - junit4-maven-plugin-tests - - jar - - - true - - - - - junit - junit - - - - com.carrotsearch.randomizedtesting - randomizedtesting-runner - ${project.version} - - - - com.carrotsearch.randomizedtesting - junit4-maven-plugin - ${project.version} - - - - - - - maven-invoker-plugin - - true - src/it - ${project.build.directory}/it - true - - **/pom.xml - - - pom.xml - - verify - ${project.build.directory}/local-repo - src/it/settings.xml - - - - integration-test - - install - run - - - - - - - diff --git a/junit4-maven-plugin-tests/src/it/01-basic-test/invoker.properties b/junit4-maven-plugin-tests/src/it/01-basic-test/invoker.properties deleted file mode 100644 index ad075dbf..00000000 --- a/junit4-maven-plugin-tests/src/it/01-basic-test/invoker.properties +++ /dev/null @@ -1 +0,0 @@ -invoker.goals=test \ No newline at end of file diff --git a/junit4-maven-plugin-tests/src/it/01-basic-test/pom.xml b/junit4-maven-plugin-tests/src/it/01-basic-test/pom.xml deleted file mode 100644 index 63b0090a..00000000 --- a/junit4-maven-plugin-tests/src/it/01-basic-test/pom.xml +++ /dev/null @@ -1,123 +0,0 @@ - - 4.0.0 - - com.carrotsearch.randomizedtesting - junit4-maven-plugin-tests - 0.0.1-SNAPSHOT - - jar - - - 3.0.2 - - - - UTF-8 - UTF-8 - - 1.8 - 1.8 - - - - - com.carrotsearch.randomizedtesting - randomizedtesting-runner - @project.version@ - test - - - - com.carrotsearch.thirdparty - simple-xml-safe - 2.7.1 - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - true - - - - - com.carrotsearch.randomizedtesting - junit4-maven-plugin - @project.version@ - - - junit4-tests - - junit4 - - - 10 - pipe,ignore - true - warn - - com.carrotsearch.thirdparty:simple-xml-safe - - - - -DargLine.property=foobar - -DargLine.property2=foobar - - - - - - - - - - - - - - - - - - **/Test0*.class - - - **/Buhu* - - - - - - - - - - - - diff --git a/junit4-maven-plugin-tests/src/it/01-basic-test/src/test/java/com/carrotsearch/examples/randomizedrunner/Test001InsideMaven.java b/junit4-maven-plugin-tests/src/it/01-basic-test/src/test/java/com/carrotsearch/examples/randomizedrunner/Test001InsideMaven.java deleted file mode 100644 index 927e1e37..00000000 --- a/junit4-maven-plugin-tests/src/it/01-basic-test/src/test/java/com/carrotsearch/examples/randomizedrunner/Test001InsideMaven.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import org.junit.Assert; -import org.junit.Test; - -public class Test001InsideMaven { - @Test - public void success() { - // Empty. - } - - @Test - public void checkArgLinePassed() { - Assert.assertEquals("foobar", System.getProperty("argLine.property")); - Assert.assertEquals("foobar", System.getProperty("argLine.property2")); - Assert.assertEquals("foobar", System.getProperty("verbatim.section")); - } -} diff --git a/junit4-maven-plugin-tests/src/it/01-basic-test/verify.bsh b/junit4-maven-plugin-tests/src/it/01-basic-test/verify.bsh deleted file mode 100644 index f69c4e7f..00000000 --- a/junit4-maven-plugin-tests/src/it/01-basic-test/verify.bsh +++ /dev/null @@ -1,19 +0,0 @@ - -import java.io.*; -import java.util.*; -import java.util.regex.*; - -import com.carrotsearch.maven.plugins.junit4.*; - -la = new LogAssert(new File(basedir, "build.log")); - -// Tests successful. -la.assertLogContains("Tests summary: 1 suite, 2 tests"); - -// Listener enabled. -la.assertLogContains("| Test001InsideMaven.success"); - -// Assertions. -la.assertLogContains("-ea:com.carrotsearch.ant.tasks.junit4.tests.sub1..."); - -return true; diff --git a/junit4-maven-plugin-tests/src/it/02-config-inheritance/invoker.properties b/junit4-maven-plugin-tests/src/it/02-config-inheritance/invoker.properties deleted file mode 100644 index cd7f006e..00000000 --- a/junit4-maven-plugin-tests/src/it/02-config-inheritance/invoker.properties +++ /dev/null @@ -1 +0,0 @@ -invoker.goals=verify \ No newline at end of file diff --git a/junit4-maven-plugin-tests/src/it/02-config-inheritance/pom.xml b/junit4-maven-plugin-tests/src/it/02-config-inheritance/pom.xml deleted file mode 100644 index 941044ea..00000000 --- a/junit4-maven-plugin-tests/src/it/02-config-inheritance/pom.xml +++ /dev/null @@ -1,142 +0,0 @@ - - 4.0.0 - - com.carrotsearch.randomizedtesting - junit4-maven-plugin-tests - 0.0.1-SNAPSHOT - - jar - - - UTF-8 - - 1.6 - 1.6 - - - @project.version@ - - - - - com.carrotsearch.randomizedtesting - randomizedtesting-runner - ${rr.version} - test - - - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - true - - - - default-test - none - - - - - - - com.carrotsearch.randomizedtesting - junit4-maven-plugin - ${rr.version} - - - - 10 - pipe,ignore - true - warn - - - - - - - arg.common - - - - - - - unit-tests - test - - junit4 - - true - - - **/Test*.class - **/*Test.class - - - **/*$* - - - - - - - integration-tests - integration-test - - junit4 - - true - - - **/IT*.class - **/*IT.class - - - **/*$* - - - - - - - - - - - com.carrotsearch.randomizedtesting - junit4-maven-plugin - - - - unit-tests - - - arg.unit - - - - - - - integration-tests - - - arg.it - - - - - - - - diff --git a/junit4-maven-plugin-tests/src/it/02-config-inheritance/src/test/java/com/carrotsearch/examples/randomizedrunner/IntegrationIT.java b/junit4-maven-plugin-tests/src/it/02-config-inheritance/src/test/java/com/carrotsearch/examples/randomizedrunner/IntegrationIT.java deleted file mode 100644 index d9642882..00000000 --- a/junit4-maven-plugin-tests/src/it/02-config-inheritance/src/test/java/com/carrotsearch/examples/randomizedrunner/IntegrationIT.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import org.junit.Assert; -import org.junit.Test; - -public class IntegrationIT { - @Test - public void commonArg() { - Assert.assertEquals("arg.common", System.getProperty("arg.common")); - } - - @Test - public void itConfigArg() { - Assert.assertEquals("arg.it", System.getProperty("arg.it")); - } -} diff --git a/junit4-maven-plugin-tests/src/it/02-config-inheritance/src/test/java/com/carrotsearch/examples/randomizedrunner/UnitTest.java b/junit4-maven-plugin-tests/src/it/02-config-inheritance/src/test/java/com/carrotsearch/examples/randomizedrunner/UnitTest.java deleted file mode 100644 index 9ce5d6a4..00000000 --- a/junit4-maven-plugin-tests/src/it/02-config-inheritance/src/test/java/com/carrotsearch/examples/randomizedrunner/UnitTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.carrotsearch.examples.randomizedrunner; - -import org.junit.Assert; -import org.junit.Test; - -public class UnitTest { - @Test - public void commonArg() { - Assert.assertEquals("arg.common", System.getProperty("arg.common")); - } - - @Test - public void unitConfigArg() { - Assert.assertEquals("arg.unit", System.getProperty("arg.unit")); - } -} diff --git a/junit4-maven-plugin-tests/src/it/02-config-inheritance/verify.bsh b/junit4-maven-plugin-tests/src/it/02-config-inheritance/verify.bsh deleted file mode 100644 index ed51a189..00000000 --- a/junit4-maven-plugin-tests/src/it/02-config-inheritance/verify.bsh +++ /dev/null @@ -1,16 +0,0 @@ - -import java.io.*; -import java.util.*; -import java.util.regex.*; - -import com.carrotsearch.maven.plugins.junit4.*; - -la = new LogAssert(new File(basedir, "build.log")); - -// Tests successful. -la.assertLogContains("Tests summary: 1 suite, 2 tests"); - -// Build successful. -la.assertLogContains("BUILD SUCCESS"); - -return true; diff --git a/junit4-maven-plugin-tests/src/it/settings.xml b/junit4-maven-plugin-tests/src/it/settings.xml deleted file mode 100644 index c8f77f0b..00000000 --- a/junit4-maven-plugin-tests/src/it/settings.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - it-repo - - true - - - - local.central - @localRepositoryUrl@ - - true - - - true - - - - - - local.central - @localRepositoryUrl@ - - true - - - true - - - - - - diff --git a/junit4-maven-plugin-tests/src/test/java/com/carrotsearch/maven/plugins/junit4/LogAssert.java b/junit4-maven-plugin-tests/src/test/java/com/carrotsearch/maven/plugins/junit4/LogAssert.java deleted file mode 100644 index 157443a4..00000000 --- a/junit4-maven-plugin-tests/src/test/java/com/carrotsearch/maven/plugins/junit4/LogAssert.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.carrotsearch.maven.plugins.junit4; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.file.Files; - -import org.junit.Assert; - -/** - * Asserts on the content of integration tests' log file. - */ -public class LogAssert { - private String logFile; - - public LogAssert(File buildLog) throws IOException { - this.logFile = new String(Files.readAllBytes(buildLog.toPath()), Charset.defaultCharset()); - } - - public void assertLogContains(String text) { - Assert.assertTrue("Log file was expected to contain: '" - + text + "'", logFile.indexOf(text) >= 0); - } -} diff --git a/junit4-maven-plugin/pom.xml b/junit4-maven-plugin/pom.xml deleted file mode 100644 index 648d76cc..00000000 --- a/junit4-maven-plugin/pom.xml +++ /dev/null @@ -1,144 +0,0 @@ - - 4.0.0 - - - com.carrotsearch.randomizedtesting - randomizedtesting-parent - 2.7.9-SNAPSHOT - ../pom.xml - - - junit4-maven-plugin - - maven-plugin - - - - com.carrotsearch.randomizedtesting - junit4-ant - ${project.version} - - - - com.carrotsearch.randomizedtesting - randomizedtesting-runner - ${project.version} - true - - - - org.apache.maven - maven-plugin-api - ${minimum.maven.version} - - - - org.apache.maven - maven-core - jar - ${minimum.maven.version} - - - - org.apache.maven - maven-artifact - jar - ${minimum.maven.version} - - - - org.apache.maven - maven-compat - ${minimum.maven.version} - - - - org.apache.maven.plugin-tools - maven-plugin-annotations - 3.5 - provided - - - - org.apache.ant - ant - compile - - - - org.apache.ant - ant-junit - compile - - - - org.dom4j - dom4j - - - - org.apache.maven.shared - maven-common-artifact-filters - 3.0.0 - - - google-collections - com.google.collections - - - maven-project - org.apache.maven - - - - - - org.apache.maven.plugins - maven-antrun-plugin - ${version.maven-antrun-plugin} - jar - - - maven-project - org.apache.maven - - - - - - - - - de.thetaphi - forbiddenapis - - - - org.apache.maven.plugins - maven-plugin-plugin - - - java-annotations - - - - - mojo-descriptor - process-classes - - descriptor - - - - - generated-helpmojo - - helpmojo - - - - - - - diff --git a/junit4-maven-plugin/src/main/java/com/carrotsearch/maven/plugins/junit4/JUnit4Mojo.java b/junit4-maven-plugin/src/main/java/com/carrotsearch/maven/plugins/junit4/JUnit4Mojo.java deleted file mode 100644 index 05c8c803..00000000 --- a/junit4-maven-plugin/src/main/java/com/carrotsearch/maven/plugins/junit4/JUnit4Mojo.java +++ /dev/null @@ -1,891 +0,0 @@ -package com.carrotsearch.maven.plugins.junit4; - -import static com.google.common.base.MoreObjects.*; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.StringReader; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.maven.artifact.Artifact; -import org.apache.maven.artifact.resolver.ArtifactResolutionResult; -import org.apache.maven.artifact.resolver.ArtifactResolver; -import org.apache.maven.artifact.resolver.filter.ArtifactFilter; -import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter; -import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter; -import org.apache.maven.artifact.versioning.DefaultArtifactVersion; -import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; -import org.apache.maven.artifact.versioning.VersionRange; -import org.apache.maven.execution.MavenSession; -import org.apache.maven.plugin.AbstractMojo; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.plugin.antrun.AntrunXmlPlexusConfigurationWriter; -import org.apache.maven.plugins.annotations.Component; -import org.apache.maven.plugins.annotations.LifecyclePhase; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; -import org.apache.maven.plugins.annotations.ResolutionScope; -import org.apache.maven.project.MavenProject; -import org.apache.maven.repository.RepositorySystem; -import org.apache.maven.shared.artifact.filter.PatternIncludesArtifactFilter; -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.Project; -import org.apache.tools.ant.ProjectHelper; -import org.codehaus.plexus.configuration.PlexusConfiguration; -import org.dom4j.Document; -import org.dom4j.DocumentFactory; -import org.dom4j.Element; -import org.dom4j.io.OutputFormat; -import org.dom4j.io.SAXReader; -import org.dom4j.io.XMLWriter; - -import com.carrotsearch.ant.tasks.junit4.JUnit4; -import com.carrotsearch.ant.tasks.junit4.listeners.TextReport; -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.google.common.base.Strings; -import com.google.common.io.Closer; - -/** - * Run tests using a delegation to Randomized - * Testing's JUnit4 ANT task. - */ -@Mojo( - name = "junit4", - defaultPhase = LifecyclePhase.TEST, - threadSafe = true, - requiresProject = true, - requiresDependencyResolution = ResolutionScope.TEST) -public class JUnit4Mojo extends AbstractMojo { - /** An empty String[]. */ - private static final String[] EMPTY_STRING_ARRAY = new String [] {}; - - /** An empty Map. */ - private static final Map EMPTY_STRING_STRING_MAP = Collections.emptyMap(); - - /** Default target in the generated ANT file. */ - private static final String DEFAULT_TARGET = "__default__"; - - /** - * The Maven project object - */ - @Parameter( - property = "project", - readonly = true, - required = true) - private MavenProject project; - - /** - * Base directory to invoke slave VMs in. Also note isolateWorkingDirectories - * parameter. - */ - @Parameter( - property = "project.build.directory", - readonly = true, - required = true) - private File dir; - - /** - * The directory to store temporary files in. - */ - @Parameter( - property = "project.build.directory") - private File tempDir; - - /** - * The number of parallel f. Can be set to a constant "max" for the - * number of cores returned from {@link Runtime#availableProcessors()} or - * "auto" for sensible defaults depending on the number of cores. - * The default is a single subprocess. - * - *

Note that this setting forks physical JVM processes so it multiplies the - * requirements for heap memory, IO, etc. - */ - @Parameter(defaultValue = "1") - private String parallelism = JUnit4.DEFAULT_PARALLELISM; - - /** - * Property to set to "true" if there is a failure in a test. The use of this - * property is discouraged in Maven (builds should be declarative). - */ - @Parameter - private String failureProperty; - - /** - * Initial random seed used for shuffling test suites and other sources - * of pseudo-randomness. If not set, any random value is set. - * - *

The seed's format is compatible with {@link RandomizedRunner} so that - * seed can be fixed for suites and methods alike. Unless the global prefix of - * randomized testing properties is changed, the seed can be overridden using "tests.seed" - * property. - */ - @Parameter(property = "tests.seed", defaultValue = "") - private String seed; - - /** - * Predictably shuffle tests order after balancing. This will help in spreading - * lighter and heavier tests over a single slave's execution timeline while - * still keeping the same tests order depending on the seed. - */ - @Parameter(defaultValue = "true") - private boolean shuffleOnSlave = JUnit4.DEFAULT_SHUFFLE_ON_SLAVE; - - /** - * Prints the summary of all executed, ignored etc. tests at the end. - */ - @Parameter(defaultValue = "true") - private boolean printSummary = JUnit4.DEFAULT_PRINT_SUMMARY; - - /** - * Stop the build process if there were failures or errors during test execution. - */ - @Parameter(defaultValue = "true") - private boolean haltOnFailure = JUnit4.DEFAULT_HALT_ON_FAILURE; - - /** - * If set to true each forked JVM gets a separate working directory - * under whatever is set in dir. The directory naming for each JVM - * follows: "Jnum", where num is the forked JVM's number. - * Directories are created automatically and removed unless leaveTemporary - * is set to true. - */ - @Parameter(defaultValue = "true") - private boolean isolateWorkingDirectories = JUnit4.DEFAULT_ISOLATE_WORKING_DIRECTORIES; - - /** - * Sets the action performed when current work directory for a forked JVM is not empty - * and isolateWorkingDirectories is set to true. - */ - @Parameter(defaultValue = "fail") - private String onNonEmptyWorkDirectory = JUnit4.DEFAULT_NON_EMPTY_WORKDIR_ACTION.name(); - - /** - * If set to true, any sysout and syserr calls will be written to original - * output and error streams (and in effect will appear as "jvm output". By default - * sysout and syserrs are captured and proxied to the event stream to be synchronized - * with other test events but occasionally one may want to synchronize them with direct - * JVM output (to synchronize with compiler output or GC output for example). - */ - @Parameter(defaultValue = "false") - private boolean sysouts = JUnit4.DEFAULT_SYSOUTS; - - /** - * Specifies the ratio of suites moved to dynamic assignment list. A dynamic - * assignment list dispatches suites to the first idle slave JVM. Theoretically - * this is an optimal strategy, but it is usually better to have some static assignments - * to avoid communication costs. - * - *

A ratio of 0 means only static assignments are used. A ratio of 1 means - * only dynamic assignments are used. - * - *

The list of dynamic assignments is sorted by decreasing cost (always) and - * is inherently prone to race conditions in distributing suites. Should there - * be an error based on suite-dependency it will not be directly repeatable. In such - * case use the per-slave-jvm list of suites file dumped to disk for each slave JVM. - * (see leaveTemporary parameter). - */ - @Parameter(defaultValue = "0.25") - private float dynamicAssignmentRatio = JUnit4.DEFAULT_DYNAMIC_ASSIGNMENT_RATIO; - - /** - * Set the maximum memory to be used by all forked JVMs. The value as - * defined by -mx or -Xmx in the java - * command line options. - */ - @Parameter - private String maxMemory; - - /** - * Set to true to leave temporary files for diagnostics. - */ - @Parameter - private boolean leaveTemporary; - - /** - * Add an additional argument to any forked JVM. - */ - @Parameter - private String [] jvmArgs; - - /** - * Arbitrary JVM options to set on the command line. - */ - @Parameter(property = "argLine") - private String argLine; - - /** - * Adds a system property to any forked JVM. - */ - @Parameter - private Map systemProperties; - - /** - * Adds an environment variable to any forked JVM. - */ - @Parameter - private Map environmentVariables; - - /** - * The command used to invoke the Java Virtual Machine, default is 'java'. The - * command is resolved by java.lang.Runtime.exec(). - */ - @Parameter(defaultValue = "java") - private String jvm; - - /** - * The directory containing generated test classes of the project being - * tested. This will be included at the beginning of the test classpath. - */ - @Parameter(defaultValue = "${project.build.testOutputDirectory}") - private File testClassesDirectory; - - /** - * The directory containing generated classes of the project being - * tested. This will be included after testClassesDirectory. - */ - @Parameter(defaultValue = "${project.build.outputDirectory}") - private File classesDirectory; - - /** - * A list of <include> elements specifying the tests (by pattern) that should be included in testing. When not - * specified defaults to: - *

-   * <include>**/*Test.class</include>
-   * <include>**/Test*.class</include>
-   * 
- * Note that this may result in nested classes being included for tests. Use proper exclusion patterns. - */ - @Parameter - private List includes; - - /** - * A list of <exclude> elements specifying the tests (by pattern) that should be excluded in testing. When not - * specified defaults to: - *
-   * <exclude>**/*$*.class</exclude>
-   * 
- * This patterns excludes any nested classes that might otherwise be included. - */ - @Parameter - private List excludes; - - /** - * This parameter adds a listener emitting surefire-compatible XMLs if no other listeners - * are added. If there are any configured listeners, this parameter is omitted (you can - * add a maven-compatible listener manually). - */ - @Parameter(defaultValue = "${project.build.directory}/surefire-reports") - private File surefireReportsDirectory; - - /** - * Specifies the name of the JUnit artifact used for running tests. JUnit dependency - * must be in at least version 4.10. - */ - @Parameter( - property = "junitArtifactName", - defaultValue = "junit:junit") - private String junitArtifactName; - - /** - * What should be done on unexpected JVM output? JVM may write directly to the - * original descriptors, bypassing redirections of System.out and System.err. Typically, - * these messages will be important and should fail the build (permgen space exceeded, - * compiler errors, crash dumps). However, certain legitimate logs (gc activity, class loading - * logs) are also printed to these streams so sometimes the output can be ignored. - * - *

Allowed values (any comma-delimited combination of): ignore, pipe, warn, fail. - */ - @Parameter( - property = "jvmOutputAction", - defaultValue = "pipe,warn") - private String jvmOutputAction; - - /** - * Allows or disallow duplicate suite names in resource collections. By default this option - * is true because certain ANT-compatible report types (like XML reports) - * will have a problem with duplicate suite names (will overwrite files). - */ - @Parameter(defaultValue = "" + JUnit4.DEFAULT_UNIQUE_SUITE_NAME) - private boolean uniqueSuiteNames = JUnit4.DEFAULT_UNIQUE_SUITE_NAME; - - /** - * Raw listeners configuration. Same XML as for ANT. - */ - @Parameter - private PlexusConfiguration listeners; - - /** - * Raw runListeners configuration. Same XML as for ANT. - */ - @Parameter - private PlexusConfiguration runListeners; - - - /** - * Raw assertions configuration. Same XML as for ANT. - */ - @Parameter - private PlexusConfiguration assertions; - - /** - * Raw balancers configuration. Same XML as for ANT. - */ - @Parameter - private PlexusConfiguration balancers; - - /** - * Raw section to copy/paste into ANT-driver. - */ - @Parameter - private PlexusConfiguration verbatim; - - /** - * Sets the heartbeat used to detect inactive/ hung forked tests (JVMs) to the given - * number of seconds. The heartbeat detects - * no-event intervals and will report them to listeners. Notably, {@link TextReport} report will - * emit heartbeat information (to a file or console). - * - *

Setting the heartbeat to zero means no detection. - */ - @Parameter(defaultValue = "0") - private long heartbeat; - - /** - * Set this to "true" to skip running tests, but still compile them. Its use - * is NOT RECOMMENDED, but quite convenient on occasion. - */ - @Parameter( - property = "skipTests", - defaultValue = "false") - private boolean skipTests; - - /** - * Project packaging mode to skip POM-projects - */ - @Parameter( - defaultValue = "${project.packaging}", - readonly = true) - private String packaging; - - /** - * List of dependencies to exclude from the test classpath. Each dependency - * string must follow the format - * groupId:artifactId. For example: org.acme:project-a - * - *

This is modeled after surefire. An excluded dependency does not mean its - * transitive dependencies will also be excluded. - */ - @Parameter - private List classpathDependencyExcludes; - - /** - * A dependency scope to exclude from the test classpath. The scope can be one of the following scopes: - *

- *

    - *
  • compile - system, provided, compile - *
  • runtime - compile, runtime - *
  • test - system, provided, compile, runtime, test - *
- */ - @Parameter(defaultValue = "") - private String classpathDependencyScopeExclude; - - /** - * Additional elements to be appended to the classpath. - */ - @Parameter - private List additionalClasspathElements; - - /** - * Initializes custom prefix for all junit4 properties. This must be consistent - * across all junit4 invocations if done from the same classpath. Use only when REALLY needed. - */ - @Parameter() - private String prefix; - - /** - * Enables a debug stream from each forked JVM. This will create an additional file - * next to each events file. For debugging the framework only, not a general-purpose setting. - */ - @Parameter() - private Boolean debugStream; - - /** - * Set new environment for the forked process? - */ - @Parameter() - private Boolean newEnvironment; - - /** - * What to do when no tests were executed (all tests were ignored)? Possible values: - * ignore, fail, warn. - */ - @Parameter(defaultValue = "ignore") - private String ifNoTests; - - /** - * Sets the property prefix to which test statistics are saved. - */ - @Parameter() - private String statsPropertyPrefix; - - /** - * Map of plugin artifacts. - */ - @Parameter( - defaultValue = "${plugin.artifactMap}", - required = true, - readonly = true) - private Map pluginArtifactMap; - - /** - * Map of project artifacts. - */ - @Parameter( - defaultValue = "${project.artifactMap}", - required = true, - readonly = true) - private Map projectArtifactMap; - - /** - * The current build session instance. - */ - @Parameter( - property = "session", - required = true, - readonly = true) - private MavenSession session; - - /** - * Repository. - * - * @component - * @readonly - * @required - */ - @Component - private RepositorySystem repositorySystem; - - /** - * For retrieval of artifact's metadata. - */ - @SuppressWarnings("deprecation") - @Component - private org.apache.maven.artifact.metadata.ArtifactMetadataSource metadataSource; - - /** - * - */ - @Component - private ArtifactResolver resolver; - - - /** - * Run the mojo. - */ - @Override - public void execute() throws MojoExecutionException, MojoFailureException { - if ("pom".equals(packaging)) { - getLog().debug("Skipping execution for packaging \"" + packaging + "\""); - return; - } - - // Check directory existence first. - if (!dir.isDirectory() || - !tempDir.isDirectory()) { - getLog().warn("Location does not exist or is not a directory: " + dir.getAbsolutePath()); - skipTests = true; - } - - if (skipTests) { - return; - } - - validateParameters(); - - // Ant project setup. - final Project antProject = new Project(); - antProject.init(); - antProject.setBaseDir(dir); - antProject.addBuildListener(new MavenListenerAdapter(getLog())); - - // Generate JUnit4 ANT task model and generate a synthetic ANT file. - Document doc = DocumentFactory.getInstance().createDocument(); - try { - populateJUnitElement(createDocumentSkeleton(doc)); - File tempAntFile = createTemporaryAntFile(doc); - - ProjectHelper.configureProject(antProject, tempAntFile); - try { - antProject.executeTarget(DEFAULT_TARGET); - } finally { - if (!leaveTemporary) { - tempAntFile.delete(); - } - } - } catch (IOException e) { - throw new MojoExecutionException("An I/O error occurred: " + e.getMessage(), e); - } catch (BuildException e) { - throw new MojoExecutionException(e.getMessage(), e.getCause()); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - - /** - * Initial validation of input parameters and configuration. - */ - private void validateParameters() throws MojoExecutionException { - // Check for junit dependency on project level. - Artifact junitArtifact = projectArtifactMap.get(junitArtifactName); - - if (junitArtifact == null) { - throw new MojoExecutionException("Missing JUnit artifact in project dependencies: " - + junitArtifactName); - } - checkVersion("JUnit", "[4.10,)", junitArtifact); - - // Fill in complex defaults if not given. - if (includes == null || includes.isEmpty()) { - includes = Arrays.asList( - "**/Test*.class", "**/*Test.class"); - } - if (excludes == null || excludes.isEmpty()) { - excludes = Arrays.asList( - "**/*$*.class"); - } - } - - /** - * Ensure artifactName matches version versionSpec. - */ - private void checkVersion(String artifactName, String versionSpec, Artifact artifact) - throws MojoExecutionException { - VersionRange range; - try { - range = VersionRange.createFromVersionSpec(versionSpec); - if (!range.containsVersion(new DefaultArtifactVersion(artifact.getVersion()))) - { - throw new MojoExecutionException( - "JUnit4 plugin requires " + artifactName + " in version " + - versionSpec + " among project dependencies, you declared: " - + artifact.getVersion()); - } - } catch (InvalidVersionSpecificationException e) { - throw new RuntimeException(e); - } - } - - /** - * Populate junit4 task with attributes and values. - */ - private void populateJUnitElement(Element junit4) { - // Attributes. - if (dir != null) junit4.addAttribute("dir", dir.getAbsolutePath()); - if (tempDir != null) junit4.addAttribute("tempDir", tempDir.getAbsolutePath()); - if (parallelism != null) junit4.addAttribute("parallelism", parallelism); - if (failureProperty != null) junit4.addAttribute("failureProperty", failureProperty); - if (seed != null) junit4.addAttribute("seed", seed); - if (jvm != null) junit4.addAttribute("jvm", jvm); - if (maxMemory != null) junit4.addAttribute("maxMemory", maxMemory); - if (jvmOutputAction != null) junit4.addAttribute("jvmOutputAction", jvmOutputAction); - if (heartbeat != 0) junit4.addAttribute("heartbeat", Long.toString(heartbeat)); - if (prefix != null) junit4.addAttribute("prefix", prefix); - if (debugStream != null) junit4.addAttribute("debugStream", debugStream.toString()); - if (newEnvironment != null) junit4.addAttribute("newEnvironment", newEnvironment.toString()); - if (ifNoTests != null) junit4.addAttribute("ifNoTests", ifNoTests); - if (statsPropertyPrefix != null) junit4.addAttribute("statsPropertyPrefix", statsPropertyPrefix); - if (onNonEmptyWorkDirectory != null) junit4.addAttribute("onNonEmptyWorkDirectory", onNonEmptyWorkDirectory); - - junit4.addAttribute("shuffleOnSlave", Boolean.toString(shuffleOnSlave)); - junit4.addAttribute("printSummary", Boolean.toString(printSummary)); - junit4.addAttribute("isolateWorkingDirectories", Boolean.toString(isolateWorkingDirectories)); - junit4.addAttribute("haltOnFailure", Boolean.toString(haltOnFailure)); - junit4.addAttribute("leaveTemporary", Boolean.toString(leaveTemporary)); - junit4.addAttribute("dynamicAssignmentRatio", Float.toString(dynamicAssignmentRatio)); - junit4.addAttribute("sysouts", Boolean.toString(sysouts)); - junit4.addAttribute("uniqueSuiteNames", Boolean.toString(uniqueSuiteNames)); - - - // JVM args. - for (String jvmArg : firstNonNull(jvmArgs, EMPTY_STRING_ARRAY)) { - junit4.addElement("jvmarg").addAttribute("value", jvmArg); - } - - if (argLine != null) { - junit4.addElement("jvmarg").addAttribute("line", argLine); - } - - // System properties - for (Map.Entry e : - firstNonNull(systemProperties, EMPTY_STRING_STRING_MAP).entrySet()) { - Element sysproperty = junit4.addElement("sysproperty"); - sysproperty.addAttribute("key", Strings.nullToEmpty(e.getKey())); - sysproperty.addAttribute("value", Strings.nullToEmpty(e.getValue())); - } - - // Environment variables. - for (Map.Entry e : - firstNonNull(environmentVariables, EMPTY_STRING_STRING_MAP).entrySet()) { - Element sysproperty = junit4.addElement("env"); - sysproperty.addAttribute("key", Strings.nullToEmpty(e.getKey())); - sysproperty.addAttribute("value", Strings.nullToEmpty(e.getValue())); - } - - // Tests input. - setupTestInput(junit4); - - // Tests classpath - setupTestClasspath(junit4); - - // Copy over listeners configuration. - if (listeners != null) { - appendRawXml(listeners, junit4); - } else { - // Add a console listener and a surefire-like XML listener. - Element listenersElement = junit4.addElement("listeners"); - - Element surefireReport = listenersElement.addElement("report-ant-xml"); - surefireReport.addAttribute("dir", surefireReportsDirectory.getAbsolutePath()); - surefireReport.addAttribute("mavenExtensions", "true"); - - Element consoleReport = listenersElement.addElement("report-text"); - consoleReport.addAttribute("showThrowable", "true"); - consoleReport.addAttribute("showStackTraces", "true"); - consoleReport.addAttribute("showOutput", "never"); - - consoleReport.addAttribute("showStatusOk", "false"); - consoleReport.addAttribute("showStatusError", "true"); - consoleReport.addAttribute("showStatusFailure", "true"); - consoleReport.addAttribute("showStatusIgnored", "false"); - - consoleReport.addAttribute("showSuiteSummary", "true"); - } - - // Copy over runlisteners - appendRawXml(runListeners, junit4); - - // Copy over assertions - appendRawXml(assertions, junit4); - - // Copy over balancers - appendRawXml(balancers, junit4); - - // Copy over verbatim section. - if (verbatim != null) { - for (PlexusConfiguration c : verbatim.getChildren()) { - appendRawXml(c, junit4); - } - } - } - - /** - * Append raw XML configuration. - */ - private void appendRawXml(PlexusConfiguration config, Element elem) { - try { - if (config == null) { - return; - } - - StringWriter writer = new StringWriter(); - AntrunXmlPlexusConfigurationWriter xmlWriter = new AntrunXmlPlexusConfigurationWriter(); - xmlWriter.write(config, writer); - Element root = new SAXReader().read( - new StringReader(writer.toString())).getRootElement(); - root.detach(); - elem.add(root); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Create a temporary ANT file for executing JUnit4 ANT task. - */ - private File createTemporaryAntFile(Document doc) throws IOException { - Closer closer = Closer.create(); - try { - File antFile = File.createTempFile("junit4-ant-", ".xml", dir); - OutputStream os = closer.register(new FileOutputStream(antFile)); - XMLWriter xmlWriter = new XMLWriter(os, OutputFormat.createPrettyPrint()); - xmlWriter.write(doc); - return antFile; - } catch (Throwable t) { - throw closer.rethrow(t); - } finally { - closer.close(); - } - } - - /** - * Creates a skeleton of a single-target ANT build file with JUnit4 task inside. - */ - private Element createDocumentSkeleton(Document doc) { - Element project = doc.addElement("project"); - project.addAttribute("name", "junit4-maven-synthetic"); - project.addAttribute("default", DEFAULT_TARGET); - - project.addComment("Define JUnit4 task and data types."); - Element taskdef = project.addElement("taskdef"); - taskdef.addAttribute("resource", JUnit4.ANTLIB_RESOURCE_NAME); - addArtifactClassPath( - taskdef.addElement("classpath"), - pluginArtifactMap.get("com.carrotsearch.randomizedtesting:junit4-ant")); - addArtifactClassPath( - taskdef.addElement("classpath"), - projectArtifactMap.get("junit:junit")); - - project.addComment("Invoke JUnit4 task."); - Element target = project.addElement("target"); - target.addAttribute("name", DEFAULT_TARGET); - - Element junit4 = target.addElement("junit4"); - return junit4; - } - - /** - * Append classpath elements of the given artefact to classpath. - */ - private void addArtifactClassPath(Element cp, Artifact artifact) { - ArtifactResolutionResult result = resolveArtifact(artifact); - if (!result.isSuccess()) { - throw new RuntimeException("Could not resolve: " + artifact.toString()); - } - - for (Artifact a : result.getArtifacts()) { - cp.addElement("pathelement").addAttribute( - "location", a.getFile().getAbsolutePath()); - } - } - - /** - * Resolve a given artifact given exclusion list. (copied from surefire). - */ - @SuppressWarnings({"deprecation"}) - private ArtifactResolutionResult resolveArtifact(Artifact artifact, Artifact... filtered) { - final ArtifactFilter filter; - if (filtered.length > 0) { - List exclusions = new ArrayList<>(filtered.length); - for (Artifact filteredArtifact : filtered) { - exclusions.add(filteredArtifact.getGroupId() + ":" - + filteredArtifact.getArtifactId()); - } - filter = new ExcludesArtifactFilter(exclusions); - } else { - filter = null; - } - - Artifact originatingArtifact = repositorySystem.createArtifact("dummy", "dummy", "1.0", "jar"); - try { - return resolver.resolveTransitively( - Collections.singleton( artifact ), - originatingArtifact, - session.getLocalRepository(), - project.getPluginArtifactRepositories(), - metadataSource, filter); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Setup the classpath used for tests. - */ - private void setupTestClasspath(Element junit4) { - junit4.addComment("Runtime classpath."); - Element cp = junit4.addElement("classpath"); - - // Test classes. - cp.addComment("Test classes directory."); - cp.addElement("pathelement").addAttribute("location", testClassesDirectory.getAbsolutePath()); - - // Classes directory. - cp.addComment("Test classes directory."); - cp.addElement("pathelement").addAttribute("location", classesDirectory.getAbsolutePath()); - - // Project dependencies. - cp.addComment("Project dependencies."); - - Set classpathArtifacts = (Set) project.getArtifacts(); - - if (!Strings.isNullOrEmpty(classpathDependencyScopeExclude)) { - classpathArtifacts = filterArtifacts(cp, classpathArtifacts, - new ScopeArtifactFilter(classpathDependencyScopeExclude)); - } - - if (classpathDependencyExcludes != null && !classpathDependencyExcludes.isEmpty()) { - classpathArtifacts = filterArtifacts(cp, classpathArtifacts, - new PatternIncludesArtifactFilter(classpathDependencyExcludes)); - } - - for (Artifact artifact : classpathArtifacts) { - if (artifact.getArtifactHandler().isAddedToClasspath()) { - File file = artifact.getFile(); - if (file != null) { - cp.addComment("Dependency artifact: " + artifact.getId()); - cp.addElement("pathelement").addAttribute("location", - file.getAbsolutePath()); - } - } - } - - // Additional dependencies. - cp.addComment("Additional classpath elements."); - if (additionalClasspathElements != null && !additionalClasspathElements.isEmpty()) { - for (String classpathElement : additionalClasspathElements) { - if (!Strings.isNullOrEmpty(classpathElement)) { - cp.addElement("pathelement").addAttribute("location", classpathElement); - } - } - } - } - - /** - * Return a new set containing only the artifacts accepted by the given filter. - */ - private Set filterArtifacts(Element cp, Set artifacts, ArtifactFilter filter) { - Set filteredArtifacts = new LinkedHashSet<>(); - for (Artifact artifact : artifacts) { - if (!filter.include(artifact)) { - filteredArtifacts.add(artifact); - } else { - cp.addComment("Filtered out artifact: " + artifact.getId() + ", location: " - + artifact.getFile()); - } - } - return filteredArtifacts; - } - - /** - * Setup the input test suites (classes locations and patterns). - */ - private void setupTestInput(Element junit4) { - Element patternSet = DocumentFactory.getInstance().createElement("patternset"); - for (String includePattern : includes) { - patternSet.addElement("include").addAttribute("name", includePattern); - } - for (String excludePattern : excludes) { - patternSet.addElement("exclude").addAttribute("name", excludePattern); - } - - if (testClassesDirectory != null) { - junit4.addComment("Test classes search paths and patterns."); - Element fs = junit4.addElement("fileset"); - fs.addAttribute("dir", testClassesDirectory.getAbsolutePath()); - fs.addAttribute("erroronmissingdir", "false"); - fs.add(patternSet.createCopy()); - } - } -} diff --git a/junit4-maven-plugin/src/main/java/com/carrotsearch/maven/plugins/junit4/MavenListenerAdapter.java b/junit4-maven-plugin/src/main/java/com/carrotsearch/maven/plugins/junit4/MavenListenerAdapter.java deleted file mode 100644 index 776f44fb..00000000 --- a/junit4-maven-plugin/src/main/java/com/carrotsearch/maven/plugins/junit4/MavenListenerAdapter.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.carrotsearch.maven.plugins.junit4; - -import org.apache.maven.plugin.logging.Log; -import org.apache.tools.ant.*; - -/** - * An adapter to maven logging system from ANT {@link BuildListener}. - */ -final class MavenListenerAdapter implements BuildListener { - private final Log log; - - public MavenListenerAdapter(Log log) { - this.log = log; - } - - @Override - public void messageLogged(BuildEvent event) { - final Throwable exception = event.getException(); - final String message = event.getMessage(); - switch (event.getPriority()) { - case Project.MSG_DEBUG: - case Project.MSG_VERBOSE: - if (exception != null) { - log.debug(message, exception); - } else { - log.debug(message); - } - break; - - case Project.MSG_INFO: - if (exception != null) { - log.info(message, exception); - } else { - log.info(message); - } - break; - - case Project.MSG_WARN: - if (exception != null) { - log.warn(message, exception); - } else { - log.warn(message); - } - break; - - case Project.MSG_ERR: - if (exception != null) { - log.error(message, exception); - } else { - log.error(message); - } - break; - } - } - - @Override - public void buildFinished(BuildEvent event) {} - - @Override - public void buildStarted(BuildEvent event) {} - - @Override - public void targetFinished(BuildEvent event) {} - - @Override - public void targetStarted(BuildEvent event) {} - - @Override - public void taskFinished(BuildEvent event) {} - - @Override - public void taskStarted(BuildEvent event) {} -} diff --git a/junit4-maven-plugin/src/site/site.xml b/junit4-maven-plugin/src/site/site.xml deleted file mode 100644 index 6c9a4225..00000000 --- a/junit4-maven-plugin/src/site/site.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - diff --git a/pom.xml b/pom.xml deleted file mode 100644 index cd128d90..00000000 --- a/pom.xml +++ /dev/null @@ -1,692 +0,0 @@ - - - - - 4.0.0 - - - ${minimum.maven.version} - - - com.carrotsearch.randomizedtesting - randomizedtesting-parent - 2.7.9-SNAPSHOT - pom - - RandomizedTesting Parent POM - https://github.com/randomizedtesting/randomizedtesting - JUnit test runner and plugins for running JUnit tests with pseudo-randomness. - 2011 - - - Carrot Search s.c. - http://carrotsearch.com - - - - - Carrot Search s.c. - info@carrotsearch.com - Carrot Search s.c. - http://www.carrotsearch.com - - - - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - - - site - scm:git:git@github.com:randomizedtesting/randomizedtesting.git - - - - - scm:git:git@github.com:randomizedtesting/randomizedtesting.git - scm:git:git@github.com:randomizedtesting/randomizedtesting.git - git@github.com:randomizedtesting/randomizedtesting.git - - - - 3.2.5 - - UTF-8 - UTF-8 - - 1.8 - 1.8 - - - - 4.13.1 - 1.9.15 - 2.2.0 - - 1.8 - 3.0.0-M1 - 3.0.0 - 3.0.0 - 3.0.0-M1 - 2.5 - - - - randomized-runner - junit4-ant - junit4-maven-plugin - junit4-maven-plugin-tests - examples/maven - examples/ant - examples/security-manager - - - - - - org.apache.ant - ant - ${version.ant} - - - - org.apache.ant - ant-junit - ${version.ant} - - - - org.dom4j - dom4j - 2.1.3 - - - - com.google.guava - guava - 25.0-jre - - - jsr305 - com.google.code.findbugs - - - com.google.errorprone - error_prone_annotations - - - com.google.j2objc - j2objc-annotations - - - org.codehaus.mojo - animal-sniffer-annotations - - - - - - org.ow2.asm - asm - 8.0.1 - - - - com.carrotsearch.thirdparty - simple-xml-safe - 2.7.1 - - - - junit - junit - ${version.junit} - - - - org.assertj - assertj-core - ${version.assertj} - test - - - - - - - - org.apache.maven.plugins - maven-site-plugin - - - attach-descriptor - - attach-descriptor - - - - - - - - - - org.apache.maven.plugins - maven-site-plugin - 3.5.1 - - - - org.apache.maven.plugins - maven-clean-plugin - ${version.maven-clean-plugin} - - false - true - - - ${project.build.directory} - - eclipse/** - idea/** - - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.8.2 - - - - org.apache.maven.plugins - maven-plugin-plugin - 3.5 - - - - org.apache.maven.plugins - maven-source-plugin - 3.0.1 - - - - org.apache.maven.plugins - maven-assembly-plugin - 2.6 - - - - org.apache.maven.plugins - maven-jar-plugin - 3.0.2 - - - - org.apache.maven.plugins - maven-install-plugin - 2.5.2 - - - - org.apache.maven.plugins - maven-resources-plugin - 3.0.1 - - - - org.apache.maven.plugins - maven-enforcer-plugin - ${version.maven-enforcer-plugin} - - - - org.apache.maven.plugins - maven-dependency-plugin - 2.10 - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.5.1 - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.6 - - - - org.apache.maven.plugins - maven-surefire-plugin - ${version.maven-surefire-plugin} - - - - org.apache.maven.plugins - maven-antrun-plugin - ${version.maven-antrun-plugin} - - - - org.apache.ant - ant - ${version.ant} - - - org.apache.ant - ant-junit - ${version.ant} - - - - - - org.apache.felix - maven-bundle-plugin - 3.2.0 - - - - org.apache.maven.plugins - maven-project-info-reports-plugin - 2.9 - - - - org.apache.maven.plugins - maven-javadoc-plugin - ${version.maven-javadoc-plugin} - - - - org.apache.maven.plugins - maven-invoker-plugin - 2.0.0 - - - - de.thetaphi - forbiddenapis - ${version.forbiddenapis} - - - - check-forbidden-apis - verify - - check - - - 1.8 - false - false - true - - - **.SuppressForbidden - - - jdk-unsafe - jdk-deprecated - jdk-system-out - jdk-non-portable - - - - - - - - - - - - - - - quick - - true - true - - - - - profile.ide.eclipse-m2e - - - - m2e.version - - - - - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - org.apache.felix - maven-bundle-plugin - [1.0.0,) - - manifest - - - - - - - - - - de.thetaphi - forbiddenapis - [1.0.0,) - - testCheck - check - - - - - - - - - - org.apache.maven.plugins - maven-plugin-plugin - [3.4,) - - descriptor - helpmojo - - - - - - - - - - - - - org.apache.maven.plugins - maven-site-plugin - - true - UTF-8 - UTF-8 - - - - - org.apache.maven.plugins - maven-scm-publish-plugin - 1.1 - - gh-pages - - - - - - - - - eclipse - - compile antrun:run - - - - maven-antrun-plugin - ${version.maven-antrun-plugin} - - - default-cli - none - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - run - - - - - - org.apache.ant - ant - ${version.ant} - - - - - - - - - - sonatype-oss-release - - - - sonatype-nexus-snapshots - Sonatype Nexus Snapshots - https://oss.sonatype.org/content/repositories/snapshots - - - sonatype-nexus-staging - Sonatype Nexus Releases - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - - - sonatype-nexus-snapshots - Sonatype Nexus Snapshots - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - - - - - - - org.apache.maven.plugins - maven-gpg-plugin - - - **/*.gz - **/*.zip - - - - - - sign - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - ${project.build.sourceEncoding} - ${project.name} v${project.version} API Documentation - ${project.name} v${project.version} API Documentation - UTF-8 - false - - - - attach-javadocs - - jar - - - - - - - org.apache.maven.plugins - maven-source-plugin - - true - - - - attach-sources - - jar-no-fork - - - - - - - - - - doclint-java8-disable - - [1.8,) - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - none - - - - - - - - - - - org.apache.maven.plugins - maven-project-info-reports-plugin - - false - - - - - summary - index - dependencies - issue-tracking - scm - plugins - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - UTF-8 - true - true - - - - non-aggregate - - javadoc - - - - - - maven-plugin-plugin - - - - diff --git a/randomized-runner/pom.xml b/randomized-runner/pom.xml deleted file mode 100644 index 5309d2cc..00000000 --- a/randomized-runner/pom.xml +++ /dev/null @@ -1,76 +0,0 @@ - - 4.0.0 - - - com.carrotsearch.randomizedtesting - randomizedtesting-parent - 2.7.9-SNAPSHOT - ../pom.xml - - - randomizedtesting-runner - RandomizedTesting Randomized Runner - - - - junit - junit - jar - compile - - - - org.assertj - assertj-core - test - - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - ${version.maven-javadoc-plugin} - - - - RandomizedRunner and RandomizedTest - com.carrotsearch.randomizedtesting* - - - Annotations - com.carrotsearch.randomizedtesting.annotations - - - Listeners, Generators and Validators - com.carrotsearch.randomizedtesting.generators:com.carrotsearch.randomizedtesting.listeners:com.carrotsearch.randomizedtesting.validators - - - - - - - - - - de.thetaphi - forbiddenapis - - - - org.apache.felix - maven-bundle-plugin - - - JavaSE-1.8 - ${project.groupId}.${project.artifactId} - ${project.groupId}.*;version="${project.version}" - - - - - - diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/AnnotatedMethodProvider.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/AnnotatedMethodProvider.java deleted file mode 100644 index 43689522..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/AnnotatedMethodProvider.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.junit.Test; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -/** - * Base class for {@link TestMethodProvider}s based on annotations. - */ -public abstract class AnnotatedMethodProvider implements TestMethodProvider { - private final Class annotation; - - public AnnotatedMethodProvider(Class ann) { - this.annotation = ann; - } - - @Override - public Collection getTestMethods(Class suiteClass, ClassModel suiteClassModel) { - // Return all methods annotated with the given annotation. Rely on further validation - // to weed out static or otherwise invalid methods. - Map methods = suiteClassModel.getAnnotatedLeafMethods(annotation); - if (annotation.equals(Test.class)) { - // @Test doesn't have inherited attribute, yet behaves like one. Fix it here by returning most - // specific method with a parent marked @Test - List fixed = new ArrayList(); - for (ClassModel.MethodModel mm : methods.values()) { - // find the most specific method. - ClassModel.MethodModel override; - while ((override = mm.getDown()) != null) { - mm = override; - } - - fixed.add(mm.element); - } - return fixed; - } - return methods.keySet(); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/AssertingRandom.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/AssertingRandom.java deleted file mode 100644 index 513e80e5..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/AssertingRandom.java +++ /dev/null @@ -1,180 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.lang.ref.WeakReference; -import java.util.Random; - -/** - * A random with a delegate, preventing {@link Random#setSeed(long)} and locked - * to be used by a single thread. - */ -@SuppressWarnings("serial") -public final class AssertingRandom extends Random { - private final Random delegate; - private final WeakReference ownerRef; - private final String ownerName; - private final StackTraceElement[] allocationStack; - - /** - * Track out-of-context use of this {@link Random} instance. This introduces memory - * barriers and scheduling side-effects but there's no other way to do it in any other - * way and sharing randoms across threads or test cases is very bad and worth tracking. - */ - private volatile boolean valid = true; - - /** - * Enable paranoid mode when assertions are enabled. - */ - private final static boolean assertionsEnabled = AssertingRandom.class.desiredAssertionStatus(); - - /** - * Creates an instance to be used by owner thread and delegating - * to delegate until {@link #destroy()}ed. - */ - public AssertingRandom(Thread owner, Random delegate) { - // Must be here, the only Random constructor. Has side-effects on setSeed, see below. - super(0); - - this.delegate = delegate; - this.ownerRef = new WeakReference(owner); - this.ownerName = owner.toString(); - this.allocationStack = Thread.currentThread().getStackTrace(); - } - - @Override - protected int next(int bits) { - throw new RuntimeException("Shouldn't be reachable."); - } - - @Override - public boolean nextBoolean() { - checkValid(); - return delegate.nextBoolean(); - } - - @Override - public void nextBytes(byte[] bytes) { - checkValid(); - delegate.nextBytes(bytes); - } - - @Override - public double nextDouble() { - checkValid(); - return delegate.nextDouble(); - } - - @Override - public float nextFloat() { - checkValid(); - return delegate.nextFloat(); - } - - @Override - public double nextGaussian() { - checkValid(); - return delegate.nextGaussian(); - } - - @Override - public int nextInt() { - checkValid(); - return delegate.nextInt(); - } - - @Override - public int nextInt(int n) { - checkValid(); - return delegate.nextInt(n); - } - - @Override - public long nextLong() { - checkValid(); - return delegate.nextLong(); - } - - @Override - public void setSeed(long seed) { - // This is an interesting case of observing uninitialized object from an instance method - // (this method is called from the superclass constructor). - if (seed == 0 && delegate == null) { - return; - } - - throw noSetSeed(); - } - - @Override - public String toString() { - checkValid(); - return delegate.toString(); - } - - @Override - public boolean equals(Object obj) { - checkValid(); - return delegate.equals(obj); - } - - @Override - public int hashCode() { - checkValid(); - return delegate.hashCode(); - } - - /** - * This object will no longer be usable after this method is called. - */ - public void destroy() { - this.valid = false; - } - - /* */ - private final void checkValid() { - // Fastpath if assertions are disabled. - if (!isVerifying()) { - return; - } - - if (!valid) { - throw new IllegalStateException("This Random instance has been invalidated and " + - "is probably used out of its allowed context (test or suite)."); - } - - final Thread owner = ownerRef.get(); - if (owner == null || Thread.currentThread() != owner) { - Throwable allocationEx = new StackTraceHolder("Original allocation stack for this Random (" + - "allocated by " + ownerName + ")"); - allocationEx.setStackTrace(allocationStack); - throw new IllegalStateException( - "This Random was created for/by another thread (" + ownerName + ")." + - " Random instances must not be shared (acquire per-thread). Current thread: " + - Thread.currentThread().toString(), allocationEx); - } - } - - @Override - protected Object clone() throws CloneNotSupportedException { - checkValid(); - throw new CloneNotSupportedException("Don't clone test Randoms."); - } - - /** - * @return Return true if this class is verifying sharing and lifecycle assertions. - * @see "https://github.com/randomizedtesting/randomizedtesting/issues/234" - */ - public static boolean isVerifying() { - return assertionsEnabled; - } - - static RuntimeException noSetSeed() { - return new RuntimeException( - RandomizedRunner.class.getSimpleName() + - " prevents changing the seed of its random generators to assure repeatability" + - " of tests. If you need a mutable instance of Random, create a new (local) instance," + - " preferably with the initial seed aquired from this Random instance."); - } - - // Overriding this has side effects on the GC; let's not be paranoid. - /* protected void finalize() throws Throwable { super.finalize(); } */ -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ClassGlobFilter.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ClassGlobFilter.java deleted file mode 100644 index 62b003b4..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ClassGlobFilter.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.junit.runner.Description; - -/** - * A filter for {@link Description#getClassName()}. - */ -public class ClassGlobFilter extends GlobFilter { - public ClassGlobFilter(String globPattern) { - super(globPattern); - } - - @Override - public boolean shouldRun(Description description) { - String className = description.getClassName(); - return className == null || globMatches(className); - } - - @Override - public String describe() { - return "Class matches: " + globPattern; - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ClassModel.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ClassModel.java deleted file mode 100644 index 45944685..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ClassModel.java +++ /dev/null @@ -1,294 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * Class model for a test suite. Builds relationship (overrides/ shadows) links - * for methods and fields. - */ -public final class ClassModel { - static final Comparator methodSorter = new Comparator() { - @Override - public int compare(Method o1, Method o2) { - return o1.toGenericString().compareTo( - o2.toGenericString()); - } - }; - - static final Comparator fieldSorter = new Comparator() { - @Override - public int compare(Field o1, Field o2) { - return o1.toGenericString().compareTo( - o2.toGenericString()); - } - }; - - private final LinkedHashMap methods; - private final LinkedHashMap fields; - - public static enum Scope { - PUBLIC, - PROTECTED, - PACKAGE, - PRIVATE - } - - abstract static class ClassElement> { - private final int modifiers; - private final Scope scope; - - public final T element; - private E up; - private E down; - - public ClassElement(T element) { - this.element = element; - this.modifiers = element.getModifiers(); - this.scope = getAccessScope(modifiers); - } - - private static Scope getAccessScope(int modifiers) { - if (Modifier.isPublic(modifiers)) return Scope.PUBLIC; - if (Modifier.isProtected(modifiers)) return Scope.PROTECTED; - if (Modifier.isPrivate(modifiers)) return Scope.PRIVATE; - return Scope.PACKAGE; - } - - void setDown(E down) { assert this.down == null; this.down = down; } - void setUp(E up) { assert this.up == null; this.up = up; } - - public E getDown() { return down; } - public E getUp() { return up; } - public Scope getAccessScope() { return scope; } - - abstract boolean overridesOrShadows(ClassElement sub); - } - - private static abstract class ModelBuilder> { - final LinkedHashMap build(Class clazz) { - final LinkedHashMap elements = new LinkedHashMap(); - final Map> tops = new HashMap>(); - for (Class c = clazz; c != Object.class; c = c.getSuperclass()) { - for (T_MEMBER m : members(c)) { - final T_MODEL model = model(m); - if (elements.put(m, model) != null) { - throw new RuntimeException("Class element should not have duplicates in superclasses: " + m); - } - - // Link up overridden/ shadowed methods to any current tops. - if (model.getAccessScope() != Scope.PRIVATE) { - List list = tops.get(model); - if (list == null) { - tops.put(model, list = new ArrayList()); - } - for (Iterator i = list.iterator(); i.hasNext();) { - T_MODEL sub = i.next(); - if (model.overridesOrShadows(sub)) { - i.remove(); - sub.setUp(model); - model.setDown(sub); - } - } - list.add(model); - } - } - } - return elements; - } - - protected abstract T_MEMBER[] members(Class c); - protected abstract T_MODEL model(T_MEMBER t); - } - - public static final class MethodModel extends ClassElement { - public MethodModel(Method m) { - super(m); - } - - @Override - public String toString() { - return element.getDeclaringClass().getSimpleName() + "." + element.getName(); - } - - @Override - boolean overridesOrShadows(ClassElement sub) { - final Method m1 = element; - final Method m2 = sub.element; - - if (!m1.getName().equals(m2.getName())) { - return false; - } - - if (!Arrays.equals(m1.getParameterTypes(), m2.getParameterTypes())) { - return false; - } - - final Package package1 = m1.getDeclaringClass().getPackage(); - final Package package2 = m2.getDeclaringClass().getPackage(); - if (getAccessScope() == Scope.PACKAGE) { - return package1.equals(package2); - } else { - return true; - } - } - - @Override - public int hashCode() { - int hashCode = element.getName().hashCode(); - for (Class c : element.getParameterTypes()) { - hashCode += 31 * c.hashCode(); - } - return hashCode; - } - - @Override - public boolean equals(Object obj) { - MethodModel other = (MethodModel) obj; - return element.getName().equals(other.element.getName()) && - Arrays.equals(element.getParameterTypes(), - other.element.getParameterTypes()); - } - } - - public static final class FieldModel extends ClassElement { - public FieldModel(Field f) { - super(f); - } - - @Override - public String toString() { - return element.getDeclaringClass().getSimpleName() + "." + element.getName(); - } - - @Override - boolean overridesOrShadows(ClassElement sub) { - final Field f1 = element; - final Field f2 = sub.element; - - if (!f1.getName().equals(f2.getName())) { - return false; - } - - final Package package1 = f1.getDeclaringClass().getPackage(); - final Package package2 = f1.getDeclaringClass().getPackage(); - if (getAccessScope() == Scope.PACKAGE) { - return package1.equals(package2); - } else { - return true; - } - } - - @Override - public int hashCode() { - return element.getName().hashCode(); - } - - @Override - public boolean equals(Object obj) { - FieldModel other = (FieldModel) obj; - return element.getName().equals(other.element.getName()); - } - } - - public ClassModel(Class clazz) { - methods = methodsModel(clazz); - fields = fieldsModel(clazz); - } - - private static LinkedHashMap methodsModel(Class clazz) { - return new ModelBuilder() { - @Override - protected Method [] members(Class c) { - Method[] declaredMethods = c.getDeclaredMethods(); - Arrays.sort(declaredMethods, methodSorter); - return declaredMethods; - } - - @Override - protected MethodModel model(Method t) { - return new MethodModel(t); - } - }.build(clazz); - } - - private static LinkedHashMap fieldsModel(Class clazz) { - return new ModelBuilder() { - @Override - protected Field [] members(Class c) { - Field[] declaredFields = c.getDeclaredFields(); - Arrays.sort(declaredFields, fieldSorter); - return declaredFields; - } - - @Override - protected FieldModel model(Field t) { - return new FieldModel(t); - } - }.build(clazz); - } - - public Map getMethods() { - return Collections.unmodifiableMap(methods); - } - - public Map getFields() { - return Collections.unmodifiableMap(fields); - } - - public Map getAnnotatedLeafMethods(final Class annotation) { - LinkedHashMap result = new LinkedHashMap(); -outer: - for (Map.Entry e : getMethods().entrySet()) { - MethodModel mm = e.getValue(); - - if (mm.element.isAnnotationPresent(annotation)) { - for (MethodModel next = mm.getDown(); next != null; next = next.getDown()) { - if (next.element.isAnnotationPresent(annotation)) { - // At least one override has the annotation on it, so skip any super methods - // because it'd double the test. - continue outer; - } - } - - result.put(e.getKey(), mm); - } - } - return Collections.unmodifiableMap(result); - } - - public T getAnnotation(Method method, Class annClass, boolean inherited) { - MethodModel methodModel = methods.get(method); - if (methodModel == null) { - throw new IllegalArgumentException("No model for method: " + methodModel); - } - - if (inherited) { - for (; methodModel != null; methodModel = methodModel.getUp()) { - T annValue = methodModel.element.getAnnotation(annClass); - if (annValue != null) { - return annValue; - } - } - return null; - } else { - return method.getAnnotation(annClass); - } - } - - public boolean isAnnotationPresent(Method method, Class annClass, boolean inherited) { - return getAnnotation(method, annClass, inherited) != null; - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Classes.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Classes.java deleted file mode 100644 index dbc95df5..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Classes.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -final class Classes { - private Classes() {} - - public static String simpleName(Class c) { - String fullName = c.getName(); - int lastDot = fullName.lastIndexOf("."); - if (lastDot < 0) { - return fullName; - } else { - return fullName.substring(lastDot + 1); - } - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/CloseableResourceInfo.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/CloseableResourceInfo.java deleted file mode 100644 index 6236f782..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/CloseableResourceInfo.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.io.Closeable; - -/** - * Allocation information (Thread, allocation stack) for tracking disposable - * resources. - */ -final class CloseableResourceInfo { - private final Closeable resource; - private final LifecycleScope scope; - private final StackTraceElement[] allocationStack; - private final String threadName; - - public CloseableResourceInfo(Closeable resource, LifecycleScope scope, Thread t, StackTraceElement[] allocationStack) { - this.resource = resource; - this.threadName = Threads.threadName(t); - this.allocationStack = allocationStack; - this.scope = scope; - } - - public Closeable getResource() { - return resource; - } - - public StackTraceElement[] getAllocationStack() { - return allocationStack; - } - - public LifecycleScope getScope() { - return scope; - } - - /** - * Return the allocating thread's name at the time of creating this resource info. - */ - public String getThreadName() { - return threadName; - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/FilterExpressionParser.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/FilterExpressionParser.java deleted file mode 100644 index 7fe83af5..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/FilterExpressionParser.java +++ /dev/null @@ -1,315 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Test group conditions filter parser. - */ -public final class FilterExpressionParser { - static final Node [] EMPTY = new Node [0]; - - @SuppressWarnings("serial") - final class SyntaxException extends RuntimeException { - final Node node; - - SyntaxException(Node node, String msg) { - super(msg); - this.node = node; - } - - @Override - public String getMessage() { - if (node != null && node.range != null) { - return super.getMessage() + " At: \"" + node.range + "\""; - } else { - return super.getMessage(); - } - } - } - - interface IContext { - boolean defaultValue(); - boolean hasGroup(String value); - } - - static class InputRange { - final String s; - final int start; - final int len; - - InputRange(String value, int start, int length) { - this.s = value; - this.start = start; - this.len = length; - } - - public String value() { - return s.substring(start, start + len); - } - - public String toString() { - return s.substring(0, start) + - ">" + value() + - "<" + s.substring(start + len); - } - } - - public abstract class Node { - int lbp; - Node [] args = EMPTY; - public InputRange range; - - Node nud() { - throw new SyntaxException(this, "Syntax error."); - } - - Node led(Node left) { - throw new SyntaxException(this, "Not an operator."); - } - - @Override - public String toString() { - return getClass().getSimpleName().replace("Node", ""); - } - - public final String toExpression() { - return toExpression(new StringBuilder()).toString(); - } - - protected StringBuilder toExpression(StringBuilder b) { - throw new UnsupportedOperationException("Not an expression node: " + toString()); - } - - public boolean evaluate(IContext context) { - throw new UnsupportedOperationException("Not an evaluation node: " + toString()); - } - } - - class EosNode extends Node { - public EosNode() { - this.lbp = -1; - } - } - - class DefaultNode extends Node { - @Override - Node nud() { - return this; - } - - @Override - protected StringBuilder toExpression(StringBuilder b) { - b.append("default"); - return b; - } - - @Override - public boolean evaluate(IContext context) { - return context.defaultValue(); - } - } - - abstract class InfixNode extends Node { - @Override - Node led(Node left) { - if (!nodes.hasNext()) { - throw new SyntaxException(this, "Missing argument for " - + toString().toUpperCase(Locale.ROOT) + "."); - } - - args = new Node [] {left, expression(lbp)}; - return this; - } - } - - class AndNode extends InfixNode { - public AndNode() { - this.lbp = 30; - } - - @Override - protected StringBuilder toExpression(StringBuilder b) { - assert args.length == 2; - b.append("("); - b.append(super.args[0].toExpression()); - b.append(" AND "); - b.append(super.args[1].toExpression()); - b.append(")"); - return b; - } - - @Override - public boolean evaluate(IContext context) { - assert args.length == 2; - return super.args[0].evaluate(context) && - super.args[1].evaluate(context); - } - } - - class OrNode extends InfixNode { - public OrNode() { - this.lbp = 20; - } - - @Override - protected StringBuilder toExpression(StringBuilder b) { - assert args.length == 2; - b.append("("); - b.append(super.args[0].toExpression()); - b.append(" OR "); - b.append(super.args[1].toExpression()); - b.append(")"); - return b; - } - - @Override - public boolean evaluate(IContext context) { - assert args.length == 2; - return super.args[0].evaluate(context) || - super.args[1].evaluate(context); - } - } - - class NotNode extends Node { - public NotNode() { - this.lbp = 40; - } - - @Override - Node nud() { - args = new Node[] { expression(lbp) }; - return this; - } - - @Override - protected StringBuilder toExpression(StringBuilder b) { - assert args.length == 1; - b.append("(NOT "); - b.append(super.args[0].toExpression()); - b.append(")"); - return b; - } - - @Override - public boolean evaluate(IContext context) { - assert args.length == 1; - return !super.args[0].evaluate(context); - } - } - - class OpeningBracketNode extends Node { - @Override - Node nud() { - Node expr = expression(0); - - if (current.getClass() != ClosingBracketNode.class) { - throw new SyntaxException(current, "Expected closing bracket."); - } - current = nodes.next(); - - return expr; - } - } - - class ClosingBracketNode extends Node { - @Override - Node led(Node left) { - throw new SyntaxException(this, "Unbalanced parenthesis."); - } - } - - class TestGroupNode extends Node { - @Override - Node nud() { - return this; - } - - @Override - protected StringBuilder toExpression(StringBuilder b) { - b.append(range.value()); - return b; - } - - @Override - public boolean evaluate(IContext context) { - return context.hasGroup(range.value()); - } - } - - private Iterator nodes; - private Node current; - - Node expression(int rbp) { - Node n = current; - current = nodes.next(); - Node left = n.nud(); - while (rbp < current.lbp) { - n = current; - current = nodes.next(); - left = n.led(left); - } - return left; - } - - /** - * Pratt's parser. - */ - public Node parse(String rule) { - nodes = tokenize(rule); - current = nodes.next(); - if (current instanceof EosNode) { - return new DefaultNode(); - } else { - return expression(-1); - } - } - - /** - * Very simple regexp based tokenizer. We don't need to be fancy or super-fast. - */ - private Iterator tokenize(String rule) { - Matcher m = Pattern.compile( - "(?:\\s*)(([^\\s\\(\\)]+)|([\\(\\)]))").matcher(rule); - List tokens = new ArrayList(); - while (m.find()) { - final int s = m.start(1); - final int len = m.end(1) - s; - final String value = m.group(1); - - final Node t; - if (value.equalsIgnoreCase("DEFAULT")) { - t = new DefaultNode(); - } else if (value.equals("(")) { - t = new OpeningBracketNode(); - } else if (value.equals(")")) { - t = new ClosingBracketNode(); - } else if (value.equalsIgnoreCase("and")) { - t = new AndNode(); - } else if (value.equalsIgnoreCase("or")) { - t = new OrNode(); - } else if (value.equalsIgnoreCase("not")) { - t = new NotNode(); - } else if (value.startsWith("@")) { - t = new TestGroupNode(); - } else { - throw new SyntaxException(null, String.format(Locale.ROOT, - "Unrecognized token '%s'. At: \"%s\"", - value == null ? "" : value, - new InputRange(rule, s, len))); - } - - t.range = new InputRange(rule, s, len); - tokens.add(t); - } - - Node eos = new EosNode(); - eos.range = new InputRange(rule, rule.length(), 0); - tokens.add(eos); - return tokens.iterator(); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/GlobFilter.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/GlobFilter.java deleted file mode 100644 index 28d63ba7..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/GlobFilter.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.regex.Pattern; - -import org.junit.runner.Description; -import org.junit.runner.manipulation.Filter; - -/** - * A filter that matches something using globbing (*) pattern. - */ -public abstract class GlobFilter extends Filter { - protected final String globPattern; - private final Pattern pattern; - - public GlobFilter(String glob) { - this.globPattern = glob; - this.pattern = globToPattern(glob); - } - - /** - * Check if a given string matches the glob. - */ - public final boolean globMatches(String string) { - boolean result = pattern.matcher(string).matches(); - return result; - } - - /** - * Simplified conversion to a regexp. - */ - private Pattern globToPattern(String glob) { - StringBuilder pattern = new StringBuilder("^"); - for (char c : glob.toCharArray()) { - switch (c) { - case '*': - pattern.append(".*"); - break; - case '?': - pattern.append('.'); - break; - case '.': - case '$': - case '-': - case '{': - case '}': - case '[': - case ']': - case '(': - case ')': - pattern.append("\\"); - pattern.append(c); - break; - case '\\': - pattern.append("\\\\"); - break; - default: - pattern.append(c); - } - } - pattern.append('$'); - return Pattern.compile(pattern.toString()); - } - - @Override - public abstract boolean shouldRun(Description description); - - @Override - public abstract String describe(); -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/GroupEvaluator.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/GroupEvaluator.java deleted file mode 100644 index c7c0dc64..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/GroupEvaluator.java +++ /dev/null @@ -1,178 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedElement; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; - -import com.carrotsearch.randomizedtesting.FilterExpressionParser.IContext; -import com.carrotsearch.randomizedtesting.FilterExpressionParser.Node; -import com.carrotsearch.randomizedtesting.RandomizedRunner.TestCandidate; -import com.carrotsearch.randomizedtesting.annotations.TestGroup; - -/** - * Evaluates enabled/ disabled state for a given test group. - */ -public final class GroupEvaluator { - private static class TestGroupInfo { - final TestGroup group; - final String name; - final String sysProperty; - final boolean enabled; - - TestGroupInfo(Class annType) { - group = annType.getAnnotation(TestGroup.class); - name = TestGroup.Utilities.getGroupName(annType); - sysProperty = TestGroup.Utilities.getSysProperty(annType); - - boolean enabled; - try { - enabled = RandomizedTest.systemPropertyAsBoolean(sysProperty, group.enabled()); - } catch (IllegalArgumentException e) { - // Ignore malformed system property, disable the group if malformed though. - enabled = false; - } - this.enabled = enabled; - } - } - - private final HashMap, TestGroupInfo> testGroups; - private final Node filter; - private String filterExpression; - - GroupEvaluator(List testCandidates) { - testGroups = collectGroups(testCandidates); - - filterExpression = System.getProperty(SysGlobals.SYSPROP_TESTFILTER()); - if (filterExpression != null && filterExpression.trim().isEmpty()) { - filterExpression = null; - } - - filter = filterExpression != null ? new FilterExpressionParser().parse(filterExpression) : null; - } - - private HashMap, TestGroupInfo> collectGroups(List testCandidates) { - final HashMap, TestGroupInfo> groups = new HashMap, TestGroupInfo>(); - - // Collect all groups declared on methods and instance classes. - HashSet> clazzes = new HashSet>(); - HashSet annotations = new HashSet(); - for (TestCandidate c : testCandidates) { - final Class testClass = c.getTestClass(); - if (!clazzes.contains(testClass)) { - clazzes.add(testClass); - annotations.addAll(Arrays.asList(testClass.getAnnotations())); - } - annotations.addAll(Arrays.asList(c.method.getAnnotations())); - } - - // Get TestGroup annotated annotations. - for (Annotation ann : annotations) { - Class annType = ann.annotationType(); - if (!groups.containsKey(ann) && annType.isAnnotationPresent(TestGroup.class)) { - groups.put(annType, new TestGroupInfo(annType)); - } - } - - return groups; - } - - void appendGroupFilteringOptions(ReproduceErrorMessageBuilder builder) { - for (TestGroupInfo info : testGroups.values()) { - if (System.getProperty(info.sysProperty) != null) { - builder.appendOpt(info.sysProperty, System.getProperty(info.sysProperty)); - } - } - - if (hasFilteringExpression()) { - builder.appendOpt(SysGlobals.SYSPROP_TESTFILTER(), filterExpression); - } - } - - boolean hasFilteringExpression() { - return filterExpression != null; - } - - /** - * @return Returns a non-null string with the reason why the annotated element (class, test or test-class pair) - * should be ignored in the execution. This is an expert-level method, typically tests - * shouldn't be concerned with this. - */ - public String getIgnoreReason(AnnotatedElement... elements) { - final Map annotations = new HashMap(); - - for (AnnotatedElement element : elements) { - for (Annotation ann : element.getAnnotations()) { - Class annType = ann.annotationType(); - if (annType.isAnnotationPresent(TestGroup.class)) { - if (!testGroups.containsKey(annType)) { - testGroups.put(annType, new TestGroupInfo(annType)); - } - annotations.put(testGroups.get(annType).name, ann); - } - } - } - - String defaultState = null; - for (Annotation ann : annotations.values()) { - TestGroupInfo g = testGroups.get(ann.annotationType()); - if (!g.enabled) { - defaultState = "'" + g.name + "' test group is disabled (" + toString(ann) + ")"; - break; - } - } - - if (hasFilteringExpression()) { - final String defaultStateCopy = defaultState; - boolean enabled = filter.evaluate(new IContext() { - @Override - public boolean defaultValue() { - return defaultStateCopy == null; - } - - @Override - public boolean hasGroup(String value) { - if (value.startsWith("@")) value = value.substring(1); - for (Annotation ann : annotations.values()) { - if (value.equalsIgnoreCase(testGroups.get(ann.annotationType()).name)) { - return true; - } - } - return false; - } - }); - return enabled ? null : "Test filter condition: " + filterExpression; - } else { - return defaultState; - } - } - - private String toString(Annotation ann) { - if (ann == null) return "@null?"; - return ann.toString().replace( - ann.annotationType().getName(), - ann.annotationType().getSimpleName()); - } - - /** - * @return Returns the current state of the an annotation marked with - * {@link TestGroup}. Note that tests may be enabled or disabled using filtering - * expressions so an enabled group does not necessarily mean a test marked with - * this group will be executed. - */ - public boolean isGroupEnabled(Class testGroupAnnotation) { - if (!testGroups.containsKey(testGroupAnnotation)) { - if (!testGroupAnnotation.isAnnotationPresent(TestGroup.class)) { - throw new IllegalArgumentException("This annotation is not marked with @" - + TestGroup.class.getName() + ": " + testGroupAnnotation.getName()); - } - - testGroups.put(testGroupAnnotation, new TestGroupInfo(testGroupAnnotation)); - } - - return testGroups.get(testGroupAnnotation).enabled; - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/InstanceProvider.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/InstanceProvider.java deleted file mode 100644 index 28d8db6e..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/InstanceProvider.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -/** - * Provide a test instance. - */ -interface InstanceProvider { - Object newInstance() throws Throwable; -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/JUnit3MethodProvider.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/JUnit3MethodProvider.java deleted file mode 100644 index 8a627b56..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/JUnit3MethodProvider.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; - -import com.carrotsearch.randomizedtesting.ClassModel.MethodModel; - -/** - * Method provider selecting tests that follow a name pattern of test(.*). - */ -public class JUnit3MethodProvider implements TestMethodProvider { - @Override - public Collection getTestMethods(Class suiteClass, ClassModel suiteClassModel) { - Map methods = suiteClassModel.getMethods(); - ArrayList result = new ArrayList(); - for (MethodModel mm : methods.values()) { - if (mm.getDown() == null && mm.element.getName().startsWith("test")) { - result.add(mm.element); - } - } - return result; - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/JUnit4MethodProvider.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/JUnit4MethodProvider.java deleted file mode 100644 index 7d868a1b..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/JUnit4MethodProvider.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.junit.Test; - -/** - * Method provider selecting {@link Test} annotated public instance parameterless methods. - */ -public class JUnit4MethodProvider extends AnnotatedMethodProvider { - public JUnit4MethodProvider() { - super(Test.class); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/LifecycleScope.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/LifecycleScope.java deleted file mode 100644 index 65bd480a..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/LifecycleScope.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.junit.After; -import org.junit.AfterClass; - -/** - * Lifecycle stages for tracking resources. - */ -public enum LifecycleScope { - /** - * A single test case, including all {@link After} hooks. - */ - TEST, - - /** - * A single suite (class), including all {@link AfterClass} hooks. - */ - SUITE; -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/MethodGlobFilter.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/MethodGlobFilter.java deleted file mode 100644 index e928951c..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/MethodGlobFilter.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.junit.runner.Description; - -/** - * A filter for {@link Description#getMethodName()}. - */ -public class MethodGlobFilter extends GlobFilter { - public MethodGlobFilter(String globPattern) { - super(globPattern); - } - - @Override - public boolean shouldRun(Description description) { - String methodName = description.getMethodName(); - return methodName == null || globMatches(methodName); - } - - @Override - public String describe() { - return "Method matches: " + globPattern; - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/MixWithSuiteName.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/MixWithSuiteName.java deleted file mode 100644 index 8ee997c1..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/MixWithSuiteName.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import com.carrotsearch.randomizedtesting.annotations.SeedDecorators; - -/** - * A {@link SeedDecorator} to be used with {@link SeedDecorators} annotation - * to modify the master {@link Randomness} with a hash off the suite's class name. - */ -public class MixWithSuiteName implements SeedDecorator { - private long xorHash; - - @Override - public void initialize(Class suiteClass) { - this.xorHash = fmix64(suiteClass.getName().hashCode()); - } - - @Override - public long decorate(long seed) { - return seed ^ xorHash; - } - - /** final mix from murmur hash 3. */ - private long fmix64(long k) { - k ^= k >>> 33; - k *= 0xff51afd7ed558ccdL; - k ^= k >>> 33; - k *= 0xc4ceb9fe1a85ec53L; - k ^= k >>> 33; - return k; - } -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/MurmurHash3.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/MurmurHash3.java deleted file mode 100644 index 1f738236..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/MurmurHash3.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -/** - * Hash routines for primitive types. The implementation is based on the finalization step - * from Austin Appleby's MurmurHash3. - * - * @see "http://sites.google.com/site/murmurhash/" - */ -final class MurmurHash3 -{ - private MurmurHash3() - { - // no instances. - } - - /** - * Hashes a 4-byte sequence (Java int). - */ - public static int hash(int k) - { - k ^= k >>> 16; - k *= 0x85ebca6b; - k ^= k >>> 13; - k *= 0xc2b2ae35; - k ^= k >>> 16; - return k; - } - - /** - * Hashes an 8-byte sequence (Java long). - */ - public static long hash(long k) - { - k ^= k >>> 33; - k *= 0xff51afd7ed558ccdL; - k ^= k >>> 33; - k *= 0xc4ceb9fe1a85ec53L; - k ^= k >>> 33; - - return k; - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ObjectProcedure.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ObjectProcedure.java deleted file mode 100644 index e97efa79..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ObjectProcedure.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -interface ObjectProcedure -{ - public void apply(KType value); -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RandomSupplier.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RandomSupplier.java deleted file mode 100644 index 07e8709d..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RandomSupplier.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.Random; - -public interface RandomSupplier { - static RandomSupplier DEFAULT = new RandomSupplier() { - @Override - public Random get(long seed) { - return new Xoroshiro128PlusRandom(seed); - } - }; - - Random get(long seed); -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RandomizedContext.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RandomizedContext.java deleted file mode 100644 index c29a16d0..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RandomizedContext.java +++ /dev/null @@ -1,390 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.io.Closeable; -import java.lang.Thread.State; -import java.lang.reflect.Method; -import java.util.*; -import java.util.concurrent.Callable; - -import com.carrotsearch.randomizedtesting.annotations.Nightly; - -/** - * Context variables for an execution of a test suite (hooks and tests) running - * under a {@link RandomizedRunner}. - */ -public final class RandomizedContext { - /** Coordination at global level. */ - private static final Object _globalLock = new Object(); - /** Coordination at context level. */ - private final Object _contextLock = new Object(); - - /** - * Per thread assigned resources. - */ - private final static class PerThreadResources { - /** - * Generators of pseudo-randomness. This is a queue because we stack - * them during lifecycle phases (suite/ method level). - */ - final ArrayDeque randomnesses = new ArrayDeque(); - } - - /** - * All thread groups we're currently tracking contexts for. - */ - final static IdentityHashMap contexts - = new IdentityHashMap(); - - /** - * Per thread resources for each context. Allow GCing of threads. - */ - final WeakHashMap perThreadResources - = new WeakHashMap(); - - /** A thread group that shares this context. */ - private final ThreadGroup threadGroup; - - /** @see #getTargetClass() */ - private final Class suiteClass; - - /** The runner to which we're bound. */ - private final RandomizedRunner runner; - - /** The context and all of its resources are no longer usable. */ - private volatile boolean disposed; - - /** - * Disposable resources. - */ - private EnumMap> disposableResources - = new EnumMap>(LifecycleScope.class); - - private Method currentMethod; - - /** */ - private RandomizedContext(ThreadGroup tg, Class suiteClass, RandomizedRunner runner) { - this.threadGroup = tg; - this.suiteClass = suiteClass; - this.runner = runner; - } - - /** The class (suite) being tested. */ - public Class getTargetClass() { - checkDisposed(); - return suiteClass; - } - - /** Runner's seed. */ - long getRunnerSeed() { - return runner.runnerRandomness.getSeed(); - } - - /** - * Returns the runner's master seed, formatted. - */ - public String getRunnerSeedAsString() { - checkDisposed(); - return SeedUtils.formatSeed(getRunnerSeed()); - } - - /** Source of randomness for the context's thread. */ - public Randomness getRandomness() { - return getPerThread().randomnesses.peekFirst(); - } - - /** - * Return all {@link Randomness} on the stack for the current thread. The most - * recent (currently used) randomness comes last in this array. - */ - Randomness [] getRandomnesses() { - ArrayDeque randomnesses = getPerThread().randomnesses; - Randomness[] array = randomnesses.toArray(new Randomness [randomnesses.size()]); - for (int i = 0, j = array.length - 1; i < j; i++, j--) { - Randomness r = array[i]; - array[i] = array[j]; - array[j] = r; - } - return array; - } - - /** - * A shorthand for calling {@link #getRandomness()} and then {@link Randomness#getRandom()}. - */ - public Random getRandom() { - return getRandomness().getRandom(); - } - - /** - * Return true if {@link Nightly} test group is explicitly enabled. - * - * @see RandomizedContext#getGroupEvaluator() - * @see GroupEvaluator#isGroupEnabled(Class) - */ - public boolean isNightly() { - checkDisposed(); - return getGroupEvaluator().isGroupEnabled(Nightly.class); - } - - /** - * @return Returns the context for the calling thread or throws an - * {@link IllegalStateException} if the thread is out of scope. - * @throws IllegalStateException If context is not available. - */ - public static RandomizedContext current() { - return context(Thread.currentThread()); - } - - /** - * Access to the runner governing this context. - */ - public RandomizedRunner getRunner() { - return runner; - } - - /** - * Dispose the given resource at the end of a given lifecycle scope. If the {@link Closeable} - * throws an exception, the test case or suite will end in a failure. - * - * @return resource (for call chaining). - */ - public T closeAtEnd(T resource, LifecycleScope scope) { - synchronized (_contextLock) { - List resources = disposableResources.get(scope); - if (resources == null) { - disposableResources.put(scope, resources = new ArrayList()); - } - resources.add(new CloseableResourceInfo( - resource, scope, Thread.currentThread(), Thread.currentThread().getStackTrace())); - return resource; - } - } - - /** - * Provide access to {@link GroupEvaluator}. - */ - public GroupEvaluator getGroupEvaluator() { - return runner.groupEvaluator; - } - - /** - * Pushes the given randomness to the top of the stack, runs the {@link Callable} and disposes - * the randomness before the this method returns. - *

- * This utility method can be used to initialize resources in a reproducible way since all calls to utility methods - * like {@link com.carrotsearch.randomizedtesting.RandomizedTest#randomInt()} et.al. are forwarded to the current - * RandomContext which uses the provided randomness from the top of the stack. - *

- * - * @param randomness the randomness to push to the top of the stack - * @param callable the callable to execute - * @param the return type of the callable - * @return the result of the call to {@link java.util.concurrent.Callable#call()} - * @throws Exception if {@link java.util.concurrent.Callable#call()} throws an exception - */ - public T runWithPrivateRandomness(Randomness randomness, Callable callable) throws Exception { - push(randomness); - try { - return callable.call(); - } finally { - popAndDestroy(); - } - } - - /** - * Pushes the given randomness to the top of the stack, runs the {@link Callable} and disposes - * the randomness before the this method returns. - *

- * This utility method can be used to initialize resources in a reproducible way since all calls to utility methods - * like {@link com.carrotsearch.randomizedtesting.RandomizedTest#randomInt()} et.al. are forwarded to the current - * RandomContext which uses the provided randomness from the top of the stack. - *

- * - * @param seed The initial seed for the new, private randomness - * @param callable the callable to execute - * @param the return type of the callable - * @return the result of the call to {@link java.util.concurrent.Callable#call()} - * @throws Exception if {@link java.util.concurrent.Callable#call()} throws an exception - */ - public T runWithPrivateRandomness(long seed, Callable callable) throws Exception { - Randomness randomness = getRandomness(); - Randomness prv = new Randomness(seed, randomness.getRandomSupplier(), randomness.getDecorators()); - return runWithPrivateRandomness(prv, callable); - } - - /** - * Dispose of any resources registered in the given scope. - */ - void closeResources(ObjectProcedure consumer, LifecycleScope scope) { - List resources; - synchronized (_contextLock) { - resources = disposableResources.remove(scope); - } - - if (resources != null) { - for (CloseableResourceInfo info : resources) { - consumer.apply(info); - } - } - } - - static RandomizedContext context(Thread thread) { - ThreadGroup currentGroup = thread.getThreadGroup(); - if (currentGroup == null) { - throw new IllegalStateException("No context for a terminated thread: " + Threads.threadName(thread)); - } - - synchronized (_globalLock) { - RandomizedContext context; - while (true) { - context = contexts.get(currentGroup); - if (context == null && currentGroup.getParent() != null) { - currentGroup = currentGroup.getParent(); - } else { - break; - } - } - - if (context == null) { - throw new IllegalStateException("No context information for thread: " + - Threads.threadName(thread) + ". " + - "Is this thread running under a " + - RandomizedRunner.class + " runner context? Add @RunWith(" + RandomizedRunner.class + ".class)" + - " to your test class. Make sure your code accesses random contexts within " - + "@BeforeClass and @AfterClass boundary (for example, static test class initializers are " - + "not permitted to access random contexts)."); - } - - synchronized (context._contextLock) { - if (!context.perThreadResources.containsKey(thread)) { - PerThreadResources perThreadResources = new PerThreadResources(); - perThreadResources.randomnesses.push( - context.runner.runnerRandomness.clone(thread)); - context.perThreadResources.put(thread, perThreadResources); - } - } - - return context; - } - } - - /** - * Create a new context bound to a thread group. - */ - static RandomizedContext create(ThreadGroup tg, Class suiteClass, RandomizedRunner runner) { - assert Thread.currentThread().getThreadGroup() == tg; - synchronized (_globalLock) { - RandomizedContext ctx = new RandomizedContext(tg, suiteClass, runner); - contexts.put(tg, ctx); - ctx.perThreadResources.put(Thread.currentThread(), new PerThreadResources()); - return ctx; - } - } - - /** - * Dispose of the context. - */ - void dispose() { - synchronized (_globalLock) { - checkDisposed(); - disposed = true; - contexts.remove(threadGroup); - - // Clean up and invalidate any per-thread published randoms. - synchronized (_contextLock) { - for (PerThreadResources ref : perThreadResources.values()) { - if (ref != null) { - for (Randomness randomness : ref.randomnesses) { - randomness.destroy(); - } - } - } - } - } - } - - /** Push a new randomness on top of the stack. */ - void push(Randomness rnd) { - getPerThread().randomnesses.push(rnd); - } - - /** Pop a randomness off the stack and dispose it. */ - void popAndDestroy() { - getPerThread().randomnesses.pop().destroy(); - } - - /** Return per-thread resources associated with the current thread. */ - private PerThreadResources getPerThread() { - checkDisposed(); - synchronized (_contextLock) { - return perThreadResources.get(Thread.currentThread()); - } - } - - /** - * Throw an exception if disposed. - */ - private void checkDisposed() { - if (disposed) { - throw new IllegalStateException("Context disposed: " + - toString() + " for thread: " + Thread.currentThread()); - } - } - - /** - * Clone context information between the current thread and another thread. - * This is for internal use only to propagate context information when forking. - */ - static void cloneFor(Thread t) { - if (t.getState() != State.NEW) { - throw new IllegalStateException("The thread to share context with is not in NEW state: " + t); - } - - final ThreadGroup tGroup = t.getThreadGroup(); - if (tGroup == null) { - throw new IllegalStateException("No thread group for thread: " + t); - } - - Thread me = Thread.currentThread(); - if (me.getThreadGroup() != tGroup) { - throw new IllegalArgumentException("Both threads must share the thread group."); - } - - synchronized (_globalLock) { - RandomizedContext context = contexts.get(tGroup); - if (context == null) { - throw new IllegalStateException("No context information for thread: " + t); - } - - synchronized (context._contextLock) { - if (context.perThreadResources.containsKey(t)) { - throw new IllegalStateException("Context already initialized for thread: " + t); - } - - if (!context.perThreadResources.containsKey(me)) { - throw new IllegalStateException("Context not initialized for thread: " + me); - } - - PerThreadResources perThreadResources = new PerThreadResources(); - for (Randomness r : context.perThreadResources.get(me).randomnesses) { - perThreadResources.randomnesses.addLast(r.clone(t)); - } - context.perThreadResources.put(t, perThreadResources); - } - } - } - - void setTargetMethod(Method method) { - this.currentMethod = method; - } - - /** - * @return Return the currently executing test case method (the thread may still - * be within test rules and may never actually hit the method). This method may return - * null if called from the static context (no test case is being executed at - * the moment). - */ - public Method getTargetMethod() { - checkDisposed(); - return currentMethod; - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RandomizedRunner.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RandomizedRunner.java deleted file mode 100644 index a11d5891..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RandomizedRunner.java +++ /dev/null @@ -1,1997 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static com.carrotsearch.randomizedtesting.SysGlobals.*; - -import java.lang.Thread.UncaughtExceptionHandler; -import java.lang.annotation.Annotation; -import java.lang.annotation.Inherited; -import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.Assert; -import org.junit.AssumptionViolatedException; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runner.Result; -import org.junit.runner.Runner; -import org.junit.runner.manipulation.Filter; -import org.junit.runner.manipulation.Filterable; -import org.junit.runner.manipulation.NoTestsRemainException; -import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunListener; -import org.junit.runner.notification.RunNotifier; -import org.junit.runners.model.FrameworkField; -import org.junit.runners.model.FrameworkMethod; -import org.junit.runners.model.InitializationError; -import org.junit.runners.model.MultipleFailureException; -import org.junit.runners.model.Statement; -import org.junit.runners.model.TestClass; - -import com.carrotsearch.randomizedtesting.ClassModel.MethodModel; -import com.carrotsearch.randomizedtesting.annotations.Listeners; -import com.carrotsearch.randomizedtesting.annotations.Name; -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.Seed; -import com.carrotsearch.randomizedtesting.annotations.SeedDecorators; -import com.carrotsearch.randomizedtesting.annotations.Seeds; -import com.carrotsearch.randomizedtesting.annotations.TestCaseInstanceProvider; -import com.carrotsearch.randomizedtesting.annotations.TestCaseOrdering; -import com.carrotsearch.randomizedtesting.annotations.TestContextRandomSupplier; -import com.carrotsearch.randomizedtesting.annotations.TestMethodProviders; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakGroup; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies.Consequence; -import com.carrotsearch.randomizedtesting.annotations.Timeout; -import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite; -import com.carrotsearch.randomizedtesting.rules.StatementAdapter; - -/** - * A {@link Runner} implementation for running randomized test cases with - * predictable and repeatable randomness. - * - *

Supports the following JUnit4 features: - *

    - *
  • {@link BeforeClass}-annotated methods (before all tests of a class/superclass),
  • - *
  • {@link Before}-annotated methods (before each test),
  • - *
  • {@link Test}-annotated methods,
  • - *
  • {@link After}-annotated methods (after each test),
  • - *
  • {@link AfterClass}-annotated methods (after all tests of a class/superclass),
  • - *
  • {@link Rule}-annotated fields implementing {@link org.junit.rules.MethodRule} - * and {@link TestRule}.
  • - *
- * - *

Contracts: - *

    - *
  • {@link BeforeClass}, {@link Before} - * methods declared in superclasses are called before methods declared in subclasses,
  • - *
  • {@link AfterClass}, {@link After} - * methods declared in superclasses are called after methods declared in subclasses,
  • - *
  • {@link BeforeClass}, {@link Before}, {@link AfterClass}, {@link After} - * methods declared within the same class are called in randomized order - * derived from the master seed (repeatable with the same seed),
  • - *
- * - *

Deviations from "standard" JUnit: - *

    - *
  • test methods are allowed to return values (the return value is ignored),
  • - *
  • hook methods need not be public; in fact, it is encouraged to make them private to - * avoid accidental shadowing which silently drops parent hooks from executing - * (applies to class hooks mostly, but also to instance hooks).
  • - *
  • all exceptions raised during hooks or test case execution are reported to the notifier, - * there is no suppression or chaining of exceptions,
  • - *
  • a test method must not leave behind any active threads; this is detected - * using {@link ThreadGroup} active counts and is sometimes problematic (many classes - * in the standard library leave active threads behind without waiting for them to terminate). - * One can use the {@link ThreadLeakScope}, {@link ThreadLeakAction} - * and other annotations to control how aggressive the detection - * strategy is and if it fails the test or not.
  • - *
  • uncaught exceptions from any of children threads will cause the test to fail.
  • - *
- * - * @see RandomizedTest - * @see ThreadLeakAction - * @see ThreadLeakScope - * @see ThreadLeakZombies - * @see ThreadLeakGroup - * @see ThreadLeakLingering - * @see ThreadLeakFilters - * @see Listeners - * @see RandomizedContext - * @see TestMethodProviders - */ -public final class RandomizedRunner extends Runner implements Filterable { - /** - * Fake package of a stack trace entry inserted into exceptions thrown by - * test methods. These stack entries contain additional information about - * seeds used during execution. - */ - public static final String AUGMENTED_SEED_PACKAGE = "__randomizedtesting"; - - /** - * Default timeout for a single test case. By default - * the timeout is disabled. Use global system property - * {@link SysGlobals#SYSPROP_TIMEOUT} or an annotation {@link Timeout} if you need to set - * timeouts or expect some test cases may hang. This will slightly slow down - * the tests because each test case is executed in a forked thread. - * - * @see SysGlobals#SYSPROP_TIMEOUT() - */ - public static final int DEFAULT_TIMEOUT = 0; - - /** - * Default timeout for an entire suite. By default - * the timeout is disabled. Use the global system property - * {@link SysGlobals#SYSPROP_TIMEOUT_SUITE} or an annotation {@link TimeoutSuite} - * if you need to set - * timeouts or expect some tests (hooks) may hang. - * - * @see SysGlobals#SYSPROP_TIMEOUT_SUITE() - */ - public static final int DEFAULT_TIMEOUT_SUITE = 0; - - /** - * The default number of first interrupts, then Thread.stop attempts. - */ - public static final int DEFAULT_KILLATTEMPTS = 5; - - /** - * Time in between interrupt retries or stop retries. - */ - public static final int DEFAULT_KILLWAIT = 500; - - /** - * The default number of test repeat iterations. - */ - public static final int DEFAULT_ITERATIONS = 1; - - /** - * Test candidate (model). - */ - class TestCandidate { - public final long seed; - public final Description description; - public final Method method; - public final InstanceProvider instanceProvider; - - public TestCandidate(Method method, long seed, Description description, InstanceProvider instanceProvider) { - this.seed = seed; - this.description = description; - this.method = method; - this.instanceProvider = instanceProvider; - } - - public Class getTestClass() { - return suiteClass; - } - } - - /** - * Package scope logger. - */ - final static Logger logger = Logger.getLogger(RandomizedRunner.class.getSimpleName()); - - /** - * A sequencer for affecting the initial seed in case of rapid succession of this class - * instance creations. Not likely, but can happen two could get the same seed. - */ - private final static AtomicLong sequencer = new AtomicLong(); - - private static final List DEFAULT_STACK_FILTERS = Arrays.asList(new String [] { - "org.junit.", - "junit.framework.", - "sun.", - "java.lang.reflect.", - "com.carrotsearch.randomizedtesting.", - }); - - /** The class with test methods (suite). */ - private final Class suiteClass; - - /** The runner's seed (master). */ - final Randomness runnerRandomness; - - /** - * If {@link SysGlobals#SYSPROP_RANDOM_SEED} property is used with two arguments (master:method) - * then this field contains method-level override. - */ - private Randomness testCaseRandomnessOverride; - - /** - * The number of each test's randomized iterations. - * - * @see SysGlobals#SYSPROP_ITERATIONS - */ - private final Integer iterationsOverride; - - /** All test candidates, processed (seeds assigned) and flattened. */ - private List testCandidates; - - /** Class suite description. */ - private Description suiteDescription; - - /** - * All tests are executed under a specified thread group so that we can have some control - * over how many threads have been started/ stopped. System daemons shouldn't be under - * this group. - */ - RunnerThreadGroup runnerThreadGroup; - - /** - * @see #subscribeListeners(RunNotifier) - */ - private final List autoListeners = new ArrayList(); - - /** - * @see SysGlobals#SYSPROP_APPEND_SEED - */ - private boolean appendSeedParameter; - - /** - * Stack trace filtering/ dumping. - */ - private final TraceFormatting traces; - - /** - * The container we're running in. - */ - private RunnerContainer containerRunner; - - /** - * {@link UncaughtExceptionHandler} for capturing uncaught exceptions - * from the test group and globally. - */ - QueueUncaughtExceptionsHandler handler; - - /** - * Class model. - */ - private ClassModel classModel; - - /** - * Random class implementation supplier. - */ - private final RandomSupplier randomSupplier; - - /** - * Methods cache. - */ - private Map,List> shuffledMethodsCache = new HashMap,List>(); - - /** - * A marker for flagging zombie threads (leaked threads that couldn't be killed). - */ - static AtomicBoolean zombieMarker = new AtomicBoolean(false); - - /** - * The "main" thread group we will be tracking (including subgroups). - */ - final static ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup(); - - private final Map restoreProperties = new HashMap(); - - public GroupEvaluator groupEvaluator; - - /** Creates a new runner for the given class. */ - public RandomizedRunner(Class testClass) throws InitializationError { - appendSeedParameter = RandomizedTest.systemPropertyAsBoolean(SYSPROP_APPEND_SEED(), false); - - if (RandomizedTest.systemPropertyAsBoolean(SYSPROP_STACKFILTERING(), true)) { - this.traces = new TraceFormatting(DEFAULT_STACK_FILTERS); - } else { - this.traces = new TraceFormatting(); - } - - this.suiteClass = testClass; - this.classModel = new ClassModel(testClass); - - // Try to detect the JUnit runner's container. This changes reporting - // behavior slightly. - this.containerRunner = detectContainer(); - - // Initialize the runner's master seed/ randomness source. - { - List decorators = new ArrayList(); - for (SeedDecorators decAnn : getAnnotationsFromClassHierarchy(testClass, SeedDecorators.class)) { - for (Class clazz : decAnn.value()) { - try { - SeedDecorator dec = clazz.newInstance(); - dec.initialize(testClass); - decorators.add(dec); - } catch (Throwable t) { - throw new RuntimeException("Could not initialize suite class: " - + testClass.getName() + " because its @SeedDecorators contains non-instantiable: " - + clazz.getName(), t); - } - } - } - SeedDecorator[] decArray = decorators.toArray(new SeedDecorator [decorators.size()]); - - randomSupplier = determineRandomSupplier(testClass); - - final long randomSeed = MurmurHash3.hash(sequencer.getAndIncrement() + System.nanoTime()); - final String globalSeed = emptyToNull(System.getProperty(SYSPROP_RANDOM_SEED())); - final long initialSeed; - if (globalSeed != null) { - final long[] seedChain = SeedUtils.parseSeedChain(globalSeed); - if (seedChain.length == 0 || seedChain.length > 2) { - throw new IllegalArgumentException("Invalid system property " - + SYSPROP_RANDOM_SEED() + " specification: " + globalSeed); - } - - if (seedChain.length > 1) { - testCaseRandomnessOverride = new Randomness(seedChain[1], randomSupplier); - } - - initialSeed = seedChain[0]; - } else if (suiteClass.isAnnotationPresent(Seed.class)) { - initialSeed = seedFromAnnot(suiteClass, randomSeed)[0]; - } else { - initialSeed = randomSeed; - } - runnerRandomness = new Randomness(initialSeed, randomSupplier, decArray); - } - - // Iterations property is primary wrt to annotations, so we leave an "undefined" value as null. - if (emptyToNull(System.getProperty(SYSPROP_ITERATIONS())) != null) { - this.iterationsOverride = RandomizedTest.systemPropertyAsInt(SYSPROP_ITERATIONS(), 0); - if (iterationsOverride < 1) - throw new IllegalArgumentException( - "System property " + SYSPROP_ITERATIONS() + " must be >= 1: " + iterationsOverride); - } else { - this.iterationsOverride = null; - } - - try { - // Fail fast if suiteClass is inconsistent or selected "standard" JUnit rules are somehow broken. - validateTarget(); - - // Collect all test candidates, regardless if they will be executed or not. - suiteDescription = Description.createSuiteDescription(suiteClass); - testCandidates = collectTestCandidates(suiteDescription); - this.groupEvaluator = new GroupEvaluator(testCandidates); - - // GH-251: Apply suite and test filters early so that the returned Description gets updated. - if (emptyToNull(System.getProperty(SYSPROP_TESTMETHOD())) != null) { - try { - filter(new MethodGlobFilter(System.getProperty(SYSPROP_TESTMETHOD()))); - } catch (NoTestsRemainException e) { - // Ignore the exception in the constructor. - } - } - - if (emptyToNull(System.getProperty(SYSPROP_TESTCLASS())) != null) { - Filter suiteFilter = new ClassGlobFilter(System.getProperty(SYSPROP_TESTCLASS())); - if (!suiteFilter.shouldRun(suiteDescription)) { - suiteDescription.getChildren().clear(); - testCandidates.clear(); - } - } - } catch (Throwable t) { - throw new InitializationError(t); - } - } - - private RandomSupplier determineRandomSupplier(Class testClass) { - List randomImpl = getAnnotationsFromClassHierarchy(testClass, TestContextRandomSupplier.class); - if (randomImpl.size() == 0) { - return RandomSupplier.DEFAULT; - } else { - Class clazz = randomImpl.get(randomImpl.size() - 1).value(); - try { - return clazz.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new IllegalArgumentException("Could not instantiate random supplier of class: " + clazz, e); - } - } - } - - /** - * Attempt to detect the container we're running under. - */ - private static RunnerContainer detectContainer() { - StackTraceElement [] stack = Thread.currentThread().getStackTrace(); - if (stack.length > 0) { - String topClass = stack[stack.length - 1].getClassName(); - - if (topClass.equals("org.eclipse.jdt.internal.junit.runner.RemoteTestRunner")) { - return RunnerContainer.ECLIPSE; - } - - if (topClass.startsWith("com.intellij.")) { - return RunnerContainer.IDEA; - } - } - return RunnerContainer.UNKNOWN; - } - - /** - * Return the current tree of test descriptions (filtered). - */ - @Override - public Description getDescription() { - return suiteDescription; - } - - /** - * Implement {@link Filterable} because GUIs depend on it to run tests selectively. - */ - @Override - public void filter(Filter filter) throws NoTestsRemainException { - // Apply the filter to test candidates. - testCandidates = applyFilters(suiteClass, testCandidates, Collections.singleton(filter)); - - // Prune any removed tests from the already created Descriptions - // and prune any empty resulting suites. - Set descriptions = Collections.newSetFromMap(new IdentityHashMap()); - for (TestCandidate tc : testCandidates) { - descriptions.add(tc.description); - } - - suiteDescription = prune(suiteDescription, descriptions); - - if (testCandidates.isEmpty()) { - throw new NoTestsRemainException(); - } - } - - private static Description prune(Description suite, Set permitted) { - if (suite.isSuite()) { - ArrayList children = suite.getChildren(); - ArrayList retained = new ArrayList<>(children.size()); - for (Description child : children) { - if (child.isSuite()) { - final Description description = prune(child, permitted); - if (!child.getChildren().isEmpty()) { - retained.add(description); - } - } else if (permitted.contains(child)) { - retained.add(child); - } - } - - final Description suiteDescription = suite.childlessCopy(); - for (Description description : retained) { - suiteDescription.addChild(description); - } - return suiteDescription; - } - return suite; - } - - /** - * Runs all tests and hooks. - */ - @Override - public void run(RunNotifier notifier) { - processSystemProperties(); - try { - runSuite(notifier); - } finally { - restoreSystemProperties(); - } - } - - private void restoreSystemProperties() { - for (Map.Entry e : restoreProperties.entrySet()) { - try { - if (e.getValue() == null) { - System.clearProperty(e.getKey()); - } else { - System.setProperty(e.getKey(), e.getValue()); - } - } catch (SecurityException x) { - logger.warning("Could not restore system property: " + e.getKey() + " => " + e.getValue()); - } - } - } - - private void processSystemProperties() { - try { - String jvmCount = System.getProperty(SysGlobals.CHILDVM_SYSPROP_JVM_COUNT); - String jvmId = System.getProperty(SysGlobals.CHILDVM_SYSPROP_JVM_ID); - if (emptyToNull(jvmCount) == null && - emptyToNull(jvmId) == null) { - // We don't run under JUnit4 so we have to fill in these manually. - System.setProperty(SysGlobals.CHILDVM_SYSPROP_JVM_COUNT, "1"); - System.setProperty(SysGlobals.CHILDVM_SYSPROP_JVM_ID, "0"); - restoreProperties.put(SysGlobals.CHILDVM_SYSPROP_JVM_COUNT, jvmCount); - restoreProperties.put(SysGlobals.CHILDVM_SYSPROP_JVM_ID, jvmId); - } - } catch (SecurityException e) { - // Ignore if we can't set those properties. - logger.warning("Could not set child VM count and ID properties."); - } - } - - static class UncaughtException { - final Thread thread; - final String threadName; - final Throwable error; - - UncaughtException(Thread t, Throwable error) { - this.threadName = Threads.threadName(t); - this.thread = t; - this.error = error; - } - } - - /** - * Queue uncaught exceptions. - */ - static class QueueUncaughtExceptionsHandler implements UncaughtExceptionHandler { - private final ArrayList uncaughtExceptions = new ArrayList(); - private boolean reporting = true; - - @Override - public void uncaughtException(Thread t, Throwable e) { - synchronized (this) { - if (!reporting) { - return; - } - uncaughtExceptions.add(new UncaughtException(t, e)); - } - - Logger.getLogger(RunnerThreadGroup.class.getSimpleName()).log( - Level.WARNING, - "Uncaught exception in thread: " + t, e); - } - - /** - * Stop reporting uncaught exceptions. - */ - void stopReporting() { - synchronized (this) { - reporting = false; - } - } - - /** - * Resume uncaught exception reporting. - */ - void resumeReporting() { - synchronized (this) { - reporting = true; - } - } - - /** - * Return the current list of uncaught exceptions and clear it. - */ - public List getUncaughtAndClear() { - synchronized (this) { - final ArrayList copy = new ArrayList(uncaughtExceptions); - uncaughtExceptions.clear(); - return copy; - } - } - } - - /** - * Test execution logic for the entire suite. - */ - private void runSuite(final RunNotifier notifier) { - // NOTE: this effectively means we can't run concurrent randomized runners. - final UncaughtExceptionHandler previous = Thread.getDefaultUncaughtExceptionHandler(); - handler = new QueueUncaughtExceptionsHandler(); - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - Thread.setDefaultUncaughtExceptionHandler(handler); - return null; - } - }); - - this.runnerThreadGroup = new RunnerThreadGroup( - "TGRP-" + Classes.simpleName(suiteClass)); - - final Thread runner = new Thread(runnerThreadGroup, - "SUITE-" + Classes.simpleName(suiteClass) + "-seed#" + SeedUtils.formatSeedChain(runnerRandomness)) { - public void run() { - try { - // Make sure static initializers are invoked and that they are invoked outside of - // the randomized context scope. This is for consistency so that we're not relying - // on the class NOT being initialized before. - try { - Class.forName(suiteClass.getName(), true, suiteClass.getClassLoader()); - } catch (ExceptionInInitializerError e) { - throw e.getCause(); - } - - RandomizedContext context = createContext(runnerThreadGroup); - runSuite(context, notifier); - context.dispose(); - } catch (Throwable t) { - notifier.fireTestFailure(new Failure(suiteDescription, t)); - } - } - }; - - runner.start(); - try { - runner.join(); - } catch (InterruptedException e) { - notifier.fireTestFailure(new Failure(suiteDescription, - new RuntimeException("Interrupted while waiting for the suite runner? Weird.", e))); - } - - UncaughtExceptionHandler current = Thread.getDefaultUncaughtExceptionHandler(); - if (current != handler) { - notifier.fireTestFailure(new Failure(suiteDescription, - new RuntimeException("Suite replaced Thread.defaultUncaughtExceptionHandler. " + - "It's better not to touch it. Or at least revert it to what it was before. Current: " + - (current == null ? "(null)" : current.getClass())))); - } - - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - Thread.setDefaultUncaughtExceptionHandler(previous); - return null; - } - }); - runnerThreadGroup = null; - handler = null; - } - - /** - * Test execution logic for the entire suite, executing under designated - * {@link RunnerThreadGroup}. - */ - private void runSuite(final RandomizedContext context, final RunNotifier notifier) { - final Result result = new Result(); - final RunListener accounting = result.createListener(); - notifier.addListener(accounting); - - final Randomness classRandomness = runnerRandomness.clone(Thread.currentThread()); - context.push(classRandomness); - try { - // Check for automatically hookable listeners. - subscribeListeners(notifier); - - // Fire a synthetic "suite started" event. - for (RunListener r : autoListeners) { - try { - r.testRunStarted(suiteDescription); - } catch (Throwable e) { - logger.log(Level.SEVERE, "Panic: RunListener hook shouldn't throw exceptions.", e); - } - } - - final List tests = testCandidates; - if (!tests.isEmpty()) { - Map ignored = determineIgnoredTests(tests); - - if (ignored.size() == tests.size()) { - // All tests ignored, ignore class hooks but report all the ignored tests. - for (TestCandidate c : tests) { - if (ignored.get(c)) { - reportAsIgnored(notifier, groupEvaluator, c); - } - } - } else { - ThreadLeakControl threadLeakControl = new ThreadLeakControl(notifier, this); - Statement s = runTestsStatement(threadLeakControl.notifier(), tests, ignored, threadLeakControl); - s = withClassBefores(s); - s = withClassAfters(s); - s = withClassRules(s); - s = withCloseContextResources(s, LifecycleScope.SUITE); - s = threadLeakControl.forSuite(s, suiteDescription); - try { - s.evaluate(); - } catch (Throwable t) { - t = augmentStackTrace(t, runnerRandomness); - if (isAssumptionViolated(t)) { - // Fire assumption failure before method ignores. (GH-103). - notifier.fireTestAssumptionFailed(new Failure(suiteDescription, t)); - - // Class level assumptions cause all tests to be ignored. - // see Rants#RANT_3 - for (final TestCandidate c : tests) { - notifier.fireTestIgnored(c.description); - } - } else { - fireTestFailure(notifier, suiteDescription, t); - } - } - } - } - } catch (Throwable t) { - notifier.fireTestFailure(new Failure(suiteDescription, t)); - } - - // Fire a synthetic "suite ended" event and unsubscribe listeners. - for (RunListener r : autoListeners) { - try { - r.testRunFinished(result); - } catch (Throwable e) { - logger.log(Level.SEVERE, "Panic: RunListener hook shouldn't throw exceptions.", e); - } - } - - // Final cleanup. - notifier.removeListener(accounting); - unsubscribeListeners(notifier); - context.popAndDestroy(); - } - - /** - * Determine the set of ignored tests. - */ - private Map determineIgnoredTests(List tests) { - Map ignoredTests = new IdentityHashMap<>(); - for (TestCandidate c : tests) { - // If it's an @Ignore-marked test, always report it as ignored, remove it from execution. - if (hasIgnoreAnnotation(c) ) { - ignoredTests.put(c, true); - } - - // Otherwise, check if the test should be ignored due to test group annotations or filtering - // expression - if (isTestFiltered(groupEvaluator, c)) { - // If we're running under an IDE, report the test back as ignored. Otherwise - // check if filtering expression is being used. If not, report the test as ignored - // (test group exclusion at work). - if (containerRunner == RunnerContainer.ECLIPSE || - containerRunner == RunnerContainer.IDEA || - !groupEvaluator.hasFilteringExpression()) { - ignoredTests.put(c, true); - } else { - ignoredTests.put(c, false); - } - } - } - return ignoredTests; - } - - /** - * Wrap with a rule to close context resources. - */ - private static Statement withCloseContextResources(final Statement s, final LifecycleScope scope) { - return new StatementAdapter(s) { - @Override - protected void afterAlways(final List errors) throws Throwable { - final ObjectProcedure disposer = new ObjectProcedure() { - public void apply(CloseableResourceInfo info) { - try { - info.getResource().close(); - } catch (Throwable t) { - ResourceDisposalError e = new ResourceDisposalError( - "Resource in scope " + - info.getScope().name() + " failed to close. Resource was" - + " registered from thread " + info.getThreadName() - + ", registration stack trace below.", t); - e.setStackTrace(info.getAllocationStack()); - errors.add(e); - } - } - }; - - RandomizedContext.current().closeResources(disposer, scope); - } - }; - } - - private Statement runTestsStatement( - final RunNotifier notifier, - final List tests, - final Map ignored, - final ThreadLeakControl threadLeakControl) { - return new Statement() { - public void evaluate() throws Throwable { - for (final TestCandidate c : tests) { - if (threadLeakControl.isTimedOut()) { - break; - } - - // Setup test thread's name so that stack dumps produce seed, test method, etc. - final String testThreadName = "TEST-" + Classes.simpleName(suiteClass) + - "." + c.method.getName() + "-seed#" + SeedUtils.formatSeedChain(runnerRandomness); - final String restoreName = Thread.currentThread().getName(); - - // This has a side effect of setting up a nested context for the test thread. - final RandomizedContext current = RandomizedContext.current(); - try { - Thread.currentThread().setName(testThreadName); - current.push(new Randomness(c.seed, randomSupplier)); - current.setTargetMethod(c.method); - - if (ignored.containsKey(c)) { - // Ignore the test, but report only if requested. - if (ignored.get(c)) { - reportAsIgnored(notifier, groupEvaluator, c); - } - } else { - runSingleTest(notifier, c, threadLeakControl); - } - } finally { - Thread.currentThread().setName(restoreName); - current.setTargetMethod(null); - current.popAndDestroy(); - } - } - } - }; - } - - void reportAsIgnored(RunNotifier notifier, GroupEvaluator ge, TestCandidate c) { - if (c.method.getAnnotation(Ignore.class) != null) { - notifier.fireTestIgnored(c.description); - return; - } - - String ignoreReason = ge.getIgnoreReason(c.method, suiteClass); - if (ignoreReason != null) { - notifier.fireTestStarted(c.description); - notifier.fireTestAssumptionFailed(new Failure(c.description, - new AssumptionViolatedException(ignoreReason))); - notifier.fireTestFinished(c.description); - } - } - - private void fireTestFailure(RunNotifier notifier, Description description, Throwable t) { - if (t instanceof MultipleFailureException) { - for (Throwable nested : ((MultipleFailureException) t).getFailures()) { - fireTestFailure(notifier, description, nested); - } - } else { - notifier.fireTestFailure(new Failure(description, t)); - } - } - - /** - * Decorate a {@link Statement} with {@link BeforeClass} hooks. - */ - private Statement withClassBefores(final Statement s) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - try { - for (Method method : getShuffledMethods(BeforeClass.class)) { - invoke(method, null); - } - } catch (Throwable t) { - throw augmentStackTrace(t, runnerRandomness); - } - s.evaluate(); - } - }; - } - - private Statement withClassAfters(final Statement s) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - List errors = new ArrayList(); - try { - s.evaluate(); - } catch (Throwable t) { - errors.add(augmentStackTrace(t, runnerRandomness)); - } - - for (Method method : getShuffledMethods(AfterClass.class)) { - try { - invoke(method, null); - } catch (Throwable t) { - errors.add(augmentStackTrace(t, runnerRandomness)); - } - } - - MultipleFailureException.assertEmpty(errors); - } - }; - } - - /** - * Wrap with {@link ClassRule}s. - */ - private Statement withClassRules(Statement s) { - List classRules = getAnnotatedFieldValues(null, ClassRule.class, TestRule.class); - for (TestRule rule : classRules) { - s = rule.apply(s, suiteDescription); - } - return s; - } - - /** - * Runs a single test in the "master" test thread. - */ - void runSingleTest(final RunNotifier notifier, - final TestCandidate c, - final ThreadLeakControl threadLeakControl) { - notifier.fireTestStarted(c.description); - - try { - // Get the test instance. - final Object instance = c.instanceProvider.newInstance(); - - // Collect rules and execute wrapped method. - Statement s = new Statement() { - public void evaluate() throws Throwable { - invoke(c.method, instance); - } - }; - - s = wrapExpectedExceptions(s, c); - s = wrapBeforeAndAfters(s, c, instance); - s = wrapMethodRules(s, c, instance); - s = withCloseContextResources(s, LifecycleScope.TEST); - s = threadLeakControl.forTest(s, c); - s.evaluate(); - } catch (Throwable e) { - e = augmentStackTrace(e); - if (isAssumptionViolated(e)) { - notifier.fireTestAssumptionFailed(new Failure(c.description, e)); - } else { - fireTestFailure(notifier, c.description, e); - } - } finally { - notifier.fireTestFinished(c.description); - } - } - - /** - * Wrap before and after hooks. - */ - private Statement wrapBeforeAndAfters(Statement s, final TestCandidate c, final Object instance) { - // Process @Before hooks. The first @Before to fail will immediately stop processing any other @Befores. - final List befores = getShuffledMethods(Before.class); - if (!befores.isEmpty()) { - final Statement afterBefores = s; - s = new Statement() { - @Override - public void evaluate() throws Throwable { - for (Method m : befores) { - invoke(m, instance); - } - afterBefores.evaluate(); - } - }; - } - - // Process @After hooks. All @After hooks are processed, regardless of their own exceptions. - final List afters = getShuffledMethods(After.class); - if (!afters.isEmpty()) { - final Statement beforeAfters = s; - s = new Statement() { - @Override - public void evaluate() throws Throwable { - List cumulative = new ArrayList(); - try { - beforeAfters.evaluate(); - } catch (Throwable t) { - cumulative.add(t); - } - - // All @Afters must be called. - for (Method m : afters) { - try { - invoke(m, instance); - } catch (Throwable t) { - cumulative.add(t); - } - } - - // At end, throw the exception or propagete. - if (cumulative.size() == 1) { - throw cumulative.get(0); - } else if (cumulative.size() > 1) { - throw new MultipleFailureException(cumulative); - } - } - }; - } - - return s; - } - - /** - * Wrap the given statement into another catching the expected exception, if declared. - */ - private Statement wrapExpectedExceptions(final Statement s, TestCandidate c) { - Test ann = c.method.getAnnotation(Test.class); - - if (ann == null) { - return s; - } - - // If there's no expected class, don't wrap. Eh, None is package-private... - final Class expectedClass = ann.expected(); - if (expectedClass.getName().equals("org.junit.Test$None")) { - return s; - } - - return new Statement() { - @Override - public void evaluate() throws Throwable { - try { - s.evaluate(); - } catch (Throwable t) { - if (!expectedClass.isInstance(t)) { - throw t; - } - // We caught something that was expected. No worries then. - return; - } - - // If we're here this means we passed the test that expected a failure. - Assert.fail("Expected an exception but the test passed: " - + expectedClass.getName()); - } - }; - } - - /** - * Wrap the given statement in any declared MethodRules (old style rules). - */ - @SuppressWarnings("deprecation") - private Statement wrapMethodRules(Statement s, TestCandidate c, Object instance) { - FrameworkMethod fm = new FrameworkMethod(c.method); - - // Old-style MethodRules first. - List methodRules = - getAnnotatedFieldValues(instance, Rule.class, org.junit.rules.MethodRule.class); - for (org.junit.rules.MethodRule rule : methodRules) { - s = rule.apply(s, fm, instance); - } - - // New-style TestRule next. - List testRules = - getAnnotatedFieldValues(instance, Rule.class, TestRule.class); - for (TestRule rule : testRules) { - s = rule.apply(s, c.description); - } - - return s; - } - - /* - * We're using JUnit infrastructure here, but provide constant - * ordering of the result. The returned list has class...super order. - */ - private List getAnnotatedFieldValues(Object test, - Class annotationClass, Class valueClass) { - TestClass info = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public TestClass run() { - return new TestClass(suiteClass); - } - }); - List results = new ArrayList(); - - List annotatedFields = - new ArrayList(info.getAnnotatedFields(annotationClass)); - - // Split fields by class - final HashMap, List> byClass = - new HashMap, List>(); - for (FrameworkField field : annotatedFields) { - Class clz = field.getField().getDeclaringClass(); - if (!byClass.containsKey(clz)) { - byClass.put(clz, new ArrayList()); - } - byClass.get(clz).add(field); - } - - // Consistent order at class level. - for (List fields : byClass.values()) { - Collections.sort(fields, new Comparator() { - @Override - public int compare(FrameworkField o1, FrameworkField o2) { - return o1.getField().getName().compareTo( - o2.getField().getName()); - } - }); - Collections.shuffle(fields, new Random(runnerRandomness.getSeed())); - } - - annotatedFields.clear(); - for (Class clz = suiteClass; clz != null; clz = clz.getSuperclass()) { - List clzFields = byClass.get(clz); - if (clzFields != null) { - annotatedFields.addAll(clzFields); - } - } - - for (FrameworkField each : annotatedFields) { - try { - Object fieldValue = each.get(test); - if (valueClass.isInstance(fieldValue)) - results.add(valueClass.cast(fieldValue)); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - return results; - } - - /** - * Create randomized context for the run. The context is shared by all - * threads in a given thread group (but the source of {@link Randomness} - * is assigned per-thread). - */ - private RandomizedContext createContext(ThreadGroup tg) { - return RandomizedContext.create(tg, suiteClass, this); - } - - /** Subscribe annotation listeners to the notifier. */ - private void subscribeListeners(RunNotifier notifier) { - for (Listeners ann : getAnnotationsFromClassHierarchy(suiteClass, Listeners.class)) { - for (Class clazz : ann.value()) { - try { - RunListener listener = clazz.newInstance(); - autoListeners.add(listener); - notifier.addListener(listener); - } catch (Throwable t) { - throw new RuntimeException("Could not initialize suite class: " - + suiteClass.getName() + " because its @Listener is not instantiable: " - + clazz.getName(), t); - } - } - } - } - - /** Unsubscribe listeners. */ - private void unsubscribeListeners(RunNotifier notifier) { - for (RunListener r : autoListeners) - notifier.removeListener(r); - } - - private static List applyFilters(Class suiteClass, - List testCandidates, - Collection testFilters) { - final List filtered; - if (testFilters.isEmpty()) { - filtered = new ArrayList(testCandidates); - } else { - filtered = new ArrayList<>(testCandidates.size()); - for (TestCandidate candidate : testCandidates) { - boolean shouldRun = true; - for (Filter f : testFilters) { - // Inquire for both full description (possibly with parameters and seed) - // and simplified description (just method name). - if (f.shouldRun(candidate.description) || - f.shouldRun(Description.createTestDescription( - suiteClass, candidate.method.getName()))) { - continue; - } - - shouldRun = false; - break; - } - - if (shouldRun) { - filtered.add(candidate); - } - } - } - return filtered; - } - - /** - * Normalize empty strings to nulls. - */ - static String emptyToNull(String value) { - if (value == null || value.trim().isEmpty()) - return null; - return value.trim(); - } - - /** - * Returns true if we should ignore this test candidate. - */ - private boolean hasIgnoreAnnotation(TestCandidate c) { - return c.method.getAnnotation(Ignore.class) != null; - } - - private boolean isTestFiltered(GroupEvaluator ev, TestCandidate c) { - return ev.getIgnoreReason(c.method, suiteClass) != null; - } - - /** - * Construct a list of ordered framework methods. Minor tweaks are done depending - * on the annotation (reversing order, etc.). - */ - private List getShuffledMethods(Class ann) { - List methods = shuffledMethodsCache.get(ann); - if (methods != null) { - return methods; - } - - methods = new ArrayList(classModel.getAnnotatedLeafMethods(ann).keySet()); - - // Shuffle sub-ranges using class level randomness. - Random rnd = new Random(runnerRandomness.getSeed()); - for (int i = 0, j = 0; i < methods.size(); i = j) { - final Method m = methods.get(i); - j = i + 1; - while (j < methods.size() && m.getDeclaringClass() == methods.get(j).getDeclaringClass()) { - j++; - } - - if (j - i > 1) { - Collections.shuffle(methods.subList(i, j), rnd); - } - } - - // Reverse processing order to super...clazz for befores - if (ann == Before.class || ann == BeforeClass.class) { - Collections.reverse(methods); - } - - methods = Collections.unmodifiableList(methods); - shuffledMethodsCache.put(ann, methods); - return methods; - } - - /** - * Collect all test candidates, regardless if they will be executed or not. At this point - * individual test methods are also expanded into multiple executions corresponding - * to the number of iterations ({@link SysGlobals#SYSPROP_ITERATIONS}) and the initial method seed - * is preassigned. - * - *

The order of test candidates is shuffled based on the runner's random.

- * - * @see Rants#RANT_1 - */ - private List collectTestCandidates(Description classDescription) { - // Get the test instance provider if explicitly stated. - TestMethodProviders providersAnnotation = - suiteClass.getAnnotation(TestMethodProviders.class); - - // If nothing, fallback to the default. - final TestMethodProvider [] providers; - if (providersAnnotation != null) { - providers = new TestMethodProvider [providersAnnotation.value().length]; - int i = 0; - for (Class clazz : providersAnnotation.value()) { - try { - providers[i++] = clazz.newInstance(); - } catch (Exception e) { - throw new RuntimeException(TestMethodProviders.class.getSimpleName() + - " classes could not be instantiated.", e); - } - } - } else { - providers = new TestMethodProvider [] { - new JUnit4MethodProvider(), - // new JUnit3MethodProvider(), - }; - } - - // Get test methods from providers. - final Set allTestMethods = new HashSet(); - for (TestMethodProvider provider : providers) { - Collection testMethods = provider.getTestMethods(suiteClass, classModel); - allTestMethods.addAll(testMethods); - } - - List testMethods = new ArrayList(allTestMethods); - Collections.sort(testMethods, new Comparator() { - @Override - public int compare(Method m1, Method m2) { - return m1.toGenericString().compareTo(m2.toGenericString()); - } - }); - - // Perform candidate method validation. - validateTestMethods(testMethods); - - // Random (but consistent) shuffle. - Collections.shuffle(testMethods, new Random(runnerRandomness.getSeed())); - - Constructor[] constructors = suiteClass.getConstructors(); - if (constructors.length != 1) { - throw new RuntimeException("There must be exactly one constructor: " + constructors.length); - } - final Constructor constructor = constructors[0]; - - // Collect test method-parameters pairs. - List testCases = collectMethodExecutions(constructor, testMethods); - - // Test case ordering. Shuffle only real test cases, don't allow shuffling - // or changing the order of reiterations or explicit @Seed annotations that - // multiply a given test. - TestCaseOrdering methodOrder = suiteClass.getAnnotation(TestCaseOrdering.class); - if (methodOrder != null) { - try { - Collections.sort(testCases, methodOrder.value().newInstance()); - } catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException("Could not sort test methods.", e); - } - } - - // Collect all variants of execution for a single method/ parameters pair. - Map descriptionRepetitions = new HashMap<>(); - List allTests = new ArrayList(); - Map> sameMethodVariants = new LinkedHashMap>(); - for (TestMethodExecution testCase : testCases) { - List variants = collectCandidatesForMethod(descriptionRepetitions, constructor, testCase); - allTests.addAll(variants); - - List existing = sameMethodVariants.get(testCase.method); - if (existing == null) { - existing = new ArrayList<>(variants); - sameMethodVariants.put(testCase.method, existing); - } else { - existing.addAll(variants); - } - } - - // Rearrange JUnit Description into a hierarchy if a given method - // has more than one variant (due to multiple repetitions, parameters or seeds). - for (Map.Entry> e : sameMethodVariants.entrySet()) { - List candidates = e.getValue(); - if (candidates.size() > 1) { - Description methodParent = Description.createSuiteDescription(e.getKey().getName()); - suiteDescription.addChild(methodParent); - for (TestCandidate candidate : candidates) { - methodParent.addChild(candidate.description); - } - } else { - suiteDescription.addChild(candidates.iterator().next().description); - } - } - - return allTests; - } - - /** - * Helper tuple (Method, instance params). - */ - static private class TestMethodExecution implements TestMethodAndParams { - final Object [] params; - final List paramsWrapper; - final Method method; - final String argFormattingTemplate; - final InstanceProvider instanceProvider; - - public TestMethodExecution(Method m, String argFormattingTemplate, Object[] params, InstanceProvider instanceProvider) { - this.method = m; - this.params = params; - this.paramsWrapper = Collections.unmodifiableList(Arrays.asList(params)); - this.argFormattingTemplate = argFormattingTemplate; - this.instanceProvider = instanceProvider; - } - - @Override - public Method getTestMethod() { - return method; - } - - @Override - public List getInstanceArguments() { - return paramsWrapper; - } - } - - /** - * Collect test candidates for a single method and the given seed. - */ - private List collectCandidatesForMethod( - Map descriptionRepetitions, - final Constructor constructor, - TestMethodExecution testCase) { - final Method method = testCase.method; - final Object[] params = testCase.params; - final boolean fixedSeed = isConstantSeedForAllIterations(method); - final int methodIterations = determineMethodIterationCount(method); - final long[] seeds = determineMethodSeeds(method); - - final List candidates = new ArrayList(); - - String argFormattingTemplate = testCase.argFormattingTemplate; - if (methodIterations > 1 || seeds.length > 1 || appendSeedParameter) { - final int seedParamIndex = params.length + 1; - argFormattingTemplate += " seed=%" + seedParamIndex + "$s"; - } - - for (final long testSeed : seeds) { - for (int i = 0; i < methodIterations; i++) { - final long thisSeed = (fixedSeed ? testSeed : testSeed ^ MurmurHash3.hash((long) i)); - - // Format constructor arguments. - Object [] args = Arrays.copyOf(testCase.params, testCase.params.length + 1, Object[].class); - args[args.length - 1] = SeedUtils.formatSeedChain(runnerRandomness, new Randomness(thisSeed, randomSupplier)); - String formattedArguments = String.format(Locale.ROOT, argFormattingTemplate, args); - - String key = method.getName() + "::" + formattedArguments; - int cnt = 1 + zeroForNull(descriptionRepetitions.get(key)); - descriptionRepetitions.put(key, cnt); - if (cnt > 1) { - formattedArguments += " #" + cnt; - } - - if (!formattedArguments.trim().isEmpty()) { - // GH-253: IntelliJ only recognizes test names for re-runs when " [...]" is used... - // Leave for now (backward compat?) - if (containerRunner == RunnerContainer.IDEA) { - formattedArguments = " [" + formattedArguments.trim() + "]"; - } else { - formattedArguments = " {" + formattedArguments.trim() + "}"; - } - } - - Description description = Description.createSuiteDescription( - String.format(Locale.ROOT, "%s%s(%s)", method.getName(), formattedArguments, suiteClass.getName()), - method.getAnnotations()); - - // Create an instance and delay instantiation exception if possible. - candidates.add(new TestCandidate(method, thisSeed, description, testCase.instanceProvider)); - } - } - - return candidates; - } - - /** Replace null with zero. */ - private static int zeroForNull(Integer v) { - return v == null ? 0 : v; - } - - /** - * Collect test method executions from list of test methods and - * potentially parameters from parameter factory methods. - */ - public List collectMethodExecutions(Constructor constructor, List testMethods) { - final List testCases = new ArrayList<>(); - String argFormattingTemplate = createDefaultArgumentFormatting(constructor); - final Map factoryMethods = classModel.getAnnotatedLeafMethods(ParametersFactory.class); - - if (factoryMethods.isEmpty()) { - Object[] noArgs = new Object [0]; - InstanceProvider instanceProvider = getInstanceProvider(constructor, noArgs); - for (Method testMethod : testMethods) { - testCases.add(new TestMethodExecution(testMethod, argFormattingTemplate, noArgs, instanceProvider)); - } - } else { - for (Method factoryMethod : factoryMethods.keySet()) { - Validation.checkThat(factoryMethod) - .isStatic() - .isPublic(); - - if (!Iterable.class.isAssignableFrom(factoryMethod.getReturnType())) { - throw new RuntimeException("@" + ParametersFactory.class.getSimpleName() + " annotated " + - "methods must be public, static and returning Iterable:" + factoryMethod); - } - - ParametersFactory pfAnnotation = factoryMethod.getAnnotation(ParametersFactory.class); - if (!pfAnnotation.argumentFormatting().equals(ParametersFactory.DEFAULT_FORMATTING)) { - argFormattingTemplate = pfAnnotation.argumentFormatting(); - } - - List args = new ArrayList<>(); - try { - Iterable factoryArguments = Iterable.class.cast(factoryMethod.invoke(null)); - for (Object o : factoryArguments) { - if (!(o instanceof Object[])) { - throw new RuntimeException("Expected Object[] for each set of constructor arguments: " + o); - } - args.add((Object[]) o); - } - } catch (InvocationTargetException e) { - if (isAssumptionViolated(e.getCause())) { - return Collections.emptyList(); - } - Rethrow.rethrow(e.getCause()); - } catch (Throwable t) { - throw new RuntimeException("Error collecting parameters from: " + factoryMethod, t); - } - - if (pfAnnotation.shuffle()) { - Collections.shuffle(args, new Random(runnerRandomness.getSeed())); - } - - for (Object[] constructorArgs : args) { - InstanceProvider instanceProvider = getInstanceProvider(constructor, constructorArgs); - for (Method testMethod : testMethods) { - testCases.add(new TestMethodExecution(testMethod, argFormattingTemplate, constructorArgs, instanceProvider)); - } - } - } - } - return testCases; - } - - private boolean isAssumptionViolated(Throwable cause) { - return cause instanceof org.junit.AssumptionViolatedException || - cause instanceof org.junit.internal.AssumptionViolatedException; - } - - /** - * Determine instance provider. - */ - private InstanceProvider getInstanceProvider(Constructor constructor, Object[] args) { - TestCaseInstanceProvider.Type type = TestCaseInstanceProvider.Type.INSTANCE_PER_TEST_METHOD; - TestCaseInstanceProvider providerAnn = suiteClass.getAnnotation(TestCaseInstanceProvider.class); - if (providerAnn != null) { - type = providerAnn.value(); - } - - switch (type) { - case INSTANCE_PER_CONSTRUCTOR_ARGS: - return new SameInstanceProvider(new NewInstanceProvider(constructor, args)); - case INSTANCE_PER_TEST_METHOD: - return new NewInstanceProvider(constructor, args); - default: - throw new RuntimeException(); - } - } - - private static class SameInstanceProvider implements InstanceProvider { - private final InstanceProvider delegate; - private volatile Object instance; - - public SameInstanceProvider(InstanceProvider delegate) { - this.delegate = delegate; - } - - @Override - public Object newInstance() throws Throwable { - // There should be no concurrent-threaded access to this method, ever, - // but we can be called from multiple threads sequentially. - if (instance == null) { - instance = delegate.newInstance(); - } - return instance; - } - } - - private static class NewInstanceProvider implements InstanceProvider { - private final Constructor constructor; - private final Object[] args; - - public NewInstanceProvider(Constructor constructor, Object[] args) { - this.constructor = constructor; - this.args = args; - } - - @Override - public Object newInstance() throws Throwable { - try { - return constructor.newInstance(args); - } catch (InvocationTargetException e) { - throw ((InvocationTargetException) e).getTargetException(); - } catch (IllegalArgumentException e) { - throw new IllegalArgumentException( - "Constructor arguments do not match provider parameters?", e); - } - } - } - - /** - * Default formatting string for constructor arguments. - */ - private static String createDefaultArgumentFormatting(Constructor constructor) { - StringBuilder b = new StringBuilder(); - final int argCount = constructor.getParameterTypes().length; - Annotation [][] anns = constructor.getParameterAnnotations(); - for (int i = 0; i < argCount; i++) { - String argName = null; - - for (Annotation ann : anns[i]) { - if (ann != null && ann.annotationType().equals(Name.class)) { - argName = ((Name) ann).value(); - break; - } - } - - if (argName == null) { - argName = "p" + i; - } - - b.append(i > 0 ? " " : "") - .append(argName) - .append("=%s"); - } - - return b.toString(); - } - - /** - * Determine if a given method's iterations should run with a fixed seed or not. - */ - private boolean isConstantSeedForAllIterations(Method method) { - if (testCaseRandomnessOverride != null) - return true; - - Repeat repeat; - if ((repeat = method.getAnnotation(Repeat.class)) != null) { - return repeat.useConstantSeed(); - } - if ((repeat = suiteClass.getAnnotation(Repeat.class)) != null) { - return repeat.useConstantSeed(); - } - - return false; - } - - /** - * Determine method iteration count based on (first declaration order wins): - *
    - *
  • global property {@link SysGlobals#SYSPROP_ITERATIONS}.
  • - *
  • method annotation {@link Repeat}.
  • - *
  • class annotation {@link Repeat}.
  • - *
  • The default (1).
  • - *
      - */ - private int determineMethodIterationCount(Method method) { - // Global override. - if (iterationsOverride != null) - return iterationsOverride; - - Repeat repeat; - if ((repeat = method.getAnnotation(Repeat.class)) != null) { - return repeat.iterations(); - } - if ((repeat = suiteClass.getAnnotation(Repeat.class)) != null) { - return repeat.iterations(); - } - - return DEFAULT_ITERATIONS; - } - - /** - * Determine a given method's initial random seed. - * - * @see Seed - * @see Seeds - */ - private long [] determineMethodSeeds(Method method) { - if (testCaseRandomnessOverride != null) { - return new long [] { testCaseRandomnessOverride.getSeed() }; - } - - // We assign each method a different starting hash based on the global seed - // and a hash of their name (so that the order of methods does not matter, only - // their names). Take into account global override and method and class level - // {@link Seed} annotations. - final long randomSeed = - runnerRandomness.getSeed() ^ MurmurHash3.hash((long) method.getName().hashCode()); - final HashSet seeds = new HashSet(); - - // Check method-level @Seed and @Seeds annotation first. - // They take precedence over anything else. - Seed seed; - if ((seed = method.getAnnotation(Seed.class)) != null) { - for (long s : seedFromAnnot(method, randomSeed)) { - seeds.add(s); - } - } - - // Check a number of seeds on a single method. - Seeds seedsValue = classModel.getAnnotation(method, Seeds.class, true); - if (seedsValue != null) { - for (Seed s : seedsValue.value()) { - if (s.value().equals("random")) - seeds.add(randomSeed); - else { - for (long s2 : SeedUtils.parseSeedChain(s.value())) { - seeds.add(s2); - } - } - } - } - - // Check suite-level override. - if (seeds.isEmpty()) { - if ((seed = suiteClass.getAnnotation(Seed.class)) != null) { - if (!seed.value().equals("random")) { - long [] seedChain = SeedUtils.parseSeedChain(suiteClass.getAnnotation(Seed.class).value()); - if (seedChain.length > 1) - seeds.add(seedChain[1]); - } - } - } - - // If still empty, add the derived random seed. - if (seeds.isEmpty()) { - seeds.add(randomSeed); - } - - long [] result = new long [seeds.size()]; - int i = 0; - for (Long s : seeds) { - result[i++] = s; - } - return result; - } - - /** - * Invoke a given method on a suiteClass instance (can be null for static methods). - */ - void invoke(final Method m, Object instance, Object... args) throws Throwable { - if (!Modifier.isPublic(m.getModifiers())) { - try { - if (!m.isAccessible()) { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - m.setAccessible(true); - return null; - }}); - } - } catch (SecurityException e) { - throw new RuntimeException("There is a non-public method that needs to be called. This requires " + - "ReflectPermission('suppressAccessChecks'). Don't run with the security manager or " + - " add this permission to the runner. Offending method: " + m.toGenericString()); - } - } - - try { - m.invoke(instance, args); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - } - - /** - * Perform additional checks on methods returned from the providers. - */ - private void validateTestMethods(List testMethods) { - HashSet> parents = new HashSet>(); - for (Class c = suiteClass; c != null; c = c.getSuperclass()) { - parents.add(c); - } - - for (Method method : testMethods) { - if (!parents.contains(method.getDeclaringClass())) { - throw new IllegalArgumentException("Test method does not belong to " + - "test suite class hierarchy: " + method.getDeclaringClass() + "#" + - method.getName()); - } - - // * method() - Validation.checkThat(method) - .describedAs("Test method " + suiteClass.getName() + "#" + method.getName()) - .isPublic() - .isNotStatic() - .hasArgsCount(0); - - // No @Test(timeout=...) and @Timeout at the same time. - Test testAnn = classModel.getAnnotation(method, Test.class, true); - if (testAnn != null && testAnn.timeout() > 0 && classModel.isAnnotationPresent(method, Timeout.class, true)) { - throw new IllegalArgumentException("Conflicting @Test(timeout=...) and @Timeout " + - "annotations in: " + suiteClass.getName() + "#" + method.getName()); - } - - // @Seed annotation on test methods must have at most 1 seed value. - Seed seed = classModel.getAnnotation(method, Seed.class, true); - if (seed != null) { - try { - String seedChain = seed.value(); - if (!seedChain.equals("random")) { - long[] chain = SeedUtils.parseSeedChain(seedChain); - if (chain.length > 1) { - throw new IllegalArgumentException("@Seed on methods must contain one seed only (no runner seed)."); - } - } - } catch (IllegalArgumentException e) { - throw new RuntimeException("@Seed annotation invalid on method " - + method.getName() + ", in class " + suiteClass.getName() + ": " - + e.getMessage()); - } - } - } - } - - /** - * Validate methods and hooks in the suiteClass. Follows "standard" JUnit rules, - * with some exceptions on return values and more rigorous checking of shadowed - * methods and fields. - */ - private void validateTarget() { - // Target is accessible (public, concrete, has a parameterless constructor etc). - Validation.checkThat(suiteClass) - .describedAs("Suite class " + suiteClass.getName()) - .isPublic() - .isConcreteClass(); - - // Check constructors. - Constructor [] constructors = suiteClass.getConstructors(); - if (constructors.length != 1 || !Modifier.isPublic(constructors[0].getModifiers())) { - throw new RuntimeException("A test class is expected to have one public constructor " - + " (parameterless or with types matching static @" + ParametersFactory.class - + "-annotated method's output): " + suiteClass.getName()); - } - - // If there is a parameterized constructor, look for a static method that privides parameters. - if (constructors[0].getParameterTypes().length > 0) { - Collection factories = classModel.getAnnotatedLeafMethods(ParametersFactory.class).keySet(); - if (factories.isEmpty()) { - throw new RuntimeException("A test class with a parameterized constructor is expected " - + " to have a static @" + ParametersFactory.class - + "-annotated method: " + suiteClass.getName()); - } - - for (Method m : factories) { - Validation.checkThat(m) - .describedAs("@ParametersFactory method " + suiteClass.getName() + "#" + m.getName()) - .isStatic() - .isPublic() - .hasArgsCount(0) - .hasReturnType(Iterable.class); - } - } - - // @BeforeClass - for (Method method : classModel.getAnnotatedLeafMethods(BeforeClass.class).keySet()) { - Validation.checkThat(method) - .describedAs("@BeforeClass method " + suiteClass.getName() + "#" + method.getName()) - .isStatic() - .hasArgsCount(0); - } - - // @AfterClass - for (Method method : classModel.getAnnotatedLeafMethods(AfterClass.class).keySet()) { - Validation.checkThat(method) - .describedAs("@AfterClass method " + suiteClass.getName() + "#" + method.getName()) - .isStatic() - .hasArgsCount(0); - } - - // @Before - for (Method method : classModel.getAnnotatedLeafMethods(Before.class).keySet()) { - Validation.checkThat(method) - .describedAs("@Before method " + suiteClass.getName() + "#" + method.getName()) - .isNotStatic() - .hasArgsCount(0); - } - - // @After - for (Method method : classModel.getAnnotatedLeafMethods(After.class).keySet()) { - Validation.checkThat(method) - .describedAs("@After method " + suiteClass.getName() + "#" + method.getName()) - .isNotStatic() - .hasArgsCount(0); - } - - // TODO: [GH-214] Validate @Rule fields (what are the "rules" for these anyway?) - } - - /** - * Augment stack trace of the given exception with seed infos. - */ - static T augmentStackTrace(T e, Randomness... seeds) { - if (seeds.length == 0) { - seeds = RandomizedContext.current().getRandomnesses(); - } - - final String seedChain = SeedUtils.formatSeedChain(seeds); - final String existingSeed = seedFromThrowable(e); - if (existingSeed != null && existingSeed.equals(seedChain)) { - return e; - } - - List stack = new ArrayList( - Arrays.asList(e.getStackTrace())); - - stack.add(0, new StackTraceElement(AUGMENTED_SEED_PACKAGE + ".SeedInfo", - "seed", seedChain, 0)); - - e.setStackTrace(stack.toArray(new StackTraceElement [stack.size()])); - return e; - } - - /** - * Collect all annotations from a clazz hierarchy. Superclass's annotations come first. - * {@link Inherited} annotations are removed (hopefully, the spec. isn't clear on this whether - * the same object is returned or not for inherited annotations). - */ - private static List getAnnotationsFromClassHierarchy(Class clazz, Class annotation) { - List anns = new ArrayList(); - IdentityHashMap inherited = new IdentityHashMap(); - for (Class c = clazz; c != Object.class; c = c.getSuperclass()) { - if (c.isAnnotationPresent(annotation)) { - T ann = c.getAnnotation(annotation); - if (ann.annotationType().isAnnotationPresent(Inherited.class) && - inherited.containsKey(ann)) { - continue; - } - anns.add(ann); - inherited.put(ann, ann); - } - } - - Collections.reverse(anns); - return anns; - } - - /** - * Get an annotated element's {@link Seed} annotation and determine if it's fixed - * or not. If it is fixed, return the seeds. Otherwise return randomSeed. - */ - private long [] seedFromAnnot(AnnotatedElement element, long randomSeed) { - Seed seed = element.getAnnotation(Seed.class); - String seedChain = seed.value(); - if (seedChain.equals("random")) { - return new long [] { randomSeed }; - } - - return SeedUtils.parseSeedChain(seedChain); - } - - /** - * Stack trace formatting utilities. These may be initialized to filter out certain packages. - */ - public TraceFormatting getTraceFormatting() { - return traces; - } - - /** - * {@link RandomizedRunner} augments stack traces of test methods that ended in an exception - * and inserts a fake entry starting with {@link #AUGMENTED_SEED_PACKAGE}. - * - * @return A string is returned with seeds combined, if any. Null is returned if no augmentation - * can be found. - */ - public static String seedFromThrowable(Throwable t) { - StringBuilder b = new StringBuilder(); - while (t != null) { - for (StackTraceElement s : t.getStackTrace()) { - if (s.getClassName().startsWith(AUGMENTED_SEED_PACKAGE)) { - if (b.length() > 0) b.append(", "); - b.append(s.getFileName()); - } - } - t = t.getCause(); - } - - if (b.length() == 0) - return null; - else - return b.toString(); - } - - /** - * Attempts to extract just the method name from parameterized notation. - */ - public static String methodName(Description description) { - return description.getMethodName().replaceAll("\\s?\\{.+\\}", ""); - } - - /** - * Returns true if any previous (or current) suite marked with - * {@link Consequence#IGNORE_REMAINING_TESTS} has - * left zombie threads. - */ - public static boolean hasZombieThreads() { - return zombieMarker.get(); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RandomizedTest.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RandomizedTest.java deleted file mode 100644 index fd9d02ab..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RandomizedTest.java +++ /dev/null @@ -1,891 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.io.Closeable; -import java.io.IOException; -import java.net.ServerSocket; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.nio.file.*; -import java.nio.file.attribute.BasicFileAttributes; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Random; -import java.util.TimeZone; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Supplier; - -import org.junit.Assume; -import org.junit.AssumptionViolatedException; -import org.junit.runner.RunWith; - -import com.carrotsearch.randomizedtesting.annotations.Listeners; -import com.carrotsearch.randomizedtesting.annotations.Nightly; -import com.carrotsearch.randomizedtesting.annotations.SuppressForbidden; -import com.carrotsearch.randomizedtesting.generators.BiasedNumbers; -import com.carrotsearch.randomizedtesting.generators.RandomBytes; -import com.carrotsearch.randomizedtesting.generators.RandomNumbers; -import com.carrotsearch.randomizedtesting.generators.RandomPicks; -import com.carrotsearch.randomizedtesting.generators.RandomStrings; - -/** - * Common scaffolding for subclassing randomized tests. - * - * @see Listeners - * @see RandomizedContext - */ -@RunWith(RandomizedRunner.class) -public class RandomizedTest { - /** - * The global multiplier property (Double). - * - * @see #multiplier() - */ - public static final String SYSPROP_MULTIPLIER = "randomized.multiplier"; - - /* Commonly used charsets (these must be supported by every JVM). */ - - protected static final Charset UTF8 = StandardCharsets.UTF_8; - protected static final Charset UTF16 = StandardCharsets.UTF_16; - protected static final Charset ISO8859_1 = StandardCharsets.ISO_8859_1; - protected static final Charset US_ASCII = StandardCharsets.US_ASCII; - - /* This charset does not need to be supported, but I don't know any JVM under which it wouldn't be. */ - - protected static final Charset UTF32 = Charset.forName("UTF-32"); - - /** - * Default multiplier. - * - * @see #SYSPROP_MULTIPLIER - */ - private static final double DEFAULT_MULTIPLIER = 1.0d; - - /** - * Shortcut for {@link RandomizedContext#current()}. - */ - public static RandomizedContext getContext() { - return RandomizedContext.current(); - } - - /** - * Returns true if {@link Nightly} test group is enabled. - * - * @see Nightly - */ - public static boolean isNightly() { - return getContext().isNightly(); - } - - /** - * Shortcut for {@link RandomizedContext#getRandom()}. Even though this method - * is static, it returns per-thread {@link Random} instance, so no race conditions - * can occur. - * - *

      It is recommended that specific methods are used to pick random values. - */ - public static Random getRandom() { - return getContext().getRandom(); - } - - // - // Random value pickers. Shortcuts to methods in {@link #getRandom()} mostly. - // - - public static boolean randomBoolean() { return getRandom().nextBoolean(); } - public static byte randomByte() { return (byte) getRandom().nextInt(); } - public static short randomShort() { return (short) getRandom().nextInt(); } - public static int randomInt() { return getRandom().nextInt(); } - public static float randomFloat() { return getRandom().nextFloat(); } - public static double randomDouble() { return getRandom().nextDouble(); } - public static long randomLong() { return getRandom().nextLong(); } - - /** @see Random#nextGaussian() */ - public static double randomGaussian() { return getRandom().nextGaussian(); } - - // - // Biased value pickers. - // - - /** - * A biased "evil" random float between min and max (inclusive). - * - * @see BiasedNumbers#randomFloatBetween(Random, float, float) - */ - public static float biasedFloatBetween(float min, float max) { return BiasedNumbers.randomFloatBetween(getRandom(), min, max); } - - /** - * A biased "evil" random double between min and max (inclusive). - * - * @see BiasedNumbers#randomDoubleBetween(Random, double, double) - */ - public static double biasedDoubleBetween(double min, double max) { return BiasedNumbers.randomDoubleBetween(getRandom(), min, max); } - - // - // Delegates to RandomBytes. - // - - /** - * Returns a byte array with random content. - * - * @param length The length of the byte array. Can be zero. - * @return Returns a byte array with random content. - */ - public static byte[] randomBytesOfLength(int length) { - return RandomBytes.randomBytesOfLength(new Random(getRandom().nextLong()), length); - } - - /** - * Returns a byte array with random content. - * - * @param minLength The minimum length of the byte array. Can be zero. - * @param maxLength The maximum length of the byte array. Can be zero. - * @return Returns a byte array with random content. - */ - public static byte[] randomBytesOfLength(int minLength, int maxLength) { - return RandomBytes.randomBytesOfLengthBetween(new Random(getRandom().nextLong()), minLength, maxLength); - } - - // - // Delegates to RandomNumbers. - // - - /** - * A random integer from 0..max (inclusive). - */ - @Deprecated - public static int randomInt(int max) { - return RandomNumbers.randomIntBetween(getRandom(), 0, max); - } - - /** - * A random long from 0..max (inclusive). - */ - @Deprecated - public static long randomLong(long max) { - return RandomNumbers.randomLongBetween(getRandom(), 0, max); - } - - /** - * A random integer from min to max (inclusive). - * - * @see #scaledRandomIntBetween(int, int) - */ - public static int randomIntBetween(int min, int max) { - return RandomNumbers.randomIntBetween(getRandom(), min, max); - } - - /** - * An alias for {@link #randomIntBetween(int, int)}. - * - * @see #scaledRandomIntBetween(int, int) - */ - public static int between(int min, int max) { - return randomIntBetween(min, max); - } - - /** - * A random long from min to max (inclusive). - */ - public static long randomLongBetween(long min, long max) { - return RandomNumbers.randomLongBetween(getRandom(), min, max); - } - - /** - * An alias for {@link #randomLongBetween}. - */ - public static long between(long min, long max) { - return randomLongBetween(min, max); - } - - /** - * Returns a random value greater or equal to min. The value - * picked is affected by {@link #isNightly()} and {@link #multiplier()}. - * - * @see #scaledRandomIntBetween(int, int) - */ - public static int atLeast(int min) { - if (min < 0) throw new IllegalArgumentException("atLeast requires non-negative argument: " + min); - return scaledRandomIntBetween(min, Integer.MAX_VALUE); - } - - /** - * Returns a non-negative random value smaller or equal max. The value - * picked is affected by {@link #isNightly()} and {@link #multiplier()}. - * - *

      This method is effectively an alias to: - *

      -   * scaledRandomIntBetween(0, max)
      -   * 
      - * - * @see #scaledRandomIntBetween(int, int) - */ - public static int atMost(int max) { - if (max < 0) throw new IllegalArgumentException("atMost requires non-negative argument: " + max); - return scaledRandomIntBetween(0, max); - } - - /** - * Rarely returns true in about 10% of all calls (regardless of the - * {@link #isNightly()} mode). - */ - public static boolean rarely() { - return randomInt(100) >= 90; - } - - /** - * The exact opposite of {@link #rarely()}. - */ - public static boolean frequently() { - return !rarely(); - } - - // - // Delegates to RandomPicks - // - - /** - * Pick a random object from the given array. The array must not be empty. - */ - public static T randomFrom(T [] array) { - return RandomPicks.randomFrom(getRandom(), array); - } - - /** - * Pick a random object from the given list. - */ - public static T randomFrom(List list) { - return RandomPicks.randomFrom(getRandom(), list); - } - - public static byte randomFrom(byte [] array) { return RandomPicks.randomFrom(getRandom(), array); } - public static short randomFrom(short [] array) { return RandomPicks.randomFrom(getRandom(), array); } - public static int randomFrom(int [] array) { return RandomPicks.randomFrom(getRandom(), array); } - public static char randomFrom(char [] array) { return RandomPicks.randomFrom(getRandom(), array); } - public static float randomFrom(float [] array) { return RandomPicks.randomFrom(getRandom(), array); } - public static long randomFrom(long [] array) { return RandomPicks.randomFrom(getRandom(), array); } - public static double randomFrom(double [] array) { return RandomPicks.randomFrom(getRandom(), array); } - - // - // "multiplied" or scaled value pickers. These will be affected by global multiplier. - // - - /** - * A multiplier can be used to linearly scale certain values. It can be used to make data - * or iterations of certain tests "heavier" for nightly runs, for example. - * - *

      The default multiplier value is 1.

      - * - * @see #SYSPROP_MULTIPLIER - */ - public static double multiplier() { - checkContext(); - return systemPropertyAsDouble(SYSPROP_MULTIPLIER, DEFAULT_MULTIPLIER); - } - - /** - * Returns a "scaled" number of iterations for loops which can have a variable - * iteration count. This method is effectively - * an alias to {@link #scaledRandomIntBetween(int, int)}. - */ - public static int iterations(int min, int max) { - return scaledRandomIntBetween(min, max); - } - - /** - * Returns a "scaled" random number between min and max (inclusive). The number of - * iterations will fall between [min, max], but the selection will also try to - * achieve the points below: - *
        - *
      • the multiplier can be used to move the number of iterations closer to min - * (if it is smaller than 1) or closer to max (if it is larger than 1). Setting - * the multiplier to 0 will always result in picking min.
      • - *
      • on normal runs, the number will be closer to min than to max.
      • - *
      • on nightly runs, the number will be closer to max than to min.
      • - *
      - * - * @see #multiplier() - * - * @param min Minimum (inclusive). - * @param max Maximum (inclusive). - * @return Returns a random number between min and max. - */ - public static int scaledRandomIntBetween(int min, int max) { - if (min < 0) throw new IllegalArgumentException("min must be >= 0: " + min); - if (min > max) throw new IllegalArgumentException("max must be >= min: " + min + ", " + max); - - double point = Math.min(1, Math.abs(randomGaussian()) * 0.3) * multiplier(); - double range = max - min; - int scaled = (int) Math.round(Math.min(point * range, range)); - if (isNightly()) { - return max - scaled; - } else { - return min + scaled; - } - } - - // Methods to help with I/O and environment. - - /** - * @see #globalTempDir() - */ - private static Path globalTempDir; - - /** */ - private static AtomicInteger tempSubFileNameCount = new AtomicInteger(0); - - /** - * Global temporary directory created for the duration of this class's lifespan. If - * multiple class loaders are used, there may be more global temp dirs, but it - * shouldn't really be the case in practice. - */ - public static Path globalTempDir() throws IOException { - checkContext(); - synchronized (RandomizedTest.class) { - if (globalTempDir == null) { - String tempDirPath = System.getProperty("java.io.tmpdir"); - if (tempDirPath == null) - throw new IOException("No property java.io.tmpdir?"); - - Path tempDir = Paths.get(tempDirPath); - if (!Files.isDirectory(tempDir) || !Files.isWritable(tempDir)) { - throw new IOException("Temporary folder not accessible: " + tempDir.toAbsolutePath()); - } - - globalTempDir = createTemp(tempDir, true, () -> { - SimpleDateFormat tsFormat = new SimpleDateFormat("'tests-'yyyyMMddHHmmss'-'SSS", Locale.ROOT); - return tsFormat.format(new Date()); - }); - - Runtime.getRuntime().addShutdownHook(new Thread() { - @SuppressForbidden("Legitimate use of syserr.") - public void run() { - try { - rmDir(globalTempDir); - } catch (IOException e) { - // Not much else to do but to log and quit. - System.err.println("Could not delete global temporary folder: " - + globalTempDir.toAbsolutePath() + ". Cause: "); - e.printStackTrace(System.err); - } - } - }); - } - return globalTempDir; - } - } - - private static Path createTemp(Path parent, boolean dir, Supplier nameSupplier) throws IOException { - int retries = 10; - Path target; - do { - try { - Path candidate = parent.resolve(nameSupplier.get()); - if (dir) { - target = Files.createDirectory(candidate); - } else { - target = Files.createFile(candidate); - } - break; - } catch (FileAlreadyExistsException e) { - if (--retries < 0) { - throw new IOException("Could not create a unique temporary folder under: " + parent); - } - try { - Thread.sleep(new Random().nextInt(250)); - } catch (InterruptedException ex) { - throw new IOException(ex); - } - } - } while (true); - return target; - } - - /** - * Creates a new temporary directory for the {@link LifecycleScope#TEST} duration. - * - * @see #globalTempDir() - */ - public Path newTempDir() throws IOException { - return newTempDir(LifecycleScope.TEST); - } - - /** - * Creates a temporary directory, deleted after the given lifecycle phase. - * Temporary directory is created relative to a globally picked temporary directory. - */ - public static Path newTempDir(LifecycleScope scope) throws IOException { - checkContext(); - synchronized (RandomizedTest.class) { - Path tempDir = createTemp(globalTempDir(), true, RandomizedTest::nextTempName); - getContext().closeAtEnd(new TempPathResource(tempDir), scope); - return tempDir; - } - } - - /** - * Registers a {@link Closeable} resource that should be closed after the test - * completes. - * - * @return resource (for call chaining). - */ - public T closeAfterTest(T resource) { - return getContext().closeAtEnd(resource, LifecycleScope.TEST); - } - - /** - * Registers a {@link Closeable} resource that should be closed after the suite - * completes. - * - * @return resource (for call chaining). - */ - public static T closeAfterSuite(T resource) { - return getContext().closeAtEnd(resource, LifecycleScope.SUITE); - } - - /** - * Creates a new temporary file for the {@link LifecycleScope#TEST} duration. - */ - public Path newTempFile() throws IOException { - return newTempFile(LifecycleScope.TEST); - } - - /** - * Creates a new temporary file deleted after the given lifecycle phase completes. - * The file is physically created on disk, but is not locked or opened. - */ - public static Path newTempFile(LifecycleScope scope) throws IOException { - checkContext(); - synchronized (RandomizedTest.class) { - Path tempFile = createTemp(globalTempDir(), false, RandomizedTest::nextTempName); - getContext().closeAtEnd(new TempPathResource(tempFile), scope); - return tempFile; - } - } - - /** Next temporary filename. */ - protected static String nextTempName() { - return String.format(Locale.ROOT, "%04d has-space", tempSubFileNameCount.getAndIncrement()); - } - - /** - * Recursively delete a folder. Throws an exception if any failure occurs. - * - * @param path Path to the folder to be (recursively) deleted. The folder must - * exist. - */ - public static void rmDir(Path path) throws IOException { - if (!Files.isDirectory(path)) { - throw new IOException("Not a folder: " + path); - } - - try { - Files.walkFileTree(path, new SimpleFileVisitor() { - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException iterationError) throws IOException { - if (iterationError != null) { - throw iterationError; - } - Files.delete(dir); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Files.delete(file); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed(Path file, IOException e) throws IOException { - throw e; - } - }); - } catch (IOException e) { - throw new IOException("Could not remove directory: " + path, e); - } - } - - /** - * Assign a temporary server socket. If you need a temporary port one can - * assign a server socket and close it immediately, just to acquire its port - * number. - * - * @param scope - * The lifecycle scope to close the socket after. If the socket is - * closed earlier, nothing happens (silently dropped). - */ - public static ServerSocket newServerSocket(LifecycleScope scope) throws IOException { - final ServerSocket socket = new ServerSocket(0); - getContext().closeAtEnd(new Closeable() { - public void close() throws IOException { - if (!socket.isClosed()) - socket.close(); - } - }, scope); - - return socket; - } - - /** - * Return a random Locale from the available locales on the system. - * - *

      Warning: This test assumes the returned array of locales is repeatable from jvm execution - * to jvm execution. It _may_ be different from jvm to jvm and as such, it can render - * tests execute in a different way.

      - */ - public static Locale randomLocale() { - Locale[] availableLocales = Locale.getAvailableLocales(); - Arrays.sort(availableLocales, new Comparator() { - public int compare(Locale o1, Locale o2) { - return o1.toString().compareTo(o2.toString()); - } - }); - return randomFrom(availableLocales); - } - - /** - * Return a random TimeZone from the available timezones on the system. - * - *

      Warning: This test assumes the returned array of time zones is repeatable from jvm execution - * to jvm execution. It _may_ be different from jvm to jvm and as such, it can render - * tests execute in a different way.

      - */ - public static TimeZone randomTimeZone() { - final String[] availableIDs = TimeZone.getAvailableIDs(); - Arrays.sort(availableIDs); - return TimeZone.getTimeZone(randomFrom(availableIDs)); - } - - // - // Characters and strings. Delegates to RandomStrings and that in turn to StringGenerators. - // - - /** - * @deprecated Use {@link #randomAsciiLettersOfLengthBetween} instead. - */ - @Deprecated - public static String randomAsciiOfLengthBetween(int minCodeUnits, int maxCodeUnits) { - return randomAsciiLettersOfLengthBetween(minCodeUnits, maxCodeUnits); - } - - /** - * @deprecated Use {@link #randomAsciiLettersOfLength} instead. - */ - @Deprecated - public static String randomAsciiOfLength(int codeUnits) { - return randomAsciiLettersOfLength(codeUnits); - } - - /** - * @see RandomStrings#randomAsciiLettersOfLengthBetween - */ - public static String randomAsciiLettersOfLengthBetween(int minLetters, int maxLetters) { - return RandomStrings.randomAsciiLettersOfLengthBetween(getRandom(), minLetters, maxLetters); - } - - /** - * @see RandomStrings#randomAsciiLettersOfLength - */ - public static String randomAsciiLettersOfLength(int codeUnits) { - return RandomStrings.randomAsciiLettersOfLength(getRandom(), codeUnits); - } - - /** - * @see RandomStrings#randomAsciiAlphanumOfLengthBetween - */ - public static String randomAsciiAlphanumOfLengthBetween(int minCodeUnits, int maxCodeUnits) { - return RandomStrings.randomAsciiAlphanumOfLengthBetween(getRandom(), minCodeUnits, maxCodeUnits); - } - - /** - * @see RandomStrings#randomAsciiAlphanumOfLength - */ - public static String randomAsciiAlphanumOfLength(int codeUnits) { - return RandomStrings.randomAsciiAlphanumOfLength(getRandom(), codeUnits); - } - - /** - * @see RandomStrings#randomUnicodeOfLengthBetween - */ - public static String randomUnicodeOfLengthBetween(int minCodeUnits, int maxCodeUnits) { - return RandomStrings.randomUnicodeOfLengthBetween(getRandom(), - minCodeUnits, maxCodeUnits); - } - - /** - * @see RandomStrings#randomUnicodeOfLength - */ - public static String randomUnicodeOfLength(int codeUnits) { - return RandomStrings.randomUnicodeOfLength(getRandom(), codeUnits); - } - - /** - * @see RandomStrings#randomUnicodeOfCodepointLengthBetween - */ - public static String randomUnicodeOfCodepointLengthBetween(int minCodePoints, int maxCodePoints) { - return RandomStrings.randomUnicodeOfCodepointLengthBetween(getRandom(), - minCodePoints, maxCodePoints); - } - - /** - * @see RandomStrings#randomUnicodeOfCodepointLength - */ - public static String randomUnicodeOfCodepointLength(int codePoints) { - return RandomStrings.randomUnicodeOfCodepointLength(getRandom(), codePoints); - } - - /** - * @see RandomStrings#randomRealisticUnicodeOfLengthBetween - */ - public static String randomRealisticUnicodeOfLengthBetween(int minCodeUnits, int maxCodeUnits) { - return RandomStrings.randomRealisticUnicodeOfLengthBetween(getRandom(), - minCodeUnits, maxCodeUnits); - } - - /** - * @see RandomStrings#randomRealisticUnicodeOfLength - */ - public static String randomRealisticUnicodeOfLength(int codeUnits) { - return RandomStrings.randomRealisticUnicodeOfLength(getRandom(), codeUnits); - } - - /** - * @see RandomStrings#randomRealisticUnicodeOfCodepointLengthBetween - */ - public static String randomRealisticUnicodeOfCodepointLengthBetween( - int minCodePoints, int maxCodePoints) { - return RandomStrings.randomRealisticUnicodeOfCodepointLengthBetween( - getRandom(), minCodePoints, maxCodePoints); - } - - /** - * @see RandomStrings#randomRealisticUnicodeOfCodepointLength - */ - public static String randomRealisticUnicodeOfCodepointLength(int codePoints) { - return RandomStrings.randomRealisticUnicodeOfCodepointLength(getRandom(), - codePoints); - } - - /** - * This is an absolutely hacky utility to take a vararg as input and return the array - * of arguments as output. The name is a dollar for brevity, idea borrowed from - * http://code.google.com/p/junitparams/. - */ - public static Object [] $(Object... objects) { - return objects; - } - - /** - * @see #$ - */ - public static Object [][] $$(Object[]... objects) { - return objects; - } - - // - // wrappers for utility methods elsewhere that don't require try..catch blocks - // and rethrow the original checked exception if needed. dirty a bit, but saves - // keystrokes... - // - - /** - * Same as {@link Thread#sleep(long)}. - */ - public static void sleep(long millis) { - try { - Thread.sleep(millis); - } catch (InterruptedException e) { - Rethrow.rethrow(e); - } - } - - // - // Extensions of Assume (with a message). - // - - /** - * Making {@link Assume#assumeTrue(boolean)} directly available. - */ - public static void assumeTrue(boolean condition) { - Assume.assumeTrue(condition); - } - - /** - * Reverse of {@link #assumeTrue(boolean)}. - */ - public static void assumeFalse(boolean condition) { - assumeTrue(!condition); - } - - /** - * Making {@link Assume#assumeNotNull(Object...)} directly available. - */ - public static void assumeNotNull(Object... objects) { - Assume.assumeNotNull(objects); - } - - /** - * @param condition - * If false an {@link AssumptionViolatedException} is - * thrown by this method and the test case (should be) ignored (or - * rather technically, flagged as a failure not passing a certain - * assumption). Tests that are assumption-failures do not break - * builds (again: typically). - * @param message - * Message to be included in the exception's string. - */ - public static void assumeTrue(String message, boolean condition) { - if (!condition) { - // @see {@link Rants#RANT_2}. - throw new AssumptionViolatedException(message); - } - } - - /** - * Reverse of {@link #assumeTrue(String, boolean)}. - */ - public static void assumeFalse(String message, boolean condition) { - assumeTrue(message, !condition); - } - - /** - * Assume t is null. - */ - public static void assumeNoException(String msg, Throwable t) { - if (t != null) { - // This does chain the exception as the cause. - throw new AssumptionViolatedException(msg, t); - } - } - - /** - * Making {@link Assume#assumeNoException(Throwable)} directly available. - */ - public static void assumeNoException(Throwable t) { - Assume.assumeNoException(t); - } - - // - // System properties and their conversion to common types, with defaults. - // - - /** - * Get a system property and convert it to a double, if defined. Otherwise, return the default value. - */ - public static double systemPropertyAsDouble(String propertyName, double defaultValue) { - String v = System.getProperty(propertyName); - if (v != null && !v.trim().isEmpty()) { - try { - return Double.parseDouble(v.trim()); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Double value expected for property " + - propertyName + ": " + v, e); - } - } else { - return defaultValue; - } - } - - /** - * Get a system property and convert it to a float, if defined. Otherwise, return the default value. - */ - public static float systemPropertyAsFloat(String propertyName, float defaultValue) { - String v = System.getProperty(propertyName); - if (v != null && !v.trim().isEmpty()) { - try { - return Float.parseFloat(v.trim()); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Float value expected for property " + - propertyName + ": " + v, e); - } - } else { - return defaultValue; - } - } - - /** - * Get a system property and convert it to an int, if defined. Otherwise, return the default value. - */ - public static int systemPropertyAsInt(String propertyName, int defaultValue) { - String v = System.getProperty(propertyName); - if (v != null && !v.trim().isEmpty()) { - try { - return Integer.parseInt(v.trim()); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Integer value expected for property " + - propertyName + ": " + v, e); - } - } else { - return defaultValue; - } - } - - /** - * Get a system property and convert it to a long, if defined. Otherwise, return the default value. - */ - public static float systemPropertyAsLong(String propertyName, int defaultValue) { - String v = System.getProperty(propertyName); - if (v != null && !v.trim().isEmpty()) { - try { - return Long.parseLong(v.trim()); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Long value expected for property " + - propertyName + ": " + v, e); - } - } else { - return defaultValue; - } - } - - /** Boolean constants mapping. */ - @SuppressWarnings("serial") - private final static HashMap BOOLEANS = new HashMap() {{ - put( "true", true); put( "false", false); - put( "on", true); put( "off", false); - put( "yes", true); put( "no", false); - put("enabled", true); put("disabled", false); - }}; - - /** - * Get a system property and convert it to a boolean, if defined. This method returns - * true if the property exists an is set to any of the following strings - * (case-insensitive): true, on, yes, enabled. - * - *

      false is returned if the property exists and is set to any of the - * following strings (case-insensitive): - * false, off, no, disabled. - */ - public static boolean systemPropertyAsBoolean(String propertyName, boolean defaultValue) { - String v = System.getProperty(propertyName); - - if (v != null && !v.trim().isEmpty()) { - v = v.trim(); - Boolean result = BOOLEANS.get(v); - if (result != null) - return result.booleanValue(); - else - throw new IllegalArgumentException("Boolean value expected for property " + - propertyName + " " + - "(true/false, on/off, enabled/disabled, yes/no): " + v); - } else { - return defaultValue; - } - } - - // - // Miscellaneous infrastructure. - // - - /** - * Ensures we're running with an initialized {@link RandomizedContext}. - */ - private static void checkContext() { - // Will throw an exception if not available. - RandomizedContext.current(); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Randomness.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Randomness.java deleted file mode 100644 index 44aa65d6..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Randomness.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.Random; - -/** - * Per-thread, per-lifecycle state randomness defined as an initial seed and - * the current Random instance. - * - *

      An instance of this class will be typically available from {@link RandomizedContext}. - * No need to instantiate manually. - * - * @see RandomizedContext - */ -public final class Randomness { - private final long seed; - private final Random random; - - private final RandomSupplier supplier; - private final SeedDecorator[] decorators; - - public Randomness(Thread owner, RandomSupplier supplier, long seed, SeedDecorator... decorators) { - this.seed = seed; - this.decorators = decorators; - this.supplier = supplier; - - Random delegate = supplier.get(decorate(seed, decorators)); - if (AssertingRandom.isVerifying()) { - this.random = new AssertingRandom(owner, delegate); - } else { - this.random = delegate; - } - } - - public Randomness(long seed, RandomSupplier supplier, SeedDecorator...decorators) { - this(Thread.currentThread(), supplier, seed, decorators); - } - - /** Random instance for this randomness. */ - public Random getRandom() { - return random; - } - - RandomSupplier getRandomSupplier() { - return supplier; - } - - SeedDecorator[] getDecorators() { - return decorators; - } - - Randomness clone(Thread newOwner) { - return new Randomness(newOwner, supplier, seed, decorators); - } - - @Override - public String toString() { - return "[Randomness, seed=" + SeedUtils.formatSeedChain(this) + "]"; - } - - /** - * Invalidate the underling randomness. - */ - void destroy() { - if (random instanceof AssertingRandom) { - ((AssertingRandom) random).destroy(); - } - } - - /** Starting seed, read-only for tests. */ - long getSeed() { - return seed; - } - - /** - * Decorate a given seed. - */ - private static long decorate(long seed, SeedDecorator[] decorators) { - for (SeedDecorator decorator : decorators) { - seed = decorator.decorate(seed); - } - return seed; - } -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Rants.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Rants.java deleted file mode 100644 index d3faf56c..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Rants.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.lang.reflect.Method; - -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; - -/** - * Rants about blocker limitations of JUnit... - */ -final class Rants { - enum RantType { - // General - ANNOYANCE, - DAMN_TERRIBLE, - WTF, - - // Personal - ISHOULDHAVEBECOMEALAWYER - } - - /** - * This if freaking dumb... there's absolutely no way to carry test class/ test name - * separately from the display name, so we can't easily include seed info on the test - * case. If we do, Eclipse complains it cannot find the target class/ test name. If we don't, - * Eclipse's JUnit runner gets confused and doesn't show test case execution properly. - * - * We can't even use a proxy or a subclass because Description has a private constructor. Eh. - * - * Having a Description properly indicate the test case/ class is useful because we could re-run - * a concrete repetition of a given test from the UI. Currently this is impossible - we can - * re-run the entire iteration sequence only (or fix the seed on the method, but this requires - * changes to the code). - */ - public static RantType RANT_1 = RantType.DAMN_TERRIBLE; - - /** - * Default assumption methods (and constructors in AssumptionViolatedException) - * do not allow specifying a custom message? - */ - public static RantType RANT_2 = RantType.ANNOYANCE; - - /** - * Why is failed assumption propagated as a Failure? This is weird an unnatural. - */ - public static RantType RANT_3 = RantType.DAMN_TERRIBLE; - - /** - * JUnit is inconsistent in how it treats annotations on methods. Some of them are "inherited" and - * some require presence on the exact same {@link Method} as the one used for testing. This has awkward - * side effects, for example {@link Ignore} and {@link Test} must co-exist on the same method, not - * on virtual method hierarchy. You cannot make {@link Test} methods protected and publish them in - * subclasses. Shadowing of {@link BeforeClass} methods is inconsistent (non-annotated shadowed method - * will not be called, shadowed method annotated with {@link BeforeClass} prevents the shadowed method - * from being called), etc. - */ - public static RantType RANT_4 = RantType.DAMN_TERRIBLE; -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ReproduceErrorMessageBuilder.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ReproduceErrorMessageBuilder.java deleted file mode 100644 index a2c39bad..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ReproduceErrorMessageBuilder.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.Arrays; - -import org.junit.runner.Description; - -import static com.carrotsearch.randomizedtesting.SysGlobals.*; -import static com.carrotsearch.randomizedtesting.RandomizedRunner.*; - -// TODO: [GH-212]: how to provide better reproduce messages (especially with -// external runner tasks that provide system properties, jvm options, etc?) - -/** - * A builder for constructing "reproduce with" message. - * - * @see #appendAllOpts(Description) - */ -public class ReproduceErrorMessageBuilder { - private final StringBuilder b; - - public ReproduceErrorMessageBuilder() { - this(new StringBuilder()); - } - - public ReproduceErrorMessageBuilder(StringBuilder builder) { - this.b = builder; - } - - /** - * Append all JVM options that may help in reproducing the error. Options are - * appended to the provided StringBuilder in the "command-line" syntax of: - *

      -   * -Doption="value"
      -   * 
      - * - * @param description Suite or test description. - */ - public ReproduceErrorMessageBuilder appendAllOpts(Description description) { - RandomizedContext ctx = null; - try { - ctx = RandomizedContext.current(); - appendOpt(SYSPROP_RANDOM_SEED(), ctx.getRunnerSeedAsString()); - } catch (IllegalStateException e) { - logger.warning("No context available when dumping reproduce options?"); - } - - if (description.getClassName() != null) { - appendOpt(SYSPROP_TESTCLASS(), description.getClassName()); - } - - if (description.getMethodName() != null) { - appendOpt(SYSPROP_TESTMETHOD(), methodName(description)); - } - - appendRunnerProperties(); - appendTestGroupOptions(ctx); - appendEnvironmentSettings(); - - return this; - } - - public ReproduceErrorMessageBuilder appendEnvironmentSettings() { - for (String sysPropName : Arrays.asList( - "file.encoding", "user.timezone")) { - if (emptyToNull(System.getProperty(sysPropName)) != null) { - appendOpt(sysPropName, System.getProperty(sysPropName)); - } - } - return this; - } - - public ReproduceErrorMessageBuilder appendTestGroupOptions(RandomizedContext ctx) { - if (ctx != null) { - ctx.getGroupEvaluator().appendGroupFilteringOptions(this); - } - return this; - } - - public ReproduceErrorMessageBuilder appendRunnerProperties() { - appendOpt(SYSPROP_PREFIX(), CURRENT_PREFIX()); - for (String sysPropName : Arrays.asList( - SYSPROP_STACKFILTERING(), - SYSPROP_ITERATIONS(), - SYSPROP_KILLATTEMPTS(), - SYSPROP_KILLWAIT(), - SYSPROP_TIMEOUT())) { - if (System.getProperty(sysPropName) != null) { - appendOpt(sysPropName, System.getProperty(sysPropName)); - } - } - return this; - } - - /** - * Append a single VM option. - */ - public ReproduceErrorMessageBuilder appendOpt(String sysPropName, String value) { - if (b.length() > 0) { - b.append(" "); - } - - b.append("-D").append(sysPropName).append("=").append(value); - return this; - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ResourceDisposalError.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ResourceDisposalError.java deleted file mode 100644 index b593aaa0..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ResourceDisposalError.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -/** - * Thrown when a resource could not be released. - * - * @see RandomizedContext#closeAtEnd(java.io.Closeable, LifecycleScope) - */ -@SuppressWarnings("serial") -class ResourceDisposalError extends Error { - public ResourceDisposalError(String msg, Throwable cause) { - super(msg, cause); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Rethrow.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Rethrow.java deleted file mode 100644 index afe9b427..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Rethrow.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -/** - * Rethrowing checked exceptions as unchecked ones. Eh, it is sometimes useful... - */ -public final class Rethrow { - /** - * Classy puzzler to rethrow any checked exception as an unchecked one. - */ - @SuppressWarnings("all") - private static class Rethrower { - private void rethrow(Throwable t) throws T { - throw (T) t; - } - } - - /** - * Rethrows t (identical object). - */ - public static RuntimeException rethrow(Throwable t) { - new Rethrower().rethrow(t); - // Inaccessible. - return null; - } -} - diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RunnerContainer.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RunnerContainer.java deleted file mode 100644 index 0f884a28..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RunnerContainer.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -/** - * What kind of container are we in? Unfortunately we need to adjust - * to some "assumptions" containers make about runners. - */ -enum RunnerContainer { - ECLIPSE, - IDEA, - UNKNOWN -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RunnerThreadGroup.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RunnerThreadGroup.java deleted file mode 100644 index 9e51e7b7..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/RunnerThreadGroup.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -/** - * A {@link ThreadGroup} under which all tests (and hooks) are executed. Theoretically, there - * should be no thread outside of this group's control. - */ -final class RunnerThreadGroup extends ThreadGroup { - /* */ - RunnerThreadGroup(String name) { - super(name); - } - - /** - * Capture all uncaught exceptions from this group's threads. - */ - @Override - public void uncaughtException(Thread t, Throwable e) { - // Try to get the context for this thread and augment the exception with the seed. - try { - e = RandomizedRunner.augmentStackTrace(e); - } catch (IllegalArgumentException ignore) { - // Very likely the randomized context has been destroyed. Don't try to augment the exception. - e.addSuppressed(ignore); - } catch (Throwable ignore) { - e.addSuppressed(ignore); - } - - super.uncaughtException(t, e); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/SeedDecorator.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/SeedDecorator.java deleted file mode 100644 index ffb466a7..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/SeedDecorator.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import com.carrotsearch.randomizedtesting.annotations.SeedDecorators; - -/** - * This is an advanced feature. See {@link SeedDecorators} annotation. - */ -public interface SeedDecorator { - /** - * Called once after instantiation to set up the decorator. - */ - void initialize(Class suiteClass); - - /** - * Called to decorate the initial seed for a {@link Randomness}. - */ - long decorate(long seed); -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/SeedUtils.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/SeedUtils.java deleted file mode 100644 index 6b47c7c9..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/SeedUtils.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -/** - * Utilities for parsing random seeds. - */ -public final class SeedUtils { - private final static char [] HEX = "0123456789ABCDEF".toCharArray(); - - private SeedUtils() {} - - /** - * Parse a single seed. The seed needs to be cleaned up from any surrounding characters. - */ - public static long parseSeed(String seed) { - long result = 0; - for (char chr : seed.toCharArray()) { - chr = Character.toLowerCase(chr); - result = result << 4; - if (chr >= '0' && chr <= '9') - result |= (chr - '0'); - else if (chr >= 'a' && chr <= 'f') - result |= (chr - 'a' + 10); - else - throw new IllegalArgumentException("Expected hexadecimal seed: " + seed); - } - return result; - } - - /** - * Format a single seed. - */ - public static String formatSeed(long seed) { - StringBuilder b = new StringBuilder(); - do { - b.append(HEX[(int) (seed & 0xF)]); - seed = seed >>> 4; - } while (seed != 0); - return b.reverse().toString(); - } - - /** - * Parse a seed chain formatted with {@link SeedUtils#formatSeedChain(Randomness...)}. - */ - public static long [] parseSeedChain(String chain) { - chain = chain.replaceAll("[\\[\\]]", ""); - if (!chain.matches("[0-9A-Fa-f\\:]+")) { - throw new IllegalArgumentException("Not a valid seed chain: " + chain); - } - String [] splits = chain.split("[\\:]"); - long [] longs = new long [splits.length]; - for (int i = 0; i < splits.length; i++) - longs[i] = parseSeed(splits[i]); - return longs; - } - - /** - * Formats randomness seed or seeds into something the user can type in to get predictably repeatable - * execution. - */ - public static String formatSeedChain(Randomness... randomnesses) { - StringBuilder b = new StringBuilder(); - b.append("["); - for (int i = 0; i < randomnesses.length; i++) { - if (i > 0) b.append(":"); - b.append(formatSeed(randomnesses[i].getSeed())); - } - b.append("]"); - return b.toString(); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/StackTraceHolder.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/StackTraceHolder.java deleted file mode 100644 index 8d4b606a..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/StackTraceHolder.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -/** - * This is never thrown. The only purpose it serves it to carry chained stack traces - * for informational purposes. - */ -@SuppressWarnings("serial") -final class StackTraceHolder extends Throwable { - public StackTraceHolder(String message) { - super(message); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/SysGlobals.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/SysGlobals.java deleted file mode 100644 index 471361cd..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/SysGlobals.java +++ /dev/null @@ -1,235 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.junit.runners.JUnit4; - -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.Seeds; -import com.carrotsearch.randomizedtesting.rules.RequireAssertionsRule; - -/** - * Global names for system properties controlling the behavior of {@link JUnit4} ANT task - * and {@link RandomizedRunner}. - */ -public final class SysGlobals { - /** System property passed to forked VMs: VM ID (sequential integer between 0 and the (number of concurrent jvms - 1)). */ - public static final String CHILDVM_SYSPROP_JVM_ID = "junit4.childvm.id"; - - /** System property passed to forked VMs: the number of concurrent JVMs. */ - public static final String CHILDVM_SYSPROP_JVM_COUNT = "junit4.childvm.count"; - - private final static Object lock = new Object(); - - /** - * Default prefix for all properties. - */ - private static final String DEFAULT_PREFIX = "tests"; - - /** - * A common prefix for all system properties used by randomizedtesting - * packages. It is discouraged to change this property but it may be used to resolve - * conflicts with packages that have overlapping property names. - */ - private static final String SYSPROP_PREFIX = DEFAULT_PREFIX + ".prefix"; - - /** - * Global singleton. Initialized once. - */ - private static SysGlobals singleton; - - /** - * Singleton initialization stack for easier debugging. - */ - private static StackTraceElement[] singletonInitStack; - - /** Initialized singleton's prefix. */ - private final String prefix; - - /* Property names, rendered. */ - private final String SYSPROP_STACKFILTERING; - private final String SYSPROP_RANDOM_SEED; - private final String SYSPROP_ITERATIONS; - private final String SYSPROP_TESTCLASS; - private final String SYSPROP_TESTMETHOD; - private final String SYSPROP_TESTFILTER; - private final String SYSPROP_KILLATTEMPTS; - private final String SYSPROP_KILLWAIT; - private final String SYSPROP_TIMEOUT; - private final String SYSPROP_TIMEOUT_SUITE; - private final String SYSPROP_APPEND_SEED; - private final String SYSPROP_ASSERTS; - - // Singleton constructor. - private SysGlobals(String prefix) { - this.prefix = prefix; - - this.SYSPROP_STACKFILTERING = prefixWith(prefix, "stackfiltering"); - this.SYSPROP_RANDOM_SEED = prefixWith(prefix, "seed"); - this.SYSPROP_ITERATIONS = prefixWith(prefix, "iters"); - this.SYSPROP_TESTCLASS = prefixWith(prefix, "class"); - this.SYSPROP_TESTMETHOD = prefixWith(prefix, "method"); - this.SYSPROP_TESTFILTER = prefixWith(prefix, "filter"); - this.SYSPROP_KILLATTEMPTS = prefixWith(prefix, "killattempts"); - this.SYSPROP_KILLWAIT = prefixWith(prefix, "killwait"); - this.SYSPROP_TIMEOUT = prefixWith(prefix, "timeout"); - this.SYSPROP_TIMEOUT_SUITE = prefixWith(prefix, "timeoutSuite"); - this.SYSPROP_APPEND_SEED = prefixWith(prefix, "appendseed"); - this.SYSPROP_ASSERTS = prefixWith(prefix, "asserts"); - } - - /** */ - private String prefixWith(String prefix, String propertyName) { - if (prefix.isEmpty()) { - return propertyName; - } else { - return prefix + (prefix.endsWith(".") ? "" : ".") + propertyName; - } - } - - /** */ - private static SysGlobals singleton() { - synchronized (lock) { - if (singleton == null) { - String prefix = System.getProperty(SYSPROP_PREFIX); - if (prefix == null) { - prefix = DEFAULT_PREFIX; - } - initializeWith(prefix); - } - return singleton; - } - } - - /** */ - public static SysGlobals initializeWith(String prefix) { - if (prefix == null) { - throw new IllegalArgumentException("Prefix must not be null."); - } - - synchronized (lock) { - if (singleton == null) { - singleton = new SysGlobals(prefix); - singletonInitStack = Thread.currentThread().getStackTrace(); - } - - if (!singleton.prefix.equals(prefix)) { - Exception e = new Exception("Original singleton initialization stack."); - e.setStackTrace(singletonInitStack); - throw new RuntimeException("A singleton has been initialized already with a " + - "different prefix: existing=" + singleton.prefix + ", attempted=" + prefix, e); - } - - return singleton; - } - } - - /** - * Global system property that holds the prefix used by other properties. - */ - public static String SYSPROP_PREFIX() { return SYSPROP_PREFIX; } - - /** - * Static singleton's property prefix. Initializes it if not already initialized. - */ - public static String CURRENT_PREFIX() { return singleton().prefix; } - - /** - * Enable or disable stack filtering. - */ - public static String SYSPROP_STACKFILTERING() { return singleton().SYSPROP_STACKFILTERING; } - - /** - * System property with an integer defining global initialization seeds for all - * random generators. Should guarantee test reproducibility. - */ - public static String SYSPROP_RANDOM_SEED() { return singleton().SYSPROP_RANDOM_SEED; } - - /** - * The global override for the number of each test's repetitions. - */ - public static String SYSPROP_ITERATIONS() { return singleton().SYSPROP_ITERATIONS; } - - /** - * Global override for picking out a single test class to execute. All other - * classes are ignored. The property can contain "globbing patterns" similar - * to shell expansion patterns. For example: - *
      -   * *MyTest
      -   * 
      - * will pick all classes ending in MyTest (in any package, including nested static - * classes if they appear on input). - */ - public static String SYSPROP_TESTCLASS() { return singleton().SYSPROP_TESTCLASS; } - - /** - * Global override for picking out a single test method to execute. If a - * matching method exists in more than one class, it will be executed. - */ - public static String SYSPROP_TESTMETHOD() { return singleton().SYSPROP_TESTMETHOD; } - - /** - * Global test filter. - */ - public static String SYSPROP_TESTFILTER() { return singleton().SYSPROP_TESTFILTER; } - - /** - * If there's a runaway thread, how many times do we try to interrupt and - * then kill it before we give up? Runaway threads may affect other tests (bad idea). - */ - public static String SYSPROP_KILLATTEMPTS() { return singleton().SYSPROP_KILLATTEMPTS; } - - /** - * If there's a runaway thread, how long should we wait between iterations of - * putting a silver bullet through its heart? - */ - public static String SYSPROP_KILLWAIT() { return singleton().SYSPROP_KILLWAIT; } - - /** - * Global override for a single test case's maximum execution time after which - * it is considered out of control and an attempt to interrupt it is executed. - * - *

      The timeout value should be in milliseconds. If the value is trailed by a - * "!" then the timeout value takes precedence over annotations, otherwise annotations - * take precedence over the default timeout. This is useful for running debugging - * sessions, for example, when default timeouts may be too short. - * - * @see RandomizedRunner#DEFAULT_TIMEOUT - */ - public static String SYSPROP_TIMEOUT() { return singleton().SYSPROP_TIMEOUT; } - - /** - * Global override for entire suite's maximum execution time after which - * it is considered out of control. - * - *

      The timeout value should be in milliseconds. If the value is trailed by a - * "!" then the timeout value takes precedence over annotations, otherwise annotations - * take precedence over the default timeout. This is useful for running debugging - * sessions, for example, when default timeouts may be too short. - * - * @see RandomizedRunner#DEFAULT_TIMEOUT_SUITE - */ - public static String SYSPROP_TIMEOUT_SUITE() { return singleton().SYSPROP_TIMEOUT_SUITE; } - - /** - * If true, append seed parameter to all methods. Methods that are for some - * reason repeated (due to {@link Repeat} annotation or multiple {@link Seeds}, for example) - * are always postfixed with the seed to discriminate tests from each other. Otherwise many - * GUI clients have a problem in telling which test result was which. - */ - public static String SYSPROP_APPEND_SEED() { return singleton().SYSPROP_APPEND_SEED; } - - /** - * Returns the property name to express the desired status of assertions during tests. - * - * @see RequireAssertionsRule - */ - public static String SYSPROP_ASSERTS() { return singleton().SYSPROP_ASSERTS; } - - /** - * Prefix a given property name with a common prefix. The prefix itself can be overridden - * using SYSPROP_PREFIX. This method initializes static singleton property - * names so it shouldn't be called on class initialization anywhere. - */ - public static String prefixProperty(String propertyName) { - return singleton().prefixWith(singleton.prefix, propertyName); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TeeOutputStream.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TeeOutputStream.java deleted file mode 100644 index aae91edc..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TeeOutputStream.java +++ /dev/null @@ -1,163 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * Custom teeing stream that ensures both streams receive the output and - * no exceptions are quietly suppressed. - */ -public class TeeOutputStream extends OutputStream { - private final OutputStream first; - private final OutputStream second; - - public TeeOutputStream(OutputStream first, OutputStream second) { - this.first = first; - this.second = second; - } - - @Override - public void write(int b) throws IOException { - IOException ex = null; - - try { - first.write(b); - } catch (IOException e) { - ex = e; - } - - try { - second.write(b); - } catch (IOException e) { - if (ex != null) { - ex.addSuppressed(e); - } else { - ex = e; - } - } - - if (ex != null) { - throw ex; - } - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - IOException ex = null; - - try { - first.write(b, off, len); - } catch (IOException e) { - ex = e; - } - - try { - second.write(b, off, len); - } catch (IOException e) { - if (ex != null) { - ex.addSuppressed(e); - } else { - ex = e; - } - } - - if (ex != null) { - throw ex; - } - } - - @Override - public void close() throws IOException { - IOException ex = null; - - try { - first.close(); - } catch (IOException e) { - ex = e; - } - - try { - second.close(); - } catch (IOException e) { - if (ex != null) { - ex.addSuppressed(e); - } else { - ex = e; - } - } - - if (ex != null) { - throw ex; - } - } - - @Override - public void flush() throws IOException { - IOException ex = null; - - try { - first.flush(); - } catch (IOException e) { - ex = e; - } - - try { - second.flush(); - } catch (IOException e) { - if (ex != null) { - ex.addSuppressed(e); - } else { - ex = e; - } - } - - if (ex != null) { - throw ex; - } - } - - @Override - public void write(byte[] b) throws IOException { - IOException ex = null; - - try { - first.write(b); - } catch (IOException e) { - ex = e; - } - - try { - second.write(b); - } catch (IOException e) { - if (ex != null) { - ex.addSuppressed(e); - } else { - ex = e; - } - } - - if (ex != null) { - throw ex; - } - } - - @Override - public String toString() { - return "[tee: 1:" + first + ", 2:" + second + "]"; - } - - @Override - public boolean equals(Object obj) { - throw new UnsupportedOperationException(); - } - - @Override - public int hashCode() { - throw new UnsupportedOperationException(); - } - - @Override - protected Object clone() throws CloneNotSupportedException { - throw new CloneNotSupportedException(); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TempPathResource.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TempPathResource.java deleted file mode 100644 index 5506c4f4..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TempPathResource.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.io.*; -import java.nio.file.Files; -import java.nio.file.Path; - -/** - * A temporary path resource will be deleted at the end of a given lifecycle phase. - * - * @see RandomizedContext#closeAtEnd(Closeable, LifecycleScope) - * @see RandomizedTest#newTempDir() - */ -public class TempPathResource implements Closeable { - private final Path location; - - public TempPathResource(Path location) { - this.location = location; - } - - public void close() throws IOException { - if (Files.isDirectory(location)) { - RandomizedTest.rmDir(location); - } else { - Files.deleteIfExists(location); - } - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TestMethodAndParams.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TestMethodAndParams.java deleted file mode 100644 index 6db86384..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TestMethodAndParams.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.lang.reflect.Method; -import java.util.List; - -import com.carrotsearch.randomizedtesting.annotations.TestCaseOrdering; - -/** - * A single test case entry composed of the test method - * and the arguments eventually passed to the test class's constructor. - * - * @see TestCaseOrdering - */ -public interface TestMethodAndParams { - Method getTestMethod(); - List getInstanceArguments(); -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TestMethodProvider.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TestMethodProvider.java deleted file mode 100644 index 6fc35cbb..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TestMethodProvider.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.lang.reflect.Method; -import java.util.Collection; - -/** - * Responsible for providing individual test instances and their descriptions. Also - * performs class validation to ensure test methods are valid. - */ -public interface TestMethodProvider { - /** - * Determine which methods are test methods. The contract is that methods must - * be public, instance bound (not static) and parameterless. No other - * restrictions apply (as if these weren't enough...). - * - * @param suiteClass - * The suite class. - * @param suiteClassModel - * A precomputed model of the suite class including method annotations and - * class hierarchy walking utilities. This is made available for performance - * reasons only. - * @return Return a set of methods which should be invoked by the runner as - * tests. - */ - Collection getTestMethods(Class suiteClass, ClassModel suiteClassModel); -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ThreadFilter.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ThreadFilter.java deleted file mode 100644 index 8ac48565..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ThreadFilter.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters; - -/** - * @see ThreadLeakFilters - */ -public interface ThreadFilter { - /** - * @return Return true if thread t should be - * filtered out. - */ - public boolean reject(Thread t); -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ThreadLeakControl.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ThreadLeakControl.java deleted file mode 100644 index 9a724c15..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ThreadLeakControl.java +++ /dev/null @@ -1,940 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static com.carrotsearch.randomizedtesting.RandomizedRunner.DEFAULT_KILLATTEMPTS; -import static com.carrotsearch.randomizedtesting.RandomizedRunner.DEFAULT_KILLWAIT; -import static com.carrotsearch.randomizedtesting.RandomizedRunner.DEFAULT_TIMEOUT; -import static com.carrotsearch.randomizedtesting.RandomizedRunner.DEFAULT_TIMEOUT_SUITE; -import static com.carrotsearch.randomizedtesting.RandomizedTest.systemPropertyAsInt; -import static com.carrotsearch.randomizedtesting.SysGlobals.SYSPROP_KILLATTEMPTS; -import static com.carrotsearch.randomizedtesting.SysGlobals.SYSPROP_KILLWAIT; -import static com.carrotsearch.randomizedtesting.SysGlobals.SYSPROP_TIMEOUT; -import static com.carrotsearch.randomizedtesting.SysGlobals.SYSPROP_TIMEOUT_SUITE; - -import java.lang.annotation.Annotation; -import java.lang.management.ManagementFactory; -import java.lang.management.ThreadInfo; -import java.lang.reflect.AnnotatedElement; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumSet; -import java.util.Formatter; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.LockSupport; -import java.util.logging.Logger; - -import org.junit.Test; -import org.junit.AssumptionViolatedException; -import org.junit.runner.Description; -import org.junit.runner.Result; -import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunListener; -import org.junit.runner.notification.RunNotifier; -import org.junit.runner.notification.StoppedByUserException; -import org.junit.runners.model.MultipleFailureException; -import org.junit.runners.model.Statement; - -import com.carrotsearch.randomizedtesting.RandomizedRunner.TestCandidate; -import com.carrotsearch.randomizedtesting.RandomizedRunner.UncaughtException; -import com.carrotsearch.randomizedtesting.annotations.SuppressForbidden; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction.Action; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakGroup; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies; -import com.carrotsearch.randomizedtesting.annotations.Timeout; -import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite; - -/** - * Everything corresponding to thread leak control. This is very, very fragile to changes - * because of how threads interact and where they can be spun off. - */ -@SuppressWarnings("resource") -class ThreadLeakControl { - /** A dummy class serving as the source of defaults for annotations. */ - @ThreadLeakScope - @ThreadLeakAction - @ThreadLeakLingering - @ThreadLeakZombies - @ThreadLeakFilters - @ThreadLeakGroup - private static class DefaultAnnotationValues {} - - /** - * Shared LOGGER. - */ - private final static Logger LOGGER = RandomizedRunner.logger; - - /** - * How many attempts to interrupt and then kill a runaway thread before giving up? - */ - private final int killAttempts; - - /** - * How long to wait between attempts to kill a runaway thread (millis). - */ - private final int killWait; - - /** - * Target notifier. - */ - private final RunNotifier targetNotifier; - - /** - * This is the assumed set of threads without leaks. - */ - private final Set expectedSuiteState; - - /** - * Atomic section for passing notifier events. - */ - private final Object notifierLock = new Object(); - - /** - * @see SubNotifier - */ - private final SubNotifier subNotifier; - - /** - * Test timeout. - */ - private TimeoutValue testTimeout; - - /** - * Suite timeout. - */ - private TimeoutValue suiteTimeout; - - /** - * Built-in filters. - */ - private final List builtinFilters; - - /** - * User filter (compound). - */ - private ThreadFilter suiteFilters; - - /** - * The governing runner. - */ - private final RandomizedRunner runner; - - /** - * Suite timeout. - */ - private AtomicBoolean suiteTimedOut = new AtomicBoolean(); - - /** - * Thread leak detection group. - */ - ThreadLeakGroup threadLeakGroup; - - /** - * Sub-notifier that controls passing events back in case of timeouts. - */ - private class SubNotifier extends RunNotifier { - private boolean stopRequested = false; - Description testInProgress; - - @Override - public void addListener(RunListener listener) { throw new UnsupportedOperationException(); } - @Override - public void addFirstListener(RunListener listener) { throw new UnsupportedOperationException(); } - @Override - public void removeListener(RunListener listener) { throw new UnsupportedOperationException(); } - @Override - public void fireTestRunFinished(Result result) { throw new UnsupportedOperationException(); } - @Override - public void fireTestRunStarted(Description description) { throw new UnsupportedOperationException(); } - - @Override - public void fireTestStarted(Description description) throws StoppedByUserException { - synchronized (notifierLock) { - if (stopRequested) return; - targetNotifier.fireTestStarted(description); - testInProgress = description; - } - } - - @Override - public void fireTestAssumptionFailed(Failure failure) { - synchronized (notifierLock) { - if (stopRequested) return; - targetNotifier.fireTestAssumptionFailed(failure); - } - } - - @Override - public void fireTestFailure(Failure failure) { - synchronized (notifierLock) { - if (stopRequested) return; - targetNotifier.fireTestFailure(failure); - } - } - - @Override - public void fireTestIgnored(Description description) { - synchronized (notifierLock) { - if (stopRequested) return; - testInProgress = null; - targetNotifier.fireTestIgnored(description); - } - } - - @Override - public void fireTestFinished(Description description) { - synchronized (notifierLock) { - if (stopRequested) return; - testInProgress = null; - targetNotifier.fireTestFinished(description); - } - } - - /** - * Detach from target notifier. - */ - @Override - public void pleaseStop() { - stopRequested = true; - } - } - - /** - * Timeout parsing code and logic. - */ - private static class TimeoutValue { - private final int timeoutOverride; - private final boolean globalTimeoutFirst; - - TimeoutValue(String sysprop, int defaultValue) { - String timeoutValue = System.getProperty(sysprop); - boolean globalTimeoutFirst = false; - if (timeoutValue == null || timeoutValue.trim().length() == 0) { - timeoutValue = null; - } - if (timeoutValue != null) { - // Check for timeout precedence. - globalTimeoutFirst = timeoutValue.matches("[0-9]+\\!"); - timeoutValue = timeoutValue.replaceAll("\\!", ""); - } else { - timeoutValue = Integer.toString(defaultValue); - } - - this.timeoutOverride = Integer.parseInt(timeoutValue); - this.globalTimeoutFirst = globalTimeoutFirst; - } - - int getTimeout(Integer value) { - if (globalTimeoutFirst) { - return timeoutOverride; - } else { - return value != null ? value : timeoutOverride; - } - } - } - - /** */ - private static class ThisThreadFilter implements ThreadFilter { - private final Thread t; - - public ThisThreadFilter(Thread t) { - this.t = t; - } - - @Override - public boolean reject(Thread t) { - return this.t == t; - } - } - - private static ThreadFilter or(final ThreadFilter... filters) { - return new ThreadFilter() { - @Override - public boolean reject(Thread t) { - boolean reject = false; - for (ThreadFilter f : filters) { - if (reject |= f.reject(t)) { - break; - } - } - return reject; - } - }; - } - - /** */ - private static class KnownSystemThread implements ThreadFilter { - @Override - public boolean reject(Thread t) { - // Explicit check for system group. - ThreadGroup tgroup = t.getThreadGroup(); - if (tgroup != null && "system".equals(tgroup.getName()) && tgroup.getParent() == null) { - return true; - } - - // Explicit check for Serializer shutdown daemon. - if (t.getName().equals("JUnit4-serializer-daemon")) { - return true; - } - - // Explicit check for java flight recorder (jfr) threads. - if (t.getName().equals("JFR request timer")) { - return true; - } - - // Explicit check for YourKit Java Profiler (YJP) agent thread. - if (t.getName().equals("YJPAgent-Telemetry")) { - return true; - } - - // J9 memory pool thread. - if (t.getName().equals("MemoryPoolMXBean notification dispatcher")) { - return true; - } - - // Explicit check for MacOSX AWT-AppKit - if (t.getName().equals("AWT-AppKit")) { - return true; - } - - // Explicit check for TokenPoller (MessageDigest spawns it). - if (t.getName().contains("Poller SunPKCS11")) { - return true; - } - - // forked process reaper on Unixish systems - if (t.getName().equals("process reaper")) { - return true; - } - - final List stack = new ArrayList(Arrays.asList(getStackTrace(t))); - Collections.reverse(stack); - - // Explicit check for GC$Daemon - if (stack.size() >= 1 && - stack.get(0).getClassName().startsWith("sun.misc.GC$Daemon")) { - return true; - } - - return false; - } - } - - /** */ - ThreadLeakControl(RunNotifier notifier, RandomizedRunner runner) { - this.targetNotifier = notifier; - this.subNotifier = new SubNotifier(); - this.runner = runner; - - this.killAttempts = systemPropertyAsInt(SYSPROP_KILLATTEMPTS(), DEFAULT_KILLATTEMPTS); - this.killWait = systemPropertyAsInt(SYSPROP_KILLWAIT(), DEFAULT_KILLWAIT); - - // Determine default timeouts. - testTimeout = new TimeoutValue(SYSPROP_TIMEOUT(), DEFAULT_TIMEOUT); - suiteTimeout = new TimeoutValue(SYSPROP_TIMEOUT_SUITE(), DEFAULT_TIMEOUT_SUITE); - - builtinFilters = Arrays.asList( - new ThisThreadFilter(Thread.currentThread()), - new KnownSystemThread()); - - // Determine a set of expected threads up front (unfiltered). - expectedSuiteState = Collections.unmodifiableSet(Threads.getAllThreads()); - } - - /** - * Runs a {@link Statement} and keeps any exception and - * completion flag. - */ - private static class StatementRunner implements Runnable { - private final Statement s; - - volatile Throwable error; - volatile boolean completed; - - StatementRunner(Statement s) { - this.s = s; - } - - public void run() { - try { - s.evaluate(); - } catch (Throwable t) { - error = t; - } finally { - completed = true; - } - } - } - - /** - * Check on zombie threads status. - */ - private static void checkZombies() throws AssumptionViolatedException { - if (RandomizedRunner.hasZombieThreads()) { - throw new AssumptionViolatedException("Leaked background threads present (zombies)."); - } - } - - /** - * A {@link Statement} for wrapping suite-level execution. - */ - Statement forSuite(final Statement s, final Description suiteDescription) { - final Class suiteClass = RandomizedContext.current().getTargetClass(); - final int timeout = determineTimeout(suiteClass); - - return new Statement() { - @Override - public void evaluate() throws Throwable { - checkZombies(); - - threadLeakGroup = firstAnnotated(ThreadLeakGroup.class, suiteClass, DefaultAnnotationValues.class); - final List errors = new ArrayList(); - suiteFilters = instantiateFilters(errors, suiteClass); - MultipleFailureException.assertEmpty(errors); - - final StatementRunner sr = new StatementRunner(s); - final boolean timedOut = forkTimeoutingTask(sr, timeout, errors); - - synchronized (notifierLock) { - if (timedOut) { - // Mark as timed out so that we don't do any checks in any currently running test - suiteTimedOut.set(true); - - // Flush streams so that we don't get warning outputs before sysout buffers. - flushStreams(); - - // Emit a warning. - LOGGER.warning("Suite execution timed out: " + suiteDescription + formatThreadStacksFull()); - - // mark subNotifier as dead (no longer passing events). - subNotifier.pleaseStop(); - } - } - - if (timedOut) { - // complete subNotifier state in case in the middle of a test. - if (subNotifier.testInProgress != null) { - targetNotifier.fireTestFailure( - new Failure(subNotifier.testInProgress, - RandomizedRunner.augmentStackTrace( - emptyStack(new Exception("Test abandoned because suite timeout was reached."))))); - targetNotifier.fireTestFinished(subNotifier.testInProgress); - } - - // throw suite failure (timeout). - errors.add(RandomizedRunner.augmentStackTrace( - emptyStack(new Exception("Suite timeout exceeded (>= " + timeout + " msec).")))); - } - - final AnnotatedElement [] chain = { suiteClass, DefaultAnnotationValues.class }; - List threadLeakErrors = timedOut ? new ArrayList() : errors; - checkThreadLeaks( - refilter(expectedSuiteState, suiteFilters), threadLeakErrors, LifecycleScope.SUITE, suiteDescription, chain); - processUncaught(errors, runner.handler.getUncaughtAndClear()); - - MultipleFailureException.assertEmpty(errors); - } - - @SuppressForbidden("Legitimate use of syserr.") - private void flushStreams() { - System.out.flush(); - System.err.flush(); - } - }; - } - - /** - * A {@link Statement} for wrapping test-level execution. - */ - Statement forTest(final Statement s, final TestCandidate c) { - final int timeout = determineTimeout(c); - - return new Statement() { - @Override - public void evaluate() throws Throwable { - checkZombies(); - - final StatementRunner sr = new StatementRunner(s); - final List errors = new ArrayList(); - final Set beforeTestState = getThreads(suiteFilters); - final boolean timedOut = forkTimeoutingTask(sr, timeout, errors); - - if (suiteTimedOut.get()) { - return; - } - - if (timedOut) { - LOGGER.warning("Test execution timed out: " + c.description + formatThreadStacksFull()); - } - - if (timedOut) { - errors.add(RandomizedRunner.augmentStackTrace( - emptyStack(new Exception("Test timeout exceeded (>= " + timeout + " msec).")))); - } - - final AnnotatedElement [] chain = - { c.method, c.getTestClass(), DefaultAnnotationValues.class }; - List threadLeakErrors = timedOut ? new ArrayList() : errors; - checkThreadLeaks(beforeTestState, threadLeakErrors, LifecycleScope.TEST, c.description, chain); - processUncaught(errors, runner.handler.getUncaughtAndClear()); - - MultipleFailureException.assertEmpty(errors); - } - }; - } - - /** - * Refilter a set of threads - */ - protected Set refilter(Set in, ThreadFilter f) { - HashSet t = new HashSet(in); - for (Iterator i = t.iterator(); i.hasNext();) { - if (f.reject(i.next())) { - i.remove(); - } - } - return t; - } - - /** - * Instantiate a full set of {@link ThreadFilter}s for a suite. - */ - private ThreadFilter instantiateFilters(List errors, Class suiteClass) { - ThreadLeakFilters ann = - firstAnnotated(ThreadLeakFilters.class, suiteClass, DefaultAnnotationValues.class); - - final ArrayList filters = new ArrayList(); - for (Class c : ann.filters()) { - try { - filters.add(c.newInstance()); - } catch (Throwable t) { - errors.add(t); - } - } - - if (ann.defaultFilters()) { - filters.addAll(builtinFilters); - } - - return or(filters.toArray(new ThreadFilter[filters.size()])); - } - - /** - * Clears a {@link Throwable}'s stack. - */ - private static T emptyStack(T t) { - t.setStackTrace(new StackTraceElement [0]); - return t; - } - - /** - * Process uncaught exceptions. - */ - protected void processUncaught(List errors, List uncaughtList) { - for (UncaughtException e : uncaughtList) { - errors.add(emptyStack(new UncaughtExceptionError( - "Captured an uncaught exception in thread: " + e.threadName, e.error))); - } - } - - /** - * Perform a thread leak check at the given scope. - */ - @SuppressWarnings("deprecation") - protected void checkThreadLeaks( - Set expectedState, - List errors, - LifecycleScope scope, Description description, - AnnotatedElement... annotationChain) - { - final ThreadLeakScope annScope = firstAnnotated(ThreadLeakScope.class, annotationChain); - - // Return immediately if no checking. - if (annScope.value() == Scope.NONE) - return; - - // If suite scope check is requested skip testing at test level. - if (annScope.value() == Scope.SUITE && scope == LifecycleScope.TEST) { - return; - } - - // Check for the set of live threads, with optional lingering. - int lingerTime = firstAnnotated(ThreadLeakLingering.class, annotationChain).linger(); - HashSet threads = getThreads(suiteFilters); - threads.removeAll(expectedState); - - if (lingerTime > 0 && !threads.isEmpty()) { - final long deadline = System.currentTimeMillis() + lingerTime; - try { - LOGGER.warning("Will linger awaiting termination of " + threads.size() + " leaked thread(s)."); - do { - // Check every few hundred milliseconds until deadline occurs. We want to break out - // sooner than the maximum lingerTime but there is no explicit even that - // would wake us up, so poll periodically. - Thread.sleep(100); - - threads = getThreads(suiteFilters); - threads.removeAll(expectedState); - if (threads.isEmpty() || System.currentTimeMillis() > deadline) - break; - } while (true); - } catch (InterruptedException e) { - LOGGER.warning("Lingering interrupted."); - } - } - - if (threads.isEmpty()) { - return; - } - - // Take one more snapshot, this time including stack traces (costly). - HashMap withTraces = getThreadsWithTraces(suiteFilters); - withTraces.keySet().removeAll(expectedState); - if (withTraces.isEmpty()) { - return; - } - - // Build up failure message (include stack traces of leaked threads). - StringBuilder message = new StringBuilder(threads.size() + " thread" + - (threads.size() == 1 ? "" : "s") + - " leaked from " + - scope + " scope at " + description + ": "); - message.append(formatThreadStacks(withTraces)); - - // The first exception is leaked threads error. - errors.add(RandomizedRunner.augmentStackTrace( - emptyStack(new ThreadLeakError(message.toString())))); - - // Perform actions on leaked threads. - final EnumSet actions = EnumSet.noneOf(Action.class); - actions.addAll(Arrays.asList(firstAnnotated(ThreadLeakAction.class, annotationChain).value())); - - if (actions.contains(Action.WARN)) { - LOGGER.severe(message.toString()); - } - - Set zombies = Collections.emptySet(); - if (actions.contains(Action.INTERRUPT)) { - zombies = tryToInterruptAll(errors, withTraces.keySet()); - } - - // Process zombie thread check consequences here. - if (!zombies.isEmpty()) { - switch (firstAnnotated(ThreadLeakZombies.class, annotationChain).value()) { - case CONTINUE: - // Do nothing about it. - break; - case IGNORE_REMAINING_TESTS: - // Mark zombie thread presence. - RandomizedRunner.zombieMarker.set(true); - break; - default: - throw new RuntimeException("Missing case."); - } - } - } - - /** - * Dump threads and their current stack trace. - */ - private String formatThreadStacks(Map threads) { - StringBuilder message = new StringBuilder(); - int cnt = 1; - final Formatter f = new Formatter(message, Locale.ROOT); - for (Map.Entry e : threads.entrySet()) { - f.format(Locale.ROOT, "\n %2d) %s", cnt++, Threads.threadName(e.getKey())).flush(); - if (e.getValue().length == 0) { - message.append("\n at (empty stack)"); - } else { - for (StackTraceElement ste : e.getValue()) { - message.append("\n at ").append(ste); - } - } - } - return message.toString(); - } - - /** Collect thread names. */ - private String threadNames(Collection threads) { - StringBuilder b = new StringBuilder(); - final Formatter f = new Formatter(b, Locale.ROOT); - int cnt = 1; - for (Thread t : threads) { - f.format(Locale.ROOT, "\n %2d) %s", cnt++, Threads.threadName(t)); - } - return b.toString(); - } - - /** Dump thread state. */ - private String formatThreadStacksFull() { - try { - StringBuilder b = new StringBuilder(); - b.append("\n==== jstack at approximately timeout time ====\n"); - for (ThreadInfo ti : ManagementFactory.getThreadMXBean().dumpAllThreads(true, true)) { - Threads.append(b, ti); - } - b.append("^^==============================================\n"); - return b.toString(); - } catch (Throwable e) { - // Ignore, perhaps not available. - } - return formatThreadStacks(getThreadsWithTraces()); - } - - private static StackTraceElement[] getStackTrace(final Thread t) { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public StackTraceElement[] run() { - return t.getStackTrace(); - } - }); - } - - /** - * Returns all {@link ThreadLeakGroup} applicable threads, with stack - * traces, for analysis. - */ - private HashMap getThreadsWithTraces(ThreadFilter... filters) { - final Set threads = getThreads(filters); - final HashMap r = new HashMap(); - for (Thread t : threads) { - r.put(t, getStackTrace(t)); - } - return r; - } - - /** - * Returns all {@link ThreadLeakGroup} threads for analysis. - */ - private HashSet getThreads(ThreadFilter... filters) { - HashSet threads; - switch (threadLeakGroup.value()) { - case ALL: - threads = Threads.getAllThreads(); - break; - case MAIN: - threads = Threads.getThreads(RandomizedRunner.mainThreadGroup); - break; - case TESTGROUP: - threads = Threads.getThreads(runner.runnerThreadGroup); - break; - default: - throw new RuntimeException(); - } - - final ThreadFilter filter = or(filters); - for (Iterator i = threads.iterator(); i.hasNext();) { - Thread t = i.next(); - if (!t.isAlive() || filter.reject(t)) { - i.remove(); - } - } - - return threads; - } - - /** - * Attempt to interrupt all threads in the given set. - */ - private Set tryToInterruptAll(List errors, Set threads) { - LOGGER.info("Starting to interrupt leaked threads:" + threadNames(threads)); - - // stop reporting uncaught exceptions. - runner.handler.stopReporting(); - try { - // This means we have an unknown ordering of interrupt calls but - // there is very little we can do about it, really. - final HashSet ordered = new HashSet(threads); - - int interruptAttempts = this.killAttempts; - int interruptWait = this.killWait; - boolean allDead; - final int restorePriority = Thread.currentThread().getPriority(); - do { - allDead = true; - try { - Thread.currentThread().setPriority(Thread.MAX_PRIORITY); - for (Thread t : ordered) { - t.interrupt(); - } - - // Maximum wait time. Progress through the threads, trying to join but - // decrease the join time each time. - long waitDeadline = System.currentTimeMillis() + interruptWait; - for (Iterator i = ordered.iterator(); i.hasNext();) { - final Thread t = i.next(); - if (t.isAlive()) { - allDead = false; - join(t, Math.max(1, waitDeadline - System.currentTimeMillis()), Thread::sleep); - } else { - i.remove(); - } - } - } catch (InterruptedException e) { - interruptAttempts = 0; - } - } while (!allDead && --interruptAttempts > 0); - Thread.currentThread().setPriority(restorePriority); - - // Check after the last join. - HashMap zombies = new HashMap(); - for (Thread t : ordered) { - if (t.isAlive()) { - zombies.put(t, getStackTrace(t)); - } - } - - if (zombies.isEmpty()) { - LOGGER.info("All leaked threads terminated."); - } else { - String message = "There are still zombie threads that couldn't be terminated:" + formatThreadStacks(zombies); - LOGGER.severe(message); - errors.add(RandomizedRunner.augmentStackTrace( - emptyStack(new ThreadLeakError(message.toString())))); - } - - return zombies.keySet(); - } finally { - runner.handler.resumeReporting(); - } - } - - /** - * Fork or not depending on the timeout value. - */ - boolean forkTimeoutingTask(StatementRunner r, int timeout, List errors) - throws InterruptedException - { - if (timeout == 0) { - r.run(); - } else { - final Thread owner = Thread.currentThread(); - final AtomicBoolean done = new AtomicBoolean(); - - Thread t = new Thread(() -> { - try { - r.run(); - } finally { - done.set(true); - LockSupport.unpark(owner); - } - }, Thread.currentThread().getName() + "-worker"); - RandomizedContext.cloneFor(t); - - t.start(); - join(t, timeout, (millis) -> { - LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(millis)); - if (done.get()) { - t.join(); - } - }); - } - - final boolean timedOut = !r.completed; - if (r.error != null) errors.add(r.error); - return timedOut; - } - - static interface AwaitCond { - void await(long millis) throws InterruptedException; - } - - static void join(Thread t, long millis, AwaitCond cond) throws InterruptedException { - if (millis <= 0) { - throw new IllegalArgumentException("Timeout must be positive: " + millis); - } - - long deadline = System.currentTimeMillis() + millis; - while (t.isAlive()) { - long delay = deadline - System.currentTimeMillis(); - if (delay > 0) { - // Don't wait longer than a few millis, then recheck condition. - // We use sleep because Thread.join() is synchronized and this thread may - // get stuck on getting the monitor for an indefinite amount of time. - cond.await(Math.min(250, delay)); - } else { - break; - } - } - } - - boolean isTimedOut() { - return suiteTimedOut.get(); - } - - /** - * Return the {@link RunNotifier} that should be used by any sub-statements - * running actual instance-scope tests. We need this because we need to - * prevent spurious notifications after suite timeouts. - */ - RunNotifier notifier() { - return subNotifier; - } - - /** - * Determine timeout for a suite. - * - * @return Returns timeout in milliseconds or 0 if the test should run until - * finished (possibly blocking forever). - */ - private int determineTimeout(Class suiteClass) { - TimeoutSuite timeoutAnn = suiteClass.getAnnotation(TimeoutSuite.class); - return suiteTimeout.getTimeout(timeoutAnn == null ? null : timeoutAnn.millis()); - } - - /** - * Determine timeout for a single test method (candidate). - * - * @return Returns timeout in milliseconds or 0 if the test should run until - * finished (possibly blocking forever). - */ - private int determineTimeout(TestCandidate c) { - Integer timeout = null; - - Timeout timeoutAnn = c.getTestClass().getAnnotation(Timeout.class); - if (timeoutAnn != null) { - timeout = (int) Math.min(Integer.MAX_VALUE, timeoutAnn.millis()); - } - - // @Test annotation timeout value. - Test testAnn = c.method.getAnnotation(Test.class); - if (testAnn != null && testAnn.timeout() > 0) { - timeout = (int) Math.min(Integer.MAX_VALUE, testAnn.timeout()); - } - - // Method-override. - timeoutAnn = c.method.getAnnotation(Timeout.class); - if (timeoutAnn != null) { - timeout = timeoutAnn.millis(); - } - - return testTimeout.getTimeout(timeout); - } - - /** - * Returns an annotation's instance declared on any annotated element (first one wins) - * or the default value if not present on any of them. - */ - private static T firstAnnotated(Class clazz, AnnotatedElement... elements) { - for (AnnotatedElement element : elements) { - T ann = element.getAnnotation(clazz); - if (ann != null) return ann; - } - throw new RuntimeException("default annotation value must be within elements."); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ThreadLeakError.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ThreadLeakError.java deleted file mode 100644 index 4ac5cb91..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/ThreadLeakError.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -/** - * A thread went wild. - */ -@SuppressWarnings("serial") -final class ThreadLeakError extends Error { - public ThreadLeakError(String message) { - super(message); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Threads.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Threads.java deleted file mode 100644 index 6aac849d..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Threads.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.lang.Thread.State; -import java.lang.management.LockInfo; -import java.lang.management.MonitorInfo; -import java.lang.management.ThreadInfo; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Arrays; -import java.util.EnumMap; -import java.util.HashSet; - -final class Threads { - private Threads() {} - - /** - * Collect thread information, JVM vendor insensitive. - */ - public static String threadName(Thread t) { - return "Thread[" + - "id=" + t.getId() + - ", name=" + t.getName() + - ", state=" + t.getState() + - ", group=" + groupName(t.getThreadGroup()) + - "]"; - } - - private static String groupName(ThreadGroup threadGroup) { - if (threadGroup == null) { - return "{null group}"; - } else { - return threadGroup.getName(); - } - } - - private final static EnumMap lockInfoStrings; - static { - lockInfoStrings = new EnumMap(State.class); - lockInfoStrings.put(State.BLOCKED, "blocked on "); - lockInfoStrings.put(State.WAITING, "waiting on "); - lockInfoStrings.put(State.TIMED_WAITING, "timed waiting on "); - lockInfoStrings.put(State.TERMINATED, "terminated? on "); - lockInfoStrings.put(State.RUNNABLE, "runnable? on "); - lockInfoStrings.put(State.NEW, "new? on "); - } - - /** - * Dump {@link ThreadInfo} information. - */ - public static void append(StringBuilder b, ThreadInfo ti) { - b.append('"').append(ti.getThreadName()).append('"'); - b.append(" ID=").append(ti.getThreadId()); - - final State threadState = ti.getThreadState(); - b.append(" ").append(threadState); - if (ti.getLockName() != null) { - b.append(" on ").append(ti.getLockName()); - } - - if (ti.getLockOwnerName() != null) { - b.append(" owned by \"").append(ti.getLockOwnerName()) - .append("\" ID=").append(ti.getLockOwnerId()); - } - - b.append(ti.isSuspended() ? " (suspended)" : ""); - b.append(ti.isInNative() ? " (in native code)" : ""); - b.append("\n"); - - final StackTraceElement[] stack = ti.getStackTrace(); - final LockInfo lockInfo = ti.getLockInfo(); - final MonitorInfo [] monitorInfos = ti.getLockedMonitors(); - for (int i = 0; i < stack.length; i++) { - b.append("\tat ").append(stack[i]).append("\n"); - if (i == 0 && lockInfo != null) { - b.append("\t- ") - .append(lockInfoStrings.get(threadState)) - .append(lockInfo) - .append("\n"); - } - - for (MonitorInfo mi : monitorInfos) { - if (mi.getLockedStackDepth() == i) { - b.append("\t- locked ").append(mi).append("\n"); - } - } - } - - LockInfo [] lockInfos = ti.getLockedSynchronizers(); - if (lockInfos.length > 0) { - b.append("\tLocked synchronizers:\n"); - for (LockInfo li : ti.getLockedSynchronizers()) { - b.append("\t- ").append(li).append("\n"); - } - } - b.append("\n"); - } - - public static HashSet getAllThreads() { - ThreadGroup tg = getTopThreadGroup(); - return getThreads(tg); - } - - public static HashSet getThreads(ThreadGroup tg) { - Thread [] threads = new Thread [2]; - int maxIndex; - while ((maxIndex = doEnumerate(tg, threads, true)) == threads.length) { - threads = new Thread [threads.length * 2]; - } - return new HashSet(Arrays.asList(threads).subList(0, maxIndex)); - } - - private static int doEnumerate(final ThreadGroup tg, final Thread[] threads, final boolean recurse) { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Integer run() { - return tg.enumerate(threads, recurse); - } - }); - } - - public static ThreadGroup getTopThreadGroup() { - // a lame workaround so that J9 works. - ThreadGroup tg = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public ThreadGroup run() { - ThreadGroup tg = Thread.currentThread().getThreadGroup(); - while (tg != null && tg.getParent() != null) { - tg = tg.getParent(); - } - return tg; - } - }); - - if (tg == null) { - throw new RuntimeException("No root ThreadGroup for thread: " + Thread.currentThread()); - } - return tg; - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TraceFormatting.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TraceFormatting.java deleted file mode 100644 index 905f0109..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/TraceFormatting.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.*; - -/** - * Utilities for dealing with throwables, stacks, etc. - */ -public final class TraceFormatting { - /** Stack filtering prefixes. */ - private final List filteredPrefixes; - - /** - * Default stack traces, no filtering. - */ - public TraceFormatting() { - this(Collections. emptyList()); - } - - public TraceFormatting(List filteredPrefixes) { - this.filteredPrefixes = filteredPrefixes; - } - - /** Format an exception and all of its nested stacks into a string. */ - public String formatThrowable(Throwable t) { - return formatThrowable(new StringBuilder(), t).toString(); - } - - /** Format an exception and all of its nested stacks into a string. */ - public StringBuilder formatThrowable(StringBuilder b, Throwable t) { - b.append(t.toString()).append("\n"); - formatStackTrace(b, t.getStackTrace()); - if (t.getCause() != null) { - b.append("Caused by: "); - formatThrowable(b, t.getCause()); - } - return b; - } - - /** Format a list of stack entries into a string. */ - public StringBuilder formatStackTrace(StringBuilder b, StackTraceElement[] stackTrace) { - return formatStackTrace(b, Arrays.asList(stackTrace)); - } - - public String formatStackTrace(StackTraceElement[] stackTrace) { - return formatStackTrace(Arrays.asList(stackTrace)); - } - - public String formatStackTrace(Iterable stackTrace) { - return formatStackTrace(new StringBuilder(), stackTrace).toString(); - } - - /** Format a list of stack entries into a string. */ - public StringBuilder formatStackTrace(StringBuilder b, Iterable stackTrace) { - Set filteredSet = new HashSet(); - for (StackTraceElement e : stackTrace) { - String stackLine = e.toString(); - - String filtered = null; - for (String prefix : filteredPrefixes) { - if (stackLine.startsWith(prefix)) { - filtered = prefix; - break; - } - } - - if (filtered != null) { - if (filteredSet.isEmpty()) { - b.append(" [..."); - } - filteredSet.add(filtered); - } else { - appendFiltered(b, filteredSet); - b.append(" ").append(stackLine).append("\n"); - } - } - appendFiltered(b, filteredSet); - return b; - } - - private static void appendFiltered(StringBuilder b, Set filteredSet) { - if (!filteredSet.isEmpty()) { - boolean first = true; - for (String prefix : filteredSet) { - if (!first) { - b.append(", "); - } - first = false; - b.append(prefix).append("*"); - } - b.append("]\n"); - filteredSet.clear(); - } - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/UncaughtExceptionError.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/UncaughtExceptionError.java deleted file mode 100644 index ea3b4daf..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/UncaughtExceptionError.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -/** - * This is thrown on uncaught exceptions during suite or test execution. - */ -@SuppressWarnings("serial") -final class UncaughtExceptionError extends Error { - public UncaughtExceptionError(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Validation.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Validation.java deleted file mode 100644 index fb82ddd5..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Validation.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; - -/** - * Validation utilities. Chained-call style. - */ -final class Validation { - - public static final class MethodValidation { - private final Method m; - private String description; - - public MethodValidation(Method m) { - this.m = m; - this.description = "Method " + m.getName(); - } - - public MethodValidation describedAs(String message) { - this.description = message; - return this; - } - - public MethodValidation isPublic() { - if (!Modifier.isPublic(m.getModifiers())) { - throw new RuntimeException(description + " should be public."); - } - return this; - } - - public MethodValidation hasArgsCount(int argsCount) { - if (m.getParameterTypes().length != argsCount) { - throw new RuntimeException(description + " should have " + argsCount + " parameters and" + - " has these: " + Arrays.toString(m.getParameterTypes())); - } - return this; - } - - public MethodValidation isStatic() { - if (!Modifier.isStatic(m.getModifiers())) { - throw new RuntimeException(description + " should be static."); - } - return this; - } - - public MethodValidation isNotStatic() { - if (Modifier.isStatic(m.getModifiers())) { - throw new RuntimeException(description + " should be instance method (not static)."); - } - return this; - } - - public MethodValidation hasReturnType(Class clazz) { - if (!clazz.isAssignableFrom(m.getReturnType())) { - throw new RuntimeException(description + " should have a return " + - "type assignable to: " + clazz.getName()); - } - return this; - } - } - - public static final class ClassValidation { - private final Class clazz; - private String description; - - public ClassValidation(Class clazz) { - this.clazz = clazz; - this.description = "Class " + clazz.getName(); - } - - public ClassValidation describedAs(String message) { - this.description = message; - return this; - } - - public ClassValidation isPublic() { - if (!Modifier.isPublic(clazz.getModifiers())) { - throw new RuntimeException(description + " should be public."); - } - return this; - } - - public ClassValidation isConcreteClass() { - if (Modifier.isInterface(clazz.getModifiers())) { - throw new RuntimeException(description + " should be a conrete class (not an interface)."); - } - if (Modifier.isAbstract(clazz.getModifiers())) { - throw new RuntimeException(description + " should be a concrete class (not abstract)."); - } - return this; - } - - public void hasPublicNoArgsConstructor() { - try { - clazz.getConstructor(new Class [0]); - } catch (Throwable e) { - throw new RuntimeException(description + " should have a public parameterless constructor."); - } - } - } - - public static MethodValidation checkThat(Method method) { - return new MethodValidation(method); - } - - public static ClassValidation checkThat(Class clazz) { - return new ClassValidation(clazz); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/WriterOutputStream.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/WriterOutputStream.java deleted file mode 100644 index 86963e6b..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/WriterOutputStream.java +++ /dev/null @@ -1,288 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.Writer; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CoderResult; -import java.nio.charset.CodingErrorAction; - -/** - * {@link OutputStream} implementation that transforms a byte stream to a - * character stream using a specified charset encoding and writes the resulting - * stream to a {@link Writer}. The stream is transformed using a - * {@link CharsetDecoder} object, guaranteeing that all charset - * encodings supported by the JRE are handled correctly. - *

      - * The output of the {@link CharsetDecoder} is buffered using a fixed size buffer. - * This implies that the data is written to the underlying {@link Writer} in chunks - * that are no larger than the size of this buffer. By default, the buffer is - * flushed only when it overflows or when {@link #flush()} or {@link #close()} - * is called. In general there is therefore no need to wrap the underlying {@link Writer} - * in a {@link java.io.BufferedWriter}. {@link WriterOutputStream} can also - * be instructed to flush the buffer after each write operation. In this case, all - * available data is written immediately to the underlying {@link Writer}, implying that - * the current position of the {@link Writer} is correlated to the current position - * of the {@link WriterOutputStream}. - *

      - * {@link WriterOutputStream} implements the inverse transformation of {@link java.io.OutputStreamWriter}; - * in the following example, writing to out2 would have the same result as writing to - * out directly (provided that the byte sequence is legal with respect to the - * charset encoding): - *

      - * OutputStream out = ...
      - * Charset cs = ...
      - * OutputStreamWriter writer = new OutputStreamWriter(out, cs);
      - * WriterOutputStream out2 = new WriterOutputStream(writer, cs);
      - * {@link WriterOutputStream} implements the same transformation as {@link java.io.InputStreamReader}, - * except that the control flow is reversed: both classes transform a byte stream - * into a character stream, but {@link java.io.InputStreamReader} pulls data from the underlying stream, - * while {@link WriterOutputStream} pushes it to the underlying stream. - *

      - * Note that while there are use cases where there is no alternative to using - * this class, very often the need to use this class is an indication of a flaw - * in the design of the code. This class is typically used in situations where an existing - * API only accepts an {@link OutputStream} object, but where the stream is known to represent - * character data that must be decoded for further use. - *

      - * Instances of {@link WriterOutputStream} are not thread safe. - * - * @since 2.0 - */ -public class WriterOutputStream extends OutputStream { - private static final int DEFAULT_BUFFER_SIZE = 1024; - - private final Writer writer; - private final CharsetDecoder decoder; - private final boolean writeImmediately; - - /** - * ByteBuffer used as input for the decoder. This buffer can be small - * as it is used only to transfer the received data to the - * decoder. - */ - private final ByteBuffer decoderIn = ByteBuffer.allocate(128); - - /** - * CharBuffer used as output for the decoder. It should be - * somewhat larger as we write from this buffer to the - * underlying Writer. - */ - private final CharBuffer decoderOut; - - /** - * Constructs a new {@link WriterOutputStream} with a default output buffer size of - * 1024 characters. The output buffer will only be flushed when it overflows or when - * {@link #flush()} or {@link #close()} is called. - * - * @param writer the target {@link Writer} - * @param decoder the charset decoder - * @since 2.1 - */ - public WriterOutputStream(Writer writer, CharsetDecoder decoder) { - this(writer, decoder, DEFAULT_BUFFER_SIZE, false); - } - - /** - * Constructs a new {@link WriterOutputStream}. - * - * @param writer the target {@link Writer} - * @param decoder the charset decoder - * @param bufferSize the size of the output buffer in number of characters - * @param writeImmediately If true the output buffer will be flushed after each - * write operation, i.e. all available data will be written to the - * underlying {@link Writer} immediately. If false, the - * output buffer will only be flushed when it overflows or when - * {@link #flush()} or {@link #close()} is called. - * @since 2.1 - */ - public WriterOutputStream(Writer writer, CharsetDecoder decoder, int bufferSize, boolean writeImmediately) { - this.writer = writer; - this.decoder = decoder; - this.writeImmediately = writeImmediately; - decoderOut = CharBuffer.allocate(bufferSize); - } - - /** - * Constructs a new {@link WriterOutputStream}. - * - * @param writer the target {@link Writer} - * @param charset the charset encoding - * @param bufferSize the size of the output buffer in number of characters - * @param writeImmediately If true the output buffer will be flushed after each - * write operation, i.e. all available data will be written to the - * underlying {@link Writer} immediately. If false, the - * output buffer will only be flushed when it overflows or when - * {@link #flush()} or {@link #close()} is called. - */ - public WriterOutputStream(Writer writer, Charset charset, int bufferSize, boolean writeImmediately) { - this(writer, - charset.newDecoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE) - .replaceWith("?"), - bufferSize, - writeImmediately); - } - - /** - * Constructs a new {@link WriterOutputStream} with a default output buffer size of - * 1024 characters. The output buffer will only be flushed when it overflows or when - * {@link #flush()} or {@link #close()} is called. - * - * @param writer the target {@link Writer} - * @param charset the charset encoding - */ - public WriterOutputStream(Writer writer, Charset charset) { - this(writer, charset, DEFAULT_BUFFER_SIZE, false); - } - - /** - * Constructs a new {@link WriterOutputStream}. - * - * @param writer the target {@link Writer} - * @param charsetName the name of the charset encoding - * @param bufferSize the size of the output buffer in number of characters - * @param writeImmediately If true the output buffer will be flushed after each - * write operation, i.e. all available data will be written to the - * underlying {@link Writer} immediately. If false, the - * output buffer will only be flushed when it overflows or when - * {@link #flush()} or {@link #close()} is called. - */ - public WriterOutputStream(Writer writer, String charsetName, int bufferSize, boolean writeImmediately) { - this(writer, Charset.forName(charsetName), bufferSize, writeImmediately); - } - - /** - * Constructs a new {@link WriterOutputStream} with a default output buffer size of - * 1024 characters. The output buffer will only be flushed when it overflows or when - * {@link #flush()} or {@link #close()} is called. - * - * @param writer the target {@link Writer} - * @param charsetName the name of the charset encoding - */ - public WriterOutputStream(Writer writer, String charsetName) { - this(writer, charsetName, DEFAULT_BUFFER_SIZE, false); - } - - /** - * Constructs a new {@link WriterOutputStream} that uses the default character encoding - * and with a default output buffer size of 1024 characters. The output buffer will only - * be flushed when it overflows or when {@link #flush()} or {@link #close()} is called. - * - * @param writer the target {@link Writer} - */ - public WriterOutputStream(Writer writer) { - this(writer, Charset.defaultCharset(), DEFAULT_BUFFER_SIZE, false); - } - - /** - * Write bytes from the specified byte array to the stream. - * - * @param b the byte array containing the bytes to write - * @param off the start offset in the byte array - * @param len the number of bytes to write - * @throws IOException if an I/O error occurs - */ - @Override - public void write(byte[] b, int off, int len) throws IOException { - while (len > 0) { - int c = Math.min(len, decoderIn.remaining()); - decoderIn.put(b, off, c); - processInput(false); - len -= c; - off += c; - } - if (writeImmediately) { - flushOutput(); - } - } - - /** - * Write bytes from the specified byte array to the stream. - * - * @param b the byte array containing the bytes to write - * @throws IOException if an I/O error occurs - */ - @Override - public void write(byte[] b) throws IOException { - write(b, 0, b.length); - } - - /** - * Write a single byte to the stream. - * - * @param b the byte to write - * @throws IOException if an I/O error occurs - */ - @Override - public void write(int b) throws IOException { - write(new byte[] { (byte)b }, 0, 1); - } - - /** - * Flush the stream. Any remaining content accumulated in the output buffer - * will be written to the underlying {@link Writer}. After that - * {@link Writer#flush()} will be called. - * @throws IOException if an I/O error occurs - */ - @Override - public void flush() throws IOException { - flushOutput(); - writer.flush(); - } - - /** - * Close the stream. Any remaining content accumulated in the output buffer - * will be written to the underlying {@link Writer}. After that - * {@link Writer#close()} will be called. - * @throws IOException if an I/O error occurs - */ - @Override - public void close() throws IOException { - processInput(true); - flushOutput(); - writer.close(); - } - - /** - * Decode the contents of the input ByteBuffer into a CharBuffer. - * - * @param endOfInput indicates end of input - * @throws IOException if an I/O error occurs - */ - private void processInput(boolean endOfInput) throws IOException { - // Prepare decoderIn for reading - decoderIn.flip(); - CoderResult coderResult; - while (true) { - coderResult = decoder.decode(decoderIn, decoderOut, endOfInput); - if (coderResult.isOverflow()) { - flushOutput(); - } else if (coderResult.isUnderflow()) { - break; - } else { - // The decoder is configured to replace malformed input and unmappable characters, - // so we should not get here. - throw new IOException("Unexpected coder result"); - } - } - // Discard the bytes that have been read - decoderIn.compact(); - } - - /** - * Flush the output. - * - * @throws IOException if an I/O error occurs - */ - private void flushOutput() throws IOException { - if (decoderOut.position() > 0) { - writer.write(decoderOut.array(), 0, decoderOut.position()); - decoderOut.rewind(); - } - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Xoroshiro128PlusRandom.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Xoroshiro128PlusRandom.java deleted file mode 100644 index 35f9f5c0..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/Xoroshiro128PlusRandom.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.Random; - -/** - * Implements Xoroshiro128PlusRandom. Not synchronized (anywhere). - * - * @see "http://xoroshiro.di.unimi.it/" - */ -@SuppressWarnings("serial") -public class Xoroshiro128PlusRandom extends Random { - private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53); - private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0 / (1L << 24); - - private long s0, s1; - - public Xoroshiro128PlusRandom(long seed) { - // Must be here, the only Random constructor. Has side-effects on setSeed, see below. - super(0); - - s0 = MurmurHash3.hash(seed); - s1 = MurmurHash3.hash(s0); - - if (s0 == 0 && s1 == 0) { - s0 = MurmurHash3.hash(0xdeadbeefL); - s1 = MurmurHash3.hash(s0); - } - } - - @Override - public void setSeed(long seed) { - // Called from super constructor and observing uninitialized state? - if (s0 == 0 && s1 == 0) { - return; - } - - throw AssertingRandom.noSetSeed(); - } - - @Override - public boolean nextBoolean() { - return nextLong() >= 0; - } - - @Override - public void nextBytes(byte[] bytes) { - for (int i = 0, len = bytes.length; i < len; ) { - long rnd = nextInt(); - for (int n = Math.min(len - i, 8); n-- > 0; rnd >>>= 8) { - bytes[i++] = (byte) rnd; - } - } - } - - @Override - public double nextDouble() { - return (nextLong() >>> 11) * DOUBLE_UNIT; - } - - @Override - public float nextFloat() { - return (nextInt() >>> 8) * FLOAT_UNIT; - } - - @Override - public int nextInt() { - return (int) nextLong(); - } - - @Override - public int nextInt(int n) { - // Leave superclass's implementation. - return super.nextInt(n); - } - - @Override - public double nextGaussian() { - // Leave superclass's implementation. - return super.nextGaussian(); - } - - @Override - public long nextLong() { - final long s0 = this.s0; - long s1 = this.s1; - final long result = s0 + s1; - s1 ^= s0; - this.s0 = Long.rotateLeft(s0, 55) ^ s1 ^ s1 << 14; - this.s1 = Long.rotateLeft(s1, 36); - return result; - } - - @Override - protected int next(int bits) { - return ((int) nextLong()) >>> (32 - bits); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Listeners.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Listeners.java deleted file mode 100644 index 6bb87099..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Listeners.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.junit.runner.notification.RunListener; -import org.junit.runner.notification.RunNotifier; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; - -/** - * Annotate your suite class with this annotation to automatically add hooks to - * the {@link RunNotifier} used for executing tests inside - * {@link RandomizedRunner}. - * - * @see #value() - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -public @interface Listeners { - /** - * An array of listener classes. These classes must be instantiable (public, static, no-args - * constructor, etc.). - */ - Class[] value(); -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Name.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Name.java deleted file mode 100644 index f674b71a..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Name.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.*; - -/** - * Used to annotate constructor parameters for parameterized tests. - * - * @see ParametersFactory - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.PARAMETER}) -public @interface Name { - public String value(); -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Nightly.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Nightly.java deleted file mode 100644 index 0dd5c7f7..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Nightly.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import com.carrotsearch.randomizedtesting.RandomizedTest; - -/** - * An annotation indicating a given test case (or suite) should run only during - * nightly tests. - * - *

      The notion of "nightly" tests is based on an assumption that these tests can - * take longer than usual or require more resources than usual. Nightly tests will - * be most commonly used with higher scaling multipliers as in - * ({@link RandomizedTest#SYSPROP_MULTIPLIER}.

      - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.TYPE}) -@Inherited -@TestGroup(enabled = false) -public @interface Nightly { - /** Additional description, if needed. */ - String value() default ""; -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ParametersFactory.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ParametersFactory.java deleted file mode 100644 index 834626f2..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ParametersFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.*; -import java.util.Formatter; - -/** - * Used to annotate methods providing parameters for parameterized tests. The method - * annotated as the factory must be static, public, parameterless and must have a return - * type assignable to {@link Iterable}<Object[]>. - * - *

      The iterable must return arrays conforming to the suite class's constructor - * with respect to the number and types of parameters. - * - *

      The constructor's parameters can be annotated with {@link Name} to provide - * more descriptive parameter names for test descriptions. - * - * @see Name - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) -public @interface ParametersFactory { - /** - * Use default argument formatting for test cases. - */ - public static final String DEFAULT_FORMATTING = "default"; - - /** - * Specify custom formatting for test names (constructor arguments). - * The string must be a valid argument to Java's built-in {@link Formatter}. - * Constructor arguments are available in the order they were returned - * from {@link ParametersFactory}. Not all arguments have to be used, - * for example: {@code foo=%1$s} would select only the second argument (indexes - * are zero-based). - */ - String argumentFormatting() default DEFAULT_FORMATTING; - - /** - * Shuffles the order of tests generated for the parameter set. - */ - boolean shuffle() default true; -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Repeat.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Repeat.java deleted file mode 100644 index 46e2e3a4..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Repeat.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Repeats randomized test case a given number of times. Repetitions can - * start with a different seed (predictably derived from the first one) or - * start from the same seed every time (useful to check if a given test is truly - * predictable for a given seed or not). - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.TYPE}) -@Inherited -public @interface Repeat { - /** - * Repeat this many iterations. Must be greater or equal 1. - */ - int iterations() default 1; - - /** - * Re-run all iterations with a constant seed. This may be helpful in checking - * if a given test is really predictably random. - */ - boolean useConstantSeed() default false; -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ReplicateOnEachVm.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ReplicateOnEachVm.java deleted file mode 100644 index 8c6e4b3c..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ReplicateOnEachVm.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - *

      Replicates the test class on each concurrent forked JVM. If only a single JVM - * is used for running tests, this annotation has no effect.

      - * - *

      The purpose of this annotation is to, for example, replicate a single test suite - * across multiple forked JVMs and then selectively ignore or execute tests on each - * JVM, depending on its number, providing poor-man's load balancing for individual - * test cases (test suites are balanced by the framework itself).

      - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -@Inherited -public @interface ReplicateOnEachVm {} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Seed.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Seed.java deleted file mode 100644 index 8ef6fc3d..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Seed.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import com.carrotsearch.randomizedtesting.SysGlobals; - -/** - * Defines the starting seed for a given test or the entire suite. - * - *

      If applied to the - * suite, it semantically overrides {@link SysGlobals#SYSPROP_RANDOM_SEED}, but - * does not affect individual test cases (these should be repeatable anyway).

      - * - *

      If applied to the method, it overrides the default randomized value that is derived - * from the global suite's seed.

      - * - *

      Typically, you'll want to override the class's seed to make the test repeat a "fixed" - * scenario. Occasionally if there's a single failing test case for repeated tests, one - * may want to override both to fix both the class's randomness and a given test case randomness. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.TYPE}) -@Inherited -public @interface Seed { - /** - * The seed expressed as a hexadecimal long number or a string random to - * indicate randomized seed should be used (default value). - * - *

      The default value random can be used to construct a list of known - * seeds for which a test previously failed and a random seed in addition to that (coverage - * of previous failures + randomized run). See {@link Seeds} for more info. - */ - String value() default "random"; -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/SeedDecorators.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/SeedDecorators.java deleted file mode 100644 index 45926fec..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/SeedDecorators.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.*; - -import com.carrotsearch.randomizedtesting.SeedDecorator; - -/** - * Allows modifying the master seed (before the suite is started). - * - *

      Use this annotation when you want to perturb or modify the master seed. This may be - * useful if there are decisions taken in static contexts of multiple suites. In such a case - * these decisions would always be identical (because at static context level the seed is - * always derived from the same master). With a {@link SeedDecorator} one can perturb - * the seed for every suite. - * - *

        - *
      • Extra care should be used to make permutations consistent across different runs.
      • - *
      • Seed decorators must be thread-safe, re-entrable, preferably unsynchronized and - * must never fail!
      • - *
      - * - * @see #value() - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -public @interface SeedDecorators { - /** - * - */ - Class[] value(); -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Seeds.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Seeds.java deleted file mode 100644 index ae238173..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Seeds.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Defines a list of starting seeds for a given test. - * - *

      Typically, you'll want to override the class's seed to make the test repeat a "fixed" - * scenario in which the test was known to fail in the past. In addition, you may still permit - * a randomized seed by adding a non-restricted {@link Seed} as in:

      - *
      - * {@literal @}{@link Seeds}({
      - *   {@literal @}{@link Seed}("deadbeef"),
      - *   {@literal @}{@link Seed}("cafebabe"), 
      - *   {@literal @}{@link Seed}()})
      - * 
      - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) -@Inherited -public @interface Seeds { - /** - * A non-empty array of {@link Seed}s. - */ - Seed [] value(); -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/SuppressForbidden.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/SuppressForbidden.java deleted file mode 100644 index 1ad2647e..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/SuppressForbidden.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Suppresses forbidden-API checks. - */ -@Retention(RetentionPolicy.CLASS) -@Target({ - ElementType.CONSTRUCTOR, - ElementType.FIELD, - ElementType.METHOD, - ElementType.TYPE }) -public @interface SuppressForbidden { - String value(); -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestCaseInstanceProvider.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestCaseInstanceProvider.java deleted file mode 100644 index 6b2400a5..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestCaseInstanceProvider.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Determines how instances of the test suite class are created for each test - * case. - * - * By default JUnit creates a new class instance for every test to prevent test - * case ordering dependencies. This is sometimes inconvenient as there is no - * "suite" context other than static fields (which are a nuisance to clean up - * properly, for example). This annotation changes the default behavior and - * permits the test cases to be executed on the same instance, for example. - * - * Note that special care should be given to scenarios in which same-instance is - * reused with arguments provided via {@link ParametersFactory} (each set of - * parameters will create a separate instance, which will then be used to run - * all of test suite's test cases). - * - * Note that the same instance will be used if the test cases are multiplied - * with {@link Seeds} or {@link Repeat} annotations. - * - * @see TestCaseInstanceProvider.Type#INSTANCE_PER_TEST_METHOD - * @see TestCaseInstanceProvider.Type#INSTANCE_PER_CONSTRUCTOR_ARGS - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -@Inherited -public @interface TestCaseInstanceProvider { - public static enum Type { - /** - * Each method (test case) will receive a new instance of the class. This is - * JUnit's default. - */ - INSTANCE_PER_TEST_METHOD, - - /** - * Each set of constructor arguments (provided from - * {@link ParametersFactory} or the default empty constructor) creates an - * instance that is then reused for all of the suite's tests. - */ - INSTANCE_PER_CONSTRUCTOR_ARGS; - } - - Type value() default Type.INSTANCE_PER_TEST_METHOD; -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestCaseOrdering.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestCaseOrdering.java deleted file mode 100644 index e58fa1e5..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestCaseOrdering.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.Comparator; - -import com.carrotsearch.randomizedtesting.TestMethodAndParams; - -/** - * Test case ordering. The returned comparator will be used for sorting - * all {@link TestMethodAndParams} entries, where method is the test method - * and params are potential parameters to the constructor for a given - * test (if {@link ParametersFactory} is used). - * - * The sort is stable with respect to the original (shuffled) order of - * test cases. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -@Inherited -public @interface TestCaseOrdering { - /** - * The comparator used to sort all test cases. - * - * @see TestCaseOrdering - */ - Class> value(); - - /** - * Alphabetic, increasing order by method name. - */ - public static class AlphabeticOrder implements Comparator { - @Override - public int compare(TestMethodAndParams o1, TestMethodAndParams o2) { - return o1.getTestMethod().getName().compareTo( - o2.getTestMethod().getName()); - } - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestContextRandomSupplier.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestContextRandomSupplier.java deleted file mode 100644 index 36cfaf7e..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestContextRandomSupplier.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.Random; - -import com.carrotsearch.randomizedtesting.RandomSupplier; -import com.carrotsearch.randomizedtesting.RandomizedContext; - -/** - * A supplier of {@link Random} instances for the {@link RandomizedContext}. The supplier class must declare - * a public no-arg constructor. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -@Inherited -public @interface TestContextRandomSupplier { - Class value(); -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestGroup.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestGroup.java deleted file mode 100644 index f3232283..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestGroup.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.Annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.Locale; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.SysGlobals; - -/** - * A test group applied to an annotation indicates that a given annotation - * can be used on individual tests as "labels". The meaning of these labels is - * mostly application-specific (example: {@link Nightly} which indicates slower, - * more intensive tests that are skipped during regular runs). - * - *

      {@link RandomizedRunner} collects groups from all tests in a suite. A group - * can be enabled or disabled using boolean system properties (or test - * hooks in the code). A test case is executed if it has no groups or if all of its groups - * are enabled. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.ANNOTATION_TYPE}) -@Inherited -public @interface TestGroup { - /** - * The name of a test group. If not defined, the default (lowercased annotation - * name) is used. - */ - String name() default ""; - - /** - * System property used to enable/ disable a group. If empty, a default is used: - *

      -   * tests.name
      -   * 
      - */ - String sysProperty() default ""; - - /** - * Is the group enabled or disabled by default (unless overridden by test group filtering - * rules). - */ - boolean enabled() default true; - - /** - * Utilities to deal with annotations annotated with {@link TestGroup}. - */ - public static class Utilities { - public static String getGroupName(Class annotationClass) { - TestGroup testGroup = annotationClass.getAnnotation(TestGroup.class); - if (testGroup == null) - throw new IllegalArgumentException("Annotation must have a @TestGroup annotation: " - + annotationClass); - - String tmp = emptyToNull(testGroup.name()); - return tmp == null ? annotationClass.getSimpleName().toLowerCase(Locale.ROOT) : tmp; - } - - public static String getSysProperty(Class annotationClass) { - TestGroup testGroup = annotationClass.getAnnotation(TestGroup.class); - if (testGroup == null) - throw new IllegalArgumentException("Annotation must have a @TestGroup annotation: " - + annotationClass); - - String tmp = emptyToNull(testGroup.sysProperty()); - return (tmp != null ? tmp : SysGlobals.prefixProperty(getGroupName(annotationClass))); - } - - private static String emptyToNull(String value) { - if (value == null || value.trim().isEmpty()) - return null; - return value.trim(); - } - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestMethodProviders.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestMethodProviders.java deleted file mode 100644 index c485afcc..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TestMethodProviders.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import com.carrotsearch.randomizedtesting.TestMethodProvider; - -/** - * Test case method provider. - * - * TODO: it would be nice to have an _instance_ provider as opposed to method provider, - * but it's hellishly difficult to integrate with the rest of the infrastructure (seeds, - * repetitions, etc.). - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -@Inherited -public @interface TestMethodProviders { - Class[] value(); -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakAction.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakAction.java deleted file mode 100644 index 42410443..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakAction.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.TYPE}) -@Inherited -public @interface ThreadLeakAction { - public static enum Action { - /** Emit a warning using Java's logging system. */ - WARN, - - /** Try to {@link Thread#interrupt()} any leaked threads. */ - INTERRUPT; - }; - - Action [] value() default { Action.WARN, Action.INTERRUPT }; -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakFilters.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakFilters.java deleted file mode 100644 index 018b6503..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakFilters.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import com.carrotsearch.randomizedtesting.ThreadFilter; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -@Inherited -public @interface ThreadLeakFilters { - boolean defaultFilters() default true; - Class [] filters() default {}; -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakGroup.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakGroup.java deleted file mode 100644 index a05002d2..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakGroup.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -@Inherited -public @interface ThreadLeakGroup { - public static enum Group { - /** - * All JVM threads will be tracked. - * - *

      WARNING: This option will not work - * on IBM J9 because of livelock bugs in {@link Thread#getAllStackTraces()}. - */ - ALL, - - /** - * The "main" thread group and descendants will be tracked. - */ - MAIN, - - /** - * Only per-suite test group and descendants will be tracked. - */ - TESTGROUP - } - - Group value() default Group.MAIN; -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakLingering.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakLingering.java deleted file mode 100644 index 0d7f3a0d..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakLingering.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.Timer; -import java.util.concurrent.Executors; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.TYPE}) -@Inherited -public @interface ThreadLeakLingering { - /** - * Time in millis to "linger" for any left-behind threads. If equals 0, there - * is no waiting. - * - *

      - * This is particularly useful if there's no way to {@link Thread#join()} and - * wait for the potential forked threads to terminate. This is the case with - * {@link Timer} or {@link Executors} for example. - */ - int linger() default 0; -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakScope.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakScope.java deleted file mode 100644 index 5daf6eec..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakScope.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.junit.ClassRule; -import org.junit.Rule; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -@Inherited -public @interface ThreadLeakScope { - public static enum Scope { - /** - * No thread leaks from any individual test (including {@link Rule}s) or the - * entire suite (including {@link ClassRule}s). - */ - TEST, - - /** - * No thread leaks from entire suite scope (individual tests may leak threads, - * they become part of the suite scope). - */ - SUITE, - - /** - * No thread leak checks at all. Highly discouraged. - */ - NONE - } - - Scope value() default Scope.TEST; -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakZombies.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakZombies.java deleted file mode 100644 index bfff252d..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/ThreadLeakZombies.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -@Inherited -public @interface ThreadLeakZombies { - public static enum Consequence { - /** - * Continue execution with zombie threads running in the background as if - * nothing happened. This is NOT a good idea because zombie threads may be - * fiddling with the test instance or static fields. It is strongly - * recommended to use a combination of - * {@link ThreadLeakAction.Action#INTERRUPT} together with - * {@link #IGNORE_REMAINING_TESTS} to enforce interruption of leaked threads - * and if this does not succeed just ignore any tests further on. - *

      - * For the reasons outlined above, this enum flag is marked as - * {@link Deprecated}. It will be supported and will not be removed, - * however. - */ - @Deprecated - CONTINUE, - - /** - * Ignore any remaining tests once zombie threads have been detected. See - * {@link #CONTINUE} for joint use with {@link ThreadLeakAction}. - */ - IGNORE_REMAINING_TESTS; - }; - - Consequence value() default Consequence.IGNORE_REMAINING_TESTS; -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Timeout.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Timeout.java deleted file mode 100644 index 94715002..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/Timeout.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.rules.TestRule; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.SysGlobals; - -/** - * Maximum execution time for a single test method. Test methods are defined as - * any instance-scope {@link TestRule}s, {@link Before} and {@link After} hooks - * and {@link Test} methods. Suite class's constructor is not part of the - * measured code (see {@link TimeoutSuite}). - * - *

      - * Overrides a global default {@link RandomizedRunner#DEFAULT_TIMEOUT} or a - * system property override {@link SysGlobals#SYSPROP_TIMEOUT}. - * - * @see TimeoutSuite - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.TYPE}) -@Inherited -public @interface Timeout { - /** - * Timeout time in millis. The timeout time is approximate, it may take longer - * to actually abort the test case. - */ - public int millis(); -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TimeoutSuite.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TimeoutSuite.java deleted file mode 100644 index ea55d58c..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/annotations/TimeoutSuite.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.carrotsearch.randomizedtesting.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.rules.TestRule; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.SysGlobals; - -/** - * Maximum execution time for an entire suite (including all hooks and tests). - * Suite is defined as any class-scope {@link TestRule}s, {@link BeforeClass} - * and {@link AfterClass} hooks, suite class's constructor, instance-scope - * {@link TestRule}s, {@link Before} and {@link After} hooks and {@link Test} - * methods. - * - *

      - * The suite class's static initializer is not part of the measured code - * (if you have static initializers in your tests, get rid of them). - * - *

      - * Overrides the global default {@link RandomizedRunner#DEFAULT_TIMEOUT} or a - * system property override {@link SysGlobals#SYSPROP_TIMEOUT}. - * - * @see Timeout - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -@Inherited -public @interface TimeoutSuite { - /** - * Timeout time in millis. The timeout time is approximate, it may take longer - * to actually abort the suite. - */ - public int millis(); -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/ASCIIGenerator.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/ASCIIGenerator.java deleted file mode 100644 index a2071088..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/ASCIIGenerator.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -/** - * A generator emitting simple ASCII characters from the set - * (newlines not counted): - *

      - * abcdefghijklmnopqrstuvwxyz
      - * ABCDEFGHIJKLMNOPQRSTUVWXYZ
      - * 
      - * - * @deprecated Use {@link AsciiLettersGenerator} instead. - */ -@Deprecated -public class ASCIIGenerator extends AsciiLettersGenerator { - -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/AsciiAlphanumGenerator.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/AsciiAlphanumGenerator.java deleted file mode 100644 index 8fce59c8..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/AsciiAlphanumGenerator.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -/** - * A generator emitting simple ASCII alphanumeric letters and numbers - * from the set (newlines not counted): - *
      - * abcdefghijklmnopqrstuvwxyz
      - * ABCDEFGHIJKLMNOPQRSTUVWXYZ
      - * 0123456789
      - * 
      - */ -public class AsciiAlphanumGenerator extends CodepointSetGenerator { - private final static char [] CHARS = - ("abcdefghijklmnopqrstuvwxyz" + - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + - "0123456789").toCharArray(); - - public AsciiAlphanumGenerator() { - super(CHARS); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/AsciiLettersGenerator.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/AsciiLettersGenerator.java deleted file mode 100644 index 81cc2f08..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/AsciiLettersGenerator.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -/** - * A generator emitting simple ASCII characters from the set - * (newlines not counted): - *
      - * abcdefghijklmnopqrstuvwxyz
      - * ABCDEFGHIJKLMNOPQRSTUVWXYZ
      - * 
      - */ -public class AsciiLettersGenerator extends CodepointSetGenerator { - private final static char [] CHARS = - ("abcdefghijklmnopqrstuvwxyz" + - "ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray(); - - public AsciiLettersGenerator() { - super(CHARS); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/BiasedNumbers.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/BiasedNumbers.java deleted file mode 100644 index c11d4c50..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/BiasedNumbers.java +++ /dev/null @@ -1,270 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -import java.util.Random; - -/** - * Utility classes for selecting numbers at random, but not necessarily - * in an uniform way. The implementation will try to pick "evil" numbers - * more often than uniform selection would. This includes exact range - * boundaries, numbers very close to range boundaries, numbers very close - * (or equal) to zero, etc. - * - * The exact method of selection is implementation-dependent and - * may change (if we find even more evil ways). - */ -public final class BiasedNumbers { - private static final int EVIL_RANGE_LEFT = 1; - private static final int EVIL_RANGE_RIGHT = 1; - private static final int EVIL_VERY_CLOSE_RANGE_ENDS = 20; - private static final int EVIL_ZERO_OR_NEAR = 5; - private static final int EVIL_SIMPLE_PROPORTION = 10; - private static final int EVIL_RANDOM_REPRESENTATION_BITS = 10; - - /** - * A random double between min (inclusive) and max - * (inclusive). If you wish to have an exclusive range, - * use {@link Math#nextAfter(double, double)} to adjust the range. - * - * The code was inspired by GeoTestUtil from Apache Lucene. - * - * @param min Left range boundary, inclusive. May be {@link Double#NEGATIVE_INFINITY}, but not NaN. - * @param max Right range boundary, inclusive. May be {@link Double#POSITIVE_INFINITY}, but not NaN. - */ - public static double randomDoubleBetween(Random r, double min, double max) { - assert max >= min : "max must be >= min: " + min + ", " + max; - assert !Double.isNaN(min) && !Double.isNaN(max); - - boolean hasZero = min <= 0 && max >= 0; - - int pick = r.nextInt( - EVIL_RANGE_LEFT + - EVIL_RANGE_RIGHT + - EVIL_VERY_CLOSE_RANGE_ENDS + - (hasZero ? EVIL_ZERO_OR_NEAR : 0) + - EVIL_SIMPLE_PROPORTION + - EVIL_RANDOM_REPRESENTATION_BITS); - - // Exact range ends - pick -= EVIL_RANGE_LEFT; - if (pick < 0 || min == max) { - return min; - } - - pick -= EVIL_RANGE_RIGHT; - if (pick < 0) { - return max; - } - - // If we're dealing with infinities, adjust them to discrete values. - assert min != max; - if (Double.isInfinite(min)) { - min = Math.nextUp(min); - } - if (Double.isInfinite(max)) { - max = Math.nextAfter(max, Double.NEGATIVE_INFINITY); - } - - // Numbers "very" close to range ends. "very" means a few floating point - // representation steps (ulps) away. - pick -= EVIL_VERY_CLOSE_RANGE_ENDS; - if (pick < 0) { - if (r.nextBoolean()) { - return fuzzUp(r, min, max); - } else { - return fuzzDown(r, max, min); - } - } - - // Zero or near-zero values, if within the range. - if (hasZero) { - pick -= EVIL_ZERO_OR_NEAR; - if (pick < 0) { - int v = r.nextInt(4); - if (v == 0) { - return 0d; - } else if (v == 1) { - return -0.0d; - } else if (v == 2) { - return fuzzDown(r, 0d, min); - } else if (v == 3) { - return fuzzUp(r, 0d, max); - } - } - } - - // Simple proportional selection. - pick -= EVIL_SIMPLE_PROPORTION; - if (pick < 0) { - return min + (max - min) * r.nextDouble(); - } - - // Random representation space selection. This will be heavily biased - // and overselect from the set of tiny values, if they're allowed. - pick -= EVIL_RANDOM_REPRESENTATION_BITS; - if (pick < 0) { - long from = toSortable(min); - long to = toSortable(max); - return fromSortable(RandomNumbers.randomLongBetween(r, from, to)); - } - - throw new RuntimeException("Unreachable."); - } - - /** - * Fuzzify the input value by decreasing it by a few ulps, but never past min. - */ - public static double fuzzDown(Random r, double v, double min) { - assert v >= min; - for (int steps = RandomNumbers.randomIntBetween(r, 1, 10); steps > 0 && v > min; steps--) { - v = Math.nextAfter(v, Double.NEGATIVE_INFINITY); - } - return v; - } - - /** - * Fuzzify the input value by increasing it by a few ulps, but never past max. - */ - public static double fuzzUp(Random r, double v, double max) { - assert v <= max; - for (int steps = RandomNumbers.randomIntBetween(r, 1, 10); steps > 0 && v < max; steps--) { - v = Math.nextUp(v); - } - return v; - } - - private static double fromSortable(long sortable) { - return Double.longBitsToDouble(flip(sortable)); - } - - private static long toSortable(double value) { - return flip(Double.doubleToLongBits(value)); - } - - private static long flip(long bits) { - return bits ^ (bits >> 63) & 0x7fffffffffffffffL; - } - - /** - * A random float between min (inclusive) and max - * (inclusive). If you wish to have an exclusive range, - * use {@link Math#nextAfter(float, double)} to adjust the range. - * - * The code was inspired by GeoTestUtil from Apache Lucene. - * - * @param min Left range boundary, inclusive. May be {@link Float#NEGATIVE_INFINITY}, but not NaN. - * @param max Right range boundary, inclusive. May be {@link Float#POSITIVE_INFINITY}, but not NaN. - */ - public static float randomFloatBetween(Random r, float min, float max) { - assert max >= min : "max must be >= min: " + min + ", " + max; - assert !Float.isNaN(min) && !Float.isNaN(max); - - boolean hasZero = min <= 0 && max >= 0; - - int pick = r.nextInt( - EVIL_RANGE_LEFT + - EVIL_RANGE_RIGHT + - EVIL_VERY_CLOSE_RANGE_ENDS + - (hasZero ? EVIL_ZERO_OR_NEAR : 0) + - EVIL_SIMPLE_PROPORTION + - EVIL_RANDOM_REPRESENTATION_BITS); - - // Exact range ends - pick -= EVIL_RANGE_LEFT; - if (pick < 0 || min == max) { - return min; - } - - pick -= EVIL_RANGE_RIGHT; - if (pick < 0) { - return max; - } - - // If we're dealing with infinities, adjust them to discrete values. - assert min != max; - if (Float.isInfinite(min)) { - min = Math.nextUp(min); - } - if (Float.isInfinite(max)) { - max = Math.nextAfter(max, Double.NEGATIVE_INFINITY); - } - - // Numbers "very" close to range ends. "very" means a few floating point - // representation steps (ulps) away. - pick -= EVIL_VERY_CLOSE_RANGE_ENDS; - if (pick < 0) { - if (r.nextBoolean()) { - return fuzzUp(r, min, max); - } else { - return fuzzDown(r, max, min); - } - } - - // Zero or near-zero values, if within the range. - if (hasZero) { - pick -= EVIL_ZERO_OR_NEAR; - if (pick < 0) { - int v = r.nextInt(4); - if (v == 0) { - return 0f; - } else if (v == 1) { - return -0.0f; - } else if (v == 2) { - return fuzzDown(r, 0f, min); - } else if (v == 3) { - return fuzzUp(r, 0f, max); - } - } - } - - // Simple proportional selection. - pick -= EVIL_SIMPLE_PROPORTION; - if (pick < 0) { - return (float) (min + (((double) max - min) * r.nextDouble())); - } - - // Random representation space selection. This will be heavily biased - // and overselect from the set of tiny values, if they're allowed. - pick -= EVIL_RANDOM_REPRESENTATION_BITS; - if (pick < 0) { - int from = toSortable(min); - int to = toSortable(max); - return fromSortable(RandomNumbers.randomIntBetween(r, from, to)); - } - - throw new RuntimeException("Unreachable."); - } - - /** - * Fuzzify the input value by decreasing it by a few ulps, but never past min. - */ - public static float fuzzDown(Random r, float v, float min) { - assert v >= min; - for (int steps = RandomNumbers.randomIntBetween(r, 1, 10); steps > 0 && v > min; steps--) { - v = Math.nextAfter(v, Double.NEGATIVE_INFINITY); - } - return v; - } - - /** - * Fuzzify the input value by increasing it by a few ulps, but never past max. - */ - public static float fuzzUp(Random r, float v, float max) { - assert v <= max; - for (int steps = RandomNumbers.randomIntBetween(r, 1, 10); steps > 0 && v < max; steps--) { - v = Math.nextUp(v); - } - return v; - } - - private static float fromSortable(int sortable) { - return Float.intBitsToFloat(flip(sortable)); - } - - private static int toSortable(float value) { - return flip(Float.floatToIntBits(value)); - } - - private static int flip(int floatBits) { - return floatBits ^ (floatBits >> 31) & 0x7fffffff; - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/CodepointSetGenerator.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/CodepointSetGenerator.java deleted file mode 100644 index 7de5909d..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/CodepointSetGenerator.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -import java.util.Random; - -/** - * A string generator from a predefined set of codepoints or characters. - */ -public class CodepointSetGenerator extends StringGenerator { - final int [] bmp; - final int [] supplementary; - final int [] all; - - /** - * All characters must be from BMP (no parts of surrogate pairs allowed). - */ - public CodepointSetGenerator(char[] chars) { - this.bmp = new int [chars.length]; - this.supplementary = new int [0]; - - for (int i = 0; i < chars.length; i++) { - bmp[i] = ((int) chars[i]) & 0xffff; - - if (isSurrogate(chars[i])) { - throw new IllegalArgumentException("Value is part of a surrogate pair: 0x" - + Integer.toHexString(bmp[i])); - } - } - - this.all = concat(bmp, supplementary); - if (all.length == 0) { - throw new IllegalArgumentException("Empty set of characters?"); - } - } - - /** - * Parse the given {@link String} and split into BMP and supplementary codepoints. - */ - public CodepointSetGenerator(String s) { - int bmps = 0; - int supplementaries = 0; - for (int i = 0; i < s.length();) { - int codepoint = s.codePointAt(i); - if (Character.isSupplementaryCodePoint(codepoint)) { - supplementaries++; - } else { - bmps++; - } - - i += Character.charCount(codepoint); - } - - this.bmp = new int [bmps]; - this.supplementary = new int [supplementaries]; - for (int i = 0; i < s.length();) { - int codepoint = s.codePointAt(i); - if (Character.isSupplementaryCodePoint(codepoint)) { - supplementary[--supplementaries] = codepoint; - } else { - bmp[--bmps] = codepoint; - } - - i += Character.charCount(codepoint); - } - - this.all = concat(bmp, supplementary); - if (all.length == 0) { - throw new IllegalArgumentException("Empty set of characters?"); - } - } - - @Override - public String ofCodeUnitsLength(Random r, int minCodeUnits, int maxCodeUnits) { - int length = RandomNumbers.randomIntBetween(r, minCodeUnits, maxCodeUnits); - - // Check and cater for odd number of code units if no bmp characters are given. - if (bmp.length == 0 && isOdd(length)) { - if (minCodeUnits == maxCodeUnits) { - throw new IllegalArgumentException("Cannot return an odd number of code units " - + " when surrogate pairs are the only available codepoints."); - } else { - // length is odd so we move forward or backward to the closest even number. - if (length == minCodeUnits) { - length++; - } else { - length--; - } - } - } - - int [] codepoints = new int [length]; - int actual = 0; - while (length > 0) { - if (length == 1) { - codepoints[actual] = bmp[r.nextInt(bmp.length)]; - } else { - codepoints[actual] = all[r.nextInt(all.length)]; - } - - if (Character.isSupplementaryCodePoint(codepoints[actual])) { - length -= 2; - } else { - length -= 1; - } - actual++; - } - return new String(codepoints, 0, actual); - } - - @Override - public String ofCodePointsLength(Random r, int minCodePoints, int maxCodePoints) { - int length = RandomNumbers.randomIntBetween(r, minCodePoints, maxCodePoints); - int [] codepoints = new int [length]; - while (length > 0) { - codepoints[--length] = all[r.nextInt(all.length)]; - } - return new String(codepoints, 0, codepoints.length); - } - - /** Is a given number odd? */ - private boolean isOdd(int v) { - return (v & 1) != 0; - } - - private int[] concat(int[]... arrays) { - int totalLength = 0; - for (int[] a : arrays) totalLength += a.length; - int [] concat = new int [totalLength]; - for (int i = 0, j = 0; j < arrays.length;) { - System.arraycopy(arrays[j], 0, concat, i, arrays[j].length); - i += arrays[j].length; - j++; - } - return concat; - } - - private boolean isSurrogate(char chr) { - return (chr >= 0xd800 && chr <= 0xdfff); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RandomBytes.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RandomBytes.java deleted file mode 100644 index 3e8a70f9..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RandomBytes.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -import java.util.Random; - -/** - * Random byte sequence generators. - */ -public final class RandomBytes { - /** - * @param r Random generator. - * @param length The length of the byte array. Can be zero. - * @return Returns a byte array with random content. - */ - public static byte[] randomBytesOfLength(Random r, int length) { - return randomBytesOfLengthBetween(r, length, length); - } - - /** - * @param r Random generator. - * @param minLength The minimum length of the byte array. Can be zero. - * @param maxLength The maximum length of the byte array. Can be zero. - * @return Returns a byte array with random content. - */ - public static byte[] randomBytesOfLengthBetween(Random r, int minLength, int maxLength) { - byte[] bytes = new byte[RandomNumbers.randomIntBetween(r, minLength, maxLength)]; - for (int i = 0; i < bytes.length; i++) { - bytes[i] = (byte) r.nextInt(); - } - return bytes; - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RandomNumbers.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RandomNumbers.java deleted file mode 100644 index d66f291c..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RandomNumbers.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -import java.util.Random; - -/** - * Utility classes for selecting random numbers from within a range or the - * numeric domain for a given type. - * - * @see BiasedNumbers - */ -public final class RandomNumbers { - /** - * A random integer between min (inclusive) and max (inclusive). - */ - public static int randomIntBetween(Random r, int min, int max) { - assert max >= min : "max must be >= min: " + min + ", " + max; - long range = (long) max - (long) min; - if (range < Integer.MAX_VALUE) { - return min + r.nextInt(1 + (int) range); - } else { - return toIntExact(min + nextLong(r, 1 + range)); - } - } - - /** - * A random long between min (inclusive) and max (inclusive). - */ - public static long randomLongBetween(Random r, long min, long max) { - assert max >= min : "max must be >= min: " + min + ", " + max; - long range = max - min; - if (range < 0) { - range -= Long.MAX_VALUE; - if (range == Long.MIN_VALUE) { - // Full spectrum. - return r.nextLong(); - } else { - long first = r.nextLong() & Long.MAX_VALUE; - long second = range == Long.MAX_VALUE ? (r.nextLong() & Long.MAX_VALUE) : nextLong(r, range + 1); - return min + first + second; - } - } else { - long second = range == Long.MAX_VALUE ? (r.nextLong() & Long.MAX_VALUE) : nextLong(r, range + 1); - return min + second; - } - } - - /** - * Similar to {@link Random#nextInt(int)}, but returns a long between - * 0 (inclusive) and n (exclusive). - * - * @param rnd Random generator. - * @param n the bound on the random number to be returned. Must be - * positive. - * @return Returns a random number between 0 and n-1. - */ - public static long nextLong(Random rnd, long n) { - if (n <= 0) { - throw new IllegalArgumentException("n <= 0: " + n); - } - - long value = rnd.nextLong(); - long range = n - 1; - if ((n & range) == 0L) { - value &= range; - } else { - for (long u = value >>> 1; u + range - (value = u % n) < 0L;) { - u = rnd.nextLong() >>> 1; - } - } - return value; - } - - private static int toIntExact(long value) { - if (value > Integer.MAX_VALUE) { - throw new ArithmeticException("Overflow: " + value); - } else { - return (int) value; - } - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RandomPicks.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RandomPicks.java deleted file mode 100644 index 2f153b1c..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RandomPicks.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Random; - -/** - * Random selections of objects. - */ -public final class RandomPicks { - public static byte randomFrom(Random r, byte [] array) { checkZeroLength(array.length); return array[r.nextInt(array.length)]; } - public static short randomFrom(Random r, short [] array) { checkZeroLength(array.length); return array[r.nextInt(array.length)]; } - public static int randomFrom(Random r, int [] array) { checkZeroLength(array.length); return array[r.nextInt(array.length)]; } - public static char randomFrom(Random r, char [] array) { checkZeroLength(array.length); return array[r.nextInt(array.length)]; } - public static float randomFrom(Random r, float [] array) { checkZeroLength(array.length); return array[r.nextInt(array.length)]; } - public static long randomFrom(Random r, long [] array) { checkZeroLength(array.length); return array[r.nextInt(array.length)]; } - public static double randomFrom(Random r, double [] array) { checkZeroLength(array.length); return array[r.nextInt(array.length)]; } - - private static void checkZeroLength(int length) { - if (length == 0) { - throw new IllegalArgumentException("Can't pick a random object from an empty array."); - } - } - - /** - * Pick a random object from the given array. - */ - public static T randomFrom(Random r, T [] array) { - checkZeroLength(array.length); - return array[r.nextInt(array.length)]; - } - - /** - * Pick a random object from the given list. - */ - public static T randomFrom(Random r, List list) { - if (list.size() == 0) { - throw new IllegalArgumentException("Can't pick a random object from an empty list."); - } - return list.get(r.nextInt(list.size())); - } - - /** - * Pick a random object from the collection. Requires linear scanning. - */ - public static T randomFrom(Random r, Collection collection) { - final int size = collection.size(); - if (size == 0) { - throw new IllegalArgumentException("Can't pick a random object from an empty collection."); - } - int pick = r.nextInt(size); - T value = null; - for (Iterator i = collection.iterator();; pick--) { - value = i.next(); - if (pick == 0) { - break; - } - } - return value; - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RandomStrings.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RandomStrings.java deleted file mode 100644 index 6c580fe4..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RandomStrings.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -import java.util.Random; - -/** - * A facade to various implementations of {@link StringGenerator} interface. - */ -public final class RandomStrings { - public final static RealisticUnicodeGenerator realisticUnicodeGenerator = new RealisticUnicodeGenerator(); - public final static UnicodeGenerator unicodeGenerator = new UnicodeGenerator(); - public final static AsciiLettersGenerator asciiLettersGenerator = new AsciiLettersGenerator(); - public final static AsciiAlphanumGenerator asciiAlphanumGenerator = new AsciiAlphanumGenerator(); - - /** - * @deprecated Use {@link RandomStrings#asciiLettersGenerator} instead. - */ - @Deprecated - public final static ASCIIGenerator asciiGenerator = new ASCIIGenerator(); - - // Ultra wide monitor required to read the source code :) - - /** @deprecated Use {@link #randomAsciiLettersOfLengthBetween} instead. */ - @Deprecated - public static String randomAsciiOfLengthBetween (Random r, int minCodeUnits, int maxCodeUnits) {return asciiGenerator.ofCodeUnitsLength(r, minCodeUnits, maxCodeUnits); } - - /** @deprecated Use {@link #randomAsciiLettersOfLength} instead. */ - @Deprecated - public static String randomAsciiOfLength (Random r, int codeUnits) {return asciiGenerator.ofCodeUnitsLength(r, codeUnits, codeUnits); } - - public static String randomAsciiLettersOfLengthBetween (Random r, int minCodeUnits, int maxCodeUnits) {return asciiLettersGenerator.ofCodeUnitsLength(r, minCodeUnits, maxCodeUnits); } - public static String randomAsciiLettersOfLength (Random r, int codeUnits) {return asciiLettersGenerator.ofCodeUnitsLength(r, codeUnits, codeUnits); } - - public static String randomAsciiAlphanumOfLengthBetween (Random r, int minCodeUnits, int maxCodeUnits) {return asciiAlphanumGenerator.ofCodeUnitsLength(r, minCodeUnits, maxCodeUnits); } - public static String randomAsciiAlphanumOfLength (Random r, int codeUnits) {return asciiAlphanumGenerator.ofCodeUnitsLength(r, codeUnits, codeUnits); } - - public static String randomUnicodeOfLengthBetween (Random r, int minCodeUnits, int maxCodeUnits) {return unicodeGenerator.ofCodeUnitsLength(r, minCodeUnits, maxCodeUnits); } - public static String randomUnicodeOfLength (Random r, int codeUnits) {return unicodeGenerator.ofCodeUnitsLength(r, codeUnits, codeUnits); } - public static String randomUnicodeOfCodepointLengthBetween (Random r, int minCodePoints, int maxCodePoints) {return unicodeGenerator.ofCodePointsLength(r, minCodePoints, maxCodePoints); } - public static String randomUnicodeOfCodepointLength (Random r, int codePoints) {return unicodeGenerator.ofCodePointsLength(r, codePoints, codePoints); } - - public static String randomRealisticUnicodeOfLengthBetween (Random r, int minCodeUnits, int maxCodeUnits) {return realisticUnicodeGenerator.ofCodeUnitsLength(r, minCodeUnits, maxCodeUnits); } - public static String randomRealisticUnicodeOfLength (Random r, int codeUnits) {return realisticUnicodeGenerator.ofCodeUnitsLength(r, codeUnits, codeUnits); } - public static String randomRealisticUnicodeOfCodepointLengthBetween (Random r, int minCodePoints, int maxCodePoints) {return realisticUnicodeGenerator.ofCodePointsLength(r, minCodePoints, maxCodePoints); } - public static String randomRealisticUnicodeOfCodepointLength (Random r, int codePoints) {return realisticUnicodeGenerator.ofCodePointsLength(r, codePoints, codePoints); } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RealisticUnicodeGenerator.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RealisticUnicodeGenerator.java deleted file mode 100644 index 786e060d..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/RealisticUnicodeGenerator.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -import java.util.Random; - -/** - * A string generator that emits valid unicodeGenerator codepoints. - */ -public class RealisticUnicodeGenerator extends StringGenerator { - /** Index-aligned with {@link #blockEnds}. */ - private static final int[] blockStarts = { - 0x0000, 0x0080, 0x0100, 0x0180, 0x0250, 0x02B0, 0x0300, 0x0370, 0x0400, - 0x0500, 0x0530, 0x0590, 0x0600, 0x0700, 0x0750, 0x0780, 0x07C0, 0x0800, - 0x0900, 0x0980, 0x0A00, 0x0A80, 0x0B00, 0x0B80, 0x0C00, 0x0C80, 0x0D00, - 0x0D80, 0x0E00, 0x0E80, 0x0F00, 0x1000, 0x10A0, 0x1100, 0x1200, 0x1380, - 0x13A0, 0x1400, 0x1680, 0x16A0, 0x1700, 0x1720, 0x1740, 0x1760, 0x1780, - 0x1800, 0x18B0, 0x1900, 0x1950, 0x1980, 0x19E0, 0x1A00, 0x1A20, 0x1B00, - 0x1B80, 0x1C00, 0x1C50, 0x1CD0, 0x1D00, 0x1D80, 0x1DC0, 0x1E00, 0x1F00, - 0x2000, 0x2070, 0x20A0, 0x20D0, 0x2100, 0x2150, 0x2190, 0x2200, 0x2300, - 0x2400, 0x2440, 0x2460, 0x2500, 0x2580, 0x25A0, 0x2600, 0x2700, 0x27C0, - 0x27F0, 0x2800, 0x2900, 0x2980, 0x2A00, 0x2B00, 0x2C00, 0x2C60, 0x2C80, - 0x2D00, 0x2D30, 0x2D80, 0x2DE0, 0x2E00, 0x2E80, 0x2F00, 0x2FF0, 0x3000, - 0x3040, 0x30A0, 0x3100, 0x3130, 0x3190, 0x31A0, 0x31C0, 0x31F0, 0x3200, - 0x3300, 0x3400, 0x4DC0, 0x4E00, 0xA000, 0xA490, 0xA4D0, 0xA500, 0xA640, - 0xA6A0, 0xA700, 0xA720, 0xA800, 0xA830, 0xA840, 0xA880, 0xA8E0, 0xA900, - 0xA930, 0xA960, 0xA980, 0xAA00, 0xAA60, 0xAA80, 0xABC0, 0xAC00, 0xD7B0, - 0xE000, 0xF900, 0xFB00, 0xFB50, 0xFE00, 0xFE10, - 0xFE20, 0xFE30, 0xFE50, 0xFE70, 0xFF00, 0xFFF0, - 0x10000, 0x10080, 0x10100, 0x10140, 0x10190, 0x101D0, 0x10280, 0x102A0, - 0x10300, 0x10330, 0x10380, 0x103A0, 0x10400, 0x10450, 0x10480, 0x10800, - 0x10840, 0x10900, 0x10920, 0x10A00, 0x10A60, 0x10B00, 0x10B40, 0x10B60, - 0x10C00, 0x10E60, 0x11080, 0x12000, 0x12400, 0x13000, 0x1D000, 0x1D100, - 0x1D200, 0x1D300, 0x1D360, 0x1D400, 0x1F000, 0x1F030, 0x1F100, 0x1F200, - 0x20000, 0x2A700, 0x2F800, 0xE0000, 0xE0100, 0xF0000, 0x100000 - }; - - /** Index-aligned with {@link #blockStarts}. */ - private static final int[] blockEnds = { - 0x007F, 0x00FF, 0x017F, 0x024F, 0x02AF, 0x02FF, 0x036F, 0x03FF, 0x04FF, - 0x052F, 0x058F, 0x05FF, 0x06FF, 0x074F, 0x077F, 0x07BF, 0x07FF, 0x083F, - 0x097F, 0x09FF, 0x0A7F, 0x0AFF, 0x0B7F, 0x0BFF, 0x0C7F, 0x0CFF, 0x0D7F, - 0x0DFF, 0x0E7F, 0x0EFF, 0x0FFF, 0x109F, 0x10FF, 0x11FF, 0x137F, 0x139F, - 0x13FF, 0x167F, 0x169F, 0x16FF, 0x171F, 0x173F, 0x175F, 0x177F, 0x17FF, - 0x18AF, 0x18FF, 0x194F, 0x197F, 0x19DF, 0x19FF, 0x1A1F, 0x1AAF, 0x1B7F, - 0x1BBF, 0x1C4F, 0x1C7F, 0x1CFF, 0x1D7F, 0x1DBF, 0x1DFF, 0x1EFF, 0x1FFF, - 0x206F, 0x209F, 0x20CF, 0x20FF, 0x214F, 0x218F, 0x21FF, 0x22FF, 0x23FF, - 0x243F, 0x245F, 0x24FF, 0x257F, 0x259F, 0x25FF, 0x26FF, 0x27BF, 0x27EF, - 0x27FF, 0x28FF, 0x297F, 0x29FF, 0x2AFF, 0x2BFF, 0x2C5F, 0x2C7F, 0x2CFF, - 0x2D2F, 0x2D7F, 0x2DDF, 0x2DFF, 0x2E7F, 0x2EFF, 0x2FDF, 0x2FFF, 0x303F, - 0x309F, 0x30FF, 0x312F, 0x318F, 0x319F, 0x31BF, 0x31EF, 0x31FF, 0x32FF, - 0x33FF, 0x4DBF, 0x4DFF, 0x9FFF, 0xA48F, 0xA4CF, 0xA4FF, 0xA63F, 0xA69F, - 0xA6FF, 0xA71F, 0xA7FF, 0xA82F, 0xA83F, 0xA87F, 0xA8DF, 0xA8FF, 0xA92F, - 0xA95F, 0xA97F, 0xA9DF, 0xAA5F, 0xAA7F, 0xAADF, 0xABFF, 0xD7AF, 0xD7FF, - 0xF8FF, 0xFAFF, 0xFB4F, 0xFDFF, 0xFE0F, 0xFE1F, - 0xFE2F, 0xFE4F, 0xFE6F, 0xFEFF, 0xFFEF, 0xFFFF, - 0x1007F, 0x100FF, 0x1013F, 0x1018F, 0x101CF, 0x101FF, 0x1029F, 0x102DF, - 0x1032F, 0x1034F, 0x1039F, 0x103DF, 0x1044F, 0x1047F, 0x104AF, 0x1083F, - 0x1085F, 0x1091F, 0x1093F, 0x10A5F, 0x10A7F, 0x10B3F, 0x10B5F, 0x10B7F, - 0x10C4F, 0x10E7F, 0x110CF, 0x123FF, 0x1247F, 0x1342F, 0x1D0FF, 0x1D1FF, - 0x1D24F, 0x1D35F, 0x1D37F, 0x1D7FF, 0x1F02F, 0x1F09F, 0x1F1FF, 0x1F2FF, - 0x2A6DF, 0x2B73F, 0x2FA1F, 0xE007F, 0xE01EF, 0xFFFFF, 0x10FFFF - }; - - @Override - public String ofCodeUnitsLength(Random r, int minCodeUnits, int maxCodeUnits) { - int length = RandomNumbers.randomIntBetween(r, minCodeUnits, maxCodeUnits); - final int block = r.nextInt(blockStarts.length); - - final StringBuilder sb = new StringBuilder(); - while (length > 0) { - int cp = RandomNumbers.randomIntBetween(r, blockStarts[block], blockEnds[block]); - if (length > Character.charCount(cp)) { - sb.appendCodePoint(cp); - length -= Character.charCount(cp); - } else { - // Padding for blocks that don't fit. - sb.appendCodePoint('a'); - length--; - } - } - return sb.toString(); - } - - @Override - public String ofCodePointsLength(Random r, int minCodePoints, int maxCodePoints) { - final int length = RandomNumbers.randomIntBetween(r, minCodePoints, maxCodePoints); - final int block = r.nextInt(blockStarts.length); - final StringBuilder sb = new StringBuilder(); - for (int i = 0; i < length; i++) - sb.appendCodePoint(RandomNumbers.randomIntBetween(r, blockStarts[block], blockEnds[block])); - return sb.toString(); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/StringGenerator.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/StringGenerator.java deleted file mode 100644 index 2c8d5d9c..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/StringGenerator.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -import java.util.Random; - -/** - * A {@link StringGenerator} generates random strings composed of characters. What these characters - * are and their distribution depends on a subclass. - * - * @see String - */ -public abstract class StringGenerator { - /** - * An alias for {@link #ofCodeUnitsLength(Random, int, int)}. - */ - public String ofStringLength(Random r, int minCodeUnits, int maxCodeUnits) { - return ofCodeUnitsLength(r, minCodeUnits, maxCodeUnits); - } - - /** - * @return Returns a string of variable length between minCodeUnits (inclusive) - * and maxCodeUnits (inclusive) length. Code units are essentially - * an equivalent of char type, see {@link String} class for - * explanation. - * - * @param minCodeUnits Minimum number of code units (inclusive). - * @param maxCodeUnits Maximum number of code units (inclusive). - * @throws IllegalArgumentException Thrown if the generator cannot emit random string - * of the given unit length. For example a generator emitting only extended unicodeGenerator - * plane characters (encoded as surrogate pairs) will not be able to emit an odd number - * of code units. - */ - public abstract String ofCodeUnitsLength(Random r, int minCodeUnits, int maxCodeUnits); - - /** - * @return Returns a string of variable length between minCodePoints (inclusive) - * and maxCodePoints (inclusive) length. Code points are full unicodeGenerator - * codepoints or an equivalent of int type, see {@link String} class for - * explanation. The returned {@link String#length()} may exceed maxCodeUnits - * because certain code points may be encoded as surrogate pairs. - * - * @param minCodePoints Minimum number of code points (inclusive). - * @param maxCodePoints Maximum number of code points (inclusive). - */ - public abstract String ofCodePointsLength(Random r, int minCodePoints, int maxCodePoints); -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/UnicodeGenerator.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/UnicodeGenerator.java deleted file mode 100644 index 66243746..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/generators/UnicodeGenerator.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -import java.util.Random; - -/** - * A string generator that emits valid unicodeGenerator codepoints. - */ -public class UnicodeGenerator extends StringGenerator { - private final static int SURROGATE_RANGE = Character.MAX_SURROGATE - Character.MIN_SURROGATE + 1; - private final static int CODEPOINT_RANGE = Character.MAX_CODE_POINT - SURROGATE_RANGE; - - @Override - public String ofCodeUnitsLength(Random r, int minCodeUnits, int maxCodeUnits) { - int length = RandomNumbers.randomIntBetween(r, minCodeUnits, maxCodeUnits); - char [] chars = new char [length]; - for (int i = 0; i < chars.length;) { - final int t = RandomNumbers.randomIntBetween(r, 0, 4); - if (t == 0 && i < length - 1) { - // Make a surrogate pair - chars[i++] = (char) RandomNumbers.randomIntBetween(r, 0xd800, 0xdbff); // high - chars[i++] = (char) RandomNumbers.randomIntBetween(r, 0xdc00, 0xdfff); // low - } else if (t <= 1) { - chars[i++] = (char) RandomNumbers.randomIntBetween(r, 0, 0x007f); - } else if (t == 2) { - chars[i++] = (char) RandomNumbers.randomIntBetween(r, 0x80, 0x07ff); - } else if (t == 3) { - chars[i++] = (char) RandomNumbers.randomIntBetween(r, 0x800, 0xd7ff); - } else if (t == 4) { - chars[i++] = (char) RandomNumbers.randomIntBetween(r, 0xe000, 0xffff); - } - } - return new String(chars); - } - - @Override - public String ofCodePointsLength(Random r, int minCodePoints, int maxCodePoints) { - int length = RandomNumbers.randomIntBetween(r, minCodePoints, maxCodePoints); - int [] chars = new int [length]; - for (int i = 0; i < chars.length; i++) { - int v = RandomNumbers.randomIntBetween(r, 0, CODEPOINT_RANGE); - if (v >= Character.MIN_SURROGATE) - v += SURROGATE_RANGE; - chars[i] = v; - } - return new String(chars, 0, chars.length); - } - - /** - * Returns a random string that will have a random UTF-8 representation length between - * minUtf8Length and maxUtf8Length. - * - * @param minUtf8Length Minimum UTF-8 representation length (inclusive). - * @param maxUtf8Length Maximum UTF-8 representation length (inclusive). - */ - public String ofUtf8Length(Random r, int minUtf8Length, int maxUtf8Length) { - final int length = RandomNumbers.randomIntBetween(r, minUtf8Length, maxUtf8Length); - final char[] buffer = new char [length * 3]; - int bytes = length; - int i = 0; - for (; i < buffer.length && bytes != 0; i++) { - int t; - if (bytes >= 4) { - t = r.nextInt(5); - } else if (bytes >= 3) { - t = r.nextInt(4); - } else if (bytes >= 2) { - t = r.nextInt(2); - } else { - t = 0; - } - if (t == 0) { - buffer[i] = (char) RandomNumbers.randomIntBetween(r, 0, 0x7f); - bytes--; - } else if (1 == t) { - buffer[i] = (char) RandomNumbers.randomIntBetween(r, 0x80, 0x7ff); - bytes -= 2; - } else if (2 == t) { - buffer[i] = (char) RandomNumbers.randomIntBetween(r, 0x800, 0xd7ff); - bytes -= 3; - } else if (3 == t) { - buffer[i] = (char) RandomNumbers.randomIntBetween(r, 0xe000, 0xffff); - bytes -= 3; - } else if (4 == t) { - // Make a surrogate pair - buffer[i++] = (char) RandomNumbers.randomIntBetween(r, 0xd800, 0xdbff); // high - buffer[i] = (char) RandomNumbers.randomIntBetween(r, 0xdc00, 0xdfff); // low - bytes -= 4; - } - } - return new String(buffer, 0, i); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/listeners/ReproduceInfoPrinter.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/listeners/ReproduceInfoPrinter.java deleted file mode 100644 index 4d384fe5..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/listeners/ReproduceInfoPrinter.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.carrotsearch.randomizedtesting.listeners; - -import org.junit.internal.AssumptionViolatedException; -import org.junit.runner.Description; -import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunListener; - -import com.carrotsearch.randomizedtesting.*; -import com.carrotsearch.randomizedtesting.annotations.SuppressForbidden; - -/** - * A {@link RunListener} that emits to {@link System#err} a string with command - * line parameters allowing quick test re-run under ANT command line. - */ -public class ReproduceInfoPrinter extends RunListener { - @Override - @SuppressForbidden("Legitimate use of syserr.") - public void testFailure(Failure failure) throws Exception { - // Ignore assumptions. - if (failure.getException() instanceof AssumptionViolatedException) { - return; - } - - final Description d = failure.getDescription(); - final StringBuilder b = new StringBuilder(); - b.append("FAILURE : ").append(d.getDisplayName()).append("\n"); - b.append("Message : " + failure.getMessage() + "\n"); - b.append("Reproduce: "); - new ReproduceErrorMessageBuilder(b).appendAllOpts(failure.getDescription()); - - b.append("\n"); - b.append("Throwable:\n"); - if (failure.getException() != null) { - TraceFormatting traces = new TraceFormatting(); - try { - traces = RandomizedContext.current().getRunner().getTraceFormatting(); - } catch (IllegalStateException e) { - // Ignore if no context. - } - traces.formatThrowable(b, failure.getException()); - } - - System.err.println(b.toString()); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/NoClassHooksShadowingRule.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/NoClassHooksShadowingRule.java deleted file mode 100644 index 5e3c9f59..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/NoClassHooksShadowingRule.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.carrotsearch.randomizedtesting.rules; - -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import org.junit.AfterClass; -import org.junit.BeforeClass; - -/** - * Don't allow {@link BeforeClass} and {@link AfterClass} hook shadowing as it is most - * likely a user error. JUnit rules for shadowed hook methods are weird. - */ -public class NoClassHooksShadowingRule extends NoShadowingOrOverridesOnMethodsRule { - public NoClassHooksShadowingRule() { - super(BeforeClass.class, AfterClass.class); - } -} - diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/NoInstanceHooksOverridesRule.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/NoInstanceHooksOverridesRule.java deleted file mode 100644 index 7f9addab..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/NoInstanceHooksOverridesRule.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.carrotsearch.randomizedtesting.rules; - -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import org.junit.After; -import org.junit.Before; - -/** - * Don't allow {@link Before} and {@link After} hook overrides as it is most - * likely a user error and will result in superclass methods not being called - * (requires manual chaining). - */ -public class NoInstanceHooksOverridesRule extends NoShadowingOrOverridesOnMethodsRule { - public NoInstanceHooksOverridesRule() { - super(Before.class, After.class); - } -} - diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/NoShadowingOrOverridesOnMethodsRule.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/NoShadowingOrOverridesOnMethodsRule.java deleted file mode 100644 index 26f7a4b1..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/NoShadowingOrOverridesOnMethodsRule.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.carrotsearch.randomizedtesting.rules; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.Map; - -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -import com.carrotsearch.randomizedtesting.ClassModel; -import com.carrotsearch.randomizedtesting.RandomizedContext; -import com.carrotsearch.randomizedtesting.ClassModel.MethodModel; - -/** - * Discovers shadowing or override relationships among methods annotated with any of the - * provided annotations. - */ -public abstract class NoShadowingOrOverridesOnMethodsRule implements TestRule { - private Class[] annotations; - - @SafeVarargs - public NoShadowingOrOverridesOnMethodsRule(Class... annotations) { - this.annotations = annotations; - } - - @Override - public final Statement apply(final Statement base, final Description description) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - Class testClass; - try { - testClass = RandomizedContext.current().getTargetClass(); - } catch (Throwable t) { - testClass = description.getTestClass(); - } - - validate(testClass); - base.evaluate(); - } - }; - } - - public final void validate(Class clazz) throws Throwable { - ClassModel classModel = new ClassModel(clazz); - - for (Class annClass : annotations) { - checkNoShadowsOrOverrides(clazz, classModel, annClass); - } - } - - private void checkNoShadowsOrOverrides(Class clazz, ClassModel classModel, Class ann) { - Map annotatedLeafMethods = classModel.getAnnotatedLeafMethods(ann); - - StringBuilder b = new StringBuilder(); - for (Map.Entry e : annotatedLeafMethods.entrySet()) { - if (verify(e.getKey())) { - MethodModel mm = e.getValue(); - if (mm.getDown() != null || mm.getUp() != null) { - b.append("Methods annotated with @" + ann.getName() + " shadow or override each other:\n"); - while (mm.getUp() != null) { - mm = mm.getUp(); - } - while (mm != null) { - b.append(" - "); - if (mm.element.isAnnotationPresent(ann)) b.append("@").append(ann.getSimpleName()).append(" "); - b.append(signature(mm.element)).append("\n"); - mm = mm.getDown(); - } - } - } - } - - if (b.length() > 0) { - throw new RuntimeException("There are overridden methods annotated with " - + ann.getName() + ". These methods would not be executed by JUnit and need to manually chain themselves which can lead to" + - " maintenance problems. Consider using different method names or make hook methods private.\n" + b.toString().trim()); - } - } - - protected boolean verify(Method key) { - return true; - } - - private String signature(Method m) { - return m.toString(); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/RamUsageEstimator.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/RamUsageEstimator.java deleted file mode 100644 index 74ca8186..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/RamUsageEstimator.java +++ /dev/null @@ -1,987 +0,0 @@ - -/* - * Imported from java-sizeof project. - */ - -package com.carrotsearch.randomizedtesting.rules; - -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import java.lang.management.ManagementFactory; -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.util.*; - -/** - * Estimates the size (memory representation) of Java objects. - * - * @see #sizeOf(Object) - * @see #shallowSizeOf(Object) - * @see #shallowSizeOfInstance(Class) - */ -final class RamUsageEstimator { - /** - * JVM diagnostic features. - */ - public static enum JvmFeature { - OBJECT_REFERENCE_SIZE("Object reference size estimated using array index scale."), - ARRAY_HEADER_SIZE("Array header size estimated using array based offset."), - FIELD_OFFSETS("Shallow instance size based on field offsets."), - OBJECT_ALIGNMENT("Object alignment retrieved from HotSpotDiagnostic MX bean."); - - public final String description; - - private JvmFeature(String description) { - this.description = description; - } - - @Override - public String toString() { - return super.name() + " (" + description + ")"; - } - } - - /** JVM info string for debugging and reports. */ - public final static String JVM_INFO_STRING; - - /** One kilobyte bytes. */ - public static final long ONE_KB = 1024; - - /** One megabyte bytes. */ - public static final long ONE_MB = ONE_KB * ONE_KB; - - /** One gigabyte bytes.*/ - public static final long ONE_GB = ONE_KB * ONE_MB; - - /** No instantiation. */ - private RamUsageEstimator() {} - - public final static int NUM_BYTES_BOOLEAN = 1; - public final static int NUM_BYTES_BYTE = 1; - public final static int NUM_BYTES_CHAR = 2; - public final static int NUM_BYTES_SHORT = 2; - public final static int NUM_BYTES_INT = 4; - public final static int NUM_BYTES_FLOAT = 4; - public final static int NUM_BYTES_LONG = 8; - public final static int NUM_BYTES_DOUBLE = 8; - - /** - * Number of bytes this jvm uses to represent an object reference. - */ - public final static int NUM_BYTES_OBJECT_REF; - - /** - * Number of bytes to represent an object header (no fields, no alignments). - */ - public final static int NUM_BYTES_OBJECT_HEADER; - - /** - * Number of bytes to represent an array header (no content, but with alignments). - */ - public final static int NUM_BYTES_ARRAY_HEADER; - - /** - * A constant specifying the object alignment boundary inside the JVM. Objects will - * always take a full multiple of this constant, possibly wasting some space. - */ - public final static int NUM_BYTES_OBJECT_ALIGNMENT; - - /** - * Sizes of primitive classes. - */ - private static final Map,Integer> primitiveSizes; - static { - primitiveSizes = new IdentityHashMap,Integer>(); - primitiveSizes.put(boolean.class, NUM_BYTES_BOOLEAN); - primitiveSizes.put(byte.class, NUM_BYTES_BYTE); - primitiveSizes.put(char.class, NUM_BYTES_CHAR); - primitiveSizes.put(short.class, NUM_BYTES_SHORT); - primitiveSizes.put(int.class, NUM_BYTES_INT); - primitiveSizes.put(float.class, NUM_BYTES_FLOAT); - primitiveSizes.put(double.class, NUM_BYTES_DOUBLE); - primitiveSizes.put(long.class, NUM_BYTES_LONG); - } - - /** - * A handle to sun.misc.Unsafe. - */ - private final static Object theUnsafe; - - /** - * A handle to sun.misc.Unsafe#fieldOffset(Field). - */ - private final static Method objectFieldOffsetMethod; - - /** - * All the supported "internal" JVM features detected at clinit. - */ - private final static EnumSet supportedFeatures; - - /** - * Initialize constants and try to collect information about the JVM internals. - */ - static { - // Initialize empirically measured defaults. We'll modify them to the current - // JVM settings later on if possible. - int referenceSize = Constants.JRE_IS_64BIT ? 8 : 4; - int objectHeader = Constants.JRE_IS_64BIT ? 16 : 8; - // The following is objectHeader + NUM_BYTES_INT, but aligned (object alignment) - // so on 64 bit JVMs it'll be align(16 + 4, @8) = 24. - int arrayHeader = Constants.JRE_IS_64BIT ? 24 : 12; - - supportedFeatures = EnumSet.noneOf(JvmFeature.class); - - Class unsafeClass = null; - Object tempTheUnsafe = null; - try { - unsafeClass = Class.forName("sun.misc.Unsafe"); - final Field unsafeField = unsafeClass.getDeclaredField("theUnsafe"); - unsafeField.setAccessible(true); - tempTheUnsafe = unsafeField.get(null); - } catch (Exception e) { - // Ignore. - } - theUnsafe = tempTheUnsafe; - - // get object reference size by getting scale factor of Object[] arrays: - try { - final Method arrayIndexScaleM = unsafeClass.getMethod("arrayIndexScale", Class.class); - referenceSize = ((Number) arrayIndexScaleM.invoke(theUnsafe, Object[].class)).intValue(); - supportedFeatures.add(JvmFeature.OBJECT_REFERENCE_SIZE); - } catch (Exception e) { - // ignore. - } - - // "best guess" based on reference size. We will attempt to modify - // these to exact values if there is supported infrastructure. - objectHeader = Constants.JRE_IS_64BIT ? (8 + referenceSize) : 8; - arrayHeader = Constants.JRE_IS_64BIT ? (8 + 2 * referenceSize) : 12; - - // get the object header size: - // - first try out if the field offsets are not scaled (see warning in Unsafe docs) - // - get the object header size by getting the field offset of the first field of a dummy object - // If the scaling is byte-wise and unsafe is available, enable dynamic size measurement for - // estimateRamUsage(). - Method tempObjectFieldOffsetMethod = null; - try { - final Method objectFieldOffsetM = unsafeClass.getMethod("objectFieldOffset", Field.class); - final Field dummy1Field = DummyTwoLongObject.class.getDeclaredField("dummy1"); - final int ofs1 = ((Number) objectFieldOffsetM.invoke(theUnsafe, dummy1Field)).intValue(); - final Field dummy2Field = DummyTwoLongObject.class.getDeclaredField("dummy2"); - final int ofs2 = ((Number) objectFieldOffsetM.invoke(theUnsafe, dummy2Field)).intValue(); - if (Math.abs(ofs2 - ofs1) == NUM_BYTES_LONG) { - final Field baseField = DummyOneFieldObject.class.getDeclaredField("base"); - objectHeader = ((Number) objectFieldOffsetM.invoke(theUnsafe, baseField)).intValue(); - supportedFeatures.add(JvmFeature.FIELD_OFFSETS); - tempObjectFieldOffsetMethod = objectFieldOffsetM; - } - } catch (Exception e) { - // Ignore. - } - objectFieldOffsetMethod = tempObjectFieldOffsetMethod; - - // Get the array header size by retrieving the array base offset - // (offset of the first element of an array). - try { - final Method arrayBaseOffsetM = unsafeClass.getMethod("arrayBaseOffset", Class.class); - // we calculate that only for byte[] arrays, it's actually the same for all types: - arrayHeader = ((Number) arrayBaseOffsetM.invoke(theUnsafe, byte[].class)).intValue(); - supportedFeatures.add(JvmFeature.ARRAY_HEADER_SIZE); - } catch (Exception e) { - // Ignore. - } - - NUM_BYTES_OBJECT_REF = referenceSize; - NUM_BYTES_OBJECT_HEADER = objectHeader; - NUM_BYTES_ARRAY_HEADER = arrayHeader; - - // Try to get the object alignment (the default seems to be 8 on Hotspot, - // regardless of the architecture). - int objectAlignment = 8; - try { - final Class beanClazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean"); - // Try to get the diagnostic mxbean without calling {@link ManagementFactory#getPlatformMBeanServer()} - // which starts AWT thread (and shows junk in the dock) on a Mac: - Object hotSpotBean; - // Java 7+, HotSpot - try { - hotSpotBean = ManagementFactory.class - .getMethod("getPlatformMXBean", Class.class) - .invoke(null, beanClazz); - } catch (Exception e1) { - // Java 6, HotSpot - try { - Class sunMF = Class.forName("sun.management.ManagementFactory"); - hotSpotBean = sunMF.getMethod("getDiagnosticMXBean").invoke(null); - } catch (Exception e2) { - // Last resort option is an attempt to get it from ManagementFactory's server anyway (may start AWT). - hotSpotBean = ManagementFactory.newPlatformMXBeanProxy( - ManagementFactory.getPlatformMBeanServer(), - "com.sun.management:type=HotSpotDiagnostic", beanClazz); - } - } - if (hotSpotBean != null) { - final Method getVMOptionMethod = beanClazz.getMethod("getVMOption", String.class); - final Object vmOption = getVMOptionMethod.invoke(hotSpotBean, "ObjectAlignmentInBytes"); - objectAlignment = Integer.parseInt( - vmOption.getClass().getMethod("getValue").invoke(vmOption).toString()); - supportedFeatures.add(JvmFeature.OBJECT_ALIGNMENT); - } - } catch (Exception e) { - // Ignore. - } - - NUM_BYTES_OBJECT_ALIGNMENT = objectAlignment; - - JVM_INFO_STRING = "[JVM: " + - Constants.JVM_NAME + ", " + Constants.JVM_VERSION + ", " + Constants.JVM_VENDOR + ", " + - Constants.JAVA_VENDOR + ", " + Constants.JAVA_VERSION + "]"; - } - - /** - * Cached information about a given class. - */ - private static final class ClassCache { - public final long alignedShallowInstanceSize; - public final Field[] referenceFields; - - public ClassCache(long alignedShallowInstanceSize, Field[] referenceFields) { - this.alignedShallowInstanceSize = alignedShallowInstanceSize; - this.referenceFields = referenceFields; - } - } - - // Object with just one field to determine the object header size by getting the offset of the dummy field: - @SuppressWarnings("unused") - private static final class DummyOneFieldObject { - public byte base; - } - - // Another test object for checking, if the difference in offsets of dummy1 and dummy2 is 8 bytes. - // Only then we can be sure that those are real, unscaled offsets: - @SuppressWarnings("unused") - private static final class DummyTwoLongObject { - public long dummy1, dummy2; - } - - /** - * Returns true, if the current JVM is fully supported by {@code RamUsageEstimator}. - * If this method returns {@code false} you are maybe using a 3rd party Java VM - * that is not supporting Oracle/Sun private APIs. The memory estimates can be - * imprecise then (no way of detecting compressed references, alignments, etc.). - * Lucene still tries to use sensible defaults. - */ - public static boolean isSupportedJVM() { - return supportedFeatures.size() == JvmFeature.values().length; - } - - /** - * Aligns an object size to be the next multiple of {@link #NUM_BYTES_OBJECT_ALIGNMENT}. - */ - public static long alignObjectSize(long size) { - size += (long) NUM_BYTES_OBJECT_ALIGNMENT - 1L; - return size - (size % NUM_BYTES_OBJECT_ALIGNMENT); - } - - /** Returns the size in bytes of the byte[] object. */ - public static long sizeOf(byte[] arr) { - return alignObjectSize((long) NUM_BYTES_ARRAY_HEADER + arr.length); - } - - /** Returns the size in bytes of the boolean[] object. */ - public static long sizeOf(boolean[] arr) { - return alignObjectSize((long) NUM_BYTES_ARRAY_HEADER + arr.length); - } - - /** Returns the size in bytes of the char[] object. */ - public static long sizeOf(char[] arr) { - return alignObjectSize((long) NUM_BYTES_ARRAY_HEADER + (long) NUM_BYTES_CHAR * arr.length); - } - - /** Returns the size in bytes of the short[] object. */ - public static long sizeOf(short[] arr) { - return alignObjectSize((long) NUM_BYTES_ARRAY_HEADER + (long) NUM_BYTES_SHORT * arr.length); - } - - /** Returns the size in bytes of the int[] object. */ - public static long sizeOf(int[] arr) { - return alignObjectSize((long) NUM_BYTES_ARRAY_HEADER + (long) NUM_BYTES_INT * arr.length); - } - - /** Returns the size in bytes of the float[] object. */ - public static long sizeOf(float[] arr) { - return alignObjectSize((long) NUM_BYTES_ARRAY_HEADER + (long) NUM_BYTES_FLOAT * arr.length); - } - - /** Returns the size in bytes of the long[] object. */ - public static long sizeOf(long[] arr) { - return alignObjectSize((long) NUM_BYTES_ARRAY_HEADER + (long) NUM_BYTES_LONG * arr.length); - } - - /** Returns the size in bytes of the double[] object. */ - public static long sizeOf(double[] arr) { - return alignObjectSize((long) NUM_BYTES_ARRAY_HEADER + (long) NUM_BYTES_DOUBLE * arr.length); - } - - /** - * Estimates the RAM usage by the given object. It will - * walk the object tree and sum up all referenced objects. - * - *

      Resource Usage: This method internally uses a set of - * every object seen during traversals so it does allocate memory - * (it isn't side-effect free). After the method exits, this memory - * should be GCed.

      - */ - public static long sizeOf(Object obj) { - ArrayList stack = new ArrayList(); - stack.add(obj); - return measureSizeOf(stack); - } - - /** - * Same as {@link #sizeOf(Object)} but sums up all the arguments. Not an - * overload to prevent accidental parameter conflicts with {@link #sizeOf(Object)}. - */ - public static long sizeOfAll(Object... objects) { - return sizeOfAll(Arrays.asList(objects)); - } - - /** - * Same as {@link #sizeOf(Object)} but sums up all the arguments. Not an - * overload to prevent accidental parameter conflicts with {@link #sizeOf(Object)}. - */ - public static long sizeOfAll(Iterable objects) { - final ArrayList stack; - if (objects instanceof Collection) { - stack = new ArrayList(((Collection) objects).size()); - } else { - stack = new ArrayList(); - } - - for (Object o : objects) { - stack.add(o); - } - - return measureSizeOf(stack); - } - - /** - * Estimates a "shallow" memory usage of the given object. For arrays, this will be the - * memory taken by array storage (no subreferences will be followed). For objects, this - * will be the memory taken by the fields. - * - * JVM object alignments are also applied. - */ - public static long shallowSizeOf(Object obj) { - if (obj == null) return 0; - final Class clz = obj.getClass(); - if (clz.isArray()) { - return shallowSizeOfArray(obj); - } else { - return shallowSizeOfInstance(clz); - } - } - - /** - * Same as {@link #shallowSizeOf(Object)} but sums up all the arguments. Not an - * overload to prevent accidental parameter conflicts with {@link #shallowSizeOf(Object)}. - */ - public static long shallowSizeOfAll(Object... objects) { - return shallowSizeOfAll(Arrays.asList(objects)); - } - - /** - * Same as {@link #shallowSizeOf(Object)} but sums up all the arguments. Duplicate - * objects are not resolved and will be counted twice. - * Not an overload to prevent accidental parameter conflicts with - * {@link #shallowSizeOf(Object)}. - */ - public static long shallowSizeOfAll(Iterable objects) { - long sum = 0; - for (Object o : objects) { - sum += shallowSizeOf(o); - } - return sum; - } - - /** - * Returns the shallow instance size in bytes an instance of the given class would occupy. - * This works with all conventional classes and primitive types, but not with arrays - * (the size then depends on the number of elements and varies from object to object). - * - * @see #shallowSizeOf(Object) - * @throws IllegalArgumentException if {@code clazz} is an array class. - */ - public static long shallowSizeOfInstance(Class clazz) { - if (clazz.isArray()) - throw new IllegalArgumentException("This method does not work with array classes."); - if (clazz.isPrimitive()) - return primitiveSizes.get(clazz); - - long size = NUM_BYTES_OBJECT_HEADER; - - // Walk type hierarchy - for (;clazz != null; clazz = clazz.getSuperclass()) { - final Class target = clazz; - final Field[] fields = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Field[] run() { - return target.getDeclaredFields(); - } - }); - for (Field f : fields) { - if (!Modifier.isStatic(f.getModifiers())) { - size = adjustForField(size, f); - } - } - } - return alignObjectSize(size); - } - - /** Return the set of unsupported JVM features that improve the estimation. */ - public static EnumSet getUnsupportedFeatures() { - EnumSet unsupported = EnumSet.allOf(JvmFeature.class); - unsupported.removeAll(supportedFeatures); - return unsupported; - } - - /** Return the set of supported JVM features that improve the estimation. */ - public static EnumSet getSupportedFeatures() { - return EnumSet.copyOf(supportedFeatures); - } - - /** - * Return shallow size of any array. - */ - private static long shallowSizeOfArray(Object array) { - long size = NUM_BYTES_ARRAY_HEADER; - final int len = Array.getLength(array); - if (len > 0) { - Class arrayElementClazz = array.getClass().getComponentType(); - if (arrayElementClazz.isPrimitive()) { - size += (long) len * primitiveSizes.get(arrayElementClazz); - } else { - size += (long) NUM_BYTES_OBJECT_REF * len; - } - } - return alignObjectSize(size); - } - - /** - * Non-recursive version of object descend. This consumes more memory than recursive in-depth - * traversal but prevents stack overflows on long chains of objects - * or complex graphs (a max. recursion depth on my machine was ~5000 objects linked in a chain - * so not too much). - * - * @param stack Root objects. - */ - private static long measureSizeOf(ArrayList stack) { - final IdentityHashSet seen = new IdentityHashSet(); - final IdentityHashMap, ClassCache> classCache = new IdentityHashMap, ClassCache>(); - - long totalSize = 0; - while (!stack.isEmpty()) { - final Object ob = stack.remove(stack.size() - 1); - - if (ob == null || seen.contains(ob)) { - continue; - } - seen.add(ob); - - final Class obClazz = ob.getClass(); - if (obClazz.isArray()) { - /* - * Consider an array, possibly of primitive types. Push any of its references to - * the processing stack and accumulate this array's shallow size. - */ - long size = NUM_BYTES_ARRAY_HEADER; - final int len = Array.getLength(ob); - if (len > 0) { - Class componentClazz = obClazz.getComponentType(); - if (componentClazz.isPrimitive()) { - size += (long) len * primitiveSizes.get(componentClazz); - } else { - size += (long) NUM_BYTES_OBJECT_REF * len; - - for (int i = len; --i >= 0 ;) { - final Object o = Array.get(ob, i); - if (o != null && !seen.contains(o)) { - stack.add(o); - } - } - } - } - totalSize += alignObjectSize(size); - } else { - /* - * Consider an object. Push any references it has to the processing stack - * and accumulate this object's shallow size. - */ - try { - ClassCache cachedInfo = classCache.get(obClazz); - if (cachedInfo == null) { - classCache.put(obClazz, cachedInfo = createCacheEntry(obClazz)); - } - - for (Field f : cachedInfo.referenceFields) { - // Fast path to eliminate redundancies. - final Object o = f.get(ob); - if (o != null && !seen.contains(o)) { - stack.add(o); - } - } - - totalSize += cachedInfo.alignedShallowInstanceSize; - } catch (IllegalAccessException e) { - // this should never happen as we enabled setAccessible(). - throw new RuntimeException("Reflective field access failed?", e); - } - } - } - - // Help the GC. - seen.clear(); - stack.clear(); - classCache.clear(); - - return totalSize; - } - - /** - * Create a cached information about shallow size and reference fields for - * a given class. - */ - private static ClassCache createCacheEntry(final Class clazz) { - ClassCache cachedInfo; - long shallowInstanceSize = NUM_BYTES_OBJECT_HEADER; - final ArrayList referenceFields = new ArrayList(32); - for (Class c = clazz; c != null; c = c.getSuperclass()) { - final Class target = clazz; - final Field[] fields = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Field[] run() { - return target.getDeclaredFields(); - } - }); - for (final Field f : fields) { - if (!Modifier.isStatic(f.getModifiers())) { - shallowInstanceSize = adjustForField(shallowInstanceSize, f); - - if (!f.getType().isPrimitive()) { - try { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - f.setAccessible(true); - return null; - } - }); - } catch (Exception e) { - throw new IllegalStateException("Unable to access '" + f + "' to estimate memory usage", e); - } - referenceFields.add(f); - } - } - } - } - - cachedInfo = new ClassCache( - alignObjectSize(shallowInstanceSize), - referenceFields.toArray(new Field[referenceFields.size()])); - return cachedInfo; - } - - /** - * This method returns the maximum representation size of an object. sizeSoFar - * is the object's size measured so far. f is the field being probed. - * - *

      The returned offset will be the maximum of whatever was measured so far and - * f field's offset and representation size (unaligned). - */ - private static long adjustForField(long sizeSoFar, final Field f) { - final Class type = f.getType(); - final int fsize = type.isPrimitive() ? primitiveSizes.get(type) : NUM_BYTES_OBJECT_REF; - if (objectFieldOffsetMethod != null) { - try { - final long offsetPlusSize = - ((Number) objectFieldOffsetMethod.invoke(theUnsafe, f)).longValue() + fsize; - return Math.max(sizeSoFar, offsetPlusSize); - } catch (IllegalAccessException ex) { - throw new RuntimeException("Access problem with sun.misc.Unsafe", ex); - } catch (InvocationTargetException ite) { - final Throwable cause = ite.getCause(); - if (cause instanceof RuntimeException) - throw (RuntimeException) cause; - if (cause instanceof Error) - throw (Error) cause; - // this should never happen (Unsafe does not declare - // checked Exceptions for this method), but who knows? - throw new RuntimeException("Call to Unsafe's objectFieldOffset() throwed "+ - "checked Exception when accessing field " + - f.getDeclaringClass().getName() + "#" + f.getName(), cause); - } - } else { - // No alignments based on field type/ subclass fields alignments? - return sizeSoFar + fsize; - } - } - - /** - * Returns size in human-readable units (GB, MB, KB or bytes). - */ - public static String humanReadableUnits(long bytes) { - return humanReadableUnits(bytes, - new DecimalFormat("0.#", DecimalFormatSymbols.getInstance(Locale.ROOT))); - } - - /** - * Returns size in human-readable units (GB, MB, KB or bytes). - */ - public static String humanReadableUnits(long bytes, DecimalFormat df) { - if (bytes / ONE_GB > 0) { - return df.format((float) bytes / ONE_GB) + " GB"; - } else if (bytes / ONE_MB > 0) { - return df.format((float) bytes / ONE_MB) + " MB"; - } else if (bytes / ONE_KB > 0) { - return df.format((float) bytes / ONE_KB) + " KB"; - } else { - return bytes + " bytes"; - } - } - - /** - * Return a human-readable size of a given object. - * @see #sizeOf(Object) - * @see #humanReadableUnits(long) - */ - public static String humanSizeOf(Object object) { - return humanReadableUnits(sizeOf(object)); - } -} - -/** - * An identity hash set implemented using open addressing. No null keys are allowed. - */ -final class IdentityHashSet implements Iterable { - /** - * Default load factor. - */ - public final static float DEFAULT_LOAD_FACTOR = 0.75f; - - /** - * Minimum capacity for the set. - */ - public final static int MIN_CAPACITY = 4; - - /** - * All of set entries. Always of power of two length. - */ - public Object[] keys; - - /** - * Cached number of assigned slots. - */ - public int assigned; - - /** - * The load factor for this set (fraction of allocated or deleted slots before - * the buffers must be rehashed or reallocated). - */ - public final float loadFactor; - - /** - * Cached capacity threshold at which we must resize the buffers. - */ - private int resizeThreshold; - - /** - * Creates a hash set with the default capacity of 16. - * load factor of {@value #DEFAULT_LOAD_FACTOR}. ` - */ - public IdentityHashSet() { - this(16, DEFAULT_LOAD_FACTOR); - } - - /** - * Creates a hash set with the given capacity, load factor of - * {@value #DEFAULT_LOAD_FACTOR}. - */ - public IdentityHashSet(int initialCapacity) { - this(initialCapacity, DEFAULT_LOAD_FACTOR); - } - - /** - * Creates a hash set with the given capacity and load factor. - */ - public IdentityHashSet(int initialCapacity, float loadFactor) { - initialCapacity = Math.max(MIN_CAPACITY, initialCapacity); - - assert initialCapacity > 0 : "Initial capacity must be between (0, " - + Integer.MAX_VALUE + "]."; - assert loadFactor > 0 && loadFactor < 1 : "Load factor must be between (0, 1)."; - this.loadFactor = loadFactor; - allocateBuffers(roundCapacity(initialCapacity)); - } - - /** - * Adds a reference to the set. Null keys are not allowed. - */ - public boolean add(KType e) { - assert e != null : "Null keys not allowed."; - - if (assigned >= resizeThreshold) expandAndRehash(); - - final int mask = keys.length - 1; - int slot = rehash(e) & mask; - Object existing; - while ((existing = keys[slot]) != null) { - if (e == existing) { - return false; // already found. - } - slot = (slot + 1) & mask; - } - assigned++; - keys[slot] = e; - return true; - } - - /** - * Checks if the set contains a given ref. - */ - public boolean contains(KType e) { - final int mask = keys.length - 1; - int slot = rehash(e) & mask; - Object existing; - while ((existing = keys[slot]) != null) { - if (e == existing) { - return true; - } - slot = (slot + 1) & mask; - } - return false; - } - - /** Rehash via MurmurHash. */ - private static int rehash(Object o) { - return MurmurHash3.hash(System.identityHashCode(o)); - } - - /** - * Expand the internal storage buffers (capacity) or rehash current keys and - * values if there are a lot of deleted slots. - */ - private void expandAndRehash() { - final Object[] oldKeys = this.keys; - - assert assigned >= resizeThreshold; - allocateBuffers(nextCapacity(keys.length)); - - /* - * Rehash all assigned slots from the old hash table. - */ - final int mask = keys.length - 1; - for (int i = 0; i < oldKeys.length; i++) { - final Object key = oldKeys[i]; - if (key != null) { - int slot = rehash(key) & mask; - while (keys[slot] != null) { - slot = (slot + 1) & mask; - } - keys[slot] = key; - } - } - Arrays.fill(oldKeys, null); - } - - /** - * Allocate internal buffers for a given capacity. - * - * @param capacity - * New capacity (must be a power of two). - */ - private void allocateBuffers(int capacity) { - this.keys = new Object[capacity]; - this.resizeThreshold = (int) (capacity * DEFAULT_LOAD_FACTOR); - } - - /** - * Return the next possible capacity, counting from the current buffers' size. - */ - protected int nextCapacity(int current) { - assert current > 0 && Long.bitCount(current) == 1 : "Capacity must be a power of two."; - assert ((current << 1) > 0) : "Maximum capacity exceeded (" - + (0x80000000 >>> 1) + ")."; - - if (current < MIN_CAPACITY / 2) current = MIN_CAPACITY / 2; - return current << 1; - } - - /** - * Round the capacity to the next allowed value. - */ - protected int roundCapacity(int requestedCapacity) { - // Maximum positive integer that is a power of two. - if (requestedCapacity > (0x80000000 >>> 1)) return (0x80000000 >>> 1); - - int capacity = MIN_CAPACITY; - while (capacity < requestedCapacity) { - capacity <<= 1; - } - - return capacity; - } - - public void clear() { - assigned = 0; - Arrays.fill(keys, null); - } - - public int size() { - return assigned; - } - - public boolean isEmpty() { - return size() == 0; - } - - @Override - public Iterator iterator() { - return new Iterator() { - int pos = -1; - Object nextElement = fetchNext(); - - @Override - public boolean hasNext() { - return nextElement != null; - } - - @SuppressWarnings("unchecked") - @Override - public KType next() { - Object r = this.nextElement; - if (r == null) { - throw new NoSuchElementException(); - } - this.nextElement = fetchNext(); - return (KType) r; - } - - private Object fetchNext() { - pos++; - while (pos < keys.length && keys[pos] == null) { - pos++; - } - - return (pos >= keys.length ? null : keys[pos]); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } -} - -/** - * Hash routines for primitive types. The implementation is based on the - * finalization step from Austin Appleby's MurmurHash3. - * - * @see "http://sites.google.com/site/murmurhash/" - */ -final class MurmurHash3 { - private MurmurHash3() { - // no instances. - } - - /** - * Hashes a 4-byte sequence (Java int). - */ - public static int hash(int k) { - k ^= k >>> 16; - k *= 0x85ebca6b; - k ^= k >>> 13; - k *= 0xc2b2ae35; - k ^= k >>> 16; - return k; - } - - /** - * Hashes an 8-byte sequence (Java long). - */ - public static long hash(long k) { - k ^= k >>> 33; - k *= 0xff51afd7ed558ccdL; - k ^= k >>> 33; - k *= 0xc4ceb9fe1a85ec53L; - k ^= k >>> 33; - - return k; - } -} - -/** - * Some useful constants. - **/ -final class Constants { - private Constants() {} // can't construct - - /** True iff running on a 64bit JVM */ - public static final boolean JRE_IS_64BIT; - - /** The value of System.getProperty("java.version"). **/ - public static final String JAVA_VERSION = System.getProperty("java.version"); - public static final String JAVA_VENDOR = System.getProperty("java.vendor"); - public static final String JVM_VENDOR = System.getProperty("java.vm.vendor"); - public static final String JVM_VERSION = System.getProperty("java.vm.version"); - public static final String JVM_NAME = System.getProperty("java.vm.name"); - public static final String OS_ARCH = System.getProperty("os.arch"); - public static final String OS_VERSION = System.getProperty("os.version"); - - static { - final String OS_ARCH = System.getProperty("os.arch"); - boolean is64Bit = false; - try { - final Class unsafeClass = Class.forName("sun.misc.Unsafe"); - final Field unsafeField = unsafeClass.getDeclaredField("theUnsafe"); - unsafeField.setAccessible(true); - final Object unsafe = unsafeField.get(null); - final int addressSize = ((Number) unsafeClass.getMethod("addressSize").invoke(unsafe)).intValue(); - is64Bit = addressSize >= 8; - } catch (Exception e) { - final String x = System.getProperty("sun.arch.data.model"); - if (x != null) { - is64Bit = x.indexOf("64") != -1; - } else { - if (OS_ARCH != null && OS_ARCH.indexOf("64") != -1) { - is64Bit = true; - } else { - is64Bit = false; - } - } - } - JRE_IS_64BIT = is64Bit; - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/RequireAssertionsRule.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/RequireAssertionsRule.java deleted file mode 100644 index 706bc103..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/RequireAssertionsRule.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.carrotsearch.randomizedtesting.rules; - -import java.util.Objects; - -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import org.junit.ClassRule; -import org.junit.rules.TestRule; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.SysGlobals; -import com.carrotsearch.randomizedtesting.annotations.SuppressForbidden; - -/** - * Require assertions {@link TestRule}. - * - * @see ClassRule - */ -public class RequireAssertionsRule extends TestRuleAdapter { - public static final boolean TEST_ASSERTS_ENABLED = - RandomizedTest.systemPropertyAsBoolean(SysGlobals.SYSPROP_ASSERTS(), /* default to assertions required */ true); - - private final Class targetClass; - - public RequireAssertionsRule(Class targetClass) { - this.targetClass = Objects.requireNonNull(targetClass); - } - - @SuppressForbidden("Permitted sysout.") - @Override - protected void before() throws Throwable { - // Make sure -ea matches -Dtests.asserts. - boolean assertsEnabled = targetClass.desiredAssertionStatus(); - if (assertsEnabled != TEST_ASSERTS_ENABLED) { - String msg = "Assertion state mismatch on " + targetClass.getSimpleName() + ": "; - if (assertsEnabled) { - msg += "-ea was specified"; - } else { - msg += "-ea was not specified"; - } - msg += " but -Dtests.asserts=" + TEST_ASSERTS_ENABLED; - - System.err.println(msg); - throw new Exception(msg); - } - } -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/StatementAdapter.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/StatementAdapter.java deleted file mode 100644 index 47c57b72..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/StatementAdapter.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.carrotsearch.randomizedtesting.rules; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.rules.RuleChain; -import org.junit.runners.model.MultipleFailureException; -import org.junit.runners.model.Statement; - -/** - * An abstract {@link Statement} that guarantees the execution of - * {@link #afterAlways} even if an exception has been thrown from delegate - * {@link Statement}. This is much like {@link AfterClass} or {@link After} - * annotations but can be used with {@link RuleChain} to guarantee the order of - * execution. - */ -public abstract class StatementAdapter extends Statement { - - private final Statement delegate; - - protected StatementAdapter(Statement delegate) { - this.delegate = delegate; - } - - /** - * - */ - @Override - final public void evaluate() throws Throwable { - final ArrayList errors = new ArrayList(); - - try { - before(); - delegate.evaluate(); - afterIfSuccessful(); - } catch (Throwable t) { - errors.add(t); - } - - try { - afterAlways(errors); - } catch (Throwable t) { - errors.add(t); - } - - MultipleFailureException.assertEmpty(errors); - } - - /** - * Always called before the delegate {@link Statement}. - */ - protected void before() throws Throwable {} - - /** - * Always called after the delegate {@link Statement}, even if an exception - * (or assumption failure) occurs. Any exceptions thrown from the body of this - * method will be chained using {@link MultipleFailureException}. - * - * @param errors - * A list of errors received so far. The list is modifiable although - * should only be extended with new potential exceptions. - */ - protected void afterAlways(List errors) throws Throwable {} - - /** - * Called only if the delegate {@link Statement} returned successfully. - */ - protected void afterIfSuccessful() throws Throwable {} - -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/StaticFieldsInvariantRule.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/StaticFieldsInvariantRule.java deleted file mode 100644 index f6b01211..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/StaticFieldsInvariantRule.java +++ /dev/null @@ -1,183 +0,0 @@ -package com.carrotsearch.randomizedtesting.rules; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Locale; - -import junit.framework.AssertionFailedError; - -import org.junit.ClassRule; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -import com.carrotsearch.randomizedtesting.RandomizedContext; - -/** - * A {@link TestRule} that ensures static, reference fields of the suite class - * (and optionally its superclasses) are cleaned up after a suite is completed. - * This is helpful in finding out static memory leaks (a class references - * something huge but is no longer used). - * - * @see ClassRule - * @see #accept(Field) - */ -public class StaticFieldsInvariantRule implements TestRule { - public static final long DEFAULT_LEAK_THRESHOLD = 10 * 1024 * 1024; - - private final long leakThreshold; - private final boolean countSuperclasses; - - /** - * By default use {@link #DEFAULT_LEAK_THRESHOLD} as the threshold and count - * in superclasses. - */ - public StaticFieldsInvariantRule() { - this(DEFAULT_LEAK_THRESHOLD, true); - } - - public StaticFieldsInvariantRule(long leakThresholdBytes, boolean countSuperclasses) { - this.leakThreshold = leakThresholdBytes; - this.countSuperclasses = countSuperclasses; - } - - static class Entry implements Comparable { - final Field field; - final Object value; - long ramUsed; - - public Entry(Field field, Object value) { - this.field = field; - this.value = value; - } - - @Override - public int compareTo(Entry o) { - if (this.ramUsed > o.ramUsed) return -1; - if (this.ramUsed < o.ramUsed) return 1; - return this.field.toString().compareTo(o.field.toString()); - } - } - - @Override - public Statement apply(final Statement s, final Description d) { - return new StatementAdapter(s) { - @Override - protected void afterAlways(List errors) throws Throwable { - // Try to get the target class from the context, if available. - Class testClass = null; - try { - testClass = RandomizedContext.current().getTargetClass(); - } catch (Throwable t) { - // Ignore. - } - - if (testClass == null) { - // This is JUnit's ugly way that attempts Class.forName and may use a different - // classloader... let's use it as a last resort option. - testClass = d.getTestClass(); - } - - // No test class? Weird. - if (testClass == null) { - throw new RuntimeException("Test class could not be acquired from the randomized " + - "context or the Description object."); - } - - // Collect all fields first to count references to the same object once. - ArrayList fieldsAndValues = new ArrayList(); - ArrayList values = new ArrayList(); - for (Class c = testClass; countSuperclasses && c.getSuperclass() != null; c = c.getSuperclass()) { - final Class target = c; - Field[] allFields = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Field[] run() { - return target.getDeclaredFields(); - } - }); - for (final Field field : allFields) { - if (Modifier.isStatic(field.getModifiers()) && - !field.getType().isPrimitive() && - accept(field)) { - try { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - field.setAccessible(true); - return null; - } - }); - Object v = field.get(null); - if (v != null) { - fieldsAndValues.add(new Entry(field, v)); - values.add(v); - } - } catch (SecurityException e) { - errors.add(new RuntimeException("Could not access field '" + field.getName() + "'.", e)); - } - } - } - } - - final long ramUsage; - try { - ramUsage = RamUsageEstimator.sizeOfAll(values); - } catch (Exception ex) { - // some problem occurred while trying to measure (e.g. Java 9, SecurityManager). - // we iterate over all fields to get the "bad one": - final StringBuilder b = new StringBuilder(); - b.append("Clean up static fields (in @AfterClass?) and null them, ") - .append("your test still has references to classes of which the ") - .append("sizes cannot be measured due to security restrictions or Java 9 ") - .append("module encapsulation:"); - for (final Entry e : fieldsAndValues) { - try { - RamUsageEstimator.sizeOf(e.value); - } catch (Exception ex1) { - b.append("\n - ").append(e.field); - } - } - - AssertionFailedError err = new AssertionFailedError(b.toString()); - err.initCause(ex); - errors.add(err); - return; - } - - if (ramUsage > leakThreshold) { - // Count per-field information to get the heaviest fields. - for (Entry e : fieldsAndValues) { - e.ramUsed = RamUsageEstimator.sizeOf(e.value); - } - Collections.sort(fieldsAndValues); - - StringBuilder b = new StringBuilder(); - b.append(String.format(Locale.ROOT, "Clean up static fields (in @AfterClass?), " - + "your test seems to hang on to approximately %,d bytes (threshold is %,d). " + - "Field reference sizes (counted individually):", - ramUsage, leakThreshold)); - - for (Entry e : fieldsAndValues) { - b.append(String.format(Locale.ROOT, "\n - %,d bytes, %s", e.ramUsed, - e.field.toString())); - } - - errors.add(new AssertionFailedError(b.toString())); - } - } - }; - } - - /** - * @return Return false to exclude a given field from being - * counted. By default final fields are rejected. - */ - protected boolean accept(Field field) { - return !Modifier.isFinal(field.getModifiers()); - } -} diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/SystemPropertiesInvariantRule.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/SystemPropertiesInvariantRule.java deleted file mode 100644 index 24eba6fa..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/SystemPropertiesInvariantRule.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.carrotsearch.randomizedtesting.rules; - -import java.util.*; - -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.MultipleFailureException; -import org.junit.runners.model.Statement; - -/** - * A {@link TestRule} that ensures system properties remain unmodified by the nested - * {@link Statement}. This can be applied both at suite level and at test level. - * - * This rule requires appropriate security permission to read and write - * system properties ({@link System#getProperties()}) if running under a security - * manager. - * - * @see SystemPropertiesRestoreRule - * @see ClassRule - * @see Rule - */ -public class SystemPropertiesInvariantRule implements TestRule { - /** - * Ignored property keys. - */ - private final HashSet ignoredProperties; - - /** - * Cares about all properties. - */ - public SystemPropertiesInvariantRule() { - this(Collections.emptySet()); - } - - /** - * Don't care about the given set of properties. - */ - public SystemPropertiesInvariantRule(String... ignoredProperties) { - this.ignoredProperties = new HashSet(Arrays.asList(ignoredProperties)); - } - - /** - * Don't care about the given set of properties. - */ - public SystemPropertiesInvariantRule(Set ignoredProperties) { - this.ignoredProperties = new HashSet(ignoredProperties); - } - - @Override - public Statement apply(final Statement s, Description d) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - TreeMap before = SystemPropertiesRestoreRule.systemPropertiesAsMap(); - ArrayList errors = new ArrayList(); - try { - s.evaluate(); - } catch (Throwable t) { - errors.add(t); - } finally { - final TreeMap after = SystemPropertiesRestoreRule.systemPropertiesAsMap(); - - // Remove ignored if they exist. - before.keySet().removeAll(ignoredProperties); - after.keySet().removeAll(ignoredProperties); - - if (!after.equals(before)) { - errors.add( - new AssertionError("System properties invariant violated.\n" + - collectErrorMessage(before, after))); - } - - // Restore original properties. - SystemPropertiesRestoreRule.restore(before, after, ignoredProperties); - } - - MultipleFailureException.assertEmpty(errors); - } - - private StringBuilder collectErrorMessage( - TreeMap before, TreeMap after) { - TreeSet newKeys = new TreeSet(after.keySet()); - newKeys.removeAll(before.keySet()); - - TreeSet missingKeys = new TreeSet(before.keySet()); - missingKeys.removeAll(after.keySet()); - - TreeSet differentKeyValues = new TreeSet(before.keySet()); - differentKeyValues.retainAll(after.keySet()); - for (Iterator i = differentKeyValues.iterator(); i.hasNext();) { - String key = i.next(); - String valueBefore = before.get(key); - String valueAfter = after.get(key); - if ((valueBefore == null && valueAfter == null) || - (valueBefore.equals(valueAfter))) { - i.remove(); - } - } - - final StringBuilder b = new StringBuilder(); - if (!missingKeys.isEmpty()) { - b.append("Missing keys:\n"); - for (String key : missingKeys) { - b.append(" ").append(key) - .append("=") - .append(before.get(key)) - .append("\n"); - } - } - if (!newKeys.isEmpty()) { - b.append("New keys:\n"); - for (String key : newKeys) { - b.append(" ").append(key) - .append("=") - .append(after.get(key)) - .append("\n"); - } - } - if (!differentKeyValues.isEmpty()) { - b.append("Different values:\n"); - for (String key : differentKeyValues) { - b.append(" [old]").append(key) - .append("=") - .append(before.get(key)).append("\n"); - b.append(" [new]").append(key) - .append("=") - .append(after.get(key)).append("\n"); - } - } - return b; - } - }; - } -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/SystemPropertiesRestoreRule.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/SystemPropertiesRestoreRule.java deleted file mode 100644 index 8a1cbb4a..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/SystemPropertiesRestoreRule.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.carrotsearch.randomizedtesting.rules; - -import java.util.*; - -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -/** - * A {@link TestRule} which restores system properties from before the nested - * {@link Statement}. - * - * This rule requires appropriate security permission to read and write - * system properties ({@link System#getProperties()}) if running under a security - * manager. - * - * @see SystemPropertiesInvariantRule - * @see ClassRule - * @see Rule - */ -public class SystemPropertiesRestoreRule implements TestRule { - /** - * Ignored property keys. - */ - private final HashSet ignoredProperties; - - /** - * Restores all properties. - */ - public SystemPropertiesRestoreRule() { - this(Collections.emptySet()); - } - - /** - * @param ignoredProperties Properties that will be ignored (and will not be restored). - */ - public SystemPropertiesRestoreRule(Set ignoredProperties) { - this.ignoredProperties = new HashSet(ignoredProperties); - } - - /** - * @param ignoredProperties Properties that will be ignored (and will not be restored). - */ - public SystemPropertiesRestoreRule(String... ignoredProperties) { - this.ignoredProperties = new HashSet(Arrays.asList(ignoredProperties)); - } - - @Override - public Statement apply(final Statement s, Description d) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - TreeMap before = systemPropertiesAsMap(); - try { - s.evaluate(); - } finally { - TreeMap after = systemPropertiesAsMap(); - if (!after.equals(before)) { - // Restore original properties. - restore(before, after, ignoredProperties); - } - } - } - }; - } - - private static TreeMap cloneAsMap(Properties properties) { - TreeMap result = new TreeMap(); - for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) { - final Object key = e.nextElement(); - // Skip non-string properties or values, they're abuse of Properties object. - if (key instanceof String) { - String value = properties.getProperty((String) key); - if (value == null) { - Object ovalue = properties.get(key); - if (ovalue != null) { - // ovalue has to be a non-string object. Skip the property because - // System.clearProperty won't be able to cast back the existing value. - continue; - } - } - result.put((String) key, value); - } - } - return result; - } - - static void restore( - TreeMap before, - TreeMap after, - Set ignoredKeys) { - - // Clear anything that is present after but wasn't before. - after.keySet().removeAll(before.keySet()); - for (String key : after.keySet()) { - if (!ignoredKeys.contains(key)) - System.clearProperty(key); - } - - // Restore original property values unless they are ignored (then leave). - for (Map.Entry e : before.entrySet()) { - String key = e.getValue(); - if (!ignoredKeys.contains(key)) { - if (key == null) { - System.clearProperty(e.getKey()); // Can this happen? - } else { - System.setProperty(e.getKey(), key); - } - } - } - } - - static TreeMap systemPropertiesAsMap() { - try { - return cloneAsMap(System.getProperties()); - } catch (SecurityException e) { - AssertionError ae = new AssertionError("Access to System.getProperties() denied."); - try { - ae.initCause(e); - } catch (Exception ignored) { - // If we can't initCause, ignore it. - } - throw ae; - } - } -} \ No newline at end of file diff --git a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/TestRuleAdapter.java b/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/TestRuleAdapter.java deleted file mode 100644 index d695ae62..00000000 --- a/randomized-runner/src/main/java/com/carrotsearch/randomizedtesting/rules/TestRuleAdapter.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.carrotsearch.randomizedtesting.rules; - -import java.util.List; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.MultipleFailureException; -import org.junit.runners.model.Statement; - -/** - * An abstract {@link TestRule} that guarantees the execution of - * {@link #afterAlways} even if an exception has been thrown from delegate - * {@link Statement}. This is much like {@link AfterClass} or {@link After} - * annotations but can be used with {@link RuleChain} to guarantee the order of - * execution. - */ -public abstract class TestRuleAdapter implements TestRule { - @Override - public Statement apply(final Statement s, final Description d) { - return new StatementAdapter(s) { - @Override - protected void before() throws Throwable { - TestRuleAdapter.this.before(); - } - - @Override - protected void afterAlways(List errors) throws Throwable { - TestRuleAdapter.this.afterAlways(errors); - } - - @Override - protected void afterIfSuccessful() throws Throwable { - TestRuleAdapter.this.afterIfSuccessful(); - } - }; - } - - /** - * Always called before the delegate {@link Statement}. - */ - protected void before() throws Throwable {} - - /** - * Always called after the delegate {@link Statement}, even if an exception - * (or assumption failure) occurs. Any exceptions thrown from the body of this - * method will be chained using {@link MultipleFailureException}. - * - * @param errors - * A list of errors received so far. The list is modifiable although - * should only be extended with new potential exceptions. - */ - protected void afterAlways(List errors) throws Throwable {} - - /** - * Called only if the delegate {@link Statement} returned successfully. - */ - protected void afterIfSuccessful() throws Throwable {} -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/PrintEventListener.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/PrintEventListener.java deleted file mode 100644 index cd34856a..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/PrintEventListener.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.io.PrintStream; -import java.util.Locale; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.runner.Description; -import org.junit.runner.Result; -import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunListener; - -public class PrintEventListener extends RunListener { - private final PrintStream out; - private AtomicInteger assumptions = new AtomicInteger(); - - public PrintEventListener(PrintStream out) { - this.out = out; - } - - @Override - public void testRunStarted(Description description) throws Exception { - out.println("Run started."); - } - - @Override - public void testRunFinished(Result result) throws Exception { - out.println(String.format(Locale.ROOT, - "Run finished: run=%s, ignored=%s, failures=%s, assumptions=%s\n", - result.getRunCount(), - result.getIgnoreCount(), - result.getFailureCount(), - assumptions.get())); - } - - @Override - public void testStarted(Description description) throws Exception { - out.println("Started : " + description.getMethodName()); - } - - @Override - public void testFinished(Description description) throws Exception { - out.println("Finished: " + description.getMethodName()); - } - - @Override - public void testFailure(Failure failure) throws Exception { - out.println("Failure : " + failure); - } - - @Override - public void testAssumptionFailure(Failure failure) { - out.println("Assumpt.: " + failure); - assumptions.incrementAndGet(); - } - - @Override - public void testIgnored(Description description) throws Exception { - String methodName = description.getMethodName(); - if (methodName == null) { - // Ignored due to class-level @Ignore or some other reason. - out.println("Ignored : " + description.getDisplayName()); - } else { - out.println("Ignored : " + description.getMethodName()); - } - } -} \ No newline at end of file diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestBiasedNumbers.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestBiasedNumbers.java deleted file mode 100644 index c0ad7228..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestBiasedNumbers.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.Locale; -import java.util.Random; - -import org.assertj.core.api.Assertions; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.generators.BiasedNumbers; - -public class TestBiasedNumbers extends RandomizedTest { - @Test - @Repeat(iterations = 100) - public void biasedFloats() { - Random r = getRandom(); - - // Some sanity checks. - sanityCheck(r, Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY); - sanityCheck(r, Float.NEGATIVE_INFINITY, 0); - sanityCheck(r, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY); - sanityCheck(r, 0, Float.POSITIVE_INFINITY); - sanityCheck(r, 0f, 0); - sanityCheck(r, 0f, 1); - sanityCheck(r, -1f, 1); - sanityCheck(r, 1f, 2); - } - - private void sanityCheck(Random r, float from, float to) { - for (int i = 0; i < 100; i++) { - float v = BiasedNumbers.randomFloatBetween(r, from, to); - Assertions.assertThat(v).isNotNaN(); - Assertions.assertThat(v >= from && v <= to).isTrue(); - } - } - - @Test - @Repeat(iterations = 100) - public void biasedDoubles() { - Random r = getRandom(); - - // Some sanity checks. - sanityCheck(r, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY); - sanityCheck(r, Double.NEGATIVE_INFINITY, 0); - sanityCheck(r, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); - sanityCheck(r, 0, Double.POSITIVE_INFINITY); - sanityCheck(r, 0d, 0); - sanityCheck(r, 0d, 1); - sanityCheck(r, -1d, 1); - sanityCheck(r, 1d, 2); - } - - private void sanityCheck(Random r, double from, double to) { - for (int i = 0; i < 100; i++) { - double v = BiasedNumbers.randomDoubleBetween(r, from, to); - Assertions.assertThat(v).isNotNaN(); - Assertions.assertThat(v >= from && v <= to).isTrue(); - } - } - - @Test - public void histo() { - Random rnd = getRandom(); - int r = 10; - int [][] counts = new int [r + 1][r + 1]; - for (int i = 0; i < 100000; i++) { - float x = r / 2 + BiasedNumbers.randomFloatBetween(rnd, -r/2, r/2); - float y = r / 2 + BiasedNumbers.randomFloatBetween(rnd, -r/2, r/2); - - counts[Math.round(x)][Math.round(y)]++; - } - - for (int x = 0; x < counts.length; x++) { - for (int y = 0; y < counts.length; y++) { - System.out.printf(Locale.ROOT, "%10d ", counts[x][y]); - } - System.out.println(); - } - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestChildTestGroupThreads.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestChildTestGroupThreads.java deleted file mode 100644 index 9f12755e..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestChildTestGroupThreads.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.Random; - -import org.junit.Test; - -/** - * Make sure we can access contexts from a sub-thread group. - */ -public class TestChildTestGroupThreads extends RandomizedTest { - volatile int guard; - - @Test - public void testSubgroup() throws Exception { - ThreadGroup tgroup = new ThreadGroup("child group"); - final Thread t = new Thread(tgroup, "child thread") { - public void run() { - Random rnd = RandomizedContext.current().getRandom(); - guard += rnd.nextInt(); - } - }; - - t.start(); - t.join(); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestClassMethodFiltering.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestClassMethodFiltering.java deleted file mode 100644 index ebd57eca..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestClassMethodFiltering.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static org.junit.Assert.*; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import static com.carrotsearch.randomizedtesting.SysGlobals.*; - -/** - * Check if global filtering works. - */ -public class TestClassMethodFiltering extends WithNestedTestClass { - static List methods = new ArrayList(); - - @RunWith(RandomizedRunner.class) - public static class Nested1 { - @BeforeClass - public static void beforeClass() { - methods.add("beforeClass1"); - } - - @Test - public void method1() { - assumeRunningNested(); - methods.add("method1"); - } - - @Test - public void method2() { - assumeRunningNested(); - methods.add("method2"); - } - } - - @RunWith(RandomizedRunner.class) - public static class Nested2 { - @BeforeClass - public static void beforeClass() { - methods.add("beforeClass2"); - } - - @Test - public void method1() { - assumeRunningNested(); - methods.add("method1"); - } - } - - /** - * Class filter (all methods). - */ - @Test - public void testClassFilter() { - System.setProperty(SYSPROP_TESTCLASS(), Nested1.class.getName()); - runTests(Nested1.class, Nested2.class); - assertTrue( - Arrays.asList("beforeClass1", "method1", "method2").equals(methods) || - Arrays.asList("beforeClass1", "method2", "method1").equals(methods)); - } - - /** - * Class and method filter (single method). - */ - @Test - public void testClassMethodFilter() { - System.setProperty(SYSPROP_TESTCLASS(), Nested1.class.getName()); - System.setProperty(SYSPROP_TESTMETHOD(), "method2"); - runTests(Nested1.class, Nested2.class); - assertEquals(Arrays.asList("beforeClass1", "method2"), methods); - } - - /** - * Awkward case: only method filter. - */ - @Test - public void testMethodFilter() { - System.setProperty(SYSPROP_TESTMETHOD(), "method1"); - runTests(Nested1.class, Nested2.class); - assertEquals(Arrays.asList("beforeClass1", "method1", "beforeClass2", "method1"), methods); - } - - /** - * Glob class name filter· - */ - @Test - public void testGlobClassName() { - System.setProperty(SYSPROP_TESTCLASS(), "*Nested1"); - runTests(Nested1.class, Nested2.class); - assertTrue( - Arrays.asList("beforeClass1", "method1", "method2").equals(methods) || - Arrays.asList("beforeClass1", "method2", "method1").equals(methods)); - } - - /** - * Glob method name filter· - */ - @Test - public void testGlobMethodName() { - System.setProperty(SYSPROP_TESTMETHOD(), "*hod1"); - runTests(Nested1.class, Nested2.class); - assertEquals(Arrays.asList("beforeClass1", "method1", "beforeClass2", "method1"), methods); - } - - @Before - public void cleanupBefore() { - cleanupAfter(); - } - - @After - public void cleanupAfter() { - System.clearProperty(SYSPROP_TESTCLASS()); - System.clearProperty(SYSPROP_TESTMETHOD()); - methods.clear(); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestContextRandom.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestContextRandom.java deleted file mode 100644 index a96bcb40..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestContextRandom.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; -import com.carrotsearch.randomizedtesting.annotations.Seed; - -/** - * Check if the context's random is indeed repeatable. - */ -public class TestContextRandom extends WithNestedTestClass { - static ArrayList numbers = new ArrayList(); - - public static class Nested1 extends RandomizedTest { - @Seed("deadbeef") // Fix the seed to get a repeatable result - @Test - public void testMethod() { - numbers.clear(); - for (int i = 0; i < 10; i++) { - numbers.add(randomInt()); - } - } - } - - public static class Nested2 extends RandomizedTest { - @Test - public void testMethod() { - numbers.clear(); - for (int i = 0; i < 10; i++) { - numbers.add(randomInt()); - } - } - } - - public static class Nested3 extends RandomizedTest { - @Seed("deadbeef") // Fix the seed to get a repeatable result even if subthreads use randomness. - @Test - public void testMethod() throws Exception { - Thread t = new Thread() { - @Override - public void run() { - numbers.clear(); - for (int i = 0; i < 10; i++) { - numbers.add(randomInt()); - } - } - }; - t.start(); - t.join(); - } - } - - /** - * Check that subthreads get the same randomness for {@link Seed} - * annotation on a method. - */ - @Test - @Ignore("Forked threads get the master seed (by-design).") - public void testFixedSeedSubthreads() { - runTests(Nested3.class); - List run1 = new ArrayList(numbers); - runTests(Nested3.class); - List run2 = new ArrayList(numbers); - Assert.assertEquals(run1, run2); - } - - @Test - public void testFixedSeed() { - runTests(Nested1.class); - List run1 = new ArrayList(numbers); - runTests(Nested1.class); - List run2 = new ArrayList(numbers); - Assert.assertEquals(run1, run2); - } - - @Test - public void testRandomSeed() { - runTests(Nested2.class); - List run1 = new ArrayList(numbers); - runTests(Nested2.class); - List run2 = new ArrayList(numbers); - Assert.assertFalse(run1.equals(run2)); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestCustomMethodProvider.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestCustomMethodProvider.java deleted file mode 100644 index d79fe125..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestCustomMethodProvider.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.JUnitCore; -import org.junit.runner.Result; -import org.junit.runners.model.InitializationError; - -import com.carrotsearch.randomizedtesting.annotations.TestMethodProviders; - -public class TestCustomMethodProvider extends WithNestedTestClass { - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD}) - @Inherited - public static @interface MyTest { - } - - public static class MyTestMethodProvider extends AnnotatedMethodProvider { - public MyTestMethodProvider() { - super(MyTest.class); - } - } - - @TestMethodProviders({MyTestMethodProvider.class}) - public static class Base {} - - public static class T4 extends Base { @MyTest private void test1() {} } - public static class T2 extends Base { @MyTest void test1() {} } - public static class T3 extends Base { @MyTest protected void test1() {} } - public static class T1 extends Base { @MyTest public void test1() {} } - - public static class ST4 extends Base { @MyTest static private void test1() {} } - public static class ST2 extends Base { @MyTest static void test1() {} } - public static class ST3 extends Base { @MyTest static protected void test1() {} } - public static class ST1 extends Base { @MyTest static public void test1() {} } - - public static class AT1 extends Base { @MyTest public void test1(int arg) {} } - public static class RT1 extends Base { @MyTest public int test1() { return 0; } } - - @Test - public void testJUnit4Valid() throws InitializationError { - Class [] valid = { - T1.class, RT1.class - }; - - for (Class cl : valid) { - Result r = new JUnitCore().run(new RandomizedRunner(cl)); - Assert.assertEquals(0, r.getFailureCount()); - Assert.assertEquals(1, r.getRunCount()); - } - } - - @Test - public void testJUnit4Invalid() { - Class [] invalid = { - T2.class, T3.class, T4.class, - ST1.class, ST2.class, ST3.class, ST4.class, - AT1.class - }; - - for (Class cl : invalid) { - try { - new JUnitCore().run(new RandomizedRunner(cl)); - Assert.fail("Expected to fail for: " + cl); - } catch (InitializationError e) { - // expected. - } - } - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestCustomTestContextSupplier.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestCustomTestContextSupplier.java deleted file mode 100644 index c7fb0c28..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestCustomTestContextSupplier.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static org.junit.Assert.*; - -import java.util.Random; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.annotations.TestContextRandomSupplier; - -/** - * - */ -@TestContextRandomSupplier(TestCustomTestContextSupplier.CustomSupplier.class) -public class TestCustomTestContextSupplier extends RandomizedTest { - public static class CustomSupplier implements RandomSupplier { - @SuppressWarnings("serial") - @Override - public Random get(long seed) { - return new Random() { - int value; - - @Override - public int nextInt() { - return value++; - } - }; - } - } - - @Test - public void testCustomSupplier() throws Exception { - // Can't just check for instanceof because random can be wrapped - // with AssertingRandom. - Random rnd = RandomizedContext.current().getRandom(); - for (int i = 0; i < 10; i++) { - assertEquals(rnd.nextInt(), i); - } - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestExpected.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestExpected.java deleted file mode 100644 index bbdedcf6..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestExpected.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.assertj.core.api.Assertions; -import org.junit.Test; - -/** - * Test {@link Test#expected()}. - */ -public class TestExpected extends WithNestedTestClass { - public static class Nested1 extends RandomizedTest { - @Test(expected = RuntimeException.class) - public void testMethod1() { - throw new RuntimeException(); - } - - // We expect a RuntimeException but get an error: should fail. - @Test(expected = RuntimeException.class) - public void testMethod2() { - assumeRunningNested(); - throw new Error(); - } - } - - public static class Nested2 extends RandomizedTest { - @Test(expected = RuntimeException.class) - public void testMethod1() { - assumeRunningNested(); - // Don't do anything. - } - } - - @Test - public void testExpectedFailureDifferentException() { - FullResult f = checkTestsOutput(2, 0, 1, 0, Nested1.class); - Assertions.assertThat(f.getFailures().get(0).getException()) - .isInstanceOf(Error.class); - } - - @Test - public void testExpectedFailurePassed() { - checkTestsOutput(1, 0, 1, 0, Nested2.class); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestFailurePropagationCompatibility.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestFailurePropagationCompatibility.java deleted file mode 100644 index 00995f10..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestFailurePropagationCompatibility.java +++ /dev/null @@ -1,148 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.ArrayList; -import java.util.Random; - -import org.junit.*; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.*; -import org.junit.runner.notification.Failure; -import org.junit.runners.model.MultipleFailureException; -import org.junit.runners.model.Statement; - - -/** - * Check failure propagation compatibility against JUnit. - */ -public class TestFailurePropagationCompatibility extends WithNestedTestClass { - static Random random; - static int frequency; - - public static class MaybeFailRule implements TestRule { - @Override - public Statement apply(final Statement base, Description description) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - try { - maybeFail(); - base.evaluate(); - maybeFail(); - } catch (Throwable t) { - maybeFail(); - } finally { - maybeFail(); - } - } - }; - } - } - - public static class FailRandomly1 { - public FailRandomly1() { - maybeFail(); - } - - @ClassRule - public static TestRule classRule1 = RuleChain - .outerRule(new MaybeFailRule()) - .around(new MaybeFailRule()); - - @Rule - public TestRule testRule1 = RuleChain - .outerRule(new MaybeFailRule()) - .around(new MaybeFailRule()); - - @BeforeClass public static void beforeClass1() { maybeFail(); } - @Before public void before() { maybeFail(); } - @Test public void test() { maybeFail(); } - @After public void after() { maybeFail(); } - @AfterClass public static void afterClass() { maybeFail(); } - } - - public static class FailRandomly2 extends FailRandomly1 { - public FailRandomly2() { - maybeFail(); - } - - @ClassRule - public static TestRule classRule2 = RuleChain - .outerRule(new MaybeFailRule()) - .around(new MaybeFailRule()); - - @Rule - public TestRule testRule2 = RuleChain - .outerRule(new MaybeFailRule()) - .around(new MaybeFailRule()); - - @BeforeClass public static void beforeClass2() { maybeFail(); } - @Before public void before2() { maybeFail(); } - @After public void after2() { maybeFail(); } - @AfterClass public static void afterClass2() { maybeFail(); } - } - - @RunWith(RandomizedRunner.class) - public static class FailRandomly3 extends FailRandomly2 { - } - - static void maybeFail() { - if (random != null) { - if (random.nextInt(frequency) == 0) { - if (random.nextBoolean()) { - throw new RuntimeException("State: " + random.nextLong()); - } else { - ArrayList errors = new ArrayList(); - errors.add(new RuntimeException("State: " + random.nextLong())); - errors.add(new RuntimeException("State: " + random.nextLong())); - // Throw MultipleFailureException as if unchecked. - Rethrow.rethrow(new MultipleFailureException(errors)); - } - } - } - } - - @Test - public void testRunEquals() throws Exception { - Random rnd = new Random(); // initial. - for (int f = 1; f < 10; f += 2) { - frequency = f; - for (int i = 0; i < 25; i++) { - final long seed = rnd.nextLong() + i; - random = new Random(seed); - Result junit4 = new JUnitCore().run(FailRandomly2.class); - random = new Random(seed); - Result rr = new JUnitCore().run(FailRandomly3.class); - - String traceJunit4 = executionTrace(junit4); - String traceRR = executionTrace(rr); - if (!traceJunit4.equals(traceRR)) { - System.out.println("=== Random(" + seed + "), freq: " + frequency); - System.out.println("--- JUnit4:"); - System.out.println(traceJunit4); - System.out.println("--- RandomizedRunner:"); - System.out.println(traceRR); - Assert.fail(); - } - } - } - } - - @AfterClass - public static void cleanup() { - random = null; - } - - private String executionTrace(Result r) { - StringBuilder sb = new StringBuilder(); - sb.append("Run count: " + r.getRunCount() + "\n"); - sb.append("Ignore count: " + r.getIgnoreCount() + "\n"); - sb.append("Failure count: " + r.getFailureCount() + "\n"); - for (Failure f : r.getFailures()) { - Throwable t = f.getException(); - sb.append(t.getClass().getName() + ": " + t.getMessage()); - sb.append("\n\n"); - } - return sb.toString(); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestFilterExpressionParser.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestFilterExpressionParser.java deleted file mode 100644 index eaf642a2..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestFilterExpressionParser.java +++ /dev/null @@ -1,157 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.ArrayDeque; -import java.util.Arrays; -import java.util.Deque; -import java.util.List; - -import org.assertj.core.api.Assertions; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.FilterExpressionParser.IContext; -import com.carrotsearch.randomizedtesting.FilterExpressionParser.Node; -import com.carrotsearch.randomizedtesting.FilterExpressionParser.SyntaxException; - -public class TestFilterExpressionParser { - @Test - public void testParsingSanity() { - // input -> expected bracketing. - Deque examples = new ArrayDeque(Arrays.asList( - "", "default", - "default", "default", - "@nightly", "@nightly", - "@nightly or @slow", "(@nightly OR @slow)", - "@nightly and @slow", "(@nightly AND @slow)", - "@nightly and not @slow", "(@nightly AND (NOT @slow))", - "@nightly and (not @slow)", "(@nightly AND (NOT @slow))", - "not @slow", "(NOT @slow)", - "not not @slow", "(NOT (NOT @slow))", - "not @nightly or @slow", "((NOT @nightly) OR @slow)", - "not(@nightly or @slow)", "(NOT (@nightly OR @slow))", - "(@nightly and (not @slow))", "(@nightly AND (NOT @slow))")); - - while (!examples.isEmpty()) { - String input = examples.remove(); - String expected = examples.remove(); - - System.out.println("-- " + input); - Node root = new FilterExpressionParser().parse(input); - String expression = root.toExpression(); - System.out.println(" " + expression); - - Assertions.assertThat(expression) - .as(input) - .isEqualTo(expected); - - Assertions.assertThat(new FilterExpressionParser().parse(expression).toExpression()) - .as(input) - .isEqualTo(expression); - } - } - - @Test - public void testTrueExpressions() { - // {groups}, {rules} - Deque examples = new ArrayDeque(Arrays.asList(new String [][] { - {}, - {"not @foo", "not default"}, - - {"@nightly"}, - {"@nightly", "@nightly or @foo", "@foo or @nightly", "not not @nightly"}, - - {"@nightly", "@slow"}, - {"@nightly and @slow", "@nightly and not @foo", "not @nightly or @slow"}, - - {"default"}, - {"", "default"}, - })); - - while (!examples.isEmpty()) { - final List groups = Arrays.asList((String[]) examples.pop()); - IContext context = new IContext() { - @Override - public boolean defaultValue() { - return hasGroup("default"); - } - - @Override - public boolean hasGroup(String value) { - return groups.contains(value); - } - }; - - for (String rule : examples.pop()) { - Assertions.assertThat(new FilterExpressionParser().parse(rule).evaluate(context)) - .as("ctx=" + groups + ", rule=" + rule) - .isEqualTo(true); - } - } - } - - @Test - public void testFalseExpressions() { - // {groups}, {rules} - Deque examples = new ArrayDeque(Arrays.asList(new String [][] { - {}, - {"@foo", "default"}, - - {"@nightly"}, - {"not @nightly", "@nightly and @foo"}, - - {"@nightly", "@slow"}, - {"not(@nightly or @slow)"}, - })); - - while (!examples.isEmpty()) { - final List groups = Arrays.asList((String[]) examples.pop()); - IContext context = new IContext() { - @Override - public boolean defaultValue() { - return hasGroup("default"); - } - - @Override - public boolean hasGroup(String value) { - return groups.contains(value); - } - }; - - for (String rule : examples.pop()) { - Assertions.assertThat(new FilterExpressionParser().parse(rule).evaluate(context)) - .as("ctx=" + groups + ", rule=" + rule) - .isEqualTo(false); - } - } - } - - @Test - public void testErrors() { - for (String rule : Arrays.asList( - "nightly", - "@nightly and ", - "@nightly or ", - "@nightly and or @slow", - "and not @slow", - "(@nightly))", - "((@nightly or @slow)" - )) { - - System.out.println("-- " + rule); - try { - new FilterExpressionParser().parse(rule); - Assertions.fail("Should cause an exception: " + rule); - } catch (SyntaxException e) { - System.out.println(" " + e.getMessage()); - } - } - } - - @Test - public void testInvalidToken() { - try { - new FilterExpressionParser().parse("@nightly and foo or @bar"); - } catch (SyntaxException e) { - Assertions.assertThat(e.toString()).contains(">foo<"); - } - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestFormattingRandomSeeds.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestFormattingRandomSeeds.java deleted file mode 100644 index c3c49926..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestFormattingRandomSeeds.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.carrotsearch.randomizedtesting.annotations.Repeat; - -@RunWith(RandomizedRunner.class) -public class TestFormattingRandomSeeds { - @Test - public void minusOne() { - check(-1L); - } - - @Test - public void zero() { - check(0); - } - - @Test - public void maxLong() { - check(Long.MAX_VALUE); - } - - /** Heck, why not use ourselves here? ;) */ - @Test - @Repeat(iterations = 1000) - public void noise() { - check(RandomizedContext.current().getRandom().nextLong()); - } - - private void check(long seed) { - String asString = SeedUtils.formatSeedChain(new Randomness(seed, RandomSupplier.DEFAULT)); - Assert.assertEquals(seed, SeedUtils.parseSeedChain(asString)[0]); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestGlobFilter.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestGlobFilter.java deleted file mode 100644 index 08d2bb0b..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestGlobFilter.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.assertj.core.api.Assertions; -import org.junit.Assert; -import org.junit.Test; - -public class TestGlobFilter { - @Test - public void testBrackets() { - GlobFilter gf = new MethodGlobFilter("ab(*)"); - Assert.assertTrue(gf.globMatches("ab()")); - Assert.assertTrue(gf.globMatches("ab(foo)")); - Assert.assertTrue(gf.globMatches("ab(bar=xxx)")); - - gf = new MethodGlobFilter("test {yaml=resthandler/10_Foo/Bar (Hello)}"); - Assert.assertTrue(gf.globMatches("test {yaml=resthandler/10_Foo/Bar (Hello)}")); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestHookMethodOrderWithExceptions.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestHookMethodOrderWithExceptions.java deleted file mode 100644 index b78ffdbe..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestHookMethodOrderWithExceptions.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -import org.assertj.core.api.Assertions; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.carrotsearch.randomizedtesting.WithNestedTestClass.FullResult; -import com.carrotsearch.randomizedtesting.annotations.Repeat; - -/** - * Try to be compatible with JUnit's runners wrt method hooks throwing - * exceptions. - */ -public class TestHookMethodOrderWithExceptions extends RandomizedTest { - static final List callOrder = new ArrayList(); - - /** - * Test superclass. - */ - public abstract static class Super { - static Random rnd; - - @BeforeClass - public static void beforeClassSuper() { - callOrder.add("beforeClassSuper"); - maybeThrowException(); - } - - @Before - public final void beforeTest() { - callOrder.add("beforeTestSuper"); - maybeThrowException(); - } - - @After - public final void afterTest() { - callOrder.add("afterTestSuper"); - maybeThrowException(); - - } - - @AfterClass - public static void afterClassSuper() { - callOrder.add("afterClassSuper"); - maybeThrowException(); - } - - public static void maybeThrowException() { - if (rnd != null && rnd.nextInt(10) == 0) { - throw new RuntimeException(); - } - } - } - - /** - * Test subclass. - */ - public static class SubSub extends Super { - @BeforeClass - public static void beforeClass() { - callOrder.add("beforeClassSub"); - maybeThrowException(); - } - - @Before - public void beforeTestSub() { - callOrder.add("beforeTestSub"); - maybeThrowException(); - } - - @Test - public void testMethod() { - callOrder.add("testMethodSub"); - maybeThrowException(); - } - - @After - public void afterTestSub() { - callOrder.add("afterTestSub"); - maybeThrowException(); - } - - @AfterClass - public static void afterClass() { - callOrder.add("afterClassSub"); - maybeThrowException(); - } - } - - @Before - public void setup() { - callOrder.clear(); - } - - @After - public void cleanup() { - callOrder.clear(); - } - - @RunWith(RandomizedRunner.class) - public static class WithRandomizedRunner extends SubSub {} - public static class WithRegularRunner extends SubSub {} - - @Test @Repeat(iterations = 20) - public void checkOrderSameAsJUnit() throws Exception { - long seed = RandomizedContext.current().getRandomness().getSeed(); - - callOrder.clear(); - Super.rnd = new Random(seed); - - FullResult r1 = WithNestedTestClass.runTests(WithRegularRunner.class); - List junitOrder = new ArrayList(callOrder); - - callOrder.clear(); - Super.rnd = new Random(seed); - FullResult r2 = WithNestedTestClass.runTests(WithRandomizedRunner.class); - List rrunnerOrder = new ArrayList(callOrder); - - Assert.assertEquals(junitOrder, rrunnerOrder); - Assertions.assertThat(r1.getRunCount()).isEqualTo(r2.getRunCount()); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestHooksWithEmptyTestSet.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestHooksWithEmptyTestSet.java deleted file mode 100644 index 76806646..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestHooksWithEmptyTestSet.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static org.junit.Assert.assertFalse; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Hooks should _not_ execute if there are no test cases to run. Note that - * ignored test cases behave as if there was something to execute (!). - */ -public class TestHooksWithEmptyTestSet extends WithNestedTestClass { - @RunWith(RandomizedRunner.class) - public static class Nested { - static boolean beforeClassExecuted; - static boolean afterClassExecuted; - - @BeforeClass - public static void beforeClass() { - assumeRunningNested(); - beforeClassExecuted = true; - } - - @AfterClass - public static void afterClass() { - afterClassExecuted = true; - } - } - - /** - * Check if methods get the same seed on every run with a fixed runner's seed. - */ - @Test - public void testSameMethodRandomnessWithFixedRunner() { - Nested.beforeClassExecuted = false; - Nested.afterClassExecuted = false; - checkTestsOutput(0, 0, 0, 0, Nested.class); - assertFalse(Nested.beforeClassExecuted); - assertFalse(Nested.afterClassExecuted); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestIgnoredRunCount.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestIgnoredRunCount.java deleted file mode 100644 index 2e7b817b..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestIgnoredRunCount.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.junit.*; -import org.junit.runner.*; - -/** - * Test {@link Result}'s run count for ignored tests. - */ -public class TestIgnoredRunCount extends WithNestedTestClass { - public static class Nested1 { - @Test @Ignore - public void ignored() {} - } - - @RunWith(RandomizedRunner.class) - public static class Nested2 { - @Test @Ignore - public void ignored() {} - } - - @Test - public void checkIgnoredCount() throws Exception { - checkTestsOutput(0, 1, 0, 0, Nested1.class); - checkTestsOutput(0, 1, 0, 0, Nested2.class); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestInstantiationTime.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestInstantiationTime.java deleted file mode 100644 index a479594e..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestInstantiationTime.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.junit.BeforeClass; -import org.junit.Test; - -/** - * Check that {@link BeforeClass} hooks are called before instance initializers. - */ -public class TestInstantiationTime extends RandomizedTest { - - private static String constant; - - /** - * Instance initializer. Will result in an NPE if - * {@link #prepare()} is not invoked before. - */ - public String copyOfStatic = constant.toUpperCase(); - - @BeforeClass - public static void prepare() { - constant = "constant"; - } - - @Test - public void testDummy() { - // empty. - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestIterationsAnnotation.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestIterationsAnnotation.java deleted file mode 100644 index 994e269d..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestIterationsAnnotation.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.annotations.Repeat; - -/** - * Nightly mode checks. - */ -public class TestIterationsAnnotation extends RandomizedTest { - static int iterations = 0; - - @Test @Repeat(iterations = 10) - public void nightly() { - iterations++; - } - - @BeforeClass - public static void clean() { - iterations = 0; - } - - @AfterClass - public static void cleanupAfter() { - Assert.assertEquals(10, iterations); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestJ9SysThreads.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestJ9SysThreads.java deleted file mode 100644 index 0a6caa8d..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestJ9SysThreads.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.lang.management.ManagementFactory; -import java.lang.management.MemoryPoolMXBean; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction.Action; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; - -/** - * Test {@link Test#expected()}. - */ -public class TestJ9SysThreads extends WithNestedTestClass { - @ThreadLeakScope(Scope.SUITE) - @ThreadLeakAction({Action.INTERRUPT}) - public static class Nested extends RandomizedTest { - @Test - public void testMethod1() { - assumeRunningNested(); - - for (MemoryPoolMXBean mbean : ManagementFactory.getMemoryPoolMXBeans()) { - mbean.getUsage(); - sysout.println(mbean.getClass().getName()); - } - } - } - - @Test - public void testSuccessfulExceptedFailure() { - checkTestsOutput(1, 0, 0, 0, Nested.class); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestJUnit3MethodProvider.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestJUnit3MethodProvider.java deleted file mode 100644 index 742b1434..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestJUnit3MethodProvider.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.JUnitCore; -import org.junit.runner.Result; -import org.junit.runners.model.InitializationError; - -import com.carrotsearch.randomizedtesting.annotations.TestMethodProviders; - -public class TestJUnit3MethodProvider { - @TestMethodProviders({JUnit3MethodProvider.class}) - public static class Base {} - - @SuppressWarnings("unused") - public static class T4 extends Base { private void test1() {} } - public static class T2 extends Base { void test1() {} } - public static class T3 extends Base { protected void test1() {} } - public static class T1 extends Base { public void test1() {} } - - @SuppressWarnings("unused") - public static class ST4 extends Base { static private void test1() {} } - public static class ST2 extends Base { static void test1() {} } - public static class ST3 extends Base { static protected void test1() {} } - public static class ST1 extends Base { static public void test1() {} } - - public static class AT1 extends Base { public void test1(int arg) {} } - public static class RT1 extends Base { public int test1() { return 0; } } - - @Test - public void testJUnit3Valid() throws Exception { - Class [] valid = { - T1.class, RT1.class - }; - - for (Class cl : valid) { - Result r = new JUnitCore().run(new RandomizedRunner(cl)); - Assert.assertEquals(0, r.getFailureCount()); - Assert.assertEquals(1, r.getRunCount()); - } - } - - @Test - public void testJUnit3Invalid() { - Class [] invalid = { - T2.class, T3.class, T4.class, - ST1.class, ST2.class, ST3.class, ST4.class, - AT1.class - }; - - for (Class cl : invalid) { - try { - new JUnitCore().run(new RandomizedRunner(cl)); - Assert.fail("Expected to fail for: " + cl); - } catch (InitializationError e) { - // expected. - } - } - } - - public static class S1 extends Base { public void test1() {} } - public static class S2 extends S1 { public void test1() {} } - public static class S3 extends S2 { public void test1() {} } - - @Test - public void testJUnit3Overrides() throws Exception { - Result r = new JUnitCore().run(new RandomizedRunner(S3.class)); - Assert.assertEquals(0, r.getFailureCount()); - Assert.assertEquals(1, r.getRunCount()); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestListenersAnnotation.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestListenersAnnotation.java deleted file mode 100644 index 25c5e808..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestListenersAnnotation.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.Description; -import org.junit.runner.Result; -import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunListener; - -import com.carrotsearch.randomizedtesting.annotations.Listeners; - -/** - * Test listeners on suite. - */ -public class TestListenersAnnotation extends WithNestedTestClass { - - public static List buffer = new ArrayList(); - - public static class NoopListener extends RunListener { - } - - public static class BufferAppendListener extends RunListener { - public void testRunStarted(Description description) throws Exception { - buffer.add("run started: " + description.getMethodName()); - } - - public void testStarted(Description description) throws Exception { - buffer.add("test started: " + description.getMethodName()); - } - - @Override - public void testFinished(Description description) throws Exception { - buffer.add("test finished: " + description.getMethodName()); - } - - @Override - public void testAssumptionFailure(Failure failure) { - buffer.add("assumption failed: " + failure.getDescription().getMethodName()); - } - - @Override - public void testIgnored(Description description) throws Exception { - buffer.add("test ignored: " + description.getMethodName()); - } - - @Override - public void testFailure(Failure failure) throws Exception { - buffer.add("failure: " + failure.getDescription().getMethodName()); - } - - @Override - public void testRunFinished(Result result) throws Exception { - buffer.add("run finished: " + result.getRunCount()); - } - } - - @Listeners({BufferAppendListener.class}) - public static class Nested1 extends RandomizedTest { - } - - @Listeners({NoopListener.class}) - public static class Nested2 extends Nested1 { - @Test @Ignore - public void ignored() { - } - - @Test - public void passing() throws Exception { - } - - @Test - public void failing() throws Exception { - assumeRunningNested(); - Assert.fail(); - } - - @Test - public void assumptionFailing() throws Exception { - assumeRunningNested(); - Assume.assumeTrue(false); - } - } - - @Test - public void checkListeners() { - runTests(Nested2.class); - // Perhaps this is overly simple, but we just want to know that it executed. - Assert.assertTrue(buffer.size() > 0); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestMacSysThreads.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestMacSysThreads.java deleted file mode 100644 index a4614300..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestMacSysThreads.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.lang.management.ManagementFactory; - -import javax.management.MBeanServer; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction.Action; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; - -/** - * Test Mac system threads. - */ -public class TestMacSysThreads extends WithNestedTestClass { - @ThreadLeakScope(Scope.SUITE) - @ThreadLeakAction({Action.WARN}) - public static class Nested extends RandomizedTest { - @Test - public void testMethod1() { - MBeanServer mb = ManagementFactory.getPlatformMBeanServer(); - mb.getMBeanCount(); - RandomizedTest.sleep(2500); - } - } - - @Test - public void testSuccessful() { - checkTestsOutput(1, 0, 0, 0, Nested.class); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestManyThreadsOOM.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestManyThreadsOOM.java deleted file mode 100644 index 2915752c..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestManyThreadsOOM.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.Random; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.annotations.Repeat; - -/** - * Make sure we don't OOM even if we recreate many, many threads during a test/ suite. - */ -public class TestManyThreadsOOM extends RandomizedTest { - volatile int guard; - - @Test - @Repeat(iterations = 10) - public void testSpawnManyThreads() throws Exception { - // create threads sequentially, attaching a big blob of data to each, then - // touch the context from within a thread and die. - for (int i = 0; i < 500; i++) { - final Thread t = new Thread() { - final byte [] hold = new byte [1024 * 1024 * 10]; - - public void run() { - Random rnd = RandomizedContext.current().getRandom(); - guard += rnd.nextInt() + hold.length; - } - }; - - t.start(); - t.join(); - } - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestNightlyMode.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestNightlyMode.java deleted file mode 100644 index f5752a02..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestNightlyMode.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static org.junit.Assert.assertTrue; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.annotations.Nightly; -import com.carrotsearch.randomizedtesting.annotations.TestGroup; - -/** - * Nightly mode checks. - */ -public class TestNightlyMode extends WithNestedTestClass { - public static class Nested extends RandomizedTest { - @Test - public void passOnNightlyOnly() { - assumeRunningNested(); - assertTrue(isNightly()); - } - - @Test @Nightly("Nightly only test case.") - public void nightlyOnly() throws Exception { - } - } - - @Test - public void invalidValueNightly() { - System.setProperty(TestGroup.Utilities.getSysProperty(Nightly.class), "invalid-value"); - dailyDefault(); - } - - @Test - public void nightly() { - System.setProperty(TestGroup.Utilities.getSysProperty(Nightly.class), "yes"); - checkTestsOutput(2, 0, 0, 0, Nested.class); - } - - @Test - public void dailyDefault() { - checkTestsOutput(2, 0, 1, 1, Nested.class); - } - - @Before - public void cleanupBefore() { - cleanupAfter(); - } - - @After - public void cleanupAfter() { - System.clearProperty(TestGroup.Utilities.getSysProperty(Nightly.class)); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestOutOfScopeRandomUse.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestOutOfScopeRandomUse.java deleted file mode 100644 index ffc3300e..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestOutOfScopeRandomUse.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static org.junit.Assert.fail; - -import java.util.List; -import java.util.Random; - -import org.assertj.core.api.Assertions; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.notification.Failure; - -import com.carrotsearch.randomizedtesting.annotations.Timeout; - -import org.junit.Assert; - -/** - * Check out of scope {@link Random} use. - */ -public class TestOutOfScopeRandomUse extends WithNestedTestClass { - public static class Nested extends RandomizedTest { - static Random instanceRandom; - static Random beforeHookRandom; - static Random staticContextRandom; - volatile static Random otherThreadRandom; - - @BeforeClass - public static void beforeClass() throws Exception { - assumeRunningNested(); - instanceRandom = null; - staticContextRandom = getRandom(); - - // Should be able to use the random we've acquired for the static context. - staticContextRandom.nextBoolean(); - - Thread t = new Thread() { - public void run() { - otherThreadRandom = getRandom(); - } - }; - t.start(); - t.join(); - } - - @AfterClass - public static void afterClass() { - if (!isRunningNested()) { - return; - } - - // Again should be able to use the random we've acquired for the static context. - staticContextRandom.nextBoolean(); - } - - @Before - public void before() { - beforeHookRandom = getRandom(); - } - - private void touchRandom() { - assumeRunningNested(); - - // We shouldn't be able to reach to some other thread's random for which - // the context is still valid. - try { - otherThreadRandom.nextBoolean(); - fail("Shouldn't be able to use another thread's Random."); - } catch (IllegalStateException e) { - // Expected. - } - - // We should always be able to reach to @Before hook initialized Random. - beforeHookRandom.nextBoolean(); - - // Check if we're the first method or the latter methods. - if (instanceRandom == null) { - instanceRandom = getRandom(); - } else { - // for anything not-first, we shouldn't be able to reuse first random anymore. - try { - instanceRandom.nextBoolean(); - fail("Shouldn't be able to use another test's Random."); - } catch (IllegalStateException e) { - // Expected. - } - } - } - - @Test - public void method1() throws Exception { - touchRandom(); - } - - @Test @Timeout(millis = 2000) - public void method2() throws Exception { - touchRandom(); - - // We shouldn't be able to use the static random because timeouting tests - // are executed in their own thread and before and after class hooks are - // dispatched in their own thread to allow termination/ interruptions. - try { - staticContextRandom.nextBoolean(); - fail("Shouldn't be able to use static context thread's Random."); - } catch (IllegalStateException e) { - // Expected. - } - } - } - - @Before - public void checkRunningWithAssertions() { - // Sharing Random is only checked with -ea - // https://github.com/randomizedtesting/randomizedtesting/issues/234 - RandomizedTest.assumeTrue("AssertionRandom not verifying sharing.", AssertingRandom.isVerifying()); - } - - @Test - public void testCrossTestCaseIsolation() throws Throwable { - List failures = runTests(Nested.class).getFailures(); - Assertions.assertThat(failures).isEmpty(); - } - - @Test - public void testCrossTestSuiteIsolation() { - runTests(Nested.class); - try { - Nested.staticContextRandom.nextBoolean(); - Assert.fail("Shouldn't be able to use another suite's Random."); - } catch (IllegalStateException e) { - // Expected. - } - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestOverlappingMethodProviders.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestOverlappingMethodProviders.java deleted file mode 100644 index 2850fa39..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestOverlappingMethodProviders.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.JUnitCore; -import org.junit.runner.Result; - -import com.carrotsearch.randomizedtesting.annotations.TestMethodProviders; - -public class TestOverlappingMethodProviders { - @TestMethodProviders({ - JUnit4MethodProvider.class, - JUnit3MethodProvider.class - }) - public static class Base { - @Test - public void testMe() {} - } - - @Test - public void testSingleMethod() throws Exception { - Result r = new JUnitCore().run(Base.class); - Assert.assertEquals(0, r.getFailureCount()); - Assert.assertEquals(1, r.getRunCount()); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestOverridingDefaultExceptionHandler.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestOverridingDefaultExceptionHandler.java deleted file mode 100644 index 4cc50d00..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestOverridingDefaultExceptionHandler.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.lang.Thread.UncaughtExceptionHandler; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -import org.assertj.core.api.Assertions; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -public class TestOverridingDefaultExceptionHandler extends WithNestedTestClass { - static List throwableMessages = new CopyOnWriteArrayList<>(); - - @SuppressWarnings("serial") - public static class TestException extends RuntimeException { - public TestException(String msg) { - super(msg); - } - } - - public static class Nested extends RandomizedTest { - private static UncaughtExceptionHandler defaultHandler; - - @BeforeClass - public static void beforeClass() { - defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); - Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { - public void uncaughtException(Thread t, Throwable e) { - if (e instanceof TestException) { - throwableMessages.add(e.getMessage()); - } else { - defaultHandler.uncaughtException(t, e); - } - } - }); - } - - @AfterClass - public static void afterClass() { - Thread.setDefaultUncaughtExceptionHandler(defaultHandler); - } - - @Test - public void exceptionFromChildThread() throws Exception { - Thread t = new Thread() { - @Override - public void run() { - throw new TestException("exceptionFromChildThread"); - } - }; - t.start(); - t.join(); - } - - @Test - public void exceptionFromSubGroup() throws Exception { - ThreadGroup subgroup = new ThreadGroup("subgroup"); - Thread t = new Thread(subgroup, new Runnable() { - @Override - public void run() { - throw new TestException("exceptionFromSubGroup"); - } - }); - t.start(); - t.join(); - } - } - - @Test - public void testHandlerPropagation() { - runTests(Nested.class); - - Assertions.assertThat(throwableMessages).contains("exceptionFromChildThread"); - Assertions.assertThat(throwableMessages).contains("exceptionFromSubGroup"); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestParameterized.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestParameterized.java deleted file mode 100644 index 060d3b62..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestParameterized.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static org.junit.Assert.*; - -import java.util.Arrays; -import java.util.Collections; - -import org.assertj.core.api.Assertions; -import org.junit.Assert; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.annotations.Name; -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.Seed; -import com.carrotsearch.randomizedtesting.annotations.Seeds; - -public class TestParameterized extends WithNestedTestClass { - public static class Nested extends RandomizedTest { - public Nested(@Name("value") int value, @Name("string") String v) { - } - - @Test - @Repeat(iterations = 3) - public void testOne() { - } - - @Test - public void testTwo() { - } - - @Seeds({@Seed("deadbeef"), @Seed("cafebabe")}) - @Test - @Repeat(iterations = 2, useConstantSeed = true) - public void testThree() { - } - - @ParametersFactory - public static Iterable parameters() { - return Arrays.asList($$( - $(1, "abc"), - $(2, "def"))); - } - } - - @Test - public void testWithRepeatsAndSeeds() { - checkTestsOutput(16, 0, 0, 0, Nested.class); - } - - public static class Nested2 extends RandomizedTest { - public Nested2(@Name("paramName") int value) { - } - - @Test - public void failing() { - assumeRunningNested(); - fail(); - } - - @ParametersFactory - public static Iterable parameters() { - assumeRunningNested(); - return Arrays.asList($$($("xyz"))); - } - } - - @Test - public void testNameAnnotation() { - FullResult r = checkTestsOutput(1, 0, 1, 0, Nested2.class); - Assertions.assertThat(r.getFailures()).hasSize(1); - Assertions.assertThat(r.getFailures().get(0).getDescription().getMethodName()) - .contains("paramName=xyz"); - Assert.assertEquals("failing", RandomizedRunner.methodName(r.getFailures().get(0).getDescription())); - } - - public static class Nested3 extends Nested2 { - public Nested3(@Name("paramName") int value) { - super(value); - } - - @ParametersFactory - public static Iterable parameters() { - return Collections.emptyList(); - } - } - - public static class Nested4 extends Nested3 { - public Nested4(@Name("paramName") int value) { - super(value); - } - - @ParametersFactory - public static Iterable parameters() { - assumeTrue(false); - throw new RuntimeException(); - } - } - - - public static class Nested5 extends RandomizedTest { - public Nested5() {} - - @Test - public void testMe() {} - - @ParametersFactory - public static Iterable parameters() { - return Arrays.asList(new Object[] {}, - new Integer[] {}); - } - } - - @Test - public void testEmptyParamsList() { - checkTestsOutput(0, 0, 0, 0, Nested3.class); - checkTestsOutput(0, 0, 0, 0, Nested4.class); - } - - @Test - public void testNonObjectArray() { - checkTestsOutput(2, 0, 0, 0, Nested5.class); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestParameterizedShufflesOrder.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestParameterizedShufflesOrder.java deleted file mode 100644 index 536d198f..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestParameterizedShufflesOrder.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.assertj.core.api.Assertions; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; - -public class TestParameterizedShufflesOrder extends WithNestedTestClass { - static StringBuilder buf; - - public static abstract class Base extends RandomizedTest { - private final int value; - - public Base(int value) { - this.value = value; - } - - @BeforeClass - public static void checkNested() { - assumeRunningNested(); - } - - @Test - public void testFoo() { - buf.append(value).append(","); - } - } - - public static class NoShuffle extends Base { - public NoShuffle(int value) { - super(value); - } - - @ParametersFactory(shuffle = false) - public static Iterable parameters() { - List params = new ArrayList(); - for (int i = 0; i < 10; i++) { - params.add($(i)); - } - return params; - } - } - - public static class WithShuffle extends Base { - public WithShuffle(int value) { - super(value); - } - - @ParametersFactory() - public static Iterable parameters() { - List params = new ArrayList(); - for (int i = 0; i < 10; i++) { - params.add($(i)); - } - return params; - } - } - - @Test - public void testWithoutShuffle() { - Set runs = new HashSet(); - for (int i = 0; i < 10; i++) { - buf = new StringBuilder(); - Assertions.assertThat(runTests(NoShuffle.class).wasSuccessful()).isTrue(); - runs.add(buf.toString()); - } - Assertions.assertThat(runs).hasSize(1); - } - - @Test - public void testWithShuffle() { - Set runs = new HashSet(); - int iters = 10; - for (int i = 0; i < iters; i++) { - buf = new StringBuilder(); - Assertions.assertThat(runTests(WithShuffle.class).wasSuccessful()).isTrue(); - runs.add(buf.toString()); - } - Assertions.assertThat(runs).hasSize(iters); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandom.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandom.java deleted file mode 100644 index fa031594..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandom.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static org.junit.Assert.*; - -import java.util.Arrays; -import java.util.Random; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.annotations.Repeat; - -@Repeat(iterations = 100) -public class TestRandom extends RandomizedTest { - @Test - public void testDoubleDistribution() { - Random rnd = getRandom(); - - int [] buckets = new int [100]; - int reps = 1000000; - for (int i = 0; i < reps; i++) { - double d = rnd.nextDouble(); - if (d < 0d || d >= 1d) { - fail("Oops: " + d); - } - - buckets[(int) (d * buckets.length)]++; - } - - // The distribution should be +- 10% within average. - int expectedAverage = reps / buckets.length; - int min = expectedAverage - expectedAverage / 10; - int max = expectedAverage + expectedAverage / 10; - for (int i = 0; i < buckets.length; i++) { - if (buckets[i] < min || buckets[i] > max) { - fail("oops: " + buckets[i] + " biased? " + Arrays.toString(buckets)); - } - } - } - - @Test - public void testFloatDistribution() { - Random rnd = getRandom(); - - int [] buckets = new int [100]; - int reps = 1000000; - for (int i = 0; i < reps; i++) { - float d = rnd.nextFloat(); - if (d < 0f || d >= 1f) { - fail("Oops: " + d); - } - - buckets[(int) (d * buckets.length)]++; - } - - // The distribution should be +- 10% within average. - int expectedAverage = reps / buckets.length; - int min = expectedAverage - expectedAverage / 10; - int max = expectedAverage + expectedAverage / 10; - for (int i = 0; i < buckets.length; i++) { - if (buckets[i] < min || buckets[i] > max) { - fail("oops: " + buckets[i] + " biased? " + Arrays.toString(buckets)); - } - } - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandomInStaticInitializer.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandomInStaticInitializer.java deleted file mode 100644 index c17bf964..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandomInStaticInitializer.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.Random; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Check out of scope {@link Random} use. - */ -public class TestRandomInStaticInitializer extends RandomizedTest { - static boolean wasOutOfScope; - - static { - try { - RandomizedContext.current(); - } catch (IllegalStateException e) { - wasOutOfScope = true; - } - } - - @Test - public void testStaticInitializerOutOfScope() { - assertTrue(wasOutOfScope); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandomNumbers.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandomNumbers.java deleted file mode 100644 index 2c930862..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandomNumbers.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static org.junit.Assert.*; - -import java.util.Random; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.generators.RandomNumbers; - -@Repeat(iterations = 100) -public class TestRandomNumbers extends RandomizedTest { - @Test - public void testRandomIntBetween() { - int max = Integer.MAX_VALUE; - int min = Integer.MIN_VALUE; - - Random rnd = getRandom(); - checkRandomInt(rnd, 1, 1); - checkRandomInt(rnd, 0, 100); - checkRandomInt(rnd, 0, max); - checkRandomInt(rnd, min, 0); - checkRandomInt(rnd, -1, max); - checkRandomInt(rnd, min, 1); - checkRandomInt(rnd, min, max); - } - - @Test - public void testRandomLongBetween() { - long max = Long.MAX_VALUE; - long min = Long.MIN_VALUE; - - Random rnd = getRandom(); - checkRandomLong(rnd, 1, 1); - checkRandomLong(rnd, 0, 100); - checkRandomLong(rnd, 0, max); - checkRandomLong(rnd, min, 0); - checkRandomLong(rnd, -1, max); - checkRandomLong(rnd, min, 1); - checkRandomLong(rnd, min, max); - } - - private void checkRandomInt(Random rnd, int min, int max) { - for (int i = 0; i < 100000; i++) { - int v = RandomNumbers.randomIntBetween(rnd, min, max); - if (v < min || v > max) { - fail(min + " " + max + ": " + v); - } - } - } - - private void checkRandomLong(Random rnd, long min, long max) { - for (int i = 0; i < 100000; i++) { - long v = RandomNumbers.randomLongBetween(rnd, min, max); - if (v < min || v > max) { - fail(min + " " + max + ": " + v); - } - } - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandomizedContext.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandomizedContext.java deleted file mode 100644 index 48966f60..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandomizedContext.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.junit.Test; - -import java.util.concurrent.Callable; - -import static org.junit.Assert.*; - -/** - */ -public class TestRandomizedContext extends RandomizedTest { - - @Test - public void testRunWithPrivateRandomness() throws Exception { - final int iters = randomIntBetween(1, 10); - for (int j = 0; j < iters; j++) { - final long seed = randomLong(); - final int[] first = RandomizedContext.current().runWithPrivateRandomness(seed, new Callable() { - @Override - public int[] call() throws Exception { - final int size = randomIntBetween(10, 1000); - final int[] result = new int[size]; - for (int i = 0; i < size; i++) { - result[i] = randomInt(); - } - return result; - } - }); - assertNotNull(first); - final int[] second = RandomizedContext.current().runWithPrivateRandomness(seed, new Callable() { - @Override - public int[] call() throws Exception { - final int size = randomIntBetween(10, 1000); - final int[] result = new int[size]; - for (int i = 0; i < size; i++) { - result[i] = randomInt(); - } - return result; - } - }); - assertNotNull(second); - assertNotSame(first, second); - assertArrayEquals("first and second sequence must be identical", first, second); - } - } - -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandomizedTest.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandomizedTest.java deleted file mode 100644 index 40a53487..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRandomizedTest.java +++ /dev/null @@ -1,264 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.io.IOException; -import java.net.ServerSocket; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.TimeZone; -import java.util.Arrays; - -import org.junit.Test; -import org.junit.internal.AssumptionViolatedException; - -import static org.junit.Assert.*; - -public class TestRandomizedTest extends RandomizedTest { - @Test - public void testRandomIntBetween() { - boolean [] array = new boolean [10]; - for (int i = 0; i < 10000; i++) - array[randomIntBetween(0, array.length - 1)] = true; - - for (boolean b: array) - assertTrue(b); - } - - @Test - public void testAtLeast() { - assertEquals(atLeast(Integer.MAX_VALUE), Integer.MAX_VALUE); - int v = randomIntBetween(0, Integer.MAX_VALUE); - for (int i = 0; i < 10000; i++) - assertTrue(atLeast(v) >= v); - } - - @Test - public void testAtMost() { - assertEquals(atMost(0), 0); - int v = randomIntBetween(0, Integer.MAX_VALUE); - for (int i = 0; i < 10000; i++) - assertTrue(atMost(v) <= v); - } - - @Test - public void testRandomIntBetweenBoundaryCases() { - for (int i = 0; i < 10000; i++) { - int j = randomIntBetween(0, Integer.MAX_VALUE); - assertTrue(j >= 0 && j <= Integer.MAX_VALUE); - - // This must fall in range, but nonetheless - randomIntBetween(Integer.MIN_VALUE, Integer.MAX_VALUE); - } - } - - @Test - public void testRandomFromArray() { - try { - randomFrom(new Object [] {}); - fail(); - } catch (IllegalArgumentException e) { - // expected. - } - - Integer [] ints = new Integer [10]; - for (int i = 0; i < ints.length; i++) - ints[i] = i; - - for (int i = 0; i < 10000; i++) { - Integer j = randomFrom(ints); - if (j != null) { - ints[j] = null; - } - } - - for (int i = 0; i < ints.length; i++) - assertTrue(ints[i] == null); - } - - @Test - public void testRandomFromList() { - try { - randomFrom(Collections.emptyList()); - fail(); - } catch (IllegalArgumentException e) { - // expected. - } - - List ints = new ArrayList(); - for (int i = 0; i < 10; i++) - ints.add(i); - - for (int i = 0; i < 10000; i++) { - Integer j = randomFrom(ints); - if (j != null) { - ints.set(j, null); - } - } - - for (int i = 0; i < ints.size(); i++) - assertTrue(ints.get(i) == null); - } - - @Test - public void testNewTempDir() throws IOException { - for (int i = 0; i < 10; i++) { - Path dir = newTempDir(); - assertNotNull(dir); - assertTrue(Files.isDirectory(dir)); - assertTrue(Files.isWritable(dir)); - assertTrue(Files.isReadable(dir)); - assertTrue(Files.isExecutable(dir)); - try (DirectoryStream path = Files.newDirectoryStream(dir)) { - assertFalse(path.iterator().hasNext()); - } - } - } - - @Test - public void testNewTempFile() throws IOException { - for (int i = 0; i < 10; i++) { - Path file = newTempFile(); - assertNotNull(file); - assertTrue(Files.isRegularFile(file)); - assertTrue(Files.isWritable(file)); - assertTrue(Files.isReadable(file)); - assertTrue(file.getFileName().toString().indexOf(' ') >= 0); - Files.newOutputStream(file).close(); - } - } - - @Test - public void testRandomLocale() { - assertNotNull(randomLocale()); - } - - @Test - public void testRandomTimeZone() throws Exception { - try { - final String[] availableIDs = TimeZone.getAvailableIDs(); - Arrays.sort(availableIDs); - for (String id : availableIDs) { - assertNotNull(id); - if (TimeZone.getTimeZone(id) == null) { - fail("getTimeZone null: " + id); - } - } - } catch (Exception e) { - System.out.println("Wtf."); - e.printStackTrace(); - throw e; - } - - assertNotNull(randomTimeZone()); - } - - @Test - public void testRandomAsciiOfLength() { - assertTrue(randomAsciiLettersOfLength(0).isEmpty()); - - for (int i = 0; i < 1000; i++) { - int maxLength = randomIntBetween(0, 20); - String str = randomAsciiLettersOfLength(maxLength); - assertTrue(str.matches("[a-zA-Z]*")); - assertTrue(str.length() <= maxLength); - } - } - - @Test - public void testRandomAlphanumOfLength() { - assertTrue(randomAsciiAlphanumOfLength(0).isEmpty()); - - for (int i = 0; i < 1000; i++) { - int maxLength = randomIntBetween(0, 20); - String str = randomAsciiAlphanumOfLength(maxLength); - assertTrue(str.matches("[a-zA-Z0-9]*")); - assertTrue(str.length() <= maxLength); - } - } - - @Test - public void testRandomUnicodeOfLength() { - for (int i = 0; i < 1000; i++) { - int maxLength = randomIntBetween(0, 20); - String str = randomUnicodeOfLength(maxLength); - assertTrue(str.length() + " " + maxLength, str.length() <= maxLength); - } - } - - @Test - public void testRandomRealisticUnicodeOfLength() { - assertTrue(randomRealisticUnicodeOfLength(0).isEmpty()); - assertTrue(randomRealisticUnicodeOfCodepointLength(0).isEmpty()); - - for (int i = 0; i < 1000; i++) { - int minLength = randomIntBetween(0, 20); - int maxLength = minLength + randomIntBetween(0, 20); - String str = randomRealisticUnicodeOfCodepointLength(maxLength); - int codepoints = countCodepoints(str); - assertTrue(codepoints <= maxLength); - - str = randomRealisticUnicodeOfCodepointLengthBetween(minLength, maxLength); - codepoints = countCodepoints(str); - assertTrue(codepoints >= minLength); - assertTrue(codepoints <= maxLength); - } - } - - private static int countCodepoints(String str) { - return str.codePointCount(0, str.length()); - } - - @Test - public void testAssumeTrue() { - String message = randomUnicodeOfLength(10); - try { - assumeTrue(message, false); - } catch (AssumptionViolatedException e) { - assertTrue(e.getMessage().contains(message)); - } - } - - @Test - public void testAssumeNoException() { - String message = randomUnicodeOfLength(10); - Throwable t = new Throwable(); - try { - assumeNoException(message, t); - } catch (AssumptionViolatedException e) { - assertTrue(e.getMessage().contains(message)); - assertSame(t, e.getCause()); - } - } - - @Test - public void testIterations() { - assertEquals(0, iterations(0, 0)); - assertEquals(Integer.MAX_VALUE, iterations(Integer.MAX_VALUE, Integer.MAX_VALUE)); - - for (int i = 0; i < iterations(1, 1000); i++) { - int j = iterations(0, 100); - assertTrue(j >= 0 && j <= 100); - } - } - - @Test - public void testNewServerSocket() throws IOException { - ServerSocket socket = newServerSocket(LifecycleScope.TEST); - socket.close(); - } - - @Test - public void testRarely() throws IOException { - int rarely = 0; - int calls = 100000; - for (int i = 0; i < calls; i++) { - if (rarely()) rarely++; - } - - double rf = rarely / (double) calls * 100; - assertTrue("rarely should be > 5% & < 15%: " + rf, rf > 5 && rf < 15); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRepeatTestWithComplexDescription.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRepeatTestWithComplexDescription.java deleted file mode 100644 index 1cdeacf2..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRepeatTestWithComplexDescription.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.ArrayList; -import java.util.List; - -import org.assertj.core.api.Assertions; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.Description; -import org.junit.runner.notification.RunListener; - -import com.carrotsearch.randomizedtesting.annotations.Listeners; -import com.carrotsearch.randomizedtesting.annotations.Name; -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.Seed; -import com.carrotsearch.randomizedtesting.annotations.Seeds; -import com.carrotsearch.randomizedtesting.rules.SystemPropertiesRestoreRule; - -/** */ -public class TestRepeatTestWithComplexDescription extends WithNestedTestClass { - @Rule - public SystemPropertiesRestoreRule restoreProperties = new SystemPropertiesRestoreRule(); - - static ArrayList buf; - - public static class CaptureFailuresListener extends RunListener { - @Override - public void testStarted(Description description) throws Exception { - buf.add(description.getMethodName()); - } - } - - @Seed("deadbeef") - @Listeners({CaptureFailuresListener.class}) - public static class Nested extends RandomizedTest { - public Nested(@Name("value") String value) { - } - - @Test - @Seeds({@Seed(), @Seed("deadbeef")}) - @Repeat(iterations = 5, useConstantSeed = false) - public void testFoo() {} - - @Test - public void testBar() {} - - @ParametersFactory() - public static Iterable parameters() { - assumeRunningNested(); - - List params = new ArrayList(); - params.add($("")); - params.add($("a/b/c")); - params.add($("\\")); - params.add($("$[]{}\\")); - return params; - } - } - - @Test - public void checkFilteringByName() { - // Collect all test names first. - buf = new ArrayList(); - runTests(Nested.class); - - for (String testName : buf) { - buf = new ArrayList(); - System.setProperty(SysGlobals.SYSPROP_TESTMETHOD(), testName); - - Assertions.assertThat(runTests(Nested.class).wasSuccessful()).isTrue(); - Assertions.assertThat(buf).containsOnly(testName); - } - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestResourceDisposal.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestResourceDisposal.java deleted file mode 100644 index 4fb5b4dd..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestResourceDisposal.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.io.Closeable; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import org.junit.Assert; - - -/** - * Check resource disposal facilities. - */ -public class TestResourceDisposal extends WithNestedTestClass { - static class DummyCloseable implements Closeable { - public boolean closed; - public void close() throws IOException { - if (closed) throw new IOException(); - closed = true; - } - } - - public static class Nested extends RandomizedTest { - static List testScope = new ArrayList(); - static List suiteScope = new ArrayList(); - static boolean allTestScopeClosed; - static boolean allSuiteScopeOpen; - - @BeforeClass - public static void clean() { - testScope.clear(); - suiteScope.clear(); - - suiteScope.add(closeAfterSuite(new DummyCloseable())); - } - - @AfterClass - public static void afterClass() { - allTestScopeClosed = true; - for (DummyCloseable c : Nested.testScope) { - if (!c.closed) allTestScopeClosed = false; - } - - allSuiteScopeOpen = true; - for (DummyCloseable c : Nested.suiteScope) { - if (c.closed) allSuiteScopeOpen = false; - } - } - - @Test - public void testScopeResource() { - assumeRunningNested(); - testScope.add(closeAfterTest(new DummyCloseable())); - testScope.add(closeAfterTest(new DummyCloseable())); - } - - @Test - public void testScopeResourceWithFailures() { - assumeRunningNested(); - testScope.add(closeAfterTest(new DummyCloseable())); - testScope.add(closeAfterTest(new DummyCloseable())); - throw new RuntimeException(); - } - - @Test - public void suiteScopeFromTest() { - assumeRunningNested(); - suiteScope.add(closeAfterSuite(new DummyCloseable())); - suiteScope.add(closeAfterSuite(new DummyCloseable())); - } - } - - @Test - public void testResourceDisposalTestScope() { - checkTestsOutput(3, 0, 1, 0, Nested.class); - for (DummyCloseable c : Nested.testScope) { - Assert.assertTrue(c.closed); - } - Assert.assertTrue(Nested.allTestScopeClosed); - } - - @Test - public void testResourceDisposalSuiteScope() { - runTests(Nested.class); - for (DummyCloseable c : Nested.suiteScope) { - Assert.assertTrue(c.closed); - } - Assert.assertTrue(Nested.allSuiteScopeOpen); - } - - public static class Nested2 extends RandomizedTest { - @Test - public void testScope() { - assumeRunningNested(); - closeAfterTest(closeAfterTest(new DummyCloseable())); - } - } - - @Test - public void testFailedDisposalBreaksTestCase() { - FullResult r = checkTestsOutput(1, 0, 1, 0, Nested2.class); - Assert.assertTrue(r.getFailures().get(0).getException() instanceof ResourceDisposalError); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRules.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRules.java deleted file mode 100644 index fe52bbb9..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestRules.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.MethodRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runner.JUnitCore; -import org.junit.runner.Request; -import org.junit.runners.model.FrameworkMethod; -import org.junit.runners.model.Statement; - -/** - * {@link Rule} and {@link MethodRule} support. - */ -@SuppressWarnings({"deprecation"}) -public class TestRules extends WithNestedTestClass { - static List order; - - public static class MethodRuleSupport { - @Rule - public MethodRule rule1 = new MethodRule() { - public Statement apply(final Statement base, FrameworkMethod method, Object target) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - assumeRunningNested(); - order.add("rule1-before"); - base.evaluate(); - order.add("rule1-after"); - } - }; - } - }; - - @Test - public void passing() { - order.add("passing"); - } - } - - public static class SimpleRule implements TestRule { - private String msg; - - public SimpleRule(String msg) { - this.msg = msg; - } - - @Override - public Statement apply(final Statement base, Description description) { - return new Statement() { - public void evaluate() throws Throwable { - assumeRunningNested(); - order.add(msg + "-before"); - try { - base.evaluate(); - } finally { - order.add(msg + "-after"); - } - } - }; - } - } - - public static class NewRuleSupportPassing { - @Rule - public TestRule rule1 = RuleChain - .outerRule(new SimpleRule("outer")) - .around(new SimpleRule("inner")); - - @Test - public void passing() { - order.add("passing"); - } - } - - public static class NewRuleSupportFailing { - @Rule - public TestRule rule1 = RuleChain - .outerRule(new SimpleRule("outer")) - .around(new SimpleRule("inner")); - - @Test - public void failing() { - order.add("failing"); - throw new RuntimeException(); - } - } - - public static class NewRuleSupportIgnored { - @Rule - public TestRule rule1 = RuleChain - .outerRule(new SimpleRule("outer")) - .around(new SimpleRule("inner")); - - @Test @Ignore - public void ignored() { - order.add("ignored"); - throw new RuntimeException(); - } - } - - @Test - public void checkOldMethodRules() throws Exception { - assertSameExecution(MethodRuleSupport.class); - } - - @Test - public void checkNewTestRules() throws Exception { - assertSameExecution(NewRuleSupportPassing.class); - assertSameExecution(NewRuleSupportFailing.class); - assertSameExecution(NewRuleSupportIgnored.class); - } - - private void assertSameExecution(Class clazz) throws Exception { - order = new ArrayList<>(); - runTests(clazz); - List order1 = order; - order = new ArrayList<>(); - - new JUnitCore().run(Request.runner(new RandomizedRunner(clazz))); - List order2 = order; - order = null; - - Assert.assertEquals(order1, order2); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedDecorator.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedDecorator.java deleted file mode 100644 index 89872ae4..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedDecorator.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.*; - -import org.assertj.core.api.Assertions; -import org.junit.*; -import org.junit.runner.RunWith; - -import com.carrotsearch.randomizedtesting.annotations.SeedDecorators; -import com.carrotsearch.randomizedtesting.generators.RandomStrings; - -/** - * Test seed decorators. - */ -public class TestSeedDecorator extends WithNestedTestClass { - private static List runnerSeeds = new ArrayList(); - private static List strings = new ArrayList(); - - @RunWith(RandomizedRunner.class) - public static class Nested1 { - @BeforeClass - public static void generateSequence() { - strings.add(RandomStrings.randomAsciiLettersOfLength(RandomizedContext.current().getRandom(), 200)); - } - - @Test - public void method1() { - assumeRunningNested(); - runnerSeeds.add(RandomizedContext.current().getRunnerSeedAsString()); - } - } - - public static class Nested2 extends Nested1 { - } - - @SeedDecorators({ - MixWithSuiteName.class - }) - public static class Nested3 extends Nested1 { - } - - public static class Nested4 extends Nested3 { - } - - @Before @After - public void cleanup() { - runnerSeeds.clear(); - strings.clear(); - System.clearProperty(SysGlobals.SYSPROP_RANDOM_SEED()); - } - - @Test - public void testDecoratedMaster() { - String masterSeed = SeedUtils.formatSeed(new Random().nextLong()); - System.setProperty(SysGlobals.SYSPROP_RANDOM_SEED(), masterSeed); - - // These classes should get a different master seed (perturbed by decorator). - runTests(Nested1.class, Nested2.class, Nested3.class, Nested4.class); - - // All four classes get the same initial "runner" seed. - Assert.assertEquals(4, runnerSeeds.size()); - Assert.assertEquals(1, new HashSet(runnerSeeds).toArray().length); - - // @BeforeClass scope strings for Nested1 and Nested2 should be the same - // because these classes share identical master seed. - Assertions.assertThat(strings.get(1)).isEqualTo(strings.get(0)); - // but Nested3 and Nested4 have a seed decorator so strings there - // should be different. - Assertions.assertThat(strings.get(2)).isNotEqualTo(strings.get(0)); - Assertions.assertThat(strings.get(3)).isNotEqualTo(strings.get(0)); - Assertions.assertThat(strings.get(2)).isNotEqualTo(strings.get(3)); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedFixing.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedFixing.java deleted file mode 100644 index f61402a7..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedFixing.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static org.junit.Assert.assertEquals; - -import org.assertj.core.api.Assertions; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.carrotsearch.randomizedtesting.annotations.Seed; - -/** - * Seed fixing for static fixtures and/or methods using annotations. - */ -@RunWith(RandomizedRunner.class) -@Seed("deadbeef") -public class TestSeedFixing { - @BeforeClass - public static void beforeClass() { - assertEquals(0xdeadbeefL, RandomizedContext.current().getRandomness().getSeed()); - } - - @Seed("cafebabe") - @Test - public void dummy() { - Assertions - .assertThat(Long.toHexString(RandomizedContext.current().getRandomness().getSeed())) - .isEqualTo("cafebabe"); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedFixingWithProperties.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedFixingWithProperties.java deleted file mode 100644 index 4d922b9e..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedFixingWithProperties.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static com.carrotsearch.randomizedtesting.SysGlobals.SYSPROP_ITERATIONS; -import static com.carrotsearch.randomizedtesting.SysGlobals.SYSPROP_RANDOM_SEED; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Seed fixing for static fixtures and/or methods using system properties. - */ -public class TestSeedFixingWithProperties extends WithNestedTestClass { - static List seeds = new ArrayList(); - - @RunWith(RandomizedRunner.class) - public static class Nested { - @BeforeClass - public static void staticFixture() { - seeds.add(RandomizedContext.current().getRandomness().getSeed()); - } - - @Test - public void testMethod() { - seeds.add(RandomizedContext.current().getRandomness().getSeed()); - } - } - - /** - * Combined seed: fixing everything: the runner, method and any repetitions. - */ - @Test - public void testRunnerAndMethodProperty() { - System.setProperty(SYSPROP_RANDOM_SEED(), "deadbeef:cafebabe"); - System.setProperty(SYSPROP_ITERATIONS(), "3"); - runTests(Nested.class); - assertEquals(Arrays.asList(0xdeadbeefL, 0xcafebabeL, 0xcafebabeL, 0xcafebabeL), seeds); - } - - /** - * Runner seed fixing only (methods have predictable pseudo-random seeds derived from - * the runner). - */ - @Test - public void testFixedRunnerPropertyOnly() { - System.setProperty(SYSPROP_RANDOM_SEED(), "deadbeef"); - System.setProperty(SYSPROP_ITERATIONS(), "3"); - checkTestsOutput(3, 0, 0, 0, Nested.class); - assertEquals(0xdeadbeefL, seeds.get(0).longValue()); - // _very_ slim chances of this actually being true... - assertFalse( - seeds.get(0).longValue() == seeds.get(1).longValue() && - seeds.get(1).longValue() == seeds.get(2).longValue()); - - // We should have the same randomized seeds on methods for the same runner seed, - // so check if this is indeed true. - List copy = new ArrayList(seeds); - seeds.clear(); - runTests(Nested.class); - assertEquals(copy, seeds); - } - - @Before - public void cleanupBefore() { - cleanupAfter(); - } - - @After - public void cleanupAfter() { - System.clearProperty(SYSPROP_ITERATIONS()); - System.clearProperty(SYSPROP_RANDOM_SEED()); - seeds.clear(); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedParameterOptional.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedParameterOptional.java deleted file mode 100644 index 0076c271..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedParameterOptional.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.HashSet; - -import org.junit.Assert; - -import org.junit.Test; -import org.junit.runner.*; -import org.junit.runner.notification.RunListener; - -import com.carrotsearch.randomizedtesting.annotations.*; - - -/** - * Check if seed parameter is optional if no repetitions - * of the test are requested. - */ -public class TestSeedParameterOptional extends WithNestedTestClass { - public static class Nested extends RandomizedTest { - @Seeds({ - @Seed("deadbeef"), - @Seed("cafebabe"), - @Seed // Adds a randomized execution too. - }) - @Test - @Repeat(iterations = 2, useConstantSeed = true) - public void method1() { } - - @Seed("cafebabe") - @Test - public void method2() { } - - @Test - public void method3() { } - } - - @Test - public void checkNames() { - final HashSet tests = new HashSet(); - - JUnitCore junit = new JUnitCore(); - junit.addListener(new RunListener() { - @Override - public void testStarted(Description description) throws Exception { - tests.add(description.getMethodName()); - } - }); - - junit.run(Nested.class); - - // Single repetitions, no seed parameter in test name. - Assert.assertTrue(tests.contains("method2")); - Assert.assertTrue(tests.contains("method3")); - - // Method 1 has 2x3 repetitions. - int count = 0; - for (String s : tests) { - if (s.startsWith("method1")) { - count++; - } - } - Assert.assertEquals(6, count); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedRepeatable.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedRepeatable.java deleted file mode 100644 index b2450856..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSeedRepeatable.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static org.junit.Assert.assertEquals; - -import java.util.HashMap; -import java.util.Map; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.carrotsearch.randomizedtesting.annotations.Seed; - -public class TestSeedRepeatable extends WithNestedTestClass { - @Seed("deadbeef") - @RunWith(RandomizedRunner.class) - public static class Nested { - static Map seeds = new HashMap(); - - @BeforeClass - public static void nested() { - assumeRunningNested(); - } - - @Test - public void testMethod1() { - checkSeed("method1"); - } - - @Test - public void testMethod2() { - checkSeed("method2"); - } - - private void checkSeed(String key) { - final Object seed = RandomizedContext.current().getRandomness().getSeed(); - if (seeds.containsKey(key)) { - assertEquals(seeds.get(key), seed); - } else { - seeds.put(key, seed); - } - } - } - - /** - * Check if methods get the same seed on every run with a fixed runner's seed. - */ - @Test - public void testSameMethodRandomnessWithFixedRunner() { - Nested.seeds.clear(); - checkTestsOutput(2, 0, 0, 0, Nested.class); - checkTestsOutput(2, 0, 0, 0, Nested.class); - checkTestsOutput(2, 0, 0, 0, Nested.class); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSetSeedLocked.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSetSeedLocked.java deleted file mode 100644 index 097c9f12..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestSetSeedLocked.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.junit.Test; - -import static org.junit.Assert.*; - -public class TestSetSeedLocked extends RandomizedTest { - @Test - public void testMethod() { - try { - getRandom().setSeed(0); - fail(); - } catch (RuntimeException e) { - // Ok, expected. - } - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestStackAugmentation.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestStackAugmentation.java deleted file mode 100644 index 09a2dfa8..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestStackAugmentation.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runner.notification.Failure; - -import com.carrotsearch.randomizedtesting.annotations.Seed; - -/** - * {@link RandomizedRunner} can augment stack traces to include seed info. Check - * if it works. - */ -public class TestStackAugmentation extends WithNestedTestClass { - @RunWith(RandomizedRunner.class) - @Seed("deadbeef") - public static class Nested { - @Test @Seed("cafebabe") - public void testMethod1() { - assumeRunningNested(); - - // Throws a chained exception. - try { - throw new RuntimeException("Inner."); - } catch (Exception e) { - throw new Error("Outer.", e); - } - } - } - - @Test - public void testMethodLevel() { - FullResult result = checkTestsOutput(1, 0, 1, 0, Nested.class); - - Failure f = result.getFailures().get(0); - String seedFromThrowable = RandomizedRunner.seedFromThrowable(f.getException()); - assertNotNull(seedFromThrowable); - assertTrue("[DEADBEEF:CAFEBABE]".compareToIgnoreCase(seedFromThrowable) == 0); - } - - @RunWith(RandomizedRunner.class) - @Seed("deadbeef") - public static class Nested2 { - @BeforeClass - public static void beforeClass() { - assumeRunningNested(); - throw new Error("beforeclass."); - } - - @Test @Seed("cafebabe") - public void testMethod1() { - } - } - - @Test - public void testBeforeClass() { - FullResult result = checkTestsOutput(0, 0, 1, 0, Nested2.class); - assertEquals(1, result.getFailureCount()); - - Failure f = result.getFailures().get(0); - String seedFromThrowable = RandomizedRunner.seedFromThrowable(f.getException()); - assertNotNull(seedFromThrowable); - assertTrue(f.getTrace(), "[DEADBEEF]".compareToIgnoreCase(seedFromThrowable) == 0); - } - - @RunWith(RandomizedRunner.class) - @Seed("deadbeef") - public static class Nested3 { - @AfterClass - public static void afterClass() { - assumeRunningNested(); - throw new Error("afterclass."); - } - - @Test @Seed("cafebabe") - public void testMethod1() { - } - } - - @Test - public void testAfterClass() { - FullResult result = checkTestsOutput(1, 0, 1, 0, Nested3.class); - - Failure f = result.getFailures().get(0); - String seedFromThrowable = RandomizedRunner.seedFromThrowable(f.getException()); - assertNotNull(seedFromThrowable); - assertTrue(f.getTrace(), "[DEADBEEF]".compareToIgnoreCase(seedFromThrowable) == 0); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTargetMethod.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTargetMethod.java deleted file mode 100644 index 56709f0d..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTargetMethod.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.assertj.core.api.Assertions; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.annotations.Repeat; - -public class TestTargetMethod extends WithNestedTestClass { - public static class Nested extends RandomizedTest { - @Before - public void checkInHook() { - assumeRunningNested(); - } - - @Test - @Repeat(iterations = 3) - public void testOne() { - Assertions.assertThat(RandomizedContext.current().getTargetMethod().getName()) - .isEqualTo("testOne"); - } - - @Test - public void testTwo() { - Assertions.assertThat(RandomizedContext.current().getTargetMethod().getName()) - .isEqualTo("testTwo"); - } - - @AfterClass - @BeforeClass - public static void staticHooks() { - Assertions.assertThat(RandomizedContext.current().getTargetMethod()) - .isNull(); - } - } - - @Test - public void testTargetMethodAvailable() { - checkTestsOutput(4, 0, 0, 0, Nested.class); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestCaseInstanceProviders.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestCaseInstanceProviders.java deleted file mode 100644 index 1fe1459e..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestCaseInstanceProviders.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.Arrays; -import java.util.IdentityHashMap; - -import org.assertj.core.api.Assertions; -import org.junit.Before; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.Seed; -import com.carrotsearch.randomizedtesting.annotations.Seeds; -import com.carrotsearch.randomizedtesting.annotations.TestCaseInstanceProvider; -import com.carrotsearch.randomizedtesting.annotations.TestCaseInstanceProvider.Type; - -public class TestTestCaseInstanceProviders extends WithNestedTestClass { - private static IdentityHashMap set = new IdentityHashMap<>(); - - @TestCaseInstanceProvider(Type.INSTANCE_PER_CONSTRUCTOR_ARGS) - public static class Nested extends RandomizedTest { - @Before - public void setup() { - assumeRunningNested(); - set.put(this, null); - } - - @Test - @Repeat(iterations = 3) - public void testOne() { - set.put(this, null); - } - - @Test - public void testTwo() { - set.put(this, null); - } - - @Seeds({@Seed("deadbeef"), @Seed("cafebabe")}) - @Test - @Repeat(iterations = 2, useConstantSeed = true) - public void testThree() { - set.put(this, null); - } - } - - @Before - public void setup() { - set.clear(); - } - - @Test - public void testDefaultConstructor() { - checkTestsOutput(3 + 1 + 2 * 2, 0, 0, 0, Nested.class); - Assertions.assertThat(set).hasSize(1); - } - - public static class Nested2 extends Nested { - public Nested2(String arg) { - } - - @ParametersFactory - public static Iterable params() { - return Arrays.asList($("1"), $("2"), $("3")); - } - } - - @Test - public void testParameterProviders() { - checkTestsOutput(3 * (3 + 1 + 2 * 2), 0, 0, 0, Nested2.class); - Assertions.assertThat(set).hasSize(3); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestCaseOrdering.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestCaseOrdering.java deleted file mode 100644 index a1318168..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestCaseOrdering.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.TestCaseOrdering; - -public class TestTestCaseOrdering extends WithNestedTestClass { - static List buf; - - @TestCaseOrdering(TestCaseOrdering.AlphabeticOrder.class) - public static class Alphabetical extends RandomizedTest { - @Before public void assumeNested() { assumeRunningNested(); } - @Test public void a() { buf.add("a"); } - @Test public void b() { buf.add("b"); } - @Test public void c() { buf.add("c"); } - @Test public void d() { buf.add("d"); } - } - - @TestCaseOrdering(TestCaseOrdering.AlphabeticOrder.class) - @Repeat(iterations = 3) - public static class AlphabeticalWithRepetitions extends RandomizedTest { - @Before public void assumeNested() { assumeRunningNested(); } - @Test public void a() { buf.add("a"); } - @Test public void b() { buf.add("b"); } - @Test public void c() { buf.add("c"); } - @Test public void d() { buf.add("d"); } - } - - public static class CustomOrder implements Comparator { - @Override - public int compare(TestMethodAndParams o1, TestMethodAndParams o2) { - int v = o1.getTestMethod().getName().compareTo( - o2.getTestMethod().getName()); - if (v == 0) { - v = ((String) o1.getInstanceArguments().get(0)).compareTo( - ((String) o2.getInstanceArguments().get(0))); - } - - return v; - } - } - - @TestCaseOrdering(CustomOrder.class) - public static class AlphabeticalWithParameters extends RandomizedTest { - String param; - - public AlphabeticalWithParameters(String param) { - this.param = param; - } - - @Before public void assumeNested() { assumeRunningNested(); } - @Test public void a() { buf.add("a:" + param); } - @Test public void b() { buf.add("b:" + param); } - @Test public void c() { buf.add("c:" + param); } - @Test public void d() { buf.add("d:" + param); } - - @ParametersFactory - public static Iterable params() { - return Arrays.asList($("1"), $("2"), $("3")); - } - } - - @Before - public void clean() { - buf = new ArrayList<>(); - } - - @Test - public void testAlphabetical() { - runTests(Alphabetical.class); - assertThat(buf).containsExactly("a", "b", "c", "d"); - } - - @Test - public void testAlphabeticalWithRepetitions() { - runTests(AlphabeticalWithRepetitions.class); - assertThat(buf).containsExactly( - "a", "a", "a", - "b", "b", "b", - "c", "c", "c", - "d", "d", "d"); - } - - @Test - public void testAlphabeticalWithParameters() { - runTests(AlphabeticalWithParameters.class); - assertThat(buf).containsExactly( - "a:1", "a:2", "a:3", - "b:1", "b:2", "b:3", - "c:1", "c:2", "c:3", - "d:1", "d:2", "d:3"); - } -} - diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestFiltering.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestFiltering.java deleted file mode 100644 index 946462c3..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestFiltering.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static com.carrotsearch.randomizedtesting.annotations.TestGroup.Utilities.getSysProperty; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.concurrent.atomic.AtomicInteger; - -import org.assertj.core.api.Assertions; -import org.junit.Rule; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.annotations.TestGroup; -import com.carrotsearch.randomizedtesting.rules.SystemPropertiesRestoreRule; - -/** - * Custom test groups. - */ -public class TestTestFiltering extends WithNestedTestClass { - @Rule - public SystemPropertiesRestoreRule restoreProperties = new SystemPropertiesRestoreRule(); - - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD, ElementType.TYPE}) - @Inherited - @TestGroup(enabled = false) - public static @interface Foo { - } - - static AtomicInteger counter = new AtomicInteger(); - - public static class Nested1 extends RandomizedTest { - @Test @Foo - public void test1() { - counter.incrementAndGet(); - } - } - - @Test - public void filterVsRulePriority() { - System.setProperty(getSysProperty(Foo.class), "false"); - - // Don't run by default (group is disabled by default). - counter.set(0); - System.setProperty(SysGlobals.SYSPROP_TESTFILTER(), ""); - checkTestsOutput(1, 0, 0, 1, Nested1.class); - Assertions.assertThat(counter.get()).isEqualTo(0); - - // Run @foo methods even though the group is disabled (but the filtering rule takes priority). - counter.set(0); - System.setProperty(SysGlobals.SYSPROP_TESTFILTER(), "@foo"); - checkTestsOutput(1, 0, 0, 0, Nested1.class); - Assertions.assertThat(counter.get()).isEqualTo(1); - - // Run the "default" filter. - counter.set(0); - System.setProperty(SysGlobals.SYSPROP_TESTFILTER(), "default"); - checkTestsOutput(0, 0, 0, 0, Nested1.class); - Assertions.assertThat(counter.get()).isEqualTo(0); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestGroups.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestGroups.java deleted file mode 100644 index 0b9d5c40..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestGroups.java +++ /dev/null @@ -1,187 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import static com.carrotsearch.randomizedtesting.annotations.TestGroup.Utilities.*; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.annotations.Nightly; -import com.carrotsearch.randomizedtesting.annotations.TestGroup; - -/** - * Custom test groups. - */ -public class TestTestGroups extends WithNestedTestClass { - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD, ElementType.TYPE}) - @Inherited - @TestGroup(enabled = true) - public static @interface Group1 { - } - - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD, ElementType.TYPE}) - @Inherited - @TestGroup(enabled = false, name = "abc", sysProperty = "custom.abc") - public static @interface Group2 { - } - - public static class Nested1 extends RandomizedTest { - @Test @Group1 @Group2 - public void test1() { - } - - @BeforeClass - public static void beforeClass() { - beforeClassRan = true; - } - - @AfterClass - public static void afterClass() { - afterClassRan = true; - } - } - - public static class Nested3 extends Nested1 { - @Test - public void testUnconditional() { - } - } - - @Group1 @Group2 - public static class Nested2 extends RandomizedTest { - @Test - public void test1() { - } - - @BeforeClass - public static void beforeClass() { - beforeClassRan = true; - } - - @AfterClass - public static void afterClass() { - afterClassRan = true; - } - } - - public static boolean beforeClassRan; - public static boolean afterClassRan; - - @Test - public void checkDefaultNames() { - Assert.assertEquals("group1", getGroupName(Group1.class)); - Assert.assertEquals("abc", getGroupName(Group2.class)); - Assert.assertEquals(SysGlobals.CURRENT_PREFIX() + ".group1", getSysProperty(Group1.class)); - Assert.assertEquals("custom.abc", getSysProperty(Group2.class)); - Assert.assertEquals(SysGlobals.CURRENT_PREFIX() + ".nightly", getSysProperty(Nightly.class)); - Assert.assertEquals("nightly", getGroupName(Nightly.class)); - } - - @Test - public void groupsOnMethods() { - String group1Property = getSysProperty(Group1.class); - String group2Property = getSysProperty(Group2.class); - try { - afterClassRan = beforeClassRan = false; - checkTestsOutput(1, 0, 0, 1, Nested1.class); - Assert.assertFalse(afterClassRan); - Assert.assertFalse(beforeClassRan); - - afterClassRan = beforeClassRan = false; - System.setProperty(group1Property, "true"); - checkTestsOutput(1, 0, 0, 1, Nested1.class); - Assert.assertFalse(afterClassRan); - Assert.assertFalse(beforeClassRan); - - afterClassRan = beforeClassRan = false; - System.setProperty(group2Property, "true"); - checkTestsOutput(1, 0, 0, 0, Nested1.class); - Assert.assertTrue(afterClassRan); - Assert.assertTrue(beforeClassRan); - - afterClassRan = beforeClassRan = false; - System.setProperty(group1Property, "false"); - checkTestsOutput(1, 0, 0, 1, Nested1.class); - Assert.assertFalse(afterClassRan); - Assert.assertFalse(beforeClassRan); - } finally { - System.clearProperty(group1Property); - System.clearProperty(group2Property); - } - } - - @Test - public void groupsOnASubsetOfMethods() { - String group1Property = getSysProperty(Group1.class); - String group2Property = getSysProperty(Group2.class); - try { - afterClassRan = beforeClassRan = false; - checkTestsOutput(2, 0, 0, 1, Nested3.class); - Assert.assertTrue(afterClassRan); - Assert.assertTrue(beforeClassRan); - - afterClassRan = beforeClassRan = false; - System.setProperty(group1Property, "true"); - checkTestsOutput(2, 0, 0, 1, Nested3.class); - Assert.assertTrue(afterClassRan); - Assert.assertTrue(beforeClassRan); - - afterClassRan = beforeClassRan = false; - System.setProperty(group2Property, "true"); - checkTestsOutput(2, 0, 0, 0, Nested3.class); - Assert.assertTrue(afterClassRan); - Assert.assertTrue(beforeClassRan); - - afterClassRan = beforeClassRan = false; - System.setProperty(group1Property, "false"); - checkTestsOutput(2, 0, 0, 1, Nested3.class); - Assert.assertTrue(afterClassRan); - Assert.assertTrue(beforeClassRan); - } finally { - System.clearProperty(group1Property); - System.clearProperty(group2Property); - } - } - - @Test - public void groupsOnClass() { - String group1Property = getSysProperty(Group1.class); - String group2Property = getSysProperty(Group2.class); - try { - afterClassRan = beforeClassRan = false; - checkTestsOutput(1, 0, 0, 1, Nested2.class); - Assert.assertFalse(afterClassRan); - Assert.assertFalse(beforeClassRan); - - afterClassRan = beforeClassRan = false; - System.setProperty(group1Property, "true"); - checkTestsOutput(1, 0, 0, 1, Nested2.class); - Assert.assertFalse(afterClassRan); - Assert.assertFalse(beforeClassRan); - - afterClassRan = beforeClassRan = false; - System.setProperty(group2Property, "true"); - checkTestsOutput(1, 0, 0, 0, Nested2.class); - Assert.assertTrue(afterClassRan); - Assert.assertTrue(beforeClassRan); - - afterClassRan = beforeClassRan = false; - System.setProperty(group1Property, "false"); - checkTestsOutput(1, 0, 0, 1, Nested2.class); - Assert.assertFalse(afterClassRan); - Assert.assertFalse(beforeClassRan); - } finally { - System.clearProperty(group1Property); - System.clearProperty(group2Property); - } - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestGroupsOnOverrides.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestGroupsOnOverrides.java deleted file mode 100644 index 636330d9..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestTestGroupsOnOverrides.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import com.carrotsearch.randomizedtesting.annotations.TestGroup; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import java.lang.annotation.*; -import java.util.ArrayList; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - -public class TestTestGroupsOnOverrides extends WithNestedTestClass { - static List buf; - - public static class Super extends RandomizedTest { - @Before - public void assumeNested() { - assumeRunningNested(); - } - - @Test - public void method() { - buf.add("super:method"); - } - } - - @Before - public void clean() { - buf = new ArrayList<>(); - } - - public static class Ignored extends Super { - @Ignore - public void method() { - buf.add("sub:method"); - } - } - - @Test - public void testIgnored() { - runTests(Ignored.class); - assertThat(buf).isEmpty(); - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD, ElementType.TYPE}) - @Inherited - @TestGroup(enabled = false) - public @interface Disabled { - } - - public static class DisabledGroup extends Super { - @Disabled - public void method() { - buf.add("sub:method"); - } - } - - @Test - public void testDisabledGroup() { - runTests(DisabledGroup.class); - assertThat(buf).isEmpty(); - } - - public static class Normal extends Super { - public void method() { - buf.add("sub:method"); - } - } - - @Test - public void testNormal() { - runTests(Normal.class); - assertThat(buf).containsExactly("sub:method"); - } -} - diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestThreadNameContainsTestName.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestThreadNameContainsTestName.java deleted file mode 100644 index 209c35bd..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestThreadNameContainsTestName.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.annotations.Timeout; - -import static org.junit.Assert.*; - -/** - * Test {@link Test#expected()}. - */ -public class TestThreadNameContainsTestName extends RandomizedTest { - @Test - public void testMarkerABC() { - String tName = Thread.currentThread().getName(); - assertTrue(tName, tName.contains("testMarkerABC")); - } - - @Test - @Timeout(millis = 0) - public void testMarkerXYZ() { - String tName = Thread.currentThread().getName(); - assertTrue(tName, tName.contains("testMarkerXYZ")); - } - - @Test - @Timeout(millis = 1000) - public void testMarkerKJI() { - String tName = Thread.currentThread().getName(); - assertTrue(tName, tName.contains("testMarkerKJI")); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestUncaughtExceptionsDuplicated.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestUncaughtExceptionsDuplicated.java deleted file mode 100644 index a6a486ff..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestUncaughtExceptionsDuplicated.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.notification.Failure; -import org.junit.Assert; - -public class TestUncaughtExceptionsDuplicated extends WithNestedTestClass { - public static class Nested1 extends RandomizedTest { - @BeforeClass - public static void beforeClass() throws Exception { - assumeRunningNested(); - Thread t = new Thread() { - public void run() { - throw new RuntimeException("foobar"); - } - }; - t.start(); - t.join(); - } - - @Test - public void test() {} - } - - public static class Nested2 extends RandomizedTest { - @BeforeClass - public static void beforeClass() { - assumeRunningNested(); - } - - @Test - public void test1() throws Exception { - Thread t = new Thread() { - public void run() { - throw new RuntimeException("foobar1"); - } - }; - t.start(); - t.join(); - } - - @Test - public void test2() throws Exception { - Thread t = new Thread() { - public void run() { - throw new RuntimeException("foobar2"); - } - }; - t.start(); - t.join(); - } - - @Test - public void test3() throws Exception { - Thread t = new Thread() { - public void run() { - throw new RuntimeException("foobar3"); - } - }; - t.start(); - t.join(); - } - } - - public static class Nested3 extends RandomizedTest { - @Before - public void runBeforeTest() throws Exception { - assumeRunningNested(); - Thread t = new Thread() { - public void run() { - throw new RuntimeException("foobar"); - } - }; - t.start(); - t.join(); - } - - @Test - public void test1() throws Exception { - } - } - - @Test - public void testExceptionInBeforeClassFailsTheTest() { - FullResult r = checkTestsOutput(1, 0, 1, 0, Nested1.class); - Assert.assertTrue(r.getFailures().get(0).getTrace().contains("foobar")); - } - - @Test - public void testExceptionWithinTestFailsTheTest() { - FullResult r = checkTestsOutput(3, 0, 3, 0, Nested2.class); - - ArrayList foobars = new ArrayList(); - for (Failure f : r.getFailures()) { - Matcher m = Pattern.compile("foobar[0-9]+").matcher(f.getTrace()); - while (m.find()) { - foobars.add(m.group()); - } - } - - Collections.sort(foobars); - Assert.assertEquals("[foobar1, foobar2, foobar3]", - Arrays.toString(foobars.toArray())); - } - - @Test - public void testExceptionWithinBeforeFailsTheTest() { - FullResult r = checkTestsOutput(1, 0, 1, 0, Nested3.class); - Assert.assertTrue(r.getFailures().get(0).getTrace().contains("foobar")); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestValidation.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestValidation.java deleted file mode 100644 index f97bcb45..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/TestValidation.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.Arrays; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -public class TestValidation extends WithNestedTestClass { - public class SuiteClassNotStatic { - } - - static class SuiteClassNotPublic { - } - - public static class BeforeClassNotStatic { - @BeforeClass - public void beforeClass() { - } - } - - public static class BeforeClassWithArgs { - @BeforeClass - public static void beforeClass(int a) { - } - } - - public static class AfterClassNotStatic { - @AfterClass - public void afterClass() { - } - } - - public static class AfterClassWithArgs { - @AfterClass - public static void afterClass(int a) { - } - } - - public static class BeforeStatic { - @Before - public static void before() { - } - } - - public static class BeforeWithArgs { - @Before - public void before(int a) { - } - } - - public static class AfterStatic { - @After - public static void after() { - } - } - - public static class AfterWithArgs { - @After - public void after(int a) { - } - } - - @Test - public void checkBeforeClass() throws Exception { - for (Class c : Arrays.asList( - SuiteClassNotPublic.class, SuiteClassNotStatic.class, - BeforeClassNotStatic.class, BeforeClassWithArgs.class, - AfterClassNotStatic.class, AfterClassWithArgs.class, - BeforeStatic.class, BeforeWithArgs.class, - AfterStatic.class, AfterWithArgs.class)) { - try { - new RandomizedRunner(c); - Assert.fail("Expected validation failure on: " + c.getName()); - } catch (Exception e) { - // Ok, expected. - } - } - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/Utils.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/Utils.java deleted file mode 100644 index 0e96f4cb..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/Utils.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.util.Set; -import java.util.logging.Logger; - -import org.assertj.core.api.Assertions; -import org.junit.Assert; -import org.junit.runner.Result; -import org.junit.runner.notification.Failure; - -import com.carrotsearch.randomizedtesting.WithNestedTestClass.FullResult; - -public class Utils { - /** - * Assert a result has at least one failure with message. - */ - public static void assertFailureWithMessage(FullResult r, String message) { - for (Failure f : r.getFailures()) { - if (f.getTrace().contains(message)) { - return; - } - } - - StringBuilder b = new StringBuilder("No failure with message: '" + message + "' (" + - r.getFailures().size() + " failures):"); - for (Failure f : r.getFailures()) { - b.append("\n\t- ").append(f.getTrace()); - } - Logger.getLogger("").severe(b.toString()); - Assert.fail(b.toString()); - } - - public static void assertNoFailureWithMessage(Result r, String message) { - boolean hadMessage = false; - for (Failure f : r.getFailures()) { - if (f.getTrace().contains(message)) { - hadMessage = true; - } - } - - if (!hadMessage) return; - - StringBuilder b = new StringBuilder("Failure with message: '" + message + "' (" + - r.getFailures().size() + " failures):"); - for (Failure f : r.getFailures()) { - b.append("\n\t- ").append(f.getTrace()); - } - Logger.getLogger("").severe(b.toString()); - Assert.fail(b.toString()); - } - - /** - * Check that all thrown failures have been augmented and contain - * a synthetic seed frame. - */ - public static void assertFailuresContainSeeds(FullResult r) { - for (Failure f : r.getFailures()) { - String seed = RandomizedRunner.seedFromThrowable(f.getException()); - Assert.assertTrue("Not augmented: " + f.getTrace(), seed != null); - } - } - - /** - * Package scope test access to {@link RandomizedContext#getRunnerSeed()}. - */ - public static long getRunnerSeed() { - return RandomizedContext.current().getRunnerSeed(); - } - - /** - * Package scope test access to {@link Randomness#getSeed()}. - */ - public static long getSeed(Randomness randomness) { - return randomness.getSeed(); - } - - /** - * Assert no threads with the given substring are present. - */ - public static void assertNoLiveThreadsContaining(String substring) { - for (Thread t : getAllThreads()) { - if (t.isAlive()) { - Assertions.assertThat(t.getName()) - .as("Unexpected live thread").doesNotContain(substring); - } - } - } - - /** - * Expose to non-package scope. - */ - public static Set getAllThreads() { - return Threads.getAllThreads(); - } - - /** - * Expose to non-package scope. - */ - public static ThreadGroup getTopThreadGroup() { - return Threads.getTopThreadGroup(); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/WithNestedTestClass.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/WithNestedTestClass.java deleted file mode 100644 index 86ace102..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/WithNestedTestClass.java +++ /dev/null @@ -1,361 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import java.io.IOException; -import java.io.PrintStream; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Handler; -import java.util.logging.LogRecord; -import java.util.logging.Logger; -import java.util.logging.SimpleFormatter; - -import org.assertj.core.api.Assertions; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assume; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runner.JUnitCore; -import org.junit.runner.Result; -import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunListener; -import org.junit.runners.model.Statement; - -import com.carrotsearch.randomizedtesting.rules.StatementAdapter; -import com.carrotsearch.randomizedtesting.rules.SystemPropertiesInvariantRule; -import com.carrotsearch.randomizedtesting.rules.TestRuleAdapter; - -/** - * Utility class to surround nested {@link RandomizedRunner} test suites. - */ -public class WithNestedTestClass { - private static boolean runningNested; - - public enum Place { - CLASS_RULE, - BEFORE_CLASS, - CONSTRUCTOR, - TEST_RULE, - BEFORE, - TEST, - AFTER, - AFTER_CLASS, - } - - public static class ApplyAtPlace extends RandomizedTest { - public static Place place; - public static Runnable runnable; - - @ClassRule - public static TestRule classRule = new TestRuleAdapter() { - protected void before() throws Throwable { - ApplyAtPlace.apply(Place.CLASS_RULE); - } - }; - - @BeforeClass - public static void beforeClass() { apply(Place.BEFORE_CLASS); } - - public ApplyAtPlace() { apply(Place.CONSTRUCTOR); } - - @Rule - public TestRule testRule = new TestRuleAdapter() { - protected void before() throws Throwable { - ApplyAtPlace.apply(Place.TEST_RULE); - } - }; - - @Before - public void before() { apply(Place.BEFORE); } - - @Test - public void testMethod() { apply(Place.TEST); } - - @After - public void after() { apply(Place.AFTER); } - - @AfterClass - public static void afterClass() { apply(Place.AFTER_CLASS); } - - private static void apply(Place p) { - if (place == p) { - assumeRunningNested(); - runnable.run(); - } - } - } - - static { - TestRule dumpLoggerOutputOnFailure = new TestRule() { - @Override - public Statement apply(Statement base, final Description description) { - return new StatementAdapter(base) { - protected void afterAlways(java.util.List errors) throws Throwable { - if (!errors.isEmpty()) { - sysout.println("-- " + description); - sysout.println(loggingMessages); - } - } - }; - } - }; - - SystemPropertiesInvariantRule noLeftOverProperties = - new SystemPropertiesInvariantRule(new HashSet(Arrays.asList( - "user.timezone"))); - - ruleChain = RuleChain - .outerRule(noLeftOverProperties) - .around(dumpLoggerOutputOnFailure); - } - - @ClassRule - public final static TestRule ruleChain; - - /** For capturing sysout. */ - protected static PrintStream sysout; - - /** For capturing syserr. */ - protected static PrintStream syserr; - - /** - * Captured sysout/ syserr. - */ - private static StringWriter sw; - - /** - * Captured java logging messages. - */ - private static StringWriter loggingMessages; - - /** - * Master logger. - */ - private static Logger logger; - - /** - * Previous handlers attached to the master. - */ - private static Handler[] handlers; - - /** - * Zombie threads. - */ - private static List zombies = new ArrayList<>(); - - private static volatile Object zombieToken; - - @BeforeClass - public static final void setupNested() throws IOException { - runningNested = true; - zombieToken = new Object(); - - // capture sysout/ syserr. - sw = new StringWriter(); - sysout = System.out; - syserr = System.err; - System.setOut(new PrintStream(new TeeOutputStream(System.out, new WriterOutputStream(sw)))); - System.setErr(new PrintStream(new TeeOutputStream(System.err, new WriterOutputStream(sw)))); - - // Add custom logging handler because java logging keeps a reference to previous System.err. - loggingMessages = new StringWriter(); - logger = Logger.getLogger(""); - handlers = logger.getHandlers(); - for (Handler h : handlers) logger.removeHandler(h); - logger.addHandler(new Handler() { - final SimpleFormatter formatter = new SimpleFormatter(); - - @Override - public void publish(LogRecord record) { - loggingMessages.write(formatter.format(record) + "\n"); - } - - @Override - public void flush() {} - - @Override - public void close() throws SecurityException {} - }); - } - - @AfterClass - public static final void clearNested() throws Exception { - zombieToken = null; - runningNested = false; - ApplyAtPlace.runnable = null; - ApplyAtPlace.place = null; - - System.setOut(sysout); - System.setErr(syserr); - - for (Handler h : logger.getHandlers()) logger.removeHandler(h); - for (Handler h : handlers) logger.addHandler(h); - - for (Thread t : zombies) { - t.interrupt(); - } - for (Thread t : zombies) { - t.join(); - } - } - - @After - public void after() { - // Reset zombie thread marker. - RandomizedRunner.zombieMarker.set(false); - } - - @Before - public void before() { - sw.getBuffer().setLength(0); - loggingMessages.getBuffer().setLength(0); - } - - protected static String getSysouts() { - System.out.flush(); - System.err.flush(); - return sw.toString(); - } - - public static String getLoggingMessages() { - return loggingMessages.toString(); - } - - protected static boolean isRunningNested() { - return runningNested; - } - - protected static void assumeRunningNested() { - Assume.assumeTrue(runningNested); - } - - protected static Thread startZombieThread(String name) { - final CountDownLatch latch = new CountDownLatch(1); - Thread t = new Thread(name) { - private final Object token = zombieToken; - - public void run() { - latch.countDown(); - while (zombieToken == token) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // ignore. - } - } - } - }; - t.start(); - zombies.add(t); - try { - latch.await(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - return t; - } - - protected static Thread startThread(String name) { - final CountDownLatch latch = new CountDownLatch(1); - Thread t = new Thread(name) { - public void run() { - latch.countDown(); - sleepForever(); - } - - private void sleepForever() { - while (true) RandomizedTest.sleep(1000); - } - }; - t.start(); - try { - latch.await(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - return t; - } - - public static class FullResult { - private AtomicInteger assumptionIgnored = new AtomicInteger(); - private Result result; - - public int getRunCount() { - return result.getRunCount(); - } - - public int getIgnoreCount() { - return result.getIgnoreCount(); - } - - public int getFailureCount() { - return result.getFailureCount(); - } - - public int getAssumptionIgnored() { - return assumptionIgnored.get(); - } - - public List getFailures() { - return result.getFailures(); - } - - public boolean wasSuccessful() { - return result.wasSuccessful(); - } - } - - public static FullResult runTests(final Class... classes) { - try { - final FullResult fullResult = new FullResult(); - - // Run on a separate thread so that it appears as we're not running in an IDE. - Thread thread = new Thread() { - @Override - public void run() { - final JUnitCore core = new JUnitCore(); - core.addListener(new PrintEventListener(sysout)); - core.addListener(new RunListener() { - @Override - public void testAssumptionFailure(Failure failure) { - fullResult.assumptionIgnored.incrementAndGet(); - } - }); - - fullResult.result = core.run(classes); - } - }; - - thread.start(); - thread.join(); - return fullResult; - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - - public static FullResult checkTestsOutput(int run, int ignored, int failures, int assumptions, Class classes) { - FullResult result = runTests(classes); - if (result.getRunCount() != run || - result.getIgnoreCount() != ignored || - result.getFailureCount() != failures || - result.getAssumptionIgnored() != assumptions) { - Assertions.fail("Different result. [run,ign,fail,ass] Expected: " - + run + "," + ignored + "," + failures + "," + assumptions + - ", Actual: " + result.getRunCount() + "," + result.getIgnoreCount() + "," + result.getFailureCount() - + "," + result.getAssumptionIgnored()); - } - return result; - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestAnnotationInheritance.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestAnnotationInheritance.java deleted file mode 100644 index 60f4983b..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestAnnotationInheritance.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.carrotsearch.randomizedtesting.contracts; - -import java.util.ArrayList; -import java.util.List; - -import org.assertj.core.api.Assertions; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runner.JUnitCore; -import org.junit.runner.Request; -import org.junit.runners.model.Statement; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; - -/** - * Verify if annotations are inherited. - */ -public class TestAnnotationInheritance extends WithNestedTestClass { - final static List order = new ArrayList<>(); - - public static class Nested1 { - @Rule - public TestRule rules = new TestRule() { - @Override - public Statement apply(final Statement base, Description description) { - return new Statement() { - public void evaluate() throws Throwable { - order.add("rule-before"); - base.evaluate(); - order.add("rule-after"); - } - }; - } - }; - - @BeforeClass - public static void beforeClass() { - order.add("before-class"); - } - - @Before - public void before() { - order.add("before-test"); - } - - @Test - public void testMethod1() { - order.add("testMethod1"); - } - - @After - public void after() { - order.add("after-test"); - } - - @AfterClass - public static void afterClass() { - order.add("after-class"); - } - } - - public static class Nested2 extends Nested1 { - public static void beforeClass() { - order.add("shadowed-before-class"); - } - - @Override - public void before() { - order.add("inherited before-test"); - } - - @Override - public void after() { - order.add("inherited after-test"); - } - - @Override - public void testMethod1() { - order.add("inherited testMethod"); - } - - public static void afterClass() { - order.add("shadowed-after-class"); - } - } - - @Test - public void checkOldMethodRules() throws Exception { - assertSameExecution(Nested2.class); - } - - private void assertSameExecution(Class clazz) throws Exception { - order.clear(); - runTests(clazz); - List order1 = new ArrayList<>(order); - order.clear(); - - new JUnitCore().run(Request.runner(new RandomizedRunner(clazz))); - List order2 = new ArrayList<>(order); - order.clear(); - - String msg = "# JUnit order:\n" + order1 + "\n" + - "# RR order:\n" + order2; - Assertions.assertThat(order2).as(msg).isEqualTo(order1); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestAssumptionsAtClassLevel.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestAssumptionsAtClassLevel.java deleted file mode 100644 index 39df4443..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestAssumptionsAtClassLevel.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.carrotsearch.randomizedtesting.contracts; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assume; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; - -/** - * Check assumptions at suite level (in {@link BeforeClass}). - */ -public class TestAssumptionsAtClassLevel extends WithNestedTestClass { - static final List callOrder = new ArrayList(); - - /** - * Test superclass. - */ - public static class Super extends RandomizedTest { - @BeforeClass - public static void beforeClassSuper() { - assumeRunningNested(); - callOrder.add("beforeClassSuper"); - Assume.assumeTrue(false); - } - - @AfterClass - public static void afterClassSuper() { - callOrder.add("afterClassSuper"); - } - } - - /** - * Test subclass. - */ - public static class SubSub extends Super { - @BeforeClass - public static void beforeClass() { - callOrder.add("beforeClassSub"); - } - - @Before - public void beforeTestSub() { - callOrder.add("beforeTestSub"); - } - - @Test - public void testMethod() { - callOrder.add("testMethodSub"); - } - - @After - public void afterTestSub() { - callOrder.add("afterTestSub"); - } - - @AfterClass - public static void afterClass() { - callOrder.add("afterClassSub"); - } - } - - @Before - public void cleanup() { - callOrder.clear(); - } - - @Test - public void checkOrder() { - checkTestsOutput(0, 1, 0, 1, SubSub.class); - - List expected = Arrays.asList( - "beforeClassSuper", - "afterClassSub", - "afterClassSuper" - ); - assertEquals(expected, callOrder); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestBeforeAfterMethodOrder.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestBeforeAfterMethodOrder.java deleted file mode 100644 index 2caf8c20..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestBeforeAfterMethodOrder.java +++ /dev/null @@ -1,232 +0,0 @@ -package com.carrotsearch.randomizedtesting.contracts; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.MethodRule; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runner.JUnitCore; -import org.junit.runners.model.FrameworkMethod; -import org.junit.runners.model.Statement; - -import com.carrotsearch.randomizedtesting.RandomizedContext; -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.Seed; - -/** - * Hooks ordering with respect to class hierarchies. - */ -@SuppressWarnings("deprecation") -public class TestBeforeAfterMethodOrder extends WithNestedTestClass { - static final List callOrder = new ArrayList(); - - public static class AppendMethodRule implements MethodRule { - private String text; - - public AppendMethodRule(String text) { - this.text = text; - } - - @Override - public Statement apply(final Statement base, FrameworkMethod method, Object target) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - callOrder.add(text + "-before"); - base.evaluate(); - callOrder.add(text + "-after"); - } - }; - } - } - - public static class AppendRule implements TestRule { - private String text; - - public AppendRule(String text) { - this.text = text; - } - - @Override - public Statement apply(final Statement base, Description description) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - callOrder.add(text + "-before"); - base.evaluate(); - callOrder.add(text + "-after"); - } - }; - } - } - - /** - * Test superclass. - */ - public static class Super { - @BeforeClass - public static void beforeClassSuper() { - callOrder.add("beforeClassSuper"); - } - - @Rule - public TestRule superRule = RuleChain - .outerRule(new AppendRule("superOuterTestRule")) - .around(new AppendRule("superMiddleTestRule")) - .around(new AppendRule("superInnerTestRule")); - - @Rule - public MethodRule superMethodRule = new AppendMethodRule("superMethodRule"); - - @Before - public final void beforeTest() { - callOrder.add("beforeTestSuper"); - } - - protected void testMethod() { - throw new RuntimeException("Should be overridden and public."); - } - - @After - public final void afterTest() { - callOrder.add("afterTestSuper"); - } - - @AfterClass - public static void afterClassSuper() { - callOrder.add("afterClassSuper"); - } - } - - /** - * Test subclass. - */ - public static class SubSub extends Super { - @Rule - public TestRule rule = RuleChain - .outerRule(new AppendRule(" subOuterTestRule")) - .around(new AppendRule(" subMiddleTestRule")) - .around(new AppendRule(" subInnerTestRule")); - - @Rule - public MethodRule methodRule = new AppendMethodRule(" subMethodRule"); - - @BeforeClass - public static void beforeClass() { - callOrder.add(" beforeClassSub"); - } - - @Before - public void beforeTestSub() { - callOrder.add(" beforeTestSub"); - } - - @Test - public void testMethod() { - callOrder.add(" testMethodSub"); - } - - @After - public void afterTestSub() { - callOrder.add(" afterTestSub"); - } - - @AfterClass - public static void afterClass() { - callOrder.add(" afterClassSub"); - } - } - - /** - * Test subclass. - */ - @Seed("deadbeef") - public static class SubSubFixedSeed extends Super { - @BeforeClass - public static void beforeClass() { - callOrder.add("beforeClassSubFS"); - } - - @Before - public void beforeTestSub() { - assumeRunningNested(); - callOrder.add("beforeTestSubFS"); - } - - @Test @Repeat(iterations = 10) - public void testMethod1() { - callOrder.add("testMethodSubFS1 " - + RandomizedContext.current().getRandom().nextInt()); - } - - @Test @Repeat(iterations = 10) - public void testMethod2() { - callOrder.add("testMethodSubFS2 " - + RandomizedContext.current().getRandom().nextInt()); - } - - @After - public void afterTestSub() { - callOrder.add("afterTestSubFS"); - } - - @AfterClass - public static void afterClass() { - callOrder.add("afterClassSubFS"); - } - } - - @Before - public void cleanup() { - callOrder.clear(); - } - - @Test - public void checkOrder() throws Exception { - // Normal JUnit. - checkTestsOutput(1, 0, 0, 0, SubSub.class); - ArrayList junitOrder = new ArrayList(callOrder); - - callOrder.clear(); - new JUnitCore().run(new RandomizedRunner(SubSub.class)); - - if (!callOrder.equals(junitOrder)) { - final int i = junitOrder.size(); - final int j = callOrder.size(); - - System.out.println(String.format(Locale.ROOT, - "%-30s | %-30s", "JUnit4", "RR")); - for (int k = 0; k < Math.max(i, j); k++) { - System.out.println(String.format(Locale.ROOT, - "%-30s | %-30s", - k < i ? junitOrder.get(k) : "--", - k < j ? callOrder.get(k) : "--")); - } - - Assert.fail("JUnit4 and RandomizedRunner differed."); - } - } - - @Test - public void checkOrderFixedSeed() throws Exception { - new JUnitCore().run(new RandomizedRunner(SubSubFixedSeed.class)); - ArrayList order = new ArrayList(callOrder); - callOrder.clear(); - new JUnitCore().run(new RandomizedRunner(SubSubFixedSeed.class)); - assertEquals(order, callOrder); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestClassLevelIgnore.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestClassLevelIgnore.java deleted file mode 100644 index f830bb6a..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestClassLevelIgnore.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.carrotsearch.randomizedtesting.contracts; - -import org.junit.Ignore; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; - -/** - * Class-level {@link Ignore}. - */ -public class TestClassLevelIgnore extends WithNestedTestClass { - @Ignore - public static class Nested extends RandomizedTest { - @Test - public void ignored() { - } - } - - @Test - public void allIgnored() { - checkTestsOutput(0, 1, 0, 0, Nested.class); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestClassRules.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestClassRules.java deleted file mode 100644 index eeef5373..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestClassRules.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.carrotsearch.randomizedtesting.contracts; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runner.JUnitCore; -import org.junit.runner.Request; -import org.junit.runners.model.Statement; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; - -/** - * {@link ClassRule} support. - */ -public class TestClassRules extends WithNestedTestClass { - final static List order = new ArrayList<>(); - - public static class ClassRuleSupport { - @ClassRule - public static TestRule rules = RuleChain.outerRule(new TestRule() { - @Override - public Statement apply(final Statement base, Description description) { - return new Statement() { - public void evaluate() throws Throwable { - order.add("rule-before"); - base.evaluate(); - order.add("rule-after"); - } - }; - } - }); - - @BeforeClass - public static void beforeClass() { - order.add("before-class"); - } - - @AfterClass - public static void afterClass() { - order.add("after-class"); - } - - @Test - public void passing() { - order.add("passing"); - } - } - - @Test - public void checkOldMethodRules() throws Exception { - assertSameExecution(ClassRuleSupport.class); - } - - private void assertSameExecution(Class clazz) throws Exception { - order.clear(); - runTests(clazz); - List order1 = new ArrayList<>(order); - order.clear(); - - new JUnitCore().run(Request.runner(new RandomizedRunner(clazz))); - List order2 = new ArrayList<>(order); - order.clear(); - - Assert.assertEquals(order1, order2); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestMethodFilteringInIDEs.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestMethodFilteringInIDEs.java deleted file mode 100644 index fcba3d12..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/contracts/TestMethodFilteringInIDEs.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.carrotsearch.randomizedtesting.contracts; - -import org.junit.Assume; -import org.junit.Ignore; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.Seed; - -@Repeat(iterations = 2, useConstantSeed = false) -@Seed("deadbeef") -public class TestMethodFilteringInIDEs extends RandomizedTest { - @Test - public void testExecuted1() { - } - - @Test - public void testExecuted2() { - } - - @Test - public void testIgnoredByAssumption() { - Assume.assumeTrue(false); - } - - @Ignore - @Test - public void testIgnoredByAnnotation() {} -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/StringGeneratorTestBase.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/StringGeneratorTestBase.java deleted file mode 100644 index 4704de3b..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/StringGeneratorTestBase.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Repeat; - -import static org.junit.Assert.*; - -/** - * Base class for testing {@link StringGenerator}s. - */ -public abstract class StringGeneratorTestBase extends RandomizedTest { - protected final StringGenerator generator; - - protected StringGeneratorTestBase(StringGenerator generator) { - this.generator = generator; - } - - @Test @Repeat(iterations = 10) - public void checkFixedCodePointLength() { - int codepoints = iterationFix(randomIntBetween(1, 100)); - String s = generator.ofCodePointsLength(getRandom(), codepoints, codepoints); - assertEquals(s, codepoints, s.codePointCount(0, s.length())); - } - - @Test @Repeat(iterations = 10) - public void checkRandomCodePointLength() { - int from = iterationFix(randomIntBetween(1, 100)); - int to = from + randomIntBetween(0, 100); - - String s = generator.ofCodePointsLength(getRandom(), from, to); - int codepoints = s.codePointCount(0, s.length()); - assertTrue(codepoints + " not within " + - from + "-" + to, from <= codepoints && codepoints <= to); - } - - @Test @Repeat(iterations = 10) - public void checkFixedCodeUnitLength() { - int codeunits = iterationFix(randomIntBetween(1, 100)); - String s = generator.ofCodeUnitsLength(getRandom(), codeunits, codeunits); - assertEquals(s, codeunits, s.length()); - assertEquals(s, codeunits, s.toCharArray().length); - } - - @Test @Repeat(iterations = 10) - public void checkRandomCodeUnitLength() { - int from = iterationFix(randomIntBetween(1, 100)); - int to = from + randomIntBetween(0, 100); - - String s = generator.ofCodeUnitsLength(getRandom(), from, to); - int codeunits = s.length(); - assertTrue(codeunits + " not within " + - from + "-" + to, from <= codeunits && codeunits <= to); - } - - @Test - public void checkZeroLength() { - assertEquals("", generator.ofCodePointsLength(getRandom(), 0, 0)); - assertEquals("", generator.ofCodeUnitsLength(getRandom(), 0, 0)); - } - - /** - * Correct the count if a given generator doesn't support all possible values (in tests). - */ - protected int iterationFix(int i) { - return i; - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestCodepointSetGenerator.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestCodepointSetGenerator.java deleted file mode 100644 index 30e4c94c..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestCodepointSetGenerator.java +++ /dev/null @@ -1,115 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -import java.util.HashSet; -import java.util.Random; -import java.util.Set; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -import com.carrotsearch.randomizedtesting.RandomizedTest; - -import static org.junit.Assert.*; - -@RunWith(Suite.class) -@SuiteClasses({ - TestCodepointSetGenerator.CodepointSetOnChars.class, - TestCodepointSetGenerator.CodepointSetOnCodePoints.class, - TestCodepointSetGenerator.CodepointSetOnSurrogatesOnly.class -}) -public class TestCodepointSetGenerator extends RandomizedTest { - private final static int [] codepoints = { - 'a', 'b', 'c', 'd', - 0xd7ff, - 0xffff, - 0x10000, - 0x1D11E, - 0x10FFFD, - }; - - private final static int [] surrogates = { - 0x10000, - 0x1D11E, - 0x10FFFD, - }; - - private final static String withSurrogates = new String(codepoints, 0, codepoints.length); - - public static class CodepointSetOnChars extends StringGeneratorTestBase { - public CodepointSetOnChars() { - super(new CodepointSetGenerator(new char[] { - 'a', 'b', 'c', 'd', - 0x100, - 0xd7ff, - 0xffff - })); - } - - @Test - public void testAllCharactersUsed() { - char [] domain = "abcdefABCDEF".toCharArray(); - Set chars = new HashSet(); - for (char chr : domain) { - chars.add(chr); - } - - CodepointSetGenerator gen = new CodepointSetGenerator(domain); - Random r = new Random(randomLong()); - for (int i = 0; i < 1000000 && !chars.isEmpty(); i++) { - for (char ch : gen.ofCodeUnitsLength(r, 100, 100).toCharArray()) { - chars.remove(ch); - } - } - - assertTrue(chars.isEmpty()); - } - - @Test(expected = IllegalArgumentException.class) - public void testSurrogatesInConstructor() { - new CodepointSetGenerator(withSurrogates.toCharArray()); - } - } - - public static class CodepointSetOnCodePoints extends StringGeneratorTestBase { - public CodepointSetOnCodePoints() { - super(new CodepointSetGenerator(withSurrogates)); - } - - @Test - public void testAllCharactersUsed() { - char [] domain = "abcdefABCDEF".toCharArray(); - Set chars = new HashSet(); - for (char chr : domain) { - chars.add(chr); - } - - CodepointSetGenerator gen = new CodepointSetGenerator(new String(domain)); - Random r = new Random(randomLong()); - for (int i = 0; i < 1000000 && !chars.isEmpty(); i++) { - for (char ch : gen.ofCodeUnitsLength(r, 100, 100).toCharArray()) { - chars.remove(ch); - } - } - - assertTrue(chars.isEmpty()); - } - } - - public static class CodepointSetOnSurrogatesOnly extends StringGeneratorTestBase { - public CodepointSetOnSurrogatesOnly() { - super(new CodepointSetGenerator(new String(surrogates, 0, surrogates.length))); - } - - @Test(expected = IllegalArgumentException.class) - public void testOddCodePoints() { - generator.ofCodeUnitsLength(getRandom(), 3, 3); - } - - @Override - protected int iterationFix(int i) { - return i & ~1; // Even only. - } - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestRandomBytes.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestRandomBytes.java deleted file mode 100644 index 81f47a23..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestRandomBytes.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -import org.assertj.core.api.Assertions; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.annotations.Repeat; - -@Repeat(iterations = 100) -public class TestRandomBytes extends RandomizedTest { - @Test - public void testRandomBytes() { - int len = randomIntBetween(0, 100); - Assertions.assertThat(randomBytesOfLength(len)).hasSize(len); - } - - @Test - public void testRandomBytesOfLength() { - int min = randomIntBetween(0, 100); - int max = min + randomIntBetween(0, 10); - - byte[] bytes = randomBytesOfLength(min, max); - Assertions.assertThat(bytes.length >= min).isTrue(); - Assertions.assertThat(bytes.length <= max).isTrue(); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestRandomPicks.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestRandomPicks.java deleted file mode 100644 index 02238087..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestRandomPicks.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; - -import static org.junit.Assert.*; - -public class TestRandomPicks extends RandomizedTest { - @Test(expected = IllegalArgumentException.class) - public void testRandomFromEmptyCollection() { - RandomPicks.randomFrom(getRandom(), new HashSet()); - } - - @Test - public void testRandomFromCollection() { - Object t = new Object(); - Object r = RandomPicks.randomFrom(getRandom(), new HashSet(Arrays.asList(t))); - assertSame(r, t); - } - - @Test(expected = IllegalArgumentException.class) - public void testRandomFromList() { - RandomPicks.randomFrom(getRandom(), new ArrayList()); - } - - @Test(expected = IllegalArgumentException.class) - public void testRandomFromArray() { - RandomPicks.randomFrom(getRandom(), new Object[] {}); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestRealisticUnicodeGenerator.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestRealisticUnicodeGenerator.java deleted file mode 100644 index 2c6b6430..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestRealisticUnicodeGenerator.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -public class TestRealisticUnicodeGenerator extends StringGeneratorTestBase { - public TestRealisticUnicodeGenerator() { - super(new UnicodeGenerator()); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestUnicodeGenerator.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestUnicodeGenerator.java deleted file mode 100644 index b14ffd99..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/generators/TestUnicodeGenerator.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.carrotsearch.randomizedtesting.generators; - -public class TestUnicodeGenerator extends StringGeneratorTestBase { - public TestUnicodeGenerator() { - super(new UnicodeGenerator()); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/inheritance/JUnitAnnotationPropagation.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/inheritance/JUnitAnnotationPropagation.java deleted file mode 100644 index 32c93481..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/inheritance/JUnitAnnotationPropagation.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.carrotsearch.randomizedtesting.inheritance; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.assertj.core.api.Assertions; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runner.JUnitCore; -import org.junit.runner.Request; -import org.junit.runners.model.Statement; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; - -public class JUnitAnnotationPropagation { - final static List order = new ArrayList<>(); - - public static class Super { - @Rule - public TestRule rules = new TestRule() { - @Override - public Statement apply(final Statement base, Description description) { - return new Statement() { - public void evaluate() throws Throwable { - order.add("rule-before"); - base.evaluate(); - order.add("rule-after"); - } - }; - } - }; - - @BeforeClass public static void beforeClass1() { order.add("super.beforeclass1"); } - public static void beforeClass2() { order.add("super.beforeclass2"); } - @BeforeClass public static void beforeClass3() { order.add("super.beforeclass3"); } - - @Before public void before1() { order.add("super.before1"); } - public void before2() { order.add("super.before2"); } - @Before public void before3() { order.add("super.before3"); } - - @Test public void testMethod1() { order.add("super.testMethod1"); } - public void testMethod2() { order.add("super.testMethod2"); } - @Test public void testMethod3() { order.add("super.testMethod3"); } - - // Awkward cases of annotations and virtual methods. - @Ignore public void testMethod4() { order.add("super.testMethod4"); } - @Test public void testMethod5() { order.add("super.testMethod5"); } - } - - public static class Sub extends Super { - public static void beforeClass1() { order.add("sub.beforeclass1"); } - @BeforeClass public static void beforeClass2() { order.add("sub.beforeclass2"); } - @BeforeClass public static void beforeClass3() { order.add("sub.beforeclass3"); } - - public void before1() { order.add("sub.before1"); } - @Before public void before2() { order.add("sub.before2"); } - @Before public void before3() { order.add("sub.before3"); } - - public void testMethod1() { order.add("sub.testMethod1"); } - @Test public void testMethod2() { order.add("sub.testMethod2"); } - @Test public void testMethod3() { order.add("sub.testMethod3"); } - - @Test public void testMethod4() { order.add("sub.testMethod4"); } - @Ignore public void testMethod5() { order.add("sub.testMethod5"); } - } - - @Test - public void checkOldMethodRules() throws Exception { - assertSameExecution(Sub.class); - } - - private void assertSameExecution(Class clazz) throws Exception { - order.clear(); - WithNestedTestClass.runTests(clazz); - List order1 = new ArrayList<>(order); - order.clear(); - - new JUnitCore().run(Request.runner(new RandomizedRunner(clazz))); - List order2 = new ArrayList<>(order); - order.clear(); - - String msg = "# JUnit order:\n" + order1 + "\n" + - "# RR order:\n" + order2; - - // Don't care about relative ordering of hook methods. - Assertions.assertThat(noNumbers(order2)).as(msg).isEqualTo(noNumbers(order1)); - - // But do care that all methods show up. - Collections.sort(order1); - Collections.sort(order2); - Assertions.assertThat(order2).as(msg).isEqualTo(order1); - } - - private List noNumbers(List in) { - List out = new ArrayList<>(); - for (String s : in) { - out.add(s.replaceAll("[0-9]+$", "")); - } - return out; - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/inheritance/PrivateHooksPropagation.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/inheritance/PrivateHooksPropagation.java deleted file mode 100644 index ecc032f0..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/inheritance/PrivateHooksPropagation.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.carrotsearch.randomizedtesting.inheritance; - -import java.util.ArrayList; -import java.util.List; - -import org.assertj.core.api.Assertions; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.JUnitCore; -import org.junit.runner.Request; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.RandomizedTest; - -public class PrivateHooksPropagation { - final static List order = new ArrayList<>(); - - public static class Super extends RandomizedTest { - @BeforeClass private static void beforeClass1() { order.add("super.beforeclass1"); } - @BeforeClass protected static void beforeClass2() { order.add("super.beforeclass2"); } - - @Before private void before1() { order.add("super.before1"); } - @Before protected void before2() { order.add("super.before2"); } - - @Test public void testMethod1() { order.add("super.testMethod1"); } - } - - public static class Sub extends Super { - @BeforeClass private static void beforeClass1() { order.add("sub.beforeclass1"); } - @BeforeClass protected static void beforeClass2() { order.add("sub.beforeclass2"); } - - @Before private void before1() { order.add("sub.before1"); } - @Before protected void before2() { order.add("sub.before2"); } - } - - @Test - public void checkOldMethodRules() throws Exception { - assertSameExecution(Sub.class); - } - - private void assertSameExecution(Class clazz) throws Exception { - new JUnitCore().run(Request.runner(new RandomizedRunner(clazz))); - List order1 = new ArrayList<>(order); - order.clear(); - - String msg = "# RR order:\n" + order1; - Assertions.assertThat(order1).as(msg).containsOnly( - "super.beforeclass1", - "sub.beforeclass1", - "sub.beforeclass2", - "super.before1", - "sub.before1", - "sub.before2", - "super.testMethod1"); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/rules/TestNoClassHooksShadowingRule.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/rules/TestNoClassHooksShadowingRule.java deleted file mode 100644 index d9f9c738..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/rules/TestNoClassHooksShadowingRule.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.carrotsearch.randomizedtesting.rules; - -import org.assertj.core.api.Assertions; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; - -public class TestNoClassHooksShadowingRule extends WithNestedTestClass { - public static class Super extends RandomizedTest { - private static TestRule assumeNotNestedRule = new TestRule() { - public Statement apply(final Statement base, Description description) { - return new Statement() { - public void evaluate() throws Throwable { - assumeRunningNested(); - base.evaluate(); - } - }; - } - }; - - @ClassRule - public static TestRule classRules = - RuleChain - .outerRule(assumeNotNestedRule) - .around(new NoClassHooksShadowingRule()); - - @BeforeClass - public static void before() {} - - @BeforeClass - private static void privateBefore() {} - - @Test - public void testEmpty() {} - } - - public static class Sub1 extends Super { - public static void before() {} - } - - public static class Sub2 extends Super { - @BeforeClass - public static void before() {} - } - - public static class Sub3 extends Super { - @BeforeClass - private static void privateBefore() {} - } - - @Test - public void testShadowingNoAnnotation() { - FullResult runClasses = runTests(Sub1.class); - Assertions.assertThat(runClasses.getFailures()).isNotEmpty(); - Assertions.assertThat(runClasses.getFailures().get(0).getTrace()) - .contains("shadow or override each other"); - } - - @Test - public void testShadowingWithAnnotation() { - FullResult runClasses = runTests(Sub2.class); - Assertions.assertThat(runClasses.getFailures()).isNotEmpty(); - Assertions.assertThat(runClasses.getFailures().get(0).getTrace()) - .contains("shadow or override each other"); - } - - @Test - public void testIndependentChains() { - FullResult runClasses = runTests(Sub3.class); - Assertions.assertThat(runClasses.getFailures()).isEmpty(); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/rules/TestNoInstanceHooksOverridesRule.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/rules/TestNoInstanceHooksOverridesRule.java deleted file mode 100644 index 01478f99..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/rules/TestNoInstanceHooksOverridesRule.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.carrotsearch.randomizedtesting.rules; - -import java.lang.reflect.Method; - -import org.assertj.core.api.Assertions; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; - -public class TestNoInstanceHooksOverridesRule extends WithNestedTestClass { - public static class Super extends RandomizedTest { - private static TestRule assumeNotNestedRule = new TestRule() { - public Statement apply(final Statement base, Description description) { - return new Statement() { - public void evaluate() throws Throwable { - assumeRunningNested(); - base.evaluate(); - } - }; - } - }; - - @ClassRule - public static TestRule classRules = - RuleChain - .outerRule(assumeNotNestedRule) - .around(new NoInstanceHooksOverridesRule() { - @Override - protected boolean verify(Method key) { - return !key.getName().equals("setup"); - } - }); - - @Before - public void before() {} - - @Before - private void privateBefore() {} - - @Before - public void setup() {} - - @Test - public void testEmpty() {} - } - - public static class Sub1 extends Super { - public void before() {} - } - - public static class Sub2 extends Super { - @Before - public void before() {} - } - - public static class Sub3 extends Super { - @Before - private void privateBefore() {} - } - - public static class Sub4 extends Super { - @Override - public void setup() {} - } - - @Test - public void testOverrideNoAnnotation() { - - FullResult runClasses = runTests(Sub1.class); - Assertions.assertThat(runClasses.getFailures()).isNotEmpty(); - Assertions.assertThat(runClasses.getFailures().get(0).getTrace()) - .contains("shadow or override each other"); - } - - @Test - public void testOverrideWithAnnotation() { - FullResult runClasses = runTests(Sub2.class); - Assertions.assertThat(runClasses.getFailures()).isNotEmpty(); - Assertions.assertThat(runClasses.getFailures().get(0).getTrace()) - .contains("shadow or override each other"); - } - - @Test - public void testIndependentChains() { - FullResult runClasses = runTests(Sub3.class); - Assertions.assertThat(runClasses.getFailures()).isEmpty(); - } - - @Test - public void testFiltering() { - FullResult runClasses = runTests(Sub4.class); - Assertions.assertThat(runClasses.getFailures()).isEmpty(); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/rules/TestStaticFieldsInvariantRule.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/rules/TestStaticFieldsInvariantRule.java deleted file mode 100644 index f15c0b5c..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/rules/TestStaticFieldsInvariantRule.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.carrotsearch.randomizedtesting.rules; - -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.Map; - -import org.assertj.core.api.Assertions; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; - -public class TestStaticFieldsInvariantRule extends WithNestedTestClass { - static int LEAK_THRESHOLD = 5 * 1024 * 1024; - - @ThreadLeakScope(Scope.SUITE) - public static class Base extends RandomizedTest { - private static TestRule assumeNotNestedRule = new TestRule() { - public Statement apply(final Statement base, Description description) { - return new Statement() { - public void evaluate() throws Throwable { - assumeRunningNested(); - base.evaluate(); - } - }; - } - }; - - @ClassRule - public static TestRule classRules = - RuleChain - .outerRule(assumeNotNestedRule) - .around(new StaticFieldsInvariantRule(LEAK_THRESHOLD, true)); - - @Test - public void testEmpty() {} - } - - public static class Smaller extends Base { - static byte [] field0; - - @BeforeClass - private static void setup() { - field0 = new byte [LEAK_THRESHOLD / 2]; - } - } - - public static class Exceeding extends Smaller { - static byte [] field1; - static byte [] field2; - static int [] field3; - static long field4; - final static long [] field5 = new long [1024]; - - @BeforeClass - private static void setup() { - field1 = new byte [LEAK_THRESHOLD / 2]; - field2 = new byte [100]; - field3 = new int [100]; - } - } - - public static class MultipleReferences extends Base { - static Object ref1, ref2, ref3, - ref4, ref5, ref6; - - static Object ref7 = null; - - static { - Map map = new HashMap(); - map.put("key", new byte [1024 * 1024 * 2]); - ref1 = ref2 = ref3 = ref4 = ref5 = ref6 = map; - } - } - - @Test - public void testReferencesCountedMultipleTimes() { - FullResult runClasses = runTests(MultipleReferences.class); - Assertions.assertThat(runClasses.getFailures()).isEmpty(); - } - - @Test - public void testPassingUnderThreshold() { - FullResult runClasses = runTests(Smaller.class); - Assertions.assertThat(runClasses.getFailures()).isEmpty(); - } - - @Test - public void testFailingAboveThreshold() { - FullResult runClasses = runTests(Exceeding.class); - Assertions.assertThat(runClasses.getFailures()).hasSize(1); - - Assertions.assertThat(runClasses.getFailures().get(0).getTrace()) - .contains(".field0") - .contains(".field1") - .contains(".field2") - .contains(".field3") - .doesNotContain(".field5"); - } - - static class Holder { - private final Path path; - - Holder() { - this.path = Paths.get("."); - final String name = this.path.getClass().getName(); - RandomizedTest.assumeTrue(Path.class.getName() + " is not implemented by internal class in this JVM: " + name, - name.startsWith("sun.") || name.startsWith("jdk.")); - } - } - - public static class FailsJava9 extends Base { - static Holder field0; - - @BeforeClass - private static void setup() throws Exception { - field0 = new Holder(); - } - } - - @Test @org.junit.Ignore - public void testJava9Jigsaw() { - // check if we have Java 9 module system: - try { - Class.class.getMethod("getModule"); - } catch (Exception e) { - RandomizedTest.assumeTrue("This test requires Java 9 module system (Jigsaw)", false); - } - - FullResult runClasses = runTests(FailsJava9.class); - Assertions.assertThat(runClasses.getFailures()).hasSize(1); - - Assertions.assertThat(runClasses.getFailures().get(0).getTrace()) - .contains("sizes cannot be measured due to security restrictions or Java 9") - .contains(".field0"); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/rules/TestSystemPropertiesInvariantRule.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/rules/TestSystemPropertiesInvariantRule.java deleted file mode 100644 index 3819a189..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/rules/TestSystemPropertiesInvariantRule.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.carrotsearch.randomizedtesting.rules; - -import java.util.Properties; - -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.*; -import org.junit.runner.notification.Failure; -import org.junit.runners.model.Statement; - -import com.carrotsearch.randomizedtesting.WithNestedTestClass; - -public class TestSystemPropertiesInvariantRule extends WithNestedTestClass { - public static final String PROP_KEY1 = "new-property-1"; - public static final String VALUE1 = "new-value-1"; - - public static class Base { - private static TestRule assumeNotNestedRule = new TestRule() { - public Statement apply(final Statement base, Description description) { - return new Statement() { - public void evaluate() throws Throwable { - assumeRunningNested(); - base.evaluate(); - } - }; - } - }; - - @ClassRule - public static TestRule classRules = - RuleChain.outerRule(assumeNotNestedRule).around(new SystemPropertiesInvariantRule()); - - @Rule - public TestRule testRules = - RuleChain.outerRule(new SystemPropertiesInvariantRule()); - - @Test - public void testEmpty() {} - } - - public static class InBeforeClass extends Base { - @BeforeClass - public static void beforeClass() { - System.setProperty(PROP_KEY1, VALUE1); - } - } - - public static class InAfterClass extends Base { - @AfterClass - public static void afterClass() { - System.setProperty(PROP_KEY1, VALUE1); - } - } - - public static class InTestMethod extends Base { - @Test - public void testMethod1() { - if (System.getProperty(PROP_KEY1) != null) { - throw new RuntimeException("Shouldn't be here."); - } - System.setProperty(PROP_KEY1, VALUE1); - } - - @Test - public void testMethod2() { - testMethod1(); - } - } - - public static class NonStringProperties extends Base { - @Test - public void testMethod1() { - if (System.getProperties().get(PROP_KEY1) != null) { - throw new RuntimeException("Will pass."); - } - - Properties properties = System.getProperties(); - properties.put(PROP_KEY1, new Object()); - Assert.assertTrue(System.getProperties().get(PROP_KEY1) != null); - } - - @Test - public void testMethod2() { - testMethod1(); - } - - @AfterClass - public static void cleanup() { - System.getProperties().remove(PROP_KEY1); - } - } - - @Test - public void testRuleInvariantBeforeClass() { - FullResult runClasses = runTests(InBeforeClass.class); - Assert.assertEquals(1, runClasses.getFailureCount()); - Assert.assertTrue(runClasses.getFailures().get(0).getMessage() - .contains(PROP_KEY1)); - Assert.assertNull(System.getProperty(PROP_KEY1)); - } - - @Test - public void testRuleInvariantAfterClass() { - FullResult runClasses = runTests(InAfterClass.class); - Assert.assertEquals(1, runClasses.getFailureCount()); - Assert.assertTrue(runClasses.getFailures().get(0).getMessage() - .contains(PROP_KEY1)); - Assert.assertNull(System.getProperty(PROP_KEY1)); - } - - @Test - public void testRuleInvariantInTestMethod() { - FullResult runClasses = runTests(InTestMethod.class); - Assert.assertEquals(2, runClasses.getFailureCount()); - for (Failure f : runClasses.getFailures()) { - Assert.assertTrue(f.getMessage().contains(PROP_KEY1)); - } - Assert.assertNull(System.getProperty(PROP_KEY1)); - } - - @Test - public void testNonStringProperties() { - FullResult runClasses = runTests(NonStringProperties.class); - Assert.assertEquals(1, runClasses.getFailureCount()); - Assert.assertTrue(runClasses.getFailures().get(0).getMessage().contains("Will pass")); - Assert.assertEquals(3, runClasses.getRunCount()); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/snippets/TheGoodBadAndUglySnippet.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/snippets/TheGoodBadAndUglySnippet.java deleted file mode 100644 index 3c2471ec..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/snippets/TheGoodBadAndUglySnippet.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.carrotsearch.randomizedtesting.snippets; - -import org.junit.BeforeClass; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction.Action; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; - -import static org.junit.Assert.*; - -public class TheGoodBadAndUglySnippet extends WithNestedTestClass { - /** - * This is cheating so that snippets appear to be extending RandomizedTest - * but at the same time snippety tests won't execute in Eclipse. - */ - public static class RandomizedTest extends com.carrotsearch.randomizedtesting.RandomizedTest { - @BeforeClass - public static void runAsTest() { - assumeRunningNested(); - } - } - - // [[[start:goodbadugly]]] - @ThreadLeakScope(Scope.TEST) - @ThreadLeakAction({Action.WARN, Action.INTERRUPT}) - @ThreadLeakLingering(linger = 1000) - public static class TheGoodBadAndUgly extends RandomizedTest { - @Test - public void good() { - // I do nothing and I'm good. - } - - @Test - @Repeat(iterations = 10) - public void bad() { - // I fail randomly, about 20% of the time. - assertFalse(randomIntBetween(1, 100) <= 20); - } - - @Test - public void ugly() { - // I start and abandon a thread which falls - // outside the test's scope. The test will fail. - new Thread() { - public void run() { - RandomizedTest.sleep(5000); - } - }.start(); - } - } - // [[[end:goodbadugly]]] -} \ No newline at end of file diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test001TimeoutSuite.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test001TimeoutSuite.java deleted file mode 100644 index 9e2c9a23..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test001TimeoutSuite.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import org.assertj.core.api.Assertions; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.Utils; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.Timeout; -import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite; - -public class Test001TimeoutSuite extends WithNestedTestClass { - /** - * Nested test suite class with {@link TimeoutSuite}. - */ - @TimeoutSuite(millis = 500) - @Timeout(millis = 5000) - public static class Nested extends ApplyAtPlace {} - - @Test public void testClassRule() { check(Place.CLASS_RULE); } - @Test public void testBeforeClass() { check(Place.BEFORE_CLASS); } - @Test public void testConstructor() { check(Place.CONSTRUCTOR); } - @Test public void testTestRule() { check(Place.TEST_RULE); } - @Test public void testBefore() { check(Place.BEFORE); } - @Test public void testTest() { check(Place.TEST); } - @Test public void testAfter() { check(Place.AFTER); } - @Test public void testAfterClass() { check(Place.AFTER_CLASS); } - - /** - * Check a given timeout place. - */ - private void check(Place p) { - ApplyAtPlace.place = p; - ApplyAtPlace.runnable = new Runnable() { - @Override - public void run() { - while (true) RandomizedTest.sleep(10000); - } - }; - - FullResult r = runTests(Nested.class); - Utils.assertFailureWithMessage(r, "Suite timeout exceeded"); - Utils.assertFailuresContainSeeds(r); - - Assertions.assertThat(getLoggingMessages()) - .doesNotContain("Test execution timed out"); - } -} - diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test002TimeoutMethod.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test002TimeoutMethod.java deleted file mode 100644 index bae1b276..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test002TimeoutMethod.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.Utils; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.Timeout; - -public class Test002TimeoutMethod extends WithNestedTestClass { - @Timeout(millis = 25) - public static class Nested extends ApplyAtPlace {} - - @Test public void testTestRule() { check(Place.TEST_RULE); } - @Test public void testBefore() { check(Place.BEFORE); } - @Test public void testTest() { check(Place.TEST); } - @Test public void testAfter() { check(Place.AFTER); } - - /** - * Check a given timeout place. - */ - private void check(Place p) { - ApplyAtPlace.place = p; - ApplyAtPlace.runnable = new Runnable() { - @Override - public void run() { - while (true) RandomizedTest.sleep(1000); - } - }; - - FullResult r = runTests(Nested.class); - Utils.assertFailureWithMessage(r, "Test timeout exceeded"); - Utils.assertFailuresContainSeeds(r); - } -} - diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test003ThreadLeaksMethod.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test003ThreadLeaksMethod.java deleted file mode 100644 index 2bd3fbbd..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test003ThreadLeaksMethod.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import org.assertj.core.api.Assertions; -import org.junit.Assert; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.LifecycleScope; -import com.carrotsearch.randomizedtesting.Utils; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction.Action; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; - -public class Test003ThreadLeaksMethod extends WithNestedTestClass { - @ThreadLeakScope(Scope.TEST) - @ThreadLeakLingering(linger = 0) - @ThreadLeakAction({Action.WARN, Action.INTERRUPT}) - public static class Nested extends ApplyAtPlace {} - - @Test public void testClassRule() { suiteLeak(Place.CLASS_RULE); } - @Test public void testBeforeClass() { suiteLeak(Place.BEFORE_CLASS); } - @Test public void testConstructor() { suiteLeak(Place.CONSTRUCTOR); } - @Test public void testTestRule() { testLeak(Place.TEST_RULE); } - @Test public void testBefore() { testLeak(Place.BEFORE); } - @Test public void testTest() { testLeak(Place.TEST); } - @Test public void testAfter() { testLeak(Place.AFTER); } - @Test public void testAfterClass() { suiteLeak(Place.AFTER_CLASS); } - - private void testLeak(Place p) { - check(p, LifecycleScope.TEST); - } - - private void suiteLeak(Place p) { - check(p, LifecycleScope.SUITE); - } - - /** - * Check a given timeout place. - */ - private void check(Place p, LifecycleScope scope) { - ApplyAtPlace.place = p; - ApplyAtPlace.runnable = new Runnable() { - @Override - public void run() { - startThread("foobar"); - } - }; - - FullResult r = runTests(Nested.class); - Utils.assertFailureWithMessage(r, "1 thread leaked from " + scope.toString() + " scope at"); - Assert.assertEquals(1, r.getFailureCount()); - Utils.assertFailuresContainSeeds(r); - Utils.assertNoLiveThreadsContaining("foobar"); - - Assertions.assertThat(getLoggingMessages()) - .doesNotContain("Uncaught exception"); - } -} - diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test004ThreadLeaksSuite.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test004ThreadLeaksSuite.java deleted file mode 100644 index 8d45e6ad..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test004ThreadLeaksSuite.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import org.assertj.core.api.Assertions; -import org.junit.Assert; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.Utils; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction.Action; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; - -public class Test004ThreadLeaksSuite extends WithNestedTestClass { - @ThreadLeakScope(Scope.SUITE) - @ThreadLeakLingering(linger = 0) - @ThreadLeakAction({Action.WARN, Action.INTERRUPT}) - public static class Nested extends ApplyAtPlace {} - - @Test public void testClassRule() { suiteLeak(Place.CLASS_RULE); } - @Test public void testBeforeClass() { suiteLeak(Place.BEFORE_CLASS); } - @Test public void testConstructor() { suiteLeak(Place.CONSTRUCTOR); } - @Test public void testTestRule() { suiteLeak(Place.TEST_RULE); } - @Test public void testBefore() { suiteLeak(Place.BEFORE); } - @Test public void testTest() { suiteLeak(Place.TEST); } - @Test public void testAfter() { suiteLeak(Place.AFTER); } - @Test public void testAfterClass() { suiteLeak(Place.AFTER_CLASS); } - - /** - * Check a given timeout place. - */ - private void suiteLeak(Place p) { - ApplyAtPlace.place = p; - ApplyAtPlace.runnable = new Runnable() { - @Override - public void run() { - startThread("foobar"); - } - }; - - FullResult r = runTests(Nested.class); - Utils.assertFailureWithMessage(r, "1 thread leaked from SUITE scope at"); - Assert.assertEquals(1, r.getFailureCount()); - Utils.assertFailuresContainSeeds(r); - Utils.assertNoLiveThreadsContaining("foobar"); - - Assertions.assertThat(getLoggingMessages()) - .doesNotContain("Uncaught exception"); - } -} - diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test005ThreadLeaksSystemThreads.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test005ThreadLeaksSystemThreads.java deleted file mode 100644 index 3f6214e0..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test005ThreadLeaksSystemThreads.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import java.lang.reflect.Method; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.assertj.core.api.Assertions; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakGroup; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakGroup.Group; - -/** - * Checks if known demon threads spawned by certain library methods are properly - * handled. - */ -public class Test005ThreadLeaksSystemThreads extends WithNestedTestClass { - - @ThreadLeakGroup(Group.MAIN) - public static class Nested extends RandomizedTest { - @Test - public void tokenPoller() throws Exception { - assumeRunningNested(); - try { - MessageDigest instance = MessageDigest.getInstance("MD5"); - instance.update(randomByte()); - instance.digest(); - } catch (NoSuchAlgorithmException e) { - Logger.getAnonymousLogger().log(Level.SEVERE, "No MD5 in MessageDigest?", e); - } - } - - @Test - public void gcDaemon() throws Exception { - assumeRunningNested(); - - try { - Class clazz = Class.forName("sun.misc.GC"); - Method method = clazz.getDeclaredMethod("requestLatency", new Class[] {long.class}); - method.invoke(null, Long.valueOf(3600000)); - } catch (ClassNotFoundException e) { - // Ignore, must be running under a JVM without this class. - } - } - } - - @Test - public void leftOverThread() throws Throwable { - FullResult r = runTests(Nested.class); - Assertions.assertThat(r.getFailures()).isEmpty(); - - Assertions.assertThat(getLoggingMessages()) - .doesNotContain("java.lang.Thread.sleep") - .doesNotContain("Uncaught exception"); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test006TimeoutAndThreadLeak.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test006TimeoutAndThreadLeak.java deleted file mode 100644 index fa05ff1c..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test006TimeoutAndThreadLeak.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import org.assertj.core.api.Assertions; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.Utils; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite; - -public class Test006TimeoutAndThreadLeak extends WithNestedTestClass { - /** - * Nested test suite class with {@link TimeoutSuite}. - */ - @TimeoutSuite(millis = 500) - public static class Nested extends ApplyAtPlace {} - - @Test public void testClassRule() { check(Place.CLASS_RULE); } - @Test public void testBeforeClass() { check(Place.BEFORE_CLASS); } - @Test public void testConstructor() { check(Place.CONSTRUCTOR); } - @Test public void testTestRule() { check(Place.TEST_RULE); } - @Test public void testBefore() { check(Place.BEFORE); } - @Test public void testTest() { check(Place.TEST); } - @Test public void testAfter() { check(Place.AFTER); } - @Test public void testAfterClass() { check(Place.AFTER_CLASS); } - - /** - * Check a given timeout place. - */ - private void check(Place p) { - ApplyAtPlace.place = p; - ApplyAtPlace.runnable = new Runnable() { - @Override - public void run() { - startThread("foobar"); - while (true) RandomizedTest.sleep(1000); - } - }; - - FullResult r = runTests(Nested.class); - Utils.assertFailureWithMessage(r, "Suite timeout exceeded"); - Utils.assertFailuresContainSeeds(r); - Utils.assertNoLiveThreadsContaining("foobar"); - - Assertions.assertThat(getLoggingMessages()) - .doesNotContain("Uncaught exception"); - } -} - diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test007UncaughtExceptions.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test007UncaughtExceptions.java deleted file mode 100644 index 8e0aa7a2..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test007UncaughtExceptions.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import org.assertj.core.api.Assertions; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.Utils; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; - -public class Test007UncaughtExceptions extends WithNestedTestClass { - static ThreadGroup parentGroup; - - public static class Nested extends RandomizedTest { - @Test - public void checkGlobal() throws Exception { - assumeRunningNested(); - - final Thread t = new Thread(parentGroup, "XYZ") { - public void run() { - throw new RuntimeException("Yoda died."); - } - }; - - t.start(); - t.join(); - } - } - - @Test - public void testUncaughtExceptionsAtMainGroup() throws Exception { - ThreadGroup parentTg = Thread.currentThread().getThreadGroup(); - while (parentTg.getParent() != null) - parentTg = parentTg.getParent(); - - parentGroup = parentTg; - check(); - } - - @Test - public void testUncaughtExceptionsAtThreadGroup() throws Exception { - parentGroup = null; - check(); - } - - /** - * Apply assertions. - */ - private void check() throws Exception { - FullResult r = runTests(Nested.class); - - Utils.assertFailureWithMessage(r, "Captured an uncaught exception in thread: "); - Utils.assertFailureWithMessage(r, "Yoda died."); - Utils.assertFailuresContainSeeds(r); - Utils.assertNoLiveThreadsContaining("XYZ"); - - Assertions.assertThat(getLoggingMessages()) - .contains("Uncaught exception") - .contains("Yoda died."); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test008SeedsAnnotation.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test008SeedsAnnotation.java deleted file mode 100644 index 164650a0..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test008SeedsAnnotation.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import static org.assertj.core.data.MapEntry.entry; - -import java.util.ArrayList; -import java.util.HashMap; - -import org.assertj.core.api.Assertions; -import org.junit.Test; -import org.junit.Assert; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.Utils; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.Seed; -import com.carrotsearch.randomizedtesting.annotations.Seeds; - - -/** - * Check {@link Seeds}. - */ -public class Test008SeedsAnnotation extends WithNestedTestClass { - final static ArrayList seeds = new ArrayList(); - - public static class Nested extends RandomizedTest { - @Seeds({ - @Seed("deadbeef"), - @Seed("cafebabe"), - @Seed // Adds a randomized execution too. - }) - @Test - @Repeat(iterations = 2, useConstantSeed = true) - public void testMe() { - assumeRunningNested(); - seeds.add(Long.toHexString(Utils.getSeed(getContext().getRandomness()))); - } - } - - @Test - public void checkSeeds() { - HashMap counts = new HashMap(); - int N = 4; - for (int i = 0; i < N; i++) { - seeds.clear(); - FullResult result = runTests(Nested.class); - Assert.assertEquals(3 * 2, result.getRunCount()); - Assertions.assertThat(result.getFailures()).isEmpty(); - for (String s : seeds) { - if (!counts.containsKey(s)) - counts.put(s, 1L); - else - counts.put(s, counts.get(s) + 1); - } - } - - Assertions.assertThat(counts).contains(entry("deadbeef", N * 2L)); - Assertions.assertThat(counts).contains(entry("cafebabe", N * 2L)); - counts.remove("deadbeef"); - counts.remove("cafebabe"); - - // Allow for a single collision. - Assert.assertTrue(counts.size() >= N - 1); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test009TimeoutOrNotIdenticalSequence.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test009TimeoutOrNotIdenticalSequence.java deleted file mode 100644 index 0fc4110b..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test009TimeoutOrNotIdenticalSequence.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import java.util.ArrayList; -import java.util.List; - -import org.assertj.core.api.Assertions; -import org.junit.Test; -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.Repeat; -import com.carrotsearch.randomizedtesting.annotations.Seed; -import com.carrotsearch.randomizedtesting.annotations.Timeout; - -/** - * It should not matter for the random sequence whether {@link Timeout} is - * used or not. - */ -public class Test009TimeoutOrNotIdenticalSequence extends WithNestedTestClass { - final static ArrayList seeds = new ArrayList(); - - public static class Nested1 extends RandomizedTest { - @Test - @Seed("deadbeef") - @Repeat(iterations = 2, useConstantSeed = false) - public void testNoTimeout() { - assumeRunningNested(); - seeds.add(randomAsciiLettersOfLength(20)); - } - } - - public static class Nested2 extends Nested1 { - @Override - @Test - @Seed("deadbeef") - @Repeat(iterations = 2, useConstantSeed = false) - @Timeout(millis = 30 * 1000) - public void testNoTimeout() { - super.testNoTimeout(); - } - } - - @Timeout(millis = 30 * 1000) - public static class Nested3 extends Nested1 { - @Override - @Test - @Seed("deadbeef") - @Repeat(iterations = 2, useConstantSeed = false) - @Timeout(millis = 30 * 1000) - public void testNoTimeout() { - super.testNoTimeout(); - } - } - - @Test - public void checkAllRunsIdentical() { - List previous = null; - for (Class c : new Class [] {Nested1.class, Nested2.class, Nested3.class}) { - seeds.clear(); - Assertions.assertThat(runTests(c).wasSuccessful()).isTrue(); - - if (previous != null) { - Assertions.assertThat(seeds).as("Class " + c.getSimpleName()).isEqualTo(previous); - } else { - previous = new ArrayList<>(seeds); - } - } - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test010Zombies.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test010Zombies.java deleted file mode 100644 index fb7c3d24..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test010Zombies.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import org.assertj.core.api.Assertions; -import org.junit.Rule; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.SysGlobals; -import com.carrotsearch.randomizedtesting.Utils; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction.Action; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies.Consequence; -import com.carrotsearch.randomizedtesting.rules.SystemPropertiesRestoreRule; - -public class Test010Zombies extends WithNestedTestClass { - @ThreadLeakScope(Scope.TEST) - @ThreadLeakLingering(linger = 0) - @ThreadLeakAction({Action.INTERRUPT}) - @ThreadLeakZombies(Consequence.IGNORE_REMAINING_TESTS) - public static class Nested extends ApplyAtPlace {} - - @Test public void testClassRule() { check(Place.CLASS_RULE); } - @Test public void testBeforeClass() { check(Place.BEFORE_CLASS); } - @Test public void testConstructor() { check(Place.CONSTRUCTOR); } - @Test public void testTestRule() { check(Place.TEST_RULE); } - @Test public void testBefore() { check(Place.BEFORE); } - @Test public void testTest() { check(Place.TEST); } - @Test public void testAfter() { check(Place.AFTER); } - @Test public void testAfterClass() { check(Place.AFTER_CLASS); } - - @Rule - public SystemPropertiesRestoreRule restoreProperties = new SystemPropertiesRestoreRule(); - - /** - * Start a zombie thread somewhere. Ensure all suites are ignored afterwards. - */ - private void check(Place p) { - System.setProperty(SysGlobals.SYSPROP_KILLWAIT(), "10"); - System.setProperty(SysGlobals.SYSPROP_KILLATTEMPTS(), "2"); - - ApplyAtPlace.place = p; - ApplyAtPlace.runnable = new Runnable() { - @Override - public void run() { - startZombieThread("foobarZombie"); - } - }; - - // Run a class spawning zombie threads. - FullResult r = runTests(Nested.class); - - Utils.assertFailureWithMessage(r, "1 thread leaked"); - Utils.assertFailureWithMessage(r, "foobarZombie"); - Utils.assertFailuresContainSeeds(r); - - Assertions.assertThat(getLoggingMessages()) - .contains("There are still zombie threads that couldn't be terminated:"); - - // Run another suite. Everything should be ignored because of zombie threads. - for (Place p2 : Place.values()) { - ApplyAtPlace.place = p2; - ApplyAtPlace.runnable = new Runnable() { - @Override - public void run() { - throw new RuntimeException(); - } - }; - - r = runTests(Nested.class); - Assertions.assertThat(r.wasSuccessful()).as("At: " + p2).isTrue(); - } - } -} - diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test011RunawayThreads.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test011RunawayThreads.java deleted file mode 100644 index f2116b9c..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test011RunawayThreads.java +++ /dev/null @@ -1,158 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import java.util.concurrent.*; - -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.*; -import org.junit.runner.notification.Failure; - -import com.carrotsearch.randomizedtesting.RandomizedContext; -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.Utils; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering; - -@RunWith(RandomizedRunner.class) -public class Test011RunawayThreads extends WithNestedTestClass { - private abstract static class ThreadWithException extends Thread { - public volatile Throwable throwable; - - @Override - public final void run() { - try { - runWrapped(); - } catch (Throwable t) { - throwable = t; - } - } - - public final ThreadWithException startAndJoin() throws Throwable { - this.start(); - try { - this.join(5000); - if (throwable != null) throw throwable; - } catch (InterruptedException e) { - throw e; - } - return this; - } - - protected abstract void runWrapped(); - } - - @Test - public void subThreadContextPropagation() throws Throwable { - final long seed = Utils.getRunnerSeed(); - new ThreadWithException() { - protected void runWrapped() { - RandomizedContext ctx = RandomizedContext.current(); - Assert.assertEquals(seed, Utils.getSeed(ctx.getRandomness())); - } - }.startAndJoin(); - } - - @ThreadLeakLingering(linger = 2000) - @Test - public void ExecutorServiceContextPropagation() throws Throwable { - final long seed = Utils.getRunnerSeed(); - final ExecutorService executor = Executors.newCachedThreadPool(); - try { - executor.submit(new Runnable() { - public void run() { - RandomizedContext ctx = RandomizedContext.current(); - Assert.assertEquals(seed, Utils.getSeed(ctx.getRandomness())); - } - }).get(); - } catch (ExecutionException e) { - throw e.getCause(); - } finally { - executor.shutdown(); - executor.awaitTermination(1, TimeUnit.SECONDS); - } - } - - public static class Nested extends RandomizedTest { - final boolean withJoin; - - public Nested() { - this(true); - } - - protected Nested(boolean withJoin) { - this.withJoin = withJoin; - } - - @Test - public void spinoffAndThrow() throws Exception{ - assumeRunningNested(); - Thread t = new Thread() { - public void run() { - RandomizedTest.sleep(500); - throw new RuntimeException("spinoff exception"); - } - }; - t.start(); - if (withJoin) { - t.join(); - } - } - } - - public static class NestedNoJoin extends Nested { - public NestedNoJoin() { - super(false); - } - } - - @Test - public void subUncaughtExceptionInSpunOffThread() throws Throwable { - FullResult r = runTests(Nested.class); - Assert.assertEquals(1, r.getFailureCount()); - Failure testFailure = r.getFailures().get(0); - Throwable testException = testFailure.getException(); - Throwable threadException = testException.getCause(); - Assert.assertNotNull(RandomizedRunner.seedFromThrowable(testException)); - Assert.assertNotNull(RandomizedRunner.seedFromThrowable(threadException)); - } - - @Test - public void subNotJoined() throws Throwable { - FullResult r = runTests(NestedNoJoin.class); - Assert.assertEquals(1, r.getFailureCount()); - Failure testFailure = r.getFailures().get(0); - Throwable testException = testFailure.getException(); - Assert.assertNotNull(RandomizedRunner.seedFromThrowable(testException)); - } - - public static class NestedClassScope extends RandomizedTest { - @BeforeClass - public static void startThread() { - if (!isRunningNested()) - return; - - new Thread() { - @Override - public void run() { - RandomizedTest.sleep(5000); - } - }.start(); - } - - @Test - public void spinoffAndThrow() throws Exception{ - assumeRunningNested(); - } - } - - @Test - public void subNotJoinOnClassLevel() throws Throwable { - FullResult r = runTests(NestedClassScope.class); - Assert.assertEquals(1, r.getFailureCount()); - Failure testFailure = r.getFailures().get(0); - Throwable testException = testFailure.getException(); - Assert.assertNotNull(RandomizedRunner.seedFromThrowable(testException)); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test012RunawayThreadsKilledAtOnce.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test012RunawayThreadsKilledAtOnce.java deleted file mode 100644 index bf37d0e7..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test012RunawayThreadsKilledAtOnce.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import java.util.concurrent.CountDownLatch; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.*; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; - -@RunWith(RandomizedRunner.class) -public class Test012RunawayThreadsKilledAtOnce extends WithNestedTestClass { - @RunWith(RandomizedRunner.class) - public static class NestedClass { - @Test - public void lotsOfStubbornThreads() throws Throwable { - assumeRunningNested(); - final CountDownLatch latch = new CountDownLatch(50); - - Thread [] threads = new Thread [(int) latch.getCount()]; - for (int i = 0; i < threads.length; i++) { - threads[i] = new Thread("stubborn-" + i) { - @Override - public void run() { - latch.countDown(); - - try { - Thread.sleep(20000); - } catch (InterruptedException e) { - // Ignore - } - } - }; - threads[i].start(); - } - - // Wait for all threads to be really started. - latch.await(); - } - } - - @Test - public void testLotsOfStubbornThreads() { - long start = System.currentTimeMillis(); - FullResult result = runTests(NestedClass.class); - long end = System.currentTimeMillis(); - - Assert.assertEquals(1, result.getFailureCount()); - Assert.assertTrue((end - start) + " msec?", (end - start) < 1000 * 10); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test013ThreadLeaksScopeNone.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test013ThreadLeaksScopeNone.java deleted file mode 100644 index 656e51d1..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test013ThreadLeaksScopeNone.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import org.assertj.core.api.Assertions; -import org.junit.Assert; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; - -public class Test013ThreadLeaksScopeNone extends WithNestedTestClass { - @ThreadLeakScope(Scope.NONE) - public static class Nested extends ApplyAtPlace {} - - @Test public void testClassRule() { testLeak(Place.CLASS_RULE); } - @Test public void testBeforeClass() { testLeak(Place.BEFORE_CLASS); } - @Test public void testConstructor() { testLeak(Place.CONSTRUCTOR); } - @Test public void testTestRule() { testLeak(Place.TEST_RULE); } - @Test public void testBefore() { testLeak(Place.BEFORE); } - @Test public void testTest() { testLeak(Place.TEST); } - @Test public void testAfter() { testLeak(Place.AFTER); } - @Test public void testAfterClass() { testLeak(Place.AFTER_CLASS); } - - private void testLeak(Place p) { - ApplyAtPlace.place = p; - ApplyAtPlace.runnable = new Runnable() { - @Override - public void run() { - startZombieThread("foobar"); - } - }; - - FullResult r = runTests(Nested.class); - Assert.assertEquals(0, r.getFailureCount()); - - Assertions.assertThat(getLoggingMessages()).isEmpty(); - Assertions.assertThat(getSysouts()).isEmpty(); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test014Timeout.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test014Timeout.java deleted file mode 100644 index 7d91ae75..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test014Timeout.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import org.junit.Test; -import org.junit.Assert; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; - -/** - * Test {@link Test#timeout()}. - */ -public class Test014Timeout extends WithNestedTestClass { - public static class Nested extends RandomizedTest { - @Test(timeout = 100) - public void testMethod1() { - assumeRunningNested(); - sleep(2000); - } - - @Test(timeout = 100) - public void testMethod2() { - assumeRunningNested(); - while (!Thread.interrupted()) { - // Do nothing. - } - } - } - - @Test - public void testTimeoutInTestAnnotation() { - FullResult result = runTests(Nested.class); - - Assert.assertEquals(0, result.getIgnoreCount()); - Assert.assertEquals(2, result.getRunCount()); - Assert.assertEquals(2, result.getFailureCount()); - Assert.assertEquals(0, result.getAssumptionIgnored()); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test015TimeoutOverride.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test015TimeoutOverride.java deleted file mode 100644 index 52f9d042..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test015TimeoutOverride.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import org.junit.After; -import org.junit.Test; -import org.junit.Assert; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.SysGlobals; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.Timeout; - - -/** - * Test global timeout override (-Dtests.timeout=1000!). - */ -public class Test015TimeoutOverride extends WithNestedTestClass { - public static class Nested extends RandomizedTest { - @Test - @Timeout(millis = 5000) - public void testMethod1() { - assumeRunningNested(); - sleep(10000); - } - } - - public static class Nested2 extends RandomizedTest { - @Test - @Timeout(millis = 100) - public void testMethod1() { - assumeRunningNested(); - sleep(1000); - } - } - - @Test - public void testTimeoutOverride() { - System.setProperty(SysGlobals.SYSPROP_TIMEOUT(), "200!"); - long start = System.currentTimeMillis(); - FullResult result = runTests(Nested.class); - long end = System.currentTimeMillis(); - Assert.assertEquals(1, result.getFailureCount()); - Assert.assertTrue(end - start < 3000); - } - - @Test - public void testDisableTimeout() { - System.setProperty(SysGlobals.SYSPROP_TIMEOUT(), "0!"); - - long start = System.currentTimeMillis(); - FullResult result = runTests(Nested2.class); - long end = System.currentTimeMillis(); - Assert.assertEquals(0, result.getFailureCount()); - Assert.assertTrue(end - start > 900); - } - - @After - public void cleanup() { - System.clearProperty(SysGlobals.SYSPROP_TIMEOUT()); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test016ThreadLeaksCustomFilters.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test016ThreadLeaksCustomFilters.java deleted file mode 100644 index 7fecc25f..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test016ThreadLeaksCustomFilters.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import org.assertj.core.api.Assertions; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.ThreadFilter; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; - -/** - * Checks custom thread ignore policy. - */ -public class Test016ThreadLeaksCustomFilters extends WithNestedTestClass { - public static class FooBarFilter implements ThreadFilter { - @Override - public boolean reject(Thread t) { - return t.getName().contains("foobar"); - } - } - - @ThreadLeakScope(Scope.TEST) - @ThreadLeakFilters(defaultFilters = true, filters = { - FooBarFilter.class - }) - public static class Nested1 extends RandomizedTest { - @Test - public void testFooBars() throws Exception { - assumeRunningNested(); - for (int i = 0; i < 10; i++) { - startZombieThread("foobar-" + i); - } - } - } - - @Test - public void testFilteredOnly() throws Throwable { - Assertions.assertThat(runTests(Nested1.class).getFailures()).isEmpty(); - - Assertions.assertThat(getLoggingMessages()).isEmpty(); - Assertions.assertThat(getSysouts()).isEmpty(); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test017ThreadLeaksCustomFiltersException.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test017ThreadLeaksCustomFiltersException.java deleted file mode 100644 index 0aafc16d..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test017ThreadLeaksCustomFiltersException.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.ThreadFilter; -import com.carrotsearch.randomizedtesting.Utils; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; - -/** - * Checks custom thread ignore policy. - */ -public class Test017ThreadLeaksCustomFiltersException extends WithNestedTestClass { - public static class ExceptionFilter implements ThreadFilter { - @Override - public boolean reject(Thread t) { - if (!isRunningNested()) { - return false; - } - throw new RuntimeException("filter-exception"); - } - } - - @ThreadLeakScope(Scope.TEST) - @ThreadLeakFilters(defaultFilters = true, filters = { - ExceptionFilter.class - }) - public static class Nested1 extends RandomizedTest { - @Test - public void testFooBars() throws Exception { - assumeRunningNested(); - for (int i = 0; i < 10; i++) { - startZombieThread("foobar-" + i); - } - } - } - - @Test - public void testExceptionInFilter() throws Throwable { - FullResult r = runTests(Nested1.class); - Utils.assertFailureWithMessage(r, "filter-exception"); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test018TimeoutStacks.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test018TimeoutStacks.java deleted file mode 100644 index c885917a..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test018TimeoutStacks.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import org.assertj.core.api.Assertions; -import org.junit.Test; -import org.junit.runner.JUnitCore; - -import com.carrotsearch.randomizedtesting.RandomizedRunner; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; -import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite; - -/** - * Checks custom thread ignore policy. - */ -public class Test018TimeoutStacks extends WithNestedTestClass { - @ThreadLeakScope(Scope.TEST) - @TimeoutSuite(millis = 1000) - public static class Nested1 { - @Test - public void testFooBars() throws Exception { - assumeRunningNested(); - for (int i = 0; i < 5; i++) { - startThread("foobar-" + i); - } - Thread.sleep(5000); - } - } - - @Test - public void testExceptionInFilter() throws Throwable { - new JUnitCore().run(new RandomizedRunner(Nested1.class)); - Assertions.assertThat(getLoggingMessages()).contains("sleepForever("); - // sysout.println(getLoggingMessages()); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test019ThreadLeakGroup.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test019ThreadLeakGroup.java deleted file mode 100644 index 4ea93ce9..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test019ThreadLeakGroup.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import java.util.concurrent.CountDownLatch; - -import org.assertj.core.api.Assertions; -import org.junit.After; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.Utils; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakGroup; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakGroup.Group; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; - -/** - * Checks thread leak detection group. - */ -public class Test019ThreadLeakGroup extends WithNestedTestClass { - volatile static Thread t; - - @ThreadLeakScope(Scope.TEST) - @ThreadLeakGroup(Group.TESTGROUP) - public static class Nested1 extends RandomizedTest { - @Test - public void testLeakOutsideOfGroup() throws Exception { - assumeRunningNested(); - - final CountDownLatch latch = new CountDownLatch(1); - ThreadGroup newTopGroup = new ThreadGroup(Utils.getTopThreadGroup(), "foobar-group"); - t = new Thread(newTopGroup, "foobar") { - @Override - public void run() { - try { - latch.countDown(); - Thread.sleep(5000); - } catch (InterruptedException e) {} - } - }; - t.start(); - latch.await(); - } - } - - @ThreadLeakGroup(Group.MAIN) - public static class Nested2 extends Nested1 { - } - - @ThreadLeakGroup(Group.ALL) - public static class Nested3 extends Nested1 { - } - - @Test - public void testTestGroup() throws Throwable { - FullResult r = runTests(Nested1.class); - Assertions.assertThat(r.getFailures()).isEmpty(); - Assertions.assertThat(t != null && t.isAlive()).isTrue(); - } - - @Test - public void testMainGroup() throws Throwable { - FullResult r = runTests(Nested2.class); - Assertions.assertThat(r.getFailures()).isEmpty(); - Assertions.assertThat(t != null && t.isAlive()).isTrue(); - } - - @Test - public void testAll() throws Throwable { - FullResult r = runTests(Nested3.class); - Utils.assertNoLiveThreadsContaining("foobar"); - Utils.assertFailureWithMessage(r, "1 thread leaked from TEST"); - } - - @After - public void cleanup() throws Exception { - if (t != null) { - t.interrupt(); - t.join(); - t = null; - } - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test020SuiteTimeoutStopsTests.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test020SuiteTimeoutStopsTests.java deleted file mode 100644 index e61c5f22..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test020SuiteTimeoutStopsTests.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import java.util.concurrent.atomic.AtomicInteger; - -import org.assertj.core.api.Assertions; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; -import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite; - -/** - * Checks custom thread ignore policy. - */ -public class Test020SuiteTimeoutStopsTests extends WithNestedTestClass { - @ThreadLeakScope(Scope.SUITE) - @TimeoutSuite(millis = 500) - @ThreadLeakLingering(linger = 0) - public static class Nested1 extends RandomizedTest { - @Test - public void test001() { idle("1"); } - @Test - public void test002() { idle("2"); } - @Test - public void test003() { idle("3"); } - @Test - public void test004() { idle("4"); } - @Test - public void test005() { idle("5"); } - @Test - public void test006() { idle("6"); } - - private static AtomicInteger executedTests; - - @BeforeClass - private static void setup() { - assumeRunningNested(); - executedTests = new AtomicInteger(); - } - - private void idle(String m) { - if (executedTests.getAndIncrement() == 0) { - System.out.println("before timeout(" + m + ")"); - try { - while (true) { Thread.sleep(1000); } - } catch (InterruptedException e) { - System.out.println("suite timeout(" + m + ")"); - // Suite timeout. - return; - } - } else { - System.out.println("after timeout(" + m + ")"); - } - } - } - - @Test - public void testExceptionInFilter() throws Throwable { - runTests(Nested1.class); - Assertions.assertThat(getSysouts()).doesNotContain("after timeout"); - sysout.println(getLoggingMessages()); - } -} diff --git a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test021SuiteTimeoutHanging.java b/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test021SuiteTimeoutHanging.java deleted file mode 100644 index 7398e058..00000000 --- a/randomized-runner/src/test/java/com/carrotsearch/randomizedtesting/timeouts/Test021SuiteTimeoutHanging.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.carrotsearch.randomizedtesting.timeouts; - -import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.carrotsearch.randomizedtesting.SysGlobals; -import com.carrotsearch.randomizedtesting.WithNestedTestClass; -import com.carrotsearch.randomizedtesting.annotations.*; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope; -import org.assertj.core.api.Assertions; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.notification.Failure; - -import java.util.ArrayList; -import java.util.Locale; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -/** - * Checks custom thread ignore policy. - */ -public class Test021SuiteTimeoutHanging extends WithNestedTestClass { - private static AtomicBoolean stop; - private static ArrayList waitQueue = new ArrayList<>(); - - @ThreadLeakScope(Scope.SUITE) - @ThreadLeakLingering(linger = 0) - @ThreadLeakAction({ThreadLeakAction.Action.WARN, ThreadLeakAction.Action.INTERRUPT}) - @ThreadLeakZombies(ThreadLeakZombies.Consequence.IGNORE_REMAINING_TESTS) - @TimeoutSuite(millis = 1000) - @TestCaseOrdering(TestCaseOrdering.AlphabeticOrder.class) - public static class Nested1 extends RandomizedTest { - @Test - public void test001() throws Exception { - synchronized (Thread.currentThread()) { - waitQueue.add(Thread.currentThread()); - while (!stop.get()) { - try { - Thread.sleep(250); - } catch (InterruptedException e) { - // If interrupted, just continue. Don't release the lock. - System.out.println("Interrupted."); - } - System.out.println("Still running."); - } - } - } - - @Test - public void test002() throws Exception { - // Should not be executed. - throw new Exception(); - } - - @BeforeClass - private static void setup() { - assumeRunningNested(); - } - } - - @Test - public void testThreadLeakInterruptsIsNotHangingOnJoin() throws Throwable { - stop = new AtomicBoolean(); - - System.setProperty(SysGlobals.SYSPROP_KILLATTEMPTS(), "1"); - AtomicReference result = new AtomicReference<>(); - Thread tester = new Thread(() -> { - waitQueue.add(Thread.currentThread()); - result.set(runTests(Nested1.class)); - }); - tester.start(); - - long deadline = System.currentTimeMillis() + 10000; - while (System.currentTimeMillis() < deadline && tester.isAlive()) { - Thread.sleep(250); - } - - boolean testerAlive = tester.isAlive(); - - // Wait for all threads to die. - stop.set(true); - for (Thread t : waitQueue) { - t.join(); - } - System.clearProperty(SysGlobals.SYSPROP_KILLATTEMPTS()); - - // Make sure the tester was dead when we left the long wait loop. This - // indicates the framework abandoned the thread it couldn't interrupt. - Assertions.assertThat(testerAlive).isFalse(); - - // Only one test executed. - Assertions.assertThat(result.get().getRunCount()).isEqualTo(1); - - // Make sure suite timeouts have been reported. - for (Failure failure : result.get().getFailures()) { - Assertions.assertThat(failure.getMessage().toLowerCase(Locale.ROOT)) - .contains("suite timeout"); - } - } -} diff --git a/src/site/site.xml b/src/site/site.xml deleted file mode 100644 index 2d1643b3..00000000 --- a/src/site/site.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - Randomized Testing - - - - org.apache.maven.skins - maven-fluido-skin - 1.5 - - - - - - - - - - - - - - - - - - From b8e40df6ef8d48b6fa56c9a99e441d4d8475007d Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Tue, 31 Aug 2021 14:42:44 +0200 Subject: [PATCH 2/5] Initial experiments with junit5 API. --- .gitignore | 9 + build.gradle.kts | 28 +++ core/build.gradle.kts | 14 ++ .../engine/RandomizedTestingEngine.java | 75 +++++++ .../org.junit.platform.engine.TestEngine | 1 + .../Junit5SanityCheckTest.java | 23 +++ gradle.properties | 8 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 185 ++++++++++++++++++ gradlew.bat | 89 +++++++++ settings.gradle.kts | 3 + 12 files changed, 440 insertions(+) create mode 100644 .gitignore create mode 100644 build.gradle.kts create mode 100644 core/build.gradle.kts create mode 100644 core/src/main/java/com/carrotsearch/randomizedtesting/engine/RandomizedTestingEngine.java create mode 100644 core/src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine create mode 100644 core/src/test/java/com/carrotsearch/randomizedtesting/Junit5SanityCheckTest.java create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle.kts diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..93bf7f2e --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build/ + +# Intellij +.idea/ +*.iml diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 00000000..06d7a0bb --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,28 @@ +plugins { + id("base") + + id("com.diffplug.spotless").version("5.14.2").apply(false) + id("de.thetaphi.forbiddenapis").version("3.1").apply(false) + id("com.carrotsearch.gradle.randomizedtesting").version("0.0.5").apply(false) +} + +allprojects { + repositories { + mavenLocal() + mavenCentral() + } +} + +with(rootProject) { + version = "3.0.0-SNAPSHOT" + description = "RandomizedTesting JUnit5 framework" +} + +subprojects { + plugins.withType { + configure { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = sourceCompatibility + } + } +} diff --git a/core/build.gradle.kts b/core/build.gradle.kts new file mode 100644 index 00000000..25ebcc5e --- /dev/null +++ b/core/build.gradle.kts @@ -0,0 +1,14 @@ + +plugins { + id("java-library") + // id("com.carrotsearch.gradle.randomizedtesting") +} + +dependencies { + implementation("org.junit.platform:junit-platform-engine:1.7.2") + testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.2") +} + +tasks.withType { + useJUnitPlatform() +} \ No newline at end of file diff --git a/core/src/main/java/com/carrotsearch/randomizedtesting/engine/RandomizedTestingEngine.java b/core/src/main/java/com/carrotsearch/randomizedtesting/engine/RandomizedTestingEngine.java new file mode 100644 index 00000000..d219efc9 --- /dev/null +++ b/core/src/main/java/com/carrotsearch/randomizedtesting/engine/RandomizedTestingEngine.java @@ -0,0 +1,75 @@ +package com.carrotsearch.randomizedtesting.engine; + +import org.junit.platform.engine.EngineDiscoveryRequest; +import org.junit.platform.engine.ExecutionRequest; +import org.junit.platform.engine.TestDescriptor; +import org.junit.platform.engine.UniqueId; +import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; +import org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver; +import org.junit.platform.engine.support.hierarchical.EngineExecutionContext; +import org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine; +import org.junit.platform.engine.support.hierarchical.Node; + +public class RandomizedTestingEngine + extends HierarchicalTestEngine { + + private final RandomizedTestDescriptor engineDescriptor; + + public RandomizedTestingEngine() { + this.engineDescriptor = + new RandomizedTestDescriptor( + UniqueId.forEngine(getId()), getId(), TestDescriptor.Type.CONTAINER); + } + + @Override + protected RandomizedContext createExecutionContext(ExecutionRequest executionRequest) { + return new RandomizedContext(); + } + + @Override + public String getId() { + return "com.carrotsearch.randomizedtesting"; + } + + private static final EngineDiscoveryRequestResolver resolver = + EngineDiscoveryRequestResolver.builder() + .addClassContainerSelectorResolver( + clazz -> { + System.out.println("class resolver: " + clazz.getName()); + return true; + }) + .build(); + + @Override + public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { + engineDescriptor.addChild( + new RandomizedTestDescriptor( + uniqueId.append("seg", "test-foo"), "foo", TestDescriptor.Type.TEST)); + return engineDescriptor; + } + + public static class RandomizedContext implements EngineExecutionContext {} + + private static class RandomizedTestDescriptor extends AbstractTestDescriptor + implements Node { + + private final Type type; + + protected RandomizedTestDescriptor(UniqueId uniqueId, String displayName, Type type) { + super(uniqueId, displayName); + this.type = type; + } + + @Override + public Type getType() { + return type; + } + + @Override + public RandomizedContext execute( + RandomizedContext context, DynamicTestExecutor dynamicTestExecutor) throws Exception { + System.out.println("Execute: " + this.getUniqueId()); + return Node.super.execute(context, dynamicTestExecutor); + } + } +} diff --git a/core/src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine b/core/src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine new file mode 100644 index 00000000..b092e74b --- /dev/null +++ b/core/src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine @@ -0,0 +1 @@ +com.carrotsearch.randomizedtesting.engine.RandomizedTestingEngine \ No newline at end of file diff --git a/core/src/test/java/com/carrotsearch/randomizedtesting/Junit5SanityCheckTest.java b/core/src/test/java/com/carrotsearch/randomizedtesting/Junit5SanityCheckTest.java new file mode 100644 index 00000000..67783932 --- /dev/null +++ b/core/src/test/java/com/carrotsearch/randomizedtesting/Junit5SanityCheckTest.java @@ -0,0 +1,23 @@ +package com.carrotsearch.randomizedtesting; + +import org.junit.jupiter.api.Test; + +public class Junit5SanityCheckTest { + @Test + public void passing() { + // Ok. + System.out.println("Passing."); + } + + @Test + public void failingOnAssertion() { + System.out.println("failingOnAssertion"); + assert false : "Failing."; + } + + @Test + public void failingWithException() { + System.out.println("failingWithException"); + throw new RuntimeException("Failing with exception."); + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..a47b68a3 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,8 @@ +systemProp.file.encoding=UTF-8 + +org.gradle.parallel=true +org.gradle.priority=low +org.gradle.workers.max=4 + +systemProp.org.gradle.internal.http.connectionTimeout=300000 +systemProp.org.gradle.internal.http.socketTimeout=300000 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..7454180f2ae8848c63b8b4dea2cb829da983f2fa GIT binary patch literal 59536 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 QuEJmfE|#`Dqx|px0L@K;Y5)KL literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..a0f7639f --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..744e882e --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MSYS* | MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..ac1b06f9 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 00000000..cedc5f80 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,3 @@ +rootProject.name = "randomizedtesting" + +include("core") \ No newline at end of file From ee535bb79495cb9c8eb3f0b6db2ba95de6a3039a Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Tue, 31 Aug 2021 14:53:12 +0200 Subject: [PATCH 3/5] Raw TestEngine. --- .gitignore | 1 + .../engine/RandomizedTestingEngine.java | 52 +++++++++---------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index 93bf7f2e..41683ecd 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ build/ # Intellij .idea/ *.iml +out/ diff --git a/core/src/main/java/com/carrotsearch/randomizedtesting/engine/RandomizedTestingEngine.java b/core/src/main/java/com/carrotsearch/randomizedtesting/engine/RandomizedTestingEngine.java index d219efc9..4adcbb86 100644 --- a/core/src/main/java/com/carrotsearch/randomizedtesting/engine/RandomizedTestingEngine.java +++ b/core/src/main/java/com/carrotsearch/randomizedtesting/engine/RandomizedTestingEngine.java @@ -1,53 +1,53 @@ package com.carrotsearch.randomizedtesting.engine; import org.junit.platform.engine.EngineDiscoveryRequest; +import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; +import org.junit.platform.engine.TestEngine; +import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; -import org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver; import org.junit.platform.engine.support.hierarchical.EngineExecutionContext; -import org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine; import org.junit.platform.engine.support.hierarchical.Node; -public class RandomizedTestingEngine - extends HierarchicalTestEngine { - - private final RandomizedTestDescriptor engineDescriptor; - - public RandomizedTestingEngine() { - this.engineDescriptor = - new RandomizedTestDescriptor( - UniqueId.forEngine(getId()), getId(), TestDescriptor.Type.CONTAINER); - } - - @Override - protected RandomizedContext createExecutionContext(ExecutionRequest executionRequest) { - return new RandomizedContext(); - } +public class RandomizedTestingEngine implements TestEngine { + public RandomizedTestingEngine() {} @Override public String getId() { return "com.carrotsearch.randomizedtesting"; } - private static final EngineDiscoveryRequestResolver resolver = - EngineDiscoveryRequestResolver.builder() - .addClassContainerSelectorResolver( - clazz -> { - System.out.println("class resolver: " + clazz.getName()); - return true; - }) - .build(); - @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { + var engineDescriptor = + new RandomizedTestDescriptor( + UniqueId.forEngine(getId()), getId(), TestDescriptor.Type.CONTAINER); + engineDescriptor.addChild( new RandomizedTestDescriptor( uniqueId.append("seg", "test-foo"), "foo", TestDescriptor.Type.TEST)); + return engineDescriptor; } + @Override + public void execute(ExecutionRequest request) { + var listener = request.getEngineExecutionListener(); + process(listener, request.getRootTestDescriptor()); + } + + private void process(EngineExecutionListener listener, TestDescriptor node) { + listener.executionStarted(node); + if (node.isContainer()) { + for (var v : node.getChildren()) { + process(listener, v); + } + } + listener.executionFinished(node, TestExecutionResult.successful()); + } + public static class RandomizedContext implements EngineExecutionContext {} private static class RandomizedTestDescriptor extends AbstractTestDescriptor From f21d28d5eb36dba90d8846f28dc6c7366e59d73c Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Wed, 1 Sep 2021 13:52:21 +0200 Subject: [PATCH 4/5] More experiments. IntelliJ idea integration. --- core/build.gradle.kts | 5 +- .../randomizedtesting/engine/Predicates.java | 61 ++++++++++++ .../engine/RandomizedTestingEngine.java | 95 ++++++++++++++++++- .../Junit5SanityCheckTest.java | 6 +- 4 files changed, 160 insertions(+), 7 deletions(-) create mode 100644 core/src/main/java/com/carrotsearch/randomizedtesting/engine/Predicates.java diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 25ebcc5e..0e89a8e8 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -6,7 +6,10 @@ plugins { dependencies { implementation("org.junit.platform:junit-platform-engine:1.7.2") - testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.2") + implementation("org.junit.jupiter:junit-jupiter-api:5.7.2") + + testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.7.2") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.2") } tasks.withType { diff --git a/core/src/main/java/com/carrotsearch/randomizedtesting/engine/Predicates.java b/core/src/main/java/com/carrotsearch/randomizedtesting/engine/Predicates.java new file mode 100644 index 00000000..30c904c6 --- /dev/null +++ b/core/src/main/java/com/carrotsearch/randomizedtesting/engine/Predicates.java @@ -0,0 +1,61 @@ +package com.carrotsearch.randomizedtesting.engine; + +import java.lang.reflect.Method; +import java.util.function.Predicate; + +import static org.junit.platform.commons.util.ReflectionUtils.*; + +class Predicates { + static class IsTestableMethod implements Predicate { + private final boolean mustReturnVoid; + + IsTestableMethod(boolean mustReturnVoid) { + this.mustReturnVoid = mustReturnVoid; + } + + @Override + public boolean test(Method candidate) { + if (isStatic(candidate) || isPrivate(candidate) || isAbstract(candidate)) { + return false; + } + if (returnsVoid(candidate) != this.mustReturnVoid) { + return false; + } + + return candidate.getName().startsWith("test"); + } + } + + static class IsPotentialTestContainer implements Predicate> { + + @Override + public boolean test(Class candidate) { + // Please do not collapse the following into a single statement. + if (isPrivate(candidate)) { + return false; + } + if (isAbstract(candidate)) { + return false; + } + if (candidate.isLocalClass()) { + return false; + } + if (candidate.isAnonymousClass()) { + return false; + } + return !isInnerClass(candidate); + } + } + + static class IsTestClassWithTests implements Predicate> { + private static final IsTestableMethod isTestMethod = new IsTestableMethod(true); + + private static final IsPotentialTestContainer isPotentialTestContainer = + new IsPotentialTestContainer(); + + @Override + public boolean test(Class candidate) { + return isPotentialTestContainer.test(candidate); + } + } +} diff --git a/core/src/main/java/com/carrotsearch/randomizedtesting/engine/RandomizedTestingEngine.java b/core/src/main/java/com/carrotsearch/randomizedtesting/engine/RandomizedTestingEngine.java index 4adcbb86..cf5e7847 100644 --- a/core/src/main/java/com/carrotsearch/randomizedtesting/engine/RandomizedTestingEngine.java +++ b/core/src/main/java/com/carrotsearch/randomizedtesting/engine/RandomizedTestingEngine.java @@ -1,16 +1,33 @@ package com.carrotsearch.randomizedtesting.engine; +import org.junit.platform.commons.util.ReflectionUtils; +import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.TestExecutionResult; +import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; +import org.junit.platform.engine.discovery.ClassSelector; +import org.junit.platform.engine.discovery.DiscoverySelectors; +import org.junit.platform.engine.discovery.MethodSelector; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; +import org.junit.platform.engine.support.descriptor.MethodSource; +import org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver; +import org.junit.platform.engine.support.discovery.SelectorResolver; import org.junit.platform.engine.support.hierarchical.EngineExecutionContext; import org.junit.platform.engine.support.hierarchical.Node; +import java.util.LinkedHashSet; +import java.util.Optional; +import java.util.Set; +import java.util.function.Supplier; + +import static java.util.stream.Collectors.toCollection; +import static org.junit.platform.commons.util.ReflectionUtils.findMethods; + public class RandomizedTestingEngine implements TestEngine { public RandomizedTestingEngine() {} @@ -19,15 +36,81 @@ public String getId() { return "com.carrotsearch.randomizedtesting"; } + private static final EngineDiscoveryRequestResolver resolver = + EngineDiscoveryRequestResolver.builder() + .addClassContainerSelectorResolver( + candidate -> + ReflectionUtils.isPublic(candidate) + && !ReflectionUtils.isAbstract(candidate) + && !ReflectionUtils.isInnerClass(candidate)) + .addSelectorResolver( + new SelectorResolver() { + @Override + public Resolution resolve(ClassSelector selector, Context context) { + var clazz = selector.getJavaClass(); + if (new Predicates.IsTestClassWithTests().test(clazz)) { + var opt = + context.addToParent( + parent -> { + var CLASS_SEGMENT = "class"; + var displayName = clazz.getName(); + var classDescriptor = + new RandomizedTestDescriptor( + parent.getUniqueId().append(CLASS_SEGMENT, clazz.getName()), + displayName, + TestDescriptor.Type.CONTAINER); + return Optional.of(classDescriptor); + }); + + return opt.map( + descriptor -> + Resolution.match( + Match.exact(descriptor, () -> methodSelectors(clazz)))) + .orElse(Resolution.unresolved()); + } else { + return Resolution.unresolved(); + } + } + + @Override + public Resolution resolve(MethodSelector selector, Context context) { + var methodName = selector.getMethodName(); + + var opt = + context.addToParent( + parent -> { + RandomizedTestDescriptor method = + new RandomizedTestDescriptor( + parent.getUniqueId().append("method", methodName), + methodName, + TestDescriptor.Type.TEST); + method.source = Optional.of(MethodSource.from(selector.getJavaMethod())); + return Optional.of(method); + }); + + return opt.map(desc -> Resolution.match(Match.exact(desc))) + .orElse(Resolution.unresolved()); + } + + private Set methodSelectors(Class testClass) { + var methods = + findMethods(testClass, new Predicates.IsTestableMethod(true)).stream() + .map(method -> DiscoverySelectors.selectMethod(testClass, method)) + .collect( + toCollection((Supplier>) LinkedHashSet::new)); + return methods; + } + }) + .addSelectorResolver(new SelectorResolver() {}) + .build(); + @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { var engineDescriptor = new RandomizedTestDescriptor( UniqueId.forEngine(getId()), getId(), TestDescriptor.Type.CONTAINER); - engineDescriptor.addChild( - new RandomizedTestDescriptor( - uniqueId.append("seg", "test-foo"), "foo", TestDescriptor.Type.TEST)); + resolver.resolve(discoveryRequest, engineDescriptor); return engineDescriptor; } @@ -54,12 +137,18 @@ private static class RandomizedTestDescriptor extends AbstractTestDescriptor implements Node { private final Type type; + Optional source = Optional.empty(); protected RandomizedTestDescriptor(UniqueId uniqueId, String displayName, Type type) { super(uniqueId, displayName); this.type = type; } + @Override + public Optional getSource() { + return source; + } + @Override public Type getType() { return type; diff --git a/core/src/test/java/com/carrotsearch/randomizedtesting/Junit5SanityCheckTest.java b/core/src/test/java/com/carrotsearch/randomizedtesting/Junit5SanityCheckTest.java index 67783932..0d759a06 100644 --- a/core/src/test/java/com/carrotsearch/randomizedtesting/Junit5SanityCheckTest.java +++ b/core/src/test/java/com/carrotsearch/randomizedtesting/Junit5SanityCheckTest.java @@ -4,19 +4,19 @@ public class Junit5SanityCheckTest { @Test - public void passing() { + public void testPassing() { // Ok. System.out.println("Passing."); } @Test - public void failingOnAssertion() { + public void testFailingOnAssertion() { System.out.println("failingOnAssertion"); assert false : "Failing."; } @Test - public void failingWithException() { + public void testFailingWithException() { System.out.println("failingWithException"); throw new RuntimeException("Failing with exception."); } From c68f075adb645e1fed80efeb710fc02c637e5e43 Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Tue, 4 Jan 2022 12:14:56 +0100 Subject: [PATCH 5/5] wip. --- build.gradle.kts | 3 + core/build.gradle.kts | 9 +- .../randomizedtesting/api/Randomized.java | 12 ++ .../api/RandomizedContext.java | 69 ++++++++ .../randomizedtesting/engine/Predicates.java | 61 ------- .../engine/RandomizedTestingEngine.java | 164 ------------------ .../extensions/ExtensionExecutionContext.java | 80 +++++++++ .../randomizedtesting/extensions/Hashing.java | 22 +++ .../extensions/InitialSeed.java | 14 ++ .../extensions/RandomSeed.java | 22 +++ .../RandomizedContextProviderExtension.java | 110 ++++++++++++ .../extensions/SeedChain.java | 57 ++++++ .../extensions/SysProps.java | 5 + .../randomizedtesting/internal/Threads.java | 19 ++ .../org.junit.platform.engine.TestEngine | 1 - .../Junit5SanityCheckTest.java | 23 --- examples/build.gradle.kts | 8 + .../examples/Test001SimpleUseCase.java | 62 +++++++ gradle/ide/idea.gradle | 47 +++++ settings.gradle.kts | 3 +- 20 files changed, 536 insertions(+), 255 deletions(-) create mode 100644 core/src/main/java/com/carrotsearch/randomizedtesting/api/Randomized.java create mode 100644 core/src/main/java/com/carrotsearch/randomizedtesting/api/RandomizedContext.java delete mode 100644 core/src/main/java/com/carrotsearch/randomizedtesting/engine/Predicates.java delete mode 100644 core/src/main/java/com/carrotsearch/randomizedtesting/engine/RandomizedTestingEngine.java create mode 100644 core/src/main/java/com/carrotsearch/randomizedtesting/extensions/ExtensionExecutionContext.java create mode 100644 core/src/main/java/com/carrotsearch/randomizedtesting/extensions/Hashing.java create mode 100644 core/src/main/java/com/carrotsearch/randomizedtesting/extensions/InitialSeed.java create mode 100644 core/src/main/java/com/carrotsearch/randomizedtesting/extensions/RandomSeed.java create mode 100644 core/src/main/java/com/carrotsearch/randomizedtesting/extensions/RandomizedContextProviderExtension.java create mode 100644 core/src/main/java/com/carrotsearch/randomizedtesting/extensions/SeedChain.java create mode 100644 core/src/main/java/com/carrotsearch/randomizedtesting/extensions/SysProps.java create mode 100644 core/src/main/java/com/carrotsearch/randomizedtesting/internal/Threads.java delete mode 100644 core/src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine delete mode 100644 core/src/test/java/com/carrotsearch/randomizedtesting/Junit5SanityCheckTest.java create mode 100644 examples/build.gradle.kts create mode 100644 examples/src/test/java/com/carrotsearch/randomizedtesting/examples/Test001SimpleUseCase.java create mode 100644 gradle/ide/idea.gradle diff --git a/build.gradle.kts b/build.gradle.kts index 06d7a0bb..c02cb26c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,6 +3,7 @@ plugins { id("com.diffplug.spotless").version("5.14.2").apply(false) id("de.thetaphi.forbiddenapis").version("3.1").apply(false) + id("com.carrotsearch.gradle.randomizedtesting").version("0.0.5").apply(false) } @@ -16,6 +17,8 @@ allprojects { with(rootProject) { version = "3.0.0-SNAPSHOT" description = "RandomizedTesting JUnit5 framework" + + apply(from = "gradle/ide/idea.gradle") } subprojects { diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 0e89a8e8..c8ab96ba 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,15 +1,14 @@ plugins { id("java-library") - // id("com.carrotsearch.gradle.randomizedtesting") } dependencies { - implementation("org.junit.platform:junit-platform-engine:1.7.2") - implementation("org.junit.jupiter:junit-jupiter-api:5.7.2") + api("org.junit.platform:junit-platform-engine:1.7.2") + api("org.junit.jupiter:junit-jupiter-api:5.7.2") + implementation("org.junit.jupiter:junit-jupiter-engine:5.7.2") - testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.7.2") - testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.2") + // testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.7.2") } tasks.withType { diff --git a/core/src/main/java/com/carrotsearch/randomizedtesting/api/Randomized.java b/core/src/main/java/com/carrotsearch/randomizedtesting/api/Randomized.java new file mode 100644 index 00000000..1fbf20fe --- /dev/null +++ b/core/src/main/java/com/carrotsearch/randomizedtesting/api/Randomized.java @@ -0,0 +1,12 @@ +package com.carrotsearch.randomizedtesting.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +@Inherited +public @interface Randomized {} diff --git a/core/src/main/java/com/carrotsearch/randomizedtesting/api/RandomizedContext.java b/core/src/main/java/com/carrotsearch/randomizedtesting/api/RandomizedContext.java new file mode 100644 index 00000000..11b4304d --- /dev/null +++ b/core/src/main/java/com/carrotsearch/randomizedtesting/api/RandomizedContext.java @@ -0,0 +1,69 @@ +package com.carrotsearch.randomizedtesting.api; + +import com.carrotsearch.randomizedtesting.extensions.RandomSeed; +import com.carrotsearch.randomizedtesting.extensions.SeedChain; +import com.carrotsearch.randomizedtesting.internal.Threads; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Locale; +import java.util.Random; +import java.util.function.LongUnaryOperator; + +public class RandomizedContext { + private final Thread owner; + private final RandomSeed seed; + private final RandomizedContext parent; + private final Random random; + + public RandomizedContext(Thread owner, RandomSeed seed) { + this(null, owner, seed); + } + + private RandomizedContext(RandomizedContext parent, Thread owner, RandomSeed seed) { + this.owner = owner; + this.seed = seed; + this.random = new Random(seed.value); + this.parent = parent; + } + + @Override + public String toString() { + return "Randomized context [" + + ("seedChain=" + getSeedChain()) + + "," + + ("thread=" + Threads.threadName(owner)) + + "]"; + } + + public SeedChain getSeedChain() { + ArrayList seeds = new ArrayList<>(); + for (RandomizedContext c = this; c != null; c = c.getParent()) { + seeds.add(c.seed); + } + Collections.reverse(seeds); + return new SeedChain(seeds); + } + + private RandomizedContext getParent() { + return parent; + } + + public RandomizedContext fork(Thread forThread, LongUnaryOperator initialSeedFunction) { + long initSeed = initialSeedFunction.applyAsLong(getRandom().nextLong()); + return new RandomizedContext(this, forThread, new RandomSeed(initSeed)); + } + + public Random getRandom() { + if (Thread.currentThread() != owner) { + throw new RuntimeException( + String.format( + Locale.ROOT, + "%s instance is bound to thread %s, can't access it from thread: %s", + RandomizedContext.class.getName(), + owner, + Thread.currentThread())); + } + return random; + } +} diff --git a/core/src/main/java/com/carrotsearch/randomizedtesting/engine/Predicates.java b/core/src/main/java/com/carrotsearch/randomizedtesting/engine/Predicates.java deleted file mode 100644 index 30c904c6..00000000 --- a/core/src/main/java/com/carrotsearch/randomizedtesting/engine/Predicates.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.carrotsearch.randomizedtesting.engine; - -import java.lang.reflect.Method; -import java.util.function.Predicate; - -import static org.junit.platform.commons.util.ReflectionUtils.*; - -class Predicates { - static class IsTestableMethod implements Predicate { - private final boolean mustReturnVoid; - - IsTestableMethod(boolean mustReturnVoid) { - this.mustReturnVoid = mustReturnVoid; - } - - @Override - public boolean test(Method candidate) { - if (isStatic(candidate) || isPrivate(candidate) || isAbstract(candidate)) { - return false; - } - if (returnsVoid(candidate) != this.mustReturnVoid) { - return false; - } - - return candidate.getName().startsWith("test"); - } - } - - static class IsPotentialTestContainer implements Predicate> { - - @Override - public boolean test(Class candidate) { - // Please do not collapse the following into a single statement. - if (isPrivate(candidate)) { - return false; - } - if (isAbstract(candidate)) { - return false; - } - if (candidate.isLocalClass()) { - return false; - } - if (candidate.isAnonymousClass()) { - return false; - } - return !isInnerClass(candidate); - } - } - - static class IsTestClassWithTests implements Predicate> { - private static final IsTestableMethod isTestMethod = new IsTestableMethod(true); - - private static final IsPotentialTestContainer isPotentialTestContainer = - new IsPotentialTestContainer(); - - @Override - public boolean test(Class candidate) { - return isPotentialTestContainer.test(candidate); - } - } -} diff --git a/core/src/main/java/com/carrotsearch/randomizedtesting/engine/RandomizedTestingEngine.java b/core/src/main/java/com/carrotsearch/randomizedtesting/engine/RandomizedTestingEngine.java deleted file mode 100644 index cf5e7847..00000000 --- a/core/src/main/java/com/carrotsearch/randomizedtesting/engine/RandomizedTestingEngine.java +++ /dev/null @@ -1,164 +0,0 @@ -package com.carrotsearch.randomizedtesting.engine; - -import org.junit.platform.commons.util.ReflectionUtils; -import org.junit.platform.engine.DiscoverySelector; -import org.junit.platform.engine.EngineDiscoveryRequest; -import org.junit.platform.engine.EngineExecutionListener; -import org.junit.platform.engine.ExecutionRequest; -import org.junit.platform.engine.TestDescriptor; -import org.junit.platform.engine.TestEngine; -import org.junit.platform.engine.TestExecutionResult; -import org.junit.platform.engine.TestSource; -import org.junit.platform.engine.UniqueId; -import org.junit.platform.engine.discovery.ClassSelector; -import org.junit.platform.engine.discovery.DiscoverySelectors; -import org.junit.platform.engine.discovery.MethodSelector; -import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; -import org.junit.platform.engine.support.descriptor.MethodSource; -import org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver; -import org.junit.platform.engine.support.discovery.SelectorResolver; -import org.junit.platform.engine.support.hierarchical.EngineExecutionContext; -import org.junit.platform.engine.support.hierarchical.Node; - -import java.util.LinkedHashSet; -import java.util.Optional; -import java.util.Set; -import java.util.function.Supplier; - -import static java.util.stream.Collectors.toCollection; -import static org.junit.platform.commons.util.ReflectionUtils.findMethods; - -public class RandomizedTestingEngine implements TestEngine { - public RandomizedTestingEngine() {} - - @Override - public String getId() { - return "com.carrotsearch.randomizedtesting"; - } - - private static final EngineDiscoveryRequestResolver resolver = - EngineDiscoveryRequestResolver.builder() - .addClassContainerSelectorResolver( - candidate -> - ReflectionUtils.isPublic(candidate) - && !ReflectionUtils.isAbstract(candidate) - && !ReflectionUtils.isInnerClass(candidate)) - .addSelectorResolver( - new SelectorResolver() { - @Override - public Resolution resolve(ClassSelector selector, Context context) { - var clazz = selector.getJavaClass(); - if (new Predicates.IsTestClassWithTests().test(clazz)) { - var opt = - context.addToParent( - parent -> { - var CLASS_SEGMENT = "class"; - var displayName = clazz.getName(); - var classDescriptor = - new RandomizedTestDescriptor( - parent.getUniqueId().append(CLASS_SEGMENT, clazz.getName()), - displayName, - TestDescriptor.Type.CONTAINER); - return Optional.of(classDescriptor); - }); - - return opt.map( - descriptor -> - Resolution.match( - Match.exact(descriptor, () -> methodSelectors(clazz)))) - .orElse(Resolution.unresolved()); - } else { - return Resolution.unresolved(); - } - } - - @Override - public Resolution resolve(MethodSelector selector, Context context) { - var methodName = selector.getMethodName(); - - var opt = - context.addToParent( - parent -> { - RandomizedTestDescriptor method = - new RandomizedTestDescriptor( - parent.getUniqueId().append("method", methodName), - methodName, - TestDescriptor.Type.TEST); - method.source = Optional.of(MethodSource.from(selector.getJavaMethod())); - return Optional.of(method); - }); - - return opt.map(desc -> Resolution.match(Match.exact(desc))) - .orElse(Resolution.unresolved()); - } - - private Set methodSelectors(Class testClass) { - var methods = - findMethods(testClass, new Predicates.IsTestableMethod(true)).stream() - .map(method -> DiscoverySelectors.selectMethod(testClass, method)) - .collect( - toCollection((Supplier>) LinkedHashSet::new)); - return methods; - } - }) - .addSelectorResolver(new SelectorResolver() {}) - .build(); - - @Override - public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { - var engineDescriptor = - new RandomizedTestDescriptor( - UniqueId.forEngine(getId()), getId(), TestDescriptor.Type.CONTAINER); - - resolver.resolve(discoveryRequest, engineDescriptor); - - return engineDescriptor; - } - - @Override - public void execute(ExecutionRequest request) { - var listener = request.getEngineExecutionListener(); - process(listener, request.getRootTestDescriptor()); - } - - private void process(EngineExecutionListener listener, TestDescriptor node) { - listener.executionStarted(node); - if (node.isContainer()) { - for (var v : node.getChildren()) { - process(listener, v); - } - } - listener.executionFinished(node, TestExecutionResult.successful()); - } - - public static class RandomizedContext implements EngineExecutionContext {} - - private static class RandomizedTestDescriptor extends AbstractTestDescriptor - implements Node { - - private final Type type; - Optional source = Optional.empty(); - - protected RandomizedTestDescriptor(UniqueId uniqueId, String displayName, Type type) { - super(uniqueId, displayName); - this.type = type; - } - - @Override - public Optional getSource() { - return source; - } - - @Override - public Type getType() { - return type; - } - - @Override - public RandomizedContext execute( - RandomizedContext context, DynamicTestExecutor dynamicTestExecutor) throws Exception { - System.out.println("Execute: " + this.getUniqueId()); - return Node.super.execute(context, dynamicTestExecutor); - } - } -} diff --git a/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/ExtensionExecutionContext.java b/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/ExtensionExecutionContext.java new file mode 100644 index 00000000..d2858870 --- /dev/null +++ b/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/ExtensionExecutionContext.java @@ -0,0 +1,80 @@ +package com.carrotsearch.randomizedtesting.extensions; + +import com.carrotsearch.randomizedtesting.api.RandomizedContext; +import org.junit.jupiter.api.extension.ExtensionContext; + +import java.util.ArrayDeque; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicLong; + +public class ExtensionExecutionContext { + /** + * A sequencer for affecting the initial seed in case of rapid succession of this class instance + * creations. Not likely, but can happen two could get the same seed. + */ + private static final AtomicLong sequencer = new AtomicLong(); + + private final List seedList; + private final ArrayDeque> contextStack = new ArrayDeque<>(); + + public ExtensionExecutionContext(List seedList) { + assert seedList.size() >= 1; + this.seedList = seedList; + } + + public void pop(ExtensionContext ctx) { + var key = getKey(ctx); + if (contextStack.isEmpty() || !contextStack.peekLast().getKey().equals(key)) { + throw new AssertionError("No context or incorrect context for key: " + key); + } + contextStack.removeLast(); + } + + private String getKey(ExtensionContext ctx) { + return ctx.getUniqueId(); + } + + public RandomizedContext getContext(ExtensionContext ctx) { + var key = getKey(ctx); + if (contextStack.isEmpty() || !contextStack.peekLast().getKey().equals(key)) { + throw new AssertionError("No context or incorrect context for key: " + key); + } + return contextStack.peekLast().getValue(); + } + + public void push(ExtensionContext extensionContext) { + RandomizedContext ctx; + var forThread = Thread.currentThread(); + var key = getKey(extensionContext); + + if (contextStack.isEmpty()) { + ctx = + new RandomizedContext( + forThread, Objects.requireNonNull(seedAtLevel(extensionContext, 0))); + } else { + var forcedSeed = seedAtLevel(extensionContext, contextStack.size()); + var last = contextStack.peekLast(); + + ctx = + last.getValue() + .fork( + forThread, + seed -> forcedSeed != null ? forcedSeed.value : seed ^ Hashing.longHash(key)); + } + + contextStack.addLast(Map.entry(key, ctx)); + } + + private RandomSeed seedAtLevel(ExtensionContext context, int index) { + if (index >= seedList.size()) { + return null; + } + var seed = seedList.get(index); + if (seed == SeedChain.WILDCARD) { + seed = new RandomSeed(Hashing.mix64(sequencer.incrementAndGet() + System.nanoTime())); + } + return seed; + } +} diff --git a/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/Hashing.java b/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/Hashing.java new file mode 100644 index 00000000..321b983b --- /dev/null +++ b/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/Hashing.java @@ -0,0 +1,22 @@ +package com.carrotsearch.randomizedtesting.extensions; + +public class Hashing { + public static long mix64(long k) { + k ^= k >>> 33; + k *= 0xff51afd7ed558ccdL; + k ^= k >>> 33; + k *= 0xc4ceb9fe1a85ec53L; + k ^= k >>> 33; + return k; + } + + /** String hash function redistributing over a long range. */ + public static long longHash(String v) { + long h = 0; + int length = v.length(); + for (int i = 0; i < length; i++) { + h = 31 * h + v.charAt(i); + } + return mix64(h); + } +} diff --git a/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/InitialSeed.java b/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/InitialSeed.java new file mode 100644 index 00000000..d26f71b9 --- /dev/null +++ b/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/InitialSeed.java @@ -0,0 +1,14 @@ +package com.carrotsearch.randomizedtesting.extensions; + +import java.util.List; + +public class InitialSeed { + public static List compute() { + final String propertySeed = System.getProperties().getProperty(SysProps.TESTS_SEED); + if (propertySeed != null) { + return SeedChain.parse(propertySeed); + } else { + return List.of(SeedChain.WILDCARD); + } + } +} diff --git a/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/RandomSeed.java b/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/RandomSeed.java new file mode 100644 index 00000000..950f88ef --- /dev/null +++ b/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/RandomSeed.java @@ -0,0 +1,22 @@ +package com.carrotsearch.randomizedtesting.extensions; + +public class RandomSeed { + private static final char[] HEX = "0123456789ABCDEF".toCharArray(); + + public final long value; + + public RandomSeed(long seed) { + this.value = seed; + } + + @Override + public String toString() { + long seed = value; + StringBuilder b = new StringBuilder(); + do { + b.append(HEX[(int) (seed & 0xF)]); + seed = seed >>> 4; + } while (seed != 0); + return b.reverse().toString(); + } +} diff --git a/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/RandomizedContextProviderExtension.java b/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/RandomizedContextProviderExtension.java new file mode 100644 index 00000000..13afa9a3 --- /dev/null +++ b/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/RandomizedContextProviderExtension.java @@ -0,0 +1,110 @@ +package com.carrotsearch.randomizedtesting.extensions; + +import com.carrotsearch.randomizedtesting.api.RandomizedContext; +import org.junit.jupiter.api.extension.AfterAllCallback; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.api.extension.ParameterResolutionException; +import org.junit.jupiter.api.extension.ParameterResolver; +import org.junit.jupiter.api.extension.TestInstanceFactory; +import org.junit.jupiter.api.extension.TestInstanceFactoryContext; +import org.junit.jupiter.api.extension.TestInstancePreDestroyCallback; +import org.junit.jupiter.api.extension.TestInstantiationException; +import org.junit.platform.commons.util.ReflectionUtils; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +public class RandomizedContextProviderExtension + implements TestInstanceFactory, + TestInstancePreDestroyCallback, + // InvocationInterceptor, + ParameterResolver, + BeforeAllCallback, + BeforeEachCallback, + AfterEachCallback, + AfterAllCallback { + private static final String KEY_EXECUTION_CONTEXT = ExtensionExecutionContext.class.getName(); + + @Override + public Object createTestInstance( + TestInstanceFactoryContext tiCtx, ExtensionContext extensionContext) + throws TestInstantiationException { + Constructor constructor = ReflectionUtils.getDeclaredConstructor(tiCtx.getTestClass()); + try { + getExecutionContext(extensionContext).push(extensionContext); + return constructor.newInstance(); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { + throw new TestInstantiationException( + "Could not instantiate class: " + tiCtx.getTestClass().getName(), e); + } + } + + @Override + public void preDestroyTestInstance(ExtensionContext extensionContext) throws Exception { + getExecutionContext(extensionContext).pop(extensionContext); + } + + @Override + public void beforeAll(ExtensionContext extensionContext) { + var classStore = getClassExtensionStore(extensionContext); + assert classStore.get(KEY_EXECUTION_CONTEXT) == null; + + var executionContext = new ExtensionExecutionContext(InitialSeed.compute()); + classStore.put(KEY_EXECUTION_CONTEXT, executionContext); + + executionContext.push(extensionContext); + } + + @Override + public void afterAll(ExtensionContext extensionContext) { + var classStore = getClassExtensionStore(extensionContext); + assert classStore.get(KEY_EXECUTION_CONTEXT) != null; + var executionContext = + classStore.remove(KEY_EXECUTION_CONTEXT, ExtensionExecutionContext.class); + executionContext.pop(extensionContext); + } + + @Override + public void beforeEach(ExtensionContext extensionContext) { + getExecutionContext(extensionContext).push(extensionContext); + } + + @Override + public void afterEach(ExtensionContext extensionContext) { + getExecutionContext(extensionContext).pop(extensionContext); + } + + @Override + public boolean supportsParameter( + ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { + return parameterContext.getParameter().getType().equals(RandomizedContext.class) + && getExecutionContext(extensionContext) != null; + } + + @Override + public RandomizedContext resolveParameter( + ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { + return getRandomizedContext(extensionContext); + } + + private RandomizedContext getRandomizedContext(ExtensionContext extensionContext) { + return getExecutionContext(extensionContext).getContext(extensionContext); + } + + private ExtensionContext.Store getClassExtensionStore(ExtensionContext extensionContext) { + return extensionContext.getStore( + ExtensionContext.Namespace.create( + RandomizedContextProviderExtension.class, extensionContext.getRequiredTestClass())); + } + + private ExtensionExecutionContext getExecutionContext(ExtensionContext extensionContext) { + var classStore = getClassExtensionStore(extensionContext); + return classStore.get(KEY_EXECUTION_CONTEXT, ExtensionExecutionContext.class); + } +} diff --git a/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/SeedChain.java b/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/SeedChain.java new file mode 100644 index 00000000..989ef0c1 --- /dev/null +++ b/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/SeedChain.java @@ -0,0 +1,57 @@ +package com.carrotsearch.randomizedtesting.extensions; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class SeedChain { + static final RandomSeed WILDCARD = new RandomSeed(0L); + + private final ArrayList seeds; + + public SeedChain(ArrayList seeds) { + this.seeds = seeds; + } + + public static List parse(String chain) { + chain = chain.replaceAll("[\\[\\]]", ""); + + String[] splits = chain.split("[:]"); + + RandomSeed[] seeds = new RandomSeed[splits.length]; + for (int i = 0; i < splits.length; i++) { + if (!splits[i].matches("[0-9A-Fa-f]+|[*]")) { + throw new IllegalArgumentException( + "Invalid component \"" + splits[i] + "\" in seed chain: " + chain); + } + seeds[i] = parseSeed(splits[i]); + } + return Arrays.asList(seeds); + } + + private static RandomSeed parseSeed(String component) { + if (component.equals("*")) { + return WILDCARD; + } else { + long result = 0; + for (char chr : component.toCharArray()) { + chr = Character.toLowerCase(chr); + result = result << 4; + if (chr >= '0' && chr <= '9') result |= (chr - '0'); + else if (chr >= 'a' && chr <= 'f') result |= (chr - 'a' + 10); + else throw new IllegalArgumentException("Expected hexadecimal seed: " + component); + } + return new RandomSeed(result); + } + } + + @Override + public String toString() { + return "[" + + seeds.stream() + .map(v -> v == WILDCARD ? "*" : v.toString()) + .collect(Collectors.joining(":")) + + "]"; + } +} diff --git a/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/SysProps.java b/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/SysProps.java new file mode 100644 index 00000000..a44e70d6 --- /dev/null +++ b/core/src/main/java/com/carrotsearch/randomizedtesting/extensions/SysProps.java @@ -0,0 +1,5 @@ +package com.carrotsearch.randomizedtesting.extensions; + +public class SysProps { + public static final String TESTS_SEED = "tests.seed"; +} diff --git a/core/src/main/java/com/carrotsearch/randomizedtesting/internal/Threads.java b/core/src/main/java/com/carrotsearch/randomizedtesting/internal/Threads.java new file mode 100644 index 00000000..fa2c21a9 --- /dev/null +++ b/core/src/main/java/com/carrotsearch/randomizedtesting/internal/Threads.java @@ -0,0 +1,19 @@ +package com.carrotsearch.randomizedtesting.internal; + +public final class Threads { + Threads() {} + + /** Collect thread information, JVM vendor insensitive. */ + public static String threadName(Thread t) { + return "Thread[" + + ("id=" + t.getId()) + + (", name=" + t.getName()) + + (", state=" + t.getState()) + + (", group=" + groupName(t.getThreadGroup())) + + "]"; + } + + private static String groupName(ThreadGroup threadGroup) { + return threadGroup == null ? "{null group}" : threadGroup.getName(); + } +} diff --git a/core/src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine b/core/src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine deleted file mode 100644 index b092e74b..00000000 --- a/core/src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine +++ /dev/null @@ -1 +0,0 @@ -com.carrotsearch.randomizedtesting.engine.RandomizedTestingEngine \ No newline at end of file diff --git a/core/src/test/java/com/carrotsearch/randomizedtesting/Junit5SanityCheckTest.java b/core/src/test/java/com/carrotsearch/randomizedtesting/Junit5SanityCheckTest.java deleted file mode 100644 index 0d759a06..00000000 --- a/core/src/test/java/com/carrotsearch/randomizedtesting/Junit5SanityCheckTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.carrotsearch.randomizedtesting; - -import org.junit.jupiter.api.Test; - -public class Junit5SanityCheckTest { - @Test - public void testPassing() { - // Ok. - System.out.println("Passing."); - } - - @Test - public void testFailingOnAssertion() { - System.out.println("failingOnAssertion"); - assert false : "Failing."; - } - - @Test - public void testFailingWithException() { - System.out.println("failingWithException"); - throw new RuntimeException("Failing with exception."); - } -} diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts new file mode 100644 index 00000000..a88309ef --- /dev/null +++ b/examples/build.gradle.kts @@ -0,0 +1,8 @@ +plugins { + id("java-library") +} + +dependencies { + testImplementation(project(":core")) + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.2") +} \ No newline at end of file diff --git a/examples/src/test/java/com/carrotsearch/randomizedtesting/examples/Test001SimpleUseCase.java b/examples/src/test/java/com/carrotsearch/randomizedtesting/examples/Test001SimpleUseCase.java new file mode 100644 index 00000000..a57fa5f5 --- /dev/null +++ b/examples/src/test/java/com/carrotsearch/randomizedtesting/examples/Test001SimpleUseCase.java @@ -0,0 +1,62 @@ +package com.carrotsearch.randomizedtesting.examples; + +import com.carrotsearch.randomizedtesting.api.Randomized; +import com.carrotsearch.randomizedtesting.api.RandomizedContext; +import com.carrotsearch.randomizedtesting.extensions.RandomizedContextProviderExtension; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.util.Locale; + +@ExtendWith({RandomizedContextProviderExtension.class}) +public class Test001SimpleUseCase { + + @BeforeAll + public static void beforeAll1(RandomizedContext context) { + log("BeforeAll1", context); + } + + private static void log(String prefix, RandomizedContext context) { + System.out.printf( + Locale.ROOT, + "prefix: %15s, %016x %s%n", + prefix, + context.getRandom().nextLong(), + context.getSeedChain()); + } + + @BeforeAll + public static void beforeAll2(RandomizedContext context) { + log("BeforeAll2", context); + } + + public Test001SimpleUseCase() { + //log(" Constructor", context); + } + + @BeforeEach + public void beforeEach(RandomizedContext context) { + log(" BeforeEach", context); + } + + @AfterEach + public void afterEach(RandomizedContext context) { + log(" AfterEach", context); + } + + @Randomized + @Test + public void testMethod1(RandomizedContext context) { + log(" Method1", context); + } + + @Randomized + @RepeatedTest(10) + public void testMethod2(RandomizedContext context) { + log(" Method2", context); + } +} diff --git a/gradle/ide/idea.gradle b/gradle/ide/idea.gradle new file mode 100644 index 00000000..b9101702 --- /dev/null +++ b/gradle/ide/idea.gradle @@ -0,0 +1,47 @@ + +// Try to detect IntelliJ model loader early. +rootProject.ext { + isIdea = System.getProperty("idea.active") != null || + gradle.startParameter.taskNames.contains('idea') || + gradle.startParameter.taskNames.contains('cleanIdea') + + if (isIdea) { + logger.lifecycle("IntelliJ Idea IDE detected.") + } +} + +// Apply intellij plugin to all projects. +allprojects { + apply plugin: 'idea' + + idea { + module { + outputDir file('build/idea/classes/main') + testOutputDir file('build/idea/classes/test') + downloadSources = true + } + } +} + +// GH-37: skip certain long tasks if we're building within IntelliJ. +// +// The exception is when we're launching something - then it's very likely +// we'll need to build packages from scratch. +if (rootProject.isIdea && !rootProject.properties.keySet().any {it.startsWith("intellij.launch") }) { + gradle.taskGraph.whenReady { taskGraph -> + def tasks = taskGraph.getAllTasks() + + def skipTasks = [ + // Skip WAR or ZIP assembly. + ".*:(war|zip)" + ] + + tasks.each { task -> + def taskPath = task.path + if (skipTasks.any {pattern -> taskPath ==~ pattern}) { + logger.debug("Skipping task on IntelliJ: " + taskPath) + task.enabled = false + } + } + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index cedc5f80..3a343824 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,4 @@ rootProject.name = "randomizedtesting" -include("core") \ No newline at end of file +include("core") +include("examples") \ No newline at end of file