blob: b4fdf1a3de596ed0c69ecfce6beb93625dc3908c [file] [edit]
// Copyright 2014 The Chromium 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 "base/strings/string_number_conversions.h"
#include "gn/test_with_scope.h"
#include "util/test/test.h"
TEST(Template, Basic) {
TestWithScope setup;
TestParseInput input(
"template(\"foo\") {\n"
" print(target_name)\n"
" print(invoker.bar)\n"
"}\n"
"foo(\"lala\") {\n"
" bar = 42\n"
"}");
ASSERT_SUCCESS(input);
Err err;
input.parsed()->Execute(setup.scope(), &err);
ASSERT_SUCCESS(err);
EXPECT_EQ("lala\n42\n", setup.print_output());
}
TEST(Template, UnusedTargetNameShouldThrowError) {
TestWithScope setup;
TestParseInput input(
"template(\"foo\") {\n"
" print(invoker.bar)\n"
"}\n"
"foo(\"lala\") {\n"
" bar = 42\n"
"}");
ASSERT_SUCCESS(input);
Err err;
input.parsed()->Execute(setup.scope(), &err);
EXPECT_TRUE(err.has_error());
}
TEST(Template, UnusedInvokerShouldThrowError) {
TestWithScope setup;
TestParseInput input(
"template(\"foo\") {\n"
" print(target_name)\n"
"}\n"
"foo(\"lala\") {\n"
" bar = 42\n"
"}");
ASSERT_SUCCESS(input);
Err err;
input.parsed()->Execute(setup.scope(), &err);
EXPECT_TRUE(err.has_error());
}
TEST(Template, UnusedVarInInvokerShouldThrowError) {
TestWithScope setup;
TestParseInput input(
"template(\"foo\") {\n"
" print(target_name)\n"
" print(invoker.bar)\n"
"}\n"
"foo(\"lala\") {\n"
" bar = 42\n"
" baz = [ \"foo\" ]\n"
"}");
ASSERT_SUCCESS(input);
Err err;
input.parsed()->Execute(setup.scope(), &err);
EXPECT_TRUE(err.has_error());
}
// Previous versions of the template implementation would copy templates by
// value when it makes a closure. Doing a sequence of them means that every new
// one copies all previous ones, which gives a significant blow-up in memory.
// If this test doesn't crash with out-of-memory, it passed.
TEST(Template, MemoryBlowUp) {
TestWithScope setup;
std::string code;
for (int i = 0; i < 100; i++)
code += "template(\"test" + base::IntToString(i) + "\") {}\n";
TestParseInput input(code);
Err err;
input.parsed()->Execute(setup.scope(), &err);
ASSERT_SUCCESS(input);
}
TEST(Template, ErrorStackTrace) {
TestWithScope setup;
TestParseInput input(
"template(\"my_template\") {\n"
" print(invoker.undefined_var)\n"
"}\n"
"my_template(\"lala\") {\n"
"}");
ASSERT_SUCCESS(input);
Err err;
input.parsed()->Execute(setup.scope(), &err);
EXPECT_TRUE(err.has_error());
EXPECT_EQ(err.to_string(),
"ERROR at //test:2:17: No value named \"undefined_var\" in scope "
"\"invoker\"\n"
" print(invoker.undefined_var)\n"
" ^------------\n"
"See //test:4:1: whence my_template was called.\n"
"my_template(\"lala\") {\n"
"^--------------------\n");
}