package org.testcontainers.containers.wait.internal;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.testcontainers.containers.Container.ExecResult;
import org.testcontainers.containers.ExecInContainerPattern;
import org.testcontainers.containers.wait.strategy.WaitStrategyTarget;

import java.time.Duration;
import java.time.Instant;
import java.util.Set;

import static java.lang.String.format;

/**
 * Mechanism for testing that a socket is listening when run from the container being checked.
 */
@RequiredArgsConstructor
@Slf4j
public class InternalCommandPortListeningCheck implements java.util.concurrent.Callable<Boolean> {

    private final WaitStrategyTarget waitStrategyTarget;
    private final Set<Integer> internalPorts;

    @Override
    public Boolean call() {
        String command = "true";

        for (int internalPort : internalPorts) {
            command += " && ";
            command += " (";
            command += format("cat /proc/net/tcp* | awk '{print $2}' | grep -i ':0*%x'", internalPort);
            command += " || ";
            command += format("nc -vz -w 1 localhost %d", internalPort);
            command += " || ";
            command += format("/bin/bash -c '</dev/tcp/localhost/%d'", internalPort);
            command += ")";
        }

        Instant before = Instant.now();
        try {
            ExecResult result = ExecInContainerPattern.execInContainer(waitStrategyTarget.getContainerInfo(), "/bin/sh", "-c", command);
            log.trace("Check for {} took {}", internalPorts, Duration.between(before, Instant.now()));
            return result.getExitCode() == 0;
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }
}

@@ -823,16 +823,23 @@
   String
+Builder
  command
@@ -845,14 +845,33 @@
 d = 
+new StringBuilder(
 %22true%22
+)
 ;%0A%0A 
@@ -941,18 +941,23 @@
 mand
- += 
+.append(
 %22 && %22
+)
 ;%0A  
@@ -977,16 +977,21 @@
 mand
- += 
+.append(
 %22 (%22
+)
 ;%0A  
@@ -999,36 +999,40 @@
          command
- += 
+.append(
 format(%22cat /pro
@@ -1086,32 +1086,33 @@
 %22, internalPort)
+)
 ;%0A            co
@@ -1112,34 +1112,39 @@
      command
- += 
+.append(
 %22 %7C%7C %22
+)
 ;%0A          
@@ -1144,36 +1144,40 @@
          command
- += 
+.append(
 format(%22nc -vz -
@@ -1200,32 +1200,33 @@
 %22, internalPort)
+)
 ;%0A            co
@@ -1234,18 +1234,23 @@
 mand
- += 
+.append(
 %22 %7C%7C %22
+)
 ;%0A  
@@ -1266,20 +1266,24 @@
  command
- += 
+.append(
 format(%22
@@ -1335,16 +1335,17 @@
 nalPort)
+)
 ;%0A      
@@ -1361,15 +1361,20 @@
 mand
- += 
+.append(
 %22)%22
+)
 ;%0A  
@@ -1570,16 +1570,27 @@
  command
+.toString()
 );%0A     
@@ -1627,16 +1627,56 @@
  took %7B%7D
+. Result code '%7B%7D', stdout message: '%7B%7D'
 %22, inter
@@ -1724,16 +1724,58 @@
 t.now())
+, result.getExitCode(), result.getStdout()
 );%0A     

Improve logging for port listener (#3736)