1''' 2''' 3# Licensed to the Apache Software Foundation (ASF) under one 4# or more contributor license agreements. See the NOTICE file 5# distributed with this work for additional information 6# regarding copyright ownership. The ASF licenses this file 7# to you under the Apache License, Version 2.0 (the 8# "License"); you may not use this file except in compliance 9# with the License. You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, software 14# distributed under the License is distributed on an "AS IS" BASIS, 15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16# See the License for the specific language governing permissions and 17# limitations under the License. 18 19import os 20 21Test.Summary = ''' 22Test custom log file format 23''' 24Test.SkipUnless( 25 Condition.HasATSFeature('TS_HAS_PIPE_BUFFER_SIZE_CONFIG') 26) 27 28ts_counter = 1 29 30 31def get_ts(logging_config): 32 """ 33 Create a Traffic Server process. 34 """ 35 global ts_counter 36 ts = Test.MakeATSProcess("ts{}".format(ts_counter)) 37 ts_counter += 1 38 39 ts.Disk.records_config.update({ 40 'proxy.config.diags.debug.enabled': 1, 41 'proxy.config.diags.debug.tags': 'log-file', 42 'proxy.config.log.max_secs_per_buffer': 1, 43 }) 44 45 # Since we're only verifying logs and not traffic, we don't need an origin 46 # server. The following will simply deny the requests and emit a log 47 # message. 48 ts.Disk.remap_config.AddLine( 49 'map / http://www.linkedin.com/ @action=deny' 50 ) 51 52 ts.Disk.logging_yaml.AddLines(logging_config) 53 54 return ts 55 56 57# 58# Test 1: Default configured log pipe size. 59# 60tr = Test.AddTestRun() 61pipe_name = "default_pipe_size.pipe" 62ts = get_ts( 63 ''' 64logging: 65 formats: 66 - name: custom 67 format: "%<hii> %<hiih>" 68 logs: 69 - filename: '{}' 70 mode: ascii_pipe 71 format: custom 72'''.format(pipe_name).split("\n") 73) 74 75pipe_path = os.path.join(ts.Variables.LOGDIR, pipe_name) 76 77ts.Streams.All += Testers.ContainsExpression( 78 "Created named pipe .*{}".format(pipe_name), 79 "Verify that the named pipe was created") 80 81ts.Streams.All += Testers.ContainsExpression( 82 "no readers for pipe .*{}".format(pipe_name), 83 "Verify that no readers for the pipe was detected.") 84 85ts.Streams.All += Testers.ExcludesExpression( 86 "New buffer size for pipe".format(pipe_name), 87 "Verify that the default pipe size was used.") 88 89curl = tr.Processes.Process("client_request", 'curl "http://127.0.0.1:{0}" --verbose'.format( 90 ts.Variables.port)) 91 92reader_output = os.path.join(ts.Variables.LOGDIR, "reader_output") 93pipe_reader = tr.Processes.Process("pipe_reader", 'cat {} | tee {}'.format(pipe_path, reader_output)) 94 95# Create an arbitrary process that just sleeps so that we can provide a wait 96# condition upon the log being emitted. The test won't wait this entire sleep 97# period, it will only poll until the FileContains Ready condition is 98# fulfilled. 99wait_for_log = tr.Processes.Process("wait_for_log", 'sleep 15') 100wait_for_log.Ready = When.FileContains(reader_output, '127.0.0.1') 101 102# This is an arbitrary Default process that will simply provide for 103# ordering of the Processes. 104tr.Processes.Default.Command = "echo 'Default place holder for process ordering.'" 105tr.Processes.Default.Return = 0 106 107# Process ordering. 108tr.Processes.Default.StartBefore(wait_for_log) 109wait_for_log.StartBefore(curl) 110curl.StartBefore(pipe_reader) 111pipe_reader.StartBefore(ts) 112 113 114# 115# Test 2: Change the log's buffer size. 116# 117tr = Test.AddTestRun() 118pipe_name = "change_pipe_size.pipe" 119# 64 KB is the default, so set the size larger than that to verify we can 120# increase the size. 121pipe_size = 75000 122ts = get_ts( 123 ''' 124logging: 125 formats: 126 - name: custom 127 format: "%<hii> %<hiih>" 128 logs: 129 - filename: '{}' 130 mode: ascii_pipe 131 format: custom 132 pipe_buffer_size: {} 133 '''.format(pipe_name, pipe_size).split("\n") 134) 135 136pipe_path = os.path.join(ts.Variables.LOGDIR, pipe_name) 137 138ts.Streams.All += Testers.ContainsExpression( 139 "Created named pipe .*{}".format(pipe_name), 140 "Verify that the named pipe was created") 141 142ts.Streams.All += Testers.ContainsExpression( 143 "no readers for pipe .*{}".format(pipe_name), 144 "Verify that no readers for the pipe was detected.") 145 146ts.Streams.All += Testers.ContainsExpression( 147 "Previous buffer size for pipe .*{}".format(pipe_name), 148 "Verify that the named pipe's size was adjusted") 149 150# See fcntl: 151# "Attempts to set the pipe capacity below the page size 152# are silently rounded up to the page size." 153# 154# As a result of this, we cannot check that the pipe size is the exact size we 155# requested, but it should be at least that big. We use the 156# pipe_buffer_is_larger_than.py helper script to verify that the pipe grew in 157# size. 158ts.Streams.All += Testers.ContainsExpression( 159 "New buffer size for pipe.*{}".format(pipe_name), 160 "Verify that the named pipe's size was adjusted") 161buffer_verifier = "pipe_buffer_is_larger_than.py" 162tr.Setup.Copy(buffer_verifier) 163verify_buffer_size = tr.Processes.Process( 164 "verify_buffer_size", 165 "python3 {} {} {}".format(buffer_verifier, pipe_path, pipe_size)) 166verify_buffer_size.Return = 0 167verify_buffer_size.Streams.All += Testers.ContainsExpression( 168 "Success", 169 "The buffer size verifier should report success.") 170 171curl = tr.Processes.Process("client_request", 'curl "http://127.0.0.1:{0}" --verbose'.format( 172 ts.Variables.port)) 173 174reader_output = os.path.join(ts.Variables.LOGDIR, "reader_output") 175pipe_reader = tr.Processes.Process("pipe_reader", 'cat {} | tee {}'.format(pipe_path, reader_output)) 176 177# Create an arbitrary process that just sleeps so that we can provide a wait 178# condition upon the log being emitted. The test won't wait this entire sleep 179# period, it will only poll until the FileContains Ready condition is 180# fulfilled. 181wait_for_log = tr.Processes.Process("wait_for_log", 'sleep 15') 182wait_for_log.Ready = When.FileContains(reader_output, '127.0.0.1') 183 184# This is an arbitrary Default process that will simply provide for 185# ordering of the Processes. 186tr.Processes.Default.Command = "echo 'Default place holder for process ordering.'" 187tr.Processes.Default.Return = 0 188 189 190# Process ordering. 191tr.Processes.Default.StartBefore(verify_buffer_size) 192verify_buffer_size.StartBefore(wait_for_log) 193wait_for_log.StartBefore(curl) 194curl.StartBefore(pipe_reader) 195pipe_reader.StartBefore(ts) 196