mirror of
https://github.com/facebook/rocksdb.git
synced 2024-11-27 11:43:49 +00:00
c364eb42b5
Summary: This patch addressed several issues. Portability including db_test std::thread -> port::Thread Cc: @ and %z to ROCKSDB portable macro. Cc: maysamyabandeh Implement Env::AreFilesSame Make the implementation of file unique number more robust Get rid of C-runtime and go directly to Windows API when dealing with file primitives. Implement GetSectorSize() and aling unbuffered read on the value if available. Adjust Windows Logger for the new interface, implement CloseImpl() Cc: anand1976 Fix test running script issue where $status var was of incorrect scope so the failures were swallowed and not reported. DestroyDB() creates a logger and opens a LOG file in the directory being cleaned up. This holds a lock on the folder and the cleanup is prevented. This fails one of the checkpoin tests. We observe the same in production. We close the log file in this change. Fix DBTest2.ReadAmpBitmapLiveInCacheAfterDBClose failure where the test attempts to open a directory with NewRandomAccessFile which does not work on Windows. Fix DBTest.SoftLimit as it is dependent on thread timing. CC: yiwu-arbug Closes https://github.com/facebook/rocksdb/pull/3552 Differential Revision: D7156304 Pulled By: siying fbshipit-source-id: 43db0a757f1dfceffeb2b7988043156639173f5b
487 lines
14 KiB
PowerShell
487 lines
14 KiB
PowerShell
# This script enables you running RocksDB tests by running
|
|
# All the tests concurrently and utilizing all the cores
|
|
Param(
|
|
[switch]$EnableJE = $false, # Look for and use test executable, append _je to listed exclusions
|
|
[switch]$RunAll = $false, # Will attempt discover all *_test[_je].exe binaries and run all
|
|
# of them as Google suites. I.e. It will run test cases concurrently
|
|
# except those mentioned as $Run, those will run as individual test cases
|
|
# And any execlued with $ExcludeExes or $ExcludeCases
|
|
# It will also not run any individual test cases
|
|
# excluded but $ExcludeCasese
|
|
[switch]$RunAllExe = $false, # Look for and use test exdcutables, append _je to exclusions automatically
|
|
# It will attempt to run them in parallel w/o breaking them up on individual
|
|
# test cases. Those listed with $ExcludeExes will be excluded
|
|
[string]$SuiteRun = "", # Split test suites in test cases and run in parallel, not compatible with $RunAll
|
|
[string]$Run = "", # Run specified executables in parallel but do not split to test cases
|
|
[string]$ExcludeCases = "", # Exclude test cases, expects a comma separated list, no spaces
|
|
# Takes effect when $RunAll or $SuiteRun is specified. Must have full
|
|
# Test cases name including a group and a parameter if any
|
|
[string]$ExcludeExes = "", # Exclude exes from consideration, expects a comma separated list,
|
|
# no spaces. Takes effect only when $RunAll is specified
|
|
[string]$WorkFolder = "", # Direct tests to use that folder. SSD or Ram drive are better options.
|
|
# Number of async tasks that would run concurrently. Recommend a number below 64.
|
|
# However, CPU utlization really depends on the storage media. Recommend ram based disk.
|
|
# a value of 1 will run everything serially
|
|
[int]$Concurrency = 8,
|
|
[int]$Limit = -1 # -1 means do not limit for test purposes
|
|
)
|
|
|
|
# Folders and commands must be fullpath to run assuming
|
|
# the current folder is at the root of the git enlistment
|
|
$StartDate = (Get-Date)
|
|
$StartDate
|
|
|
|
|
|
$DebugPreference = "Continue"
|
|
|
|
# These tests are not google test suites and we should guard
|
|
# Against running them as suites
|
|
$RunOnly = New-Object System.Collections.Generic.HashSet[string]
|
|
$RunOnly.Add("c_test") | Out-Null
|
|
$RunOnly.Add("compact_on_deletion_collector_test") | Out-Null
|
|
$RunOnly.Add("merge_test") | Out-Null
|
|
$RunOnly.Add("stringappend_test") | Out-Null # Apparently incorrectly written
|
|
$RunOnly.Add("backupable_db_test") | Out-Null # Disabled
|
|
$RunOnly.Add("timer_queue_test") | Out-Null # Not a gtest
|
|
|
|
if($RunAll -and $SuiteRun -ne "") {
|
|
Write-Error "$RunAll and $SuiteRun are not compatible"
|
|
exit 1
|
|
}
|
|
|
|
if($RunAllExe -and $Run -ne "") {
|
|
Write-Error "$RunAllExe and $Run are not compatible"
|
|
exit 1
|
|
}
|
|
|
|
# If running under Appveyor assume that root
|
|
[string]$Appveyor = $Env:APPVEYOR_BUILD_FOLDER
|
|
if($Appveyor -ne "") {
|
|
$RootFolder = $Appveyor
|
|
} else {
|
|
$RootFolder = $PSScriptRoot -replace '\\build_tools', ''
|
|
}
|
|
|
|
$LogFolder = -Join($RootFolder, "\db_logs\")
|
|
$BinariesFolder = -Join($RootFolder, "\build\Debug\")
|
|
|
|
if($WorkFolder -eq "") {
|
|
|
|
# If TEST_TMPDIR is set use it
|
|
[string]$var = $Env:TEST_TMPDIR
|
|
if($var -eq "") {
|
|
$WorkFolder = -Join($RootFolder, "\db_tests\")
|
|
$Env:TEST_TMPDIR = $WorkFolder
|
|
} else {
|
|
$WorkFolder = $var
|
|
}
|
|
} else {
|
|
# Override from a command line
|
|
$Env:TEST_TMPDIR = $WorkFolder
|
|
}
|
|
|
|
Write-Output "Root: $RootFolder, WorkFolder: $WorkFolder"
|
|
Write-Output "BinariesFolder: $BinariesFolder, LogFolder: $LogFolder"
|
|
|
|
# Create test directories in the current folder
|
|
md -Path $WorkFolder -ErrorAction Ignore | Out-Null
|
|
md -Path $LogFolder -ErrorAction Ignore | Out-Null
|
|
|
|
|
|
$ExcludeCasesSet = New-Object System.Collections.Generic.HashSet[string]
|
|
if($ExcludeCases -ne "") {
|
|
Write-Host "ExcludeCases: $ExcludeCases"
|
|
$l = $ExcludeCases -split ' '
|
|
ForEach($t in $l) {
|
|
$ExcludeCasesSet.Add($t) | Out-Null
|
|
}
|
|
}
|
|
|
|
$ExcludeExesSet = New-Object System.Collections.Generic.HashSet[string]
|
|
if($ExcludeExes -ne "") {
|
|
Write-Host "ExcludeExe: $ExcludeExes"
|
|
$l = $ExcludeExes -split ' '
|
|
ForEach($t in $l) {
|
|
$ExcludeExesSet.Add($t) | Out-Null
|
|
}
|
|
}
|
|
|
|
|
|
# Extract the names of its tests by running db_test with --gtest_list_tests.
|
|
# This filter removes the "#"-introduced comments, and expands to
|
|
# fully-qualified names by changing input like this:
|
|
#
|
|
# DBTest.
|
|
# Empty
|
|
# WriteEmptyBatch
|
|
# MultiThreaded/MultiThreadedDBTest.
|
|
# MultiThreaded/0 # GetParam() = 0
|
|
# MultiThreaded/1 # GetParam() = 1
|
|
#
|
|
# into this:
|
|
#
|
|
# DBTest.Empty
|
|
# DBTest.WriteEmptyBatch
|
|
# MultiThreaded/MultiThreadedDBTest.MultiThreaded/0
|
|
# MultiThreaded/MultiThreadedDBTest.MultiThreaded/1
|
|
#
|
|
# Output into the parameter in a form TestName -> Log File Name
|
|
function ExtractTestCases([string]$GTestExe, $HashTable) {
|
|
|
|
$Tests = @()
|
|
# Run db_test to get a list of tests and store it into $a array
|
|
&$GTestExe --gtest_list_tests | tee -Variable Tests | Out-Null
|
|
|
|
# Current group
|
|
$Group=""
|
|
|
|
ForEach( $l in $Tests) {
|
|
|
|
# Leading whitespace is fine
|
|
$l = $l -replace '^\s+',''
|
|
# Trailing dot is a test group but no whitespace
|
|
if ($l -match "\.$" -and $l -notmatch "\s+") {
|
|
$Group = $l
|
|
} else {
|
|
# Otherwise it is a test name, remove leading space
|
|
$test = $l
|
|
# remove trailing comment if any and create a log name
|
|
$test = $test -replace '\s+\#.*',''
|
|
$test = "$Group$test"
|
|
|
|
if($ExcludeCasesSet.Contains($test)) {
|
|
Write-Warning "$test case is excluded"
|
|
continue
|
|
}
|
|
|
|
$test_log = $test -replace '[\./]','_'
|
|
$test_log += ".log"
|
|
$log_path = -join ($LogFolder, $test_log)
|
|
|
|
# Add to a hashtable
|
|
$HashTable.Add($test, $log_path);
|
|
}
|
|
}
|
|
}
|
|
|
|
# The function removes trailing .exe siffix if any,
|
|
# creates a name for the log file
|
|
# Then adds the test name if it was not excluded into
|
|
# a HashTable in a form of test_name -> log_path
|
|
function MakeAndAdd([string]$token, $HashTable) {
|
|
|
|
$test_name = $token -replace '.exe$', ''
|
|
$log_name = -join ($test_name, ".log")
|
|
$log_path = -join ($LogFolder, $log_name)
|
|
$HashTable.Add($test_name, $log_path)
|
|
}
|
|
|
|
# This function takes a list of Suites to run
|
|
# Lists all the test cases in each of the suite
|
|
# and populates HashOfHashes
|
|
# Ordered by suite(exe) @{ Exe = @{ TestCase = LogName }}
|
|
function ProcessSuites($ListOfSuites, $HashOfHashes) {
|
|
|
|
$suite_list = $ListOfSuites
|
|
# Problem: if you run --gtest_list_tests on
|
|
# a non Google Test executable then it will start executing
|
|
# and we will get nowhere
|
|
ForEach($suite in $suite_list) {
|
|
|
|
if($RunOnly.Contains($suite)) {
|
|
Write-Warning "$suite is excluded from running as Google test suite"
|
|
continue
|
|
}
|
|
|
|
if($EnableJE) {
|
|
$suite += "_je"
|
|
}
|
|
|
|
$Cases = [ordered]@{}
|
|
$Cases.Clear()
|
|
$suite_exe = -Join ($BinariesFolder, $suite)
|
|
ExtractTestCases -GTestExe $suite_exe -HashTable $Cases
|
|
if($Cases.Count -gt 0) {
|
|
$HashOfHashes.Add($suite, $Cases);
|
|
}
|
|
}
|
|
|
|
# Make logs and run
|
|
if($CasesToRun.Count -lt 1) {
|
|
Write-Error "Failed to extract tests from $SuiteRun"
|
|
exit 1
|
|
}
|
|
|
|
}
|
|
|
|
# This will contain all test executables to run
|
|
|
|
# Hash table that contains all non suite
|
|
# Test executable to run
|
|
$TestExes = [ordered]@{}
|
|
|
|
# Check for test exe that are not
|
|
# Google Test Suites
|
|
# Since this is explicitely mentioned it is not subject
|
|
# for exclusions
|
|
if($Run -ne "") {
|
|
|
|
$test_list = $Run -split ' '
|
|
ForEach($t in $test_list) {
|
|
|
|
if($EnableJE) {
|
|
$t += "_je"
|
|
}
|
|
MakeAndAdd -token $t -HashTable $TestExes
|
|
}
|
|
|
|
if($TestExes.Count -lt 1) {
|
|
Write-Error "Failed to extract tests from $Run"
|
|
exit 1
|
|
}
|
|
} elseif($RunAllExe) {
|
|
# Discover all the test binaries
|
|
if($EnableJE) {
|
|
$pattern = "*_test_je.exe"
|
|
} else {
|
|
$pattern = "*_test.exe"
|
|
}
|
|
|
|
$search_path = -join ($BinariesFolder, $pattern)
|
|
Write-Host "Binaries Search Path: $search_path"
|
|
|
|
$DiscoveredExe = @()
|
|
dir -Path $search_path | ForEach-Object {
|
|
$DiscoveredExe += ($_.Name)
|
|
}
|
|
|
|
# Remove exclusions
|
|
ForEach($e in $DiscoveredExe) {
|
|
$e = $e -replace '.exe$', ''
|
|
$bare_name = $e -replace '_je$', ''
|
|
|
|
if($ExcludeExesSet.Contains($bare_name)) {
|
|
Write-Warning "Test $e is excluded"
|
|
continue
|
|
}
|
|
MakeAndAdd -token $e -HashTable $TestExes
|
|
}
|
|
|
|
if($TestExes.Count -lt 1) {
|
|
Write-Error "Failed to discover test executables"
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
# Ordered by exe @{ Exe = @{ TestCase = LogName }}
|
|
$CasesToRun = [ordered]@{}
|
|
|
|
if($SuiteRun -ne "") {
|
|
$suite_list = $SuiteRun -split ' '
|
|
ProcessSuites -ListOfSuites $suite_list -HashOfHashes $CasesToRun
|
|
} elseif ($RunAll) {
|
|
# Discover all the test binaries
|
|
if($EnableJE) {
|
|
$pattern = "*_test_je.exe"
|
|
} else {
|
|
$pattern = "*_test.exe"
|
|
}
|
|
|
|
$search_path = -join ($BinariesFolder, $pattern)
|
|
Write-Host "Binaries Search Path: $search_path"
|
|
|
|
$ListOfExe = @()
|
|
dir -Path $search_path | ForEach-Object {
|
|
$ListOfExe += ($_.Name)
|
|
}
|
|
|
|
# Exclude those in RunOnly from running as suites
|
|
$ListOfSuites = @()
|
|
ForEach($e in $ListOfExe) {
|
|
|
|
$e = $e -replace '.exe$', ''
|
|
$bare_name = $e -replace '_je$', ''
|
|
|
|
if($ExcludeExesSet.Contains($bare_name)) {
|
|
Write-Warning "Test $e is excluded"
|
|
continue
|
|
}
|
|
|
|
if($RunOnly.Contains($bare_name)) {
|
|
MakeAndAdd -token $e -HashTable $TestExes
|
|
} else {
|
|
$ListOfSuites += $bare_name
|
|
}
|
|
}
|
|
|
|
ProcessSuites -ListOfSuites $ListOfSuites -HashOfHashes $CasesToRun
|
|
}
|
|
|
|
|
|
# Invoke a test with a filter and redirect all output
|
|
$InvokeTestCase = {
|
|
param($exe, $test, $log);
|
|
&$exe --gtest_filter=$test > $log 2>&1
|
|
}
|
|
|
|
# Invoke all tests and redirect output
|
|
$InvokeTestAsync = {
|
|
param($exe, $log)
|
|
&$exe > $log 2>&1
|
|
}
|
|
|
|
# Hash that contains tests to rerun if any failed
|
|
# Those tests will be rerun sequentially
|
|
# $Rerun = [ordered]@{}
|
|
# Test limiting factor here
|
|
[int]$count = 0
|
|
# Overall status
|
|
[bool]$script:success = $true;
|
|
|
|
function RunJobs($Suites, $TestCmds, [int]$ConcurrencyVal)
|
|
{
|
|
# Array to wait for any of the running jobs
|
|
$jobs = @()
|
|
# Hash JobToLog
|
|
$JobToLog = @{}
|
|
|
|
# Wait for all to finish and get the results
|
|
while(($JobToLog.Count -gt 0) -or
|
|
($TestCmds.Count -gt 0) -or
|
|
($Suites.Count -gt 0)) {
|
|
|
|
# Make sure we have maximum concurrent jobs running if anything
|
|
# and the $Limit either not set or allows to proceed
|
|
while(($JobToLog.Count -lt $ConcurrencyVal) -and
|
|
((($TestCmds.Count -gt 0) -or ($Suites.Count -gt 0)) -and
|
|
(($Limit -lt 0) -or ($count -lt $Limit)))) {
|
|
|
|
# We always favore suites to run if available
|
|
[string]$exe_name = ""
|
|
[string]$log_path = ""
|
|
$Cases = @{}
|
|
|
|
if($Suites.Count -gt 0) {
|
|
# Will the first one
|
|
ForEach($e in $Suites.Keys) {
|
|
$exe_name = $e
|
|
$Cases = $Suites[$e]
|
|
break
|
|
}
|
|
[string]$test_case = ""
|
|
[string]$log_path = ""
|
|
ForEach($c in $Cases.Keys) {
|
|
$test_case = $c
|
|
$log_path = $Cases[$c]
|
|
break
|
|
}
|
|
|
|
Write-Host "Starting $exe_name::$test_case"
|
|
[string]$Exe = -Join ($BinariesFolder, $exe_name)
|
|
$job = Start-Job -Name "$exe_name::$test_case" -ArgumentList @($Exe,$test_case,$log_path) -ScriptBlock $InvokeTestCase
|
|
$JobToLog.Add($job, $log_path)
|
|
|
|
$Cases.Remove($test_case)
|
|
if($Cases.Count -lt 1) {
|
|
$Suites.Remove($exe_name)
|
|
}
|
|
|
|
} elseif ($TestCmds.Count -gt 0) {
|
|
|
|
ForEach($e in $TestCmds.Keys) {
|
|
$exe_name = $e
|
|
$log_path = $TestCmds[$e]
|
|
break
|
|
}
|
|
|
|
Write-Host "Starting $exe_name"
|
|
[string]$Exe = -Join ($BinariesFolder, $exe_name)
|
|
$job = Start-Job -Name $exe_name -ScriptBlock $InvokeTestAsync -ArgumentList @($Exe,$log_path)
|
|
$JobToLog.Add($job, $log_path)
|
|
|
|
$TestCmds.Remove($exe_name)
|
|
|
|
} else {
|
|
Write-Error "In the job loop but nothing to run"
|
|
exit 1
|
|
}
|
|
|
|
++$count
|
|
} # End of Job starting loop
|
|
|
|
if($JobToLog.Count -lt 1) {
|
|
break
|
|
}
|
|
|
|
$jobs = @()
|
|
foreach($k in $JobToLog.Keys) { $jobs += $k }
|
|
|
|
$completed = Wait-Job -Job $jobs -Any
|
|
$log = $JobToLog[$completed]
|
|
$JobToLog.Remove($completed)
|
|
|
|
$message = -join @($completed.Name, " State: ", ($completed.State))
|
|
|
|
$log_content = @(Get-Content $log)
|
|
|
|
if($completed.State -ne "Completed") {
|
|
$script:success = $false
|
|
Write-Warning $message
|
|
$log_content | Write-Warning
|
|
} else {
|
|
# Scan the log. If we find PASSED and no occurrence of FAILED
|
|
# then it is a success
|
|
[bool]$pass_found = $false
|
|
ForEach($l in $log_content) {
|
|
|
|
if(($l -match "^\[\s+FAILED") -or
|
|
($l -match "Assertion failed:")) {
|
|
$pass_found = $false
|
|
break
|
|
}
|
|
|
|
if(($l -match "^\[\s+PASSED") -or
|
|
($l -match " : PASSED$") -or
|
|
($l -match "^PASS$") -or # Special c_test case
|
|
($l -match "Passed all tests!") ) {
|
|
$pass_found = $true
|
|
}
|
|
}
|
|
|
|
if(!$pass_found) {
|
|
$script:success = $false;
|
|
Write-Warning $message
|
|
$log_content | Write-Warning
|
|
} else {
|
|
Write-Host $message
|
|
}
|
|
}
|
|
|
|
# Remove cached job info from the system
|
|
# Should be no output
|
|
Receive-Job -Job $completed | Out-Null
|
|
}
|
|
}
|
|
|
|
RunJobs -Suites $CasesToRun -TestCmds $TestExes -ConcurrencyVal $Concurrency
|
|
|
|
$EndDate = (Get-Date)
|
|
|
|
New-TimeSpan -Start $StartDate -End $EndDate |
|
|
ForEach-Object {
|
|
"Elapsed time: {0:g}" -f $_
|
|
}
|
|
|
|
|
|
if(!$script:success) {
|
|
# This does not succeed killing off jobs quick
|
|
# So we simply exit
|
|
# Remove-Job -Job $jobs -Force
|
|
# indicate failure using this exit code
|
|
exit 1
|
|
}
|
|
|
|
exit 0
|
|
|
|
|