LibHac/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SaveDataManagement.cs

706 lines
27 KiB
C#
Raw Normal View History

2020-08-05 07:49:01 +02:00
using System;
using System.Linq;
using LibHac.Common;
using LibHac.Fs;
using LibHac.Fs.Shim;
using LibHac.FsSrv.Impl;
using LibHac.Ncm;
using LibHac.Time;
using Xunit;
using static LibHac.Fs.SaveData;
2021-11-14 20:08:57 +01:00
namespace LibHac.Tests.Fs.FileSystemClientTests.ShimTests;
public class SaveDataManagement
{
2021-11-14 20:08:57 +01:00
[Fact]
public void CreateCacheStorage_InUserSaveSpace_StorageIsCreated()
{
2021-11-14 20:08:57 +01:00
var applicationId = new Ncm.ApplicationId(1);
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2021-11-14 20:08:57 +01:00
Assert.Success(fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 0, 0, SaveDataFlags.None));
2021-11-14 20:08:57 +01:00
using var iterator = new UniqueRef<SaveDataIterator>();
fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User);
2021-11-14 20:08:57 +01:00
var info = new SaveDataInfo[2];
iterator.Get.ReadSaveDataInfo(out long entriesRead, info);
2021-11-14 20:08:57 +01:00
Assert.Equal(1, entriesRead);
Assert.Equal(applicationId, info[0].ProgramId);
}
2021-11-14 20:08:57 +01:00
[Fact]
public void CreateCacheStorage_InSdCacheSaveSpace_StorageIsCreated()
{
var applicationId = new Ncm.ApplicationId(1);
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2021-12-29 18:13:42 +01:00
Assert.Success(fs.CreateCacheStorage(applicationId, SaveDataSpaceId.SdUser, applicationId.Value, 0, 0, SaveDataFlags.None));
2021-11-14 20:08:57 +01:00
using var iterator = new UniqueRef<SaveDataIterator>();
2021-12-29 18:13:42 +01:00
fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.SdUser);
2021-11-14 20:08:57 +01:00
var info = new SaveDataInfo[2];
iterator.Get.ReadSaveDataInfo(out long entriesRead, info);
2021-11-14 20:08:57 +01:00
Assert.Equal(1, entriesRead);
Assert.Equal(applicationId, info[0].ProgramId);
}
2021-11-14 20:08:57 +01:00
[Fact]
public void CreateCacheStorage_InSdCacheSaveSpaceWhenNoSdCard_ReturnsSdCardNotFound()
{
var applicationId = new Ncm.ApplicationId(1);
FileSystemClient fs = FileSystemServerFactory.CreateClient(false);
2021-12-29 18:13:42 +01:00
Assert.Result(ResultFs.PortSdCardNoDevice, fs.CreateCacheStorage(applicationId, SaveDataSpaceId.SdUser, applicationId.Value, 0, 0, SaveDataFlags.None));
2021-11-14 20:08:57 +01:00
}
2021-11-14 20:08:57 +01:00
[Fact]
public void CreateCacheStorage_AlreadyExists_ReturnsPathAlreadyExists()
{
var applicationId = new Ncm.ApplicationId(1);
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2021-11-14 20:08:57 +01:00
Assert.Success(fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 0, 0, SaveDataFlags.None));
Assert.Result(ResultFs.PathAlreadyExists, fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 0, 0, SaveDataFlags.None));
}
2021-11-14 20:08:57 +01:00
[Fact]
public void CreateCacheStorage_WithIndex_CreatesMultiple()
{
var applicationId = new Ncm.ApplicationId(1);
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2021-11-14 20:08:57 +01:00
Assert.Success(fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 0, 0, 0, SaveDataFlags.None));
Assert.Success(fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 1, 0, 0, SaveDataFlags.None));
2021-11-14 20:08:57 +01:00
using var iterator = new UniqueRef<SaveDataIterator>();
fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User);
2021-11-14 20:08:57 +01:00
var info = new SaveDataInfo[3];
iterator.Get.ReadSaveDataInfo(out long entriesRead, info);
2021-11-14 20:08:57 +01:00
Assert.Equal(2, entriesRead);
Assert.Equal(applicationId, info[0].ProgramId);
Assert.Equal(applicationId, info[1].ProgramId);
2021-11-14 20:08:57 +01:00
ushort[] expectedIndexes = { 0, 1 };
ushort[] actualIndexes = info.Take(2).Select(x => x.Index).OrderBy(x => x).ToArray();
2020-04-04 23:19:36 +02:00
2021-11-14 20:08:57 +01:00
Assert.Equal(expectedIndexes, actualIndexes);
}
2020-04-04 23:19:36 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void CreateBcatSaveData_DoesNotExist_SaveIsCreated()
{
var applicationId = new Ncm.ApplicationId(1);
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2020-04-04 23:19:36 +02:00
2021-11-14 20:08:57 +01:00
Assert.Success(fs.CreateBcatSaveData(applicationId, 0x400000));
2020-04-04 23:19:36 +02:00
2021-11-14 20:08:57 +01:00
using var iterator = new UniqueRef<SaveDataIterator>();
fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User);
2020-04-04 23:19:36 +02:00
2021-11-14 20:08:57 +01:00
var info = new SaveDataInfo[2];
iterator.Get.ReadSaveDataInfo(out long entriesRead, info);
2020-04-04 23:19:36 +02:00
2021-11-14 20:08:57 +01:00
Assert.Equal(1, entriesRead);
Assert.Equal(applicationId, info[0].ProgramId);
Assert.Equal(SaveDataType.Bcat, info[0].Type);
}
2020-04-04 23:19:36 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void CreateBcatSaveData_AlreadyExists_ReturnsPathAlreadyExists()
{
var applicationId = new Ncm.ApplicationId(1);
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
Assert.Success(fs.CreateBcatSaveData(applicationId, 0x400000));
Assert.Result(ResultFs.PathAlreadyExists, fs.CreateBcatSaveData(applicationId, 0x400000));
}
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void CreateSystemSaveData_DoesNotExist_SaveIsCreatedInSystem()
{
ulong saveId = 0x8000000001234000;
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Create the save
Assert.Success(fs.CreateSystemSaveData(saveId, 0x1000, 0x1000, SaveDataFlags.None));
2021-11-14 20:08:57 +01:00
// Make sure it was placed in the System save space with the right info.
using var iterator = new UniqueRef<SaveDataIterator>();
Assert.Success(fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.System));
2021-11-14 20:08:57 +01:00
var info = new SaveDataInfo[2];
Assert.Success(iterator.Get.ReadSaveDataInfo(out long entriesRead, info));
2021-11-14 20:08:57 +01:00
Assert.Equal(1, entriesRead);
Assert.Equal(SaveDataType.System, info[0].Type);
Assert.Equal(SaveDataSpaceId.System, info[0].SpaceId);
Assert.Equal(saveId, info[0].StaticSaveDataId);
Assert.Equal(saveId, info[0].SaveDataId);
Assert.Equal(SaveDataState.Normal, info[0].State);
}
2021-11-14 20:08:57 +01:00
[Theory]
[InlineData(AccessControlBits.Bits.SystemSaveData)]
[InlineData(AccessControlBits.Bits.None)]
public void CreateSystemSaveData_HasBuiltInSystemPermission_SaveIsCreatedInSystem(AccessControlBits.Bits permissions)
{
ulong saveId = 0x8000000001234000;
2021-11-14 20:08:57 +01:00
Horizon hos = FileSystemServerFactory.CreateHorizonServer();
2021-11-14 20:08:57 +01:00
var mainProgramId = new ProgramId(0x123456);
2021-11-14 20:08:57 +01:00
HorizonClient client = hos.CreateHorizonClient(new ProgramLocation(mainProgramId, StorageId.BuiltInSystem),
permissions);
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
HorizonClient privilegedClient = hos.CreatePrivilegedHorizonClient();
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Create the save
if (permissions.HasFlag(AccessControlBits.Bits.SystemSaveData))
{
Assert.Success(client.Fs.CreateSystemSaveData(saveId, 0x1000, 0x1000, SaveDataFlags.None));
2020-08-05 07:49:01 +02:00
}
2021-11-14 20:08:57 +01:00
else
2020-08-05 07:49:01 +02:00
{
2021-11-14 20:08:57 +01:00
// Creation should fail if we don't have the right permissions.
Assert.Failure(client.Fs.CreateSystemSaveData(saveId, 0x1000, 0x1000, SaveDataFlags.None));
return;
}
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Make sure it was placed in the System save space with the right info.
using var iterator = new UniqueRef<SaveDataIterator>();
Assert.Success(privilegedClient.Fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.System));
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
var info = new SaveDataInfo[2];
Assert.Success(iterator.Get.ReadSaveDataInfo(out long entriesRead, info));
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
Assert.Equal(1, entriesRead);
Assert.Equal(SaveDataType.System, info[0].Type);
Assert.Equal(SaveDataSpaceId.System, info[0].SpaceId);
Assert.Equal(saveId, info[0].StaticSaveDataId);
Assert.Equal(saveId, info[0].SaveDataId);
Assert.Equal(SaveDataState.Normal, info[0].State);
}
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void CreateSaveData_DoesNotExist_SaveIsCreated()
{
var applicationId = new Ncm.ApplicationId(1);
var userId = new UserId(5, 4);
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
Assert.Success(fs.CreateSaveData(applicationId, userId, 0, 0x1000, 0x1000, SaveDataFlags.None));
2021-11-14 20:08:57 +01:00
using var iterator = new UniqueRef<SaveDataIterator>();
Assert.Success(fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User));
2021-11-14 20:08:57 +01:00
var info = new SaveDataInfo[2];
iterator.Get.ReadSaveDataInfo(out long entriesRead, info);
2021-11-14 20:08:57 +01:00
Assert.Equal(1, entriesRead);
Assert.Equal(applicationId, info[0].ProgramId);
Assert.Equal(SaveDataType.Account, info[0].Type);
Assert.Equal(userId, info[0].UserId);
}
2021-11-14 20:08:57 +01:00
[Fact]
public void CreateSaveData_DoesNotExist_HasCorrectOwnerId()
{
uint ownerId = 1;
2021-11-14 20:08:57 +01:00
var applicationId = new Ncm.ApplicationId(ownerId);
var userId = new UserId(5, 4);
2021-11-14 20:08:57 +01:00
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2021-11-14 20:08:57 +01:00
// Create the save
Assert.Success(fs.CreateSaveData(applicationId, userId, ownerId, 0x1000, 0x1000, SaveDataFlags.None));
2021-11-14 20:08:57 +01:00
// Get the created save data's ID
using var iterator = new UniqueRef<SaveDataIterator>();
Assert.Success(fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User));
2021-11-14 20:08:57 +01:00
var info = new SaveDataInfo[2];
iterator.Get.ReadSaveDataInfo(out long entriesRead, info);
2021-11-14 20:08:57 +01:00
Assert.Equal(1, entriesRead);
2021-11-14 20:08:57 +01:00
// Get the created save data's owner ID
Assert.Success(fs.GetSaveDataOwnerId(out ulong actualOwnerId, info[0].SaveDataId));
2021-11-14 20:08:57 +01:00
Assert.Equal(ownerId, actualOwnerId);
}
2021-11-14 20:08:57 +01:00
[Fact]
public void CreateSaveData_DoesNotExist_HasCorrectFlags()
{
SaveDataFlags flags = SaveDataFlags.KeepAfterRefurbishment | SaveDataFlags.NeedsSecureDelete;
2021-11-14 20:08:57 +01:00
var applicationId = new Ncm.ApplicationId(1);
var userId = new UserId(5, 4);
2021-11-14 20:08:57 +01:00
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2021-11-14 20:08:57 +01:00
// Create the save
Assert.Success(fs.CreateSaveData(applicationId, userId, 0, 0x1000, 0x1000, flags));
2021-11-14 20:08:57 +01:00
// Get the created save data's ID
using var iterator = new UniqueRef<SaveDataIterator>();
Assert.Success(fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User));
2021-11-14 20:08:57 +01:00
var info = new SaveDataInfo[2];
iterator.Get.ReadSaveDataInfo(out long entriesRead, info);
2021-11-14 20:08:57 +01:00
Assert.Equal(1, entriesRead);
2021-11-14 20:08:57 +01:00
// Get the created save data's flags
Assert.Success(fs.GetSaveDataFlags(out SaveDataFlags actualFlags, info[0].SaveDataId));
2021-11-14 20:08:57 +01:00
Assert.Equal(flags, actualFlags);
}
2021-11-14 20:08:57 +01:00
[Fact]
public void CreateSaveData_DoesNotExist_HasCorrectSizes()
{
long availableSize = 0x220000;
long journalSize = 0x120000;
2021-11-14 20:08:57 +01:00
var applicationId = new Ncm.ApplicationId(1);
var userId = new UserId(5, 4);
2021-11-14 20:08:57 +01:00
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2021-11-14 20:08:57 +01:00
// Create the save
Assert.Success(fs.CreateSaveData(applicationId, userId, 0, availableSize, journalSize, SaveDataFlags.None));
2021-11-14 20:08:57 +01:00
// Get the created save data's ID
using var iterator = new UniqueRef<SaveDataIterator>();
Assert.Success(fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User));
2021-11-14 20:08:57 +01:00
var info = new SaveDataInfo[2];
iterator.Get.ReadSaveDataInfo(out long entriesRead, info);
2021-11-14 20:08:57 +01:00
Assert.Equal(1, entriesRead);
2021-11-14 20:08:57 +01:00
// Get the created save data's sizes
Assert.Success(fs.GetSaveDataAvailableSize(out long actualAvailableSize, info[0].SaveDataId));
Assert.Success(fs.GetSaveDataJournalSize(out long actualJournalSize, info[0].SaveDataId));
2021-11-14 20:08:57 +01:00
Assert.Equal(availableSize, actualAvailableSize);
Assert.Equal(journalSize, actualJournalSize);
}
2021-11-14 20:08:57 +01:00
[Fact]
public void CreateSaveData_FromSubProgram_CreatesSaveDataForMainProgram()
{
Horizon hos = FileSystemServerFactory.CreateHorizonServer();
2021-11-14 20:08:57 +01:00
Span<ProgramIndexMapInfo> mapInfo = stackalloc ProgramIndexMapInfo[5];
var mainProgramId = new Ncm.ApplicationId(0x123456);
2021-11-14 20:08:57 +01:00
var programId = new ProgramId(mainProgramId.Value + 2);
2021-11-14 20:08:57 +01:00
for (int i = 0; i < mapInfo.Length; i++)
{
mapInfo[i].MainProgramId = mainProgramId;
mapInfo[i].ProgramId = new ProgramId(mainProgramId.Value + (uint)i);
mapInfo[i].ProgramIndex = (byte)i;
}
2021-11-14 20:08:57 +01:00
HorizonClient client = hos.CreatePrivilegedHorizonClient();
HorizonClient subProgramClient =
hos.CreateHorizonClient(new ProgramLocation(programId, StorageId.BuiltInUser),
AccessControlBits.Bits.CreateSaveData);
2021-11-14 20:08:57 +01:00
Assert.Success(client.Fs.RegisterProgramIndexMapInfo(mapInfo));
Assert.Success(subProgramClient.Fs.CreateSaveData(Ncm.ApplicationId.InvalidId, InvalidUserId, 0, 0x4000,
2021-11-14 20:08:57 +01:00
0x4000, SaveDataFlags.None));
2021-11-14 20:08:57 +01:00
// Get the created save data's ID
using var iterator = new UniqueRef<SaveDataIterator>();
Assert.Success(client.Fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User));
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
var info = new SaveDataInfo[2];
iterator.Get.ReadSaveDataInfo(out long entriesRead, info);
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
Assert.Equal(1, entriesRead);
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
Assert.Equal(mainProgramId, info[0].ProgramId);
}
2020-08-05 07:49:01 +02:00
[Fact]
public void CreateTemporaryStorage_DoesNotExist_SaveIsCreated()
{
long availableSize = 0x220000;
var applicationId = new Ncm.ApplicationId(1);
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
Assert.Success(fs.CreateTemporaryStorage(applicationId, 0, availableSize, SaveDataFlags.None));
using var iterator = new UniqueRef<SaveDataIterator>();
fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.Temporary);
var info = new SaveDataInfo[2];
iterator.Get.ReadSaveDataInfo(out long entriesRead, info);
Assert.Equal(1, entriesRead);
Assert.Equal(applicationId, info[0].ProgramId);
Assert.Equal(SaveDataType.Temporary, info[0].Type);
}
[Fact]
public void CreateTemporaryStorage_AlreadyExists_ReturnsPathAlreadyExists()
{
var applicationId = new Ncm.ApplicationId(1);
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
Assert.Success(fs.CreateTemporaryStorage(applicationId, 0, 0x400000, SaveDataFlags.None));
Assert.Result(ResultFs.PathAlreadyExists, fs.CreateTemporaryStorage(applicationId, 0, 0x400000, SaveDataFlags.None));
}
2021-11-14 20:08:57 +01:00
[Fact]
public void DeleteSaveData_DoesNotExist_ReturnsTargetNotFound()
{
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
Assert.Result(ResultFs.TargetNotFound, fs.DeleteSaveData(1));
}
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void DeleteSaveData_SaveExistsInUserSaveSpace_SaveIsDeleted()
{
var applicationId = new Ncm.ApplicationId(1);
var userId = new UserId(5, 4);
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Create the save
Assert.Success(fs.CreateSaveData(applicationId, userId, 0, 0x1000, 0x1000, SaveDataFlags.None));
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Get the ID of the save
using var iterator = new UniqueRef<SaveDataIterator>();
Assert.Success(fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User));
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
var info = new SaveDataInfo[1];
Assert.Success(iterator.Get.ReadSaveDataInfo(out _, info));
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Delete the save
Assert.Success(fs.DeleteSaveData(info[0].SaveDataId));
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Iterate saves again
using var iterator2 = new UniqueRef<SaveDataIterator>();
Assert.Success(fs.OpenSaveDataIterator(ref iterator2.Ref(), SaveDataSpaceId.User));
Assert.Success(iterator2.Get.ReadSaveDataInfo(out long entriesRead, info));
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Make sure no saves were returned
Assert.Equal(0, entriesRead);
}
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
[Theory]
[InlineData(2, 3, 2)]
[InlineData(3, 3, 4)]
[InlineData(5, 3, 5)]
public void DeleteSaveData_SaveDataIteratorsAreOpen_IteratorsPointToSameEntry(int nextEntryWhenRemoving,
int entryToRemove, int expectedNextEntry)
{
const int count = 20;
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Create saves
Assert.Success(PopulateSaveData(fs, count));
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Open an iterator
using var iterator = new UniqueRef<SaveDataIterator>();
Assert.Success(fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User));
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Skip ahead a few entries. Entries start counting at 1, so subtract 1
var infos = new SaveDataInfo[nextEntryWhenRemoving - 1];
Assert.Success(iterator.Get.ReadSaveDataInfo(out long readCount, infos));
Assert.Equal(infos.Length, readCount);
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Delete the save
Assert.Success(fs.DeleteSaveData(SaveDataSpaceId.User, (ulong)entryToRemove));
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Check the program ID of the next entry
Assert.Success(iterator.Get.ReadSaveDataInfo(out long readCount2, infos.AsSpan(0, 1)));
Assert.Equal(1, readCount2);
Assert.Equal((ulong)expectedNextEntry, infos[0].ProgramId.Value);
}
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
[Theory]
[InlineData(6, 7, 6)]
[InlineData(8, 7, 8)]
public void CreateSaveData_SaveDataIteratorsAreOpen_IteratorsPointToSameEntry(int nextEntryWhenAdding,
int entryToAdd, int expectedNextEntry)
{
// Static save IDs must have the high bit set
const ulong mask = 0x8000000000000000;
const int count = 10;
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Create saves
for (int i = 0; i < count * 2; i++)
{
Assert.Success(fs.CreateSystemSaveData(SaveDataSpaceId.User, ((ulong)i * 2) | mask, 0, 0x4000,
2020-08-05 07:49:01 +02:00
0x4000, SaveDataFlags.None));
2021-11-14 20:08:57 +01:00
}
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Open an iterator
using var iterator = new UniqueRef<SaveDataIterator>();
Assert.Success(fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User));
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Skip ahead a few entries. We skipped 0 and added every other ID, so divide by 2 and subtract 1
var infos = new SaveDataInfo[nextEntryWhenAdding / 2 - 1];
Assert.Success(iterator.Get.ReadSaveDataInfo(out long readCount, infos));
Assert.Equal(infos.Length, readCount);
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Create the save
Assert.Success(fs.CreateSystemSaveData(SaveDataSpaceId.User, (uint)entryToAdd | mask, (ulong)entryToAdd, 0x4000,
0x4000, SaveDataFlags.None));
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
// Check the save ID of the next entry
Assert.Success(iterator.Get.ReadSaveDataInfo(out long readCount2, infos.AsSpan(0, 1)));
Assert.Equal(1, readCount2);
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
Assert.Equal((uint)expectedNextEntry | mask, infos[0].SaveDataId);
}
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
[Fact]
public void OpenSaveDataIterator_MultipleSavesExist_IteratorReturnsSavesInOrder()
{
const int count = 20;
const int rngSeed = 359;
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2020-08-05 07:49:01 +02:00
2021-11-14 20:08:57 +01:00
Assert.Success(PopulateSaveData(fs, count, rngSeed));
2021-11-14 20:08:57 +01:00
using var iterator = new UniqueRef<SaveDataIterator>();
Assert.Success(fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User));
2021-11-14 20:08:57 +01:00
var info = new SaveDataInfo();
for (int i = 0; i < count; i++)
{
Assert.Success(iterator.Get.ReadSaveDataInfo(out long readCount, SpanHelpers.AsSpan(ref info)));
Assert.Equal(1, readCount);
Assert.Equal((ulong)i, info.ProgramId.Value);
}
2021-11-14 20:08:57 +01:00
Assert.Success(iterator.Get.ReadSaveDataInfo(out long readCountFinal, SpanHelpers.AsSpan(ref info)));
2021-11-14 20:08:57 +01:00
Assert.Equal(0, readCountFinal);
}
2021-11-14 20:08:57 +01:00
[Fact]
public void ReadSaveDataInfo_WhenFilteringSavesByUserId_IteratorReturnsAllMatchingSaves()
{
const int count = 10;
const int countUser1 = 5;
2021-11-14 20:08:57 +01:00
var user1Id = new UserId(0x1234, 0x5678);
var user2Id = new UserId(0x1122, 0x3344);
2021-11-14 20:08:57 +01:00
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2021-11-14 20:08:57 +01:00
for (int i = 1; i <= countUser1; i++)
{
var applicationId = new Ncm.ApplicationId((uint)i);
Assert.Success(fs.CreateSaveData(applicationId, user1Id, 0, 0x4000, 0x4000, SaveDataFlags.None));
}
2021-11-14 20:08:57 +01:00
for (int i = countUser1 + 1; i <= count; i++)
{
var applicationId = new Ncm.ApplicationId((uint)i);
Assert.Success(fs.CreateSaveData(applicationId, user2Id, 0, 0x4000, 0x4000, SaveDataFlags.None));
}
Assert.Success(SaveDataFilter.Make(out SaveDataFilter filter, programId: default, saveType: default, user2Id,
saveDataId: default, index: default));
2021-11-14 20:08:57 +01:00
using var iterator = new UniqueRef<SaveDataIterator>();
Assert.Success(fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User, in filter));
2021-11-14 20:08:57 +01:00
var info = new SaveDataInfo();
for (int i = countUser1 + 1; i <= count; i++)
{
Assert.Success(iterator.Get.ReadSaveDataInfo(out long readCount, SpanHelpers.AsSpan(ref info)));
2021-11-14 20:08:57 +01:00
Assert.Equal(1, readCount);
Assert.Equal((ulong)i, info.ProgramId.Value);
Assert.Equal(user2Id, info.UserId);
2020-08-05 07:49:01 +02:00
}
2021-11-14 20:08:57 +01:00
Assert.Success(iterator.Get.ReadSaveDataInfo(out long readCountFinal, SpanHelpers.AsSpan(ref info)));
Assert.Equal(0, readCountFinal);
}
2021-11-14 20:08:57 +01:00
[Fact]
public void GetSaveDataCommitId_AfterSetSaveDataCommitIdIsCalled_ReturnsSetCommitId()
{
long commitId = 46506854;
2021-11-14 20:08:57 +01:00
var applicationId = new Ncm.ApplicationId(1);
var userId = new UserId(5, 4);
2021-11-14 20:08:57 +01:00
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2021-11-14 20:08:57 +01:00
// Create the save
Assert.Success(fs.CreateSaveData(applicationId, userId, 0, 0x1000, 0x1000, SaveDataFlags.None));
2021-11-14 20:08:57 +01:00
// Get the created save data's ID
using var iterator = new UniqueRef<SaveDataIterator>();
Assert.Success(fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User));
2021-11-14 20:08:57 +01:00
var info = new SaveDataInfo[2];
iterator.Get.ReadSaveDataInfo(out long entriesRead, info);
2021-11-14 20:08:57 +01:00
Assert.Equal(1, entriesRead);
2021-11-14 20:08:57 +01:00
// Set the new commit ID
Assert.Success(fs.SetSaveDataCommitId(info[0].SpaceId, info[0].SaveDataId, commitId));
2021-11-14 20:08:57 +01:00
Assert.Success(fs.GetSaveDataCommitId(out long actualCommitId, info[0].SpaceId, info[0].SaveDataId));
2021-11-14 20:08:57 +01:00
Assert.Equal(commitId, actualCommitId);
}
[Fact]
public void GetSaveDataTimeStamp_AfterSetSaveDataTimeStampIsCalled_ReturnsSetTimeStamp()
{
var timeStamp = new PosixTime(12345678);
2021-11-14 20:08:57 +01:00
var applicationId = new Ncm.ApplicationId(1);
var userId = new UserId(5, 4);
2021-11-14 20:08:57 +01:00
FileSystemClient fs = FileSystemServerFactory.CreateClient(true);
2021-11-14 20:08:57 +01:00
// Create the save
Assert.Success(fs.CreateSaveData(applicationId, userId, 0, 0x1000, 0x1000, SaveDataFlags.None));
2021-11-14 20:08:57 +01:00
// Get the created save data's ID
using var iterator = new UniqueRef<SaveDataIterator>();
Assert.Success(fs.OpenSaveDataIterator(ref iterator.Ref(), SaveDataSpaceId.User));
2021-11-14 20:08:57 +01:00
var info = new SaveDataInfo[2];
iterator.Get.ReadSaveDataInfo(out long entriesRead, info);
2021-11-14 20:08:57 +01:00
Assert.Equal(1, entriesRead);
2021-11-14 20:08:57 +01:00
// Set the new timestamp
Assert.Success(fs.SetSaveDataTimeStamp(info[0].SpaceId, info[0].SaveDataId, timeStamp));
2021-11-14 20:08:57 +01:00
Assert.Success(fs.GetSaveDataTimeStamp(out PosixTime actualTimeStamp, info[0].SpaceId, info[0].SaveDataId));
2021-11-14 20:08:57 +01:00
Assert.Equal(timeStamp, actualTimeStamp);
}
[Fact]
public void OpenCacheStorageList_ReadIntoLargeBuffer_AllIndexesAreRead()
{
var applicationId = new Ncm.ApplicationId(1);
Horizon hos = HorizonFactory.CreateBasicHorizon();
HorizonClient client = hos.CreateHorizonClient(new ProgramLocation(applicationId, StorageId.BuiltInSystem),
(AccessControlBits.Bits)ulong.MaxValue);
Assert.Success(client.Fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 0, 0, 0, SaveDataFlags.None));
Assert.Success(client.Fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 6, 0, 0, SaveDataFlags.None));
Assert.Success(client.Fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 2, 0, 0, SaveDataFlags.None));
Assert.Success(client.Fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 3, 0, 0, SaveDataFlags.None));
Assert.Success(client.Fs.OpenCacheStorageList(out CacheStorageListHandle handle));
var infoBuffer = new CacheStorageInfo[5];
Assert.Success(client.Fs.ReadCacheStorageList(out int readCount, infoBuffer, handle));
Assert.Equal(4, readCount);
Assert.Equal(0, infoBuffer[0].Index);
Assert.Equal(2, infoBuffer[1].Index);
Assert.Equal(3, infoBuffer[2].Index);
Assert.Equal(6, infoBuffer[3].Index);
client.Fs.CloseCacheStorageList(handle);
}
[Fact]
public void OpenCacheStorageList_ReadIntoMultipleBuffers_AllIndexesAreRead()
{
var applicationId = new Ncm.ApplicationId(1);
Horizon hos = HorizonFactory.CreateBasicHorizon();
HorizonClient client = hos.CreateHorizonClient(new ProgramLocation(applicationId, StorageId.BuiltInSystem),
(AccessControlBits.Bits)ulong.MaxValue);
Assert.Success(client.Fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 0, 0, 0, SaveDataFlags.None));
Assert.Success(client.Fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 6, 0, 0, SaveDataFlags.None));
Assert.Success(client.Fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 2, 0, 0, SaveDataFlags.None));
Assert.Success(client.Fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 3, 0, 0, SaveDataFlags.None));
Assert.Success(client.Fs.OpenCacheStorageList(out CacheStorageListHandle handle));
var infoBuffer = new CacheStorageInfo[2];
Assert.Success(client.Fs.ReadCacheStorageList(out int readCount, infoBuffer, handle));
Assert.Equal(2, readCount);
Assert.Equal(0, infoBuffer[0].Index);
Assert.Equal(2, infoBuffer[1].Index);
Assert.Success(client.Fs.ReadCacheStorageList(out readCount, infoBuffer, handle));
Assert.Equal(2, readCount);
Assert.Equal(3, infoBuffer[0].Index);
Assert.Equal(6, infoBuffer[1].Index);
Assert.Success(client.Fs.ReadCacheStorageList(out readCount, infoBuffer, handle));
Assert.Equal(0, readCount);
client.Fs.CloseCacheStorageList(handle);
}
2021-11-14 20:08:57 +01:00
private static Result PopulateSaveData(FileSystemClient fs, int count, int seed = -1)
{
if (seed == -1)
2020-08-05 07:49:01 +02:00
{
2021-11-14 20:08:57 +01:00
for (int i = 1; i <= count; i++)
2020-08-05 07:49:01 +02:00
{
2021-11-14 20:08:57 +01:00
var applicationId = new Ncm.ApplicationId((uint)i);
Result rc = fs.CreateSaveData(applicationId, InvalidUserId, 0, 0x4000, 0x4000, SaveDataFlags.None);
2021-11-14 20:08:57 +01:00
if (rc.IsFailure()) return rc;
2020-08-05 07:49:01 +02:00
}
2021-11-14 20:08:57 +01:00
}
else
{
var rng = new FullCycleRandom(count, seed);
for (int i = 1; i <= count; i++)
2020-08-05 07:49:01 +02:00
{
2021-11-14 20:08:57 +01:00
var applicationId = new Ncm.ApplicationId((uint)rng.Next());
Result rc = fs.CreateSaveData(applicationId, InvalidUserId, 0, 0x4000, 0x4000, SaveDataFlags.None);
2021-11-14 20:08:57 +01:00
if (rc.IsFailure()) return rc;
2020-08-05 07:49:01 +02:00
}
}
2021-11-14 20:08:57 +01:00
return Result.Success;
}
2021-12-29 18:13:42 +01:00
}