xref: /aosp_15_r20/external/jazzer-api/src/main/java/com/code_intelligence/jazzer/mutation/api/MutatorFactory.java (revision 33edd6723662ea34453766bfdca85dbfdd5342b8)
1 /*
2  * Copyright 2023 Code Intelligence GmbH
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.code_intelligence.jazzer.mutation.api;
18 
19 import static com.code_intelligence.jazzer.mutation.support.Preconditions.require;
20 import static com.code_intelligence.jazzer.mutation.support.TypeSupport.asAnnotatedType;
21 import static java.lang.String.format;
22 
23 import com.google.errorprone.annotations.CheckReturnValue;
24 import java.lang.reflect.AnnotatedType;
25 import java.util.Optional;
26 
27 /**
28  * Instances of this class are not required to be thread safe, but are generally lightweight and can
29  * thus be created as needed.
30  */
31 public abstract class MutatorFactory {
canMutate(AnnotatedType type)32   public final boolean canMutate(AnnotatedType type) {
33     return tryCreate(type).isPresent();
34   }
35 
createOrThrow(Class<T> clazz)36   public final <T> SerializingMutator<T> createOrThrow(Class<T> clazz) {
37     return (SerializingMutator<T>) createOrThrow(asAnnotatedType(clazz));
38   }
39 
createOrThrow(AnnotatedType type)40   public final SerializingMutator<?> createOrThrow(AnnotatedType type) {
41     Optional<SerializingMutator<?>> maybeMutator = tryCreate(type);
42     require(maybeMutator.isPresent(), "Failed to create mutator for " + type);
43     return maybeMutator.get();
44   }
45 
createInPlaceOrThrow(AnnotatedType type)46   public final SerializingInPlaceMutator<?> createInPlaceOrThrow(AnnotatedType type) {
47     Optional<SerializingInPlaceMutator<?>> maybeMutator = tryCreateInPlace(type);
48     require(maybeMutator.isPresent(), "Failed to create mutator for " + type);
49     return maybeMutator.get();
50   }
51 
52   /**
53    * Tries to create a mutator for {@code type} and, if successful, asserts that it is an instance
54    * of {@link SerializingInPlaceMutator}.
55    */
tryCreateInPlace(AnnotatedType type)56   public final Optional<SerializingInPlaceMutator<?>> tryCreateInPlace(AnnotatedType type) {
57     return tryCreate(type).map(mutator -> {
58       require(mutator instanceof InPlaceMutator<?>,
59           format("Mutator for %s is not in-place: %s", type, mutator.getClass()));
60       return (SerializingInPlaceMutator<?>) mutator;
61     });
62   }
63 
64   @CheckReturnValue
tryCreate(AnnotatedType type)65   public final Optional<SerializingMutator<?>> tryCreate(AnnotatedType type) {
66     return tryCreate(type, this);
67   }
68 
69   /**
70    * Attempt to create a {@link SerializingMutator} for the given type.
71    *
72    * @param type the type to mutate
73    * @param factory the factory to use when creating submutators
74    * @return a {@link SerializingMutator} for the given {@code type}, or {@link Optional#empty()}
75    * if this factory can't create such mutators
76    */
77   @CheckReturnValue
tryCreate( AnnotatedType type, MutatorFactory factory)78   public abstract Optional<SerializingMutator<?>> tryCreate(
79       AnnotatedType type, MutatorFactory factory);
80 }
81