1//===-- flags_test.cpp ------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "tests/scudo_unit_test.h"
10
11#include "flags.h"
12#include "flags_parser.h"
13
14#include <string.h>
15
16static const char FlagName[] = "flag_name";
17static const char FlagDesc[] = "flag description";
18
19template <typename T>
20static void testFlag(scudo::FlagType Type, T StartValue, const char *Env,
21 T FinalValue) {
22 scudo::FlagParser Parser;
23 T Flag = StartValue;
24 Parser.registerFlag(Name: FlagName, Desc: FlagDesc, Type, Var: &Flag);
25 Parser.parseString(S: Env);
26 EXPECT_EQ(FinalValue, Flag);
27 // Reporting unrecognized flags is needed to reset them.
28 scudo::reportUnrecognizedFlags();
29}
30
31TEST(ScudoFlagsTest, BooleanFlags) {
32 testFlag(Type: scudo::FlagType::FT_bool, StartValue: false, Env: "flag_name=1", FinalValue: true);
33 testFlag(Type: scudo::FlagType::FT_bool, StartValue: false, Env: "flag_name=yes", FinalValue: true);
34 testFlag(Type: scudo::FlagType::FT_bool, StartValue: false, Env: "flag_name='yes'", FinalValue: true);
35 testFlag(Type: scudo::FlagType::FT_bool, StartValue: false, Env: "flag_name=true", FinalValue: true);
36 testFlag(Type: scudo::FlagType::FT_bool, StartValue: true, Env: "flag_name=0", FinalValue: false);
37 testFlag(Type: scudo::FlagType::FT_bool, StartValue: true, Env: "flag_name=\"0\"", FinalValue: false);
38 testFlag(Type: scudo::FlagType::FT_bool, StartValue: true, Env: "flag_name=no", FinalValue: false);
39 testFlag(Type: scudo::FlagType::FT_bool, StartValue: true, Env: "flag_name=false", FinalValue: false);
40 testFlag(Type: scudo::FlagType::FT_bool, StartValue: true, Env: "flag_name='false'", FinalValue: false);
41}
42
43TEST(ScudoFlagsDeathTest, BooleanFlags) {
44 EXPECT_DEATH(testFlag(scudo::FlagType::FT_bool, false, "flag_name", true),
45 "expected '='");
46 EXPECT_DEATH(testFlag(scudo::FlagType::FT_bool, false, "flag_name=", true),
47 "invalid value for bool option: ''");
48 EXPECT_DEATH(testFlag(scudo::FlagType::FT_bool, false, "flag_name=2", true),
49 "invalid value for bool option: '2'");
50 EXPECT_DEATH(testFlag(scudo::FlagType::FT_bool, false, "flag_name=-1", true),
51 "invalid value for bool option: '-1'");
52 EXPECT_DEATH(testFlag(scudo::FlagType::FT_bool, false, "flag_name=on", true),
53 "invalid value for bool option: 'on'");
54}
55
56TEST(ScudoFlagsTest, IntFlags) {
57 testFlag(Type: scudo::FlagType::FT_int, StartValue: -11, Env: nullptr, FinalValue: -11);
58 testFlag(Type: scudo::FlagType::FT_int, StartValue: -11, Env: "flag_name=0", FinalValue: 0);
59 testFlag(Type: scudo::FlagType::FT_int, StartValue: -11, Env: "flag_name='0'", FinalValue: 0);
60 testFlag(Type: scudo::FlagType::FT_int, StartValue: -11, Env: "flag_name=42", FinalValue: 42);
61 testFlag(Type: scudo::FlagType::FT_int, StartValue: -11, Env: "flag_name=-42", FinalValue: -42);
62 testFlag(Type: scudo::FlagType::FT_int, StartValue: -11, Env: "flag_name=\"-42\"", FinalValue: -42);
63
64 // Unrecognized flags are ignored.
65 testFlag(Type: scudo::FlagType::FT_int, StartValue: -11, Env: "--flag_name=42", FinalValue: -11);
66 testFlag(Type: scudo::FlagType::FT_int, StartValue: -11, Env: "zzzzzzz=42", FinalValue: -11);
67}
68
69TEST(ScudoFlagsDeathTest, IntFlags) {
70 EXPECT_DEATH(testFlag(scudo::FlagType::FT_int, -11, "flag_name", 0),
71 "expected '='");
72 EXPECT_DEATH(testFlag(scudo::FlagType::FT_int, -11, "flag_name=42U", 0),
73 "invalid value for int option");
74}
75
76static void testTwoFlags(const char *Env, bool ExpectedFlag1,
77 const int ExpectedFlag2, const char *Name1 = "flag1",
78 const char *Name2 = "flag2") {
79 scudo::FlagParser Parser;
80 bool Flag1 = !ExpectedFlag1;
81 int Flag2;
82 Parser.registerFlag(Name: Name1, Desc: FlagDesc, Type: scudo::FlagType::FT_bool, Var: &Flag1);
83 Parser.registerFlag(Name: Name2, Desc: FlagDesc, Type: scudo::FlagType::FT_int, Var: &Flag2);
84 Parser.parseString(S: Env);
85 EXPECT_EQ(ExpectedFlag1, Flag1);
86 EXPECT_EQ(Flag2, ExpectedFlag2);
87 // Reporting unrecognized flags is needed to reset them.
88 scudo::reportUnrecognizedFlags();
89}
90
91TEST(ScudoFlagsTest, MultipleFlags) {
92 testTwoFlags(Env: "flag1=1 flag2=42", ExpectedFlag1: true, ExpectedFlag2: 42);
93 testTwoFlags(Env: "flag2=-1 flag1=0", ExpectedFlag1: false, ExpectedFlag2: -1);
94 testTwoFlags(Env: "flag1=false:flag2=1337", ExpectedFlag1: false, ExpectedFlag2: 1337);
95 testTwoFlags(Env: "flag2=42:flag1=yes", ExpectedFlag1: true, ExpectedFlag2: 42);
96 testTwoFlags(Env: "flag2=42\nflag1=yes", ExpectedFlag1: true, ExpectedFlag2: 42);
97 testTwoFlags(Env: "flag2=42\r\nflag1=yes", ExpectedFlag1: true, ExpectedFlag2: 42);
98 testTwoFlags(Env: "flag2=42\tflag1=yes", ExpectedFlag1: true, ExpectedFlag2: 42);
99}
100
101TEST(ScudoFlagsTest, CommonSuffixFlags) {
102 testTwoFlags(Env: "flag=1 other_flag=42", ExpectedFlag1: true, ExpectedFlag2: 42, Name1: "flag", Name2: "other_flag");
103 testTwoFlags(Env: "other_flag=42 flag=1", ExpectedFlag1: true, ExpectedFlag2: 42, Name1: "flag", Name2: "other_flag");
104}
105
106TEST(ScudoFlagsTest, AllocatorFlags) {
107 scudo::FlagParser Parser;
108 scudo::Flags Flags;
109 scudo::registerFlags(Parser: &Parser, F: &Flags);
110 Flags.setDefaults();
111 Flags.dealloc_type_mismatch = false;
112 Flags.delete_size_mismatch = false;
113 Flags.quarantine_max_chunk_size = 1024;
114 Parser.parseString(S: "dealloc_type_mismatch=true:delete_size_mismatch=true:"
115 "quarantine_max_chunk_size=2048");
116 EXPECT_TRUE(Flags.dealloc_type_mismatch);
117 EXPECT_TRUE(Flags.delete_size_mismatch);
118 EXPECT_EQ(2048, Flags.quarantine_max_chunk_size);
119}
120
121#ifdef GWP_ASAN_HOOKS
122TEST(ScudoFlagsTest, GWPASanFlags) {
123 scudo::FlagParser Parser;
124 scudo::Flags Flags;
125 scudo::registerFlags(Parser: &Parser, F: &Flags);
126 Flags.setDefaults();
127 Flags.GWP_ASAN_Enabled = false;
128 Parser.parseString(S: "GWP_ASAN_Enabled=true:GWP_ASAN_SampleRate=1:"
129 "GWP_ASAN_InstallSignalHandlers=false");
130 EXPECT_TRUE(Flags.GWP_ASAN_Enabled);
131 EXPECT_FALSE(Flags.GWP_ASAN_InstallSignalHandlers);
132 EXPECT_EQ(1, Flags.GWP_ASAN_SampleRate);
133}
134#endif // GWP_ASAN_HOOKS
135

source code of compiler-rt/lib/scudo/standalone/tests/flags_test.cpp