Add unit-tests for formatting disks during initialization (#2635)

* Add unit-tests for formatting disks during initialization

- Fixed corresponding code at places where it was deviating from the
  tabular spec.

* Added more test cases and simplified algo

... based on feedback from ``go test -coverprofile``.
This commit is contained in:
Krishnan Parthasarathi 2016-09-08 09:35:13 -07:00 committed by Harshavardhana
parent 182109f0de
commit 66459a4ce0
2 changed files with 167 additions and 8 deletions

View File

@ -121,22 +121,28 @@ func prepForInit(disks []string, sErrs []error, diskCount int) InitActions {
return FormatDisks return FormatDisks
} }
return WaitForFormatting return WaitForFormatting
} else if (disksUnformatted >= quorum) && (disksUnformatted+disksOffline == diskCount) { } else if disksUnformatted >= quorum {
if disksUnformatted+disksOffline == diskCount {
return WaitForAll return WaitForAll
} }
// Some disks possibly corrupted.
return WaitForHeal
}
// Already formatted, proceed to initialization of object layer. // Already formatted, proceed to initialization of object layer.
if disksFormatted == diskCount { if disksFormatted == diskCount {
return InitObjectLayer return InitObjectLayer
} else if disksFormatted >= quorum && disksFormatted+disksOffline == diskCount {
return InitObjectLayer
} else if disksFormatted >= quorum { } else if disksFormatted >= quorum {
// TODO: Print minioctl heal command if (disksFormatted+disksOffline == diskCount) ||
(disksFormatted+disksUnformatted == diskCount) {
return InitObjectLayer return InitObjectLayer
} }
// Some disks possibly corrupted.
return WaitForHeal
}
// No Quorum. // No Quorum.
if disksOffline > quorum { if disksOffline >= quorum {
return WaitForQuorum return WaitForQuorum
} }

153
cmd/prepare-storage_test.go Normal file
View File

@ -0,0 +1,153 @@
/*
* Minio Cloud Storage, (C) 2016 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cmd
import (
"runtime"
"testing"
)
func (action InitActions) String() string {
switch action {
case InitObjectLayer:
return "InitObjectLayer"
case FormatDisks:
return "FormatDisks"
case WaitForFormatting:
return "WaitForFormatting"
case WaitForHeal:
return "WaitForHeal"
case WaitForAll:
return "WaitForAll"
case WaitForQuorum:
return "WaitForQuorum"
case Abort:
return "Abort"
default:
return "Unknown"
}
}
func TestPrepForInit(t *testing.T) {
var disks []string
if runtime.GOOS == "windows" {
disks = []string{
`c:\mnt\disk1`,
`c:\mnt\disk2`,
`c:\mnt\disk3`,
`c:\mnt\disk4`,
`c:\mnt\disk5`,
`c:\mnt\disk6`,
`c:\mnt\disk7`,
`c:\mnt\disk8`,
}
} else {
disks = []string{
"/mnt/disk1",
"/mnt/disk2",
"/mnt/disk3",
"/mnt/disk4",
"/mnt/disk5",
"/mnt/disk6",
"/mnt/disk7",
"/mnt/disk8",
}
}
// Building up disks that resolve to localhost and remote w.r.t isLocalStorage().
var (
disksLocal []string
disksRemote []string
)
for i := range disks {
disksLocal = append(disksLocal, "localhost:"+disks[i])
}
// Using 4.4.4.4 as a known non-local address.
for i := range disks {
disksRemote = append(disksRemote, "4.4.4.4:"+disks[i])
}
// All disks are unformatted, a fresh setup.
allUnformatted := []error{
errUnformattedDisk, errUnformattedDisk, errUnformattedDisk, errUnformattedDisk,
errUnformattedDisk, errUnformattedDisk, errUnformattedDisk, errUnformattedDisk,
}
// All disks are formatted, possible restart of a node in a formatted setup.
allFormatted := []error{
nil, nil, nil, nil,
nil, nil, nil, nil,
}
// Quorum number of disks are formatted and rest are offline.
quorumFormatted := []error{
nil, nil, nil, nil,
nil, errDiskNotFound, errDiskNotFound, errDiskNotFound,
}
// Minority disks are corrupted, can be healed.
minorityCorrupted := []error{
errCorruptedFormat, errCorruptedFormat, errCorruptedFormat, nil,
nil, nil, nil, nil,
}
// Majority disks are corrupted, pretty bad setup.
majorityCorrupted := []error{
errCorruptedFormat, errCorruptedFormat, errCorruptedFormat, errCorruptedFormat,
errCorruptedFormat, nil, nil, nil,
}
// Quorum disks are unformatted, remaining yet to come online.
quorumUnformatted := []error{
errUnformattedDisk, errUnformattedDisk, errUnformattedDisk, errUnformattedDisk,
errUnformattedDisk, errDiskNotFound, errDiskNotFound, errDiskNotFound,
}
quorumUnformattedSomeCorrupted := []error{
errUnformattedDisk, errUnformattedDisk, errUnformattedDisk, errUnformattedDisk,
errUnformattedDisk, errCorruptedFormat, errCorruptedFormat, errDiskNotFound,
}
// Quorum number of disks not online yet.
noQuourm := []error{
errDiskNotFound, errDiskNotFound, errDiskNotFound, errDiskNotFound,
errDiskNotFound, nil, nil, nil,
}
testCases := []struct {
// Params for prepForInit().
disks []string
errs []error
diskCount int
action InitActions
}{
// Local disks.
{disksLocal, allFormatted, 8, InitObjectLayer},
{disksLocal, quorumFormatted, 8, InitObjectLayer},
{disksLocal, allUnformatted, 8, FormatDisks},
{disksLocal, quorumUnformatted, 8, WaitForAll},
{disksLocal, quorumUnformattedSomeCorrupted, 8, WaitForHeal},
{disksLocal, noQuourm, 8, WaitForQuorum},
{disksLocal, minorityCorrupted, 8, WaitForHeal},
{disksLocal, majorityCorrupted, 8, Abort},
// Remote disks.
{disksRemote, allFormatted, 8, InitObjectLayer},
{disksRemote, quorumFormatted, 8, InitObjectLayer},
{disksRemote, allUnformatted, 8, WaitForFormatting},
{disksRemote, quorumUnformatted, 8, WaitForAll},
{disksRemote, quorumUnformattedSomeCorrupted, 8, WaitForHeal},
{disksRemote, noQuourm, 8, WaitForQuorum},
{disksRemote, minorityCorrupted, 8, WaitForHeal},
{disksRemote, majorityCorrupted, 8, Abort},
}
for i, test := range testCases {
actual := prepForInit(test.disks, test.errs, test.diskCount)
if actual != test.action {
t.Errorf("Test %d expected %s but receieved %s\n", i+1, test.action, actual)
}
}
}