@@ -358,3 +358,94 @@ func TestInotifyInnerMapLength(t *testing.T) {
358
358
t .Fatalf ("Expected paths len is 0, but got: %d, %v" , len (w .paths ), w .paths )
359
359
}
360
360
}
361
+
362
+ func TestInotifyOverflow (t * testing.T ) {
363
+ // We need to generate many more events than the
364
+ // fs.inotify.max_queued_events sysctl setting.
365
+ // We use multiple goroutines (one per directory)
366
+ // to speed up file creation.
367
+ numDirs := 128
368
+ numFiles := 1024
369
+
370
+ testDir := tempMkdir (t )
371
+ defer os .RemoveAll (testDir )
372
+
373
+ w , err := NewWatcher ()
374
+ if err != nil {
375
+ t .Fatalf ("Failed to create watcher: %v" , err )
376
+ }
377
+ defer w .Close ()
378
+
379
+ for dn := 0 ; dn < numDirs ; dn ++ {
380
+ testSubdir := fmt .Sprintf ("%s/%d" , testDir , dn )
381
+
382
+ err := os .Mkdir (testSubdir , 0777 )
383
+ if err != nil {
384
+ t .Fatalf ("Cannot create subdir: %v" , err )
385
+ }
386
+
387
+ err = w .Add (testSubdir )
388
+ if err != nil {
389
+ t .Fatalf ("Failed to add subdir: %v" , err )
390
+ }
391
+ }
392
+
393
+ errChan := make (chan error , numDirs * numFiles )
394
+
395
+ for dn := 0 ; dn < numDirs ; dn ++ {
396
+ testSubdir := fmt .Sprintf ("%s/%d" , testDir , dn )
397
+
398
+ go func () {
399
+ for fn := 0 ; fn < numFiles ; fn ++ {
400
+ testFile := fmt .Sprintf ("%s/%d" , testSubdir , fn )
401
+
402
+ handle , err := os .Create (testFile )
403
+ if err != nil {
404
+ errChan <- fmt .Errorf ("Create failed: %v" , err )
405
+ continue
406
+ }
407
+
408
+ err = handle .Close ()
409
+ if err != nil {
410
+ errChan <- fmt .Errorf ("Close failed: %v" , err )
411
+ continue
412
+ }
413
+ }
414
+ }()
415
+ }
416
+
417
+ creates := 0
418
+ overflows := 0
419
+
420
+ after := time .After (10 * time .Second )
421
+ for overflows == 0 && creates < numDirs * numFiles {
422
+ select {
423
+ case <- after :
424
+ t .Fatalf ("Not done" )
425
+ case err := <- errChan :
426
+ t .Fatalf ("Got an error from file creator goroutine: %v" , err )
427
+ case err := <- w .Errors :
428
+ if err == ErrEventOverflow {
429
+ overflows ++
430
+ } else {
431
+ t .Fatalf ("Got an error from watcher: %v" , err )
432
+ }
433
+ case evt := <- w .Events :
434
+ if ! strings .HasPrefix (evt .Name , testDir ) {
435
+ t .Fatalf ("Got an event for an unknown file: %s" , evt .Name )
436
+ }
437
+ if evt .Op == Create {
438
+ creates ++
439
+ }
440
+ }
441
+ }
442
+
443
+ if creates == numDirs * numFiles {
444
+ t .Fatalf ("Could not trigger overflow" )
445
+ }
446
+
447
+ if overflows == 0 {
448
+ t .Fatalf ("No overflow and not enough creates (expected %d, got %d)" ,
449
+ numDirs * numFiles , creates )
450
+ }
451
+ }
0 commit comments