/src/libavif/tests/gtest/avif_fuzztest_enc_dec.cc
Line | Count | Source |
1 | | // Copyright 2022 Google LLC |
2 | | // SPDX-License-Identifier: BSD-2-Clause |
3 | | |
4 | | #include <array> |
5 | | #include <cstdint> |
6 | | #include <cstring> |
7 | | #include <memory> |
8 | | #include <vector> |
9 | | |
10 | | #include "avif/avif.h" |
11 | | #include "avif_fuzztest_helpers.h" |
12 | | #include "aviftest_helpers.h" |
13 | | #include "fuzztest/fuzztest.h" |
14 | | #include "gtest/gtest.h" |
15 | | |
16 | | namespace avif { |
17 | | namespace testutil { |
18 | | namespace { |
19 | | |
20 | | void CheckGainMapMetadataMatches(const avifGainMap& actual, |
21 | 696 | const avifGainMap& expected) { |
22 | 696 | EXPECT_EQ(actual.baseHdrHeadroom.n, expected.baseHdrHeadroom.n); |
23 | 696 | EXPECT_EQ(actual.baseHdrHeadroom.d, expected.baseHdrHeadroom.d); |
24 | 696 | EXPECT_EQ(actual.alternateHdrHeadroom.n, expected.alternateHdrHeadroom.n); |
25 | 696 | EXPECT_EQ(actual.alternateHdrHeadroom.d, expected.alternateHdrHeadroom.d); |
26 | 2.78k | for (int c = 0; c < 3; ++c) { |
27 | 2.08k | SCOPED_TRACE(c); |
28 | 2.08k | EXPECT_EQ(actual.baseOffset[c].n, expected.baseOffset[c].n); |
29 | 2.08k | EXPECT_EQ(actual.baseOffset[c].d, expected.baseOffset[c].d); |
30 | 2.08k | EXPECT_EQ(actual.alternateOffset[c].n, expected.alternateOffset[c].n); |
31 | 2.08k | EXPECT_EQ(actual.alternateOffset[c].d, expected.alternateOffset[c].d); |
32 | 2.08k | EXPECT_EQ(actual.gainMapGamma[c].n, expected.gainMapGamma[c].n); |
33 | 2.08k | EXPECT_EQ(actual.gainMapGamma[c].d, expected.gainMapGamma[c].d); |
34 | 2.08k | EXPECT_EQ(actual.gainMapMin[c].n, expected.gainMapMin[c].n); |
35 | 2.08k | EXPECT_EQ(actual.gainMapMin[c].d, expected.gainMapMin[c].d); |
36 | 2.08k | EXPECT_EQ(actual.gainMapMax[c].n, expected.gainMapMax[c].n); |
37 | 2.08k | EXPECT_EQ(actual.gainMapMax[c].d, expected.gainMapMax[c].d); |
38 | 2.08k | } |
39 | 696 | } |
40 | | |
41 | 8.99k | void EncodeDecodeValid(ImagePtr image, EncoderPtr encoder, DecoderPtr decoder) { |
42 | 8.99k | ImagePtr decoded_image(avifImageCreateEmpty()); |
43 | 8.99k | ASSERT_NE(image.get(), nullptr); |
44 | 8.99k | ASSERT_NE(encoder.get(), nullptr); |
45 | 8.99k | ASSERT_NE(decoder.get(), nullptr); |
46 | 8.99k | ASSERT_NE(decoded_image.get(), nullptr); |
47 | | |
48 | 8.99k | AvifRwData encoded_data; |
49 | 8.99k | const avifResult encoder_result = |
50 | 8.99k | avifEncoderWrite(encoder.get(), image.get(), &encoded_data); |
51 | 17.9k | ASSERT_EQ(encoder_result, AVIF_RESULT_OK) |
52 | 17.9k | << avifResultToString(encoder_result) << ": " << encoder->diag.error; |
53 | | |
54 | 8.99k | const avifResult decoder_result = avifDecoderReadMemory( |
55 | 8.99k | decoder.get(), decoded_image.get(), encoded_data.data, encoded_data.size); |
56 | 17.9k | ASSERT_EQ(decoder_result, AVIF_RESULT_OK) |
57 | 17.9k | << avifResultToString(decoder_result) << ": " << decoder->diag.error; |
58 | | |
59 | 8.99k | EXPECT_EQ(decoded_image->width, image->width); |
60 | 8.99k | EXPECT_EQ(decoded_image->height, image->height); |
61 | 8.99k | EXPECT_EQ(decoded_image->depth, image->depth); |
62 | 8.99k | EXPECT_EQ(decoded_image->yuvFormat, image->yuvFormat); |
63 | | |
64 | 8.99k | EXPECT_EQ(decoded_image->gainMap != nullptr, image->gainMap != nullptr); |
65 | 8.99k | if (decoded_image->gainMap != nullptr && |
66 | 1.07k | (decoder->imageContentToDecode & AVIF_IMAGE_CONTENT_GAIN_MAP)) { |
67 | 696 | ASSERT_NE(decoded_image->gainMap->image, nullptr); |
68 | 696 | EXPECT_EQ(decoded_image->gainMap->image->width, |
69 | 696 | image->gainMap->image->width); |
70 | 696 | EXPECT_EQ(decoded_image->gainMap->image->height, |
71 | 696 | image->gainMap->image->height); |
72 | 696 | EXPECT_EQ(decoded_image->gainMap->image->depth, |
73 | 696 | image->gainMap->image->depth); |
74 | 696 | EXPECT_EQ(decoded_image->gainMap->image->yuvFormat, |
75 | 696 | image->gainMap->image->yuvFormat); |
76 | 696 | EXPECT_EQ(image->gainMap->image->gainMap, nullptr); |
77 | 696 | EXPECT_EQ(decoded_image->gainMap->image->alphaPlane, nullptr); |
78 | | |
79 | 696 | CheckGainMapMetadataMatches(*decoded_image->gainMap, *image->gainMap); |
80 | 696 | } |
81 | | |
82 | | // Verify that an opaque input leads to an opaque output. |
83 | 8.99k | if (avifImageIsOpaque(image.get())) { |
84 | 5.88k | EXPECT_TRUE(avifImageIsOpaque(decoded_image.get())); |
85 | 5.88k | } |
86 | | // A transparent image may be heavily compressed to an opaque image. This is |
87 | | // hard to verify so do not check it. |
88 | 8.99k | } |
89 | | |
90 | | FUZZ_TEST(EncodeDecodeAvifFuzzTest, EncodeDecodeValid) |
91 | | .WithDomains(fuzztest::OneOf(ArbitraryAvifImage(), |
92 | | ArbitraryAvifImageWithGainMap()), |
93 | | ArbitraryAvifEncoder(), ArbitraryAvifDecoder()); |
94 | | |
95 | | } // namespace |
96 | | } // namespace testutil |
97 | | } // namespace avif |