1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
8 #define STATEFILE_PRIVATE
9 #define CONTROL_EVENTS_PRIVATE
10 #define PROCESS_PRIVATE
11 #include "core/or/or.h"
12 #include "app/config/config.h"
13 #include "lib/confmgt/confmgt.h"
14 #include "feature/control/control.h"
15 #include "feature/control/control_events.h"
16 #include "feature/client/transports.h"
17 #include "core/or/circuitbuild.h"
18 #include "app/config/statefile.h"
19 #include "test/test.h"
20 #include "lib/encoding/confline.h"
21 #include "lib/net/resolve.h"
22 #include "lib/process/process.h"
24 #include "app/config/or_state_st.h"
26 #include "test/log_test_helpers.h"
29 reset_mp(managed_proxy_t
*mp
)
31 mp
->conf_state
= PT_PROTO_LAUNCHED
;
32 SMARTLIST_FOREACH(mp
->transports
, transport_t
*, t
, transport_free(t
));
33 smartlist_clear(mp
->transports
);
37 test_pt_parsing(void *arg
)
40 transport_t
*transport
= NULL
;
43 managed_proxy_t
*mp
= tor_malloc_zero(sizeof(managed_proxy_t
));
45 mp
->conf_state
= PT_PROTO_INFANT
;
46 mp
->transports
= smartlist_new();
48 /* incomplete cmethod */
49 strlcpy(line
,"CMETHOD trebuchet",sizeof(line
));
50 tt_int_op(parse_cmethod_line(line
, mp
), OP_LT
, 0);
54 /* wrong proxy type */
55 strlcpy(line
,"CMETHOD trebuchet dog 127.0.0.1:1999",sizeof(line
));
56 tt_int_op(parse_cmethod_line(line
, mp
), OP_LT
, 0);
61 strlcpy(line
,"CMETHOD trebuchet socks4 abcd",sizeof(line
));
62 tt_int_op(parse_cmethod_line(line
, mp
), OP_LT
, 0);
67 strlcpy(line
,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line
));
68 tt_int_op(parse_cmethod_line(line
, mp
), OP_EQ
, 0);
69 tt_int_op(smartlist_len(mp
->transports
), OP_EQ
, 1);
70 transport
= smartlist_get(mp
->transports
, 0);
71 /* test registered address of transport */
72 tor_addr_parse(&test_addr
, "127.0.0.1");
73 tt_assert(tor_addr_eq(&test_addr
, &transport
->addr
));
74 /* test registered port of transport */
75 tt_uint_op(transport
->port
, OP_EQ
, 1999);
76 /* test registered SOCKS version of transport */
77 tt_int_op(transport
->socks_version
, OP_EQ
, PROXY_SOCKS5
);
78 /* test registered name of transport */
79 tt_str_op(transport
->name
,OP_EQ
, "trebuchet");
83 /* incomplete smethod */
84 strlcpy(line
,"SMETHOD trebuchet",sizeof(line
));
85 tt_int_op(parse_smethod_line(line
, mp
), OP_LT
, 0);
90 strlcpy(line
,"SMETHOD trebuchet abcd",sizeof(line
));
91 tt_int_op(parse_smethod_line(line
, mp
), OP_LT
, 0);
96 strlcpy(line
,"SMETHOD trebuchy 127.0.0.2:2999",sizeof(line
));
97 tt_int_op(parse_smethod_line(line
, mp
), OP_EQ
, 0);
98 tt_int_op(smartlist_len(mp
->transports
), OP_EQ
, 1);
99 transport
= smartlist_get(mp
->transports
, 0);
100 /* test registered address of transport */
101 tor_addr_parse(&test_addr
, "127.0.0.2");
102 tt_assert(tor_addr_eq(&test_addr
, &transport
->addr
));
103 /* test registered port of transport */
104 tt_uint_op(transport
->port
, OP_EQ
, 2999);
105 /* test registered name of transport */
106 tt_str_op(transport
->name
,OP_EQ
, "trebuchy");
110 /* Include some arguments. Good ones. */
111 strlcpy(line
,"SMETHOD trebuchet 127.0.0.1:9999 "
112 "ARGS:counterweight=3,sling=snappy",
114 tt_int_op(parse_smethod_line(line
, mp
), OP_EQ
, 0);
115 tt_int_op(1, OP_EQ
, smartlist_len(mp
->transports
));
117 const transport_t
*transport_
= smartlist_get(mp
->transports
, 0);
118 tt_assert(transport_
);
119 tt_str_op(transport_
->name
, OP_EQ
, "trebuchet");
120 tt_int_op(transport_
->port
, OP_EQ
, 9999);
121 tt_str_op(fmt_addr(&transport_
->addr
), OP_EQ
, "127.0.0.1");
122 tt_str_op(transport_
->extra_info_args
, OP_EQ
,
123 "counterweight=3,sling=snappy");
127 /* unsupported version */
128 strlcpy(line
,"VERSION 666",sizeof(line
));
129 tt_int_op(parse_version(line
, mp
), OP_LT
, 0);
131 /* incomplete VERSION */
132 strlcpy(line
,"VERSION ",sizeof(line
));
133 tt_int_op(parse_version(line
, mp
), OP_LT
, 0);
135 /* correct VERSION */
136 strlcpy(line
,"VERSION 1",sizeof(line
));
137 tt_int_op(parse_version(line
, mp
), OP_EQ
, 0);
141 smartlist_free(mp
->transports
);
146 test_pt_get_transport_options(void *arg
)
149 smartlist_t
*transport_list
= smartlist_new();
151 or_options_t
*options
= get_options_mutable();
152 char *opt_str
= NULL
;
153 config_line_t
*cl
= NULL
;
156 execve_args
= tor_malloc(sizeof(char*)*2);
157 execve_args
[0] = tor_strdup("cheeseshop");
158 execve_args
[1] = NULL
;
160 mp
= managed_proxy_create(transport_list
, execve_args
, 1);
161 tt_ptr_op(mp
, OP_NE
, NULL
);
162 opt_str
= get_transport_options_for_server_proxy(mp
);
163 tt_ptr_op(opt_str
, OP_EQ
, NULL
);
165 smartlist_add_strdup(mp
->transports_to_launch
, "gruyere");
166 smartlist_add_strdup(mp
->transports_to_launch
, "roquefort");
167 smartlist_add_strdup(mp
->transports_to_launch
, "stnectaire");
171 cl
= tor_malloc_zero(sizeof(config_line_t
));
172 cl
->value
= tor_strdup("gruyere melty=10 hardness=se;ven");
173 options
->ServerTransportOptions
= cl
;
175 cl
= tor_malloc_zero(sizeof(config_line_t
));
176 cl
->value
= tor_strdup("stnectaire melty=4 hardness=three");
177 cl
->next
= options
->ServerTransportOptions
;
178 options
->ServerTransportOptions
= cl
;
180 cl
= tor_malloc_zero(sizeof(config_line_t
));
181 cl
->value
= tor_strdup("pepperjack melty=12 hardness=five");
182 cl
->next
= options
->ServerTransportOptions
;
183 options
->ServerTransportOptions
= cl
;
185 opt_str
= get_transport_options_for_server_proxy(mp
);
186 tt_str_op(opt_str
, OP_EQ
,
187 "gruyere:melty=10;gruyere:hardness=se\\;ven;"
188 "stnectaire:melty=4;stnectaire:hardness=three");
192 config_free_lines(cl
);
193 managed_proxy_destroy(mp
, 0);
194 smartlist_free(transport_list
);
198 test_pt_protocol(void *arg
)
202 managed_proxy_t
*mp
= tor_malloc_zero(sizeof(managed_proxy_t
));
204 mp
->conf_state
= PT_PROTO_LAUNCHED
;
205 mp
->transports
= smartlist_new();
206 mp
->argv
= tor_calloc(2, sizeof(char *));
207 mp
->argv
[0] = tor_strdup("<testcase>");
209 /* various wrong protocol runs: */
211 strlcpy(line
,"VERSION 1",sizeof(line
));
212 handle_proxy_line(line
, mp
);
213 tt_assert(mp
->conf_state
== PT_PROTO_ACCEPTING_METHODS
);
215 strlcpy(line
,"VERSION 1",sizeof(line
));
216 handle_proxy_line(line
, mp
);
217 tt_assert(mp
->conf_state
== PT_PROTO_BROKEN
);
221 strlcpy(line
,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line
));
222 handle_proxy_line(line
, mp
);
223 tt_assert(mp
->conf_state
== PT_PROTO_BROKEN
);
227 /* correct protocol run: */
228 strlcpy(line
,"VERSION 1",sizeof(line
));
229 handle_proxy_line(line
, mp
);
230 tt_assert(mp
->conf_state
== PT_PROTO_ACCEPTING_METHODS
);
232 strlcpy(line
,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line
));
233 handle_proxy_line(line
, mp
);
234 tt_assert(mp
->conf_state
== PT_PROTO_ACCEPTING_METHODS
);
236 strlcpy(line
,"CMETHOD-ERROR fakename not supported",sizeof(line
));
237 handle_proxy_line(line
, mp
);
238 tt_assert(mp
->conf_state
== PT_PROTO_ACCEPTING_METHODS
);
240 strlcpy(line
,"CMETHODS DONE",sizeof(line
));
241 handle_proxy_line(line
, mp
);
242 tt_assert(mp
->conf_state
== PT_PROTO_CONFIGURED
);
246 smartlist_free(mp
->transports
);
247 tor_free(mp
->argv
[0]);
253 test_pt_get_extrainfo_string(void *arg
)
255 managed_proxy_t
*mp1
= NULL
, *mp2
= NULL
;
256 char **argv1
, **argv2
;
257 smartlist_t
*t1
= smartlist_new(), *t2
= smartlist_new();
262 argv1
= tor_malloc_zero(sizeof(char*)*3);
263 argv1
[0] = tor_strdup("ewige");
264 argv1
[1] = tor_strdup("Blumenkraft");
266 argv2
= tor_malloc_zero(sizeof(char*)*4);
267 argv2
[0] = tor_strdup("und");
268 argv2
[1] = tor_strdup("ewige");
269 argv2
[2] = tor_strdup("Schlangenkraft");
272 mp1
= managed_proxy_create(t1
, argv1
, 1);
273 mp2
= managed_proxy_create(t2
, argv2
, 1);
275 r
= parse_smethod_line("SMETHOD hagbard 127.0.0.1:5555", mp1
);
276 tt_int_op(r
, OP_EQ
, 0);
277 r
= parse_smethod_line("SMETHOD celine 127.0.0.1:1723 ARGS:card=no-enemy",
279 tt_int_op(r
, OP_EQ
, 0);
281 /* Force these proxies to look "completed" or they won't generate output. */
282 mp1
->conf_state
= mp2
->conf_state
= PT_PROTO_COMPLETED
;
284 s
= pt_get_extra_info_descriptor_string();
287 "transport hagbard 127.0.0.1:5555\n"
288 "transport celine 127.0.0.1:1723 card=no-enemy\n");
291 /* XXXX clean up better */
298 process_read_stdout_replacement(process_t
*process
, buf_t
*buffer
)
301 static int times_called
= 0;
303 /* Generate some dummy CMETHOD lines the first 5 times. The 6th
304 time, send 'CMETHODS DONE' to finish configuring the proxy. */
307 if (times_called
<= 5) {
308 buf_add_printf(buffer
, "SMETHOD mock%d 127.0.0.1:555%d\n",
309 times_called
, times_called
);
310 } else if (times_called
<= 6) {
311 buf_add_string(buffer
, "SMETHODS DONE\n");
312 } else if (times_called
<= 7) {
313 buf_add_string(buffer
, "LOG SEVERITY=error MESSAGE=\"Oh noes, something "
314 "bad happened. What do we do!?\"\n");
315 buf_add_string(buffer
, "LOG SEVERITY=warning MESSAGE=\"warning msg\"\n");
316 buf_add_string(buffer
, "LOG SEVERITY=notice MESSAGE=\"notice msg\"\n");
317 buf_add_string(buffer
, "LOG SEVERITY=info MESSAGE=\"info msg\"\n");
318 buf_add_string(buffer
, "LOG SEVERITY=debug MESSAGE=\"debug msg\"\n");
319 } else if (times_called
<= 8) {
320 buf_add_string(buffer
, "STATUS TRANSPORT=a K_1=a K_2=b K_3=\"foo bar\"\n");
321 buf_add_string(buffer
, "STATUS TRANSPORT=b K_1=a K_2=b K_3=\"foo bar\"\n");
322 buf_add_string(buffer
, "STATUS TRANSPORT=c K_1=a K_2=b K_3=\"foo bar\"\n");
325 return (int)buf_datalen(buffer
);
328 static or_state_t
*dummy_state
= NULL
;
331 get_or_state_replacement(void)
336 static int controlevent_n
= 0;
337 static uint16_t controlevent_event
= 0;
338 static smartlist_t
*controlevent_msgs
= NULL
;
341 queue_control_event_string_replacement(uint16_t event
, char *msg
)
344 controlevent_event
= event
;
345 if (!controlevent_msgs
)
346 controlevent_msgs
= smartlist_new();
347 smartlist_add(controlevent_msgs
, msg
);
350 /* Test the configure_proxy() function. */
352 test_pt_configure_proxy(void *arg
)
355 managed_proxy_t
*mp
= NULL
;
358 dummy_state
= or_state_new();
360 MOCK(process_read_stdout
, process_read_stdout_replacement
);
362 get_or_state_replacement
);
363 MOCK(queue_control_event_string
,
364 queue_control_event_string_replacement
);
366 control_testing_set_global_event_mask(EVENT_TRANSPORT_LAUNCHED
);
368 mp
= tor_malloc_zero(sizeof(managed_proxy_t
));
369 mp
->conf_state
= PT_PROTO_ACCEPTING_METHODS
;
370 mp
->transports
= smartlist_new();
371 mp
->transports_to_launch
= smartlist_new();
372 mp
->argv
= tor_malloc_zero(sizeof(char*)*2);
373 mp
->argv
[0] = tor_strdup("<testcase>");
376 /* Configure the process. */
377 mp
->process
= process_new("");
378 process_set_stdout_read_callback(mp
->process
, managed_proxy_stdout_callback
);
379 process_set_data(mp
->process
, mp
);
381 /* Test the return value of configure_proxy() by calling it some
382 times while it is uninitialized and then finally finalizing its
384 for (i
= 0 ; i
< 5 ; i
++) {
385 /* force a read from our mocked stdout reader. */
386 process_notify_event_stdout(mp
->process
);
387 /* try to configure our proxy. */
388 retval
= configure_proxy(mp
);
389 /* retval should be zero because proxy hasn't finished configuring yet */
390 tt_int_op(retval
, OP_EQ
, 0);
391 /* check the number of registered transports */
392 tt_int_op(smartlist_len(mp
->transports
), OP_EQ
, i
+1);
393 /* check that the mp is still waiting for transports */
394 tt_assert(mp
->conf_state
== PT_PROTO_ACCEPTING_METHODS
);
397 /* Get the SMETHOD DONE written to the process. */
398 process_notify_event_stdout(mp
->process
);
400 /* this last configure_proxy() should finalize the proxy configuration. */
401 retval
= configure_proxy(mp
);
402 /* retval should be 1 since the proxy finished configuring */
403 tt_int_op(retval
, OP_EQ
, 1);
404 /* check the mp state */
405 tt_assert(mp
->conf_state
== PT_PROTO_COMPLETED
);
407 tt_int_op(controlevent_n
, OP_EQ
, 5);
408 tt_int_op(controlevent_event
, OP_EQ
, EVENT_TRANSPORT_LAUNCHED
);
409 tt_int_op(smartlist_len(controlevent_msgs
), OP_EQ
, 5);
410 smartlist_sort_strings(controlevent_msgs
);
411 tt_str_op(smartlist_get(controlevent_msgs
, 0), OP_EQ
,
412 "650 TRANSPORT_LAUNCHED server mock1 127.0.0.1 5551\r\n");
413 tt_str_op(smartlist_get(controlevent_msgs
, 1), OP_EQ
,
414 "650 TRANSPORT_LAUNCHED server mock2 127.0.0.1 5552\r\n");
415 tt_str_op(smartlist_get(controlevent_msgs
, 2), OP_EQ
,
416 "650 TRANSPORT_LAUNCHED server mock3 127.0.0.1 5553\r\n");
417 tt_str_op(smartlist_get(controlevent_msgs
, 3), OP_EQ
,
418 "650 TRANSPORT_LAUNCHED server mock4 127.0.0.1 5554\r\n");
419 tt_str_op(smartlist_get(controlevent_msgs
, 4), OP_EQ
,
420 "650 TRANSPORT_LAUNCHED server mock5 127.0.0.1 5555\r\n");
422 /* Get the log message out. */
423 setup_full_capture_of_logs(LOG_ERR
);
424 process_notify_event_stdout(mp
->process
);
425 expect_single_log_msg_containing("Oh noes, something bad happened");
426 teardown_capture_of_logs();
428 tt_int_op(controlevent_n
, OP_EQ
, 10);
429 tt_int_op(controlevent_event
, OP_EQ
, EVENT_PT_LOG
);
430 tt_int_op(smartlist_len(controlevent_msgs
), OP_EQ
, 10);
431 tt_str_op(smartlist_get(controlevent_msgs
, 5), OP_EQ
,
432 "650 PT_LOG PT=<testcase> SEVERITY=error "
433 "MESSAGE=\"Oh noes, "
434 "something bad happened. What do we do!?\"\r\n");
435 tt_str_op(smartlist_get(controlevent_msgs
, 6), OP_EQ
,
436 "650 PT_LOG PT=<testcase> SEVERITY=warning "
437 "MESSAGE=\"warning msg\"\r\n");
438 tt_str_op(smartlist_get(controlevent_msgs
, 7), OP_EQ
,
439 "650 PT_LOG PT=<testcase> SEVERITY=notice "
440 "MESSAGE=\"notice msg\"\r\n");
441 tt_str_op(smartlist_get(controlevent_msgs
, 8), OP_EQ
,
442 "650 PT_LOG PT=<testcase> SEVERITY=info "
443 "MESSAGE=\"info msg\"\r\n");
444 tt_str_op(smartlist_get(controlevent_msgs
, 9), OP_EQ
,
445 "650 PT_LOG PT=<testcase> SEVERITY=debug "
446 "MESSAGE=\"debug msg\"\r\n");
448 /* Get the STATUS messages out. */
449 process_notify_event_stdout(mp
->process
);
451 tt_int_op(controlevent_n
, OP_EQ
, 13);
452 tt_int_op(controlevent_event
, OP_EQ
, EVENT_PT_STATUS
);
453 tt_int_op(smartlist_len(controlevent_msgs
), OP_EQ
, 13);
455 tt_str_op(smartlist_get(controlevent_msgs
, 10), OP_EQ
,
457 "PT=<testcase> TRANSPORT=a K_1=a K_2=b K_3=\"foo bar\"\r\n");
458 tt_str_op(smartlist_get(controlevent_msgs
, 11), OP_EQ
,
460 "PT=<testcase> TRANSPORT=b K_1=a K_2=b K_3=\"foo bar\"\r\n");
461 tt_str_op(smartlist_get(controlevent_msgs
, 12), OP_EQ
,
463 "PT=<testcase> TRANSPORT=c K_1=a K_2=b K_3=\"foo bar\"\r\n");
465 { /* check that the transport info were saved properly in the tor state */
466 config_line_t
*transport_in_state
= NULL
;
467 smartlist_t
*transport_info_sl
= smartlist_new();
468 char *name_of_transport
= NULL
;
469 char *bindaddr
= NULL
;
471 /* Get the bindaddr for "mock1" and check it against the bindaddr
472 that the mocked tor_get_lines_from_handle() generated. */
473 transport_in_state
= get_transport_in_state_by_name("mock1");
474 tt_assert(transport_in_state
);
475 smartlist_split_string(transport_info_sl
, transport_in_state
->value
,
477 name_of_transport
= smartlist_get(transport_info_sl
, 0);
478 bindaddr
= smartlist_get(transport_info_sl
, 1);
479 tt_str_op(name_of_transport
, OP_EQ
, "mock1");
480 tt_str_op(bindaddr
, OP_EQ
, "127.0.0.1:5551");
482 SMARTLIST_FOREACH(transport_info_sl
, char *, cp
, tor_free(cp
));
483 smartlist_free(transport_info_sl
);
487 teardown_capture_of_logs();
488 or_state_free(dummy_state
);
489 UNMOCK(process_read_stdout
);
490 UNMOCK(get_or_state
);
491 UNMOCK(queue_control_event_string
);
492 if (controlevent_msgs
) {
493 SMARTLIST_FOREACH(controlevent_msgs
, char *, cp
, tor_free(cp
));
494 smartlist_free(controlevent_msgs
);
495 controlevent_msgs
= NULL
;
497 if (mp
->transports
) {
498 SMARTLIST_FOREACH(mp
->transports
, transport_t
*, t
, transport_free(t
));
499 smartlist_free(mp
->transports
);
501 smartlist_free(mp
->transports_to_launch
);
502 process_free(mp
->process
);
503 tor_free(mp
->argv
[0]);
508 /* Test the get_pt_proxy_uri() function. */
510 test_get_pt_proxy_uri(void *arg
)
512 or_options_t
*options
= get_options_mutable();
517 /* Test with no proxy. */
518 uri
= get_pt_proxy_uri();
519 tt_ptr_op(uri
, OP_EQ
, NULL
);
521 /* Test with a SOCKS4 proxy. */
522 options
->Socks4Proxy
= tor_strdup("192.0.2.1:1080");
523 ret
= tor_addr_port_lookup(options
->Socks4Proxy
,
524 &options
->Socks4ProxyAddr
,
525 &options
->Socks4ProxyPort
);
526 tt_int_op(ret
, OP_EQ
, 0);
527 uri
= get_pt_proxy_uri();
528 tt_str_op(uri
, OP_EQ
, "socks4a://192.0.2.1:1080");
530 tor_free(options
->Socks4Proxy
);
532 /* Test with a SOCKS5 proxy, no username/password. */
533 options
->Socks5Proxy
= tor_strdup("192.0.2.1:1080");
534 ret
= tor_addr_port_lookup(options
->Socks5Proxy
,
535 &options
->Socks5ProxyAddr
,
536 &options
->Socks5ProxyPort
);
537 tt_int_op(ret
, OP_EQ
, 0);
538 uri
= get_pt_proxy_uri();
539 tt_str_op(uri
, OP_EQ
, "socks5://192.0.2.1:1080");
542 /* Test with a SOCKS5 proxy, with username/password. */
543 options
->Socks5ProxyUsername
= tor_strdup("hwest");
544 options
->Socks5ProxyPassword
= tor_strdup("r34n1m470r");
545 uri
= get_pt_proxy_uri();
546 tt_str_op(uri
, OP_EQ
, "socks5://hwest:r34n1m470r@192.0.2.1:1080");
548 tor_free(options
->Socks5Proxy
);
549 tor_free(options
->Socks5ProxyUsername
);
550 tor_free(options
->Socks5ProxyPassword
);
552 /* Test with a HTTPS proxy, no authenticator. */
553 options
->HTTPSProxy
= tor_strdup("192.0.2.1:80");
554 ret
= tor_addr_port_lookup(options
->HTTPSProxy
,
555 &options
->HTTPSProxyAddr
,
556 &options
->HTTPSProxyPort
);
557 tt_int_op(ret
, OP_EQ
, 0);
558 uri
= get_pt_proxy_uri();
559 tt_str_op(uri
, OP_EQ
, "http://192.0.2.1:80");
562 /* Test with a HTTPS proxy, with authenticator. */
563 options
->HTTPSProxyAuthenticator
= tor_strdup("hwest:r34n1m470r");
564 uri
= get_pt_proxy_uri();
565 tt_str_op(uri
, OP_EQ
, "http://hwest:r34n1m470r@192.0.2.1:80");
567 tor_free(options
->HTTPSProxy
);
568 tor_free(options
->HTTPSProxyAuthenticator
);
570 /* Token nod to the fact that IPv6 exists. */
571 options
->Socks4Proxy
= tor_strdup("[2001:db8::1]:1080");
572 ret
= tor_addr_port_lookup(options
->Socks4Proxy
,
573 &options
->Socks4ProxyAddr
,
574 &options
->Socks4ProxyPort
);
575 tt_int_op(ret
, OP_EQ
, 0);
576 uri
= get_pt_proxy_uri();
577 tt_str_op(uri
, OP_EQ
, "socks4a://[2001:db8::1]:1080");
579 tor_free(options
->Socks4Proxy
);
587 #define PT_LEGACY(name) \
588 { (#name), test_pt_ ## name , 0, NULL, NULL }
591 struct testcase_t pt_tests
[] = {
594 { "get_transport_options", test_pt_get_transport_options
, TT_FORK
,
596 { "get_extrainfo_string", test_pt_get_extrainfo_string
, TT_FORK
,
598 { "configure_proxy",test_pt_configure_proxy
, TT_FORK
,
600 { "get_pt_proxy_uri", test_get_pt_proxy_uri
, TT_FORK
,