blob: 70b4a650ba9841b4adfc2babce83e3b73eadb652 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/developer/debug/zxdb/expr/identifier_glob.h"
#include <lib/syslog/cpp/macros.h>
#include <gtest/gtest.h>
#include "src/developer/debug/zxdb/expr/expr_parser.h"
namespace zxdb {
namespace {
using Score = std::optional<int>;
// Parses the given idetifier and asserts success. Used for constant input in this test.
ParsedIdentifier Parse(const std::string& s) {
ParsedIdentifier result;
Err err = ExprParser::ParseIdentifier(s, &result);
FX_CHECK(!err.has_error()) << err.msg();
return result;
}
} // namespace
TEST(IdentifierGlob, Exact) {
IdentifierGlob myclass;
ASSERT_FALSE(myclass.Init("MyClass").has_error());
// Exact match.
EXPECT_EQ(Score(0), myclass.Matches(Parse("MyClass")));
// The identifier parser will trim whitespace.
EXPECT_EQ(Score(0), myclass.Matches(Parse("MyClass ")));
EXPECT_EQ(Score(0), myclass.Matches(Parse(" MyClass")));
// Non-matches.
EXPECT_EQ(std::nullopt, myclass.Matches(Parse("MyClassA")));
EXPECT_EQ(std::nullopt, myclass.Matches(Parse("MyClas")));
EXPECT_EQ(std::nullopt, myclass.Matches(Parse("myclass")));
EXPECT_EQ(std::nullopt, myclass.Matches(Parse("MyClass<>")));
// Global qualification in either direction doesn't matter.
IdentifierGlob global_myclass;
ASSERT_FALSE(global_myclass.Init("::MyClass").has_error());
EXPECT_EQ(Score(0), global_myclass.Matches(Parse("::MyClass")));
EXPECT_EQ(Score(0), global_myclass.Matches(Parse("MyClass")));
}
TEST(IdentifierGlob, EmptyTemplates) {
IdentifierGlob no_star;
ASSERT_FALSE(no_star.Init("MyClass<>").has_error());
// Template existance must match.
EXPECT_EQ(Score(0), no_star.Matches(Parse("MyClass<>"))); // Technically invalid C++.
EXPECT_EQ(std::nullopt, no_star.Matches(Parse("MyClass")));
}
TEST(IdentifierGlob, OneTemplate) {
IdentifierGlob one_star;
ASSERT_FALSE(one_star.Init("MyClass<*>").has_error());
// "*" won't match no template params.
EXPECT_EQ(std::nullopt, one_star.Matches(Parse("MyClass<>")));
// String globs will match this, but our identifier one won't.
EXPECT_EQ(std::nullopt, one_star.Matches(Parse("MyClass<int>::Something<int>")));
// Will eat multiple params.
EXPECT_EQ(Score(1), one_star.Matches(Parse("MyClass<int>")));
EXPECT_EQ(Score(2), one_star.Matches(Parse("MyClass<int, int>")));
EXPECT_EQ(Score(3), one_star.Matches(Parse("MyClass<int,int,double>")));
}
TEST(IdentifierGlob, TwoTemplate) {
IdentifierGlob one_star;
ASSERT_FALSE(one_star.Init("MyClass<*,*>").has_error());
// Won't match fewer template params.
EXPECT_EQ(std::nullopt, one_star.Matches(Parse("MyClass<>")));
EXPECT_EQ(std::nullopt, one_star.Matches(Parse("MyClass<int>")));
EXPECT_EQ(std::nullopt, one_star.Matches(Parse("MyClass<Something<Foo>>")));
EXPECT_EQ(Score(1), one_star.Matches(Parse("MyClass<int, Something<Foo>>")));
EXPECT_EQ(Score(2), one_star.Matches(Parse("MyClass<int,int,double>")));
}
TEST(IdentifierGlob, LiteralTemplate) {
IdentifierGlob one_lit;
ASSERT_FALSE(one_lit.Init("MyClass<int>").has_error());
EXPECT_EQ(std::nullopt, one_lit.Matches(Parse("MyClass<>")));
EXPECT_EQ(std::nullopt, one_lit.Matches(Parse("MyClass<float>")));
EXPECT_EQ(std::nullopt, one_lit.Matches(Parse("MyClass<int, int>")));
EXPECT_EQ(std::nullopt, one_lit.Matches(Parse("MyClass<int*>")));
EXPECT_EQ(Score(0), one_lit.Matches(Parse("MyClass<int>")));
// * not by itself is a literal (in this case, a pointer).
IdentifierGlob lit_ptr;
ASSERT_FALSE(lit_ptr.Init("MyClass<int*>").has_error());
EXPECT_EQ(std::nullopt, lit_ptr.Matches(Parse("MyClass<int>")));
EXPECT_EQ(Score(0), lit_ptr.Matches(Parse("MyClass<int* >")));
IdentifierGlob two_lit;
ASSERT_FALSE(two_lit.Init("MyClass<int, float>").has_error());
EXPECT_EQ(std::nullopt, two_lit.Matches(Parse("MyClass<int, int>")));
EXPECT_EQ(Score(0), two_lit.Matches(Parse("MyClass <int,float >")));
}
TEST(IdentifierGlob, StarLiteralTemplate) {
IdentifierGlob star_lit;
ASSERT_FALSE(star_lit.Init("MyClass<*, int>").has_error());
EXPECT_EQ(std::nullopt, star_lit.Matches(Parse("MyClass<int>")));
EXPECT_EQ(Score(1), star_lit.Matches(Parse("MyClass<double,int>")));
// "*" not greedy unless last.
EXPECT_EQ(std::nullopt, star_lit.Matches(Parse("MyClass<double, double, int>")));
EXPECT_EQ(std::nullopt, star_lit.Matches(Parse("MyClass<double, int, double>")));
}
TEST(IdentifierGlob, LiteralStarTemplate) {
IdentifierGlob lit_star;
ASSERT_FALSE(lit_star.Init("MyClass<int,*>").has_error());
EXPECT_EQ(std::nullopt, lit_star.Matches(Parse("MyClass<int>")));
EXPECT_EQ(Score(1), lit_star.Matches(Parse("MyClass<int,int>")));
EXPECT_EQ(Score(2), lit_star.Matches(Parse("MyClass<int,double,float>")));
}
} // namespace zxdb