Refactor Input/Output file to use const char* instead of standard string, and to use parent_folder and file_name for input and output files. This also incorporates the move from nearby_connections to nearby.

PiperOrigin-RevId: 415587802
This commit is contained in:
jfcarroll
2021-12-10 12:49:50 -08:00
committed by Copybara-Service
parent 5ba6623eac
commit f12bb6c405
48 changed files with 540 additions and 377 deletions
+10 -8
View File
@@ -61,6 +61,9 @@ class ImplementationPlatform {
// - file I/O
// - Logging
static std::unique_ptr<std::string> GetDownloadPath(
std::unique_ptr<std::string> path);
// Atomics:
// =======
@@ -78,12 +81,11 @@ class ImplementationPlatform {
std::int32_t count);
static std::unique_ptr<Mutex> CreateMutex(Mutex::Mode mode);
static std::unique_ptr<ConditionVariable> CreateConditionVariable(
Mutex* mutex);
static std::unique_ptr<InputFile> CreateInputFile(PayloadId payload_id,
std::int64_t total_size);
static std::unique_ptr<OutputFile> CreateOutputFile(PayloadId payload_id);
Mutex *mutex);
static std::unique_ptr<InputFile> CreateInputFile(const char *file_path);
static std::unique_ptr<OutputFile> CreateOutputFile(const char *file_path);
static std::unique_ptr<LogMessage> CreateLogMessage(
const char* file, int line, LogMessage::Severity severity);
const char *file, int line, LogMessage::Severity severity);
// Java-like Executors
static std::unique_ptr<SubmittableExecutor> CreateSingleThreadExecutor();
@@ -94,10 +96,10 @@ class ImplementationPlatform {
// Protocol implementations, domain-specific support
static std::unique_ptr<BluetoothAdapter> CreateBluetoothAdapter();
static std::unique_ptr<BluetoothClassicMedium> CreateBluetoothClassicMedium(
BluetoothAdapter&);
static std::unique_ptr<BleMedium> CreateBleMedium(BluetoothAdapter&);
BluetoothAdapter &);
static std::unique_ptr<BleMedium> CreateBleMedium(BluetoothAdapter &);
static std::unique_ptr<ble_v2::BleMedium> CreateBleV2Medium(
BluetoothAdapter&);
BluetoothAdapter &);
static std::unique_ptr<ServerSyncMedium> CreateServerSyncMedium();
static std::unique_ptr<WifiMedium> CreateWifiMedium();
static std::unique_ptr<WifiLanMedium> CreateWifiLanMedium();
+1
View File
@@ -29,6 +29,7 @@ cc_library(
"bluetooth_utils.h",
"byte_array.h",
"callable.h",
"core_config.h",
"exception.h",
"feature_flags.h",
"input_stream.h",
+38
View File
@@ -0,0 +1,38 @@
// Copyright 2020 Google LLC
//
// 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
//
// https://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 CORE_CONFIG_H_
#define CORE_CONFIG_H_
namespace location {
namespace nearby {
namespace connections {
#ifdef _WIN32 // These storage class specifiers only matter to win32 dll
// builds.
#ifdef CORE_ADAPTER_DLL
#define DLL_API \
__declspec(dllexport) // If we're building the core, we're exporting.
#else // !CORE_ADAPTER_DLL
#define DLL_API \
__declspec(dllimport) // If we're not building the core, we're importing.
#endif // CORE_ADAPTER_DLL
#else // !_WIN32
#define DLL_API // We're not building a win32 dll, leave the source unchanged.
#endif // _WIN32
} // namespace connections
} // namespace nearby
} // namespace location
#endif // CORE_CONFIG_H_
+8 -9
View File
@@ -55,11 +55,11 @@ namespace location {
namespace nearby {
namespace api {
namespace {
std::string GetPayloadPath(PayloadId payload_id) {
return absl::StrCat("/tmp/", payload_id);
std::unique_ptr<std::string> ImplementationPlatform::GetDownloadPath(
std::unique_ptr<std::string> path) {
std::string basePath("/tmp/");
return std::make_unique<std::string>(basePath += *path);
}
} // namespace
int GetCurrentTid() {
const LiveThread* my = Thread_GetMyLiveThread();
@@ -102,14 +102,13 @@ std::unique_ptr<AtomicBoolean> ImplementationPlatform::CreateAtomicBoolean(
}
std::unique_ptr<InputFile> ImplementationPlatform::CreateInputFile(
PayloadId payload_id, std::int64_t total_size) {
return absl::make_unique<shared::InputFile>(GetPayloadPath(payload_id),
total_size);
const char* file_path) {
return absl::make_unique<shared::InputFile>(file_path);
}
std::unique_ptr<OutputFile> ImplementationPlatform::CreateOutputFile(
PayloadId payload_id) {
return absl::make_unique<shared::OutputFile>(GetPayloadPath(payload_id));
const char* file_path) {
return absl::make_unique<shared::OutputFile>(file_path);
}
std::unique_ptr<LogMessage> ImplementationPlatform::CreateLogMessage(
@@ -161,7 +161,10 @@ class GNCInputStreamFromNSStream : public InputStream {
PayloadId payloadId = Payload::GenerateId();
// Add the pair of payloadId and fileURL to the map in the GNCCore.
[_core insertURLToMapWithPayloadID:payloadId urlToSend:fileURL];
Payload corePayload(payloadId, InputFile(payloadId, fileSize));
// TODO(edwinwu): Need someone familiar with iOS to fix this
std::string path("FIXME, WE NEED A PATH HERE");
Payload corePayload(payloadId, InputFile(path.c_str()));
progress.totalUnitCount = fileSize;
return [self sendPayload:std::move(corePayload)
size:fileSize
@@ -146,7 +146,7 @@ void GNCPayloadListener::OnPayload(const std::string &endpoint_id, Payload paylo
case Payload::Type::kFile:
if (handlers.filePayloadHandler) {
InputFile *payloadInputFile = payload.AsFile();
const InputFile *payloadInputFile = payload.AsFile();
NSURL *fileURL =
[NSURL URLWithString:ObjCStringFromCppString(payloadInputFile->GetFilePath())];
int64_t fileSize = payloadInputFile->GetTotalSize();
@@ -37,18 +37,11 @@ namespace location {
namespace nearby {
namespace api {
namespace {
std::string GetPayloadPath(PayloadId payload_id) {
// This is to get a file path, e.g. /tmp/[payload_id], for the storage of payload file.
// NOTE: Per
// https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html
// Files saved in the /tmp directory will be deleted by the system. Callers should be responsible
// for copying the files to the permanent storage.
NSString *payloadIdString = ObjCStringFromCppString(std::to_string(payload_id));
return CppStringFromObjCString(
[NSTemporaryDirectory() stringByAppendingPathComponent:payloadIdString]);
std::unique_ptr<std::string> ImplementationPlatform::GetDownloadPath(
std::unique_ptr<std::string> path) {
// TODO(jfcarroll): Fixme, we need to modulate the path the the system download path
return path;
}
} // namespace
// Atomics:
std::unique_ptr<AtomicBoolean> ImplementationPlatform::CreateAtomicBoolean(bool initial_value) {
@@ -78,22 +71,25 @@ std::unique_ptr<ConditionVariable> ImplementationPlatform::CreateConditionVariab
return std::make_unique<ios::ConditionVariable>(static_cast<ios::Mutex*>(mutex));
}
std::unique_ptr<InputFile> ImplementationPlatform::CreateInputFile(PayloadId payload_id,
std::int64_t total_size) {
// Extract the NSURL object with payload_id from |GNCCore| which stores the maps. If the retrieved
// NSURL object is not nil, we create InputFile by ios::InputFile. The difference is
// that ios::InputFile implements to read bytes from local real file for sending.
std::unique_ptr<InputFile> ImplementationPlatform::CreateInputFile(const char* file_path) {
// Extract the NSURL object with payload_id from |GNCCore| which stores the maps. If the retrieved
// NSURL object is not nil, we create InputFile by ios::InputFile. The difference is
// that ios::InputFile implements to read bytes from local real file for sending.
// TODO(jfcarroll): Need someone familiar with iOS to fix this
#if 0
GNCCore* core = GNCGetCore();
NSURL* url = [core extractURLWithPayloadID:payload_id];
if (url != nil) {
return absl::make_unique<ios::InputFile>(url);
} else {
return absl::make_unique<shared::InputFile>(GetPayloadPath(payload_id), total_size);
return absl::make_unique<shared::InputFile>(GetDownloadPath(payload_id), total_size);
}
#endif
return nullptr;
}
std::unique_ptr<OutputFile> ImplementationPlatform::CreateOutputFile(PayloadId payload_id) {
return absl::make_unique<shared::OutputFile>(GetPayloadPath(payload_id));
std::unique_ptr<OutputFile> ImplementationPlatform::CreateOutputFile(const char* file_path) {
return absl::make_unique<shared::OutputFile>(file_path);
}
std::unique_ptr<LogMessage> ImplementationPlatform::CreateLogMessage(
+1 -1
View File
@@ -23,7 +23,7 @@ objc_library(
srcs = [
"Platform/GNCCryptoTest.mm",
"Platform/GNCInputFileTest.mm",
"Platform/GNCMultiThreadExecutorTest.mm",
#"Platform/GNCMultiThreadExecutorTest.mm",
"Platform/GNCScheduledExecutorTest.mm",
"Platform/GNCSingleThreadExecutorTest.mm",
],
+23 -4
View File
@@ -25,9 +25,21 @@ namespace nearby {
namespace shared {
// InputFile
InputFile::InputFile(const char* file_path) : file_path_(file_path) {
// Open the file with the current location at eof (std::ios::ate)
// std::ios::binary - specifies binary access mode
// std::ios::in - allows input (read operations) from a stream
// std::ios::ate - sets the stream's position indicator to the
// end of the stream on opening.
file_.open(std::string(file_path),
std::ios::binary | std::ios::in | std::ios::ate);
InputFile::InputFile(const std::string& path, std::int64_t size)
: file_(path, std::ios::binary), path_(path), total_size_(size) {}
// Read the current position in the file and use that for total size.
total_size_ = file_.tellg();
// Reset to the beginning of the file.
file_.seekg(0);
}
ExceptionOr<ByteArray> InputFile::Read(std::int64_t size) {
if (!file_.is_open()) {
@@ -62,8 +74,15 @@ Exception InputFile::Close() {
// OutputFile
OutputFile::OutputFile(absl::string_view path)
: file_(std::string(path), std::ios::binary) {}
OutputFile::OutputFile(const char* file_path) {
// std::ios::binary - specifies binary access mode
// std::ios::out - allows output (read operations) from
// a stream
// std::ios::trunc - when the file is opened, the old
// contents are immediately removed.
file_ = std::ofstream(file_path,
std::ios::binary | std::ios::out | std::ios::trunc);
}
Exception OutputFile::Write(const ByteArray& data) {
if (!file_.is_open()) {
+7 -7
View File
@@ -29,25 +29,25 @@ namespace shared {
class InputFile final : public api::InputFile {
public:
explicit InputFile(const std::string& path, std::int64_t size);
explicit InputFile(const char* file_path);
~InputFile() override = default;
InputFile(InputFile&&) = default;
InputFile& operator=(InputFile&&) = default;
ExceptionOr<ByteArray> Read(std::int64_t size) override;
std::string GetFilePath() const override { return path_; }
std::int64_t GetTotalSize() const override { return total_size_; }
ExceptionOr<ByteArray> Read(int64_t size) override;
std::string GetFilePath() const override { return file_path_; }
int64_t GetTotalSize() const override { return total_size_; }
Exception Close() override;
private:
std::ifstream file_;
std::string path_;
std::int64_t total_size_;
std::string file_path_;
int64_t total_size_;
};
class OutputFile final : public api::OutputFile {
public:
explicit OutputFile(absl::string_view path);
explicit OutputFile(const char* file_path);
~OutputFile() override = default;
OutputFile(OutputFile&&) = default;
OutputFile& operator=(OutputFile&&) = default;
+19 -13
View File
@@ -14,7 +14,9 @@
#include "platform/impl/shared/file.h"
#include <codecvt>
#include <cstring>
#include <filesystem>
#include <fstream>
#include <memory>
#include <ostream>
@@ -24,6 +26,10 @@
#include "absl/strings/string_view.h"
#include "platform/base/byte_array.h"
#define TEST_FILE_NAME std::string("testfilename.txt")
#define TEST_INVALID_PARENT_FOLDER \
std::string("fake/path/that/has/not/been/created/")
namespace location {
namespace nearby {
namespace shared {
@@ -32,7 +38,7 @@ class FileTest : public ::testing::Test {
protected:
void SetUp() override {
temp_path_ = std::make_unique<TempPath>(TempPath::Local);
path_ = temp_path_->path() + "/file.txt";
path_ = temp_path_->path() + "/" + TEST_FILE_NAME;
std::ofstream output_file(path_);
file_ = std::fstream(path_, std::fstream::in | std::fstream::out);
}
@@ -65,39 +71,39 @@ class FileTest : public ::testing::Test {
};
TEST_F(FileTest, InputFile_NonExistentPath) {
InputFile input_file("/not/a/valid/path.txt", GetSize());
InputFile input_file((TEST_INVALID_PARENT_FOLDER + TEST_FILE_NAME).c_str());
ExceptionOr<ByteArray> read_result = input_file.Read(kMaxSize);
EXPECT_FALSE(read_result.ok());
EXPECT_TRUE(read_result.GetException().Raised(Exception::kIo));
}
TEST_F(FileTest, InputFile_GetFilePath) {
InputFile input_file(path_, GetSize());
InputFile input_file(path_.c_str());
EXPECT_EQ(input_file.GetFilePath(), path_);
}
TEST_F(FileTest, InputFile_EmptyFileEOF) {
InputFile input_file(path_, GetSize());
InputFile input_file(path_.c_str());
AssertEmpty(input_file.Read(kMaxSize));
}
TEST_F(FileTest, InputFile_ReadWorks) {
WriteToFile("abc");
InputFile input_file(path_, GetSize());
InputFile input_file(path_.c_str());
input_file.Read(kMaxSize);
SUCCEED();
}
TEST_F(FileTest, InputFile_ReadUntilEOF) {
WriteToFile("abc");
InputFile input_file(path_, GetSize());
InputFile input_file(path_.c_str());
AssertEquals(input_file.Read(kMaxSize), "abc");
AssertEmpty(input_file.Read(kMaxSize));
}
TEST_F(FileTest, InputFile_ReadWithSize) {
WriteToFile("abc");
InputFile input_file(path_, GetSize());
InputFile input_file(path_.c_str());
AssertEquals(input_file.Read(2), "ab");
AssertEquals(input_file.Read(1), "c");
AssertEmpty(input_file.Read(kMaxSize));
@@ -105,7 +111,7 @@ TEST_F(FileTest, InputFile_ReadWithSize) {
TEST_F(FileTest, InputFile_GetTotalSize) {
WriteToFile("abc");
InputFile input_file(path_, GetSize());
InputFile input_file(path_.c_str());
EXPECT_EQ(input_file.GetTotalSize(), 3);
AssertEquals(input_file.Read(1), "a");
EXPECT_EQ(input_file.GetTotalSize(), 3);
@@ -113,7 +119,7 @@ TEST_F(FileTest, InputFile_GetTotalSize) {
TEST_F(FileTest, InputFile_Close) {
WriteToFile("abc");
InputFile input_file(path_, GetSize());
InputFile input_file(path_.c_str());
input_file.Close();
ExceptionOr<ByteArray> read_result = input_file.Read(kMaxSize);
EXPECT_FALSE(read_result.ok());
@@ -121,23 +127,23 @@ TEST_F(FileTest, InputFile_Close) {
}
TEST_F(FileTest, OutputFile_NonExistentPath) {
OutputFile output_file("/not/a/valid/path.txt");
OutputFile output_file((TEST_INVALID_PARENT_FOLDER + TEST_FILE_NAME).c_str());
ByteArray bytes("a", 1);
EXPECT_TRUE(output_file.Write(bytes).Raised(Exception::kIo));
}
TEST_F(FileTest, OutputFile_Write) {
OutputFile output_file(path_);
OutputFile output_file(path_.c_str());
ByteArray bytes1("a");
ByteArray bytes2("bc");
EXPECT_EQ(output_file.Write(bytes1), Exception{Exception::kSuccess});
EXPECT_EQ(output_file.Write(bytes2), Exception{Exception::kSuccess});
InputFile input_file(path_, GetSize());
InputFile input_file(path_.c_str());
AssertEquals(input_file.Read(kMaxSize), "abc");
}
TEST_F(FileTest, OutputFile_Close) {
OutputFile output_file(path_);
OutputFile output_file(path_.c_str());
output_file.Close();
ByteArray bytes("a");
EXPECT_EQ(output_file.Write(bytes), Exception{Exception::kIo});
-2
View File
@@ -26,11 +26,9 @@ cc_library(
"condition_variable.h",
"executor.h",
"future.h",
"input_file.h",
"listenable_future.h",
"log_message.h",
"mutex.h",
"output_file.h",
"scheduled_executor.h",
"settable_future.h",
"submittable_executor.h",
+13 -2
View File
@@ -125,20 +125,25 @@ TEST(ExecutorTests, SingleThreadedExecutorMultipleTasksSucceeds) {
// Container to note threads that ran
std::unique_ptr<std::vector<DWORD>> threadIds =
std::make_unique<std::vector<DWORD>>();
CRITICAL_SECTION crit_sec;
InitializeCriticalSection(&crit_sec);
threadIds->push_back(GetCurrentThreadId());
// Act
for (int index = 0; index < 5; index++) {
executor->Execute([&output, &threadIds, index]() {
executor->Execute([&output, &threadIds, &crit_sec, index]() {
EnterCriticalSection(&crit_sec);
threadIds->push_back(GetCurrentThreadId());
char buffer[128];
snprintf(buffer, sizeof(buffer), "%s%d, ", RUNNABLE_TEXT.c_str(), index);
output.append(std::string(buffer));
LeaveCriticalSection(&crit_sec);
});
}
executor->Shutdown();
DeleteCriticalSection(&crit_sec);
// Assert
// We should've run 1 time on the main thread, and 5 times on the
@@ -200,19 +205,25 @@ TEST(ExecutorTests, MultiThreadedExecutorMultipleTasksSucceeds) {
std::shared_ptr<std::string> output = std::make_shared<std::string>();
CRITICAL_SECTION crit_sec;
InitializeCriticalSection(&crit_sec);
threadIds->push_back(GetCurrentThreadId());
// Act
for (int index = 0; index < 5; index++) {
executor->Execute([&output, &threadIds, index]() {
executor->Execute([&output, &threadIds, &crit_sec, index]() {
EnterCriticalSection(&crit_sec);
threadIds->push_back(GetCurrentThreadId());
char buffer[128];
snprintf(buffer, sizeof(buffer), "%s %d, ", RUNNABLE_TEXT.c_str(), index);
output->append(std::string(buffer));
LeaveCriticalSection(&crit_sec);
});
}
executor->Shutdown();
DeleteCriticalSection(&crit_sec);
// Assert
// We should've run 1 time on the main thread, and 5 times on the
-50
View File
@@ -1,50 +0,0 @@
// Copyright 2020 Google LLC
//
// 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
//
// https://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 PLATFORM_IMPL_WINDOWS_INPUT_FILE_H_
#define PLATFORM_IMPL_WINDOWS_INPUT_FILE_H_
#include "platform/api/input_file.h"
#include "platform/base/byte_array.h"
#include "platform/base/exception.h"
namespace location {
namespace nearby {
namespace windows {
// An InputFile represents a readable file on the system.
class InputFile : public api::InputFile {
public:
// TODO(b/184975123): replace with real implementation.
~InputFile() override = default;
// TODO(b/184975123): replace with real implementation.
std::string GetFilePath() const override { return "Un-implemented"; }
// TODO(b/184975123): replace with real implementation.
std::int64_t GetTotalSize() const override { return 0; }
// throws Exception::kIo
// TODO(b/184975123): replace with real implementation.
ExceptionOr<ByteArray> Read(std::int64_t size) override {
return ExceptionOr<ByteArray>(Exception::kFailed);
}
// throws Exception::kIo
// TODO(b/184975123): replace with real implementation.
Exception Close() override { return Exception{}; }
};
} // namespace windows
} // namespace nearby
} // namespace location
#endif // PLATFORM_IMPL_WINDOWS_INPUT_FILE_H_
+18 -27
View File
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "platform/impl/windows/input_file.h"
#include "gtest/gtest.h"
#include "platform/base/exception.h"
#include "platform/base/payload_id.h"
@@ -24,21 +22,18 @@ class InputFileTests : public testing::Test {
protected:
// You can define per-test set-up logic as usual.
void SetUp() override {
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
hFile_ = CreateFileA(
test_utils::GetPayloadPath(payloadId).c_str(), // name of the write
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // default security
CREATE_ALWAYS, // create new file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
hFile_ = CreateFileA(TEST_FILE_PATH.c_str(), // name of the write
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // default security
CREATE_ALWAYS, // create new file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
if (hFile_ == INVALID_HANDLE_VALUE) {
NEARBY_LOG(ERROR,
"Failed to create OutputFile with payloadId: %s and error: %d",
test_utils::GetPayloadPath(payloadId).c_str(), GetLastError());
"Failed to create OutputFile with file path: %s and error: %d",
TEST_FILE_PATH.c_str(), GetLastError());
}
const char* buffer = TEST_STRING;
@@ -52,9 +47,8 @@ class InputFileTests : public testing::Test {
// You can define per-test tear-down logic as usual.
void TearDown() override {
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
if (FileExists(test_utils::GetPayloadPath(payloadId).c_str())) {
DeleteFileA(test_utils::GetPayloadPath(payloadId).c_str());
if (FileExists(TEST_FILE_PATH.c_str())) {
DeleteFileA(TEST_FILE_PATH.c_str());
}
}
@@ -74,7 +68,7 @@ TEST_F(InputFileTests, SuccessfulCreation) {
std::unique_ptr<location::nearby::api::InputFile> inputFile = nullptr;
inputFile = location::nearby::api::ImplementationPlatform::CreateInputFile(
payloadId, strlen(TEST_STRING));
TEST_FILE_PATH.c_str());
EXPECT_NE(inputFile, nullptr);
EXPECT_EQ(inputFile->Close(),
@@ -82,28 +76,27 @@ TEST_F(InputFileTests, SuccessfulCreation) {
}
TEST_F(InputFileTests, SuccessfulGetFilePath) {
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
std::unique_ptr<location::nearby::api::InputFile> inputFile = nullptr;
std::string fileName;
std::string expected(TEST_FILE_PATH.c_str());
inputFile = location::nearby::api::ImplementationPlatform::CreateInputFile(
payloadId, strlen(TEST_STRING));
TEST_FILE_PATH.c_str());
fileName = inputFile->GetFilePath();
EXPECT_EQ(inputFile->Close(),
location::nearby::Exception{location::nearby::Exception::kSuccess});
EXPECT_EQ(fileName, test_utils::GetPayloadPath(payloadId).c_str());
EXPECT_EQ(fileName, expected);
}
TEST_F(InputFileTests, SuccessfulGetTotalSize) {
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
std::unique_ptr<location::nearby::api::InputFile> inputFile = nullptr;
int64_t size = -1;
inputFile = location::nearby::api::ImplementationPlatform::CreateInputFile(
payloadId, strlen(TEST_STRING));
TEST_FILE_PATH.c_str());
size = inputFile->GetTotalSize();
@@ -114,11 +107,10 @@ TEST_F(InputFileTests, SuccessfulGetTotalSize) {
}
TEST_F(InputFileTests, SuccessfulRead) {
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
std::unique_ptr<location::nearby::api::InputFile> inputFile = nullptr;
inputFile = location::nearby::api::ImplementationPlatform::CreateInputFile(
payloadId, strlen(TEST_STRING));
TEST_FILE_PATH.c_str());
auto fileSize = inputFile->GetTotalSize();
auto dataRead = inputFile->Read(fileSize);
@@ -131,11 +123,10 @@ TEST_F(InputFileTests, SuccessfulRead) {
}
TEST_F(InputFileTests, FailedRead) {
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
std::unique_ptr<location::nearby::api::InputFile> inputFile = nullptr;
inputFile = location::nearby::api::ImplementationPlatform::CreateInputFile(
payloadId, strlen(TEST_STRING));
TEST_FILE_PATH.c_str());
auto fileSize = inputFile->GetTotalSize();
EXPECT_NE(fileSize, -1);
-47
View File
@@ -1,47 +0,0 @@
// Copyright 2020 Google LLC
//
// 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
//
// https://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 PLATFORM_IMPL_WINDOWS_OUTPUT_FILE_H_
#define PLATFORM_IMPL_WINDOWS_OUTPUT_FILE_H_
#include "platform/api/output_file.h"
#include "platform/base/byte_array.h"
#include "platform/base/exception.h"
namespace location {
namespace nearby {
namespace windows {
// An OutputFile represents a writable file on the system.
class OutputFile : public api::OutputFile {
public:
// TODO(b/184975123): replace with real implementation.
~OutputFile() override = default;
// throws Exception::kIo
// TODO(b/184975123): replace with real implementation.
Exception Write(const ByteArray& data) override { return Exception{}; }
// throws Exception::kIo
// TODO(b/184975123): replace with real implementation.
Exception Flush() override { return Exception{}; }
// throws Exception::kIo
// TODO(b/184975123): replace with real implementation.
Exception Close() override { return Exception{}; }
};
} // namespace windows
} // namespace nearby
} // namespace location
#endif // PLATFORM_IMPL_WINDOWS_OUTPUT_FILE_H_
+9 -16
View File
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "platform/impl/windows/output_file.h"
#include "gtest/gtest.h"
#include "platform/api/platform.h"
#include "platform/base/exception.h"
@@ -24,17 +22,15 @@ class OutputFileTests : public testing::Test {
protected:
// You can define per-test set-up logic as usual.
void SetUp() override {
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
if (FileExists(test_utils::GetPayloadPath(payloadId).c_str())) {
DeleteFileA(test_utils::GetPayloadPath(payloadId).c_str());
if (FileExists(TEST_FILE_PATH.c_str())) {
DeleteFileA(TEST_FILE_PATH.c_str());
}
}
// You can define per-test tear-down logic as usual.
void TearDown() override {
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
if (FileExists(test_utils::GetPayloadPath(payloadId).c_str())) {
DeleteFileA(test_utils::GetPayloadPath(payloadId).c_str());
if (FileExists(TEST_FILE_PATH.c_str())) {
DeleteFileA(TEST_FILE_PATH.c_str());
}
}
@@ -47,44 +43,41 @@ class OutputFileTests : public testing::Test {
};
TEST_F(OutputFileTests, SuccessfulCreation) {
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
std::unique_ptr<location::nearby::api::OutputFile> outputFile = nullptr;
EXPECT_NO_THROW(
outputFile =
location::nearby::api::ImplementationPlatform::CreateOutputFile(
payloadId));
TEST_FILE_PATH.c_str()));
EXPECT_NE(outputFile, nullptr);
EXPECT_NO_THROW(outputFile->Close());
}
TEST_F(OutputFileTests, SuccessfulClose) {
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
std::unique_ptr<location::nearby::api::OutputFile> outputFile = nullptr;
EXPECT_NO_THROW(
outputFile =
location::nearby::api::ImplementationPlatform::CreateOutputFile(
payloadId));
TEST_FILE_PATH.c_str()));
EXPECT_NO_THROW(outputFile->Close());
DeleteFileA(test_utils::GetPayloadPath(payloadId).c_str());
DeleteFileA(TEST_FILE_PATH.c_str());
}
TEST_F(OutputFileTests, SuccessfulWrite) {
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
location::nearby::ByteArray data(std::string(TEST_STRING));
std::unique_ptr<location::nearby::api::OutputFile> outputFile = nullptr;
EXPECT_NO_THROW(
outputFile =
location::nearby::api::ImplementationPlatform::CreateOutputFile(
payloadId));
TEST_FILE_PATH.c_str()));
EXPECT_NO_THROW(outputFile->Write(data));
EXPECT_NO_THROW(outputFile->Close());
DeleteFileA(test_utils::GetPayloadPath(payloadId).c_str());
DeleteFileA(TEST_FILE_PATH.c_str());
}
+11 -13
View File
@@ -41,9 +41,9 @@
namespace location {
namespace nearby {
namespace api {
namespace {
std::string GetPayloadPath(PayloadId payload_id) {
std::unique_ptr<std::string> ImplementationPlatform::GetDownloadPath(
std::unique_ptr<std::string> path) {
PWSTR basePath;
// Retrieves the full path of a known folder identified by the folder's
@@ -61,13 +61,12 @@ std::string GetPayloadPath(PayloadId payload_id) {
// is no longer needed by calling CoTaskMemFree, whether
// SHGetKnownFolderPath succeeds or not.
char* fullpathUTF8 = new char((wcslen(basePath) + 1) * sizeof(char));
wcstombs(fullpathUTF8, basePath, (wcslen(basePath) + 1) * sizeof(char));
std::string fullPath = std::string(fullpathUTF8);
auto retval = absl::StrCat(fullPath += "/", payload_id);
return retval;
auto basePathLength = (wcslen(basePath) + 1) * sizeof(char);
char* fullpathUTF8 = new char(basePathLength);
wcstombs(fullpathUTF8, basePath, basePathLength);
return std::make_unique<std::string>(std::string(fullpathUTF8) +=
"/" + *path);
}
} // namespace
std::unique_ptr<AtomicBoolean> ImplementationPlatform::CreateAtomicBoolean(
bool initial_value) {
@@ -94,14 +93,13 @@ ImplementationPlatform::CreateConditionVariable(Mutex* mutex) {
}
std::unique_ptr<InputFile> ImplementationPlatform::CreateInputFile(
PayloadId payload_id, std::int64_t total_size) {
return absl::make_unique<shared::InputFile>(GetPayloadPath(payload_id),
total_size);
const char* file_path) {
return absl::make_unique<shared::InputFile>(file_path);
}
std::unique_ptr<OutputFile> ImplementationPlatform::CreateOutputFile(
PayloadId payload_id) {
return absl::make_unique<shared::OutputFile>(GetPayloadPath(payload_id));
const char* file_path) {
return absl::make_unique<shared::OutputFile>(file_path);
}
// TODO(b/184975123): replace with real implementation.
@@ -31,15 +31,21 @@ TEST(ScheduledExecutorTests, ExecuteSucceeds) {
std::unique_ptr<std::vector<DWORD>> threadIds =
std::make_unique<std::vector<DWORD>>();
CRITICAL_SECTION crit_sec;
InitializeCriticalSection(&crit_sec);
threadIds->push_back(GetCurrentThreadId());
// Act
submittableExecutor->Execute([&output, &threadIds]() {
submittableExecutor->Execute([&output, &threadIds, &crit_sec]() {
EnterCriticalSection(&crit_sec);
threadIds->push_back(GetCurrentThreadId());
output.append(RUNNABLE_0_TEXT.c_str());
LeaveCriticalSection(&crit_sec);
});
submittableExecutor->Shutdown();
DeleteCriticalSection(&crit_sec);
// Assert
// We should've run 1 time on the main thread, and 1 times on the
@@ -63,6 +69,9 @@ TEST(ScheduledExecutorTests, ScheduleSucceeds) {
std::unique_ptr<std::vector<DWORD>> threadIds =
std::make_unique<std::vector<DWORD>>();
CRITICAL_SECTION crit_sec;
InitializeCriticalSection(&crit_sec);
threadIds->push_back(GetCurrentThreadId());
std::chrono::system_clock::time_point timeNow =
@@ -71,16 +80,19 @@ TEST(ScheduledExecutorTests, ScheduleSucceeds) {
// Act
submittableExecutor->Schedule(
[&output, &threadIds, &timeExecuted]() {
[&output, &threadIds, &timeExecuted, &crit_sec]() {
EnterCriticalSection(&crit_sec);
timeExecuted = std::chrono::system_clock::now();
threadIds->push_back(GetCurrentThreadId());
output.append(RUNNABLE_0_TEXT.c_str());
LeaveCriticalSection(&crit_sec);
},
absl::Milliseconds(50));
SleepEx(100, true); // Yield the thread
submittableExecutor->Shutdown();
DeleteCriticalSection(&crit_sec);
auto difference = std::chrono::duration_cast<std::chrono::milliseconds>(
timeExecuted - timeNow)
@@ -148,13 +160,18 @@ TEST(ScheduledExecutorTests, CancelAfterStartedFails) {
std::unique_ptr<std::vector<DWORD>> threadIds =
std::make_unique<std::vector<DWORD>>();
CRITICAL_SECTION crit_sec;
InitializeCriticalSection(&crit_sec);
threadIds->push_back(GetCurrentThreadId());
// Act
auto cancelable = submittableExecutor->Schedule(
[&output, &threadIds]() {
[&output, &threadIds, &crit_sec]() {
EnterCriticalSection(&crit_sec);
threadIds->push_back(GetCurrentThreadId());
output.append(RUNNABLE_0_TEXT.c_str());
LeaveCriticalSection(&crit_sec);
},
absl::Milliseconds(100));
@@ -163,6 +180,7 @@ TEST(ScheduledExecutorTests, CancelAfterStartedFails) {
auto actual = cancelable->Cancel();
submittableExecutor->Shutdown();
DeleteCriticalSection(&crit_sec);
// Assert
ASSERT_FALSE(actual);
@@ -164,19 +164,25 @@ TEST(SubmittableExecutorTests, SingleThreadedExecuteMultipleTasksSucceeds) {
std::unique_ptr<std::vector<DWORD>> threadIds =
std::make_unique<std::vector<DWORD>>();
CRITICAL_SECTION crit_sec;
InitializeCriticalSection(&crit_sec);
threadIds->push_back(GetCurrentThreadId());
// Act
for (int index = 0; index < 5; index++) {
submittableExecutor->Execute([&output, &threadIds, index]() {
submittableExecutor->Execute([&output, &threadIds, &crit_sec, index]() {
EnterCriticalSection(&crit_sec);
threadIds->push_back(GetCurrentThreadId());
char buffer[128];
snprintf(buffer, sizeof(buffer), "%s%d, ", RUNNABLE_TEXT.c_str(), index);
output->append(std::string(buffer));
LeaveCriticalSection(&crit_sec);
});
}
submittableExecutor->Shutdown();
DeleteCriticalSection(&crit_sec);
// Assert
// We should've run 1 time on the main thread, and 5 times on the
@@ -206,20 +212,27 @@ TEST(SubmittableExecutorTests, SingleThreadedDoSubmitMultipleTasksSucceeds) {
std::unique_ptr<std::vector<DWORD>> threadIds =
std::make_unique<std::vector<DWORD>>();
CRITICAL_SECTION crit_sec;
InitializeCriticalSection(&crit_sec);
threadIds->push_back(GetCurrentThreadId());
// Act
bool result = true;
for (int index = 0; index < 5; index++) {
result &= submittableExecutor->DoSubmit([&output, &threadIds, index]() {
result &= submittableExecutor->DoSubmit([&output, &threadIds, &crit_sec,
index]() {
EnterCriticalSection(&crit_sec);
threadIds->push_back(GetCurrentThreadId());
char buffer[128];
snprintf(buffer, sizeof(buffer), "%s%d, ", RUNNABLE_TEXT.c_str(), index);
output->append(std::string(buffer));
LeaveCriticalSection(&crit_sec);
});
}
submittableExecutor->Shutdown();
DeleteCriticalSection(&crit_sec);
// Assert
// All of these should have submitted
+2 -27
View File
@@ -19,39 +19,14 @@
#include "absl/strings/str_cat.h"
namespace test_utils {
std::wstring StringToWideString(const std::string& s) {
std::wstring StringToWideString(const std::string &s) {
int len;
int slength = (int)s.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
wchar_t *buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
}
std::string GetPayloadPath(location::nearby::PayloadId payload_id) {
PWSTR basePath;
// Retrieves the full path of a known folder identified by the folder's
// KNOWNFOLDERID.
// https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath
SHGetKnownFolderPath(
FOLDERID_Downloads, // rfid: A reference to the KNOWNFOLDERID that
// identifies the folder.
0, // dwFlags: Flags that specify special retrieval options.
NULL, // hToken: An access token that represents a particular user.
&basePath); // ppszPath: When this method returns, contains the address
// of a pointer to a null-terminated Unicode string that
// specifies the path of the known folder. The calling
// process is responsible for freeing this resource once it
// is no longer needed by calling CoTaskMemFree, whether
// SHGetKnownFolderPath succeeds or not.
char* fullpathUTF8 = new char((wcslen(basePath) + 1) * sizeof(char));
wcstombs(fullpathUTF8, basePath, (wcslen(basePath) + 1) * sizeof(char));
std::string fullPath = std::string(fullpathUTF8);
auto retval = absl::StrCat(fullPath += "/", payload_id);
return retval;
}
} // namespace test_utils
+13 -7
View File
@@ -15,14 +15,8 @@
#ifndef PLATFORM_IMPL_WINDOWS_TEST_UTILS_H_
#define PLATFORM_IMPL_WINDOWS_TEST_UTILS_H_
#include <Windows.h>
#include <stdio.h>
#include <string>
#include <xstring>
#include "platform/base/payload_id.h"
#define TEST_BUFFER_SIZE 256
#define TEST_PAYLOAD_ID 64l
#define TEST_STRING \
@@ -39,9 +33,21 @@
"eu tellus. Cras feugiat ornare vestibulum. Nullam at ipsum vestibulum " \
"sapien luctus dictum ac vel ligula."
#define TEST_FILE_PATH std::string("testfilename.txt")
namespace test_utils {
std::wstring StringToWideString(const std::string& s);
std::string GetPayloadPath(location::nearby::PayloadId payload_id);
class TempPath {
public:
enum Location {
Local, // Some local directory, works for unittest and on borglets.
CNSTest, // Creates a directory on the cns test cell.
};
TempPath(Location location) : location_(location) {}
Location location_;
const std::string path() { return ""; }
};
} // namespace test_utils
#endif // PLATFORM_IMPL_WINDOWS_TEST_UTILS_H_
-1
View File
@@ -29,7 +29,6 @@ cc_library(
"cancelable_alarm.h",
"cancellable_task.h",
"condition_variable.h",
"core_config.h",
"count_down_latch.h",
"crypto.h",
"file.h",
+12 -15
View File
@@ -17,16 +17,19 @@
namespace location {
namespace nearby {
InputFile::InputFile(PayloadId payload_id, std::int64_t size)
: impl_(Platform::CreateInputFile(payload_id, size)), id_(payload_id) {}
InputFile::InputFile(const char* file_path)
: impl_(Platform::CreateInputFile(file_path)) {}
InputFile::~InputFile() = default;
InputFile::InputFile(InputFile&&) noexcept = default;
InputFile::InputFile(InputFile&& other) noexcept {
impl_ = std::move(other.impl_);
}
InputFile& InputFile::operator=(InputFile&&) noexcept = default;
// Reads up to size bytes and returns as a ByteArray object wrapped by
// ExceptionOr.
// Returns Exception::kIo on error, or end of file.
ExceptionOr<ByteArray> InputFile::Read(std::int64_t size) {
ExceptionOr<ByteArray> InputFile::Read(std::int64_t size) const {
return impl_->Read(size);
}
@@ -36,13 +39,13 @@ std::string InputFile::GetFilePath() const { return impl_->GetFilePath(); }
// Returns total size of this file in bytes.
std::int64_t InputFile::GetTotalSize() const { return impl_->GetTotalSize(); }
ExceptionOr<size_t> InputFile::Skip(size_t offset) {
ExceptionOr<size_t> InputFile::Skip(size_t offset) const {
return impl_->Skip(offset);
}
// Disallows further reads from the file and frees system resources,
// associated with it.
Exception InputFile::Close() { return impl_->Close(); }
Exception InputFile::Close() const { return impl_->Close(); }
// Returns a handle to the underlying input stream.
//
@@ -51,13 +54,10 @@ Exception InputFile::Close() { return impl_->Close(); }
// Side effects of any non-const operation invoked for InputFile (such as
// Read, or Close will be observable through InputStream& handle, and vice
// versa.
InputStream& InputFile::GetInputStream() { return *impl_; }
const InputStream& InputFile::GetInputStream() const { return *impl_; }
// Returns payload id of this file. The closest "file" equivalent is inode.
PayloadId InputFile::GetPayloadId() const { return id_; }
OutputFile::OutputFile(PayloadId payload_id)
: impl_(Platform::CreateOutputFile(payload_id)), id_(payload_id) {}
OutputFile::OutputFile(const char* file_path)
: impl_(Platform::CreateOutputFile(file_path)) {}
OutputFile::~OutputFile() = default;
OutputFile::OutputFile(OutputFile&&) noexcept = default;
OutputFile& OutputFile::operator=(OutputFile&&) noexcept = default;
@@ -85,8 +85,5 @@ Exception OutputFile::Close() { return impl_->Close(); }
// versa.
OutputStream& OutputFile::GetOutputStream() { return *impl_; }
// Returns payload id of this file. The closest "file" equivalent is inode.
PayloadId OutputFile::GetPayloadId() const { return id_; }
} // namespace nearby
} // namespace location
+7 -15
View File
@@ -23,10 +23,10 @@
#include "platform/api/output_file.h"
#include "platform/api/platform.h"
#include "platform/base/byte_array.h"
#include "platform/base/core_config.h"
#include "platform/base/exception.h"
#include "platform/base/input_stream.h"
#include "platform/base/output_stream.h"
#include "platform/public/core_config.h"
namespace location {
namespace nearby {
@@ -34,7 +34,7 @@ namespace nearby {
class DLL_API InputFile final {
public:
using Platform = api::ImplementationPlatform;
InputFile(PayloadId payload_id, std::int64_t size);
InputFile(const char* file_path);
~InputFile();
InputFile(InputFile&&) noexcept;
InputFile& operator=(InputFile&&) noexcept;
@@ -42,7 +42,7 @@ class DLL_API InputFile final {
// Reads up to size bytes and returns as a ByteArray object wrapped by
// ExceptionOr.
// Returns Exception::kIo on error, or end of file.
ExceptionOr<ByteArray> Read(std::int64_t size);
ExceptionOr<ByteArray> Read(std::int64_t size) const;
// Returns a string that uniqely identifies this file.
std::string GetFilePath() const;
@@ -50,11 +50,11 @@ class DLL_API InputFile final {
// Returns total size of this file in bytes.
std::int64_t GetTotalSize() const;
ExceptionOr<size_t> Skip(size_t offset);
ExceptionOr<size_t> Skip(size_t offset) const;
// Disallows further reads from the file and frees system resources,
// associated with it.
Exception Close();
Exception Close() const;
// Returns a handle to the underlying input stream.
//
@@ -63,20 +63,16 @@ class DLL_API InputFile final {
// Side effects of any non-const operation invoked for InputFile (such as
// Read, or Close will be observable through InputStream& handle, and vice
// versa.
InputStream& GetInputStream();
// Returns payload id of this file. The closest "file" equivalent is inode.
PayloadId GetPayloadId() const;
const InputStream& GetInputStream() const;
private:
std::unique_ptr<api::InputFile> impl_;
PayloadId id_;
};
class DLL_API OutputFile final {
public:
using Platform = api::ImplementationPlatform;
explicit OutputFile(PayloadId payload_id);
explicit OutputFile(const char* file_path);
~OutputFile();
OutputFile(OutputFile&&) noexcept;
OutputFile& operator=(OutputFile&&) noexcept;
@@ -102,12 +98,8 @@ class DLL_API OutputFile final {
// versa.
OutputStream& GetOutputStream();
// Returns payload id of this file. The closest "file" equivalent is inode.
PayloadId GetPayloadId() const;
private:
std::unique_ptr<api::OutputFile> impl_;
PayloadId id_;
};
} // namespace nearby