github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/test_framework/testcase.go (about) 1 package test_framework 2 3 import ( 4 "fmt" 5 "github.com/balzaczyy/golucene/core/analysis" 6 . "github.com/balzaczyy/golucene/core/codec/spi" 7 docu "github.com/balzaczyy/golucene/core/document" 8 "github.com/balzaczyy/golucene/core/index" 9 "github.com/balzaczyy/golucene/core/search" 10 "github.com/balzaczyy/golucene/core/store" 11 "github.com/balzaczyy/golucene/core/util" 12 ti "github.com/balzaczyy/golucene/test_framework/index" 13 ts "github.com/balzaczyy/golucene/test_framework/search" 14 . "github.com/balzaczyy/golucene/test_framework/util" 15 . "github.com/balzaczyy/gounit" 16 "io" 17 "log" 18 "math" 19 "math/rand" 20 "os" 21 "reflect" 22 ) 23 24 // -------------------------------------------------------------------- 25 // Test groups, system properties and other annotations modifying tests 26 // -------------------------------------------------------------------- 27 28 // ----------------------------------------------------------------- 29 // Truly immutable fields and constants, initialized once and valid 30 // for all suites ever since. 31 // ----------------------------------------------------------------- 32 33 // Use this constant then creating Analyzers and any other version-dependent 34 // stuff. NOTE: Change this when developmenet starts for new Lucene version: 35 var TEST_VERSION_CURRENT = util.VERSION_45 36 37 // Throttling 38 var TEST_THROTTLING = either(TEST_NIGHTLY, THROTTLING_SOMETIMES, THROTTLING_NEVER).(Throttling) 39 40 func either(flag bool, value, orValue interface{}) interface{} { 41 if flag { 42 return value 43 } 44 return orValue 45 } 46 47 // L300 48 49 // ----------------------------------------------------------------- 50 // Class level (suite) rules. 51 // ----------------------------------------------------------------- 52 53 // Class environment setup rule. 54 var ClassEnvRule = &TestRuleSetupAndRestoreClassEnv{} 55 56 // ----------------------------------------------------------------- 57 // Test facilities and facades for subclasses. 58 // ----------------------------------------------------------------- 59 60 // Create a new index writer config with random defaults 61 func NewIndexWriterConfig(v util.Version, a analysis.Analyzer) *index.IndexWriterConfig { 62 return newRandomIndexWriteConfig(Random(), v, a) 63 } 64 65 // Create a new index write config with random defaults using the specified random 66 func newRandomIndexWriteConfig(r *rand.Rand, v util.Version, a analysis.Analyzer) *index.IndexWriterConfig { 67 c := index.NewIndexWriterConfig(v, a) 68 c.SetSimilarity(ClassEnvRule.similarity) 69 if VERBOSE { 70 // Even through TestRuleSetupAndRestoreClassEnv calls 71 // infoStream.SetDefault, we do it again here so that the 72 // PrintStreamInfoStream.messageID increments so that when there 73 // are separate instance of IndexWriter created we see "IW 0", 74 // "IW 1", "IW 2", ... instead of just always "IW 0": 75 c.SetInfoStream(newThreadNameFixingPrintStreamInfoStream(os.Stdout)) 76 } 77 78 if r.Intn(2) == 0 { 79 c.SetMergeScheduler(index.NewSerialMergeScheduler()) 80 } else if Rarely(r) { 81 log.Println("Use ConcurrentMergeScheduler") 82 maxRoutineCount := NextInt(Random(), 1, 4) 83 maxMergeCount := NextInt(Random(), maxRoutineCount, maxRoutineCount+4) 84 cms := index.NewConcurrentMergeScheduler() 85 cms.SetMaxMergesAndRoutines(maxMergeCount, maxRoutineCount) 86 c.SetMergeScheduler(cms) 87 } 88 if r.Intn(2) == 0 { 89 if Rarely(r) { 90 log.Println("Use crazy value for buffered docs") 91 // crazy value 92 c.SetMaxBufferedDocs(NextInt(r, 2, 15)) 93 } else { 94 // reasonable value 95 c.SetMaxBufferedDocs(NextInt(r, 16, 1000)) 96 } 97 } 98 // Go doesn't need thread-affinity state. 99 // if r.Intn(2) == 0 { 100 // maxNumRoutineState := either(Rarely(r), 101 // NextInt(r, 5, 20), // crazy value 102 // NextInt(r, 1, 4)) // reasonable value 103 104 // if Rarely(r) { 105 // // reandom thread pool 106 // c.SetIndexerThreadPool(newRandomDocumentsWriterPerThreadPool(maxNumRoutineState, r)) 107 // } else { 108 // // random thread pool 109 // c.SetMaxThreadStates(maxNumRoutineState) 110 // } 111 // } 112 113 c.SetMergePolicy(newMergePolicy(r)) 114 115 if Rarely(r) { 116 log.Println("Use SimpleMergedSegmentWarmer") 117 c.SetMergedSegmentWarmer(index.NewSimpleMergedSegmentWarmer(c.InfoStream())) 118 } 119 c.SetUseCompoundFile(r.Intn(2) == 0) 120 // c.SetUseCompoundFile(false) 121 c.SetReaderPooling(r.Intn(2) == 0) 122 c.SetReaderTermsIndexDivisor(NextInt(r, 1, 4)) 123 return c 124 } 125 126 func newMergePolicy(r *rand.Rand) index.MergePolicy { 127 if Rarely(r) { 128 log.Println("Use MockRandomMergePolicy") 129 return ti.NewMockRandomMergePolicy(r) 130 } else if r.Intn(2) == 0 { 131 return newTieredMergePolicy(r) 132 } else if r.Intn(5) == 0 { 133 return newAlcoholicMergePolicy(r /*, ClassEnvRule.timeZone*/) 134 } else { 135 return newLogMergePolicy(r) 136 } 137 } 138 139 // L883 140 func newTieredMergePolicy(r *rand.Rand) *index.TieredMergePolicy { 141 tmp := index.NewTieredMergePolicy() 142 if Rarely(r) { 143 log.Println("Use crazy value for max merge at once") 144 tmp.SetMaxMergeAtOnce(NextInt(r, 2, 9)) 145 tmp.SetMaxMergeAtOnceExplicit(NextInt(r, 2, 9)) 146 } else { 147 tmp.SetMaxMergeAtOnce(NextInt(r, 10, 50)) 148 tmp.SetMaxMergeAtOnceExplicit(NextInt(r, 10, 50)) 149 } 150 if Rarely(r) { 151 log.Println("Use crazy value for max merge segment MB") 152 tmp.SetMaxMergedSegmentMB(0.2 + r.Float64()*100) 153 } else { 154 tmp.SetMaxMergedSegmentMB(r.Float64() * 100) 155 } 156 tmp.SetFloorSegmentMB(0.2 + r.Float64()*2) 157 tmp.SetForceMergeDeletesPctAllowed(0 + r.Float64()*30) 158 if Rarely(r) { 159 log.Println("Use crazy value for max merge per tire") 160 tmp.SetSegmentsPerTier(float64(NextInt(r, 2, 20))) 161 } else { 162 tmp.SetSegmentsPerTier(float64(NextInt(r, 10, 50))) 163 } 164 configureRandom(r, tmp) 165 tmp.SetReclaimDeletesWeight(r.Float64() * 4) 166 return tmp 167 } 168 169 func newAlcoholicMergePolicy(r *rand.Rand /*, tz TimeZone*/) *ti.AlcoholicMergePolicy { 170 return ti.NewAlcoholicMergePolicy(rand.New(rand.NewSource(r.Int63()))) 171 } 172 173 func newLogMergePolicy(r *rand.Rand) *index.LogMergePolicy { 174 var logmp *index.LogMergePolicy 175 if r.Intn(2) == 0 { 176 logmp = index.NewLogDocMergePolicy() 177 } else { 178 logmp = index.NewLogByteSizeMergePolicy() 179 } 180 if Rarely(r) { 181 log.Println("Use crazy value for merge factor") 182 logmp.SetMergeFactor(NextInt(r, 2, 9)) 183 } else { 184 logmp.SetMergeFactor(NextInt(r, 10, 50)) 185 } 186 configureRandom(r, logmp) 187 return logmp 188 } 189 190 func configureRandom(r *rand.Rand, mergePolicy index.MergePolicy) { 191 if r.Intn(2) == 0 { 192 mergePolicy.SetNoCFSRatio(0.1 + r.Float64()*0.8) 193 } else if r.Intn(2) == 0 { 194 mergePolicy.SetNoCFSRatio(1.0) 195 } else { 196 mergePolicy.SetNoCFSRatio(0) 197 } 198 199 if Rarely(r) { 200 log.Println("Use crazy value for max CFS segment size MB") 201 mergePolicy.SetMaxCFSSegmentSizeMB(0.2 + r.Float64()*2) 202 } else { 203 mergePolicy.SetMaxCFSSegmentSizeMB(math.Inf(1)) 204 } 205 } 206 207 /* 208 Returns a new Direcotry instance. Use this when the test does not care about 209 the specific Directory implementation (most tests). 210 211 The Directory is wrapped with BaseDirectoryWrapper. This menas usually it 212 will be picky, such as ensuring that you properly close it and all open files 213 in your test. It will emulate some features of Windows, such as not allowing 214 open files ot be overwritten. 215 */ 216 func NewDirectory() BaseDirectoryWrapper { 217 return newDirectoryWithSeed(Random()) 218 } 219 220 // Returns a new Directory instance, using the specified random. 221 // See NewDirecotry() for more information 222 func newDirectoryWithSeed(r *rand.Rand) BaseDirectoryWrapper { 223 return wrapDirectory(r, newDirectoryImpl(r, TEST_DIRECTORY), Rarely(r)) 224 } 225 226 func wrapDirectory(random *rand.Rand, directory store.Directory, bare bool) BaseDirectoryWrapper { 227 if Rarely(random) { 228 log.Println("Use NRTCachingDirectory") 229 directory = store.NewNRTCachingDirectory(directory, random.Float64(), random.Float64()) 230 } 231 232 if Rarely(random) { 233 maxMBPerSec := 10 + 5*(random.Float64()-0.5) 234 if VERBOSE { 235 log.Printf("LuceneTestCase: will rate limit output IndexOutput to %v MB/sec", maxMBPerSec) 236 } 237 rateLimitedDirectoryWrapper := store.NewRateLimitedDirectoryWrapper(directory) 238 switch random.Intn(10) { 239 case 3: // sometimes rate limit on flush 240 rateLimitedDirectoryWrapper.SetMaxWriteMBPerSec(maxMBPerSec, store.IO_CONTEXT_TYPE_FLUSH) 241 case 2: // sometimes rate limit flush & merge 242 rateLimitedDirectoryWrapper.SetMaxWriteMBPerSec(maxMBPerSec, store.IO_CONTEXT_TYPE_FLUSH) 243 rateLimitedDirectoryWrapper.SetMaxWriteMBPerSec(maxMBPerSec, store.IO_CONTEXT_TYPE_MERGE) 244 default: 245 rateLimitedDirectoryWrapper.SetMaxWriteMBPerSec(maxMBPerSec, store.IO_CONTEXT_TYPE_MERGE) 246 } 247 directory = rateLimitedDirectoryWrapper 248 } 249 250 if bare { 251 base := NewBaseDirectoryWrapper(directory) 252 CloseAfterSuite(NewCloseableDirectory(base, SuiteFailureMarker)) 253 return base 254 } else { 255 mock := NewMockDirectoryWrapper(random, directory) 256 257 mock.SetThrottling(TEST_THROTTLING) 258 CloseAfterSuite(NewCloseableDirectory(mock, SuiteFailureMarker)) 259 return mock 260 } 261 } 262 263 // L1064 264 func NewTextField(name, value string, stored bool) *docu.Field { 265 flag := docu.TEXT_FIELD_TYPE_STORED 266 if !stored { 267 flag = docu.TEXT_FIELD_TYPE_NOT_STORED 268 } 269 return NewField(Random(), name, value, flag) 270 } 271 272 func NewField(r *rand.Rand, name, value string, typ *docu.FieldType) *docu.Field { 273 panic("not implemented yet") 274 // if Usually(r) || !typ.Indexed() { 275 // // most of the time, don't modify the params 276 // return docu.NewStringField(name, value, typ) 277 // } 278 279 // newType := docu.NewFieldTypeFrom(typ) 280 // if !newType.Stored() && r.Intn(2) == 0 { 281 // newType.SetStored(true) // randonly store it 282 // } 283 284 // if !newType.StoreTermVectors() && r.Intn(2) == 0 { 285 // newType.SetStoreTermVectors(true) 286 // if !newType.StoreTermVectorOffsets() { 287 // newType.SetStoreTermVectorOffsets(r.Intn(2) == 0) 288 // } 289 // if !newType.StoreTermVectorPositions() { 290 // newType.SetStoreTermVectorPositions(r.Intn(2) == 0) 291 292 // if newType.StoreTermVectorPositions() && !newType.StoreTermVectorPayloads() && !PREFLEX_IMPERSONATION_IS_ACTIVE { 293 // newType.SetStoreTermVectorPayloads(r.Intn(2) == 2) 294 // } 295 // } 296 // } 297 298 // return docu.NewStringField(name, value, newType) 299 } 300 301 // Ian: Different from Lucene's default random class initializer, I have to 302 // explicitly initialize different directory randomly. 303 func newDirectoryImpl(random *rand.Rand, clazzName string) store.Directory { 304 if clazzName == "random" { 305 if Rarely(random) { 306 switch random.Intn(1) { 307 case 0: 308 clazzName = "SimpleFSDirectory" 309 } 310 } else { 311 clazzName = "RAMDirectory" 312 } 313 } 314 if clazzName == "RAMDirectory" { 315 return store.NewRAMDirectory() 316 } else { 317 path := TempDir("index") 318 if err := os.MkdirAll(path, os.ModeTemporary); err != nil { 319 panic(err) 320 } 321 switch clazzName { 322 case "SimpleFSDirectory": 323 d, err := store.NewSimpleFSDirectory(path) 324 if err != nil { 325 panic(err) 326 } 327 return d 328 } 329 panic(fmt.Sprintf("not supported yet: %v", clazzName)) 330 } 331 } 332 333 func NewDefaultIOContext(r *rand.Rand) store.IOContext { 334 return NewIOContext(r, store.IO_CONTEXT_DEFAULT) 335 } 336 337 func NewIOContext(r *rand.Rand, oldContext store.IOContext) store.IOContext { 338 randomNumDocs := r.Intn(4192) 339 size := r.Int63n(512) * int64(randomNumDocs) 340 if oldContext.FlushInfo != nil { 341 // Always return at least the estimatedSegmentSize of the 342 // incoming IOContext: 343 if size < oldContext.FlushInfo.EstimatedSegmentSize { 344 size = oldContext.FlushInfo.EstimatedSegmentSize 345 } 346 return store.NewIOContextForFlush(&store.FlushInfo{randomNumDocs, size}) 347 } else if oldContext.MergeInfo != nil { 348 // Always return at least the estimatedMergeBytes of the 349 // incoming IOContext: 350 if size < oldContext.MergeInfo.EstimatedMergeBytes { 351 size = oldContext.MergeInfo.EstimatedMergeBytes 352 } 353 return store.NewIOContextForMerge( 354 &store.MergeInfo{randomNumDocs, size, r.Intn(2) == 0, NextInt(r, 1, 100)}) 355 } else { 356 // Make a totally random IOContext: 357 switch r.Intn(5) { 358 case 1: 359 return store.IO_CONTEXT_READ 360 case 2: 361 return store.IO_CONTEXT_READONCE 362 case 3: 363 return store.NewIOContextForMerge(&store.MergeInfo{randomNumDocs, size, true, -1}) 364 case 4: 365 return store.NewIOContextForFlush(&store.FlushInfo{randomNumDocs, size}) 366 default: 367 return store.IO_CONTEXT_DEFAULT 368 } 369 } 370 } 371 372 // L1193 373 /* 374 Sometimes wrap the IndexReader as slow, parallel or filter reader (or 375 combinations of that) 376 */ 377 func maybeWrapReader(r index.IndexReader) (index.IndexReader, error) { 378 random := Random() 379 if Rarely(random) { 380 panic("not implemented yet") 381 } 382 return r, nil 383 } 384 385 // L1305 386 // Create a new searcher over the reader. This searcher might randomly use threads 387 func NewSearcher(r index.IndexReader) *ts.AssertingIndexSearcher { 388 return newSearcher(r, true) 389 } 390 391 /* 392 Create a new searcher over the reader. This searcher might randomly 393 use threads. If maybeWrap is true, this searcher migt wrap the reader 394 with one that return nil for sequentialSubReaders. 395 */ 396 func newSearcher(r index.IndexReader, maybeWrap bool) *ts.AssertingIndexSearcher { 397 random := Random() 398 var err error 399 // By default, GoLucene would make use of Goroutines to do 400 // concurrent search and collect 401 // 402 // if util.Usually(random) { 403 if maybeWrap { 404 r, err = maybeWrapReader(r) 405 assert(err == nil) 406 } 407 if random.Intn(2) == 0 { 408 ss := ts.NewAssertingIndexSearcher(random, r) 409 ss.SetSimilarity(ClassEnvRule.similarity) 410 return ss 411 } 412 ss := ts.NewAssertingIndexSearcherFromContext(random, r.Context()) 413 ss.SetSimilarity(ClassEnvRule.similarity) 414 return ss 415 // } 416 } 417 418 // util/TestRuleSetupAndRestoreClassEnv.java 419 420 var suppressedCodecs string 421 422 func SuppressCodecs(name string) { 423 suppressedCodecs = name 424 } 425 426 type ThreadNameFixingPrintStreamInfoStream struct { 427 *util.PrintStreamInfoStream 428 } 429 430 func newThreadNameFixingPrintStreamInfoStream(w io.Writer) *ThreadNameFixingPrintStreamInfoStream { 431 return &ThreadNameFixingPrintStreamInfoStream{util.NewPrintStreamInfoStream(w)} 432 } 433 434 func (is *ThreadNameFixingPrintStreamInfoStream) Message(component, message string, args ...interface{}) { 435 if "TP" == component { 436 return // ignore test points! 437 } 438 is.PrintStreamInfoStream.Message(component, message, args...) 439 } 440 441 /* 442 Setup and restore suite-level environment (fine grained junk that 443 doesn't fit anywhere else) 444 */ 445 type TestRuleSetupAndRestoreClassEnv struct { 446 savedCodec Codec 447 savedInfoStream util.InfoStream 448 449 similarity search.Similarity 450 codec Codec 451 452 avoidCodecs map[string]bool 453 } 454 455 func (rule *TestRuleSetupAndRestoreClassEnv) Before() error { 456 // if verbose: print some debugging stuff about which codecs are loaded. 457 if VERBOSE { 458 for _, codec := range AvailableCodecs() { 459 log.Printf("Loaded codec: '%v': %v", codec, 460 reflect.TypeOf(LoadCodec(codec))) 461 } 462 463 for _, postingFormat := range AvailablePostingsFormats() { 464 log.Printf("Loaded postingsFormat: '%v': %v", postingFormat, 465 reflect.TypeOf(LoadPostingsFormat(postingFormat))) 466 } 467 } 468 469 rule.savedInfoStream = util.DefaultInfoStream() 470 random := Random() 471 if INFOSTREAM { 472 util.SetDefaultInfoStream(newThreadNameFixingPrintStreamInfoStream(os.Stdout)) 473 } else if random.Intn(2) == 0 { 474 util.SetDefaultInfoStream(NewNullInfoStream()) 475 } 476 477 rule.avoidCodecs = make(map[string]bool) 478 if suppressedCodecs != "" { 479 rule.avoidCodecs[suppressedCodecs] = true 480 } 481 482 rule.savedCodec = DefaultCodec() 483 randomVal := random.Intn(10) 484 if "Lucene3x" == TEST_CODEC || 485 "random" == TEST_CODEC && 486 "random" == TEST_POSTINGSFORMAT && 487 "random" == TEST_DOCVALUESFORMAT && 488 randomVal == 3 && 489 !rule.shouldAvoidCodec("Lucene3x") { // preflex-only setup 490 panic("not supported yet") 491 } else if "Lucene40" == TEST_CODEC || 492 "random" == TEST_CODEC && 493 "random" == TEST_POSTINGSFORMAT && 494 randomVal == 0 && 495 !rule.shouldAvoidCodec("Lucene40") { // 4.0 setup 496 panic("not supported yet") 497 } else if "Lucene41" == TEST_CODEC || 498 "random" == TEST_CODEC && 499 "random" == TEST_POSTINGSFORMAT && 500 "random" == TEST_DOCVALUESFORMAT && 501 randomVal == 1 && 502 !rule.shouldAvoidCodec("Lucene41") { 503 panic("not supported yet") 504 } else if "Lucene42" == TEST_CODEC || 505 "random" == TEST_CODEC && 506 "random" == TEST_POSTINGSFORMAT && 507 "random" == TEST_DOCVALUESFORMAT && 508 randomVal == 2 && 509 !rule.shouldAvoidCodec("Lucene42") { 510 panic("not supported yet") 511 } else if "Lucene45" == TEST_CODEC || 512 "random" == TEST_CODEC && 513 "random" == TEST_POSTINGSFORMAT && 514 "random" == TEST_DOCVALUESFORMAT && 515 randomVal == 3 && 516 !rule.shouldAvoidCodec("Lucene45") { 517 panic("not supported yet") 518 } else if "Lucene46" == TEST_CODEC || 519 "random" == TEST_CODEC && 520 "random" == TEST_POSTINGSFORMAT && 521 "random" == TEST_DOCVALUESFORMAT && 522 randomVal == 4 && 523 !rule.shouldAvoidCodec("Lucene46") { 524 panic("not supported yet") 525 } else if "Lucene49" == TEST_CODEC || 526 "random" == TEST_CODEC && 527 "random" == TEST_POSTINGSFORMAT && 528 "random" == TEST_DOCVALUESFORMAT && 529 randomVal == 5 && 530 !rule.shouldAvoidCodec("Lucene49") { 531 532 rule.codec = LoadCodec("Lucene49") 533 OLD_FORMAT_IMPERSONATION_IS_ACTIVE = true 534 535 } else if "random" != TEST_POSTINGSFORMAT || 536 "random" != TEST_DOCVALUESFORMAT { 537 // the user wired postings or DV: this is messy 538 // refactor into RandomCodec... 539 540 panic("not supported yet") 541 } else if "SimpleText" == TEST_CODEC || 542 "random" == TEST_CODEC && 543 randomVal == 9 && 544 Rarely(random) && 545 !rule.shouldAvoidCodec("SimpleText") { 546 panic("not supported yet") 547 } else if "Appending" == TEST_CODEC || 548 "random" == TEST_CODEC && 549 randomVal == 8 && 550 !rule.shouldAvoidCodec("Appending") { 551 panic("not supported yet") 552 } else if "CheapBastard" == TEST_CODEC || 553 "random" == TEST_CODEC && 554 randomVal == 8 && 555 !rule.shouldAvoidCodec("CheapBastard") && 556 !rule.shouldAvoidCodec("Lucene41") { 557 panic("not supported yet") 558 } else if "Asserting" == TEST_CODEC || 559 "random" == TEST_CODEC && 560 randomVal == 6 && 561 !rule.shouldAvoidCodec("Asserting") { 562 panic("not implemented yet") 563 } else if "Compressing" == TEST_CODEC || 564 "random" == TEST_CODEC && 565 randomVal == 5 && 566 !rule.shouldAvoidCodec("Compressing") { 567 panic("not supported yet") 568 } else if "random" != TEST_CODEC { 569 rule.codec = LoadCodec(TEST_CODEC) 570 } else if "random" == TEST_POSTINGSFORMAT { 571 panic("not supported yet") 572 } else { 573 panic("should not be here") 574 } 575 log.Printf("Use codec: %v", rule.codec) 576 DefaultCodec = func() Codec { return rule.codec } 577 578 // Initialize locale/ timezone 579 // testLocale := or(os.Getenv("tests.locale"), "random") 580 // testTimeZon := or(os.Getenv("tests.timezone"), "random") 581 582 // Always pick a random one for consistency (whether tests.locale 583 // was specified or not) 584 // Ian: it's not supported yet 585 // rule.savedLocale := DefaultLocale() 586 // if "random" == testLocale { 587 // rule.locale = randomLocale(random) 588 // } else { 589 // rule.locale = localeForName(testLocale) 590 // } 591 // SetDefaultLocale(rule.locale) 592 593 // SetDefaultTimeZone() will set user.timezone to the default 594 // timezone of the user's locale. So store the original property 595 // value and restore it at end. 596 // rule.restoreProperties["user.timezone"] = os.Getenv("user.timezone") 597 // rule.savedTimeZone = DefaultTimeZone() 598 // if "random" == testTimeZone { 599 // rule.timeZone = randomTimeZone(random) 600 // } else { 601 // rule.timeZone = TimeZone(testTimeZone) 602 // } 603 // SetDefaultTImeZone(rule.timeZone) 604 605 if random.Intn(2) == 0 { 606 rule.similarity = search.NewDefaultSimilarity() 607 } else { 608 rule.similarity = ts.NewRandomSimilarityProvider(random) 609 } 610 611 // Check codec restrictions once at class level. 612 err := rule.checkCodecRestrictions(rule.codec) 613 if err != nil { 614 log.Printf("NOTE: %v Suppressed codecs: %v", err, rule.avoidCodecs) 615 return err 616 } 617 618 // We have "stickiness" so taht sometimes all we do is vary the RAM 619 // buffer size, other times just the doc count to flush by, else 620 // both. This way the assertMemory in DWFC sometimes runs (when we 621 // always flush by RAM). 622 // setLiveIWCFlushMode(LiveIWCFlushMode(random.Intn(3))) 623 624 return nil 625 } 626 627 func or(a, b string) string { 628 if len(a) > 0 { 629 return a 630 } 631 return b 632 } 633 634 // Check codec restrictions. 635 func (rule *TestRuleSetupAndRestoreClassEnv) checkCodecRestrictions(codec Codec) error { 636 assert(codec != nil) 637 AssumeTrue(fmt.Sprintf("Class not allowed to use codec: %v.", codec.Name), 638 rule.shouldAvoidCodec(codec.Name())) 639 640 if _, ok := codec.(*index.RandomCodec); ok && len(rule.avoidCodecs) > 0 { 641 panic("not implemented yet") 642 } 643 644 pf := codec.PostingsFormat() 645 AssumeFalse(fmt.Sprintf("Class not allowed to use postings format: %v.", pf.Name()), 646 rule.shouldAvoidCodec(pf.Name())) 647 648 AssumeFalse(fmt.Sprintf("Class not allowed to use postings format: %v.", TEST_POSTINGSFORMAT), 649 rule.shouldAvoidCodec(TEST_POSTINGSFORMAT)) 650 651 return nil 652 } 653 654 func (rule *TestRuleSetupAndRestoreClassEnv) After() error { 655 panic("not implemented yet") 656 // savedCodec := rule.savedCodec 657 // index.DefaultCodec = func() Codec { return savedCodec } 658 // util.SetDefaultInfoStream(rule.savedInfoStream) 659 // // if rule.savedLocale != nil { 660 // // SetDefaultLocale(rule.savedLocale) 661 // // } 662 // // if rule.savedTimeZone != nil { 663 // // SetDefaultTimeZone(rule.savedTimeZone) 664 // // } 665 // return nil 666 } 667 668 // Should a given codec be avoided for the currently executing suite? 669 func (rule *TestRuleSetupAndRestoreClassEnv) shouldAvoidCodec(codec string) bool { 670 if len(rule.avoidCodecs) == 0 { 671 return false 672 } 673 _, ok := rule.avoidCodecs[codec] 674 return ok 675 }