'''
'''
#  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.

Test.Summary = 'Testing ATS TCP handshake timeout'

# Skipping this in the normal CI because it requires privilege.
# Comment out to run in your privileged environment
Test.SkipIf(Condition.true("Test requires privilege"))

ts = Test.MakeATSProcess("ts")

Test.ContinueOnFail = True
Test.GetTcpPort("blocked_upstream_port")
Test.GetTcpPort("upstream_port")

ts.Disk.records_config.update({
    'proxy.config.url_remap.remap_required': 1,
    'proxy.config.http.connect_attempts_timeout': 2,
    'proxy.config.http.connect_attempts_max_retries': 0,
    'proxy.config.http.transaction_no_activity_timeout_out': 5,
    'proxy.config.diags.debug.enabled': 0,
    'proxy.config.diags.debug.tags': 'http',
})

ts.Disk.remap_config.AddLine('map /blocked http://10.1.1.1:{0}'.format(Test.Variables.blocked_upstream_port))
ts.Disk.remap_config.AddLine('map /not-blocked http://10.1.1.1:{0}'.format(Test.Variables.upstream_port))

# Set up the network name space.  Requires privilege
tr = Test.AddTestRun("tr-ns-setup")
tr.Processes.Default.StartBefore(ts)
tr.Processes.Default.TimeOut = 2
tr.Setup.Copy('setupnetns.sh')
tr.Processes.Default.Command = 'echo start; sudo sh -x ./setupnetns.sh {0} {1}'.format(
    Test.Variables.blocked_upstream_port, Test.Variables.upstream_port)

# Request to the port that is blocked in the network ns.  The SYN should never be responded to
# and the connect timeout should trigger with a 50x return.  If the SYN handshake occurs, the
# no activity timeout would trigger, but not before the test timeout expires
tr = Test.AddTestRun("tr-blocking")
tr.Processes.Default.Command = 'curl -i http://127.0.0.1:{0}/blocked {0}'.format(ts.Variables.port)
tr.Processes.Default.TimeOut = 4
tr.Processes.Default.Streams.All = Testers.ContainsExpression(
    "HTTP/1.1 502 internal error - server connection terminated", "Connect failed")

#  Should not catch the connect timeout.  Even though the first bytes are not sent until after the 2 second connect timeout
#  But before the no-activity timeout
tr = Test.AddTestRun("tr-delayed")
tr.Setup.Copy('delay-server.sh')
tr.Setup.Copy('case1.sh')
tr.Processes.Default.Command = 'sh ./case1.sh {0} {1}'.format(ts.Variables.port, ts.Variables.upstream_port)
tr.Processes.Default.TimeOut = 7
tr.Processes.Default.Streams.All = Testers.ContainsExpression("HTTP/1.1 200", "Connect succeeded")


# cleanup the network namespace and virtual network
tr = Test.AddTestRun("tr-cleanup")
tr.Processes.Default.Command = 'sudo ip netns del testserver; sudo ip link del veth0 type veth peer name veth1'
tr.Processes.Default.TimeOut = 4

@@ -1157,16 +1157,60 @@
 port%22)%0A%0A
+server4 = Test.MakeOriginServer(%22server4%22)%0A%0A
 ts.Disk.
@@ -1334,16 +1334,74 @@
 ut': 2,%0A
+    'proxy.config.http.post_connect_attempts_timeout': 2,%0A
     'pro
@@ -1822,16 +1822,243 @@
 port))%0A%0A
+ts.Disk.logging_yaml.AddLines(%0A    '''%0Alogging:%0A  formats:%0A    - name: testformat%0A      format: '%25%3Cpssc%3E %25%3Ccquc%3E %25%3Cpscert%3E %25%3Ccscert%3E'%0A  logs:%0A    - mode: ascii%0A      format: testformat%0A      filename: squid%0A'''.split(%22%5Cn%22)%0A)%0A%0A%0A
 # Set up
@@ -2983,16 +2983,350 @@
 iled%22)%0A%0A
+tr = Test.AddTestRun(%22tr-blocking-post%22)%0Atr.Processes.Default.Command = 'curl -d %22stuff%22 -i http://127.0.0.1:%7B0%7D/blocked %7B0%7D'.format(ts.Variables.port)%0Atr.Processes.Default.TimeOut = 4%0Atr.Processes.Default.Streams.All = Testers.ContainsExpression(%0A    %22HTTP/1.1 502 internal error - server connection terminated%22, %22Connect failed%22)%0A%0A%0A
 #  Shoul
@@ -4015,16 +4015,16 @@
  veth1'%0A
-
 tr.Proce
@@ -4028,28 +4028,292 @@
 ocesses.Default.TimeOut = 4%0A
+%0Atr = Test.AddTestRun(%22Wait for the access log to write out%22)%0Atr.Processes.Default.StartBefore(server4, ready=When.FileExists(ts.Disk.squid_log))%0Atr.StillRunningAfter = ts%0Atr.Processes.Default.Command = 'echo %22log file exists%22'%0Atr.Processes.Default.ReturnCode = 0%0A

Add a post case to the conn_timeout test (#7334)