(t *testing.T, workerCount int, conf concurrentConfig, testDuration time.Duration)
| 160 | } |
| 161 | |
| 162 | func concurrentReadAndWrite(t *testing.T, |
| 163 | workerCount int, |
| 164 | conf concurrentConfig, |
| 165 | testDuration time.Duration) { |
| 166 | |
| 167 | t.Log("Preparing db.") |
| 168 | db := mustCreateDB(t, &bolt.Options{ |
| 169 | PageSize: 4096, |
| 170 | }) |
| 171 | defer db.Close() |
| 172 | err := db.Update(func(tx *bolt.Tx) error { |
| 173 | for i := 0; i < conf.bucketCount; i++ { |
| 174 | if _, err := tx.CreateBucketIfNotExists(bucketName(i)); err != nil { |
| 175 | return err |
| 176 | } |
| 177 | } |
| 178 | return nil |
| 179 | }) |
| 180 | require.NoError(t, err) |
| 181 | |
| 182 | var records historyRecords |
| 183 | // t.Failed() returns false during panicking. We need to forcibly |
| 184 | // save data on panicking. |
| 185 | // Refer to: https://github.com/golang/go/issues/49929 |
| 186 | panicked := true |
| 187 | defer func() { |
| 188 | t.Log("Save data if failed.") |
| 189 | saveDataIfFailed(t, db, records, panicked) |
| 190 | }() |
| 191 | |
| 192 | t.Log("Starting workers.") |
| 193 | records = runWorkers(t, |
| 194 | db, |
| 195 | workerCount, |
| 196 | conf, |
| 197 | testDuration) |
| 198 | |
| 199 | t.Log("Analyzing the history records.") |
| 200 | if err := validateSequential(records); err != nil { |
| 201 | t.Errorf("The history records are not sequential:\n %v", err) |
| 202 | } |
| 203 | |
| 204 | t.Log("Checking database consistency.") |
| 205 | if err := checkConsistency(t, db); err != nil { |
| 206 | t.Errorf("The data isn't consistency: %v", err) |
| 207 | } |
| 208 | |
| 209 | panicked = false |
| 210 | // TODO (ahrtr): |
| 211 | // 1. intentionally inject a random failpoint. |
| 212 | } |
| 213 | |
| 214 | // mustCreateDB is created in place of `btesting.MustCreateDB`, and it's |
| 215 | // only supposed to be used by the concurrent test case. The purpose is |
no test coverage detected