aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/cpp/naming/utils
diff options
context:
space:
mode:
authorGravatar Alexander Polcyn <apolcyn@google.com>2018-03-06 17:13:06 -0800
committerGravatar Alexander Polcyn <apolcyn@google.com>2018-03-06 19:22:34 -0800
commit0a05b782fe0acdd4d5d14ee486baf51d779449c7 (patch)
treef30799b6922e8eb39ee1a2e82486b6cb227c01c5 /test/cpp/naming/utils
parent3c5e12de08a255edf78890d7408e2f98ebca7e2d (diff)
Move python DNS utilities to utils subdirectory
Diffstat (limited to 'test/cpp/naming/utils')
-rw-r--r--test/cpp/naming/utils/BUILD50
-rwxr-xr-xtest/cpp/naming/utils/dns_resolver.py48
-rwxr-xr-xtest/cpp/naming/utils/dns_server.py134
-rwxr-xr-xtest/cpp/naming/utils/tcp_connect.py35
4 files changed, 267 insertions, 0 deletions
diff --git a/test/cpp/naming/utils/BUILD b/test/cpp/naming/utils/BUILD
new file mode 100644
index 0000000000..e7b6bc5fe7
--- /dev/null
+++ b/test/cpp/naming/utils/BUILD
@@ -0,0 +1,50 @@
+# Copyright 2017 gRPC authors.
+#
+# Licensed 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(
+ default_visibility = ["//visibility:public"],
+ features = [
+ "-layering_check",
+ "-parse_headers",
+ ],
+)
+
+licenses(["notice"]) # Apache v2
+
+load("//bazel:grpc_build_system.bzl", "grpc_py_binary")
+
+grpc_py_binary(
+ name = "dns_server",
+ srcs = ["dns_server.py"],
+ testonly = True,
+ external_deps = [
+ "twisted",
+ "yaml",
+ ]
+)
+
+grpc_py_binary(
+ name = "dns_resolver",
+ srcs = ["dns_resolver.py"],
+ testonly = True,
+ external_deps = [
+ "twisted",
+ ]
+)
+
+grpc_py_binary(
+ name = "tcp_connect",
+ srcs = ["tcp_connect.py"],
+ testonly = True,
+)
diff --git a/test/cpp/naming/utils/dns_resolver.py b/test/cpp/naming/utils/dns_resolver.py
new file mode 100755
index 0000000000..6b272444e7
--- /dev/null
+++ b/test/cpp/naming/utils/dns_resolver.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python2.7
+# Copyright 2015 gRPC authors.
+#
+# Licensed 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.
+
+"""Makes DNS queries for A records to specified servers"""
+
+import argparse
+import signal
+import twisted.internet.task as task
+import twisted.names.client as client
+
+def main():
+ argp = argparse.ArgumentParser(description='Make DNS queries for A records')
+ argp.add_argument('-s', '--server_host', default='127.0.0.1', type=str,
+ help='Host for DNS server to listen on for TCP and UDP.')
+ argp.add_argument('-p', '--server_port', default=53, type=int,
+ help='Port that the DNS server is listening on.')
+ argp.add_argument('-n', '--qname', default=None, type=str,
+ help=('Name of the record to query for. '))
+ argp.add_argument('-t', '--timeout', default=1, type=int,
+ help=('Force process exit after this number of seconds.'))
+ args = argp.parse_args()
+ signal.alarm(args.timeout)
+ def OnResolverResultAvailable(result):
+ answers, authority, additional = result
+ for a in answers:
+ print(a.payload)
+ def BeginQuery(reactor, qname):
+ servers = [(args.server_host, args.server_port)]
+ resolver = client.Resolver(servers=servers)
+ deferred_result = resolver.lookupAddress(args.qname)
+ deferred_result.addCallback(OnResolverResultAvailable)
+ return deferred_result
+ task.react(BeginQuery, [args.qname])
+
+if __name__ == '__main__':
+ main()
diff --git a/test/cpp/naming/utils/dns_server.py b/test/cpp/naming/utils/dns_server.py
new file mode 100755
index 0000000000..9f42f65ee6
--- /dev/null
+++ b/test/cpp/naming/utils/dns_server.py
@@ -0,0 +1,134 @@
+#!/usr/bin/env python2.7
+# Copyright 2015 gRPC authors.
+#
+# Licensed 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.
+
+"""Starts a local DNS server for use in tests"""
+
+import argparse
+import sys
+import yaml
+import signal
+import os
+
+import twisted
+import twisted.internet
+import twisted.internet.reactor
+import twisted.internet.threads
+import twisted.internet.defer
+import twisted.internet.protocol
+import twisted.names
+import twisted.names.client
+import twisted.names.dns
+import twisted.names.server
+from twisted.names import client, server, common, authority, dns
+import argparse
+
+_SERVER_HEALTH_CHECK_RECORD_NAME = 'health-check-local-dns-server-is-alive.resolver-tests.grpctestingexp' # missing end '.' for twisted syntax
+_SERVER_HEALTH_CHECK_RECORD_DATA = '123.123.123.123'
+
+class NoFileAuthority(authority.FileAuthority):
+ def __init__(self, soa, records):
+ # skip FileAuthority
+ common.ResolverBase.__init__(self)
+ self.soa = soa
+ self.records = records
+
+def start_local_dns_server(args):
+ all_records = {}
+ def _push_record(name, r):
+ print('pushing record: |%s|' % name)
+ if all_records.get(name) is not None:
+ all_records[name].append(r)
+ return
+ all_records[name] = [r]
+
+ def _maybe_split_up_txt_data(name, txt_data, r_ttl):
+ start = 0
+ txt_data_list = []
+ while len(txt_data[start:]) > 0:
+ next_read = len(txt_data[start:])
+ if next_read > 255:
+ next_read = 255
+ txt_data_list.append(txt_data[start:start+next_read])
+ start += next_read
+ _push_record(name, dns.Record_TXT(*txt_data_list, ttl=r_ttl))
+
+ with open(args.records_config_path) as config:
+ test_records_config = yaml.load(config)
+ common_zone_name = test_records_config['resolver_tests_common_zone_name']
+ for group in test_records_config['resolver_component_tests']:
+ for name in group['records'].keys():
+ for record in group['records'][name]:
+ r_type = record['type']
+ r_data = record['data']
+ r_ttl = int(record['TTL'])
+ record_full_name = '%s.%s' % (name, common_zone_name)
+ assert record_full_name[-1] == '.'
+ record_full_name = record_full_name[:-1]
+ if r_type == 'A':
+ _push_record(record_full_name, dns.Record_A(r_data, ttl=r_ttl))
+ if r_type == 'AAAA':
+ _push_record(record_full_name, dns.Record_AAAA(r_data, ttl=r_ttl))
+ if r_type == 'SRV':
+ p, w, port, target = r_data.split(' ')
+ p = int(p)
+ w = int(w)
+ port = int(port)
+ target_full_name = '%s.%s' % (target, common_zone_name)
+ r_data = '%s %s %s %s' % (p, w, port, target_full_name)
+ _push_record(record_full_name, dns.Record_SRV(p, w, port, target_full_name, ttl=r_ttl))
+ if r_type == 'TXT':
+ _maybe_split_up_txt_data(record_full_name, r_data, r_ttl)
+ # Server health check record
+ _push_record(_SERVER_HEALTH_CHECK_RECORD_NAME, dns.Record_A(_SERVER_HEALTH_CHECK_RECORD_DATA, ttl=0))
+ soa_record = dns.Record_SOA(mname = common_zone_name)
+ test_domain_com = NoFileAuthority(
+ soa = (common_zone_name, soa_record),
+ records = all_records,
+ )
+ server = twisted.names.server.DNSServerFactory(
+ authorities=[test_domain_com], verbose=2)
+ server.noisy = 2
+ twisted.internet.reactor.listenTCP(args.port, server)
+ dns_proto = twisted.names.dns.DNSDatagramProtocol(server)
+ dns_proto.noisy = 2
+ twisted.internet.reactor.listenUDP(args.port, dns_proto)
+ print('starting local dns server on 127.0.0.1:%s' % args.port)
+ print('starting twisted.internet.reactor')
+ twisted.internet.reactor.suggestThreadPoolSize(1)
+ twisted.internet.reactor.run()
+
+def _quit_on_signal(signum, _frame):
+ print('Received SIGNAL %d. Quitting with exit code 0' % signum)
+ twisted.internet.reactor.stop()
+ sys.stdout.flush()
+ sys.exit(0)
+
+def main():
+ argp = argparse.ArgumentParser(description='Local DNS Server for resolver tests')
+ argp.add_argument('-p', '--port', default=None, type=int,
+ help='Port for DNS server to listen on for TCP and UDP.')
+ argp.add_argument('-r', '--records_config_path', default=None, type=str,
+ help=('Directory of resolver_test_record_groups.yaml file. '
+ 'Defauls to path needed when the test is invoked as part of run_tests.py.'))
+ args = argp.parse_args()
+ signal.signal(signal.SIGALRM, _quit_on_signal)
+ signal.signal(signal.SIGTERM, _quit_on_signal)
+ signal.signal(signal.SIGINT, _quit_on_signal)
+ # Prevent zombies. Tests that use this server are short-lived.
+ signal.alarm(2 * 60)
+ start_local_dns_server(args)
+
+if __name__ == '__main__':
+ main()
diff --git a/test/cpp/naming/utils/tcp_connect.py b/test/cpp/naming/utils/tcp_connect.py
new file mode 100755
index 0000000000..bf7455e3c2
--- /dev/null
+++ b/test/cpp/naming/utils/tcp_connect.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python2.7
+# Copyright 2015 gRPC authors.
+#
+# Licensed 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.
+
+"""Opens a TCP connection to a specified server and then exits."""
+
+import argparse
+import signal
+import socket
+
+def main():
+ argp = argparse.ArgumentParser(description='Open a TCP handshake to a server')
+ argp.add_argument('-s', '--server_host', default=None, type=str,
+ help='Server host name or IP.')
+ argp.add_argument('-p', '--server_port', default=0, type=int,
+ help='Port that the server is listening on.')
+ argp.add_argument('-t', '--timeout', default=1, type=int,
+ help='Force process exit after this number of seconds.')
+ args = argp.parse_args()
+ signal.alarm(args.timeout)
+ socket.create_connection([args.server_host, args.server_port])
+
+if __name__ == '__main__':
+ main()