diff options
Diffstat (limited to 'src/test/java/com/code_intelligence/jazzer/mutation/mutator/lang/ByteArrayMutatorTest.java')
-rw-r--r-- | src/test/java/com/code_intelligence/jazzer/mutation/mutator/lang/ByteArrayMutatorTest.java | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/src/test/java/com/code_intelligence/jazzer/mutation/mutator/lang/ByteArrayMutatorTest.java b/src/test/java/com/code_intelligence/jazzer/mutation/mutator/lang/ByteArrayMutatorTest.java new file mode 100644 index 00000000..1592b17d --- /dev/null +++ b/src/test/java/com/code_intelligence/jazzer/mutation/mutator/lang/ByteArrayMutatorTest.java @@ -0,0 +1,189 @@ +/* + * Copyright 2023 Code Intelligence GmbH + * + * 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.code_intelligence.jazzer.mutation.mutator.lang; + +import static com.code_intelligence.jazzer.mutation.support.TestSupport.mockPseudoRandom; +import static com.google.common.truth.Truth.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import com.code_intelligence.jazzer.mutation.annotation.NotNull; +import com.code_intelligence.jazzer.mutation.annotation.WithLength; +import com.code_intelligence.jazzer.mutation.api.SerializingMutator; +import com.code_intelligence.jazzer.mutation.mutator.libfuzzer.LibFuzzerMutator; +import com.code_intelligence.jazzer.mutation.support.TestSupport.MockPseudoRandom; +import com.code_intelligence.jazzer.mutation.support.TypeHolder; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +@SuppressWarnings({"unchecked", "ResultOfMethodCallIgnored"}) +public class ByteArrayMutatorTest { + /** + * Some tests may set {@link LibFuzzerMutator#MOCK_SIZE_KEY} which can interfere with other tests + * unless cleared. + */ + @AfterEach + void cleanMockSize() { + System.clearProperty(LibFuzzerMutator.MOCK_SIZE_KEY); + } + + @Test + void testBasicFunction() { + SerializingMutator<byte[]> mutator = + (SerializingMutator<byte[]>) LangMutators.newFactory().createOrThrow( + new TypeHolder<byte[]>() {}.annotatedType()); + assertThat(mutator.toString()).isEqualTo("Nullable<byte[]>"); + + byte[] arr; + try (MockPseudoRandom prng = mockPseudoRandom(false, 5, new byte[] {1, 2, 3, 4, 5})) { + arr = mutator.init(prng); + } + assertThat(arr).isEqualTo(new byte[] {1, 2, 3, 4, 5}); + + System.setProperty(LibFuzzerMutator.MOCK_SIZE_KEY, "10"); + try (MockPseudoRandom prng = mockPseudoRandom(false)) { + arr = mutator.mutate(arr, prng); + } + assertThat(arr).isEqualTo(new byte[] {2, 4, 6, 8, 10, 6, 7, 8, 9, 10}); + } + + @Test + void testMaxLength() { + SerializingMutator<byte[]> mutator = + (SerializingMutator<byte[]>) LangMutators.newFactory().createOrThrow( + new TypeHolder<byte @NotNull @WithLength(max = 10)[]>() {}.annotatedType()); + assertThat(mutator.toString()).isEqualTo("byte[]"); + + byte[] arr; + try (MockPseudoRandom prng = mockPseudoRandom(8, new byte[] {1, 2, 3, 4, 5, 6, 7, 8})) { + arr = mutator.init(prng); + } + assertThat(arr).isEqualTo(new byte[] {1, 2, 3, 4, 5, 6, 7, 8}); + + System.setProperty(LibFuzzerMutator.MOCK_SIZE_KEY, "11"); + try (MockPseudoRandom prng = mockPseudoRandom()) { + // the ByteArrayMutator will limit the maximum size of the data requested from libfuzzer to + // WithLength::max so setting the mock mutator to make it bigger will cause an exception + assertThrows(ArrayIndexOutOfBoundsException.class, () -> { mutator.mutate(arr, prng); }); + } + } + + @Test + void testMaxLengthInitClamp() { + SerializingMutator<byte[]> mutator = + (SerializingMutator<byte[]>) LangMutators.newFactory().createOrThrow( + new TypeHolder<byte @NotNull @WithLength(max = 5)[]>() {}.annotatedType()); + assertThat(mutator.toString()).isEqualTo("byte[]"); + + try (MockPseudoRandom prng = mockPseudoRandom(10)) { + // init will call closedRange(min, max) and the mock prng will assert that the given value + // above is between those values which we want to fail here to show that we're properly + // clamping the range + assertThrows(AssertionError.class, () -> { mutator.init(prng); }); + } + } + + @Test + void testMinLengthInitClamp() { + SerializingMutator<byte[]> mutator = + (SerializingMutator<byte[]>) LangMutators.newFactory().createOrThrow( + new TypeHolder<byte @NotNull @WithLength(min = 5)[]>() {}.annotatedType()); + assertThat(mutator.toString()).isEqualTo("byte[]"); + + try (MockPseudoRandom prng = mockPseudoRandom(3)) { + // init will call closedrange(min, max) and the mock prng will assert that the given value + // above is between those values which we want to fail here to show that we're properly + // clamping the range + assertThrows(AssertionError.class, () -> { mutator.init(prng); }); + } + } + + @Test + void testMinLength() { + SerializingMutator<byte[]> mutator = + (SerializingMutator<byte[]>) LangMutators.newFactory().createOrThrow( + new TypeHolder<byte @NotNull @WithLength(min = 5)[]>() {}.annotatedType()); + assertThat(mutator.toString()).isEqualTo("byte[]"); + + byte[] arr; + try (MockPseudoRandom prng = mockPseudoRandom(10, new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})) { + arr = mutator.init(prng); + } + assertThat(arr).hasLength(10); + + System.setProperty(LibFuzzerMutator.MOCK_SIZE_KEY, "3"); + + try (MockPseudoRandom prng = mockPseudoRandom()) { + arr = mutator.mutate(arr, prng); + } + assertThat(arr).hasLength(5); + assertThat(arr).isEqualTo(new byte[] {2, 4, 6, 0, 0}); + } + + @Test + void testCrossOver() { + SerializingMutator<byte[]> mutator = + (SerializingMutator<byte[]>) LangMutators.newFactory().createOrThrow( + new TypeHolder<byte @NotNull[]>() {}.annotatedType()); + assertThat(mutator.toString()).isEqualTo("byte[]"); + + byte[] value = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + byte[] otherValue = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + + byte[] crossedOver; + try (MockPseudoRandom prng = mockPseudoRandom( + // intersect arrays + 0, + // out length + 8, + // copy 3 from first + 3, + // copy 1 from second + 1, + // copy 1 from first, + 1, + // copy 3 from second + 3)) { + crossedOver = mutator.crossOver(value, otherValue, prng); + assertThat(crossedOver).isEqualTo(new byte[] {0, 1, 2, 10, 3, 11, 12, 13}); + } + + try (MockPseudoRandom prng = mockPseudoRandom( + // insert into action + 1, + // copy size + 3, + // from position + 5, + // to position + 2)) { + crossedOver = mutator.crossOver(value, otherValue, prng); + assertThat(crossedOver).isEqualTo(new byte[] {0, 1, 15, 16, 17, 2, 3, 4, 5, 6, 7, 8, 9}); + } + + try (MockPseudoRandom prng = mockPseudoRandom( + // overwrite action + 2, + // to position + 3, + // copy size + 3, + // from position + 4)) { + crossedOver = mutator.crossOver(value, otherValue, prng); + assertThat(crossedOver).isEqualTo(new byte[] {0, 1, 2, 14, 15, 16, 6, 7, 8, 9}); + } + } +} |