diff options
Diffstat (limited to 'ui/build/proc_sync_test.go')
-rw-r--r-- | ui/build/proc_sync_test.go | 241 |
1 files changed, 0 insertions, 241 deletions
diff --git a/ui/build/proc_sync_test.go b/ui/build/proc_sync_test.go deleted file mode 100644 index 857bea38..00000000 --- a/ui/build/proc_sync_test.go +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2017 Google Inc. All rights reserved. -// -// 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 build - -import ( - "fmt" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "syscall" - "testing" - - "android/soong/ui/logger" -) - -// some util methods and data structures that aren't directly part of a test -func makeLockDir() (path string, err error) { - return ioutil.TempDir("", "soong_lock_test") -} -func lockOrFail(t *testing.T) (lock fileLock) { - lockDir, err := makeLockDir() - var lockPointer *fileLock - if err == nil { - lockPointer, err = newLock(lockDir) - } - if err != nil { - os.RemoveAll(lockDir) - t.Fatalf("Failed to create lock: %v", err) - } - - return *lockPointer -} -func removeTestLock(fileLock fileLock) { - lockdir := filepath.Dir(fileLock.File.Name()) - os.RemoveAll(lockdir) -} - -// countWaiter only exists for the purposes of testing lockSynchronous -type countWaiter struct { - numWaitsElapsed int - maxNumWaits int -} - -func newCountWaiter(count int) (waiter *countWaiter) { - return &countWaiter{0, count} -} - -func (c *countWaiter) wait() { - c.numWaitsElapsed++ -} -func (c *countWaiter) checkDeadline() (done bool, remainder string) { - numWaitsRemaining := c.maxNumWaits - c.numWaitsElapsed - if numWaitsRemaining < 1 { - return true, "" - } - return false, fmt.Sprintf("%v waits remain", numWaitsRemaining) -} -func (c countWaiter) summarize() (summary string) { - return fmt.Sprintf("waiting %v times", c.maxNumWaits) -} - -// countLock only exists for the purposes of testing lockSynchronous -type countLock struct { - nextIndex int - successIndex int -} - -var _ lockable = (*countLock)(nil) - -// returns a countLock that succeeds on iteration <index> -func testLockCountingTo(index int) (lock *countLock) { - return &countLock{nextIndex: 0, successIndex: index} -} -func (c *countLock) description() (message string) { - return fmt.Sprintf("counter that counts from %v to %v", c.nextIndex, c.successIndex) -} -func (c *countLock) tryLock() (err error) { - currentIndex := c.nextIndex - c.nextIndex++ - if currentIndex == c.successIndex { - return nil - } - return fmt.Errorf("Lock busy: %s", c.description()) -} -func (c *countLock) Unlock() (err error) { - if c.nextIndex == c.successIndex { - return nil - } - return fmt.Errorf("Not locked: %s", c.description()) -} - -// end of util methods - -// start of tests - -// simple test -func TestGetLock(t *testing.T) { - lockfile := lockOrFail(t) - defer removeTestLock(lockfile) -} - -// a more complicated test that spans multiple processes -var lockPathVariable = "LOCK_PATH" -var successStatus = 0 -var unexpectedError = 1 -var busyStatus = 2 - -func TestTrylock(t *testing.T) { - lockpath := os.Getenv(lockPathVariable) - if len(lockpath) < 1 { - checkTrylockMainProcess(t) - } else { - getLockAndExit(lockpath) - } -} - -// the portion of TestTrylock that runs in the main process -func checkTrylockMainProcess(t *testing.T) { - var err error - lockfile := lockOrFail(t) - defer removeTestLock(lockfile) - lockdir := filepath.Dir(lockfile.File.Name()) - otherAcquired, message, err := forkAndGetLock(lockdir) - if err != nil { - t.Fatalf("Unexpected error in subprocess trying to lock uncontested fileLock: %v. Subprocess output: %q", err, message) - } - if !otherAcquired { - t.Fatalf("Subprocess failed to lock uncontested fileLock. Subprocess output: %q", message) - } - - err = lockfile.tryLock() - if err != nil { - t.Fatalf("Failed to lock fileLock: %v", err) - } - - reacquired, message, err := forkAndGetLock(filepath.Dir(lockfile.File.Name())) - if err != nil { - t.Fatal(err) - } - if reacquired { - t.Fatalf("Permitted locking fileLock twice. Subprocess output: %q", message) - } - - err = lockfile.Unlock() - if err != nil { - t.Fatalf("Error unlocking fileLock: %v", err) - } - - reacquired, message, err = forkAndGetLock(filepath.Dir(lockfile.File.Name())) - if err != nil { - t.Fatal(err) - } - if !reacquired { - t.Fatalf("Subprocess failed to acquire lock after it was released by the main process. Subprocess output: %q", message) - } -} -func forkAndGetLock(lockDir string) (acquired bool, subprocessOutput []byte, err error) { - cmd := exec.Command(os.Args[0], "-test.run=TestTrylock") - cmd.Env = append(os.Environ(), fmt.Sprintf("%s=%s", lockPathVariable, lockDir)) - subprocessOutput, err = cmd.CombinedOutput() - exitStatus := successStatus - if exitError, ok := err.(*exec.ExitError); ok { - if waitStatus, ok := exitError.Sys().(syscall.WaitStatus); ok { - exitStatus = waitStatus.ExitStatus() - } - } - if exitStatus == successStatus { - return true, subprocessOutput, nil - } else if exitStatus == busyStatus { - return false, subprocessOutput, nil - } else { - return false, subprocessOutput, fmt.Errorf("Unexpected status %v", exitStatus) - } -} - -// This function runs in a different process. See TestTrylock -func getLockAndExit(lockpath string) { - fmt.Printf("Will lock path %q\n", lockpath) - lockfile, err := newLock(lockpath) - exitStatus := unexpectedError - if err == nil { - err = lockfile.tryLock() - if err == nil { - exitStatus = successStatus - } else { - exitStatus = busyStatus - } - } - fmt.Printf("Tried to lock path %s. Received error %v. Exiting with status %v\n", lockpath, err, exitStatus) - os.Exit(exitStatus) -} - -func TestLockFirstTrySucceeds(t *testing.T) { - noopLogger := logger.New(ioutil.Discard) - lock := testLockCountingTo(0) - waiter := newCountWaiter(0) - err := lockSynchronous(lock, waiter, noopLogger) - if err != nil { - t.Fatal(err) - } - if waiter.numWaitsElapsed != 0 { - t.Fatalf("Incorrect number of waits elapsed; expected 0, got %v", waiter.numWaitsElapsed) - } -} -func TestLockThirdTrySucceeds(t *testing.T) { - noopLogger := logger.New(ioutil.Discard) - lock := testLockCountingTo(2) - waiter := newCountWaiter(2) - err := lockSynchronous(lock, waiter, noopLogger) - if err != nil { - t.Fatal(err) - } - if waiter.numWaitsElapsed != 2 { - t.Fatalf("Incorrect number of waits elapsed; expected 2, got %v", waiter.numWaitsElapsed) - } -} -func TestLockTimedOut(t *testing.T) { - noopLogger := logger.New(ioutil.Discard) - lock := testLockCountingTo(3) - waiter := newCountWaiter(2) - err := lockSynchronous(lock, waiter, noopLogger) - if err == nil { - t.Fatalf("Appeared to have acquired lock on iteration %v which should not be available until iteration %v", waiter.numWaitsElapsed, lock.successIndex) - } - if waiter.numWaitsElapsed != waiter.maxNumWaits { - t.Fatalf("Waited an incorrect number of times; expected %v, got %v", waiter.maxNumWaits, waiter.numWaitsElapsed) - } -} |