github.com/opentofu/opentofu@v1.7.1/internal/states/statemgr/statemgr_test.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 package statemgr 7 8 import ( 9 "context" 10 "encoding/json" 11 "flag" 12 "os" 13 "testing" 14 "time" 15 16 _ "github.com/opentofu/opentofu/internal/logging" 17 ) 18 19 func TestNewLockInfo(t *testing.T) { 20 info1 := NewLockInfo() 21 info2 := NewLockInfo() 22 23 if info1.ID == "" { 24 t.Fatal("LockInfo missing ID") 25 } 26 27 if info1.Version == "" { 28 t.Fatal("LockInfo missing version") 29 } 30 31 if info1.Created.IsZero() { 32 t.Fatal("LockInfo missing Created") 33 } 34 35 if info1.ID == info2.ID { 36 t.Fatal("multiple LockInfo with identical IDs") 37 } 38 39 // test the JSON output is valid 40 newInfo := &LockInfo{} 41 err := json.Unmarshal(info1.Marshal(), newInfo) 42 if err != nil { 43 t.Fatal(err) 44 } 45 } 46 47 func TestLockWithContext(t *testing.T) { 48 s := NewFullFake(nil, TestFullInitialState()) 49 50 id, err := s.Lock(NewLockInfo()) 51 if err != nil { 52 t.Fatal(err) 53 } 54 55 // use a cancelled context for an immediate timeout 56 ctx, cancel := context.WithCancel(context.Background()) 57 cancel() 58 59 info := NewLockInfo() 60 info.Info = "lock with context" 61 _, err = LockWithContext(ctx, s, info) 62 if err == nil { 63 t.Fatal("lock should have failed immediately") 64 } 65 66 // block until LockwithContext has made a first attempt 67 attempted := make(chan struct{}) 68 postLockHook = func() { 69 close(attempted) 70 postLockHook = nil 71 } 72 73 // unlock the state during LockWithContext 74 unlocked := make(chan struct{}) 75 var unlockErr error 76 go func() { 77 defer close(unlocked) 78 <-attempted 79 unlockErr = s.Unlock(id) 80 }() 81 82 ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second) 83 defer cancel() 84 85 id, err = LockWithContext(ctx, s, info) 86 if err != nil { 87 t.Fatal("lock should have completed within 2s:", err) 88 } 89 90 // ensure the goruotine completes 91 <-unlocked 92 if unlockErr != nil { 93 t.Fatal(unlockErr) 94 } 95 } 96 97 func TestMain(m *testing.M) { 98 flag.Parse() 99 os.Exit(m.Run()) 100 }