FTXUI 7.0.0
C++ functional terminal UI.
Loading...
Searching...
No Matches
component_fuzzer.cpp
Go to the documentation of this file.
1// Copyright 2021 Arthur Sonzogni. All rights reserved.
2// Use of this source code is governed by the MIT license that can be found in
3// the LICENSE file.
4#include <cassert>
7#include <vector>
10
11using namespace ftxui;
12namespace {
13
14bool GeneratorBool(const char*& data, size_t& size) {
15 if (size == 0) {
16 return false;
17 }
18
19 auto out = bool(data[0] % 2);
20 data++;
21 size--;
22 return out;
23}
24
25std::string GeneratorString(const char*& data, size_t& size) {
26 int index = 0;
27 while (index < size && data[index]) {
28 ++index;
29 }
30
31 auto out = std::string(data, data + index);
32 data += index;
33 size -= index;
34
35 // The input component do not support invalid UTF8 yet.
36 try {
37 to_wstring(out);
38 } catch (...) {
39 return "0";
40 }
41 return std::move(out);
42}
43
44int GeneratorInt(const char* data, size_t size) {
45 if (size == 0) {
46 return 0;
47 }
48 auto out = int(data[0]);
49 data++;
50 size--;
51 return out;
52}
53
54Color GeneratorColor(const char* data, size_t size) {
55 return Color::RGB(GeneratorInt(data, size), GeneratorInt(data, size),
56 GeneratorInt(data, size));
57}
58
59AnimatedColorOption GeneratorAnimatedColorOption(const char* data,
60 size_t size) {
61 AnimatedColorOption option;
62 option.enabled = GeneratorBool(data, size);
63 option.inactive = GeneratorColor(data, size);
64 option.active = GeneratorColor(data, size);
65 option.duration = std::chrono::milliseconds(GeneratorInt(data, size));
66 return option;
67}
68
69AnimatedColorsOption GeneratorAnimatedColorsOptions(const char* data,
70 size_t size) {
71 AnimatedColorsOption option;
72 option.background = GeneratorAnimatedColorOption(data, size);
73 option.foreground = GeneratorAnimatedColorOption(data, size);
74 return option;
75}
76
77ButtonOption GeneratorButtonOption(const char* data, size_t size) {
78 ButtonOption option;
79 option.animated_colors = GeneratorAnimatedColorsOptions(data, size);
80 return option;
81}
82
83UnderlineOption GeneratorUnderlineOption(const char* data, size_t size) {
84 UnderlineOption option;
85 option.enabled = GeneratorBool(data, size);
86 option.color_active = GeneratorColor(data, size);
87 option.color_inactive = GeneratorColor(data, size);
88 option.leader_duration = std::chrono::milliseconds(GeneratorInt(data, size));
89 option.follower_duration =
90 std::chrono::milliseconds(GeneratorInt(data, size));
91 option.leader_delay = std::chrono::milliseconds(GeneratorInt(data, size));
92 option.follower_delay = std::chrono::milliseconds(GeneratorInt(data, size));
93 return option;
94}
95
96MenuEntryOption GeneratorMenuEntryOption(const char* data, size_t size) {
97 MenuEntryOption option;
98 option.animated_colors = GeneratorAnimatedColorsOptions(data, size);
99 return option;
100}
101
102MenuOption GeneratorMenuOption(const char* data, size_t size) {
103 MenuOption option;
104 option.underline = GeneratorUnderlineOption(data, size);
105 option.entries_option = GeneratorMenuEntryOption(data, size);
106 option.direction = static_cast<Direction>(GeneratorInt(data, size) % 4);
107 return option;
108}
109
110bool g_bool;
111int g_int;
112std::vector<std::string> g_list;
113
114Components GeneratorComponents(const char*& data, size_t& size, int depth);
115
116Component GeneratorComponent(const char*& data, size_t& size, int depth) {
117 depth--;
118 int value = GeneratorInt(data, size);
119 if (depth <= 0) {
120 return Button(GeneratorString(data, size), [] {});
121 }
122
123 constexpr int value_max = 26;
124 value = (value % value_max + value_max) % value_max;
125 switch (value) {
126 case 0:
127 return Button(
128 GeneratorString(data, size), [] {},
129 GeneratorButtonOption(data, size));
130 case 1:
131 return Checkbox(GeneratorString(data, size), &g_bool);
132 case 2:
133 return Input(GeneratorString(data, size), GeneratorString(data, size));
134 case 3:
135 return Menu(&g_list, &g_int, GeneratorMenuOption(data, size));
136 case 4:
137 return Radiobox(&g_list, &g_int);
138 case 5:
139 return Toggle(&g_list, &g_int);
140 case 6:
141 return Slider(GeneratorString(data, size), &g_int,
142 GeneratorInt(data, size), GeneratorInt(data, size),
143 GeneratorInt(data, size));
144 case 7:
145 return ResizableSplitLeft(GeneratorComponent(data, size, depth - 1),
146 GeneratorComponent(data, size, depth - 1),
147 &g_int);
148 case 8:
149 return ResizableSplitRight(GeneratorComponent(data, size, depth - 1),
150 GeneratorComponent(data, size, depth - 1),
151 &g_int);
152 case 9:
153 return ResizableSplitTop(GeneratorComponent(data, size, depth - 1),
154 GeneratorComponent(data, size, depth - 1),
155 &g_int);
156 case 10:
157 return ResizableSplitBottom(GeneratorComponent(data, size, depth - 1),
158 GeneratorComponent(data, size, depth - 1),
159 &g_int);
160 case 11:
161 return Container::Vertical(GeneratorComponents(data, size, depth - 1));
162
163 case 12:
164 return Container::Vertical(GeneratorComponents(data, size, depth - 1),
165 &g_int);
166
167 case 13:
168 return Container::Horizontal(GeneratorComponents(data, size, depth - 1));
169 case 14:
170 return Container::Horizontal(GeneratorComponents(data, size, depth - 1),
171 &g_int);
172 case 15:
173 return Container::Tab(GeneratorComponents(data, size, depth - 1), &g_int);
174 case 16:
175 return Maybe(GeneratorComponent(data, size, depth - 1), &g_bool);
176 case 17:
177 return Dropdown(&g_list, &g_int);
178 case 18:
179 return Collapsible(GeneratorString(data, size),
180 GeneratorComponent(data, size, depth - 1),
181 GeneratorBool(data, size));
182 case 19:
183 return Container::Stacked(GeneratorComponents(data, size, depth - 1));
184 case 20:
185 return MenuEntry(GeneratorString(data, size));
186 case 21:
187 return Renderer(GeneratorComponent(data, size, depth - 1),
188 [] { return text("hello"); });
189 case 22:
190 return CatchEvent(GeneratorComponent(data, size, depth - 1),
191 [](Event) { return true; });
192 case 23:
193 return Modal(GeneratorComponent(data, size, depth - 1),
194 GeneratorComponent(data, size, depth - 1), &g_bool);
195 case 24:
196 return Hoverable(GeneratorComponent(data, size, depth - 1), &g_bool);
197 case 25: {
198 WindowOptions options;
199 options.inner = GeneratorComponent(data, size, depth - 1);
200 options.title = GeneratorString(data, size);
201 return Window(options);
202 }
203 default:
204 assert(false);
205 }
206}
207
208Components GeneratorComponents(const char*& data, size_t& size, int depth) {
209 Components out;
210 if (depth > 0) {
211 while (size && GeneratorInt(data, size) % 2) {
212 out.push_back(GeneratorComponent(data, size, depth - 1));
213 }
214 }
215 return std::move(out);
216}
217
218} // namespace
219extern "C" int LLVMFuzzerTestOneInput(const char* data, size_t size) {
220 g_bool = GeneratorBool(data, size);
221 g_int = GeneratorInt(data, size);
222 g_list = {
223 "test_1", "test_2", "test_3", "test_4", "test_5",
224 };
225
226 int depth = 10;
227 auto component = GeneratorComponent(data, size, depth);
228
229 int width = GeneratorInt(data, size);
230 int height = GeneratorInt(data, size);
231
232 width %= 500;
233 width += 500;
234
235 height %= 500;
236 height += 500;
237
238 auto screen =
239 Screen::Create(Dimension::Fixed(width), Dimension::Fixed(height));
240
241 // Generate some events.
242 std::vector<Event> events;
243 auto parser =
244 TerminalInputParser([&](const Event& event) { events.push_back(event); });
245
246 for (size_t i = 0; i < size; ++i) {
247 parser.Add(data[i]);
248 }
249
250 for (const auto& event : events) {
251 component->OnEvent(event);
252 auto document = component->Render();
253 Render(screen, document);
254 }
255 return 0; // Non-zero return values are reserved for future use.
256}
int LLVMFuzzerTestOneInput(const char *data, size_t size)
Component Button(ConstStringRef label, std::function< void()> on_click, ButtonOption options=ButtonOption::Simple())
Draw a button. Execute a function when clicked.
Component ResizableSplitTop(Component main, Component back, int *main_size)
An vertical split in between two components, configurable using the mouse.
Component Toggle(ConstStringListRef entries, int *selected)
An horizontal list of elements. The user can navigate through them.
FTXUI_EXPORT(COMPONENT) ComponentDecorator Maybe(std Component Modal(Component main, Component modal, const bool *show_modal)
Definition modal.cpp:18
Component Renderer(Component child, std::function< Element()>)
Return a new Component, similar to |child|, but using |render| as the Component::Render() event.
Component Hoverable(Component component, bool *hover)
Wrap a component. Gives the ability to know if it is hovered by the mouse.
Definition hoverable.cpp:33
Component Checkbox(ConstStringRef label, bool *checked, CheckboxOption options=CheckboxOption::Simple())
Draw checkable element.
Component Window(WindowOptions option)
A draggeable / resizeable window. To use multiple of them, they must be stacked using Container::Stac...
Component Maybe(Component child, std::function< bool()> show)
Decorate a component |child|. It is shown only when |show| returns true.
Component ResizableSplitRight(Component main, Component back, int *main_size)
An horizontal split in between two components, configurable using the mouse.
Component Input(StringRef content, InputOption options={})
An input box for editing text.
Component Dropdown(ConstStringListRef entries, int *selected)
A dropdown menu.
Component Radiobox(ConstStringListRef entries, int *selected_, RadioboxOption options={})
A list of element, where only one can be selected.
Component ResizableSplitBottom(Component main, Component back, int *main_size)
An vertical split in between two components, configurable using the mouse.
Component Menu(ConstStringListRef entries, int *selected_, MenuOption options=MenuOption::Vertical())
A list of text. The focused element is selected.
Component ResizableSplitLeft(Component main, Component back, int *main_size)
An horizontal split in between two components, configurable using the mouse.
Component MenuEntry(ConstStringRef label, MenuEntryOption options={})
A specific menu entry. They can be put into a Container::Vertical to form a menu.
Element text(std::string_view text)
Display a piece of UTF8 encoded unicode text.
Decorator size(WidthOrHeight direction, Constraint constraint, int value)
Apply a constraint on the size of an element.
Direction
Direction is an enumeration that represents the four cardinal directions.
Definition direction.hpp:15
The FTXUI ftxui:: namespace.
Definition animation.hpp:11
std::vector< Component > Components
Component Collapsible(ConstStringRef label, Component child, Ref< bool > show=false)
A collapsible component. It displays a checkbox with an arrow. Once activated, the child is displayed...
Component Slider(SliderOption< T > options)
A slider in any direction.
FTXUI_EXPORT(SCREEN) std FTXUI_EXPORT(SCREEN) std std::wstring to_wstring(T s)
Definition string.hpp:18
void Render(Screen &screen, Node *node, Selection &selection)
Definition node.cpp:105
int value
Definition elements.hpp:188
std::shared_ptr< ComponentBase > Component
Definition app.hpp:23
Component CatchEvent(Component child, std::function< bool(Event)>)