Skip to content

Commit

Permalink
refactor(test): avoid Diag_Collector in Variable_Analyzer test
Browse files Browse the repository at this point in the history
  • Loading branch information
strager committed Jan 8, 2024
1 parent f04b533 commit 85aa52f
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 54 deletions.
22 changes: 20 additions & 2 deletions test/quick-lint-js/gtest.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,35 @@ std::string get_matcher_message(::testing::Matcher<const Value &> matcher,
::testing::internal::MakePredicateFormatterFromMatcher(matcher), value, \
ADD_FAILURE_AT_CALLER)

// Like ASSERT_EQ, but using the 'caller' variable for source locations.
#define ASSERT_NE_AT_CALLER(lhs, rhs) \
GTEST_PRED_FORMAT2_(::testing::internal::CmpHelperNE, lhs, rhs, \
GTEST_FAIL_AT_CALLER)

// Like EXPECT_EQ, but using the 'caller' variable for source locations.
#define EXPECT_EQ_AT_CALLER(lhs, rhs) \
GTEST_PRED_FORMAT2_(::testing::internal::EqHelper::Compare, lhs, rhs, \
ADD_FAILURE_AT_CALLER)

#define ADD_FAILURE_AT_CALLER(message) \
// Like EXPECT_TRUE, but using the 'caller' variable for source locations.
#define EXPECT_TRUE_AT_CALLER(value) EXPECT_EQ_AT_CALLER(value, true)

// Like ADD_FAILURE, but using the 'caller' variable for source locations.
#define ADD_FAILURE_AT_CALLER(message) \
ADD_FAILURE_OR_FAIL_AT_CALLER(message, \
::testing::TestPartResult::kNonFatalFailure)

// Like GTEST_FAIL, but using the 'caller' variable for source locations.
#define GTEST_FAIL_AT_CALLER(message) \
ADD_FAILURE_OR_FAIL_AT_CALLER(message, \
::testing::TestPartResult::kFatalFailure)

#define ADD_FAILURE_OR_FAIL_AT_CALLER(message, failure_kind) \
GTEST_MESSAGE_AT_( \
(caller.valid() ? caller.file_name() : __FILE__), \
(caller.valid() ? ::quick_lint_js::narrow_cast<int>(caller.line()) \
: __LINE__), \
message, ::testing::TestPartResult::kNonFatalFailure)
message, failure_kind)
}

// quick-lint-js finds bugs in JavaScript programs.
Expand Down
116 changes: 64 additions & 52 deletions test/test-variable-analyzer-type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,19 @@ TEST(Test_Variable_Analyzer_Type, type_use_does_not_see_non_type_variables) {
typescript_analyze_options, default_globals);
}

template <class Diag>
Diag* get_only_diagnostic(const Diag_List& diags, Diag_Type type) {
Diag* diag = nullptr;
int found_count = 0;
diags.for_each([&](Diag_Type current_type, void* raw_diag) -> void {
if (current_type == type) {
++found_count;
diag = static_cast<Diag*>(raw_diag);
}
});
return found_count == 1 ? diag : nullptr;
}

TEST(Test_Variable_Analyzer_Type,
interfaces_are_ignored_in_runtime_expressions) {
static const Char8 outer_declaration[] = u8"I";
Expand All @@ -299,6 +312,8 @@ TEST(Test_Variable_Analyzer_Type,
delete_expression.data() + 7, delete_expression.data() + 8);
ASSERT_EQ(deleted_variable_span.string_view(), u8"I"_sv);

Monotonic_Allocator memory("test");

struct Variable_Visit_Kind {
const char* description;
void (*visit)(Variable_Analyzer&);
Expand All @@ -310,11 +325,11 @@ TEST(Test_Variable_Analyzer_Type,
// If no run-time variable exists with the same name as the interface,
// 'runtime_var_kind' is nullopt.
void (*check_diagnostics_impl)(
Diag_Collector& diags, std::optional<Variable_Kind> runtime_var_kind,
const Diag_List& diags, std::optional<Variable_Kind> runtime_var_kind,
Source_Location caller);

void check_diagnostics(
Diag_Collector& diags, std::optional<Variable_Kind> runtime_var_kind,
const Diag_List& diags, std::optional<Variable_Kind> runtime_var_kind,
Source_Location caller = Source_Location::current()) {
return this->check_diagnostics_impl(diags, runtime_var_kind, caller);
}
Expand All @@ -329,30 +344,30 @@ TEST(Test_Variable_Analyzer_Type,
Variable_Assignment_Flags::none);
},
.check_diagnostics_impl =
[](Diag_Collector& diags,
[](const Diag_List& diags,
std::optional<Variable_Kind> runtime_var_kind,
Source_Location caller) -> void {
if (runtime_var_kind.has_value()) {
if (*runtime_var_kind == Variable_Kind::_const) {
EXPECT_THAT_AT_CALLER(
diags.errors,
ElementsAreArray({
DIAG_TYPE_2_SPANS(Diag_Assignment_To_Const_Variable, //
assignment, span_of(assignment), //
declaration,
span_of(outer_declaration)),
}));
auto* diag =
get_only_diagnostic<Diag_Assignment_To_Const_Variable>(
diags, Diag_Type::Diag_Assignment_To_Const_Variable);
ASSERT_NE_AT_CALLER(diag, nullptr);
EXPECT_TRUE_AT_CALLER(
same_pointers(diag->assignment, span_of(assignment)));
EXPECT_TRUE_AT_CALLER(same_pointers(
diag->declaration, span_of(outer_declaration)));
} else {
EXPECT_THAT_AT_CALLER(diags.errors, IsEmpty());
EXPECT_TRUE_AT_CALLER(diags.empty());
}
} else {
// TODO(strager): Report a more helpful diagnostic.
EXPECT_THAT_AT_CALLER(
diags.errors,
ElementsAreArray({
DIAG_TYPE_SPAN(Diag_Assignment_To_Undeclared_Variable,
assignment, span_of(assignment)),
}));
auto* diag =
get_only_diagnostic<Diag_Assignment_To_Undeclared_Variable>(
diags, Diag_Type::Diag_Assignment_To_Undeclared_Variable);
ASSERT_NE_AT_CALLER(diag, nullptr);
EXPECT_TRUE_AT_CALLER(
same_pointers(diag->assignment, span_of(assignment)));
}
},
},
Expand All @@ -365,20 +380,19 @@ TEST(Test_Variable_Analyzer_Type,
delete_keyword_span);
},
.check_diagnostics_impl =
[](Diag_Collector& diags,
[](const Diag_List& diags,
std::optional<Variable_Kind> runtime_var_kind,
Source_Location caller) -> void {
if (runtime_var_kind.has_value()) {
EXPECT_THAT_AT_CALLER(
diags.errors,
ElementsAreArray({
DIAG_TYPE_OFFSETS(
&delete_expression,
Diag_Redundant_Delete_Statement_On_Variable, //
delete_expression, 0, u8"delete I"_sv),
}));
auto* diag = get_only_diagnostic<
Diag_Redundant_Delete_Statement_On_Variable>(
diags,
Diag_Type::Diag_Redundant_Delete_Statement_On_Variable);
ASSERT_NE_AT_CALLER(diag, nullptr);
EXPECT_TRUE_AT_CALLER(same_pointers(diag->delete_expression,
span_of(delete_expression)));
} else {
EXPECT_THAT_AT_CALLER(diags.errors, IsEmpty());
EXPECT_TRUE_AT_CALLER(diags.empty());
}
},
},
Expand All @@ -390,19 +404,17 @@ TEST(Test_Variable_Analyzer_Type,
l.visit_variable_use(identifier_of(use));
},
.check_diagnostics_impl =
[](Diag_Collector& diags,
[](const Diag_List& diags,
std::optional<Variable_Kind> runtime_var_kind,
Source_Location caller) -> void {
if (runtime_var_kind.has_value()) {
EXPECT_THAT_AT_CALLER(diags.errors, IsEmpty());
EXPECT_TRUE_AT_CALLER(diags.empty());
} else {
// TODO(strager): Report a more helpful diagnostic.
EXPECT_THAT_AT_CALLER(
diags.errors,
ElementsAreArray({
DIAG_TYPE_SPAN(Diag_Use_Of_Undeclared_Variable, name,
span_of(use)),
}));
auto* diag = get_only_diagnostic<Diag_Use_Of_Undeclared_Variable>(
diags, Diag_Type::Diag_Use_Of_Undeclared_Variable);
ASSERT_NE_AT_CALLER(diag, nullptr);
EXPECT_TRUE_AT_CALLER(same_pointers(diag->name, span_of(use)));
}
},
},
Expand All @@ -414,23 +426,23 @@ TEST(Test_Variable_Analyzer_Type,
{
// interface I {}
// I; // ERROR
Diag_Collector v;
Diag_List_Diag_Reporter v(&memory);
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
l.visit_variable_declaration(identifier_of(declaration),
Variable_Kind::_interface,
Variable_Declaration_Flags::none);
visit_kind.visit(l);
l.visit_end_of_module();

visit_kind.check_diagnostics(v, std::nullopt);
visit_kind.check_diagnostics(v.diags(), std::nullopt);
}

{
// interface I {}
// {
// I; // ERROR
// }
Diag_Collector v;
Diag_List_Diag_Reporter v(&memory);
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
l.visit_variable_declaration(identifier_of(declaration),
Variable_Kind::_interface,
Expand All @@ -440,7 +452,7 @@ TEST(Test_Variable_Analyzer_Type,
l.visit_exit_block_scope();
l.visit_end_of_module();

visit_kind.check_diagnostics(v, std::nullopt);
visit_kind.check_diagnostics(v.diags(), std::nullopt);
}

{
Expand All @@ -450,7 +462,7 @@ TEST(Test_Variable_Analyzer_Type,
// I; // ERROR
// });
// });
Diag_Collector v;
Diag_List_Diag_Reporter v(&memory);
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
l.visit_variable_declaration(identifier_of(declaration),
Variable_Kind::_interface,
Expand All @@ -464,7 +476,7 @@ TEST(Test_Variable_Analyzer_Type,
l.visit_exit_function_scope();
l.visit_end_of_module();

visit_kind.check_diagnostics(v, std::nullopt);
visit_kind.check_diagnostics(v.diags(), std::nullopt);
}

for (Variable_Kind outer_kind : {
Expand All @@ -485,7 +497,7 @@ TEST(Test_Variable_Analyzer_Type,
// interface I {}
// I;
// }
Diag_Collector v;
Diag_List_Diag_Reporter v(&memory);
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
l.visit_variable_declaration(identifier_of(outer_declaration),
outer_kind,
Expand All @@ -498,7 +510,7 @@ TEST(Test_Variable_Analyzer_Type,
l.visit_exit_block_scope();
l.visit_end_of_module();

visit_kind.check_diagnostics(v, outer_kind);
visit_kind.check_diagnostics(v.diags(), outer_kind);
}

{
Expand All @@ -507,7 +519,7 @@ TEST(Test_Variable_Analyzer_Type,
// {
// I;
// }
Diag_Collector v;
Diag_List_Diag_Reporter v(&memory);
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
l.visit_variable_declaration(identifier_of(outer_declaration),
outer_kind,
Expand All @@ -520,14 +532,14 @@ TEST(Test_Variable_Analyzer_Type,
l.visit_exit_block_scope();
l.visit_end_of_module();

visit_kind.check_diagnostics(v, outer_kind);
visit_kind.check_diagnostics(v.diags(), outer_kind);
}

{
// let I;
// interface I {}
// I;
Diag_Collector v;
Diag_List_Diag_Reporter v(&memory);
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
l.visit_variable_declaration(identifier_of(outer_declaration),
outer_kind,
Expand All @@ -538,14 +550,14 @@ TEST(Test_Variable_Analyzer_Type,
visit_kind.visit(l);
l.visit_end_of_module();

visit_kind.check_diagnostics(v, outer_kind);
visit_kind.check_diagnostics(v.diags(), outer_kind);
}

{
// interface I {}
// let I;
// I;
Diag_Collector v;
Diag_List_Diag_Reporter v(&memory);
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
l.visit_variable_declaration(identifier_of(declaration),
Variable_Kind::_interface,
Expand All @@ -556,7 +568,7 @@ TEST(Test_Variable_Analyzer_Type,
visit_kind.visit(l);
l.visit_end_of_module();

visit_kind.check_diagnostics(v, outer_kind);
visit_kind.check_diagnostics(v.diags(), outer_kind);
}

{
Expand All @@ -565,7 +577,7 @@ TEST(Test_Variable_Analyzer_Type,
// });
// interface I {}
// let I;
Diag_Collector v;
Diag_List_Diag_Reporter v(&memory);
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
l.visit_enter_function_scope();
l.visit_enter_function_scope_body();
Expand All @@ -579,7 +591,7 @@ TEST(Test_Variable_Analyzer_Type,
Variable_Declaration_Flags::none);
l.visit_end_of_module();

visit_kind.check_diagnostics(v, outer_kind);
visit_kind.check_diagnostics(v.diags(), outer_kind);
}
}
}
Expand Down

0 comments on commit 85aa52f

Please sign in to comment.