1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15
16 /// @file fuzztest.h
17 /// Stubs for the FuzzTest interface
18 ///
19 /// @rst
20 /// .. warning::
21 /// This header depends on portions of the standard library that may not
22 /// supported on your device!
23 ///
24 /// This header provides stubs for the full FuzzTest interface, including
25 /// `macros`_ and `domains`_ that include C++ standard library `headers`_ that
26 /// are not permitted in Pigweed. It should only be used in downstream projects
27 /// that support the full standard library on both host and device. It should
28 /// never be used in core Pigweed.
29 ///
30 /// If possible, consider including ``pw_fuzzer/fuzztest.h`` instead.
31 ///
32 /// This header is included when FuzzTest is disabled, e.g. for GN, when
33 /// ``dir_pw_third_party_fuzztest`` or ``pw_toolchain_FUZZING_ENABLED`` are not
34 /// set. Otherwise, ``$dir_pw_third_party_fuzztest/fuzztest.h`` is used instead.
35 ///
36 /// .. _domains:
37 /// https://github.com/google/fuzztest/blob/main/doc/domains-reference.md
38 /// .. _headers: https://pigweed.dev/docs/style_guide.html#permitted-headers
39 /// .. _macros:
40 /// https://github.com/google/fuzztest/blob/main/doc/fuzz-test-macro.md
41 /// @endrst
42
43 #include <deque>
44 #include <list>
45 #include <map>
46 #include <memory>
47 #include <set>
48 #include <string>
49 #include <unordered_map>
50 #include <unordered_set>
51 #include <vector>
52
53 #include "pw_fuzzer/internal/fuzztest.h"
54
55 namespace fuzztest {
56
57 // This namespace is here only as a way to disable ADL (argument-dependent
58 // lookup). Names should be used from the fuzztest:: namespace.
59 namespace internal_no_adl {
60
61 template <typename T>
ElementOf(std::vector<T>)62 auto ElementOf(std::vector<T>) {
63 return internal::Domain<T>{};
64 }
65
String()66 inline auto String() { return Arbitrary<std::string>(); }
67
68 template <int&... ExplicitArgumentBarrier, typename T>
StringOf(internal::Domain<T> inner)69 inline auto StringOf(internal::Domain<T> inner) {
70 return ContainerOf<std::string>(std::move(inner));
71 }
72
AsciiString()73 inline auto AsciiString() { return StringOf(AsciiChar()); }
74
PrintableAsciiString()75 inline auto PrintableAsciiString() { return StringOf(PrintableAsciiChar()); }
76
77 template <template <typename> class Ptr,
78 int&... ExplicitArgumentBarrier,
79 typename T>
SmartPointerOf(internal::Domain<T>)80 auto SmartPointerOf(internal::Domain<T>) {
81 return internal::Domain<Ptr<T>>{};
82 }
83
84 template <int&... ExplicitArgumentBarrier, typename T>
UniquePtrOf(internal::Domain<T>)85 auto UniquePtrOf(internal::Domain<T>) {
86 return internal::Domain<std::unique_ptr<T>>{};
87 }
88
89 template <int&... ExplicitArgumentBarrier, typename T>
SharedPtrOf(internal::Domain<T>)90 auto SharedPtrOf(internal::Domain<T>) {
91 return internal::Domain<std::shared_ptr<T>>{};
92 }
93
94 template <int&... ExplicitArgumentBarrier, typename T>
VectorOf(internal::Domain<T> inner)95 auto VectorOf(internal::Domain<T> inner) {
96 return ContainerOf<std::vector<T>>(std::move(inner));
97 }
98
99 template <int&... ExplicitArgumentBarrier, typename T>
DequeOf(internal::Domain<T> inner)100 auto DequeOf(internal::Domain<T> inner) {
101 return ContainerOf<std::deque<T>>(std::move(inner));
102 }
103
104 template <int&... ExplicitArgumentBarrier, typename T>
ListOf(internal::Domain<T> inner)105 auto ListOf(internal::Domain<T> inner) {
106 return ContainerOf<std::list<T>>(std::move(inner));
107 }
108
109 template <int&... ExplicitArgumentBarrier, typename T>
SetOf(internal::Domain<T> inner)110 auto SetOf(internal::Domain<T> inner) {
111 return ContainerOf<std::set<T>>(std::move(inner));
112 }
113
114 template <int&... ExplicitArgumentBarrier, typename K, typename V>
MapOf(internal::Domain<K> keys,internal::Domain<V> values)115 auto MapOf(internal::Domain<K> keys, internal::Domain<V> values) {
116 return ContainerOf<std::map<K, V>>(
117 PairOf(std::move(keys), std::move(values)));
118 }
119
120 template <int&... ExplicitArgumentBarrier, typename T>
UnorderedSetOf(internal::Domain<T> inner)121 auto UnorderedSetOf(internal::Domain<T> inner) {
122 return ContainerOf<std::unordered_set<T>>(std::move(inner));
123 }
124
125 template <int&... ExplicitArgumentBarrier, typename K, typename V>
UnorderedMapOf(internal::Domain<K> keys,internal::Domain<V> values)126 auto UnorderedMapOf(internal::Domain<K> keys, internal::Domain<V> values) {
127 return ContainerOf<std::unordered_map<K, V>>(
128 PairOf(std::move(keys), std::move(values)));
129 }
130
131 template <typename T>
UniqueElementsVectorOf(internal::Domain<T> inner)132 auto UniqueElementsVectorOf(internal::Domain<T> inner) {
133 return VectorOf(std::move(inner));
134 }
135
136 template <typename P,
137 typename T = std::remove_cv_t<
138 std::remove_pointer_t<decltype(std::declval<P>()())>>>
ProtobufOf(P)139 auto ProtobufOf(P) {
140 return internal::Domain<std::unique_ptr<T>>{};
141 }
142
143 } // namespace internal_no_adl
144
145 // Inject the names from internal_no_adl into fuzztest, without allowing for
146 // ADL. Note that an `inline` namespace would not have this effect (ie it would
147 // still allow ADL to trigger).
148 using namespace internal_no_adl; // NOLINT
149
150 } // namespace fuzztest
151