ams: support building unit test programs on windows/linux/macos

This commit is contained in:
Michael Scire
2022-03-06 12:08:20 -08:00
committed by SciresM
parent 9a38be201a
commit 64a97576d0
756 changed files with 33359 additions and 9372 deletions

View File

@@ -14,28 +14,37 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "ncm_content_manager_factory.hpp"
#include "ncm_remote_content_manager_impl.hpp"
namespace ams::ncm {
namespace {
sf::SharedPointer<IContentManager> g_content_manager;
constinit sf::SharedPointer<IContentManager> g_content_manager;
sf::UnmanagedServiceObject<IContentManager, RemoteContentManagerImpl> g_remote_manager_impl;
#if defined(ATMOSPHERE_OS_HORIZON)
constinit util::TypedStorage<sf::UnmanagedServiceObject<IContentManager, RemoteContentManagerImpl>> g_remote_manager_storage = {};
#endif
}
void Initialize() {
AMS_ASSERT(g_content_manager == nullptr);
R_ABORT_UNLESS(ncmInitialize());
g_content_manager = g_remote_manager_impl.GetShared();
#if defined(ATMOSPHERE_OS_HORIZON)
util::ConstructAt(g_remote_manager_storage);
g_content_manager = util::GetReference(g_remote_manager_storage).GetShared();
#else
g_content_manager = CreateDefaultContentManager(ContentManagerConfig{});
#endif
}
void Finalize() {
AMS_ASSERT(g_content_manager != nullptr);
g_content_manager.Reset();
ncmExit();
#if defined(ATMOSPHERE_OS_HORIZON)
util::DestroyAt(g_remote_manager_storage);
#endif
}
void InitializeWithObject(sf::SharedPointer<IContentManager> manager_object) {

View File

@@ -34,7 +34,7 @@ namespace ams::ncm {
/* Convert each character pair to a byte until we reach the end. */
for (size_t i = 0; i < src_size; i += 2) {
char tmp[3];
strlcpy(tmp, src + i, sizeof(tmp));
util::Strlcpy(tmp, src + i, sizeof(tmp));
char *err = nullptr;
reinterpret_cast<u8 *>(dst)[i / 2] = static_cast<u8>(std::strtoul(tmp, std::addressof(err), 16));

View File

@@ -0,0 +1,27 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "ncm_content_manager_factory.hpp"
namespace ams::ncm {
sf::SharedPointer<IContentManager> CreateDefaultContentManager(const ContentManagerConfig &config) {
auto ref = sf::CreateSharedObjectEmplaced<IContentManager, ContentManagerImpl>();
R_ABORT_UNLESS(ref.GetImpl().Initialize(config));
return ref;
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
namespace ams::ncm {
sf::SharedPointer<IContentManager> CreateDefaultContentManager(const ContentManagerConfig &config);
}

View File

@@ -266,7 +266,7 @@ namespace ams::ncm {
ON_SCOPE_EXIT { fs::Unmount(root->mount_name); };
/* Ensure the path exists for us to import to. */
R_TRY(fs::EnsureDirectoryRecursively(root->path));
R_TRY(fs::EnsureDirectory(root->path));
/* Copy the file from bis to our save. */
R_TRY(impl::CopyFile(savedata_db_path, bis_db_path));
@@ -395,7 +395,7 @@ namespace ams::ncm {
ON_SCOPE_EXIT { fs::Unmount(root->mount_name); };
/* Ensure the content storage root's path exists. */
R_TRY(fs::EnsureDirectoryRecursively(root->path));
R_TRY(fs::EnsureDirectory(root->path));
/* Initialize content and placeholder directories for the root. */
return ContentStorageImpl::InitializeBase(root->path);
@@ -415,7 +415,7 @@ namespace ams::ncm {
ON_SCOPE_EXIT { fs::Unmount(root->mount_name); };
/* Ensure the content meta database root's path exists. */
R_TRY(fs::EnsureDirectoryRecursively(root->path));
R_TRY(fs::EnsureDirectory(root->path));
/* Commit our changes. */
return fs::CommitSaveData(root->mount_name);
@@ -542,7 +542,7 @@ namespace ams::ncm {
/* Mount based on the storage type. */
if (storage_id == StorageId::GameCard) {
fs::GameCardHandle handle;
fs::GameCardHandle handle{};
R_TRY(fs::GetGameCardHandle(std::addressof(handle)));
R_TRY(fs::MountGameCardPartition(root->mount_name, handle, fs::GameCardPartition::Secure));
} else {

View File

@@ -94,7 +94,7 @@ namespace ams::ncm {
PackagedContentMetaReader reader(meta.Get(), meta.GetSize());
/* Define a helper to output the base meta infos. */
const auto ReadMetaInfoListFromBase = [&] ALWAYS_INLINE_LAMBDA () -> Result {
const auto ReadMetaInfoListFromBase = [&] () ALWAYS_INLINE_LAMBDA -> Result {
/* Output the base content meta info count. */
*out_count = reader.GetContentMetaCount();

View File

@@ -36,7 +36,7 @@ namespace ams::ncm {
Result EnsureContentDirectory(ContentId id, MakeContentPathFunction func, const char *root_path) {
PathString path;
MakeContentPath(std::addressof(path), id, func, root_path);
return fs::EnsureParentDirectoryRecursively(path);
return fs::EnsureParentDirectory(path);
}
Result DeleteContentFile(ContentId id, MakeContentPathFunction func, const char *root_path) {
@@ -303,11 +303,11 @@ namespace ams::ncm {
/* Create the content directory. */
MakeBaseContentDirectoryPath(std::addressof(path), root_path);
R_TRY(fs::EnsureDirectoryRecursively(path));
R_TRY(fs::EnsureDirectory(path));
/* Create the placeholder directory. */
PlaceHolderAccessor::MakeBaseDirectoryPath(std::addressof(path), root_path);
return fs::EnsureDirectoryRecursively(path);
return fs::EnsureDirectory(path);
}
Result ContentStorageImpl::CleanupBase(const char *root_path) {

View File

@@ -38,7 +38,7 @@ namespace ams::ncm {
fs::DirectoryEntry m_entries[MaxDirectoryEntries]{};
s64 m_entry_count{};
public:
constexpr ContentIterator() = default;
constexpr ContentIterator() { /* ... */ }
~ContentIterator();
Result Initialize(const char *root_path, size_t max_depth);
@@ -48,6 +48,7 @@ namespace ams::ncm {
Result OpenDirectory(const char *dir);
Result LoadEntries();
};
static_assert(std::is_constructible<ContentIterator>::value);
protected:
PlaceHolderAccessor m_placeholder_accessor;
ContentId m_cached_content_id;

View File

@@ -39,19 +39,19 @@ namespace ams::ncm {
u16 Get16BitSha256HashPrefix(ContentId id) {
u8 hash[crypto::Sha256Generator::HashSize];
crypto::GenerateSha256Hash(hash, sizeof(hash), std::addressof(id), sizeof(id));
crypto::GenerateSha256(hash, sizeof(hash), std::addressof(id), sizeof(id));
return static_cast<u16>(hash[0]) | (static_cast<u16>(hash[1]) << 8);
}
u8 Get8BitSha256HashPrefix(ContentId id) {
u8 hash[crypto::Sha256Generator::HashSize];
crypto::GenerateSha256Hash(hash, sizeof(hash), std::addressof(id), sizeof(id));
crypto::GenerateSha256(hash, sizeof(hash), std::addressof(id), sizeof(id));
return hash[0];
}
u8 Get8BitSha256HashPrefix(PlaceHolderId id) {
u8 hash[crypto::Sha256Generator::HashSize];
crypto::GenerateSha256Hash(hash, sizeof(hash), std::addressof(id), sizeof(id));
crypto::GenerateSha256(hash, sizeof(hash), std::addressof(id), sizeof(id));
return hash[0];
}

View File

@@ -39,13 +39,6 @@ namespace ams::ncm {
func(out, id, path);
}
ALWAYS_INLINE Result ConvertNotFoundResult(Result r) {
R_TRY_CATCH(r) {
R_CONVERT(ams::fs::ResultPathNotFound, ncm::ResultPlaceHolderNotFound())
} R_END_TRY_CATCH;
return ResultSuccess();
}
}
void PlaceHolderAccessor::MakePath(PathString *out_placeholder_path, PlaceHolderId placeholder_id) const {
@@ -59,7 +52,7 @@ namespace ams::ncm {
Result PlaceHolderAccessor::EnsurePlaceHolderDirectory(PlaceHolderId placeholder_id) {
PathString path;
this->MakePath(std::addressof(path), placeholder_id);
return fs::EnsureParentDirectoryRecursively(path);
return fs::EnsureParentDirectory(path);
}
Result PlaceHolderAccessor::GetPlaceHolderIdFromFileName(PlaceHolderId *out, const char *name) {
@@ -71,7 +64,7 @@ namespace ams::ncm {
PlaceHolderId placeholder_id = {};
for (size_t i = 0; i < sizeof(placeholder_id); i++) {
char tmp[3];
strlcpy(tmp, name + i * 2, sizeof(tmp));
util::Strlcpy(tmp, name + i * 2, sizeof(tmp));
char *err = nullptr;
reinterpret_cast<u8 *>(std::addressof(placeholder_id))[i] = static_cast<u8>(std::strtoul(tmp, std::addressof(err), 16));

View File

@@ -20,14 +20,15 @@
namespace ams::ncm {
#if defined(ATMOSPHERE_OS_HORIZON)
class RemoteContentManagerImpl {
private:
/* TODO: sf::ProxyObjectAllocator */
using ObjectFactory = sf::ObjectFactory<sf::StdAllocationPolicy<std::allocator>>;
public:
RemoteContentManagerImpl() { /* ... */ }
RemoteContentManagerImpl() { R_ABORT_UNLESS(::ncmInitialize()); }
~RemoteContentManagerImpl() { /* ... */ }
~RemoteContentManagerImpl() { ::ncmExit(); }
public:
Result CreateContentStorage(StorageId storage_id) {
return ::ncmCreateContentStorage(static_cast<NcmStorageId>(storage_id));
@@ -100,5 +101,6 @@ namespace ams::ncm {
}
};
static_assert(ncm::IsIContentManager<RemoteContentManagerImpl>);
#endif
}

View File

@@ -18,6 +18,7 @@
namespace ams::ncm {
#if defined(ATMOSPHERE_OS_HORIZON)
class RemoteContentMetaDatabaseImpl {
private:
::NcmContentMetaDatabase m_srv;
@@ -169,5 +170,6 @@ namespace ams::ncm {
}
};
static_assert(ncm::IsIContentMetaDatabase<RemoteContentMetaDatabaseImpl>);
#endif
}

View File

@@ -18,6 +18,7 @@
namespace ams::ncm {
#if defined(ATMOSPHERE_OS_HORIZON)
class RemoteContentStorageImpl {
private:
::NcmContentStorage m_srv;
@@ -209,5 +210,6 @@ namespace ams::ncm {
}
};
static_assert(ncm::IsIContentStorage<RemoteContentStorageImpl>);
#endif
}

View File

@@ -80,28 +80,6 @@ namespace ams::ncm {
return ResultSuccess();
}
namespace {
constexpr const char * const StorageIdStrings[] = {
"None",
"Host",
"GameCard",
"BuiltInSystem",
"BuiltInUser",
"SdCard"
};
constexpr const char * const StorageIdStringsForPlayReport[] = {
"None",
"Host",
"Card",
"BuildInSystem",
"BuildInUser",
"SdCard"
};
}
const char *GetStorageIdString(StorageId storage_id) {
switch (storage_id) {
case StorageId::None: return "None";