singrdk/base/Services/Fat/Fs/ComponentTest.sg

496 lines
18 KiB
Plaintext

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: Test.sg
//
// Note:
//
//
using DirectoryServices.Utils;
using Microsoft.SingSharp;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Directory;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.Security;
using System;
using MSD = Microsoft.Singularity.Directory;
namespace Microsoft.Singularity.Services.Fat.Fs
{
public class ComponentTest
{
private delegate EnumerationRecords[] in ExHeap EnumerateDelegate(uint whence, out uint nextWhence);
private static string! DirEntryToHuman(char[]! in ExHeap dn)
{
int ls = 7;
while (dn[ls] == ' ' && ls > 0) {
ls--;
}
string! s = Bitter.ToString2(dn, 0, ls + 1);
ls = 10;
while (dn[ls] == ' ' && ls >= 8) {
ls--;
}
if (ls >= 8) {
s += "." + Bitter.ToString2(dn, 8, ls - 8 + 1);
}
return s;
}
private static void TestShortName(string! longName,
int attempt,
string! shortName)
{
char[]! in ExHeap ln = Bitter.FromString2(longName);
char[]! in ExHeap sn = new [ExHeap] char [DirectoryEntry.ShortNameEntryLength];
LongDirectoryEntry.WriteShortNameEntry(ln, attempt, sn);
string got = DirEntryToHuman(sn);
DebugStub.Print("Longname = \"{0}\" (\"{1}\") => \"{2}\" ({3})",
__arglist(longName, shortName,
got,
Bitter.ToString2(sn))
);
if (got == shortName) {
DebugStub.Print(" [ Pass ]\n");
}
else {
DebugStub.Print(" [ FAIL ]\n");
DebugStub.Break();
}
delete ln;
delete sn;
}
private static void TestShortName(string! longName, string! shortName)
{
TestShortName(longName, 1, shortName);
}
private static void TestShortNames()
{
TestShortName("The cat sat on the mat", "THECAT~1");
TestShortName("The cat sat on the mat", "THECAT~1");
TestShortName("abcdefghi.xyz", "ABCDEF~1.XYZ");
TestShortName("test1.txt", "TEST1~1.TXT");
TestShortName("....test1.txt...", "TEST1~1.TXT");
TestShortName(" . . ..test1.txt.. . ", "TEST1~1.TXT");
TestShortName("The cat sat on the mat.txt", "THECAT~1.TXT");
TestShortName("a.b", "A~1.B");
TestShortName("a.b", "A~1.B");
TestShortName("a.b", 99, "A~99.B");
TestShortName("abcdefghi.1234", 700, "ABCD~700.123");
}
private static void TestEnumerate(EnumerateDelegate! enumerateDelegate)
{
int done = 0;
for (uint whence = 0; whence != Directory.FinalWhence;) {
uint nextWhence;
EnumerationRecords[] in ExHeap er = enumerateDelegate(whence, out nextWhence);
if (er != null) {
for (int i = 0; i < er.Length; i++) {
expose (er[i]) {
DebugStub.Print(
"{0}{1}\n",
__arglist(
Bitter.ToString(er[i].Path),
(er[i].Type == NodeType.Directory) ? "/" : "",
er[i].Type)
);
}
}
done += er.Length;
delete er;
}
whence = nextWhence;
}
DebugStub.Print("Counted {0} entries.", __arglist(done));
}
private static void EnumerateAndFindResults(Directory! d)
{
int done = 0;
for (uint whence = 0; whence != Directory.FinalWhence;) {
uint nextWhence;
EnumerationRecords[] in ExHeap er =
d.Enumerate2(whence, out nextWhence);
if (er != null) {
for (int i = 0; i < er.Length; i++) {
expose (er[i]) {
DebugStub.Print(
"Validating find for {0}{1}...",
__arglist(
Bitter.ToString(er[i].Path),
(er[i].Type == NodeType.Directory) ? "/" : "",
er[i].Type)
);
bool exists = d.FileOrDirectoryExists(er[i].Path);
DebugStub.Print("{0}\n",
__arglist(exists ? "yes" : "no"));
}
}
done += er.Length;
delete er;
}
whence = nextWhence;
}
Console.WriteLine("Counted {0} entries.", done);
}
private static void FillInTail(char[]! in ExHeap filename,
int suffix)
{
int pos = filename.Length;
while (suffix != 0 && pos != 0) {
filename[--pos] = (char)((int)'0' + (suffix % 10));
suffix /= 10;
}
}
private static bool CreateRangeOfSubDirectories(Directory! d,
string basename,
int rangeBegin,
int rangeLength)
{
int digitCount = (int)Math.Log10(rangeBegin + rangeLength);
char []! in ExHeap fullname =
Bitter.FromString2(basename + new string(' ', digitCount + 1));
try {
int rangeEnd = rangeBegin + rangeLength;
while (rangeBegin != rangeEnd) {
FillInTail(fullname, rangeBegin);
MSD.ErrorCode error = d.CreateDirectory(fullname);
if (error != MSD.ErrorCode.NoError) {
Console.WriteLine(
"Failed to create directory {0}: {1}",
Bitter.ToString2(fullname),
SdsUtils.ErrorCodeToString(error));
return false;
}
rangeBegin++;
}
}
finally {
delete fullname;
}
return true;
}
private static bool DeleteRangeOfSubDirectories(Directory! d,
string basename,
int rangeBegin,
int rangeLength)
{
int digitCount = (int)Math.Log10(rangeBegin + rangeLength);
char []! in ExHeap fullname =
Bitter.FromString2(basename + new string(' ', digitCount + 1));
try {
int rangeEnd = rangeBegin + rangeLength;
while (rangeBegin != rangeEnd) {
FillInTail(fullname, rangeBegin);
MSD.ErrorCode error = d.DeleteDirectory(fullname);
if (error != MSD.ErrorCode.NoError) {
Console.WriteLine(
"Failed to delete directory {0}: {1}",
Bitter.ToString2(fullname),
SdsUtils.ErrorCodeToString(error));
return false;
}
rangeBegin++;
}
}
finally {
delete fullname;
}
return true;
}
private static char[]! in ExHeap GetTreeNodeName(int count, int depth)
{
return Bitter.FromString2(
(!)String.Format("d_{0}_{1}", depth, count)
);
}
private static void CreateTree(Directory! treeRoot,
int fanout,
int depth)
{
if (depth <= 0) {
return;
}
DebugStub.Print("CreateTree(fanout = {0}, depth = {1})",
__arglist(fanout, depth));
for (int i = 0; i < fanout; i++) {
char[]! in ExHeap nodeName = GetTreeNodeName(i, depth);
try {
MSD.ErrorCode error = treeRoot.CreateDirectory(nodeName);
if (error != MSD.ErrorCode.NoError) {
DebugStub.Break();
}
Directory child;
error = treeRoot.OpenDirectory(nodeName, out child);
if (error != MSD.ErrorCode.NoError) {
DebugStub.Break();
}
CreateTree((!)child, fanout, depth - 1);
} finally {
delete nodeName;
}
}
}
private static void DeleteTree(Directory! treeRoot,
int fanout,
int depth)
{
if (depth <= 0) {
return;
}
DebugStub.Print("DeleteTree(fanout = {0}, depth = {1})\n",
__arglist(fanout, depth));
for (int i = 0; i < fanout; i++) {
char[]! in ExHeap nodeName = GetTreeNodeName(i, depth);
try {
Directory child;
MSD.ErrorCode error =
treeRoot.OpenDirectory(nodeName, out child);
DebugStub.Assert(error == MSD.ErrorCode.NoError);
DeleteTree((!)child, fanout, depth - 1);
error = treeRoot.DeleteDirectory(nodeName);
DebugStub.Assert(error == MSD.ErrorCode.NoError);
error = treeRoot.OpenDirectory(nodeName, out child);
DebugStub.Assert(error == MSD.ErrorCode.NotFound);
}
finally {
delete nodeName;
}
}
}
private static void CreateAndDestroyTree(Directory! treeRoot,
int fanout,
int depth)
{
CreateTree(treeRoot, fanout, depth);
DeleteTree(treeRoot, fanout, depth);
}
private static void CreateFile(Directory! directory,
string! filename)
{
File file;
char[]! in ExHeap ename = Bitter.FromString2(filename);
MSD.ErrorCode error = directory.CreateAndOpenFile(ename, out file);
delete ename;
DebugStub.Assert(error == MSD.ErrorCode.NoError);
if (file == null) {
return;
}
byte[]! in ExHeap buffer = new [ExHeap] byte [32];
try {
const int sections = 1000;
for (int i = 0; i < sections; i++) {
byte b = (byte)('a' + (i % 26));
for (int j = 0; j < buffer.Length; j++) {
buffer[j] = b;
}
buffer[buffer.Length - 2] = (byte)'\r';
buffer[buffer.Length - 1] = (byte)'\n';
int written;
FileError fe = file.Write(buffer,
0, (uint)(i * buffer.Length),
buffer.Length, out written);
DebugStub.Assert(written == buffer.Length);
DebugStub.Assert(fe == FileError.NoError);
}
DebugStub.Print("Wrote {0} bytes to {1}\n",
__arglist(sections * buffer.Length,
filename));
file.Close();
}
finally {
delete buffer;
}
}
private static void CreateSparseFile(Directory! directory,
string! filename)
{
File file;
char[]! in ExHeap ename = Bitter.FromString2(filename);
MSD.ErrorCode error = directory.CreateAndOpenFile(ename, out file);
delete ename;
DebugStub.Assert(error == MSD.ErrorCode.NoError);
if (file == null) {
return;
}
byte[]! in ExHeap buffer = new [ExHeap] byte [32];
try {
const int sections = 1000;
for (int i = 0; i < sections; i++) {
byte b = (byte)('a' + (i % 26));
for (int j = 0; j < buffer.Length; j++) {
buffer[j] = b;
}
buffer[buffer.Length - 2] = (byte)'\r';
buffer[buffer.Length - 1] = (byte)'\n';
int written;
FileError fe = file.Write(buffer,
0, (uint)(2 * i * buffer.Length),
buffer.Length, out written);
DebugStub.Assert(written == buffer.Length);
DebugStub.Assert(fe == FileError.NoError);
}
DebugStub.Print("Wrote {0} bytes to {1}\n",
__arglist(sections * buffer.Length,
filename));
file.Close();
}
finally {
delete buffer;
}
}
public static int MainTest(string []! args)
{
TestShortNames();
BPB.ValidateOverlay();
if (args.Length >= 2) {
if (FatVolume.Mount((!)args[1], false) == false) {
return 0;
}
DateTime t0 = DateTime.Now;
Directory! d = Directory.OpenRootDirectory();
CreateFile(d, "testfile.txt");
CreateSparseFile(d, "testfile2.txt");
DateTime t1 = DateTime.Now;
Directory! dummy = Directory.OpenRootDirectory();
DateTime t2 = DateTime.Now;
assert dummy != null;
DebugStub.Print("First open took {0} ms.\n",
__arglist((t1 - t0).Milliseconds));
DebugStub.Print("Second open took {0} ms.\n",
__arglist((t2 - t1).Milliseconds));
//#if TEST_OPEN
Directory foo;
char []! in ExHeap subDirName = Bitter.FromString2("some T~1");
d.OpenDirectory(subDirName, out foo);
delete subDirName;
Directory bar;
char []! in ExHeap subDirName2 = Bitter.FromString2("foo");
d.OpenDirectory(subDirName2, out bar);
delete subDirName2;
// #endif // TEST_OPEN
EnumerateDelegate! ed1 = new EnumerateDelegate(d.Enumerate);
DateTime t3 = DateTime.Now;
TestEnumerate(ed1);
DateTime t4 = DateTime.Now;
TestEnumerate(ed1);
DateTime t5 = DateTime.Now;
EnumerateDelegate! ed2 = new EnumerateDelegate(d.Enumerate2);
DateTime t6 = DateTime.Now;
TestEnumerate(ed2);
DateTime t7 = DateTime.Now;
DebugStub.Print("Enum0 attempt 0 {0} ms.\n",
__arglist((t4 - t3).Milliseconds));
DebugStub.Print("Enum0 attempt 1 {0} ms.\n",
__arglist((t5 - t4).Milliseconds));
DebugStub.Print("Enum1 attempt 0 {0} ms.\n",
__arglist((t7 - t6).Milliseconds));
EnumerateAndFindResults(d);
const int TestFileCount = 200;
const string TestFileBaseName = "some testing directory ";
DebugStub.Print("Creating test directories");
CreateRangeOfSubDirectories(d, "Some long test dir",
1, 400);
TestEnumerate(ed1);
TestEnumerate(ed2);
EnumerateAndFindResults(d);
DeleteRangeOfSubDirectories(d, "Some long test dir",
1, 400);
TestEnumerate(ed1);
TestEnumerate(ed2);
EnumerateAndFindResults(d);
CreateRangeOfSubDirectories(
d, "The cat sat on the mat is long", 1, 3000);
EnumerateAndFindResults(d);
DeleteRangeOfSubDirectories(
d, "The cat sat on the mat is long", 1, 3000);
TestEnumerate(ed1);
TestEnumerate(ed2);
EnumerateAndFindResults(d);
CreateRangeOfSubDirectories(
d, "foo", 1, 300);
EnumerateAndFindResults(d);
DeleteRangeOfSubDirectories(
d, "foo", 1, 300);
TestEnumerate(ed1);
TestEnumerate(ed2);
EnumerateAndFindResults(d);
DebugStub.Print("Running directory tree create and delete test\n");
CreateAndDestroyTree(d, 12, 3);
FatVolume.Unmount();
}
return 0;
}
}
}