1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/files/file.h"
61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/files/scoped_temp_dir.h"
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "tools/gn/functions.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "tools/gn/test_with_scope.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Returns true on success, false if write_file signaled an error.
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool CallWriteFile(Scope* scope,
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   const std::string& filename,
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   const Value& data) {
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Err err;
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<Value> args;
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  args.push_back(Value(NULL, filename));
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  args.push_back(data);
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  FunctionCallNode function_call;
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Value result = functions::RunWriteFile(scope, &function_call, args, &err);
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(Value::NONE, result.type());  // Should always return none.
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return !err.has_error();
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST(WriteFile, WithData) {
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestWithScope setup;
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Make a real directory for writing the files.
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::ScopedTempDir temp_dir;
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  setup.build_settings()->SetRootPath(temp_dir.path());
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  setup.build_settings()->SetBuildDir(SourceDir("//out/"));
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Value some_string(NULL, "some string contents");
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Should refuse to write files outside of the output dir.
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_FALSE(CallWriteFile(setup.scope(), "//in_root.txt", some_string));
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_FALSE(CallWriteFile(setup.scope(), "//other_dir/foo.txt",
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                             some_string));
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Should be able to write to a new dir inside the out dir.
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(CallWriteFile(setup.scope(), "//out/foo.txt", some_string));
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::FilePath foo_name = temp_dir.path().Append(FILE_PATH_LITERAL("out"))
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      .Append(FILE_PATH_LITERAL("foo.txt"));
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string result_contents;
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(base::ReadFileToString(foo_name, &result_contents));
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(some_string.string_value(), result_contents);
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Update the contents with a list of a string and a number.
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Value some_list(NULL, Value::LIST);
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  some_list.list_value().push_back(Value(NULL, "line 1"));
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  some_list.list_value().push_back(Value(NULL, static_cast<int64>(2)));
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(CallWriteFile(setup.scope(), "//out/foo.txt", some_list));
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(base::ReadFileToString(foo_name, &result_contents));
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ("line 1\n2\n", result_contents);
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Test that the file is not rewritten if the contents are not changed.
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Start by setting the modified time to something old to avoid clock
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // resolution issues.
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::Time old_time = base::Time::Now() - base::TimeDelta::FromDays(1);
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::File foo_file(foo_name,
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                      base::File::FLAG_OPEN |
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                      base::File::FLAG_READ | base::File::FLAG_WRITE);
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_TRUE(foo_file.IsValid());
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  foo_file.SetTimes(old_time, old_time);
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Read the current time to avoid timer resolution issues when comparing
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // below.
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::File::Info original_info;
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  foo_file.GetInfo(&original_info);
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(CallWriteFile(setup.scope(), "//out/foo.txt", some_list));
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Verify that the last modified time is the same as before.
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::File::Info new_info;
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  foo_file.GetInfo(&new_info);
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(original_info.last_modified, new_info.last_modified);
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
87