1 /**
2  * Tests all Network implementations.
3  *
4  * License:
5  *   This Source Code Form is subject to the terms of
6  *   the Mozilla Public License, v. 2.0. If a copy of
7  *   the MPL was not distributed with this file, You
8  *   can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * Authors:
11  *   Vladimir Panteleev <ae@cy.md>
12  */
13 
14 module ae.sys.net.test;
15 
16 import std.array;
17 import std.file;
18 import std.process : environment;
19 
20 import ae.net.http.common;
21 import ae.sys.data;
22 
23 static import ae.sys.net.ae;
24 static import ae.sys.net.curl;
25 version(Windows)
26 static import ae.sys.net.wininet;
27 static import ae.sys.net.cachedcurl;
28 
29 debug static import std.stdio;
30 
31 /// Test endpoint base.
32 /// Server-side test scripts are here:
33 /// https://gist.github.com/58df32ed1dbe64fffd0545f87d9321ad
34 string testBaseURL = "http://thecybershadow.net/d/nettest/"; // (must be HTTP)
35 
36 /// Test a `ae.sys.net.Network` implementation.
37 void test(string moduleName, string className)()
38 {
39 	debug std.stdio.stderr.writeln("Testing " ~ className);
40 
41 	mixin("import ae.sys.net." ~ moduleName ~ ";");
42 	mixin("alias Net = " ~ className ~ ";");
43 	auto net = new Net();
44 
45 	debug std.stdio.stderr.writeln(" - getFile");
46 	{
47 		assert(net.getFile(testBaseURL ~ "testUrl1") == "Hello world\n");
48 	}
49 
50 	debug std.stdio.stderr.writeln(" - downloadFile");
51 	{
52 		enum fn = "test.txt";
53 		if (fn.exists) fn.remove();
54 		scope(exit) if (fn.exists) fn.remove();
55 
56 		net.downloadFile(testBaseURL ~ "testUrl1", fn);
57 		assert(fn.readText() == "Hello world\n");
58 	}
59 
60 	debug std.stdio.stderr.writeln(" - urlOK");
61 	{
62 		assert( net.urlOK(testBaseURL ~ "testUrl1"));
63 		assert(!net.urlOK(testBaseURL ~ "testUrlNX"));
64 		static if (moduleName == "wininet")
65 			assert( net.urlOK(testBaseURL.replace("http://", "https://") ~  "testUrl1"));
66 	}
67 
68 	debug std.stdio.stderr.writeln(" - resolveRedirect");
69 	{
70 		auto result = net.resolveRedirect(testBaseURL ~ "testUrl3");
71 		assert(result == testBaseURL ~ "testUrl2", result);
72 	}
73 
74 	debug std.stdio.stderr.writeln(" - post");
75 	{
76 		auto result = cast(string)net.post(testBaseURL ~ "testUrl4", "Hello world\n");
77 		assert(result == "Hello world\n", result);
78 	}
79 
80 	debug std.stdio.stderr.writeln(" - httpRequest");
81 	{
82 		auto request = new HttpRequest(testBaseURL ~ "testUrl5");
83 		request.method = "PUT";
84 		request.headers.add("Test-Request-Header", "foo");
85 		request.data = DataVec(Data("bar"));
86 		auto response = net.httpRequest(request);
87 		assert(response.status == HttpStatusCode.Accepted);
88 		assert(response.statusMessage == "Custom Message");
89 		assert(response.data.joinToHeap == "PUT foo bar");
90 		assert(response.headers["Test-Response-Header"] == "baz");
91 	}
92 }
93 
94 unittest
95 {
96 	// Don't do network requests on the project tester.
97 	// See:
98 	// - https://github.com/CyberShadow/ae/issues/30
99 	// - https://github.com/dlang/dmd/pull/9618#issuecomment-483214780
100 	if (environment.get("BUILDKITE_AGENT_NAME"))
101 		return;
102 
103 	test!("ae", "AENetwork");
104 	test!("curl", "CurlNetwork");
105 	version(Windows)
106 	test!("wininet", "WinINetNetwork");
107 
108 	import ae.utils.meta : classInit;
109 	auto cacheDir = classInit!(ae.sys.net.cachedcurl.CachedCurlNetwork).cacheDir;
110 	if (cacheDir.exists) cacheDir.rmdirRecurse();
111 	scope(exit) if (cacheDir.exists) cacheDir.rmdirRecurse();
112 	test!("cachedcurl", "CachedCurlNetwork");
113 }