1effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// found in the LICENSE file.
4effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
5effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "testing/gtest/include/gtest/gtest.h"
6effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "tools/gn/input_file.h"
7effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "tools/gn/parse_tree.h"
8effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "tools/gn/scope.h"
9effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "tools/gn/test_with_scope.h"
10effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
11effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochTEST(ParseTree, Accessor) {
12effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  TestWithScope setup;
13effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
14effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Make a pretend parse node with proper tracking that we can blame for the
15effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // given value.
16effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  InputFile input_file(SourceFile("//foo"));
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Token base_token(Location(&input_file, 1, 1, 1), Token::IDENTIFIER, "a");
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Token member_token(Location(&input_file, 1, 1, 1), Token::IDENTIFIER, "b");
19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
20effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  AccessorNode accessor;
21effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  accessor.set_base(base_token);
22effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
23effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  scoped_ptr<IdentifierNode> member_identifier(
24effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      new IdentifierNode(member_token));
25effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  accessor.set_member(member_identifier.Pass());
26effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
27effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // The access should fail because a is not defined.
28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  Err err;
29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  Value result = accessor.Execute(setup.scope(), &err);
30effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  EXPECT_TRUE(err.has_error());
31effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  EXPECT_EQ(Value::NONE, result.type());
32effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
33effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Define a as a Scope. It should still fail because b isn't defined.
34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  err = Err();
35c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  setup.scope()->SetValue("a",
36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      Value(NULL, scoped_ptr<Scope>(new Scope(setup.scope()))), NULL);
37effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  result = accessor.Execute(setup.scope(), &err);
38effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  EXPECT_TRUE(err.has_error());
39effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  EXPECT_EQ(Value::NONE, result.type());
40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
41effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Define b, accessor should succeed now.
42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const int64 kBValue = 42;
43effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  err = Err();
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  setup.scope()->GetMutableValue("a", false)->scope_value()->SetValue(
45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "b", Value(NULL, kBValue), NULL);
46effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  result = accessor.Execute(setup.scope(), &err);
47effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  EXPECT_FALSE(err.has_error());
48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  ASSERT_EQ(Value::INTEGER, result.type());
49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  EXPECT_EQ(kBValue, result.int_value());
50effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST(ParseTree, BlockUnusedVars) {
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestWithScope setup;
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Printing both values should be OK.
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestParseInput input_all_used(
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "{\n"
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "  a = 12\n"
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "  b = 13\n"
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "  print(\"$a $b\")\n"
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "}");
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_FALSE(input_all_used.has_error());
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Err err;
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  input_all_used.parsed()->Execute(setup.scope(), &err);
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_FALSE(err.has_error());
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Skipping one should throw an unused var error.
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestParseInput input_unused(
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "{\n"
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "  a = 12\n"
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "  b = 13\n"
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "  print(\"$a\")\n"
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "}");
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_FALSE(input_unused.has_error());
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  input_unused.parsed()->Execute(setup.scope(), &err);
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(err.has_error());
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Also verify that the unused variable has the correct origin set. The
816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // origin will point to the value assigned to the variable (in this case, the
826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // "13" assigned to "b".
836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_EQ(3, err.location().line_number());
846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_EQ(7, err.location().char_offset());
856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)TEST(ParseTree, OriginForDereference) {
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  TestWithScope setup;
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  TestParseInput input(
916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      "a = 6\n"
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      "get_target_outputs(a)");
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_FALSE(input.has_error());
946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  Err err;
966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  input.parsed()->Execute(setup.scope(), &err);
976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_TRUE(err.has_error());
986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // The origin for the "not a string" error message should be where the value
1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // was dereferenced (the "a" on the second line).
1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_EQ(2, err.location().line_number());
1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_EQ(20, err.location().char_offset());
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
104