dhcp client: Add FileIO class

This add class FileIO and corresponding unittests.
This class is used to save dhcp config to persistent storage
and read from that.

Bug: 25642025
TEST=compile and unittes

Change-Id: I72e409c9e6e32f88fbf50a38ef3642bac7f217dd
diff --git a/dhcp_client.gyp b/dhcp_client.gyp
index 474c029..709cc4d 100644
--- a/dhcp_client.gyp
+++ b/dhcp_client.gyp
@@ -62,6 +62,7 @@
         'dhcp_options_parser.cc',
         'dhcp_options_writer.cc',
         'dhcpv4.cc',
+        'file_io.cc',
         'message_loop_event_dispatcher.cc',
         'manager.cc',
         'service.cc',
@@ -89,6 +90,7 @@
             'dhcp_message_unittest.cc',
             'dhcp_options_parser_unittest.cc',
             'dhcp_options_writer_unittest.cc',
+            'file_io_unittest.cc',
             'testrunner.cc',
           ],
         },
diff --git a/file_io.cc b/file_io.cc
new file mode 100644
index 0000000..1976316
--- /dev/null
+++ b/file_io.cc
@@ -0,0 +1,65 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "dhcp_client/file_io.h"
+
+#include <string>
+
+#include <base/files/file_util.h>
+
+namespace dhcp_client {
+
+namespace {
+base::LazyInstance<FileIO> g_file_io
+    = LAZY_INSTANCE_INITIALIZER;
+}  // namespace
+
+FileIO::FileIO() {}
+FileIO::~FileIO() {}
+
+FileIO* FileIO::GetInstance() {
+  return g_file_io.Pointer();
+}
+
+bool FileIO::Write(const std::string& file_name,
+                   const shill::ByteString& data) {
+  if (base::WriteFile(base::FilePath(file_name),
+                      reinterpret_cast<const char*>(data.GetConstData()),
+                      data.GetLength()) == -1) {
+    return false;
+  }
+  return true;
+}
+
+bool FileIO::Read(const std::string& file_name, shill::ByteString* out_data) {
+  std::string buffer;
+  if (!base::ReadFileToString(base::FilePath(file_name),
+                              &buffer)) {
+    return false;
+  }
+  *out_data = shill::ByteString(buffer, false);
+  return true;
+}
+
+bool FileIO::PathExists(const std::string& file_name) {
+  return base::PathExists(base::FilePath(file_name));
+}
+
+bool FileIO::DeleteFile(const std::string& file_name) {
+  return base::DeleteFile(base::FilePath(file_name), false);
+}
+
+}  // namespace dhcp_client
diff --git a/file_io.h b/file_io.h
new file mode 100644
index 0000000..37ecc6d
--- /dev/null
+++ b/file_io.h
@@ -0,0 +1,54 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef DHCP_CLIENT_FILE_IO_H_
+#define DHCP_CLIENT_FILE_IO_H_
+
+#include <string>
+
+#include <base/lazy_instance.h>
+#include <shill/net/byte_string.h>
+
+namespace dhcp_client {
+
+// Singleton class for handling file operations.
+class FileIO {
+ public:
+  virtual ~FileIO();
+
+  // This is a singleton. Use FileWriter::GetInstance()->Foo().
+  static FileIO* GetInstance();
+
+  bool Write(const std::string& file_name,
+             const shill::ByteString& data);
+
+  bool Read(const std::string& file_name, shill::ByteString* out_data);
+
+  bool PathExists(const std::string& file_name);
+  bool DeleteFile(const std::string& file_name);
+
+ protected:
+  FileIO();
+
+ private:
+  friend struct base::DefaultLazyInstanceTraits<FileIO>;
+
+  DISALLOW_COPY_AND_ASSIGN(FileIO);
+};
+
+}  // namespace dhcp_client
+
+#endif  // DHCP_CLIENT_FILE_IO_H_
diff --git a/file_io_unittest.cc b/file_io_unittest.cc
new file mode 100644
index 0000000..fb470dc
--- /dev/null
+++ b/file_io_unittest.cc
@@ -0,0 +1,82 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <dhcp_client/file_io.h>
+
+#include <string>
+
+#include <base/files/file_util.h>
+#include <base/files/scoped_temp_dir.h>
+#include <gtest/gtest.h>
+
+#include <shill/net/byte_string.h>
+
+namespace dhcp_client {
+namespace {
+  const unsigned char kFakeFileContent[] = "fake_content";
+}
+
+class FileIOTest : public testing::Test {
+ public:
+  FileIOTest() {}
+};
+
+
+TEST_F(FileIOTest, PathExistsTrue) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath path;
+  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), &path));
+  EXPECT_TRUE(FileIO::GetInstance()->PathExists(path.value()));
+}
+
+TEST_F(FileIOTest, PathExistsFalse) {
+  const std::string kNonExistentFilePath("non-existent_path");
+  EXPECT_FALSE(FileIO::GetInstance()->PathExists(kNonExistentFilePath));
+}
+
+TEST_F(FileIOTest, DeleteFile) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath path;
+  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), &path));
+  EXPECT_TRUE(FileIO::GetInstance()->DeleteFile(path.value()));
+}
+
+TEST_F(FileIOTest, WriteAndReadFile) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath path;
+  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), &path));
+  shill::ByteString content =
+      shill::ByteString(kFakeFileContent, sizeof(kFakeFileContent));
+  EXPECT_TRUE(FileIO::GetInstance()->Write(path.value(), content));
+  shill::ByteString content_read;
+  EXPECT_TRUE(FileIO::GetInstance()->Read(path.value(), &content_read));
+  EXPECT_TRUE(content.Equals(content_read));
+}
+
+TEST_F(FileIOTest, ReadEmptyFile) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath path;
+  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), &path));
+  shill::ByteString content_read;
+  EXPECT_TRUE(FileIO::GetInstance()->Read(path.value(), &content_read));
+  EXPECT_EQ(0, content_read.GetLength());
+}
+
+}  // namespace dhcp_client