1// Copyright 2013-2020 Aerospike, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package aerospike_test
16
17import (
18	"math/rand"
19	"strings"
20	"time"
21
22	as "github.com/aerospike/aerospike-client-go"
23
24	. "github.com/onsi/ginkgo"
25	. "github.com/onsi/gomega"
26)
27
28const RANDOM_OPS_RUNS = 1000
29
30// ALL tests are isolated by SetName and Key, which are 50 random characters
31var _ = Describe("Aerospike", func() {
32
33	Describe("Random Data Operations", func() {
34		// connection data
35		var err error
36		var ns = *namespace
37		var set = randString(50)
38		var key *as.Key
39		var wpolicy = as.NewWritePolicy(0, 0)
40		var rpolicy = as.NewPolicy()
41		var rec *as.Record
42
43		if *useReplicas {
44			rpolicy.ReplicaPolicy = as.MASTER_PROLES
45		}
46
47		Context("Put/Get operations", func() {
48
49			It("must create, update and read keys consistently", func() {
50				key, err = as.NewKey(ns, set, randString(50))
51				Expect(err).ToNot(HaveOccurred())
52
53				bin1 := as.NewBin("Aerospike1", 0)
54				bin2 := as.NewBin("Aerospike2", "a") // to avoid deletion of key
55
56				i := 0
57				for i < RANDOM_OPS_RUNS {
58					iters := rand.Intn(10) + 1
59					for wr := 0; wr < iters; wr++ {
60						i++
61
62						//reset
63						err = client.PutBins(wpolicy, key, bin1, bin2)
64						Expect(err).ToNot(HaveOccurred())
65
66						// update
67						err = client.PutBins(wpolicy, key, as.NewBin("Aerospike1", i), as.NewBin("Aerospike2", strings.Repeat("a", i)))
68						Expect(err).ToNot(HaveOccurred())
69					}
70
71					rec, err = client.Get(rpolicy, key)
72					Expect(err).ToNot(HaveOccurred())
73					Expect(rec.Bins[bin1.Name]).To(Equal(i))
74					Expect(rec.Bins[bin2.Name]).To(Equal(strings.Repeat("a", i)))
75				}
76			})
77
78		}) // context put/get operations
79
80		Context("Parallel Put/Get/Delete operations", func() {
81
82			It("must save, read, delete keys consistently", func() {
83
84				errChan := make(chan error, 100)
85
86				func_delete := func(keys ...*as.Key) {
87					defer GinkgoRecover()
88					for _, key := range keys {
89						existed, err := client.Delete(wpolicy, key)
90						Expect(existed).To(BeTrue())
91						errChan <- err
92					}
93				}
94
95				i := 0
96				for i < RANDOM_OPS_RUNS {
97					iters := rand.Intn(1000) + 1
98					for wr := 0; wr < iters; wr++ {
99						i++
100
101						key, err = as.NewKey(ns, set, randString(50))
102						Expect(err).ToNot(HaveOccurred())
103
104						err = client.PutBins(wpolicy, key, as.NewBin("Aerospike1", i), as.NewBin("Aerospike2", strings.Repeat("a", i)))
105						Expect(err).ToNot(HaveOccurred())
106
107						go func_delete(key)
108					}
109
110					// Timeout
111					timeout := time.After(time.Second * 3)
112
113					// Gather errors
114					for i := 0; i < iters; i++ {
115						select {
116						case err := <-errChan:
117							Expect(err).ToNot(HaveOccurred())
118
119						case <-timeout:
120							Expect(timeout).To(BeNil())
121						}
122					} // for i < iters
123
124				} // for i < iters
125			})
126
127		}) // context parallel put/get/delete operations
128
129	}) // describe
130
131}) // describe
132