@@ -10,9 +10,11 @@ import (
1010 "context"
1111 "fmt"
1212 "github.com/oracle/coherence-go-client/v2/coherence"
13+ "github.com/oracle/coherence-go-client/v2/coherence/extractors"
1314 "log"
1415 "math/rand"
1516 "os"
17+ "sort"
1618 "testing"
1719 "time"
1820)
@@ -30,11 +32,23 @@ type Config struct {
3032 Students coherence.NamedCache [int , Student ]
3133}
3234
35+ type PerformanceResult struct {
36+ Executions int64
37+ TotalTime int64
38+ MinTime time.Duration
39+ MaxTime time.Duration
40+ }
41+
3342var (
3443 ctx = context .Background ()
35- //nolint:gosec // just a test
36- rnd = rand .New (rand .NewSource (time . Now (). UnixNano () ))
44+ //nolint:gosec // just a test - have something consistent
45+ rnd = rand .New (rand .NewSource (123_456_789 ))
3746 config = Config {}
47+
48+ courseExtractor = extractors.Extract [string ]("course" )
49+ countryExtractor = extractors.Extract [string ]("country" )
50+ idExtractor = extractors.Extract [int ]("id" )
51+ mapResults = make (map [string ]* PerformanceResult )
3852)
3953
4054const (
@@ -59,24 +73,66 @@ func TestMain(m *testing.M) {
5973 errorAndExit ("unable to clear" , err )
6074 }
6175
76+ // Add Indexes
77+ err = coherence .AddIndex [int , Student ](ctx , config .Students , courseExtractor , true )
78+ if err != nil {
79+ errorAndExit ("unable to add index" , err )
80+ }
81+
82+ err = coherence .AddIndex [int , Student ](ctx , config .Students , countryExtractor , true )
83+ if err != nil {
84+ errorAndExit ("unable to add index" , err )
85+ }
86+
87+ err = coherence .AddIndex [int , Student ](ctx , config .Students , idExtractor , true )
88+ if err != nil {
89+ errorAndExit ("unable to add index" , err )
90+ }
91+
6292 log .Println ("Populating cache with" , maxStudents , "students" )
6393 if populateCache (config .Students , maxStudents ) != nil {
6494 errorAndExit ("failed to populate cache" , err )
6595 }
6696
6797 size , err = config .Students .Size (ctx )
68- if err != nil || size != maxStudents {
69- errorAndExit ("size not correct" , err )
98+ if err != nil {
99+ errorAndExit ("error" , err )
100+ }
101+ if size != maxStudents {
102+ errorAndExit ("count" , fmt .Errorf ("invalid number of students: %d" , size ))
70103 }
71104 log .Println ("Cache size is" , size )
72105
73106 exitCode := m .Run ()
74107
75108 fmt .Printf ("Tests completed with return code %d\n " , exitCode )
109+ printResults ()
76110
77111 os .Exit (exitCode )
78112}
79113
114+ func printResults () {
115+ keys := make ([]string , 0 , len (mapResults ))
116+ for k := range mapResults {
117+ keys = append (keys , k )
118+ }
119+ sort .Strings (keys )
120+
121+ // Sort keys
122+ sort .Strings (keys )
123+ fmt .Println ()
124+ fmt .Println ("RESULTS START" )
125+ fmt .Println ()
126+ fmt .Printf ("%-30s %15s %15s %15s %15s %15s\n " , "TEST" , "TOTAL TIME" , "EXECUTIONS" , "MIN" , "MAX" , "AVERAGE" )
127+ for _ , k := range keys {
128+ v := mapResults [k ]
129+ fmt .Printf ("%-30s %15v %15d %15v %15v %15v\n " , k , time .Duration (v .TotalTime ), v .Executions ,
130+ v .MinTime , v .MaxTime , time .Duration (v .TotalTime / v .Executions ))
131+ }
132+ fmt .Println ()
133+ fmt .Println ("RESULTS END" )
134+ }
135+
80136func errorAndExit (message string , err error ) {
81137 fmt .Println (message , err )
82138 os .Exit (1 )
@@ -101,23 +157,20 @@ func InitializeCoherence(ctx context.Context, address string) (Config, error) {
101157 return config , nil
102158}
103159
160+ var (
161+ courses = []string {"C1" , "C2" , "C3" , "C4" }
162+ countries = []string {"Australia" , "USA" , "Canada" , "Mexico" }
163+ )
164+
104165func populateCache (cache coherence.NamedMap [int , Student ], count int ) error {
105166 var (
106167 buffer = make (map [int ]Student )
107168 err error
108- courses = []string {"C1" , "C2" , "C3" , "C4" }
109- countries = []string {"Australia" , "USA" , "Canada" , "Mexico" }
110169 batchSize = 10_000
111170 )
112171
113172 for i := 1 ; i <= count ; i ++ {
114- buffer [i ] = Student {
115- ID : i ,
116- Name : fmt .Sprintf ("student%d" , i ),
117- Address : fmt .Sprintf ("address%d" , i ),
118- Country : randomize (countries ),
119- Course : randomize (courses ),
120- }
173+ buffer [i ] = getRandomStudent (i )
121174 if i % batchSize == 0 {
122175 err = cache .PutAll (ctx , buffer )
123176 if err != nil {
@@ -133,9 +186,61 @@ func populateCache(cache coherence.NamedMap[int, Student], count int) error {
133186 return nil
134187}
135188
189+ func getRandomStudent (i int ) Student {
190+ return Student {
191+ ID : i ,
192+ Name : fmt .Sprintf ("student%d" , i ),
193+ Address : fmt .Sprintf ("address%d" , i ),
194+ Country : randomize (countries ),
195+ Course : randomize (courses ),
196+ }
197+ }
198+
136199func randomize (arr []string ) string {
137200 if len (arr ) == 0 {
138201 return ""
139202 }
140203 return arr [rnd .Intn (len (arr ))]
141204}
205+
206+ type testTimer struct {
207+ startTime time.Time
208+ endTime time.Time
209+ minDuration time.Duration
210+ maxDuration time.Duration
211+ currentStart time.Time
212+ count int64
213+ }
214+
215+ func (t * testTimer ) Start () {
216+ t .currentStart = time .Now ()
217+ }
218+
219+ func (t * testTimer ) End () {
220+ duration := time .Since (t .currentStart )
221+ if duration < t .minDuration {
222+ t .minDuration = duration * time .Nanosecond
223+ }
224+ if duration > t .maxDuration {
225+ t .maxDuration = duration * time .Nanosecond
226+ }
227+ }
228+
229+ func (t * testTimer ) Complete () * PerformanceResult {
230+ t .endTime = time .Now ()
231+ return & PerformanceResult {
232+ Executions : t .count ,
233+ TotalTime : t .endTime .Sub (t .startTime ).Nanoseconds (),
234+ MaxTime : t .maxDuration ,
235+ MinTime : t .minDuration ,
236+ }
237+ }
238+
239+ func newTestTimer (count int64 ) * testTimer {
240+ return & testTimer {
241+ startTime : time .Now (),
242+ count : count ,
243+ minDuration : time .Duration (10000 ) * time .Second ,
244+ maxDuration : 0 ,
245+ }
246+ }
0 commit comments