mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
330 lines
11 KiB
C
330 lines
11 KiB
C
/**
|
|
* @file dirbuf-test.c
|
|
*
|
|
* @copyright 2015-2019 Bill Zissimopoulos
|
|
*/
|
|
/*
|
|
* This file is part of WinFsp.
|
|
*
|
|
* You can redistribute it and/or modify it under the terms of the GNU
|
|
* General Public License version 3 as published by the Free Software
|
|
* Foundation.
|
|
*
|
|
* Licensees holding a valid commercial license may use this software
|
|
* in accordance with the commercial license agreement provided in
|
|
* conjunction with the software. The terms and conditions of any such
|
|
* commercial license agreement shall govern, supersede, and render
|
|
* ineffective any application of the GPLv3 license to this software,
|
|
* notwithstanding of any reference thereto in the software or
|
|
* associated repository.
|
|
*/
|
|
|
|
#include <winfsp/winfsp.h>
|
|
#include <tlib/testsuite.h>
|
|
#include <time.h>
|
|
|
|
#include "winfsp-tests.h"
|
|
|
|
static void dirbuf_empty_test(void)
|
|
{
|
|
PVOID DirBuffer = 0;
|
|
NTSTATUS Result;
|
|
BOOLEAN Success;
|
|
UINT8 Buffer[64];
|
|
ULONG BytesTransferred;
|
|
|
|
BytesTransferred = 0;
|
|
FspFileSystemReadDirectoryBuffer(&DirBuffer, 0, Buffer, sizeof Buffer, &BytesTransferred);
|
|
ASSERT(sizeof(UINT16) == BytesTransferred);
|
|
|
|
Result = STATUS_UNSUCCESSFUL;
|
|
Success = FspFileSystemAcquireDirectoryBuffer(&DirBuffer, FALSE, &Result);
|
|
ASSERT(Success);
|
|
ASSERT(STATUS_SUCCESS == Result);
|
|
|
|
FspFileSystemReleaseDirectoryBuffer(&DirBuffer);
|
|
|
|
BytesTransferred = 0;
|
|
FspFileSystemReadDirectoryBuffer(&DirBuffer, 0, Buffer, sizeof Buffer, &BytesTransferred);
|
|
ASSERT(sizeof(UINT16) == BytesTransferred);
|
|
|
|
Result = STATUS_UNSUCCESSFUL;
|
|
Success = FspFileSystemAcquireDirectoryBuffer(&DirBuffer, FALSE, &Result);
|
|
ASSERT(!Success);
|
|
ASSERT(STATUS_SUCCESS == Result);
|
|
|
|
BytesTransferred = 0;
|
|
FspFileSystemReadDirectoryBuffer(&DirBuffer, 0, Buffer, sizeof Buffer, &BytesTransferred);
|
|
ASSERT(sizeof(UINT16) == BytesTransferred);
|
|
|
|
Result = STATUS_UNSUCCESSFUL;
|
|
Success = FspFileSystemAcquireDirectoryBuffer(&DirBuffer, TRUE, &Result);
|
|
ASSERT(Success);
|
|
ASSERT(STATUS_SUCCESS == Result);
|
|
|
|
FspFileSystemReleaseDirectoryBuffer(&DirBuffer);
|
|
|
|
BytesTransferred = 0;
|
|
FspFileSystemReadDirectoryBuffer(&DirBuffer, 0, Buffer, sizeof Buffer, &BytesTransferred);
|
|
ASSERT(sizeof(UINT16) == BytesTransferred);
|
|
|
|
FspFileSystemDeleteDirectoryBuffer(&DirBuffer);
|
|
FspFileSystemDeleteDirectoryBuffer(&DirBuffer);
|
|
}
|
|
|
|
static void dirbuf_dots_test(void)
|
|
{
|
|
PVOID DirBuffer = 0;
|
|
NTSTATUS Result;
|
|
BOOLEAN Success;
|
|
union
|
|
{
|
|
UINT8 B[sizeof(FSP_FSCTL_DIR_INFO) + MAX_PATH * sizeof(WCHAR)];
|
|
FSP_FSCTL_DIR_INFO D;
|
|
} DirInfoBuf;
|
|
FSP_FSCTL_DIR_INFO *DirInfo = &DirInfoBuf.D, *DirInfoEnd;
|
|
UINT8 Buffer[1024];
|
|
ULONG Length, BytesTransferred;
|
|
WCHAR CurrFileName[MAX_PATH];
|
|
ULONG N;
|
|
|
|
Length = sizeof Buffer;
|
|
|
|
Result = STATUS_UNSUCCESSFUL;
|
|
Success = FspFileSystemAcquireDirectoryBuffer(&DirBuffer, FALSE, &Result);
|
|
ASSERT(Success);
|
|
ASSERT(STATUS_SUCCESS == Result);
|
|
|
|
memset(&DirInfoBuf, 0, sizeof DirInfoBuf);
|
|
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + 1 * sizeof(WCHAR));
|
|
DirInfo->FileNameBuf[0] = L'.';
|
|
Success = FspFileSystemFillDirectoryBuffer(&DirBuffer, DirInfo, &Result);
|
|
ASSERT(Success);
|
|
ASSERT(STATUS_SUCCESS == Result);
|
|
|
|
memset(&DirInfoBuf, 0, sizeof DirInfoBuf);
|
|
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + 1 * sizeof(WCHAR));
|
|
DirInfo->FileNameBuf[0] = L' ';
|
|
Success = FspFileSystemFillDirectoryBuffer(&DirBuffer, DirInfo, &Result);
|
|
ASSERT(Success);
|
|
ASSERT(STATUS_SUCCESS == Result);
|
|
|
|
memset(&DirInfoBuf, 0, sizeof DirInfoBuf);
|
|
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + 2 * sizeof(WCHAR));
|
|
DirInfo->FileNameBuf[0] = L'.';
|
|
DirInfo->FileNameBuf[1] = L'.';
|
|
Success = FspFileSystemFillDirectoryBuffer(&DirBuffer, DirInfo, &Result);
|
|
ASSERT(Success);
|
|
ASSERT(STATUS_SUCCESS == Result);
|
|
|
|
FspFileSystemReleaseDirectoryBuffer(&DirBuffer);
|
|
|
|
BytesTransferred = 0;
|
|
FspFileSystemReadDirectoryBuffer(&DirBuffer, 0, Buffer, Length, &BytesTransferred);
|
|
|
|
N = 0;
|
|
for (
|
|
DirInfo = (PVOID)Buffer, DirInfoEnd = (PVOID)(Buffer + BytesTransferred);
|
|
DirInfoEnd > DirInfo && 0 != DirInfo->Size;
|
|
DirInfo = (PVOID)((PUINT8)DirInfo + FSP_FSCTL_DEFAULT_ALIGN_UP(DirInfo->Size)), N++)
|
|
{
|
|
memcpy(CurrFileName, DirInfo->FileNameBuf, DirInfo->Size - sizeof *DirInfo);
|
|
CurrFileName[(DirInfo->Size - sizeof *DirInfo) / sizeof(WCHAR)] = L'\0';
|
|
|
|
if (0 == N)
|
|
ASSERT(0 == wcscmp(CurrFileName, L"."));
|
|
else if (1 == N)
|
|
ASSERT(0 == wcscmp(CurrFileName, L".."));
|
|
else if (2 == N)
|
|
ASSERT(0 == wcscmp(CurrFileName, L" "));
|
|
}
|
|
ASSERT(DirInfoEnd > DirInfo);
|
|
ASSERT(0 == DirInfo->Size);
|
|
ASSERT(N == 3);
|
|
|
|
FspFileSystemDeleteDirectoryBuffer(&DirBuffer);
|
|
}
|
|
|
|
static void dirbuf_fill_dotest(unsigned seed, ULONG Count)
|
|
{
|
|
PVOID DirBuffer = 0;
|
|
NTSTATUS Result;
|
|
BOOLEAN Success;
|
|
union
|
|
{
|
|
UINT8 B[sizeof(FSP_FSCTL_DIR_INFO) + MAX_PATH * sizeof(WCHAR)];
|
|
FSP_FSCTL_DIR_INFO D;
|
|
} DirInfoBuf;
|
|
FSP_FSCTL_DIR_INFO *DirInfo = &DirInfoBuf.D, *DirInfoEnd;
|
|
PUINT8 Buffer;
|
|
ULONG Length, BytesTransferred;
|
|
WCHAR CurrFileName[MAX_PATH], PrevFileName[MAX_PATH];
|
|
ULONG DotIndex = Count / 3, DotDotIndex = Count / 3 * 2;
|
|
WCHAR Marker[MAX_PATH];
|
|
ULONG N, MarkerIndex, MarkerLength;
|
|
|
|
srand(seed);
|
|
|
|
Length = Count * FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof DirInfoBuf) + sizeof(UINT16);
|
|
Buffer = malloc(Length);
|
|
ASSERT(0 != Buffer);
|
|
|
|
Result = STATUS_UNSUCCESSFUL;
|
|
Success = FspFileSystemAcquireDirectoryBuffer(&DirBuffer, FALSE, &Result);
|
|
ASSERT(Success);
|
|
ASSERT(STATUS_SUCCESS == Result);
|
|
|
|
for (ULONG I = 0; Count > I; I++)
|
|
{
|
|
memset(&DirInfoBuf, 0, sizeof DirInfoBuf);
|
|
|
|
if (I == DotIndex)
|
|
{
|
|
N = 1;
|
|
DirInfo->FileNameBuf[0] = L'.';
|
|
}
|
|
else if (I == DotDotIndex)
|
|
{
|
|
N = 2;
|
|
DirInfo->FileNameBuf[0] = L'.';
|
|
DirInfo->FileNameBuf[1] = L'.';
|
|
}
|
|
else
|
|
{
|
|
N = 24 + rand() % (32 - 24);
|
|
for (ULONG J = 0; N > J; J++)
|
|
DirInfo->FileNameBuf[J] = 'A' + rand() % 26;
|
|
}
|
|
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + N * sizeof(WCHAR));
|
|
|
|
Success = FspFileSystemFillDirectoryBuffer(&DirBuffer, DirInfo, &Result);
|
|
ASSERT(Success);
|
|
ASSERT(STATUS_SUCCESS == Result);
|
|
}
|
|
|
|
FspFileSystemReleaseDirectoryBuffer(&DirBuffer);
|
|
|
|
MarkerIndex = rand() % Count;
|
|
|
|
BytesTransferred = 0;
|
|
FspFileSystemReadDirectoryBuffer(&DirBuffer, 0, Buffer, Length, &BytesTransferred);
|
|
|
|
N = 0;
|
|
PrevFileName[0] = L'\0';
|
|
for (
|
|
DirInfo = (PVOID)Buffer, DirInfoEnd = (PVOID)(Buffer + BytesTransferred);
|
|
DirInfoEnd > DirInfo && 0 != DirInfo->Size;
|
|
DirInfo = (PVOID)((PUINT8)DirInfo + FSP_FSCTL_DEFAULT_ALIGN_UP(DirInfo->Size)), N++)
|
|
{
|
|
memcpy(CurrFileName, DirInfo->FileNameBuf, DirInfo->Size - sizeof *DirInfo);
|
|
CurrFileName[(DirInfo->Size - sizeof *DirInfo) / sizeof(WCHAR)] = L'\0';
|
|
|
|
if (0 == N)
|
|
ASSERT(0 == wcscmp(CurrFileName, L"."));
|
|
else if (1 == N)
|
|
ASSERT(0 == wcscmp(CurrFileName, L".."));
|
|
else
|
|
ASSERT(0 != wcscmp(CurrFileName, L".") && 0 != wcscmp(CurrFileName, L".."));
|
|
|
|
//ASSERT(wcscmp(PrevFileName, CurrFileName) <= 0);
|
|
/* filenames are random enought that should not happen in practice */
|
|
ASSERT(wcscmp(PrevFileName, CurrFileName) < 0);
|
|
|
|
memcpy(PrevFileName, CurrFileName, sizeof CurrFileName);
|
|
|
|
if (N == MarkerIndex)
|
|
{
|
|
memcpy(Marker, CurrFileName, sizeof CurrFileName);
|
|
MarkerLength = (ULONG)((PUINT8)DirInfo + FSP_FSCTL_DEFAULT_ALIGN_UP(DirInfo->Size) - Buffer);
|
|
}
|
|
}
|
|
ASSERT(DirInfoEnd > DirInfo);
|
|
ASSERT(0 == DirInfo->Size);
|
|
ASSERT(N == Count);
|
|
|
|
BytesTransferred = 0;
|
|
FspFileSystemReadDirectoryBuffer(&DirBuffer, Marker, Buffer, Length, &BytesTransferred);
|
|
|
|
N = 0;
|
|
PrevFileName[0] = L'\0';
|
|
for (
|
|
DirInfo = (PVOID)Buffer, DirInfoEnd = (PVOID)(Buffer + BytesTransferred);
|
|
DirInfoEnd > DirInfo && 0 != DirInfo->Size;
|
|
DirInfo = (PVOID)((PUINT8)DirInfo + FSP_FSCTL_DEFAULT_ALIGN_UP(DirInfo->Size)), N++)
|
|
{
|
|
memcpy(CurrFileName, DirInfo->FileNameBuf, DirInfo->Size - sizeof *DirInfo);
|
|
CurrFileName[(DirInfo->Size - sizeof *DirInfo) / sizeof(WCHAR)] = L'\0';
|
|
|
|
ASSERT(0 != wcscmp(CurrFileName, Marker));
|
|
|
|
//ASSERT(wcscmp(PrevFileName, CurrFileName) <= 0);
|
|
/* filenames are random enought that should not happen in practice */
|
|
ASSERT(wcscmp(PrevFileName, CurrFileName) < 0);
|
|
|
|
memcpy(PrevFileName, CurrFileName, sizeof CurrFileName);
|
|
}
|
|
ASSERT(DirInfoEnd > DirInfo);
|
|
ASSERT(0 == DirInfo->Size);
|
|
ASSERT(N == Count - MarkerIndex - 1);
|
|
|
|
BytesTransferred = 0;
|
|
FspFileSystemReadDirectoryBuffer(&DirBuffer, 0, Buffer, MarkerLength, &BytesTransferred);
|
|
|
|
N = 0;
|
|
PrevFileName[0] = L'\0';
|
|
for (
|
|
DirInfo = (PVOID)Buffer, DirInfoEnd = (PVOID)(Buffer + BytesTransferred);
|
|
DirInfoEnd > DirInfo && 0 != DirInfo->Size;
|
|
DirInfo = (PVOID)((PUINT8)DirInfo + FSP_FSCTL_DEFAULT_ALIGN_UP(DirInfo->Size)), N++)
|
|
{
|
|
memcpy(CurrFileName, DirInfo->FileNameBuf, DirInfo->Size - sizeof *DirInfo);
|
|
CurrFileName[(DirInfo->Size - sizeof *DirInfo) / sizeof(WCHAR)] = L'\0';
|
|
|
|
if (N == MarkerIndex)
|
|
ASSERT(0 == wcscmp(CurrFileName, Marker));
|
|
else
|
|
ASSERT(0 != wcscmp(CurrFileName, Marker));
|
|
|
|
//ASSERT(wcscmp(PrevFileName, CurrFileName) <= 0);
|
|
/* filenames are random enought that should not happen in practice */
|
|
ASSERT(wcscmp(PrevFileName, CurrFileName) < 0);
|
|
|
|
memcpy(PrevFileName, CurrFileName, sizeof CurrFileName);
|
|
}
|
|
ASSERT(DirInfoEnd <= DirInfo);
|
|
ASSERT(N == MarkerIndex + 1);
|
|
|
|
FspFileSystemDeleteDirectoryBuffer(&DirBuffer);
|
|
|
|
free(Buffer);
|
|
}
|
|
|
|
static void dirbuf_fill_test(void)
|
|
{
|
|
unsigned seed = (unsigned)time(0);
|
|
|
|
dirbuf_fill_dotest(1485473509, 10);
|
|
|
|
for (ULONG I = 0; 10000 > I; I++)
|
|
dirbuf_fill_dotest(seed + I, 10);
|
|
|
|
for (ULONG I = 0; 1000 > I; I++)
|
|
dirbuf_fill_dotest(seed + I, 100);
|
|
|
|
for (ULONG I = 0; 100 > I; I++)
|
|
dirbuf_fill_dotest(seed + I, 1000);
|
|
|
|
for (ULONG I = 0; 10 > I; I++)
|
|
dirbuf_fill_dotest(seed + I, 10000);
|
|
}
|
|
|
|
void dirbuf_tests(void)
|
|
{
|
|
if (OptExternal)
|
|
return;
|
|
|
|
TEST(dirbuf_empty_test);
|
|
TEST(dirbuf_dots_test);
|
|
TEST(dirbuf_fill_test);
|
|
}
|