/*
 * Copyright 2019 LinkedIn Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package azkaban.user;

import static org.junit.Assert.assertEquals;

import com.google.common.io.Resources;
import com.sun.nio.file.SensitivityWatchEventModifier;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.util.ArrayList;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class FileWatcherTest {

  private final Path PATH = setPath();
  private FileWatcher fileWatcher;

  private Path setPath() {
    final URL configURL = Resources.getResource("test-conf/azkaban-users-test1.xml");
    final String origpath = configURL.getPath();
    // Generate a path for test file.
    final String path = origpath.replace("test1", "file_watcher");
    return Paths.get(path);
  }

  @Before
  public void setUp() throws Exception {
    this.fileWatcher = new FileWatcher(SensitivityWatchEventModifier.HIGH);
  }

  @After
  public void tearDown() throws Exception {
    if (this.fileWatcher != null) {
      this.fileWatcher.close();
    }
  }

  @Test
  public void registerAndTake() throws Exception {
    write();

    // start watching
    final Path dir = Paths.get(PATH.toString()).getParent();
    this.fileWatcher.register(dir);

    // sleep for a second to have different modification time
    Thread.sleep(1000L);
    write();

    final WatchKey key = this.fileWatcher.take();
    final List<WatchEvent<?>> events = this.fileWatcher.pollEvents(key);
    assertEquals(1, events.size());

    final WatchEvent<?> event = events.get(0);
    @SuppressWarnings("unchecked") final Path name = ((WatchEvent<Path>) event).context();
    final String resolvedFileName = dir.resolve(name).toString();
    assertEquals(PATH.toString(), resolvedFileName);
  }

  private void write() throws IOException {
    // Update the file
    Files.write(PATH, new ArrayList<>());
  }

}

@@ -611,16 +611,74 @@
 .user;%0A%0A
+import static org.assertj.core.api.Assertions.assertThat;%0A
 import s
@@ -2225,37 +2225,155 @@
     
-assertEquals(1, events.size()
+// depending on the OS & file system there may be at least 1 or 2 events even with 1 write()%0A    assertThat(events.size()).isGreaterThanOrEqualTo(1
 );%0A%0A
@@ -2373,29 +2373,28 @@
 o(1);%0A%0A    f
-inal 
+or (
 WatchEvent%3C?
@@ -2405,25 +2405,22 @@
 ent 
-=
+:
  events
-.get(0);%0A
+) %7B%0A  
     
@@ -2506,24 +2506,26 @@
 text();%0A    
+  
 final String
@@ -2574,24 +2574,26 @@
 ring();%0A    
+  
 assertEquals
@@ -2629,16 +2629,22 @@
 eName);%0A
+    %7D%0A
   %7D%0A%0A  p

Fix flaky FileWatcherTest (#2259)