Skip to content

Commit

Permalink
chore: add overrides attribute to @LeakyHapiTest, remove `propert…
Browse files Browse the repository at this point in the history
…yPreservingHapiSpec()` (#14222)

Signed-off-by: Michael Tinker <[email protected]>
  • Loading branch information
tinker-michaelj authored Jul 13, 2024
1 parent 0b139b2 commit 2e9034b
Show file tree
Hide file tree
Showing 72 changed files with 6,634 additions and 7,706 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

package com.hedera.services.bdd.junit;

/**
* Enumerates reasons a {@link LeakyHapiTest} cannot be run concurrently with other tests.
*/
public enum ContextRequirement {
/**
* The test expects a predictable relationship between its created entity numbers,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2024 Hedera Hashgraph, LLC
*
* 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.hedera.services.bdd.junit;

import static com.hedera.services.bdd.junit.TestTags.EMBEDDED;
import static org.junit.jupiter.api.parallel.ResourceAccessMode.READ;

import com.hedera.services.bdd.junit.extensions.NetworkTargetingExtension;
import com.hedera.services.bdd.junit.extensions.SpecNamingExtension;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.parallel.ResourceLock;

/**
* Annotation for a {@link HapiTest} that can only be run in embedded mode. The {@link EmbeddedReason} annotation
* enumerates common reasons a test has to run in embedded mode.
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@TestFactory
@ExtendWith({NetworkTargetingExtension.class, SpecNamingExtension.class})
@ResourceLock(value = "NETWORK", mode = READ)
@Tag(EMBEDDED)
public @interface EmbeddedHapiTest {
/**
* The reasons the test has to run in embedded mode.
* @return the reasons the test has to run in embedded mode
*/
EmbeddedReason[] value();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2024 Hedera Hashgraph, LLC
*
* 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.hedera.services.bdd.junit;

/**
* Enumerates reasons a {@link LeakyHapiTest} cannot be run concurrently with other tests.
*/
public enum EmbeddedReason {
/**
* The test must skip the ingest workflow to submit its transactions, as they would always be rejected by
* a node in normal operations.
*/
MUST_SKIP_INGEST,
/**
* The test must directly access state to assert expectations that cannot be verified through the gRPC API.
*/
NEEDS_STATE_ACCESS,
/**
* The test manipulates the software version of the simulated consensus event for a transaction.
*/
MANIPULATES_EVENT_VERSION,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2024 Hedera Hashgraph, LLC
*
* 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.hedera.services.bdd.junit;

import static com.hedera.services.bdd.junit.TestTags.EMBEDDED;
import static org.junit.jupiter.api.parallel.ResourceAccessMode.READ_WRITE;

import com.hedera.services.bdd.junit.extensions.NetworkTargetingExtension;
import com.hedera.services.bdd.junit.extensions.SpecNamingExtension;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.parallel.ResourceLock;

/**
* Annotation for a {@link HapiTest} that can only be run in embedded mode, and not concurrently with other embedded
* tests. The {@link EmbeddedReason} attribute gives the reasons the test has to run in embedded mode. The
* {@link ContextRequirement} attribute gives the reasons the test cannot run concurrently.
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@TestFactory
@ExtendWith({NetworkTargetingExtension.class, SpecNamingExtension.class})
@ResourceLock(value = "NETWORK", mode = READ_WRITE)
@Tag(EMBEDDED)
public @interface LeakyEmbeddedHapiTest {
/**
* The reasons the test has to run in embedded mode.
* @return the reasons the test has to run in embedded mode
*/
EmbeddedReason[] reason();
/**
* The requirements preventing the test from running concurrently with other tests.
* @return the reasons the test cannot run concurrently with other tests
*/
ContextRequirement[] requirement() default {};
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,26 @@
* Annotation for a {@link HapiTest} that "leaks" side effects into the test context (or
* is permeable to such side effects itself). The {@link ContextRequirement} annotation
* enumerates common types of leakage and permeability.
* <p>
* If set, the {@link LeakyHapiTest#overrides()} field lists the names of properties that
* the test overrides and needs automatically restored to their original values after the test completes.
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@TestFactory
@ExtendWith({NetworkTargetingExtension.class, SpecNamingExtension.class})
@ResourceLock(value = "NETWORK", mode = READ_WRITE)
public @interface LeakyHapiTest {
ContextRequirement[] value() default {};
/**
* If set, the types of context requirements that the test is subject to.
* @return the context requirements
*/
ContextRequirement[] requirement() default {};

/**
* If set, the names of properties this test overrides and needs automatically
* restored to their original values after the test completes.
* @return the names of properties this test overrides
*/
String[] overrides() default {};
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@

import static org.junit.platform.commons.support.AnnotationSupport.isAnnotated;

import com.hedera.services.bdd.junit.EmbeddedHapiTest;
import com.hedera.services.bdd.junit.GenesisHapiTest;
import com.hedera.services.bdd.junit.HapiTest;
import com.hedera.services.bdd.junit.LeakyEmbeddedHapiTest;
import com.hedera.services.bdd.junit.LeakyHapiTest;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.lang.reflect.Method;
Expand All @@ -34,6 +36,8 @@ public static Optional<Method> hapiTestMethodOf(@NonNull final ExtensionContext
private static boolean isHapiTest(@NonNull final Method method) {
return isAnnotated(method, HapiTest.class)
|| isAnnotated(method, LeakyHapiTest.class)
|| isAnnotated(method, GenesisHapiTest.class);
|| isAnnotated(method, GenesisHapiTest.class)
|| isAnnotated(method, EmbeddedHapiTest.class)
|| isAnnotated(method, LeakyEmbeddedHapiTest.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@

import com.hedera.services.bdd.junit.GenesisHapiTest;
import com.hedera.services.bdd.junit.HapiTest;
import com.hedera.services.bdd.junit.LeakyHapiTest;
import com.hedera.services.bdd.junit.hedera.HederaNetwork;
import com.hedera.services.bdd.junit.hedera.embedded.EmbeddedNetwork;
import com.hedera.services.bdd.spec.HapiSpec;
import com.hedera.services.bdd.spec.keys.RepeatableKeyGenerator;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
Expand All @@ -52,12 +54,18 @@ public void beforeEach(@NonNull final ExtensionContext extensionContext) {
HapiSpec.TARGET_NETWORK.set(targetNetwork);
} else {
HapiSpec.TARGET_NETWORK.set(SHARED_NETWORK.get());
// If there are properties to preserve, bind that info to the thread before executing the test factory
if (isAnnotated(method, LeakyHapiTest.class)) {
HapiSpec.PROPERTIES_TO_PRESERVE.set(
List.of(method.getAnnotation(LeakyHapiTest.class).overrides()));
}
}
});
}

@Override
public void afterEach(@NonNull final ExtensionContext extensionContext) {
HapiSpec.TARGET_NETWORK.remove();
HapiSpec.PROPERTIES_TO_PRESERVE.remove();
}
}
Loading

0 comments on commit 2e9034b

Please sign in to comment.