chromium/services/network/public/cpp/transferable_directory_unittest.cc

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "services/network/public/cpp/transferable_directory.h"

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "services/network/public/cpp/network_service_buildflags.h"
#include "services/network/public/mojom/transferable_directory.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace network {
namespace {

TransferableDirectoryTest;

const base::FilePath kDirPath(FILE_PATH_LITERAL("/some/directory"));

TEST_F(TransferableDirectoryTest, ManipulatePathOnly) {}

TEST_F(TransferableDirectoryTest, MojoTraitsWithPath) {}

#if BUILDFLAG(IS_DIRECTORY_TRANSFER_REQUIRED)

class TransferableDirectoryTestWithHandle : public testing::Test {
 public:
  TransferableDirectoryTestWithHandle() = default;
  ~TransferableDirectoryTestWithHandle() override = default;

  static constexpr char kFileFromParent[] = "from_parent";
  static constexpr char kFileFromChild[] = "from_child";
  static constexpr char kData[] = "yarr yee";

  void SetUp() override {
    // Create a temporary directory and publish a file into it.
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
    ASSERT_TRUE(
        base::WriteFile(temp_dir_.GetPath().Append(kFileFromParent), kData));

    // Construct a TransferableDirectory from the temp dir and prepare it for
    // mounting.
    transferable_temp_dir_ = TransferableDirectory(temp_dir_.GetPath());
    EXPECT_TRUE(transferable_temp_dir_.IsOpenForTransferRequired());
    EXPECT_FALSE(transferable_temp_dir_.NeedsMount());
    transferable_temp_dir_.OpenForTransfer();
    EXPECT_TRUE(transferable_temp_dir_.NeedsMount());
  }

 protected:
  base::ScopedTempDir temp_dir_;
  TransferableDirectory transferable_temp_dir_;
};

TEST_F(TransferableDirectoryTestWithHandle, OpenMountAndUnmount) {
  {
    // Mount the directory and verify that the parent-published file can be
    // seen.
    base::ScopedClosureRunner scoped_mount(transferable_temp_dir_.Mount());
    EXPECT_NE(transferable_temp_dir_.path(), temp_dir_.GetPath());

    EXPECT_TRUE(base::PathExists(transferable_temp_dir_.path()));
    ASSERT_FALSE(transferable_temp_dir_.path().empty());
    ASSERT_TRUE(base::PathExists(transferable_temp_dir_.path()));
    EXPECT_TRUE(base::PathExists(
        transferable_temp_dir_.path().Append(kFileFromParent)));

    // Write a file into the directory, for the parent to see.
    EXPECT_FALSE(
        base::PathExists(transferable_temp_dir_.path().Append(kFileFromChild)));
    ASSERT_TRUE(
        base::WriteFile(temp_dir_.GetPath().Append(kFileFromChild), kData));
    EXPECT_TRUE(
        base::PathExists(transferable_temp_dir_.path().Append(kFileFromChild)));
  }

  // |scoped_mount| is no longer in scope, so verify that the directory was
  // unmounted.
  EXPECT_FALSE(base::PathExists(transferable_temp_dir_.path()));

  // The child-published file should still be available in the original tempdir.
  EXPECT_TRUE(base::PathExists(temp_dir_.GetPath().Append(kFileFromChild)));
}

TEST_F(TransferableDirectoryTestWithHandle, SupportsMoveAsHandle) {
  // Mount the directory and verify that the published file exists.
  TransferableDirectory moved_temp_dir = std::move(transferable_temp_dir_);
  auto scoped_mount = moved_temp_dir.Mount();
  EXPECT_TRUE(base::PathExists(moved_temp_dir.path()));
  ASSERT_FALSE(moved_temp_dir.path().empty());
  EXPECT_TRUE(base::PathExists(moved_temp_dir.path().Append(kFileFromParent)));
}

TEST_F(TransferableDirectoryTestWithHandle, MojoTraitsWithHandle) {
  // Verify that the handle is preserved when transmitted using
  // mojo::TransferableDirectory.
  TransferableDirectory roundtripped;
  ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::TransferableDirectory>(
      transferable_temp_dir_, roundtripped));

  auto scoped_mount = roundtripped.Mount();
  ASSERT_TRUE(base::PathExists(roundtripped.path()));
  EXPECT_TRUE(base::PathExists(roundtripped.path().Append(kFileFromParent)));
}

#else

TEST_F(TransferableDirectoryTest, OpenAndMountNotSupportedForPlatform) {}

#endif  // BUILDFLAG(IS_DIRECTORY_TRANSFER_REQUIRED)

}  // namespace
}  // namespace network