Добавлена папка source в CristalDiskMark
This commit is contained in:
+4771
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "WexTestClass.h"
|
||||
|
||||
namespace UnitTests
|
||||
{
|
||||
BEGIN_MODULE()
|
||||
MODULE_PROPERTY(L"Feature", L"CmdLineParser")
|
||||
END_MODULE()
|
||||
|
||||
MODULE_SETUP(ModuleSetup);
|
||||
MODULE_CLEANUP(ModuleCleanup);
|
||||
|
||||
class CmdLineParserUnitTests : public WEX::TestClass<CmdLineParserUnitTests>
|
||||
{
|
||||
private:
|
||||
void VerifyParseCmdLineDisableAllCache(Profile &profile);
|
||||
void VerifyParseCmdLineMappedIO(Profile &profile, MemoryMappedIoFlushMode FlushMode);
|
||||
void VerifyParseCmdLineAccessHints(Profile &profile, bool RandomAccess, bool SequentialScan, bool TemporaryFile);
|
||||
|
||||
public:
|
||||
TEST_CLASS(CmdLineParserUnitTests)
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup);
|
||||
TEST_CLASS_CLEANUP(ClassCleanup);
|
||||
|
||||
TEST_METHOD_SETUP(MethodSetup);
|
||||
TEST_METHOD_CLEANUP(MethodCleanup);
|
||||
|
||||
TEST_METHOD(Test_GetSizeInBytes);
|
||||
TEST_METHOD(TestGetRandomDataWriteBufferData);
|
||||
TEST_METHOD(TestParseCmdLine);
|
||||
TEST_METHOD(TestParseCmdLineAssignAffinity);
|
||||
TEST_METHOD(TestParseCmdLineBlockSize);
|
||||
TEST_METHOD(TestParseCmdLineBufferedWriteThrough);
|
||||
TEST_METHOD(TestParseCmdLineBurstSizeAndThinkTime);
|
||||
TEST_METHOD(TestParseCmdLineConflictingCacheModes);
|
||||
TEST_METHOD(TestParseCmdLineCreateFileAndMaxFileSize);
|
||||
TEST_METHOD(TestParseCmdLineDisableAffinity);
|
||||
TEST_METHOD(TestParseCmdLineDisableAffinityConflict);
|
||||
TEST_METHOD(TestParseCmdLineDisableAllCacheMode1);
|
||||
TEST_METHOD(TestParseCmdLineDisableAllCacheMode2);
|
||||
TEST_METHOD(TestParseCmdLineDisableLocalCache);
|
||||
TEST_METHOD(TestParseCmdLineDisableOSCache);
|
||||
TEST_METHOD(TestParseCmdLineDurationAndProgress);
|
||||
TEST_METHOD(TestParseCmdLineEtwDISK_IO);
|
||||
TEST_METHOD(TestParseCmdLineEtwIMAGE_LOAD);
|
||||
TEST_METHOD(TestParseCmdLineEtwMEMORY_HARD_FAULTS);
|
||||
TEST_METHOD(TestParseCmdLineEtwMEMORY_PAGE_FAULTS);
|
||||
TEST_METHOD(TestParseCmdLineEtwNETWORK);
|
||||
TEST_METHOD(TestParseCmdLineEtwPROCESS);
|
||||
TEST_METHOD(TestParseCmdLineEtwREGISTRY);
|
||||
TEST_METHOD(TestParseCmdLineEtwTHREAD);
|
||||
TEST_METHOD(TestParseCmdLineEtwUseCycleCount);
|
||||
TEST_METHOD(TestParseCmdLineEtwUsePagedMemory);
|
||||
TEST_METHOD(TestParseCmdLineEtwUsePerfTimer);
|
||||
TEST_METHOD(TestParseCmdLineEtwUseSystemTimer);
|
||||
TEST_METHOD(TestParseCmdLineGroupAffinity);
|
||||
TEST_METHOD(TestParseCmdLineHintFlag);
|
||||
TEST_METHOD(TestParseCmdLineBaseMaxTarget);
|
||||
TEST_METHOD(TestParseCmdLineInterlockedSequential);
|
||||
TEST_METHOD(TestParseCmdLineInterlockedSequentialWithStride);
|
||||
TEST_METHOD(TestParseCmdLineIOPriority);
|
||||
TEST_METHOD(TestParseCmdLineMappedIO);
|
||||
TEST_METHOD(TestParseCmdLineMeasureLatency);
|
||||
TEST_METHOD(TestParseCmdLineOverlappedCountAndBaseOffset);
|
||||
TEST_METHOD(TestParseCmdLineRandomIOAlignment);
|
||||
TEST_METHOD(TestParseCmdLineRandomSequentialMixed);
|
||||
TEST_METHOD(TestParseCmdLineRandomWriteBuffers);
|
||||
TEST_METHOD(TestParseCmdLineRandSeed);
|
||||
TEST_METHOD(TestParseCmdLineRandSeedGetTickCount);
|
||||
TEST_METHOD(TestParseCmdLineResultOutput);
|
||||
TEST_METHOD(TestParseCmdLineStrideSize);
|
||||
TEST_METHOD(TestParseCmdLineTargetDistribution);
|
||||
TEST_METHOD(TestParseCmdLineTargetPosition);
|
||||
TEST_METHOD(TestParseCmdLineThreadsPerFileAndThreadStride);
|
||||
TEST_METHOD(TestParseCmdLineThroughput);
|
||||
TEST_METHOD(TestParseCmdLineTotalThreadCountAndThroughput);
|
||||
TEST_METHOD(TestParseCmdLineTotalThreadCountAndTotalRequestCount);
|
||||
TEST_METHOD(TestParseCmdLineUseCompletionRoutines);
|
||||
TEST_METHOD(TestParseCmdLineUseLargePages);
|
||||
TEST_METHOD(TestParseCmdLineUseParallelAsyncIO);
|
||||
TEST_METHOD(TestParseCmdLineVerbose);
|
||||
TEST_METHOD(TestParseCmdLineWarmupAndCooldown);
|
||||
TEST_METHOD(TestParseCmdLineWriteBufferContentRandomNoFilePath);
|
||||
TEST_METHOD(TestParseCmdLineWriteBufferContentRandomWithFilePath);
|
||||
TEST_METHOD(TestParseCmdLineZeroWriteBuffers);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <windows.h>
|
||||
#include "Version.h"
|
||||
|
||||
#include <ntverp.h>
|
||||
|
||||
#define VER_FILETYPE VFT_APP
|
||||
#define VER_FILESUBTYPE VFT2_UNKNOWN
|
||||
#define VER_FILEDESCRIPTION_STR "DiskSpd Storage Performance Tool"
|
||||
#define VER_INTERNALNAME_STR "CmdLineParser.UnitTests.dll"
|
||||
|
||||
#undef VER_PRODUCTVERSION
|
||||
#define VER_PRODUCTVERSION DISKSPD_MAJOR,DISKSPD_MINOR,DISKSPD_BUILD,DISKSPD_QFE
|
||||
|
||||
#undef VER_PRODUCTVERSION_STR
|
||||
#define VER_PRODUCTVERSION_STR DISKSPD_NUMERIC_VERSION_STRING
|
||||
|
||||
#include "common.ver"
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "WexTestClass.h"
|
||||
|
||||
namespace UnitTests
|
||||
{
|
||||
BEGIN_MODULE()
|
||||
MODULE_PROPERTY(L"Feature", L"Common")
|
||||
END_MODULE()
|
||||
|
||||
class PerfTimerUnitTests : public WEX::TestClass<PerfTimerUnitTests>
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(PerfTimerUnitTests);
|
||||
TEST_METHOD(Test_Freq);
|
||||
TEST_METHOD(Test_GetTime);
|
||||
TEST_METHOD(Test_PerfTimeToSeconds);
|
||||
TEST_METHOD(Test_PerfTimeToMilliseconds);
|
||||
TEST_METHOD(Test_PerfTimeToMicroseconds);
|
||||
TEST_METHOD(Test_SecondsToPerfTime);
|
||||
TEST_METHOD(Test_MillisecondsToPerfTime);
|
||||
TEST_METHOD(Test_MicrosecondsToPerfTime);
|
||||
};
|
||||
|
||||
class HistogramUnitTests : public WEX::TestClass<HistogramUnitTests>
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(HistogramUnitTests);
|
||||
TEST_METHOD(Test_Empty);
|
||||
TEST_METHOD(Test_Add);
|
||||
TEST_METHOD(Test_Clear);
|
||||
TEST_METHOD(Test_MinMax);
|
||||
TEST_METHOD(Test_GetPercentile);
|
||||
TEST_METHOD(Test_GetMean);
|
||||
TEST_METHOD(Test_Merge);
|
||||
};
|
||||
|
||||
class IoBucketizerUnitTests : public WEX::TestClass<IoBucketizerUnitTests>
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(IoBucketizerUnitTests);
|
||||
TEST_METHOD(Test_Empty);
|
||||
TEST_METHOD(Test_Add);
|
||||
TEST_METHOD(Test_Merge);
|
||||
TEST_METHOD(Test_GetStandardDeviation);
|
||||
};
|
||||
|
||||
class ProfileUnitTests : public WEX::TestClass<ProfileUnitTests>
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(ProfileUnitTests);
|
||||
TEST_METHOD(Test_GetXmlEmptyProfile);
|
||||
TEST_METHOD(Test_GetXmlPrecreateFilesUseMaxSize);
|
||||
TEST_METHOD(Test_GetXmlPrecreateFilesOnlyFilesWithConstantSizes);
|
||||
TEST_METHOD(Test_GetXmlPrecreateFilesOnlyFilesWithConstantOrZeroSizes);
|
||||
TEST_METHOD(Test_MarkFilesAsCreated);
|
||||
TEST_METHOD(Test_Validate);
|
||||
TEST_METHOD(Test_ValidateSystem);
|
||||
};
|
||||
|
||||
class TargetUnitTests : public WEX::TestClass<TargetUnitTests>
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(TargetUnitTests);
|
||||
TEST_METHOD(TestGetSetRandomDataWriteBufferSize);
|
||||
TEST_METHOD(TestGetSetRandomDataWriteBufferSourcePath);
|
||||
TEST_METHOD(Test_TargetGetXmlWriteBufferContentSequential);
|
||||
TEST_METHOD(Test_TargetGetXmlWriteBufferContentZero);
|
||||
TEST_METHOD(Test_TargetGetXmlWriteBufferContentRandomNoFilePath);
|
||||
TEST_METHOD(Test_TargetGetXmlWriteBufferContentRandomWithFilePath);
|
||||
TEST_METHOD(Test_TargetGetXmlDisableAllCache);
|
||||
TEST_METHOD(Test_TargetGetXmlDisableLocalCache);
|
||||
TEST_METHOD(Test_TargetGetXmlDisableOSCache);
|
||||
TEST_METHOD(Test_TargetGetXmlBufferedWriteThrough);
|
||||
TEST_METHOD(Test_TargetGetXmlMemoryMappedIo);
|
||||
TEST_METHOD(Test_TargetGetXmlMemoryMappedIoFlushModeViewOfFile);
|
||||
TEST_METHOD(Test_TargetGetXmlMemoryMappedIoFlushModeNonVolatileMemory);
|
||||
TEST_METHOD(Test_TargetGetXmlMemoryMappedIoFlushModeNonVolatileMemoryNoDrain);
|
||||
TEST_METHOD(Test_TargetGetXmlRandomAccessHint);
|
||||
TEST_METHOD(Test_TargetGetXmlSequentialScanHint);
|
||||
TEST_METHOD(Test_TargetGetXmlCombinedAccessHint);
|
||||
TEST_METHOD(Test_AllocateAndFillRandomDataWriteBuffer);
|
||||
TEST_METHOD(Test_AllocateAndFillRandomDataWriteBufferFromFile);
|
||||
};
|
||||
|
||||
class ThreadParametersUnitTests : public WEX::TestClass<ThreadParametersUnitTests>
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(ThreadParametersUnitTests);
|
||||
TEST_METHOD(Test_AllocateAndFillBufferForTarget);
|
||||
};
|
||||
|
||||
class TopologyUnitTests : public WEX::TestClass<TopologyUnitTests>
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(TopologyUnitTests);
|
||||
TEST_METHOD(Test_MaskCount);
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: ThreadParameters::GetWriteBuffer
|
||||
// TODO: Target::GetRandomDataWriteBuffer();
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <windows.h>
|
||||
#include "Version.h"
|
||||
|
||||
#include <ntverp.h>
|
||||
|
||||
#define VER_FILETYPE VFT_APP
|
||||
#define VER_FILESUBTYPE VFT2_UNKNOWN
|
||||
#define VER_FILEDESCRIPTION_STR "DiskSpd Storage Performance Tool"
|
||||
#define VER_INTERNALNAME_STR "Common.UnitTests.dll"
|
||||
|
||||
#undef VER_PRODUCTVERSION
|
||||
#define VER_PRODUCTVERSION DISKSPD_MAJOR,DISKSPD_MINOR,DISKSPD_BUILD,DISKSPD_QFE
|
||||
|
||||
#undef VER_PRODUCTVERSION_STR
|
||||
#define VER_PRODUCTVERSION_STR DISKSPD_NUMERIC_VERSION_STRING
|
||||
|
||||
#include "common.ver"
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
+1327
File diff suppressed because it is too large
Load Diff
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "WexTestClass.h"
|
||||
|
||||
namespace UnitTests
|
||||
{
|
||||
BEGIN_MODULE()
|
||||
MODULE_PROPERTY(L"Feature", L"IORequestGenerator")
|
||||
END_MODULE()
|
||||
|
||||
class IORequestGeneratorUnitTests : public WEX::TestClass<IORequestGeneratorUnitTests>
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(IORequestGeneratorUnitTests);
|
||||
TEST_METHOD(Test_GetFilesToPrecreate1);
|
||||
TEST_METHOD(Test_GetFilesToPrecreate2);
|
||||
TEST_METHOD(Test_GetFilesToPrecreateConstantSizes);
|
||||
TEST_METHOD(Test_GetFilesToPrecreateConstantOrZeroSizes);
|
||||
TEST_METHOD(Test_GetFilesToPrecreateUseMaxSize);
|
||||
|
||||
TEST_METHOD(Test_GetNextFileOffsetRandom);
|
||||
TEST_METHOD(Test_GetNextFileOffsetSequential);
|
||||
TEST_METHOD(Test_GetNextFileOffsetInterlockedSequential);
|
||||
TEST_METHOD(Test_GetNextFileOffsetParallelAsyncIO);
|
||||
TEST_METHOD(Test_SequentialWithStride);
|
||||
TEST_METHOD(Test_SequentialWithStrideInterleaved);
|
||||
TEST_METHOD(Test_SequentialWithStrideUneven);
|
||||
|
||||
TEST_METHOD(Test_GetThreadBaseFileOffset);
|
||||
TEST_METHOD(Test_GetThreadBaseFileOffsetWithStride);
|
||||
|
||||
TEST_METHOD(Test_ThreadTargetStateInit);
|
||||
TEST_METHOD(Test_ThreadTargetStateEffectiveDistPct);
|
||||
TEST_METHOD(Test_ThreadTargetStateEffectiveDistAbs);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <windows.h>
|
||||
#include "Version.h"
|
||||
|
||||
#include <ntverp.h>
|
||||
|
||||
#define VER_FILETYPE VFT_APP
|
||||
#define VER_FILESUBTYPE VFT2_UNKNOWN
|
||||
#define VER_FILEDESCRIPTION_STR "DiskSpd Storage Performance Tool"
|
||||
#define VER_INTERNALNAME_STR "IORequestGenerator.UnitTests.dll"
|
||||
|
||||
#undef VER_PRODUCTVERSION
|
||||
#define VER_PRODUCTVERSION DISKSPD_MAJOR,DISKSPD_MINOR,DISKSPD_BUILD,DISKSPD_QFE
|
||||
|
||||
#undef VER_PRODUCTVERSION_STR
|
||||
#define VER_PRODUCTVERSION_STR DISKSPD_NUMERIC_VERSION_STRING
|
||||
|
||||
#include "common.ver"
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
@@ -0,0 +1,965 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "ResultParser.UnitTests.h"
|
||||
#include "Common.h"
|
||||
#include "resultparser.h"
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
using namespace WEX::TestExecution;
|
||||
using namespace WEX::Logging;
|
||||
using namespace std;
|
||||
|
||||
namespace UnitTests
|
||||
{
|
||||
void ResultParserUnitTests::Test_ParseResults()
|
||||
{
|
||||
Profile profile;
|
||||
TimeSpan timeSpan;
|
||||
ResultParser parser;
|
||||
|
||||
Results results;
|
||||
results.fUseETW = false;
|
||||
double fTime = 120.0;
|
||||
results.ullTimeCount = PerfTimer::SecondsToPerfTime(fTime);
|
||||
|
||||
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION systemProcessorInfo = {};
|
||||
systemProcessorInfo.UserTime.QuadPart = static_cast<LONGLONG>(fTime * 30 * 100000);
|
||||
systemProcessorInfo.IdleTime.QuadPart = static_cast<LONGLONG>(fTime * 45 * 100000);
|
||||
systemProcessorInfo.KernelTime.QuadPart = static_cast<LONGLONG>(fTime * 70 * 100000);
|
||||
results.vSystemProcessorPerfInfo.push_back(systemProcessorInfo);
|
||||
|
||||
TargetResults targetResults;
|
||||
targetResults.sPath = "testfile1.dat";
|
||||
targetResults.ullFileSize = 10 * 1024 * 1024;
|
||||
targetResults.ullReadBytesCount = 4 * 1024 * 1024;
|
||||
targetResults.ullReadIOCount = 6;
|
||||
targetResults.ullWriteBytesCount = 2 * 1024 * 1024;
|
||||
targetResults.ullWriteIOCount = 10;
|
||||
targetResults.ullBytesCount = targetResults.ullReadBytesCount + targetResults.ullWriteBytesCount;
|
||||
targetResults.ullIOCount = targetResults.ullReadIOCount + targetResults.ullWriteIOCount;
|
||||
|
||||
// TODO: Histogram<float> readLatencyHistogram;
|
||||
// TODO: Histogram<float> writeLatencyHistogram;
|
||||
|
||||
// TODO: IoBucketizer writeBucketizer;
|
||||
|
||||
timeSpan.SetCalculateIopsStdDev(true);
|
||||
targetResults.readBucketizer.Initialize(1000, timeSpan.GetDuration());
|
||||
for (size_t i = 0; i < timeSpan.GetDuration(); i++)
|
||||
{
|
||||
// add an io halfway through the bucket's time interval
|
||||
targetResults.readBucketizer.Add(i * 1000 + 500, 100);
|
||||
}
|
||||
|
||||
ThreadResults threadResults;
|
||||
threadResults.vTargetResults.push_back(targetResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
|
||||
vector<Results> vResults;
|
||||
vResults.push_back(results);
|
||||
|
||||
// just throw away the computername - for the ut, it's as useful (and simpler)
|
||||
// to verify a static null as anything else.
|
||||
SystemInformation system;
|
||||
system.sComputerName.clear();
|
||||
system.ResetTime();
|
||||
|
||||
// and power plan
|
||||
system.sActivePolicyName.clear();
|
||||
system.sActivePolicyGuid.clear();
|
||||
|
||||
system.processorTopology._ulProcessorCount = 1;
|
||||
system.processorTopology._ubPerformanceEfficiencyClass = 0;
|
||||
system.processorTopology._fSMT = false;
|
||||
|
||||
system.processorTopology._vProcessorGroupInformation.clear();
|
||||
system.processorTopology._vProcessorGroupInformation.emplace_back((WORD)0, (BYTE)1, (BYTE)1, (KAFFINITY)0x1);
|
||||
|
||||
ProcessorNumaInformation node;
|
||||
node._nodeNumber = 0;
|
||||
node._vProcessorMasks.emplace_back((WORD)0, (KAFFINITY)0x1);
|
||||
system.processorTopology._vProcessorNumaInformation.clear();
|
||||
system.processorTopology._vProcessorNumaInformation.push_back(node);
|
||||
|
||||
ProcessorSocketInformation socket;
|
||||
socket._vProcessorMasks.emplace_back((WORD)0, (KAFFINITY)0x1);
|
||||
system.processorTopology._vProcessorSocketInformation.clear();
|
||||
system.processorTopology._vProcessorSocketInformation.push_back(socket);
|
||||
|
||||
system.processorTopology._vProcessorCoreInformation.clear();
|
||||
system.processorTopology._vProcessorCoreInformation.emplace_back((WORD)0, (KAFFINITY)0x1, (BYTE)0);
|
||||
|
||||
// finally, add the timespan to the profile and dump.
|
||||
profile.AddTimeSpan(timeSpan);
|
||||
|
||||
string sResults = parser.ParseResults(profile, system, vResults);
|
||||
|
||||
// stringify random text, quoting "'s and adding newline/preserving tabs
|
||||
// gc some.txt |% { write-host $("`"{0}\n`"" -f $($_ -replace "`"","\`"" -replace "`t","\t")) }
|
||||
|
||||
const char *pcszExpectedOutput = "\n"
|
||||
"Command Line: \n"
|
||||
"\n"
|
||||
"Input parameters:\n"
|
||||
"\n"
|
||||
"\ttimespan: 1\n"
|
||||
"\t-------------\n"
|
||||
"\tduration: 10s\n"
|
||||
"\twarm up time: 5s\n"
|
||||
"\tcool down time: 0s\n"
|
||||
"\tgathering IOPS at intervals of 1000ms\n"
|
||||
"\trandom seed: 0\n"
|
||||
"\n"
|
||||
"System information:\n\n"
|
||||
"\tcomputer name: \n"
|
||||
"\tstart time: \n"
|
||||
"\n"
|
||||
"\tcpu count:\t\t1\n"
|
||||
"\tcore count:\t\t1\n"
|
||||
"\tgroup count:\t\t1\n"
|
||||
"\tnode count:\t\t1\n"
|
||||
"\tsocket count:\t\t1\n"
|
||||
"\theterogeneous cores:\tn\n"
|
||||
"\n"
|
||||
"\tactive power scheme:\t\n"
|
||||
"\n"
|
||||
"Results for timespan 1:\n"
|
||||
"*******************************************************************************\n"
|
||||
"\n"
|
||||
"actual test time:\t120.00s\n"
|
||||
"thread count:\t\t1\n"
|
||||
"\n"
|
||||
"CPU | Usage | User | Kernel | Idle\n"
|
||||
"----------------------------------------\n"
|
||||
" 0| 55.00%| 30.00%| 25.00%| 45.00%\n"
|
||||
"----------------------------------------\n"
|
||||
"avg.| 55.00%| 30.00%| 25.00%| 45.00%\n"
|
||||
"\n"
|
||||
"Total IO\n"
|
||||
"thread | bytes | I/Os | MiB/s | I/O per s | IopsStdDev | file\n"
|
||||
"-------------------------------------------------------------------------------------------\n"
|
||||
" 0 | 6291456 | 16 | 0.05 | 0.13 | 0.00 | testfile1.dat (10MiB)\n"
|
||||
"-------------------------------------------------------------------------------------------\n"
|
||||
"total: 6291456 | 16 | 0.05 | 0.13 | 0.00\n"
|
||||
"\n"
|
||||
"Read IO\n"
|
||||
"thread | bytes | I/Os | MiB/s | I/O per s | IopsStdDev | file\n"
|
||||
"-------------------------------------------------------------------------------------------\n"
|
||||
" 0 | 4194304 | 6 | 0.03 | 0.05 | 0.00 | testfile1.dat (10MiB)\n"
|
||||
"-------------------------------------------------------------------------------------------\n"
|
||||
"total: 4194304 | 6 | 0.03 | 0.05 | 0.00\n"
|
||||
"\n"
|
||||
"Write IO\n"
|
||||
"thread | bytes | I/Os | MiB/s | I/O per s | IopsStdDev | file\n"
|
||||
"-------------------------------------------------------------------------------------------\n"
|
||||
" 0 | 2097152 | 10 | 0.02 | 0.08 | 0.00 | testfile1.dat (10MiB)\n"
|
||||
"-------------------------------------------------------------------------------------------\n"
|
||||
"total: 2097152 | 10 | 0.02 | 0.08 | 0.00\n";
|
||||
VERIFY_ARE_EQUAL(sResults, pcszExpectedOutput);
|
||||
}
|
||||
|
||||
void ResultParserUnitTests::Test_ParseProfile()
|
||||
{
|
||||
Profile profile;
|
||||
ResultParser parser;
|
||||
TimeSpan timeSpan;
|
||||
Target target;
|
||||
|
||||
timeSpan.AddTarget(target);
|
||||
profile.AddTimeSpan(timeSpan);
|
||||
|
||||
string s = parser.ParseProfile(profile);
|
||||
const char *pszExpectedResult = "\nCommand Line: \n"
|
||||
"\n"
|
||||
"Input parameters:\n"
|
||||
"\n"
|
||||
"\ttimespan: 1\n"
|
||||
"\t-------------\n"
|
||||
"\tduration: 10s\n"
|
||||
"\twarm up time: 5s\n"
|
||||
"\tcool down time: 0s\n"
|
||||
"\trandom seed: 0\n"
|
||||
"\tpath: ''\n"
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing sequential I/O (stride: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tthreads per file: 1\n"
|
||||
"\t\tusing I/O Completion Ports\n"
|
||||
"\t\tIO priority: normal\n\n";
|
||||
|
||||
VERIFY_ARE_EQUAL(strlen(pszExpectedResult), s.length());
|
||||
VERIFY_IS_TRUE(!strcmp(pszExpectedResult, s.c_str()));
|
||||
}
|
||||
|
||||
void ResultParserUnitTests::Test_PrintTarget()
|
||||
{
|
||||
ResultParser parser;
|
||||
Target target;
|
||||
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
const char *pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing sequential I/O (stride: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetThreadStrideInBytes(100 * 1024);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing sequential I/O (stride: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tthread stride size: 100KiB\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
target.SetThreadStrideInBytes(0);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetMaxFileSize(2000 * 1024);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing sequential I/O (stride: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tmax file size: 1.95MiB\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
target.SetMaxFileSize(0);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetBaseFileOffsetInBytes(2 * 1024 * 1024);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing sequential I/O (stride: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tbase file offset: 2MiB\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
target.SetBaseFileOffsetInBytes(0);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetThroughput(1000);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing sequential I/O (stride: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tIO priority: normal\n"
|
||||
"\t\tthroughput rate-limited to 1000 B/ms\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
target.SetThroughput(0);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetThroughputIOPS(1000);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing sequential I/O (stride: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tIO priority: normal\n"
|
||||
"\t\tthroughput rate-limited to 1000 IOPS\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
target.SetThroughputIOPS(0);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetWriteRatio(30);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tperforming mix test (read/write ratio: 70/30)\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing sequential I/O (stride: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
target.SetWriteRatio(0);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetRandomDataWriteBufferSize(12341234);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\twrite buffer size: 11.77MiB\n"
|
||||
"\t\twrite buffer source: random fill\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing sequential I/O (stride: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetRandomDataWriteBufferSourcePath("x:\\foo\\bar.dat");
|
||||
target.SetRandomRatio(100);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\twrite buffer size: 11.77MiB\n"
|
||||
"\t\twrite buffer source: 'x:\\foo\\bar.dat'\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing random I/O (alignment: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
target.SetRandomDataWriteBufferSize(0);
|
||||
target.SetRandomDataWriteBufferSourcePath("");
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetCacheMode(TargetCacheMode::DisableOSCache);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tsoftware cache disabled\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing random I/O (alignment: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetCacheMode(TargetCacheMode::DisableOSCache);
|
||||
target.SetWriteThroughMode(WriteThroughMode::On);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tsoftware cache disabled\n"
|
||||
"\t\thardware write cache disabled, writethrough on\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing random I/O (alignment: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetCacheMode(TargetCacheMode::Cached);
|
||||
target.SetWriteThroughMode(WriteThroughMode::On);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\thardware and software write caches disabled, writethrough on\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing random I/O (alignment: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
target.SetWriteThroughMode(WriteThroughMode::Undefined);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetCacheMode(TargetCacheMode::DisableLocalCache);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tlocal software cache disabled, remote cache enabled\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing random I/O (alignment: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetCacheMode(TargetCacheMode::Cached);
|
||||
target.SetMemoryMappedIoMode(MemoryMappedIoMode::On);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tmemory mapped I/O enabled\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing random I/O (alignment: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetMemoryMappedIoFlushMode(MemoryMappedIoFlushMode::ViewOfFile);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tmemory mapped I/O enabled, flush mode: FlushViewOfFile\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing random I/O (alignment: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetMemoryMappedIoFlushMode(MemoryMappedIoFlushMode::NonVolatileMemory);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tmemory mapped I/O enabled, flush mode: FlushNonVolatileMemory\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing random I/O (alignment: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetMemoryMappedIoFlushMode(MemoryMappedIoFlushMode::NonVolatileMemoryNoDrain);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tmemory mapped I/O enabled, flush mode: FlushNonVolatileMemory with no drain\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing random I/O (alignment: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetMemoryMappedIoMode(MemoryMappedIoMode::Off);
|
||||
target.SetMemoryMappedIoFlushMode(MemoryMappedIoFlushMode::Undefined);
|
||||
target.SetCacheMode(TargetCacheMode::DisableLocalCache);
|
||||
target.SetTemporaryFileHint(true);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tlocal software cache disabled, remote cache enabled\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing random I/O (alignment: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tusing FILE_ATTRIBUTE_TEMPORARY hint\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetRandomAccessHint(true);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tlocal software cache disabled, remote cache enabled\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing random I/O (alignment: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tusing FILE_FLAG_RANDOM_ACCESS hint\n"
|
||||
"\t\tusing FILE_ATTRIBUTE_TEMPORARY hint\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
target.SetRandomAccessHint(false);
|
||||
target.SetTemporaryFileHint(false);
|
||||
target.SetSequentialScanHint(true);
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tlocal software cache disabled, remote cache enabled\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing random I/O (alignment: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tusing FILE_FLAG_SEQUENTIAL_SCAN hint\n"
|
||||
"\t\tIO priority: normal\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
}
|
||||
|
||||
void ResultParserUnitTests::Test_PrintTargetDistributionPct()
|
||||
{
|
||||
ResultParser parser;
|
||||
Target target;
|
||||
|
||||
vector<DistributionRange> v;
|
||||
|
||||
// these match the CmdLineParser UTs
|
||||
|
||||
// -rdpct10/10:10/10:0/10, though we need to produce the tail here
|
||||
v.emplace_back(0, 10, make_pair(0, 10));
|
||||
v.emplace_back(10, 10, make_pair(10, 10));
|
||||
v.emplace_back(20, 0, make_pair(20, 10)); // zero IO% length hole
|
||||
v.emplace_back(20, 80, make_pair(30, 70));
|
||||
target.SetDistributionRange(v, DistributionType::Percent);
|
||||
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
const char *pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing sequential I/O (stride: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tIO priority: normal\n"
|
||||
"\t\tIO Distribution:\n"
|
||||
"\t\t 10% of IO => [ 0% - 10%) of target\n"
|
||||
"\t\t 10% of IO => [10% - 20%) of target\n"
|
||||
"\t\t 0% of IO => [20% - 30%) of target\n"
|
||||
"\t\t 80% of IO => [30% - 100%) of target\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
v.clear();
|
||||
parser._sResult.clear();
|
||||
}
|
||||
|
||||
void ResultParserUnitTests::Test_PrintTargetDistributionAbs()
|
||||
{
|
||||
ResultParser parser;
|
||||
Target target;
|
||||
|
||||
vector<DistributionRange> v;
|
||||
|
||||
// these match the CmdLineParser UTs
|
||||
|
||||
// -rdabs10/1G:10/1G:0/100G, again producing tail
|
||||
v.emplace_back(0,10, make_pair(0, 1*GB));
|
||||
v.emplace_back(10,10, make_pair(1*GB, 1*GB));
|
||||
v.emplace_back(20,0, make_pair(2*GB, 100*GB));
|
||||
v.emplace_back(20,80, make_pair(102*GB, 0));
|
||||
target.SetDistributionRange(v, DistributionType::Absolute);
|
||||
|
||||
parser._PrintTarget(target, false, true, false);
|
||||
const char *pszExpectedResult = "\tpath: ''\n" \
|
||||
"\t\tthink time: 0ms\n"
|
||||
"\t\tburst size: 0\n"
|
||||
"\t\tusing software cache\n"
|
||||
"\t\tusing hardware write cache, writethrough off\n"
|
||||
"\t\tperforming read test\n"
|
||||
"\t\tblock size: 64KiB\n"
|
||||
"\t\tusing sequential I/O (stride: 64KiB)\n"
|
||||
"\t\tnumber of outstanding I/O operations per thread: 2\n"
|
||||
"\t\tIO priority: normal\n"
|
||||
"\t\tIO Distribution:\n"
|
||||
"\t\t 10% of IO => [ 0 - 1GiB)\n"
|
||||
"\t\t 10% of IO => [ 1GiB - 2GiB)\n"
|
||||
"\t\t 0% of IO => [ 2GiB - 102GiB)\n"
|
||||
"\t\t 80% of IO => [ 102GiB - end)\n";
|
||||
VERIFY_ARE_EQUAL(parser._sResult, pszExpectedResult);
|
||||
v.clear();
|
||||
parser._sResult.clear();
|
||||
}
|
||||
|
||||
void ResultParserUnitTests::Test_PrintEffectiveDistributionPct()
|
||||
{
|
||||
// the first matches the corresponding IORequestGenerator effdist UT
|
||||
ResultParser parser;
|
||||
|
||||
Target target;
|
||||
target.SetBlockAlignmentInBytes(4*KB);
|
||||
target.SetBlockSizeInBytes(4*KB);
|
||||
|
||||
Random r;
|
||||
ThreadParameters tp;
|
||||
tp.pRand = &r;
|
||||
|
||||
vector<DistributionRange> v;
|
||||
|
||||
// -rdpct10/10:10/10:0/10 + tail
|
||||
// this is the same distribution in the cmdlineparser UT
|
||||
v.emplace_back(0, 10, make_pair(0, 10));
|
||||
v.emplace_back(10, 10, make_pair(10, 10));
|
||||
v.emplace_back(20, 0, make_pair(20, 10)); // zero IO% length hole
|
||||
v.emplace_back(20, 80, make_pair(30, 70));
|
||||
target.SetDistributionRange(v, DistributionType::Percent);
|
||||
tp.vTargets.push_back(target);
|
||||
|
||||
{
|
||||
ThreadTargetState tts(&tp, 0, 100*KB);
|
||||
|
||||
Results results;
|
||||
ThreadResults threadResults;
|
||||
TargetResults targetResults;
|
||||
|
||||
targetResults.sPath = "testfile.dat";
|
||||
targetResults.vDistributionRange = tts._vDistributionRange;
|
||||
|
||||
threadResults.vTargetResults.push_back(targetResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
|
||||
parser._PrintEffectiveDistributions(results);
|
||||
|
||||
const char* pcszResults = "\nEffective IO Distributions\n" \
|
||||
"--------------------------\n"
|
||||
"target: testfile.dat [thread: 0]\n"
|
||||
" 10% of IO => [ 0 - 8KiB)\n"
|
||||
" 10% of IO => [ 8KiB - 20KiB)\n"
|
||||
" 80% of IO => [ 28KiB - 100KiB)\n";
|
||||
VERIFY_ARE_EQUAL(pcszResults, parser._sResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
}
|
||||
|
||||
//
|
||||
// Tests of distribution deduplication.
|
||||
//
|
||||
|
||||
// now repeat, duplicating the thread result for a second thread
|
||||
|
||||
{
|
||||
ThreadTargetState tts(&tp, 0, 100*KB);
|
||||
|
||||
Results results;
|
||||
ThreadResults threadResults;
|
||||
TargetResults targetResults;
|
||||
|
||||
targetResults.sPath = "testfile.dat";
|
||||
targetResults.vDistributionRange = tts._vDistributionRange;
|
||||
|
||||
threadResults.vTargetResults.push_back(targetResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
|
||||
parser._PrintEffectiveDistributions(results);
|
||||
|
||||
const char* pcszResults = "\nEffective IO Distributions\n" \
|
||||
"--------------------------\n"
|
||||
"target: testfile.dat [thread: 0 1]\n"
|
||||
" 10% of IO => [ 0 - 8KiB)\n"
|
||||
" 10% of IO => [ 8KiB - 20KiB)\n"
|
||||
" 80% of IO => [ 28KiB - 100KiB)\n";
|
||||
VERIFY_ARE_EQUAL(pcszResults, parser._sResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
}
|
||||
|
||||
// now repeat, for a third thread - ellision
|
||||
|
||||
{
|
||||
ThreadTargetState tts(&tp, 0, 100*KB);
|
||||
|
||||
Results results;
|
||||
ThreadResults threadResults;
|
||||
TargetResults targetResults;
|
||||
|
||||
targetResults.sPath = "testfile.dat";
|
||||
targetResults.vDistributionRange = tts._vDistributionRange;
|
||||
|
||||
threadResults.vTargetResults.push_back(targetResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
|
||||
parser._PrintEffectiveDistributions(results);
|
||||
|
||||
const char* pcszResults = "\nEffective IO Distributions\n" \
|
||||
"--------------------------\n"
|
||||
"target: testfile.dat [thread: 0 - 2]\n"
|
||||
" 10% of IO => [ 0 - 8KiB)\n"
|
||||
" 10% of IO => [ 8KiB - 20KiB)\n"
|
||||
" 80% of IO => [ 28KiB - 100KiB)\n";
|
||||
VERIFY_ARE_EQUAL(pcszResults, parser._sResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
}
|
||||
|
||||
// now repeat, moving the third thread to a different target
|
||||
|
||||
{
|
||||
ThreadTargetState tts(&tp, 0, 100*KB);
|
||||
|
||||
Results results;
|
||||
ThreadResults threadResults;
|
||||
TargetResults targetResults;
|
||||
|
||||
targetResults.vDistributionRange = tts._vDistributionRange;
|
||||
|
||||
targetResults.sPath = "testfile.dat";
|
||||
threadResults.vTargetResults.push_back(targetResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
|
||||
targetResults.sPath = "testfile2.dat";
|
||||
threadResults.vTargetResults.clear();
|
||||
threadResults.vTargetResults.push_back(targetResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
|
||||
parser._PrintEffectiveDistributions(results);
|
||||
|
||||
const char* pcszResults = "\nEffective IO Distributions\n" \
|
||||
"--------------------------\n"
|
||||
"target: testfile.dat [thread: 0 1]\n"
|
||||
"target: testfile2.dat [thread: 2]\n"
|
||||
" 10% of IO => [ 0 - 8KiB)\n"
|
||||
" 10% of IO => [ 8KiB - 20KiB)\n"
|
||||
" 80% of IO => [ 28KiB - 100KiB)\n";
|
||||
VERIFY_ARE_EQUAL(pcszResults, parser._sResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
}
|
||||
|
||||
// now repeat, four threads on the first target, three contiguous and one not
|
||||
// the thread on the second target is used to create the gap - ellision will occur
|
||||
// and the fourth thread will stand alone
|
||||
|
||||
{
|
||||
ThreadTargetState tts(&tp, 0, 100*KB);
|
||||
|
||||
Results results;
|
||||
ThreadResults threadResults;
|
||||
TargetResults targetResults;
|
||||
|
||||
targetResults.vDistributionRange = tts._vDistributionRange;
|
||||
|
||||
targetResults.sPath = "testfile.dat";
|
||||
threadResults.vTargetResults.push_back(targetResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
|
||||
threadResults.vTargetResults.clear();
|
||||
targetResults.sPath = "testfile2.dat";
|
||||
threadResults.vTargetResults.push_back(targetResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
|
||||
threadResults.vTargetResults.clear();
|
||||
targetResults.sPath = "testfile.dat";
|
||||
threadResults.vTargetResults.push_back(targetResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
|
||||
parser._PrintEffectiveDistributions(results);
|
||||
|
||||
const char* pcszResults = "\nEffective IO Distributions\n" \
|
||||
"--------------------------\n"
|
||||
"target: testfile.dat [thread: 0 - 2 4]\n"
|
||||
"target: testfile2.dat [thread: 3]\n"
|
||||
" 10% of IO => [ 0 - 8KiB)\n"
|
||||
" 10% of IO => [ 8KiB - 20KiB)\n"
|
||||
" 80% of IO => [ 28KiB - 100KiB)\n";
|
||||
VERIFY_ARE_EQUAL(pcszResults, parser._sResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
}
|
||||
|
||||
// two distinct distributions which share the same IO%
|
||||
|
||||
{
|
||||
ThreadTargetState tts1(&tp, 0, 100*KB);
|
||||
ThreadTargetState tts2(&tp, 0, 1*MB);
|
||||
|
||||
Results results;
|
||||
ThreadResults threadResults;
|
||||
TargetResults targetResults;
|
||||
|
||||
targetResults.vDistributionRange = tts1._vDistributionRange;
|
||||
targetResults.sPath = "testfile.dat";
|
||||
threadResults.vTargetResults.push_back(targetResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
|
||||
threadResults.vTargetResults.clear();
|
||||
|
||||
targetResults.vDistributionRange = tts2._vDistributionRange;
|
||||
targetResults.sPath = "testfile2.dat";
|
||||
threadResults.vTargetResults.push_back(targetResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
|
||||
parser._PrintEffectiveDistributions(results);
|
||||
|
||||
const char* pcszResults = "\nEffective IO Distributions\n" \
|
||||
"--------------------------\n"
|
||||
"target: testfile.dat [thread: 0]\n"
|
||||
" 10% of IO => [ 0 - 8KiB)\n"
|
||||
" 10% of IO => [ 8KiB - 20KiB)\n"
|
||||
" 80% of IO => [ 28KiB - 100KiB)\n"
|
||||
"target: testfile2.dat [thread: 1]\n"
|
||||
" 10% of IO => [ 0 - 100KiB)\n"
|
||||
" 10% of IO => [ 100KiB - 204KiB)\n"
|
||||
" 80% of IO => [ 304KiB - 1MiB)\n";
|
||||
VERIFY_ARE_EQUAL(pcszResults, parser._sResult);
|
||||
|
||||
parser._sResult.clear();
|
||||
}
|
||||
|
||||
tp.vTargets.clear();
|
||||
v.clear();
|
||||
}
|
||||
|
||||
void ResultParserUnitTests::Test_PrintEffectiveDistributionAbs()
|
||||
{
|
||||
// the first matches the corresponding IORequestGenerator effdist UT
|
||||
ResultParser parser;
|
||||
|
||||
Target target;
|
||||
target.SetBlockAlignmentInBytes(4*KB);
|
||||
target.SetBlockSizeInBytes(4*KB);
|
||||
|
||||
Random r;
|
||||
ThreadParameters tp;
|
||||
|
||||
vector<DistributionRange> v;
|
||||
|
||||
// -rdabs10/1G:10/1G:0/100G, again producing tail - with autoscale (0)
|
||||
// this is the same distribution in the cmdlineparser UT
|
||||
// aligned tail range
|
||||
v.emplace_back(0,10, make_pair(0, 1*GB));
|
||||
v.emplace_back(10,10, make_pair(1*GB, 1*GB));
|
||||
v.emplace_back(20,0, make_pair(2*GB, 100*GB));
|
||||
v.emplace_back(20,80, make_pair(102*GB, 0));
|
||||
target.SetDistributionRange(v, DistributionType::Absolute);
|
||||
tp.vTargets.push_back(target);
|
||||
|
||||
{
|
||||
ThreadTargetState tts(&tp, 0, 200*GB);
|
||||
|
||||
Results results;
|
||||
ThreadResults threadResults;
|
||||
TargetResults targetResults;
|
||||
|
||||
targetResults.sPath = "testfile.dat";
|
||||
targetResults.vDistributionRange = tts._vDistributionRange;
|
||||
|
||||
threadResults.vTargetResults.push_back(targetResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
|
||||
parser._PrintEffectiveDistributions(results);
|
||||
|
||||
const char* pcszResults = "\nEffective IO Distributions\n" \
|
||||
"--------------------------\n"
|
||||
"target: testfile.dat [thread: 0]\n"
|
||||
" 10% of IO => [ 0 - 1GiB)\n"
|
||||
" 10% of IO => [ 1GiB - 2GiB)\n"
|
||||
" 80% of IO => [ 102GiB - 200GiB)\n";
|
||||
VERIFY_ARE_EQUAL(pcszResults, parser._sResult);
|
||||
|
||||
tp.vTargets.clear();
|
||||
v.clear();
|
||||
parser._sResult.clear();
|
||||
}
|
||||
|
||||
// -rdabs10/50k:20/10k:30/1G on 100KiB target - autoscale tail, but trimmed on last spec'd range
|
||||
// this results in logical truncation since the covered ranges are only 60% of IO%, a case which
|
||||
// is specific to absolute distributions.
|
||||
v.emplace_back(0, 10, make_pair(0, 50*KB));
|
||||
v.emplace_back(10, 20, make_pair(50*KB, 10*KB));
|
||||
v.emplace_back(30, 30, make_pair(60*KB, 1*GB));
|
||||
v.emplace_back(60, 40, make_pair(1*GB + 60*KB, 0));
|
||||
target.SetDistributionRange(v, DistributionType::Absolute);
|
||||
tp.vTargets.push_back(target);
|
||||
|
||||
{
|
||||
ThreadTargetState tts(&tp, 0, 100*KB);
|
||||
|
||||
Results results;
|
||||
ThreadResults threadResults;
|
||||
TargetResults targetResults;
|
||||
|
||||
targetResults.sPath = "testfile.dat";
|
||||
targetResults.vDistributionRange = tts._vDistributionRange;
|
||||
|
||||
threadResults.vTargetResults.push_back(targetResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
|
||||
parser._PrintEffectiveDistributions(results);
|
||||
|
||||
const char* pcszResults = "\nEffective IO Distributions\n" \
|
||||
"--------------------------\n"
|
||||
"target: testfile.dat [thread: 0]\n"
|
||||
" 16.7% of IO => [ 0 - 50KiB)\n"
|
||||
" 33.3% of IO => [ 50KiB - 60KiB)\n"
|
||||
" 50.0% of IO => [ 60KiB - 100KiB)\n";
|
||||
VERIFY_ARE_EQUAL(pcszResults, parser._sResult);
|
||||
|
||||
tp.vTargets.clear();
|
||||
v.clear();
|
||||
parser._sResult.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "WexTestClass.h"
|
||||
|
||||
namespace UnitTests
|
||||
{
|
||||
BEGIN_MODULE()
|
||||
MODULE_PROPERTY(L"Feature", L"ResultParser")
|
||||
END_MODULE()
|
||||
|
||||
class ResultParserUnitTests : public WEX::TestClass<ResultParserUnitTests>
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(ResultParserUnitTests);
|
||||
TEST_METHOD(Test_ParseResults);
|
||||
TEST_METHOD(Test_ParseProfile);
|
||||
TEST_METHOD(Test_PrintTarget);
|
||||
TEST_METHOD(Test_PrintTargetDistributionPct);
|
||||
TEST_METHOD(Test_PrintTargetDistributionAbs);
|
||||
TEST_METHOD(Test_PrintEffectiveDistributionPct);
|
||||
TEST_METHOD(Test_PrintEffectiveDistributionAbs);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <windows.h>
|
||||
#include "Version.h"
|
||||
|
||||
#include <ntverp.h>
|
||||
|
||||
#define VER_FILETYPE VFT_APP
|
||||
#define VER_FILESUBTYPE VFT2_UNKNOWN
|
||||
#define VER_FILEDESCRIPTION_STR "DiskSpd Storage Performance Tool"
|
||||
#define VER_INTERNALNAME_STR "ResultParser.UnitTests.dll"
|
||||
|
||||
#undef VER_PRODUCTVERSION
|
||||
#define VER_PRODUCTVERSION DISKSPD_MAJOR,DISKSPD_MINOR,DISKSPD_BUILD,DISKSPD_QFE
|
||||
|
||||
#undef VER_PRODUCTVERSION_STR
|
||||
#define VER_PRODUCTVERSION_STR DISKSPD_NUMERIC_VERSION_STRING
|
||||
|
||||
#include "common.ver"
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
+1672
File diff suppressed because it is too large
Load Diff
+116
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "WexTestClass.h"
|
||||
#include "XmlProfileParser.h"
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
namespace UnitTests
|
||||
{
|
||||
BEGIN_MODULE()
|
||||
MODULE_PROPERTY(L"Feature", L"XmlProfileParser")
|
||||
END_MODULE()
|
||||
|
||||
MODULE_SETUP(ModuleSetup);
|
||||
MODULE_CLEANUP(ModuleCleanup);
|
||||
|
||||
class XmlProfileParserUnitTests : public WEX::TestClass<XmlProfileParserUnitTests>
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(XmlProfileParserUnitTests)
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup);
|
||||
TEST_CLASS_CLEANUP(ClassCleanup);
|
||||
|
||||
TEST_METHOD_SETUP(MethodSetup);
|
||||
TEST_METHOD_CLEANUP(MethodCleanup);
|
||||
|
||||
TEST_METHOD(Test_ParseDistributionAbsolute);
|
||||
TEST_METHOD(Test_ParseDistributionPercent);
|
||||
TEST_METHOD(Test_ParseFile);
|
||||
TEST_METHOD(Test_ParseFileGlobalRequestCount);
|
||||
TEST_METHOD(Test_ParseFilePrecreateFilesOnlyFilesWithConstantOrZeroSizes);
|
||||
TEST_METHOD(Test_ParseFilePrecreateFilesOnlyFilesWithConstantSizes);
|
||||
TEST_METHOD(Test_ParseFilePrecreateFilesUseMaxSize);
|
||||
TEST_METHOD(Test_ParseFileWriteBufferContentRandom);
|
||||
TEST_METHOD(Test_ParseFileWriteBufferContentRandomNoFilePath);
|
||||
TEST_METHOD(Test_ParseFileWriteBufferContentRandomWithFilePath);
|
||||
TEST_METHOD(Test_ParseFileWriteBufferContentSequential);
|
||||
TEST_METHOD(Test_ParseFileWriteBufferContentZero);
|
||||
TEST_METHOD(Test_ParseGroupAffinity);
|
||||
TEST_METHOD(Test_ParseNonGroupAffinity);
|
||||
TEST_METHOD(Test_ParseRandomSequentialMixed);
|
||||
TEST_METHOD(Test_ParseTemplateTargets);
|
||||
TEST_METHOD(Test_ParseThroughput);
|
||||
|
||||
//
|
||||
// Utility wrapping the specification and validation of a given distribution.
|
||||
//
|
||||
// Note that % and abs distributions are represented in the same way, only
|
||||
// differing in the relative scale of the target spans.
|
||||
//
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4200) // zero length array
|
||||
|
||||
typedef struct {
|
||||
UINT32 size;
|
||||
struct {
|
||||
UINT32 io;
|
||||
UINT64 target;
|
||||
} range[];
|
||||
} RangePair;
|
||||
|
||||
typedef struct {
|
||||
UINT32 size;
|
||||
struct{
|
||||
UINT32 ioBase, ioSpan;
|
||||
UINT64 targetBase, targetSpan;
|
||||
} range[];
|
||||
} DistQuad;
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
void ValidateDistribution(
|
||||
const PWCHAR desc,
|
||||
boolean expectedParseResult,
|
||||
boolean expectedValidate,
|
||||
DistributionType type,
|
||||
PCHAR xmlDoc,
|
||||
const RangePair *insert,
|
||||
const DistQuad *dist
|
||||
);
|
||||
|
||||
private:
|
||||
string _sTempFilePath;
|
||||
HMODULE _hModule;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <windows.h>
|
||||
#include "Version.h"
|
||||
|
||||
DISKSPD.XSD HTML "..\\XmlProfileParser\\diskspd.xsd"
|
||||
|
||||
#include <ntverp.h>
|
||||
|
||||
#define VER_FILETYPE VFT_APP
|
||||
#define VER_FILESUBTYPE VFT2_UNKNOWN
|
||||
#define VER_FILEDESCRIPTION_STR "DiskSpd Storage Performance Tool"
|
||||
#define VER_INTERNALNAME_STR "XmlProfileParser.UnitTests.dll"
|
||||
|
||||
#undef VER_PRODUCTVERSION
|
||||
#define VER_PRODUCTVERSION DISKSPD_MAJOR,DISKSPD_MINOR,DISKSPD_BUILD,DISKSPD_QFE
|
||||
|
||||
#undef VER_PRODUCTVERSION_STR
|
||||
#define VER_PRODUCTVERSION_STR DISKSPD_NUMERIC_VERSION_STRING
|
||||
|
||||
#include "common.ver"
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
+464
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "XmlResultParser.UnitTests.h"
|
||||
#include "Common.h"
|
||||
#include "xmlresultparser.h"
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
using namespace WEX::TestExecution;
|
||||
using namespace WEX::Logging;
|
||||
using namespace std;
|
||||
|
||||
namespace UnitTests
|
||||
{
|
||||
void XmlResultParserUnitTests::Test_ParseResults()
|
||||
{
|
||||
Profile profile;
|
||||
TimeSpan timeSpan;
|
||||
Target target;
|
||||
XmlResultParser parser;
|
||||
|
||||
Results results;
|
||||
results.fUseETW = false;
|
||||
double fTime = 120.0;
|
||||
results.ullTimeCount = PerfTimer::SecondsToPerfTime(fTime);
|
||||
|
||||
// First group has 1 active cpu
|
||||
// 30% user, 45% idle, 25% non-idle kernel (45% + 25% = 70%)
|
||||
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION systemProcessorInfo = { 0 };
|
||||
systemProcessorInfo.UserTime.QuadPart = static_cast<LONGLONG>(fTime * 30 * 100000);
|
||||
systemProcessorInfo.IdleTime.QuadPart = static_cast<LONGLONG>(fTime * 45 * 100000);
|
||||
systemProcessorInfo.KernelTime.QuadPart = static_cast<LONGLONG>(fTime * 70 * 100000);
|
||||
results.vSystemProcessorPerfInfo.push_back(systemProcessorInfo);
|
||||
|
||||
// Second group has 2 active
|
||||
// 100% idle
|
||||
systemProcessorInfo.UserTime.QuadPart = static_cast<LONGLONG>(fTime * 0 * 100000);
|
||||
systemProcessorInfo.IdleTime.QuadPart = static_cast<LONGLONG>(fTime * 100 * 100000);
|
||||
systemProcessorInfo.KernelTime.QuadPart = static_cast<LONGLONG>(fTime * 100 * 100000);
|
||||
results.vSystemProcessorPerfInfo.push_back(systemProcessorInfo);
|
||||
results.vSystemProcessorPerfInfo.push_back(systemProcessorInfo);
|
||||
|
||||
// TODO: multiple target cases, full profile/result variations
|
||||
target.SetPath("testfile1.dat");
|
||||
target.SetCacheMode(TargetCacheMode::DisableOSCache);
|
||||
target.SetWriteThroughMode(WriteThroughMode::On);
|
||||
target.SetThroughputIOPS(1000);
|
||||
|
||||
timeSpan.AddTarget(target);
|
||||
timeSpan.SetCalculateIopsStdDev(true);
|
||||
|
||||
TargetResults targetResults;
|
||||
targetResults.sPath = "testfile1.dat";
|
||||
targetResults.ullFileSize = 10 * 1024 * 1024;
|
||||
targetResults.ullReadBytesCount = 4 * 1024 * 1024;
|
||||
targetResults.ullReadIOCount = 6;
|
||||
targetResults.ullWriteBytesCount = 2 * 1024 * 1024;
|
||||
targetResults.ullWriteIOCount = 10;
|
||||
targetResults.ullBytesCount = targetResults.ullReadBytesCount + targetResults.ullWriteBytesCount;
|
||||
targetResults.ullIOCount = targetResults.ullReadIOCount + targetResults.ullWriteIOCount;
|
||||
|
||||
// TODO: Histogram<float> readLatencyHistogram;
|
||||
// TODO: Histogram<float> writeLatencyHistogram;
|
||||
// TODO: IoBucketizer writeBucketizer;
|
||||
|
||||
targetResults.readBucketizer.Initialize(1000, timeSpan.GetDuration());
|
||||
for (size_t i = 0; i < timeSpan.GetDuration(); i++)
|
||||
{
|
||||
// add an io halfway through the bucket's time interval
|
||||
targetResults.readBucketizer.Add(i*1000 + 500, 0);
|
||||
}
|
||||
|
||||
ThreadResults threadResults;
|
||||
threadResults.vTargetResults.push_back(targetResults);
|
||||
results.vThreadResults.push_back(threadResults);
|
||||
|
||||
vector<Results> vResults;
|
||||
vResults.push_back(results);
|
||||
|
||||
// Just throw away the computername, pp and reset the timestamp - for the ut, it's
|
||||
// as useful (and simpler) to verify statics as anything else. Reconstruct the
|
||||
// processor topo to a fixed example as well. Note that the performance
|
||||
// efficiency class must be placed since it is calculated on the fly during
|
||||
// the actual GLPIEx enumeration. If we could shim GLPIEx ...
|
||||
SystemInformation system;
|
||||
system.ResetTime();
|
||||
system.sComputerName.clear();
|
||||
system.sActivePolicyName.clear();
|
||||
system.sActivePolicyGuid.clear();
|
||||
|
||||
system.processorTopology._ulProcessorCount = 3;
|
||||
system.processorTopology._ubPerformanceEfficiencyClass = 1;
|
||||
system.processorTopology._fSMT = true;
|
||||
|
||||
system.processorTopology._vProcessorGroupInformation.clear();
|
||||
system.processorTopology._vProcessorGroupInformation.emplace_back((WORD)0, (BYTE)1, (BYTE)1, (KAFFINITY)0x1);
|
||||
system.processorTopology._vProcessorGroupInformation.emplace_back((WORD)1, (BYTE)4, (BYTE)2, (KAFFINITY)0x3);
|
||||
|
||||
ProcessorNumaInformation node;
|
||||
node._nodeNumber = 0;
|
||||
node._vProcessorMasks.emplace_back((WORD)0, (KAFFINITY)0x1);
|
||||
node._vProcessorMasks.emplace_back((WORD)1, (KAFFINITY)0x3);
|
||||
system.processorTopology._vProcessorNumaInformation.clear();
|
||||
system.processorTopology._vProcessorNumaInformation.push_back(node);
|
||||
|
||||
ProcessorSocketInformation socket;
|
||||
socket._vProcessorMasks.emplace_back((WORD)0, (KAFFINITY)0x1);
|
||||
socket._vProcessorMasks.emplace_back((WORD)1, (KAFFINITY)0x3);
|
||||
system.processorTopology._vProcessorSocketInformation.clear();
|
||||
system.processorTopology._vProcessorSocketInformation.push_back(socket);
|
||||
|
||||
system.processorTopology._vProcessorCoreInformation.clear();
|
||||
system.processorTopology._vProcessorCoreInformation.emplace_back((WORD)0, (KAFFINITY)0x1, (BYTE)0);
|
||||
system.processorTopology._vProcessorCoreInformation.emplace_back((WORD)1, (KAFFINITY)0x3, (BYTE)1);
|
||||
|
||||
// finally, add the timespan to the profile and dump.
|
||||
profile.AddTimeSpan(timeSpan);
|
||||
|
||||
string sResults = parser.ParseResults(profile, system, vResults);
|
||||
|
||||
// stringify random text, quoting "'s and adding newline/preserving tabs
|
||||
// gc some.txt |% { write-host $("`"{0}\n`"" -f $($_ -replace "`"","\`"" -replace "`t","\t")) }
|
||||
|
||||
const char *pcszExpectedOutput = \
|
||||
"<Results>\n"
|
||||
" <System>\n"
|
||||
" <ComputerName></ComputerName>\n"
|
||||
" <Tool>\n"
|
||||
" <Version>" DISKSPD_NUMERIC_VERSION_STRING "</Version>\n"
|
||||
" <VersionDate>" DISKSPD_DATE_VERSION_STRING "</VersionDate>\n"
|
||||
" </Tool>\n"
|
||||
" <RunTime></RunTime>\n"
|
||||
" <PowerScheme Name=\"\" Guid=\"\"/>\n"
|
||||
" <ProcessorTopology Heterogeneous=\"true\">\n"
|
||||
" <Group Group=\"0\" MaximumProcessors=\"1\" ActiveProcessors=\"1\" ActiveProcessorMask=\"0x1\"/>\n"
|
||||
" <Group Group=\"1\" MaximumProcessors=\"4\" ActiveProcessors=\"2\" ActiveProcessorMask=\"0x3\"/>\n"
|
||||
" <Node Node=\"0\">\n"
|
||||
" <Group Group=\"0\" Mask=\"0x1\"/>\n"
|
||||
" <Group Group=\"1\" Mask=\"0x3\"/>\n"
|
||||
" </Node>\n"
|
||||
" <Socket Socket=\"0\">\n"
|
||||
" <Group Group=\"0\" Mask=\"0x1\"/>\n"
|
||||
" <Group Group=\"1\" Mask=\"0x3\"/>\n"
|
||||
" </Socket>\n"
|
||||
" <Core Group=\"0\" Core=\"0\" Mask=\"0x1\" EfficiencyClass=\"0\"/>\n"
|
||||
" <Core Group=\"1\" Core=\"0\" Mask=\"0x3\" EfficiencyClass=\"1\"/>\n"
|
||||
" </ProcessorTopology>\n"
|
||||
" </System>\n"
|
||||
" <Profile>\n"
|
||||
" <Progress>0</Progress>\n"
|
||||
" <ResultFormat>text</ResultFormat>\n"
|
||||
" <Verbose>false</Verbose>\n"
|
||||
" <TimeSpans>\n"
|
||||
" <TimeSpan>\n"
|
||||
" <CompletionRoutines>false</CompletionRoutines>\n"
|
||||
" <MeasureLatency>false</MeasureLatency>\n"
|
||||
" <CalculateIopsStdDev>true</CalculateIopsStdDev>\n"
|
||||
" <DisableAffinity>false</DisableAffinity>\n"
|
||||
" <Duration>10</Duration>\n"
|
||||
" <Warmup>5</Warmup>\n"
|
||||
" <Cooldown>0</Cooldown>\n"
|
||||
" <ThreadCount>0</ThreadCount>\n"
|
||||
" <RequestCount>0</RequestCount>\n"
|
||||
" <IoBucketDuration>1000</IoBucketDuration>\n"
|
||||
" <RandSeed>0</RandSeed>\n"
|
||||
" <Targets>\n"
|
||||
" <Target>\n"
|
||||
" <Path>testfile1.dat</Path>\n"
|
||||
" <BlockSize>65536</BlockSize>\n"
|
||||
" <BaseFileOffset>0</BaseFileOffset>\n"
|
||||
" <SequentialScan>false</SequentialScan>\n"
|
||||
" <RandomAccess>false</RandomAccess>\n"
|
||||
" <TemporaryFile>false</TemporaryFile>\n"
|
||||
" <UseLargePages>false</UseLargePages>\n"
|
||||
" <DisableOSCache>true</DisableOSCache>\n"
|
||||
" <WriteThrough>true</WriteThrough>\n"
|
||||
" <WriteBufferContent>\n"
|
||||
" <Pattern>sequential</Pattern>\n"
|
||||
" </WriteBufferContent>\n"
|
||||
" <ParallelAsyncIO>false</ParallelAsyncIO>\n"
|
||||
" <StrideSize>65536</StrideSize>\n"
|
||||
" <InterlockedSequential>false</InterlockedSequential>\n"
|
||||
" <ThreadStride>0</ThreadStride>\n"
|
||||
" <MaxFileSize>0</MaxFileSize>\n"
|
||||
" <RequestCount>2</RequestCount>\n"
|
||||
" <WriteRatio>0</WriteRatio>\n"
|
||||
" <Throughput unit=\"IOPS\">1000</Throughput>\n"
|
||||
" <ThreadsPerFile>1</ThreadsPerFile>\n"
|
||||
" <IOPriority>3</IOPriority>\n"
|
||||
" <Weight>1</Weight>\n"
|
||||
" </Target>\n"
|
||||
" </Targets>\n"
|
||||
" </TimeSpan>\n"
|
||||
" </TimeSpans>\n"
|
||||
" </Profile>\n"
|
||||
" <TimeSpan>\n"
|
||||
" <TestTimeSeconds>120.00</TestTimeSeconds>\n"
|
||||
" <ThreadCount>1</ThreadCount>\n"
|
||||
" <RequestCount>0</RequestCount>\n"
|
||||
" <ProcCount>3</ProcCount>\n"
|
||||
" <CpuUtilization>\n"
|
||||
" <CPU>\n"
|
||||
" <Socket>0</Socket>\n"
|
||||
" <Node>0</Node>\n"
|
||||
" <Group>0</Group>\n"
|
||||
" <Core>0</Core>\n"
|
||||
" <EfficiencyClass>0</EfficiencyClass>\n"
|
||||
" <Id>0</Id>\n"
|
||||
" <UsagePercent>55.00</UsagePercent>\n"
|
||||
" <UserPercent>30.00</UserPercent>\n"
|
||||
" <KernelPercent>25.00</KernelPercent>\n"
|
||||
" <IdlePercent>45.00</IdlePercent>\n"
|
||||
" </CPU>\n"
|
||||
" <CPU>\n"
|
||||
" <Socket>0</Socket>\n"
|
||||
" <Node>0</Node>\n"
|
||||
" <Group>1</Group>\n"
|
||||
" <Core>0</Core>\n"
|
||||
" <EfficiencyClass>1</EfficiencyClass>\n"
|
||||
" <Id>0</Id>\n"
|
||||
" <UsagePercent>0.00</UsagePercent>\n"
|
||||
" <UserPercent>0.00</UserPercent>\n"
|
||||
" <KernelPercent>0.00</KernelPercent>\n"
|
||||
" <IdlePercent>100.00</IdlePercent>\n"
|
||||
" </CPU>\n"
|
||||
" <CPU>\n"
|
||||
" <Socket>0</Socket>\n"
|
||||
" <Node>0</Node>\n"
|
||||
" <Group>1</Group>\n"
|
||||
" <Core>0</Core>\n"
|
||||
" <EfficiencyClass>1</EfficiencyClass>\n"
|
||||
" <Id>1</Id>\n"
|
||||
" <UsagePercent>0.00</UsagePercent>\n"
|
||||
" <UserPercent>0.00</UserPercent>\n"
|
||||
" <KernelPercent>0.00</KernelPercent>\n"
|
||||
" <IdlePercent>100.00</IdlePercent>\n"
|
||||
" </CPU>\n"
|
||||
" <Average>\n"
|
||||
" <UsagePercent>18.33</UsagePercent>\n"
|
||||
" <UserPercent>10.00</UserPercent>\n"
|
||||
" <KernelPercent>8.33</KernelPercent>\n"
|
||||
" <IdlePercent>81.67</IdlePercent>\n"
|
||||
" </Average>\n"
|
||||
" </CpuUtilization>\n"
|
||||
" <Iops>\n"
|
||||
" <ReadIopsStdDev>0.000</ReadIopsStdDev>\n"
|
||||
" <IopsStdDev>0.000</IopsStdDev>\n"
|
||||
" <Bucket SampleMillisecond=\"1000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"2000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"3000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"4000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"5000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"6000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"7000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"8000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"9000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"10000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" </Iops>\n"
|
||||
" <Thread>\n"
|
||||
" <Id>0</Id>\n"
|
||||
" <Target>\n"
|
||||
" <Path>testfile1.dat</Path>\n"
|
||||
" <BytesCount>6291456</BytesCount>\n"
|
||||
" <FileSize>10485760</FileSize>\n"
|
||||
" <IOCount>16</IOCount>\n"
|
||||
" <ReadBytes>4194304</ReadBytes>\n"
|
||||
" <ReadCount>6</ReadCount>\n"
|
||||
" <WriteBytes>2097152</WriteBytes>\n"
|
||||
" <WriteCount>10</WriteCount>\n"
|
||||
" <Iops>\n"
|
||||
" <ReadIopsStdDev>0.000</ReadIopsStdDev>\n"
|
||||
" <IopsStdDev>0.000</IopsStdDev>\n"
|
||||
" <Bucket SampleMillisecond=\"1000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"2000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"3000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"4000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"5000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"6000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"7000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"8000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"9000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" <Bucket SampleMillisecond=\"10000\" Read=\"1\" Write=\"0\" Total=\"1\" ReadMinLatencyMilliseconds=\"0.000\" ReadMaxLatencyMilliseconds=\"0.000\" ReadAvgLatencyMilliseconds=\"0.000\" ReadLatencyStdDev=\"0.000\" WriteMinLatencyMilliseconds=\"0.000\" WriteMaxLatencyMilliseconds=\"0.000\" WriteAvgLatencyMilliseconds=\"0.000\" WriteLatencyStdDev=\"0.000\"/>\n"
|
||||
" </Iops>\n"
|
||||
" </Target>\n"
|
||||
" </Thread>\n"
|
||||
" </TimeSpan>\n"
|
||||
"</Results>";
|
||||
|
||||
#if 0
|
||||
HANDLE h;
|
||||
DWORD written;
|
||||
h = CreateFileW(L"g:\\xmlresult-received.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
WriteFile(h, sResults.c_str(), (DWORD)sResults.length(), &written, NULL);
|
||||
VERIFY_ARE_EQUAL(sResults.length(), written);
|
||||
CloseHandle(h);
|
||||
|
||||
h = CreateFileW(L"g:\\xmlresult-expected.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
WriteFile(h, pcszExpectedOutput, (DWORD)strlen(pcszExpectedOutput), &written, NULL);
|
||||
VERIFY_ARE_EQUAL((DWORD)strlen(pcszExpectedOutput), written);
|
||||
CloseHandle(h);
|
||||
|
||||
printf("--\n%s\n", sResults.c_str());
|
||||
printf("-------------------------------------------------\n");
|
||||
printf("--\n%s\n", pcszExpectedOutput);
|
||||
#endif
|
||||
|
||||
VERIFY_ARE_EQUAL(0, strcmp(sResults.c_str(), pcszExpectedOutput));
|
||||
}
|
||||
|
||||
void XmlResultParserUnitTests::Test_ParseProfile()
|
||||
{
|
||||
Profile profile;
|
||||
XmlResultParser parser;
|
||||
TimeSpan timeSpan;
|
||||
Target target;
|
||||
|
||||
timeSpan.AddTarget(target);
|
||||
profile.AddTimeSpan(timeSpan);
|
||||
|
||||
string s = parser.ParseProfile(profile);
|
||||
const char *pcszExpectedOutput = "<Profile>\n"
|
||||
" <Progress>0</Progress>\n"
|
||||
" <ResultFormat>text</ResultFormat>\n"
|
||||
" <Verbose>false</Verbose>\n"
|
||||
" <TimeSpans>\n"
|
||||
" <TimeSpan>\n"
|
||||
" <CompletionRoutines>false</CompletionRoutines>\n"
|
||||
" <MeasureLatency>false</MeasureLatency>\n"
|
||||
" <CalculateIopsStdDev>false</CalculateIopsStdDev>\n"
|
||||
" <DisableAffinity>false</DisableAffinity>\n"
|
||||
" <Duration>10</Duration>\n"
|
||||
" <Warmup>5</Warmup>\n"
|
||||
" <Cooldown>0</Cooldown>\n"
|
||||
" <ThreadCount>0</ThreadCount>\n"
|
||||
" <RequestCount>0</RequestCount>\n"
|
||||
" <IoBucketDuration>1000</IoBucketDuration>\n"
|
||||
" <RandSeed>0</RandSeed>\n"
|
||||
" <Targets>\n"
|
||||
" <Target>\n"
|
||||
" <Path></Path>\n"
|
||||
" <BlockSize>65536</BlockSize>\n"
|
||||
" <BaseFileOffset>0</BaseFileOffset>\n"
|
||||
" <SequentialScan>false</SequentialScan>\n"
|
||||
" <RandomAccess>false</RandomAccess>\n"
|
||||
" <TemporaryFile>false</TemporaryFile>\n"
|
||||
" <UseLargePages>false</UseLargePages>\n"
|
||||
" <WriteBufferContent>\n"
|
||||
" <Pattern>sequential</Pattern>\n"
|
||||
" </WriteBufferContent>\n"
|
||||
" <ParallelAsyncIO>false</ParallelAsyncIO>\n"
|
||||
" <StrideSize>65536</StrideSize>\n"
|
||||
" <InterlockedSequential>false</InterlockedSequential>\n"
|
||||
" <ThreadStride>0</ThreadStride>\n"
|
||||
" <MaxFileSize>0</MaxFileSize>\n"
|
||||
" <RequestCount>2</RequestCount>\n"
|
||||
" <WriteRatio>0</WriteRatio>\n"
|
||||
" <Throughput>0</Throughput>\n"
|
||||
" <ThreadsPerFile>1</ThreadsPerFile>\n"
|
||||
" <IOPriority>3</IOPriority>\n"
|
||||
" <Weight>1</Weight>\n"
|
||||
" </Target>\n"
|
||||
" </Targets>\n"
|
||||
" </TimeSpan>\n"
|
||||
" </TimeSpans>\n"
|
||||
"</Profile>\n";
|
||||
|
||||
//VERIFY_ARE_EQUAL(pcszExpectedOutput, s.c_str());
|
||||
VERIFY_ARE_EQUAL(strlen(pcszExpectedOutput), s.length());
|
||||
VERIFY_IS_TRUE(!strcmp(pcszExpectedOutput, s.c_str()));
|
||||
}
|
||||
|
||||
void XmlResultParserUnitTests::Test_ParseTargetProfile()
|
||||
{
|
||||
Target target;
|
||||
string sResults;
|
||||
char pszExpectedOutput[4096];
|
||||
int nWritten;
|
||||
|
||||
const char *pcszOutputTemplate = \
|
||||
"<Target>\n"
|
||||
" <Path>testfile1.dat</Path>\n"
|
||||
" <BlockSize>65536</BlockSize>\n"
|
||||
" <BaseFileOffset>0</BaseFileOffset>\n"
|
||||
" <SequentialScan>false</SequentialScan>\n"
|
||||
" <RandomAccess>false</RandomAccess>\n"
|
||||
" <TemporaryFile>false</TemporaryFile>\n"
|
||||
" <UseLargePages>false</UseLargePages>\n"
|
||||
" <DisableOSCache>true</DisableOSCache>\n"
|
||||
" <WriteThrough>true</WriteThrough>\n"
|
||||
" <WriteBufferContent>\n"
|
||||
" <Pattern>sequential</Pattern>\n"
|
||||
" </WriteBufferContent>\n"
|
||||
" <ParallelAsyncIO>false</ParallelAsyncIO>\n"
|
||||
" <StrideSize>65536</StrideSize>\n"
|
||||
" <InterlockedSequential>false</InterlockedSequential>\n"
|
||||
" <ThreadStride>0</ThreadStride>\n"
|
||||
" <MaxFileSize>0</MaxFileSize>\n"
|
||||
" <RequestCount>2</RequestCount>\n"
|
||||
" <WriteRatio>0</WriteRatio>\n"
|
||||
" <Throughput%s>%s</Throughput>\n" // 2 param
|
||||
" <ThreadsPerFile>1</ThreadsPerFile>\n"
|
||||
" <IOPriority>3</IOPriority>\n"
|
||||
" <Weight>1</Weight>\n"
|
||||
"</Target>\n";
|
||||
|
||||
target.SetPath("testfile1.dat");
|
||||
target.SetCacheMode(TargetCacheMode::DisableOSCache);
|
||||
target.SetWriteThroughMode(WriteThroughMode::On);
|
||||
|
||||
// Base case - no limit
|
||||
|
||||
nWritten = sprintf_s(pszExpectedOutput, sizeof(pszExpectedOutput),
|
||||
pcszOutputTemplate, "", "0");
|
||||
VERIFY_IS_GREATER_THAN(nWritten, 0);
|
||||
sResults = target.GetXml(0);
|
||||
VERIFY_ARE_EQUAL(sResults, pszExpectedOutput);
|
||||
|
||||
// IOPS - with units
|
||||
|
||||
target.SetThroughputIOPS(1000);
|
||||
nWritten = sprintf_s(pszExpectedOutput, sizeof(pszExpectedOutput),
|
||||
pcszOutputTemplate, " unit=\"IOPS\"", "1000");
|
||||
VERIFY_IS_GREATER_THAN(nWritten, 0);
|
||||
sResults = target.GetXml(0);
|
||||
VERIFY_ARE_EQUAL(sResults, pszExpectedOutput);
|
||||
|
||||
// BPMS - not specified with units in output
|
||||
|
||||
target.SetThroughput(1000);
|
||||
nWritten = sprintf_s(pszExpectedOutput, sizeof(pszExpectedOutput),
|
||||
pcszOutputTemplate, "", "1000");
|
||||
VERIFY_IS_GREATER_THAN(nWritten, 0);
|
||||
sResults = target.GetXml(0);
|
||||
VERIFY_ARE_EQUAL(sResults, pszExpectedOutput);
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "WexTestClass.h"
|
||||
|
||||
namespace UnitTests
|
||||
{
|
||||
BEGIN_MODULE()
|
||||
MODULE_PROPERTY(L"Feature", L"XmlResultParser")
|
||||
END_MODULE()
|
||||
|
||||
class XmlResultParserUnitTests : public WEX::TestClass<XmlResultParserUnitTests>
|
||||
{
|
||||
public:
|
||||
TEST_CLASS(XmlResultParserUnitTests);
|
||||
TEST_METHOD(Test_ParseResults);
|
||||
TEST_METHOD(Test_ParseProfile);
|
||||
TEST_METHOD(Test_ParseTargetProfile);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <windows.h>
|
||||
#include "Version.h"
|
||||
|
||||
#include <ntverp.h>
|
||||
|
||||
#define VER_FILETYPE VFT_APP
|
||||
#define VER_FILESUBTYPE VFT2_UNKNOWN
|
||||
#define VER_FILEDESCRIPTION_STR "DiskSpd Storage Performance Tool"
|
||||
#define VER_INTERNALNAME_STR "XmlResultParser.UnitTests.dll"
|
||||
|
||||
#undef VER_PRODUCTVERSION
|
||||
#define VER_PRODUCTVERSION DISKSPD_MAJOR,DISKSPD_MINOR,DISKSPD_BUILD,DISKSPD_QFE
|
||||
|
||||
#undef VER_PRODUCTVERSION_STR
|
||||
#define VER_PRODUCTVERSION_STR DISKSPD_NUMERIC_VERSION_STRING
|
||||
|
||||
#include "common.ver"
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
Reference in New Issue
Block a user