/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.redis.internal.executor.pubsub;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.commons.lang3.SystemUtils;
import org.apache.logging.log4j.Logger;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.ClassRule;

import org.apache.geode.NativeRedisTestRule;
import org.apache.geode.logging.internal.log4j.api.LogService;

public class PubSubNativeRedisAcceptanceTest extends AbstractPubSubIntegrationTest {

  private static final Logger logger = LogService.getLogger();
  private static long socketTimeWaitMsec = 240000;

  @ClassRule
  public static NativeRedisTestRule redis = new NativeRedisTestRule();

  @BeforeClass
  public static void runOnce() throws IOException {
    if (SystemUtils.IS_OS_LINUX) {
      try {
        String line = getCommandOutput("cat", "/proc/sys/net/ipv4/tcp_fin_timeout");
        socketTimeWaitMsec = Long.parseLong(line.trim());
      } catch (NumberFormatException | IOException ignored) {
      }
    } else if (SystemUtils.IS_OS_MAC) {
      try {
        String line = getCommandOutput("sysctl", "net.inet.tcp.msl");
        String[] parts = line.split(":");
        if (parts.length == 2) {
          socketTimeWaitMsec = 2 * Long.parseLong(parts[1].trim());
        }
      } catch (NumberFormatException | IOException ignored) {
      }
    }
    // Just leave timeout at the default if it's some other OS or there's a problem getting OS value
  }

  private static String getCommandOutput(String... commandStringElements) throws IOException {
    Process process = new ProcessBuilder(commandStringElements).start();
    try (BufferedReader reader = new BufferedReader(
        new InputStreamReader(process.getInputStream()))) {
      return reader.readLine();
    } finally {
      // Probably overkill but ensures test leaves no orphaned processes
      process.destroy();
    }
  }

  @AfterClass
  public static void cleanup() throws InterruptedException {
    // This test consumes a lot of sockets and any subsequent tests may fail because of spurious
    // bind exceptions. Even though sockets are closed, they will remain in TIME_WAIT state so we
    // need to wait for that to clear up. It shouldn't take more than a minute or so.
    // For now a thread sleep is the simplest way to wait for the sockets to be out of the TIME_WAIT
    // state. The default timeout of 240 sec was chosen because that is the default duration for
    // TIME_WAIT on Windows. The timeouts for both mac and linux are significantly shorter.
    Thread.sleep(socketTimeWaitMsec);
  }

  @Override
  public int getPort() {
    return redis.getPort();
  }
}

@@ -846,147 +846,8 @@
 b;%0A%0A
-import java.io.BufferedReader;%0Aimport java.io.IOException;%0Aimport java.io.InputStreamReader;%0A%0Aimport org.apache.commons.lang3.SystemUtils;%0A
 impo
@@ -915,38 +915,8 @@
 ss;%0A
-import org.junit.BeforeClass;%0A
 impo
@@ -1201,59 +1201,8 @@
 r();
-%0A  private static long socketTimeWaitMsec = 240000;
 %0A%0A  
@@ -1288,1230 +1288,8 @@
 );%0A%0A
-  @BeforeClass%0A  public static void runOnce() throws IOException %7B%0A    if (SystemUtils.IS_OS_LINUX) %7B%0A      try %7B%0A        String line = getCommandOutput(%22cat%22, %22/proc/sys/net/ipv4/tcp_fin_timeout%22);%0A        socketTimeWaitMsec = Long.parseLong(line.trim());%0A      %7D catch (NumberFormatException %7C IOException ignored) %7B%0A      %7D%0A    %7D else if (SystemUtils.IS_OS_MAC) %7B%0A      try %7B%0A        String line = getCommandOutput(%22sysctl%22, %22net.inet.tcp.msl%22);%0A        String%5B%5D parts = line.split(%22:%22);%0A        if (parts.length == 2) %7B%0A          socketTimeWaitMsec = 2 * Long.parseLong(parts%5B1%5D.trim());%0A        %7D%0A      %7D catch (NumberFormatException %7C IOException ignored) %7B%0A      %7D%0A    %7D%0A    // Just leave timeout at the default if it's some other OS or there's a problem getting OS value%0A  %7D%0A%0A  private static String getCommandOutput(String... commandStringElements) throws IOException %7B%0A    Process process = new ProcessBuilder(commandStringElements).start();%0A    try (BufferedReader reader = new BufferedReader(%0A        new InputStreamReader(process.getInputStream()))) %7B%0A      return reader.readLine();%0A    %7D finally %7B%0A      // Probably overkill but ensures test leaves no orphaned processes%0A      process.destroy();%0A    %7D%0A  %7D%0A%0A
   @A
@@ -1647,17 +1647,79 @@
 %0A    // 
-F
+There will be a better solution for this from GEODE-9495, but f
 or now a
@@ -1738,16 +1738,23 @@
 p is the
+%0A    //
  simples
@@ -1809,23 +1809,16 @@
 IME_WAIT
-%0A    //
  state. 
@@ -1821,24 +1821,16 @@
 te. The 
-default 
 timeout 
@@ -1839,16 +1839,23 @@
  240 sec
+%0A    //
  was cho
@@ -1898,23 +1898,16 @@
 tion for
-%0A    //
  TIME_WA
@@ -1937,16 +1937,23 @@
 outs for
+%0A    //
  both ma
@@ -2012,26 +2012,14 @@
 eep(
-socketTimeWaitMsec
+240000
 );%0A 

Revert "GEODE-9495: Limit Thread Sleep In PubSubNativeRedisAcceptanceTest (#6866)" (#6879)