Source release 19.4.0

This commit is contained in:
Vicky Min
2024-11-27 00:07:23 +00:00
parent 11c108a8da
commit 22759672a8
72 changed files with 5321 additions and 2622 deletions

View File

@@ -7,63 +7,118 @@
#ifndef WVCDM_UTIL_FILE_STORE_H_
#define WVCDM_UTIL_FILE_STORE_H_
#include <cstdint>
#include <stddef.h>
#include <memory>
#include <string>
#include <vector>
#include "disallow_copy_and_assign.h"
#include "platform.h"
#include "util_common.h"
#include "wv_class_utils.h"
namespace wvutil {
// Fixed filename for ATSC DRM certificate pre-installed
// on ATSC devices for ATSC licenses.
static const std::string kAtscCertificateFileName = "atsccert.bin";
// General filename for either global or unmapped app-origin
// DRM certificates.
static const std::string kCertificateFileName = "cert1.bin";
// File extension for DRM and OEM certificate files.
static const std::string kCertificateFileNameExt = ".bin";
static const std::string kCertificateFileNamePrefix = "cert1_";
// Filename prefix for mapped (scoped) DRM certificate filenames
// specific to a particular app-origin.
static const std::string kScopedCertificateFilenamePrefix = "cert1_";
// TODO(b/376533901): Replace this constant with
// kScopedCertificateFilenamePrefix in source code..
static const std::string kCertificateFileNamePrefix =
kScopedCertificateFilenamePrefix;
// Legacy general filename for either global or unmapped app-origin
// DRM certificates.
static const std::string kLegacyCertificateFileName = "cert.bin";
static const std::string kLegacyCertificateFileNamePrefix = "cert";
// Legacy filename prefix for mapped (scoped) DRM certificate filenames
// specific to a particular app-origin.
static const std::string kLegacyScopedCertificateFilenamePrefix = "cert";
// TODO(b/376533901): Replace this constant with
// kLegacyScopedCertificateFilenamePrefix in source code..
static const std::string kLegacyCertificateFileNamePrefix =
kLegacyScopedCertificateFilenamePrefix;
// Filename for global OEM certificates.
static const std::string kOemCertificateFileName = "oemcert.bin";
static const std::string kOemCertificateFileNamePrefix = "oemcert_";
// File class. The implementation is platform dependent.
// File interface. The implementation is platform dependent.
class File {
public:
WVCDM_DISALLOW_COPY_AND_MOVE(File);
File() {}
virtual ~File() {}
virtual ssize_t Read(char* buffer, size_t bytes) = 0;
virtual ssize_t Write(const char* buffer, size_t bytes) = 0;
friend class FileSystem;
CORE_DISALLOW_COPY_AND_ASSIGN(File);
};
// File system base class. The implementation is platform dependent.
class FileSystem {
public:
WVCDM_DISALLOW_COPY_AND_MOVE(FileSystem);
FileSystem();
FileSystem(const std::string& origin, void* extra_data);
virtual ~FileSystem();
// Concreate implementation of FileSystem.
// Depending on the platform, this may be vendor or Widevine implemented.
class Impl;
// defines as bit flag
enum OpenFlags {
kNoFlags = 0,
kCreate = 1,
kReadOnly = 2, // defaults to read and write access
kTruncate = 4
};
// Flags for calls to Open.
static constexpr int kNoFlags = 0;
// Create file if does not already exist, open file if it does exist.
static constexpr int kCreate = (1 << 0);
// Open file as read-only; typically should not be used with kCreate.
static constexpr int kReadOnly = (1 << 1);
// Open file and truncated. May be used with kCreate; should not
// be used with kReadOnly.
static constexpr int kTruncate = (1 << 2);
virtual std::unique_ptr<File> Open(const std::string& file_path, int flags);
virtual bool Exists(const std::string& file_path);
virtual bool Exists(const std::string& file_path, int* errno_value);
virtual bool Remove(const std::string& file_path);
// Checks if the |path| exists. The |path| may be a file or directory.
// Return true if an entry in the file system exists; false otherwise.
virtual bool Exists(const std::string& path);
// Same as above, except the optional parameter of |errno_value| should
// be set to 0 or the value of C errno when attempting to check
// the existence of a file.
virtual bool Exists(const std::string& path, int* errno_value);
// Removes the specified |path|.
//
// If |path| is a regular file, the file should be removed.
// If |path| is a directory, both the directory and the directory
// contents should be removed.
//
// Implementation must support a |path| containing a single wildcard
// character in the filename component of the path.
//
// Return value:
// - true : File/directory was removed, or file/directory did not exist
// - false : File/directory could not be removed, or other error.
virtual bool Remove(const std::string& path);
// Obtain the size of a file in bytes. |file_path| must be a file,
// and not a directory.
//
// Return value:
// - non-negative : size of file in bytes if file exists
// - negative : file does not exist, or error occurred.
virtual ssize_t FileSize(const std::string& file_path);
// Return the filenames stored at dir_path.
// dir_path will be stripped from the returned names.
// Return the entries stored at |dir_path| (includes both files
// and directories).
//
// Return value:
// - true : Directory exists, and directory entry names are stored
// in |names|; |names| may be empty if directory was empty.
// - false : Directory does not exist, |dir_path| is not a directory,
// or error was encountered.
virtual bool List(const std::string& dir_path,
std::vector<std::string>* names);
@@ -78,8 +133,6 @@ class FileSystem {
std::unique_ptr<FileSystem::Impl> impl_;
std::string origin_;
std::string identifier_;
CORE_DISALLOW_COPY_AND_ASSIGN(FileSystem);
};
} // namespace wvutil

View File

@@ -1,9 +1,14 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#include "file_store.h"
#include <errno.h>
#include <set>
#include <string>
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -11,18 +16,20 @@
#include "test_vectors.h"
namespace wvutil {
namespace {
const std::string kTestDirName = "test_dir";
const std::string kTestFileName = "test.txt";
const std::string kTestFileName2 = "test2.txt";
const std::string kTestFileName3 = "test3.other";
const std::string kTestFileNameExt = ".txt";
const std::string kTestFileNameExt3 = ".other";
const std::string kTestIdentifier1 = "some_identifier";
const std::string kTestIdentifier2 = "some_other_identifier";
const std::string kWildcard = "*";
const std::string kUnderscore = "_";
constexpr char kTestFilename[] = "sample.txt";
constexpr char kTestIdentifier1[] = "some_identifier";
constexpr char kTestIdentifier2[] = "some_other_identifier";
constexpr int kNoError = 0;
constexpr int kEntryDoesNotExist = ENOENT;
bool StartsWith(const std::string& haystack, const std::string& needle) {
if (needle.empty()) return true;
if (haystack.size() < needle.size()) return false;
return haystack.find(needle) == 0;
}
} // namespace
class FileTest : public testing::Test {
@@ -32,7 +39,19 @@ class FileTest : public testing::Test {
void TearDown() override { RemoveTestDir(); }
void RemoveTestDir() {
EXPECT_TRUE(file_system_.Remove(wvcdm::test_vectors::kTestDir));
ASSERT_TRUE(file_system_.Remove(wvcdm::test_vectors::kTestDir))
<< "Failed to update test directory: " << wvcdm::test_vectors::kTestDir;
}
std::string PathJoin(const std::string& base_path,
const std::string& add_path) {
if (base_path.empty()) return add_path;
std::string path = base_path;
if (path.back() != '/') {
path.push_back('/');
}
path.append(add_path);
return path;
}
FileSystem file_system_;
@@ -40,336 +59,505 @@ class FileTest : public testing::Test {
TEST_F(FileTest, FileExists) {
int errno_value = -1;
EXPECT_TRUE(file_system_.Exists(wvcdm::test_vectors::kExistentFile));
EXPECT_TRUE(file_system_.Exists(wvcdm::test_vectors::kExistentFile))
<< "path = " << wvcdm::test_vectors::kExistentFile;
EXPECT_TRUE(
file_system_.Exists(wvcdm::test_vectors::kExistentFile, &errno_value));
EXPECT_EQ(0, errno_value);
EXPECT_TRUE(file_system_.Exists(wvcdm::test_vectors::kExistentDir));
file_system_.Exists(wvcdm::test_vectors::kExistentFile, &errno_value))
<< "path = " << wvcdm::test_vectors::kExistentFile;
EXPECT_EQ(kNoError, errno_value);
}
EXPECT_FALSE(file_system_.Exists(wvcdm::test_vectors::kNonExistentFile));
TEST_F(FileTest, FileDoesNotExist) {
int errno_value = -1;
EXPECT_FALSE(file_system_.Exists(wvcdm::test_vectors::kNonExistentFile))
<< "path = " << wvcdm::test_vectors::kNonExistentFile;
EXPECT_FALSE(
file_system_.Exists(wvcdm::test_vectors::kNonExistentFile, &errno_value));
EXPECT_EQ(ENOENT, errno_value);
EXPECT_FALSE(file_system_.Exists(wvcdm::test_vectors::kNonExistentDir));
file_system_.Exists(wvcdm::test_vectors::kNonExistentFile, &errno_value))
<< "path = " << wvcdm::test_vectors::kNonExistentFile;
EXPECT_EQ(kEntryDoesNotExist, errno_value);
}
TEST_F(FileTest, DirectoryExists) {
int errno_value = -1;
EXPECT_TRUE(file_system_.Exists(wvcdm::test_vectors::kExistentDir))
<< "path = " << wvcdm::test_vectors::kExistentDir;
EXPECT_TRUE(
file_system_.Exists(wvcdm::test_vectors::kExistentDir, &errno_value))
<< "path = " << wvcdm::test_vectors::kExistentDir;
EXPECT_EQ(kNoError, errno_value);
}
TEST_F(FileTest, DirectoryDoesNotExist) {
int errno_value = -1;
EXPECT_FALSE(file_system_.Exists(wvcdm::test_vectors::kNonExistentDir))
<< "path = " << wvcdm::test_vectors::kNonExistentDir;
EXPECT_FALSE(
file_system_.Exists(wvcdm::test_vectors::kNonExistentDir, &errno_value))
<< "path = " << wvcdm::test_vectors::kNonExistentDir;
EXPECT_EQ(kEntryDoesNotExist, errno_value);
}
TEST_F(FileTest, RemoveDir) {
EXPECT_TRUE(file_system_.Remove(wvcdm::test_vectors::kTestDir));
EXPECT_FALSE(file_system_.Exists(wvcdm::test_vectors::kTestDir));
EXPECT_TRUE(file_system_.Remove(wvcdm::test_vectors::kTestDir))
<< "path = " << wvcdm::test_vectors::kTestDir;
EXPECT_FALSE(file_system_.Exists(wvcdm::test_vectors::kTestDir))
<< "path = " << wvcdm::test_vectors::kTestDir;
}
TEST_F(FileTest, OpenFile) {
std::string path = wvcdm::test_vectors::kTestDir + kTestFileName;
EXPECT_TRUE(file_system_.Remove(path));
const std::string path =
PathJoin(wvcdm::test_vectors::kTestDir, kTestFilename);
EXPECT_TRUE(file_system_.Remove(path)) << "path = " << path;
std::unique_ptr<File> file = file_system_.Open(path, FileSystem::kCreate);
ASSERT_TRUE(file);
ASSERT_TRUE(file) << "Failed to create file: " << path;
EXPECT_TRUE(file_system_.Exists(path));
EXPECT_TRUE(file_system_.Exists(path)) << "path = " << path;
}
TEST_F(FileTest, RemoveDirAndFile) {
std::string path = wvcdm::test_vectors::kTestDir + kTestFileName;
const std::string path =
PathJoin(wvcdm::test_vectors::kTestDir, kTestFilename);
std::unique_ptr<File> file = file_system_.Open(path, FileSystem::kCreate);
ASSERT_TRUE(file);
ASSERT_TRUE(file) << "Failed to create file: " << path;
EXPECT_TRUE(file_system_.Exists(path));
EXPECT_TRUE(file_system_.Remove(path));
EXPECT_FALSE(file_system_.Exists(path));
EXPECT_TRUE(file_system_.Exists(path)) << "path = " << path;
EXPECT_TRUE(file_system_.Remove(path)) << "path = " << path;
EXPECT_FALSE(file_system_.Exists(path)) << "path = " << path;
file = file_system_.Open(path, FileSystem::kCreate);
ASSERT_TRUE(file);
ASSERT_TRUE(file) << "Failed to create file: " << path;
EXPECT_TRUE(file_system_.Exists(path));
RemoveTestDir();
EXPECT_FALSE(file_system_.Exists(wvcdm::test_vectors::kTestDir));
EXPECT_FALSE(file_system_.Exists(path));
EXPECT_TRUE(file_system_.Exists(path)) << "path = " << path;
ASSERT_NO_FATAL_FAILURE(RemoveTestDir());
EXPECT_FALSE(file_system_.Exists(wvcdm::test_vectors::kTestDir))
<< "path = " << path;
EXPECT_FALSE(file_system_.Exists(path)) << "path = " << path;
}
TEST_F(FileTest, RemoveWildcardFiles) {
std::string path1 = wvcdm::test_vectors::kTestDir + kTestFileName;
std::string path2 = wvcdm::test_vectors::kTestDir + kTestFileName2;
std::string wildcard_path =
wvcdm::test_vectors::kTestDir + kWildcard + kTestFileNameExt;
const std::string path1 =
PathJoin(wvcdm::test_vectors::kTestDir, "first.txt");
const std::string path2 =
PathJoin(wvcdm::test_vectors::kTestDir, "second.txt");
const std::string wildcard_path =
PathJoin(wvcdm::test_vectors::kTestDir, "*.txt");
std::unique_ptr<File> file = file_system_.Open(path1, FileSystem::kCreate);
ASSERT_TRUE(file);
ASSERT_TRUE(file) << "Failed to create file (1): " << path1;
file = file_system_.Open(path2, FileSystem::kCreate);
ASSERT_TRUE(file);
ASSERT_TRUE(file) << "Failed to create file (2): " << path2;
EXPECT_TRUE(file_system_.Exists(path1));
EXPECT_TRUE(file_system_.Exists(path2));
EXPECT_TRUE(file_system_.Remove(wildcard_path));
EXPECT_FALSE(file_system_.Exists(path1));
EXPECT_FALSE(file_system_.Exists(path2));
EXPECT_TRUE(file_system_.Exists(path1)) << "path = " << path1;
EXPECT_TRUE(file_system_.Exists(path2)) << "path = " << path2;
EXPECT_TRUE(file_system_.Remove(wildcard_path))
<< "wildcard_path = " << wildcard_path;
EXPECT_FALSE(file_system_.Exists(path1)) << "path = " << path1;
EXPECT_FALSE(file_system_.Exists(path2)) << "path = " << path2;
}
TEST_F(FileTest, FileSize) {
std::string path = wvcdm::test_vectors::kTestDir + kTestFileName;
const std::string path =
PathJoin(wvcdm::test_vectors::kTestDir, kTestFilename);
file_system_.Remove(path);
std::string write_data = CdmRandom::RandomData(600);
size_t write_data_size = write_data.size();
std::unique_ptr<File> file = file_system_.Open(path, FileSystem::kCreate);
ASSERT_TRUE(file);
EXPECT_EQ(file->Write(write_data.data(), write_data_size), write_data_size);
EXPECT_TRUE(file_system_.Exists(path));
constexpr size_t kDataSize = 600;
const std::string write_data = CdmRandom::RandomData(kDataSize);
ASSERT_EQ(write_data.size(), kDataSize);
EXPECT_EQ(static_cast<ssize_t>(write_data_size), file_system_.FileSize(path));
std::unique_ptr<File> file = file_system_.Open(path, FileSystem::kCreate);
ASSERT_TRUE(file) << "Failed to create file: " << path;
EXPECT_EQ(file->Write(write_data.data(), write_data.size()),
write_data.size());
file.reset(); // Close file.
EXPECT_TRUE(file_system_.Exists(path)) << "path = " << path;
EXPECT_EQ(static_cast<ssize_t>(kDataSize), file_system_.FileSize(path))
<< "path = " << path;
}
TEST_F(FileTest, WriteReadBinaryFile) {
std::string path = wvcdm::test_vectors::kTestDir + kTestFileName;
const std::string path =
PathJoin(wvcdm::test_vectors::kTestDir, kTestFilename);
file_system_.Remove(path);
std::string write_data = CdmRandom::RandomData(600);
size_t write_data_size = write_data.size();
std::unique_ptr<File> file = file_system_.Open(path, FileSystem::kCreate);
ASSERT_TRUE(file);
EXPECT_EQ(file->Write(write_data.data(), write_data_size), write_data_size);
EXPECT_TRUE(file_system_.Exists(path));
constexpr size_t kDataSize = 600;
const std::string write_data = CdmRandom::RandomData(kDataSize);
ASSERT_EQ(write_data.size(), kDataSize);
std::unique_ptr<File> file = file_system_.Open(path, FileSystem::kCreate);
ASSERT_TRUE(file) << "Failed to create file: " << path;
constexpr ssize_t kExpectedFileSizeResult = static_cast<ssize_t>(kDataSize);
EXPECT_EQ(file->Write(write_data.data(), write_data.size()),
kExpectedFileSizeResult)
<< "path = " << path;
file.reset(); // Close file.
EXPECT_TRUE(file_system_.Exists(path)) << "path = " << path;
std::string read_data;
read_data.resize(file_system_.FileSize(path));
size_t read_data_size = read_data.size();
file = file_system_.Open(path, FileSystem::kReadOnly);
ASSERT_TRUE(file);
EXPECT_EQ(file->Read(&read_data[0], read_data_size), read_data_size);
ASSERT_TRUE(file) << "Failed to re-open file: " << path;
std::string read_data(kDataSize, '\0');
;
ASSERT_EQ(file->Read(&read_data[0], read_data.size()),
kExpectedFileSizeResult)
<< "path = " << path;
EXPECT_EQ(write_data, read_data);
}
TEST_F(FileTest, ListFiles) {
std::vector<std::string> names;
const std::string kTxtFilename1 = "data.txt";
const std::string kTxtFilename2 = "other.txt";
const std::string kBinFilename = "sample.bin";
std::string not_path("zzz");
std::string path1 = wvcdm::test_vectors::kTestDir + kTestFileName;
std::string path2 = wvcdm::test_vectors::kTestDir + kTestFileName2;
std::string path3 = wvcdm::test_vectors::kTestDir + kTestFileName3;
std::string path_dir = wvcdm::test_vectors::kTestDir;
const std::string dir_path = wvcdm::test_vectors::kTestDir;
const std::string path1 = PathJoin(dir_path, kTxtFilename1);
const std::string path2 = PathJoin(dir_path, kTxtFilename2);
const std::string path3 = PathJoin(dir_path, kBinFilename);
// Create files.
std::unique_ptr<File> file = file_system_.Open(path1, FileSystem::kCreate);
ASSERT_TRUE(file);
ASSERT_TRUE(file) << "Failed to create file (1): " << path1;
file = file_system_.Open(path2, FileSystem::kCreate);
ASSERT_TRUE(file);
ASSERT_TRUE(file) << "Failed to create file (2): " << path2;
file = file_system_.Open(path3, FileSystem::kCreate);
ASSERT_TRUE(file);
ASSERT_TRUE(file) << "Failed to create file (3): " << path3;
file.reset(); // Close file
EXPECT_TRUE(file_system_.Exists(path1));
EXPECT_TRUE(file_system_.Exists(path2));
EXPECT_TRUE(file_system_.Exists(path3));
// Ask for non-existent path.
EXPECT_FALSE(file_system_.List(not_path, &names));
std::vector<std::string> names;
ASSERT_TRUE(file_system_.List(dir_path, &names)) << "dir_path = " << dir_path;
// Valid path, but no way to return names.
EXPECT_FALSE(file_system_.List(path_dir, nullptr));
size_t expected_file_count = 3;
EXPECT_EQ(names.size(), expected_file_count);
// Valid path, valid return.
EXPECT_TRUE(file_system_.List(path_dir, &names));
// Should find three files. Order not important.
EXPECT_EQ(3u, names.size());
// Should find the three files. Order not important.
EXPECT_THAT(names, ::testing::UnorderedElementsAre(
kTestFileName, kTestFileName2, kTestFileName3));
kTxtFilename1, kTxtFilename2, kBinFilename));
std::string wild_card_path = path_dir + kWildcard + kTestFileNameExt;
EXPECT_TRUE(file_system_.Remove(wild_card_path));
EXPECT_TRUE(file_system_.List(path_dir, &names));
// Remove .txt files.
const std::string txt_wildcard_path = PathJoin(dir_path, "*.txt");
EXPECT_EQ(1u, names.size());
EXPECT_TRUE(names[0].compare(kTestFileName3) == 0);
EXPECT_TRUE(file_system_.Remove(txt_wildcard_path))
<< "txt_wildcard_path = " << txt_wildcard_path;
EXPECT_TRUE(file_system_.List(dir_path, &names)) << "dir_path = " << dir_path;
std::string wild_card_path2 = path_dir + kWildcard + kTestFileNameExt3;
EXPECT_TRUE(file_system_.Remove(wild_card_path2));
EXPECT_TRUE(file_system_.List(path_dir, &names));
expected_file_count = 1;
ASSERT_EQ(names.size(), expected_file_count);
EXPECT_EQ(names.front(), kBinFilename);
EXPECT_EQ(0u, names.size());
const std::string bin_wildcard_path = PathJoin(dir_path, "*.bin");
EXPECT_TRUE(file_system_.Remove(bin_wildcard_path))
<< "bin_wildcard_path = " << bin_wildcard_path;
// All files should be removed, but listing should still succeed.
EXPECT_TRUE(file_system_.List(dir_path, &names)) << "dir_path = " << dir_path;
expected_file_count = 0;
EXPECT_EQ(expected_file_count, names.size());
}
TEST_F(FileTest, CreateGlobalCertificates) {
// Clear directory
TEST_F(FileTest, ListFiles_NotAPath) {
const std::string not_path("zzz/xxx");
std::vector<std::string> names;
std::string path_dir = wvcdm::test_vectors::kTestDir;
std::string wild_card_path = path_dir + kWildcard;
file_system_.Remove(wild_card_path);
if (file_system_.List(path_dir, &names)) {
EXPECT_EQ(0u, names.size());
// Ask for non-existent path.
EXPECT_FALSE(file_system_.List(not_path, &names));
}
TEST_F(FileTest, ListFiles_NullParameter) {
const std::string dir_path = wvcdm::test_vectors::kTestDir;
const std::string path = PathJoin(dir_path, kTestFilename);
std::unique_ptr<File> file = file_system_.Open(path, FileSystem::kCreate);
ASSERT_TRUE(file) << "Failed to create file: " << path;
file.reset(); // Close file.
// Valid path, but no way to return names.
EXPECT_FALSE(file_system_.List(dir_path, nullptr));
}
// On certain platforms, the FileSystem may perform special
// name translations on certificate filenames which make them behave
// differently from non-certificate filenames.
TEST_F(FileTest, CreateGlobalCertificates) {
ASSERT_TRUE(file_system_.IsGlobal())
<< "Test case requires global file system";
const std::string dir_path = wvcdm::test_vectors::kTestDir;
// Clear directory
const std::string all_file_wildcard_path = PathJoin(dir_path, "*");
file_system_.Remove(all_file_wildcard_path);
// Ensure directory is empty.
std::vector<std::string> names;
if (file_system_.List(dir_path, &names)) {
constexpr size_t kZero = 0;
ASSERT_EQ(kZero, names.size()) << "Test requires empty directory";
}
// Create certificates and verify that they exist
std::string certificate_path =
wvcdm::test_vectors::kTestDir + kCertificateFileName;
std::string legacy_certificate_path =
wvcdm::test_vectors::kTestDir + kLegacyCertificateFileName;
const std::string certificate_path = PathJoin(dir_path, kCertificateFileName);
const std::string legacy_certificate_path =
PathJoin(dir_path, kLegacyCertificateFileName);
// Create certificates and verify that they exist
std::unique_ptr<File> file =
file_system_.Open(certificate_path, FileSystem::kCreate);
ASSERT_TRUE(file);
ASSERT_TRUE(file) << "Failed to create certificate file: "
<< certificate_path;
file = file_system_.Open(legacy_certificate_path, FileSystem::kCreate);
ASSERT_TRUE(file);
EXPECT_TRUE(file_system_.IsGlobal());
ASSERT_TRUE(file) << "Failed to create legacy certificate file: "
<< legacy_certificate_path;
file.reset(); // Close file.
EXPECT_TRUE(file_system_.Exists(certificate_path));
EXPECT_TRUE(file_system_.Exists(legacy_certificate_path));
EXPECT_TRUE(file_system_.Exists(certificate_path))
<< "certificate_path = " << certificate_path;
EXPECT_TRUE(file_system_.Exists(legacy_certificate_path))
<< "legacy_certificate_path = " << legacy_certificate_path;
EXPECT_TRUE(file_system_.List(path_dir, &names));
ASSERT_TRUE(file_system_.List(dir_path, &names));
// Should find two files. Order not important.
EXPECT_EQ(2u, names.size());
constexpr size_t kExpectedCount = 2;
EXPECT_EQ(kExpectedCount, names.size());
EXPECT_THAT(names, ::testing::UnorderedElementsAre(
kCertificateFileName, kLegacyCertificateFileName));
}
// On certain platforms, the FileSystem may perform special
// name translations on certificate filenames which make them behave
// differently from non-certificate filenames.
TEST_F(FileTest, CreateCertificates) {
ASSERT_TRUE(file_system_.IsGlobal())
<< "Test case requires starting with a global file system";
const std::string dir_path = wvcdm::test_vectors::kTestDir;
// Clear directory
const std::string all_file_wildcard_path = PathJoin(dir_path, "*");
file_system_.Remove(all_file_wildcard_path);
// Ensure directory is empty.
std::vector<std::string> names;
std::string path_dir = wvcdm::test_vectors::kTestDir;
std::string wild_card_path = path_dir + kWildcard;
file_system_.Remove(wild_card_path);
if (file_system_.List(path_dir, &names)) {
EXPECT_EQ(0u, names.size());
if (file_system_.List(dir_path, &names)) {
constexpr size_t kZero = 0;
ASSERT_EQ(kZero, names.size()) << "Test requires empty directory";
}
std::string certificate_path =
wvcdm::test_vectors::kTestDir + kCertificateFileName;
std::string legacy_certificate_path =
wvcdm::test_vectors::kTestDir + kLegacyCertificateFileName;
const std::string certificate_path = PathJoin(dir_path, kCertificateFileName);
const std::string legacy_certificate_path =
PathJoin(dir_path, kLegacyCertificateFileName);
// Create Global certificates
// Create Global certificates.
std::unique_ptr<File> file =
file_system_.Open(certificate_path, FileSystem::kCreate);
ASSERT_TRUE(file);
ASSERT_TRUE(file) << "Failed to create global certificate: "
<< certificate_path;
file = file_system_.Open(legacy_certificate_path, FileSystem::kCreate);
ASSERT_TRUE(file);
EXPECT_TRUE(file_system_.IsGlobal());
ASSERT_TRUE(file) << "Failed to create global legacy certificate: "
<< legacy_certificate_path;
file.reset(); // Close file.
EXPECT_TRUE(file_system_.Exists(certificate_path))
<< "Global certificate: " << certificate_path;
EXPECT_TRUE(file_system_.Exists(legacy_certificate_path))
<< "Global legacy certificate: " << legacy_certificate_path;
// Switch to first identifier.
file_system_.set_identifier(kTestIdentifier1);
ASSERT_FALSE(file_system_.IsGlobal()) << "identifier = " << kTestIdentifier1;
// Global certificates should not be visible once identifier has been
// specified.
EXPECT_FALSE(file_system_.Exists(certificate_path))
<< kTestIdentifier1 << " certificate: " << certificate_path;
EXPECT_FALSE(file_system_.Exists(legacy_certificate_path))
<< kTestIdentifier1 << " legacy certificate: " << legacy_certificate_path;
// Create certificates with first identifier
file_system_.set_identifier(kTestIdentifier1);
file = file_system_.Open(certificate_path, FileSystem::kCreate);
ASSERT_TRUE(file);
ASSERT_TRUE(file) << "Failed to create " << kTestIdentifier1
<< " certificate: " << certificate_path;
file = file_system_.Open(legacy_certificate_path, FileSystem::kCreate);
ASSERT_TRUE(file);
EXPECT_TRUE(!file_system_.IsGlobal());
ASSERT_TRUE(file) << "Failed to create " << kTestIdentifier1
<< " legacy certificate: " << legacy_certificate_path;
file.reset(); // Close file.
// Verify they now exist.
EXPECT_TRUE(file_system_.Exists(certificate_path))
<< kTestIdentifier1 << " certificate: " << certificate_path;
EXPECT_TRUE(file_system_.Exists(legacy_certificate_path))
<< kTestIdentifier1 << " legacy certificate: " << legacy_certificate_path;
// Switch to second identifier.
file_system_.set_identifier(kTestIdentifier2);
ASSERT_FALSE(file_system_.IsGlobal()) << "identifier = " << kTestIdentifier2;
// Global and first identifier certificates should not be
// visible.
EXPECT_FALSE(file_system_.Exists(certificate_path))
<< kTestIdentifier2 << " certificate: " << certificate_path;
EXPECT_FALSE(file_system_.Exists(legacy_certificate_path))
<< kTestIdentifier2 << " legacy certificate: " << legacy_certificate_path;
// Create certificates with second identifier
file_system_.set_identifier(kTestIdentifier2);
file = file_system_.Open(certificate_path, FileSystem::kCreate);
ASSERT_TRUE(file);
ASSERT_TRUE(file) << "Failed to create " << kTestIdentifier2
<< " certificate: " << certificate_path;
file = file_system_.Open(legacy_certificate_path, FileSystem::kCreate);
ASSERT_TRUE(file);
EXPECT_TRUE(!file_system_.IsGlobal());
ASSERT_TRUE(file) << "Failed to create " << kTestIdentifier2
<< " legacy certificate: " << legacy_certificate_path;
file.reset(); // Close file.
EXPECT_TRUE(file_system_.Exists(certificate_path));
EXPECT_TRUE(file_system_.Exists(legacy_certificate_path));
// Verify they now exist.
EXPECT_TRUE(file_system_.Exists(certificate_path))
<< kTestIdentifier2 << " certificate: " << certificate_path;
EXPECT_TRUE(file_system_.Exists(legacy_certificate_path))
<< kTestIdentifier2 << " legacy certificate: " << legacy_certificate_path;
EXPECT_TRUE(file_system_.List(path_dir, &names));
// FileSystem::List is expected to still return all certificate files
// (both global and scoped).
ASSERT_TRUE(file_system_.List(dir_path, &names)) << "dir_path = " << dir_path;
// Should find six files. Order not important.
constexpr size_t kExpectedTotalCertCount = 6;
ASSERT_EQ(names.size(), kExpectedTotalCertCount);
bool is_global_certificate_present = false;
bool is_global_legacy_certificate_present = false;
size_t certificate_count = 0;
size_t legacy_certificate_count = 0;
EXPECT_EQ(6u, names.size());
for (size_t i = 0; i < names.size(); ++i) {
if (names[i].size() > kCertificateFileName.size()) {
if (names[i].compare(0, kCertificateFileNamePrefix.size(),
kCertificateFileNamePrefix) == 0)
++certificate_count;
else if (names[i].compare(0, kLegacyCertificateFileNamePrefix.size(),
kLegacyCertificateFileNamePrefix) == 0)
++legacy_certificate_count;
} else if (names[i].compare(kCertificateFileName) == 0) {
is_global_certificate_present = true;
} else if (names[i].compare(kLegacyCertificateFileName) == 0) {
for (const auto& filename : names) {
if (filename == kLegacyCertificateFileName) {
is_global_legacy_certificate_present = true;
} else if (filename == kCertificateFileName) {
is_global_certificate_present = true;
} else if (StartsWith(filename, kScopedCertificateFilenamePrefix)) {
certificate_count++;
} else if (StartsWith(filename, kLegacyScopedCertificateFilenamePrefix)) {
legacy_certificate_count++;
} else {
EXPECT_TRUE(false);
ADD_FAILURE() << "Unexpected filename: " << filename;
}
}
EXPECT_EQ(2, certificate_count);
EXPECT_EQ(2, legacy_certificate_count);
EXPECT_TRUE(is_global_certificate_present);
EXPECT_TRUE(is_global_legacy_certificate_present);
constexpr size_t kExpectedScopedCertCount = 2;
EXPECT_EQ(certificate_count, kExpectedScopedCertCount)
<< "Missing certificates";
EXPECT_EQ(legacy_certificate_count, kExpectedScopedCertCount)
<< "Missing legacy certificates";
EXPECT_TRUE(is_global_certificate_present)
<< "Missing global certificate: " << kCertificateFileName;
EXPECT_TRUE(is_global_legacy_certificate_present)
<< "Missing legacy global certificate: " << kLegacyCertificateFileName;
}
// On certain platforms, the FileSystem may perform special
// name translations on certificate file names which make them behave
// differently from non-certificate file names.
TEST_F(FileTest, RemoveCertificates) {
ASSERT_TRUE(file_system_.IsGlobal())
<< "Test case requires starting with a global file system";
const std::string dir_path = wvcdm::test_vectors::kTestDir;
// Clear directory
const std::string all_file_wildcard_path = PathJoin(dir_path, "*");
file_system_.Remove(all_file_wildcard_path);
// Ensure directory is empty.
std::vector<std::string> names;
std::string path_dir = wvcdm::test_vectors::kTestDir;
std::string wild_card_path = path_dir + kWildcard;
file_system_.Remove(wild_card_path);
if (file_system_.List(path_dir, &names)) {
EXPECT_EQ(0u, names.size());
if (file_system_.List(dir_path, &names)) {
constexpr size_t kZero = 0;
ASSERT_EQ(kZero, names.size()) << "Test requires empty directory";
}
std::string certificate_path =
wvcdm::test_vectors::kTestDir + kCertificateFileName;
std::string legacy_certificate_path =
wvcdm::test_vectors::kTestDir + kLegacyCertificateFileName;
const std::string certificate_path = PathJoin(dir_path, kCertificateFileName);
const std::string legacy_certificate_path =
PathJoin(dir_path, kLegacyCertificateFileName);
// Create Global certificates
// Create Global certificates.
std::unique_ptr<File> file =
file_system_.Open(certificate_path, FileSystem::kCreate);
ASSERT_TRUE(file);
ASSERT_TRUE(file) << "Failed to create global certificate: "
<< certificate_path;
file = file_system_.Open(legacy_certificate_path, FileSystem::kCreate);
ASSERT_TRUE(file);
EXPECT_TRUE(file_system_.IsGlobal());
ASSERT_TRUE(file) << "Failed to create global legacy certificate: "
<< legacy_certificate_path;
file.reset(); // Close file.
// Switch to first identifier.
file_system_.set_identifier(kTestIdentifier1);
ASSERT_FALSE(file_system_.IsGlobal()) << "identifier = " << kTestIdentifier1;
// Create certificates with first identifier
file_system_.set_identifier(kTestIdentifier1);
file = file_system_.Open(certificate_path, FileSystem::kCreate);
ASSERT_TRUE(file);
ASSERT_TRUE(file) << "Failed to create " << kTestIdentifier1
<< " certificate: " << certificate_path;
file = file_system_.Open(legacy_certificate_path, FileSystem::kCreate);
ASSERT_TRUE(file);
EXPECT_TRUE(!file_system_.IsGlobal());
ASSERT_TRUE(file) << "Failed to create " << kTestIdentifier1
<< " legacy certificate: " << legacy_certificate_path;
file.reset(); // Close file.
// Switch to second identifier.
file_system_.set_identifier(kTestIdentifier2);
ASSERT_FALSE(file_system_.IsGlobal()) << "identifier = " << kTestIdentifier2;
// Create certificates with second identifier
file_system_.set_identifier(kTestIdentifier2);
file = file_system_.Open(certificate_path, FileSystem::kCreate);
ASSERT_TRUE(file);
ASSERT_TRUE(file) << "Failed to create " << kTestIdentifier2
<< " certificate: " << certificate_path;
file = file_system_.Open(legacy_certificate_path, FileSystem::kCreate);
ASSERT_TRUE(file);
EXPECT_TRUE(!file_system_.IsGlobal());
ASSERT_TRUE(file) << "Failed to create " << kTestIdentifier2
<< " legacy certificate: " << legacy_certificate_path;
file.reset(); // Close file.
EXPECT_TRUE(file_system_.Exists(certificate_path));
EXPECT_TRUE(file_system_.Exists(legacy_certificate_path));
EXPECT_TRUE(file_system_.List(path_dir, &names));
EXPECT_EQ(6u, names.size());
// FileSystem::List is expected to still return all certificate files
// (both global and scoped).
ASSERT_TRUE(file_system_.List(dir_path, &names)) << "dir_path = " << dir_path;
// Should find six files. Order not important.
constexpr size_t kExpectedTotalCertCount = 6;
ASSERT_EQ(names.size(), kExpectedTotalCertCount);
std::set<std::string> removed_certs;
// Remove all even number listed files
for (size_t i = 0; i < names.size(); ++i) {
if (i % 2 == 0) {
EXPECT_TRUE(
file_system_.Remove(wvcdm::test_vectors::kTestDir + names[i]));
}
if ((i % 2) != 0) continue;
const std::string& cert_filename = names[i];
const std::string cert_path = PathJoin(dir_path, cert_filename);
ASSERT_TRUE(file_system_.Remove(cert_path))
<< "Failed to remove cert: " << cert_path;
removed_certs.insert(cert_filename);
}
// Verify that they have been removed
for (size_t i = 0; i < names.size(); ++i) {
if (i % 2 == 1) {
EXPECT_TRUE(
file_system_.Exists(wvcdm::test_vectors::kTestDir + names[i]));
for (const std::string& cert_filename : names) {
const std::string cert_path = PathJoin(dir_path, cert_filename);
if (removed_certs.find(cert_filename) == removed_certs.end()) {
// Ensure still exists.
ASSERT_TRUE(file_system_.Exists(cert_path))
<< "Cert missing: " << cert_filename;
} else {
EXPECT_FALSE(
file_system_.Exists(wvcdm::test_vectors::kTestDir + names[i]));
ASSERT_FALSE(file_system_.Exists(cert_path))
<< "Cert not removed: " << cert_filename;
}
}
// Remove all odd number listed files
for (size_t i = 0; i < names.size(); ++i) {
if (i % 2 == 1) {
EXPECT_TRUE(
file_system_.Remove(wvcdm::test_vectors::kTestDir + names[i]));
}
// Remove all remaining.
for (const std::string& cert_filename : names) {
if (removed_certs.find(cert_filename) != removed_certs.end()) continue;
const std::string cert_path = PathJoin(dir_path, cert_filename);
ASSERT_TRUE(file_system_.Remove(cert_path))
<< "Failed to remove cert: " << cert_path;
}
// Verify that all have been removed
for (size_t i = 0; i < names.size(); ++i) {
EXPECT_FALSE(file_system_.Exists(wvcdm::test_vectors::kTestDir + names[i]));
for (const std::string& cert_filename : names) {
const std::string cert_path = PathJoin(dir_path, cert_filename);
EXPECT_FALSE(file_system_.Exists(cert_path))
<< "Cert not removed: " << cert_filename;
}
}
} // namespace wvutil

View File

@@ -20,9 +20,9 @@ class FakeClock : public TestSleep::CallBack {
FakeClock() {
auto now = std::chrono::system_clock().now();
now_ = now.time_since_epoch() / std::chrono::milliseconds(1);
TestSleep::set_callback(this);
TestSleep::AddCallback(this);
}
~FakeClock() { TestSleep::set_callback(nullptr); }
~FakeClock() { TestSleep::RemoveCallback(this); }
void ElapseTime(int64_t milliseconds) { now_ += milliseconds; }
int64_t now() const { return now_; }

View File

@@ -26,7 +26,7 @@
namespace wvutil {
bool TestSleep::real_sleep_ = true;
TestSleep::CallBack* TestSleep::callback_ = nullptr;
std::unordered_set<TestSleep::CallBack*> TestSleep::callbacks_;
int TestSleep::total_clock_rollback_seconds_ = 0;
void TestSleep::Sleep(unsigned int seconds) {
@@ -52,7 +52,7 @@ void TestSleep::Sleep(unsigned int seconds) {
milliseconds = total_real - fake_clock;
fake_clock += milliseconds;
}
if (callback_ != nullptr) callback_->ElapseTime(milliseconds);
for (auto* cb : callbacks_) cb->ElapseTime(milliseconds);
}
void TestSleep::SleepUntil(int64_t desired_time) {
@@ -80,9 +80,8 @@ void TestSleep::SetFakeClock(int64_t time_seconds) {
// by the current time on a real clock, and then the command line
// re-initializes it to 0, then delta is negative.
int64_t delta = time_seconds - Clock().GetCurrentTime();
if (callback_ != nullptr) {
callback_->ElapseTime(delta * 1000);
} else {
for (auto* cb : callbacks_) cb->ElapseTime(delta * 1000);
if (callbacks_.empty()) {
LOGE("Setting fake clock with no callback. This won't work.");
}
}
@@ -130,8 +129,8 @@ bool TestSleep::RollbackSystemTime(int seconds) {
// For both real and fake sleep we still update the callback and we still keep
// track of the total amount of time slept.
total_clock_rollback_seconds_ += seconds;
if (callback_ != nullptr) {
callback_->ElapseTime(-1000 * static_cast<int64_t>(seconds));
for (auto* cb : callbacks_) {
cb->ElapseTime(-1000 * static_cast<int64_t>(seconds));
}
return true;
}

View File

@@ -9,6 +9,8 @@
#include <stdint.h>
#include <unordered_set>
namespace wvutil {
class TestSleep {
@@ -67,13 +69,18 @@ class TestSleep {
static bool real_sleep() { return real_sleep_; }
// The callback is notified whenever sleep is called.
static void set_callback(CallBack* callback) { callback_ = callback; }
static void AddCallback(CallBack* callback) {
callbacks_.insert(callback);
}
static void RemoveCallback(CallBack* callback) {
callbacks_.erase(callback);
}
private:
// Controls if the test sleep should use real sleep.
static bool real_sleep_;
// Called when the clock should advance.
static CallBack* callback_;
static std::unordered_set<CallBack*> callbacks_;
// The sum of all calls to RollBackSystemTime. Kept so we can undo all changes
// at the end of a test.
static int total_clock_rollback_seconds_;