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