private static boolean sleepIfNeeded() {
   if (HeavyProcessLatch.INSTANCE.isInsideLowPriorityThread()) {
     TimeoutUtil.sleep(1);
     return true;
   }
   return false;
 }
  public void testDelayedTasksThatFiredAtTheSameTimeAreExecutedConcurrently()
      throws InterruptedException, ExecutionException {
    final AppScheduledExecutorService service = new AppScheduledExecutorService(getName());
    final List<LogInfo> log = Collections.synchronizedList(new ArrayList<>());
    int delay = 500;

    int N = 20;
    List<? extends Future<?>> futures =
        ContainerUtil.map(
            Collections.nCopies(N, ""),
            __ ->
                service.schedule(
                    () -> {
                      log.add(new LogInfo(0));
                      TimeoutUtil.sleep(10 * 1000);
                    },
                    delay,
                    TimeUnit.MILLISECONDS));

    for (Future<?> future : futures) {
      future.get();
    }

    assertEquals(N, log.size());
    Set<Thread> usedThreads = ContainerUtil.map2Set(log, logInfo -> logInfo.currentThread);

    assertEquals(N, usedThreads.size());
    service.shutdownAppScheduledExecutorService();
    assertTrue(service.awaitTermination(10, TimeUnit.SECONDS));
  }
 private static void runIndeterminateProgress(ProgressIndicator indicator) {
   indicator.setIndeterminate(true);
   indicator.setText("Indeterminate");
   for (int i = 0; i < 200; i++) {
     TimeoutUtil.sleep(10);
     indicator.checkCanceled();
   }
 }
 private static void runDeterminateProgress(ProgressIndicator indicator) {
   int iterations = 3000;
   for (int i = 0; i < iterations; i++) {
     TimeoutUtil.sleep(1);
     indicator.setFraction(((double) i + 1) / ((double) iterations));
     indicator.setText(String.valueOf(i));
     ProgressManager.checkCanceled();
   }
 }
  public void testStatusDoesNotLockForWrite() throws Exception {
    final File ioFile = new File(myWorkingCopyRoot, filename);
    ioFile.getParentFile().mkdirs();

    /*SVNWCClient client11 = new SVNWCClient((ISVNRepositoryPool)null, new DefaultSVNOptions());
    client11.doAdd(ioFile.getParentFile(), true, false, true, true);*/

    ioFile.createNewFile();
    try {
      final SVNStatusClient readClient =
          new SVNStatusClient((ISVNRepositoryPool) null, new DefaultSVNOptions());
      final Semaphore semaphore = new Semaphore();
      final Semaphore semaphoreMain = new Semaphore();
      final Semaphore semaphoreWokeUp = new Semaphore();

      final AtomicReference<Boolean> wasUp = new AtomicReference<Boolean>(false);
      final ISVNStatusHandler handler =
          status -> {
            semaphore.waitFor();
            wasUp.set(true);
          };

      semaphore.down();
      semaphoreMain.down();
      semaphoreWokeUp.down();

      final SVNException[] exception = new SVNException[1];
      Thread thread =
          new Thread(
              () -> {
                try {
                  semaphoreMain.up();
                  readClient.doStatus(myWorkingCopyRoot, true, false, true, false, handler);
                  semaphoreWokeUp.up();
                } catch (SVNException e) {
                  exception[0] = e;
                }
              },
              "svn test");
      thread.start();

      semaphoreMain.waitFor();
      TimeoutUtil.sleep(5);
      SVNWCClient client = new SVNWCClient((ISVNRepositoryPool) null, new DefaultSVNOptions());
      client.doAdd(ioFile.getParentFile(), true, false, true, true);
      semaphore.up();
      semaphoreWokeUp.waitFor();

      Assert.assertEquals(true, wasUp.get().booleanValue());
      if (exception[0] != null) {
        throw exception[0];
      }
      thread.join();
    } finally {
      ioFile.delete();
    }
  }
 public void run() {
   try {
     while (readAvailable()) {
       TimeoutUtil.sleep(50L);
     }
   } catch (Exception e) {
     LOG.error(e);
   }
 }
  public synchronized void close() throws IOException {
    if (myWaitForThreadFuture != null) {
      myWaitForThreadFuture.cancel(true);
    }
    if (myWaitSemaphore != null) {
      myWaitSemaphore.up();
    }

    try {
      if (myInputStream != null && !myContainsError) {
        myInputStream.close();
        TimeoutUtil.sleep(10);
      }
    } finally {
      try {
        if (myOutputStream != null && !myContainsError) {
          myOutputStream.close();
          TimeoutUtil.sleep(10);
        }
        try {
          if (myErrThread != null) {
            myErrThread.setProcessTerminated(true);
          }
          if (myStdErrFuture != null) {
            myStdErrFuture.get();
          }
        } catch (InterruptedException e) {
          //
        } catch (ExecutionException e) {
          LOG.error(e);
        }
      } finally {
        try {
          if (myProcess != null) {
            myProcess.destroy();
          }
        } finally {
          myInputStream = null;
          myOutputStream = null;
          myProcess = null;
        }
      }
    }
  }
  public void testAwaitTerminationMakesSureTasksTransferredToBackendExecutorAreFinished()
      throws InterruptedException, ExecutionException {
    final AppScheduledExecutorService service = new AppScheduledExecutorService(getName());
    final List<LogInfo> log = Collections.synchronizedList(new ArrayList<>());

    int N = 20;
    int delay = 500;
    List<? extends Future<?>> futures =
        ContainerUtil.map(
            Collections.nCopies(N, ""),
            s ->
                service.schedule(
                    () -> {
                      TimeoutUtil.sleep(5000);
                      log.add(new LogInfo(0));
                    },
                    delay,
                    TimeUnit.MILLISECONDS));
    TimeoutUtil.sleep(delay);
    long start = System.currentTimeMillis();
    while (!service.delayQueue.isEmpty() && System.currentTimeMillis() < start + 20000) {
      // wait till all tasks transferred to backend
    }
    List<SchedulingWrapper.MyScheduledFutureTask> queuedTasks = new ArrayList<>(service.delayQueue);
    if (!queuedTasks.isEmpty()) {
      String s =
          queuedTasks
              .stream()
              .map(BoundedTaskExecutor::info)
              .collect(Collectors.toList())
              .toString();
      fail("Queued tasks left: " + s + ";\n" + queuedTasks);
    }
    service.shutdownAppScheduledExecutorService();
    assertTrue(service.awaitTermination(20, TimeUnit.SECONDS));

    for (Future<?> future : futures) {
      assertTrue(future.isDone());
    }
    assertEquals(log.toString(), N, log.size());
  }
  public void testDelayedTasksReusePooledThreadIfExecuteAtDifferentTimes()
      throws InterruptedException, ExecutionException {
    final AppScheduledExecutorService service = new AppScheduledExecutorService(getName());
    final List<LogInfo> log = Collections.synchronizedList(new ArrayList<>());
    // pre-start one thread
    Future<?> future = service.submit(EmptyRunnable.getInstance());
    future.get();
    service.setBackendPoolCorePoolSize(1);
    assertEquals(1, service.getBackendPoolExecutorSize());

    int delay = 500;

    ScheduledFuture<?> f1 =
        service.schedule((Runnable) () -> log.add(new LogInfo(1)), delay, TimeUnit.MILLISECONDS);
    ScheduledFuture<?> f2 =
        service.schedule(
            (Runnable) () -> log.add(new LogInfo(2)), delay + 100, TimeUnit.MILLISECONDS);
    ScheduledFuture<?> f3 =
        service.schedule(
            (Runnable) () -> log.add(new LogInfo(3)), delay + 200, TimeUnit.MILLISECONDS);

    assertEquals(1, service.getBackendPoolExecutorSize());

    assertFalse(f1.isDone());
    assertFalse(f2.isDone());
    assertFalse(f3.isDone());

    TimeoutUtil.sleep(delay + 200 + 300);
    assertTrue(f1.isDone());
    assertTrue(f2.isDone());
    assertTrue(f3.isDone());
    assertEquals(1, service.getBackendPoolExecutorSize());

    assertEquals(3, log.size());
    Set<Thread> usedThreads =
        new HashSet<>(
            Arrays.asList(
                log.get(0).currentThread, log.get(1).currentThread, log.get(2).currentThread));
    if (usedThreads.size() != 1) {
      System.err.println(ThreadDumper.dumpThreadsToString());
    }
    assertEquals(usedThreads.toString(), 1, usedThreads.size()); // must be executed in same thread

    service.shutdownAppScheduledExecutorService();
    assertTrue(service.awaitTermination(10, TimeUnit.SECONDS));
  }
  @Override
  @TestOnly
  public void shutdown() throws InterruptedException {
    final Application app = ApplicationManager.getApplication();
    assert app != null && app.isUnitTestMode() : app;

    final MyProcessHandler processHandler = myProcessHandler;
    if (processHandler != null) {
      myIsShuttingDown = true;
      shutdownProcess();

      long t = System.currentTimeMillis();
      while (!processHandler.isProcessTerminated()) {
        if ((System.currentTimeMillis() - t) > 5000) {
          throw new InterruptedException("Timed out waiting watcher process to terminate");
        }
        TimeoutUtil.sleep(100);
      }
    }
  }
  public void testWatchRootRecreation() throws Exception {
    File rootDir = createTestDir("root");
    File file1 = createTestFile(rootDir, "file1.txt", "abc");
    File file2 = createTestFile(rootDir, "file2.txt", "123");
    refresh(rootDir);

    LocalFileSystem.WatchRequest request = watch(rootDir);
    try {
      myAccept = true;
      assertTrue(FileUtil.delete(rootDir));
      assertTrue(rootDir.mkdir());
      if (SystemInfo.isLinux) TimeoutUtil.sleep(1100); // implementation specific
      assertTrue(file1.createNewFile());
      assertTrue(file2.createNewFile());
      assertEvent(VFileContentChangeEvent.class, file1.getPath(), file2.getPath());
    } finally {
      unwatch(request);
      delete(rootDir);
    }
  }
  public void testDirectoryRecreation() throws Exception {
    File rootDir = createTestDir("root");
    File topDir = createTestDir(rootDir, "top");
    File file1 = createTestFile(topDir, "file1.txt", "abc");
    File file2 = createTestFile(topDir, "file2.txt", "123");
    refresh(topDir);

    LocalFileSystem.WatchRequest request = watch(rootDir);
    try {
      myAccept = true;
      assertTrue(FileUtil.delete(topDir));
      assertTrue(topDir.mkdir());
      TimeoutUtil.sleep(100);
      assertTrue(file1.createNewFile());
      assertTrue(file2.createNewFile());
      assertEvent(VFileContentChangeEvent.class, file1.getPath(), file2.getPath());
    } finally {
      unwatch(request);
      delete(topDir);
    }
  }
  @Override
  @Nullable
  public Project newProject(
      final String projectName,
      @NotNull String filePath,
      boolean useDefaultProjectSettings,
      boolean isDummy) {
    filePath = toCanonicalName(filePath);

    //noinspection ConstantConditions
    if (LOG_PROJECT_LEAKAGE_IN_TESTS && ApplicationManager.getApplication().isUnitTestMode()) {
      for (int i = 0; i < 42; i++) {
        if (myProjects.size() < MAX_LEAKY_PROJECTS) break;
        System.gc();
        TimeoutUtil.sleep(100);
        System.gc();
      }

      if (myProjects.size() >= MAX_LEAKY_PROJECTS) {
        List<Project> copy = new ArrayList<Project>(myProjects.keySet());
        myProjects.clear();
        throw new TooManyProjectLeakedException(copy);
      }
    }

    ProjectImpl project =
        createProject(
            projectName, filePath, false, ApplicationManager.getApplication().isUnitTestMode());
    try {
      initProject(project, useDefaultProjectSettings ? (ProjectImpl) getDefaultProject() : null);
      if (LOG_PROJECT_LEAKAGE_IN_TESTS) {
        myProjects.put(project, null);
      }
      return project;
    } catch (final Exception e) {
      LOG.info(e);
      Messages.showErrorDialog(message(e), ProjectBundle.message("project.load.default.error"));
    }
    return null;
  }
    protected void doRun() {
      try {
        while (true) {
          boolean read = readAvailableBlocking();

          if (!read) {
            break;
          } else {
            if (isStopped) {
              break;
            }

            TimeoutUtil.sleep(mySleepingPolicy.getTimeToSleep(true));
          }
        }
      } catch (Exception e) {
        fireCommunicationError();
      } finally {
        close();
        fireExitEvent();
      }
    }
  private static void doAsyncRefreshTest(File temp) throws Exception {
    final int N = 1000;
    final byte[] data = "xxx".getBytes("UTF-8");

    LocalFileSystem fs = LocalFileSystem.getInstance();
    VirtualFile vTemp = fs.findFileByIoFile(temp);
    assertNotNull(vTemp);
    VirtualFile[] children = new VirtualFile[N];

    long[] timestamp = new long[N];
    for (int i = 0; i < N; i++) {
      File file = new File(temp, i + ".txt");
      FileUtil.writeToFile(file, data);
      VirtualFile child = fs.refreshAndFindFileByIoFile(file);
      assertNotNull(child);
      children[i] = child;
      timestamp[i] = file.lastModified();
    }

    vTemp.refresh(false, true);

    for (int i = 0; i < N; i++) {
      File file = new File(temp, i + ".txt");
      assertEquals(timestamp[i], file.lastModified());
      VirtualFile child = fs.findFileByIoFile(file);
      assertNotNull(child);
      IoTestUtil.assertTimestampsEqual(timestamp[i], child.getTimeStamp());
    }

    for (int i = 0; i < N; i++) {
      File file = new File(temp, i + ".txt");
      FileUtil.writeToFile(file, data);
      assertTrue(file.setLastModified(timestamp[i] - 2000));
      long modified = file.lastModified();
      assertTrue("File:" + file.getPath() + "; time:" + modified, timestamp[i] != modified);
      timestamp[i] = modified;
      IoTestUtil.assertTimestampsNotEqual(children[i].getTimeStamp(), modified);
    }

    final CountDownLatch latch = new CountDownLatch(N);
    for (final VirtualFile child : children) {
      child.refresh(
          true,
          true,
          new Runnable() {
            @Override
            public void run() {
              latch.countDown();
            }
          });
      TimeoutUtil.sleep(10);
    }
    while (latch.getCount() > 0) {
      latch.await(100, TimeUnit.MILLISECONDS);
      UIUtil.pump();
    }

    for (int i = 0; i < N; i++) {
      VirtualFile child = children[i];
      IoTestUtil.assertTimestampsEqual(timestamp[i], child.getTimeStamp());
    }
  }
 private static void waitUntilIndexReady(AtomicReference<RebuildStatus> rebuildStatus) {
   while (rebuildStatus.get() != OK) {
     ProgressManager.checkCanceled();
     TimeoutUtil.sleep(50);
   }
 }
  public void testDelayedWorks() throws InterruptedException {
    final AppScheduledExecutorService service = new AppScheduledExecutorService(getName());
    final List<LogInfo> log = Collections.synchronizedList(new ArrayList<>());
    assertFalse(service.isShutdown());
    assertFalse(service.isTerminated());

    service.invokeAll(
        Collections.nCopies(
            service.getBackendPoolCorePoolSize() + 1,
            Executors.callable(EmptyRunnable.getInstance()))); // pre-start all threads

    int delay = 1000;
    long start = System.currentTimeMillis();
    ScheduledFuture<?> f1 =
        service.schedule(
            () -> {
              log.add(new LogInfo(1));
              TimeoutUtil.sleep(10);
            },
            delay,
            TimeUnit.MILLISECONDS);
    assertFalse(service.isShutdown());
    assertFalse(service.isTerminated());
    ScheduledFuture<?> f2 =
        service.schedule(
            () -> {
              log.add(new LogInfo(2));
              TimeoutUtil.sleep(10);
            },
            delay,
            TimeUnit.MILLISECONDS);
    assertFalse(service.isShutdown());
    assertFalse(service.isTerminated());
    ScheduledFuture<?> f3 =
        service.schedule(
            () -> {
              log.add(new LogInfo(3));
              TimeoutUtil.sleep(10);
            },
            delay,
            TimeUnit.MILLISECONDS);

    assertFalse(service.isShutdown());
    assertFalse(service.isTerminated());
    Future<?> f4 = service.submit((Runnable) () -> log.add(new LogInfo(4)));

    assertFalse(service.isShutdown());
    assertFalse(service.isTerminated());
    assertFalse(f1.isDone());
    assertFalse(f2.isDone());
    assertFalse(f3.isDone());

    TimeoutUtil.sleep(delay / 2);
    long elapsed = System.currentTimeMillis() - start; // can be > delay/2 on overloaded agent
    assertEquals(String.valueOf(f1.isDone()), elapsed > delay, f1.isDone());
    assertEquals(String.valueOf(f2.isDone()), elapsed > delay, f2.isDone());
    assertEquals(String.valueOf(f3.isDone()), elapsed > delay, f3.isDone());
    assertTrue(f4.isDone());

    TimeoutUtil.sleep(delay / 2 + 500);
    assertTrue(f1.isDone());
    assertTrue(f2.isDone());
    assertTrue(f3.isDone());
    assertTrue(f4.isDone());

    assertEquals(4, log.size());
    assertEquals(4, log.get(0).runnable);
    List<Thread> threads =
        Arrays.asList(log.get(1).currentThread, log.get(2).currentThread, log.get(3).currentThread);
    assertEquals(
        threads.toString(), 3, new HashSet<>(threads).size()); // must be executed in parallel

    service.shutdownAppScheduledExecutorService();
    assertTrue(service.awaitTermination(10, TimeUnit.SECONDS));
  }