/
varset.go
153 lines (131 loc) · 3.53 KB
/
varset.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package types
import "sync"
// VarSet is a dictionary for storing auxiliary state during the execution of the testcase
// VarSet is stored in the context passed to actions and conditions
type VarSet struct {
vars map[string]interface{}
lock *sync.Mutex
}
// NewVarSet instantiates Vars
func NewVarSet() *VarSet {
return &VarSet{
vars: make(map[string]interface{}),
lock: new(sync.Mutex),
}
}
// VarSetGet returns the value with the specified label and typecasts it
func VarSetGet[T any](v *VarSet, label string) (T, bool) {
var result T
valI, ok := v.Get(label)
if !ok {
return result, ok
}
result, ok = valI.(T)
return result, ok
}
// Get returns the value stored of the specified label
// the second return argument is false if the label does not exist
func (v *VarSet) Get(label string) (interface{}, bool) {
v.lock.Lock()
defer v.lock.Unlock()
val, ok := v.vars[label]
return val, ok
}
// GetInt casts the value at label (if it exists) into integer and returns it
func (v *VarSet) GetInt(label string) (int, bool) {
return VarSetGet[int](v, label)
}
// GetString casts the value at label (if it exists) into string and returns it
func (v *VarSet) GetString(label string) (string, bool) {
return VarSetGet[string](v, label)
}
// GetBool casts the value at label (if it exists) into boolean and returns it
func (v *VarSet) GetBool(label string) (bool, bool) {
return VarSetGet[bool](v, label)
}
// Set the value at the specified label
func (v *VarSet) Set(label string, value interface{}) {
v.lock.Lock()
defer v.lock.Unlock()
v.vars[label] = value
}
func (v *VarSet) Keys() []string {
v.lock.Lock()
defer v.lock.Unlock()
keys := make([]string, 0)
for k := range v.vars {
keys = append(keys, k)
}
return keys
}
// Reset removes all vars in the varset
func (v *VarSet) Reset() {
v.lock.Lock()
defer v.lock.Unlock()
v.vars = make(map[string]interface{})
}
// Exists returns true if there is a variable of the specified key
func (v *VarSet) Exists(label string) bool {
v.lock.Lock()
defer v.lock.Unlock()
_, ok := v.vars[label]
return ok
}
// SetCounter sets a counter instance at the specified label with initial value 1
func (v *VarSet) SetCounter(label string) {
v.lock.Lock()
defer v.lock.Unlock()
counter := NewCounter()
v.vars[label] = counter
}
// GetCounter returns the counter at the label if it exists (nil, false) otherwise
func (v *VarSet) GetCounter(label string) (*Counter, bool) {
return VarSetGet[*Counter](v, label)
}
// NewMessageSet creates a message set at the specified label
func (v *VarSet) NewMessageSet(label string) {
v.lock.Lock()
defer v.lock.Unlock()
v.vars[label] = NewMap[MessageID, *Message]()
}
// GetMessageSet returns the message set at label if one exists (nil, false) otherwise
func (v *VarSet) GetMessageSet(label string) (*Map[MessageID, *Message], bool) {
v.lock.Lock()
defer v.lock.Unlock()
sI, exists := v.vars[label]
if !exists {
return nil, false
}
set, ok := sI.(*Map[MessageID, *Message])
return set, ok
}
// Counter threadsafe counter
type Counter struct {
val int
lock *sync.Mutex
}
// NewCounter returns a counter
func NewCounter() *Counter {
return &Counter{
val: 0,
lock: new(sync.Mutex),
}
}
// SetValue sets the counter to the specified value
func (c *Counter) SetValue(v int) {
c.lock.Lock()
defer c.lock.Unlock()
c.val = v
}
// Incr increments the counter
func (c *Counter) Incr() {
c.lock.Lock()
defer c.lock.Unlock()
c.val = c.val + 1
}
// Value returns the counter value
func (c *Counter) Value() int {
c.lock.Lock()
defer c.lock.Unlock()
return c.val
}