1 // OpenTween - Client of Twitter
2 // Copyright (c) 2014 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
5 // This file is part of OpenTween.
7 // This program is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General public License as published by the Free
9 // Software Foundation; either version 3 of the License, or (at your option)
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General public License
17 // You should have received a copy of the GNU General public License along
18 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
19 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 // Boston, MA 02110-1301, USA.
23 using System.Collections.Generic;
26 using System.Net.Http;
28 using System.Threading;
29 using System.Threading.Tasks;
31 using Xunit.Extensions;
35 public class ShortUrlTest
38 public async Task ExpandUrlAsync_Test()
40 var handler = new HttpMessageHandlerMock();
41 using var http = new HttpClient(handler);
42 var shortUrl = new ShortUrl(http);
44 // https://t.co/hoge1 -> http://example.com/hoge2
47 Assert.Equal(HttpMethod.Head, x.Method);
48 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
50 return this.CreateRedirectResponse("http://example.com/hoge2");
53 Assert.Equal(new Uri("http://example.com/hoge2"),
54 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1")));
56 Assert.Equal(0, handler.QueueCount);
60 public async Task ExpandUrlAsync_IrregularUrlTest()
62 var handler = new HttpMessageHandlerMock();
63 using var http = new HttpClient(handler);
64 var shortUrl = new ShortUrl(http);
66 // https://www.flickr.com/photo.gne?short=hoge -> /photos/foo/11111/
69 Assert.Equal(HttpMethod.Head, x.Method);
70 Assert.Equal(new Uri("https://www.flickr.com/photo.gne?short=hoge"), x.RequestUri);
72 return this.CreateRedirectResponse("/photos/foo/11111/", UriKind.Relative);
75 Assert.Equal(new Uri("https://www.flickr.com/photos/foo/11111/"),
76 await shortUrl.ExpandUrlAsync(new Uri("https://www.flickr.com/photo.gne?short=hoge")));
78 Assert.Equal(0, handler.QueueCount);
82 public async Task ExpandUrlAsync_DisableExpandingTest()
84 var handler = new HttpMessageHandlerMock();
85 using var http = new HttpClient(handler);
86 var shortUrl = new ShortUrl(http);
88 shortUrl.DisableExpanding = true;
90 // https://t.co/hoge1 -> http://example.com/hoge2
95 return this.CreateRedirectResponse("http://example.com/hoge2");
98 Assert.Equal(new Uri("https://t.co/hoge1"),
99 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1")));
101 Assert.Equal(1, handler.QueueCount);
105 public async Task ExpandUrlAsync_RecursiveTest()
107 var handler = new HttpMessageHandlerMock();
108 using var http = new HttpClient(handler);
109 var shortUrl = new ShortUrl(http);
111 // https://t.co/hoge1 -> https://bit.ly/hoge2
114 Assert.Equal(HttpMethod.Head, x.Method);
115 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
117 return this.CreateRedirectResponse("https://bit.ly/hoge2");
120 // https://bit.ly/hoge2 -> http://example.com/hoge3
123 Assert.Equal(HttpMethod.Head, x.Method);
124 Assert.Equal(new Uri("https://bit.ly/hoge2"), x.RequestUri);
126 return this.CreateRedirectResponse("http://example.com/hoge3");
129 Assert.Equal(new Uri("http://example.com/hoge3"),
130 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1")));
132 Assert.Equal(0, handler.QueueCount);
136 public async Task ExpandUrlAsync_RecursiveLimitTest()
138 var handler = new HttpMessageHandlerMock();
139 using var http = new HttpClient(handler);
140 var shortUrl = new ShortUrl(http);
142 // https://t.co/hoge1 -> https://bit.ly/hoge2
145 Assert.Equal(HttpMethod.Head, x.Method);
146 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
148 return this.CreateRedirectResponse("https://bit.ly/hoge2");
151 // https://bit.ly/hoge2 -> https://tinyurl.com/hoge3
154 Assert.Equal(HttpMethod.Head, x.Method);
155 Assert.Equal(new Uri("https://bit.ly/hoge2"), x.RequestUri);
157 return this.CreateRedirectResponse("https://tinyurl.com/hoge3");
160 // https://tinyurl.com/hoge3 -> http://example.com/hoge4
165 return this.CreateRedirectResponse("http://example.com/hoge4");
168 Assert.Equal(new Uri("https://tinyurl.com/hoge3"),
169 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1"), redirectLimit: 2));
171 Assert.Equal(1, handler.QueueCount);
175 public async Task ExpandUrlAsync_UpgradeToHttpsTest()
177 var handler = new HttpMessageHandlerMock();
178 using var http = new HttpClient(handler);
179 var shortUrl = new ShortUrl(http);
181 // http://t.co/hoge -> http://example.com/hoge
184 // https:// に変換されてリクエストが送信される
185 Assert.Equal(HttpMethod.Head, x.Method);
186 Assert.Equal(new Uri("https://t.co/hoge"), x.RequestUri);
188 return this.CreateRedirectResponse("http://example.com/hoge");
191 Assert.Equal(new Uri("http://example.com/hoge"),
192 await shortUrl.ExpandUrlAsync(new Uri("http://t.co/hoge")));
194 Assert.Equal(0, handler.QueueCount);
198 public async Task ExpandUrlAsync_InsecureDomainTest()
200 var handler = new HttpMessageHandlerMock();
201 using var http = new HttpClient(handler);
202 var shortUrl = new ShortUrl(http);
204 // http://tinami.jp/hoge -> http://example.com/hoge
207 // HTTPS非対応のドメインは http:// のままリクエストが送信される
208 Assert.Equal(HttpMethod.Head, x.Method);
209 Assert.Equal(new Uri("http://tinami.jp/hoge"), x.RequestUri);
211 return this.CreateRedirectResponse("http://example.com/hoge");
214 Assert.Equal(new Uri("http://example.com/hoge"),
215 await shortUrl.ExpandUrlAsync(new Uri("http://tinami.jp/hoge")));
217 Assert.Equal(0, handler.QueueCount);
221 public async Task ExpandUrlAsync_RelativeUriTest()
223 var handler = new HttpMessageHandlerMock();
224 using var http = new HttpClient(handler);
225 var shortUrl = new ShortUrl(http);
231 return this.CreateRedirectResponse("");
234 // 相対 URI に対しては何も行わない
235 Assert.Equal(new Uri("./foo/bar", UriKind.Relative),
236 await shortUrl.ExpandUrlAsync(new Uri("./foo/bar", UriKind.Relative)));
238 Assert.Equal(1, handler.QueueCount);
242 public async Task ExpandUrlAsync_RelativeRedirectTest()
244 var handler = new HttpMessageHandlerMock();
245 using var http = new HttpClient(handler);
246 var shortUrl = new ShortUrl(http);
248 // Location に相対 URL を指定したリダイレクト (テストに使う URL は適当)
249 // https://t.co/hogehoge -> /tetetete
252 Assert.Equal(HttpMethod.Head, x.Method);
253 Assert.Equal(new Uri("https://t.co/hogehoge"), x.RequestUri);
255 return this.CreateRedirectResponse("/tetetete", UriKind.Relative);
258 // https://t.co/tetetete -> http://example.com/tetetete
261 Assert.Equal(HttpMethod.Head, x.Method);
262 Assert.Equal(new Uri("https://t.co/tetetete"), x.RequestUri);
264 return this.CreateRedirectResponse("http://example.com/tetetete");
267 Assert.Equal(new Uri("http://example.com/tetetete"),
268 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hogehoge")));
270 Assert.Equal(0, handler.QueueCount);
274 public async Task ExpandUrlAsync_String_Test()
276 var handler = new HttpMessageHandlerMock();
277 using var http = new HttpClient(handler);
278 var shortUrl = new ShortUrl(http);
280 // https://t.co/hoge1 -> http://example.com/hoge2
283 Assert.Equal(HttpMethod.Head, x.Method);
284 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
286 return this.CreateRedirectResponse("http://example.com/hoge2");
289 Assert.Equal("http://example.com/hoge2",
290 await shortUrl.ExpandUrlAsync("https://t.co/hoge1"));
292 Assert.Equal(0, handler.QueueCount);
296 public async Task ExpandUrlAsync_String_SchemeLessUrlTest()
298 var handler = new HttpMessageHandlerMock();
299 using var http = new HttpClient(handler);
300 var shortUrl = new ShortUrl(http);
302 // https://t.co/hoge1 -> http://example.com/hoge2
305 Assert.Equal(HttpMethod.Head, x.Method);
306 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
308 return this.CreateRedirectResponse("http://example.com/hoge2");
312 Assert.Equal("http://example.com/hoge2",
313 await shortUrl.ExpandUrlAsync("t.co/hoge1"));
315 Assert.Equal(0, handler.QueueCount);
319 public async Task ExpandUrlAsync_String_InvalidUrlTest()
321 var handler = new HttpMessageHandlerMock();
322 using var http = new HttpClient(handler);
323 var shortUrl = new ShortUrl(http);
329 return this.CreateRedirectResponse("http://example.com/hoge2");
333 Assert.Equal("..hogehoge..", await shortUrl.ExpandUrlAsync("..hogehoge.."));
335 Assert.Equal(1, handler.QueueCount);
339 public async Task ExpandUrlAsync_HttpErrorTest()
341 var handler = new HttpMessageHandlerMock();
342 using var http = new HttpClient(handler);
343 var shortUrl = new ShortUrl(http);
345 // https://t.co/hoge1 -> 503 Service Unavailable
348 return new HttpResponseMessage(HttpStatusCode.ServiceUnavailable);
351 Assert.Equal(new Uri("https://t.co/hoge1"),
352 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1")));
354 Assert.Equal(0, handler.QueueCount);
358 public async Task ExpandUrlHtmlAsync_Test()
360 var handler = new HttpMessageHandlerMock();
361 using var http = new HttpClient(handler);
362 var shortUrl = new ShortUrl(http);
364 // https://t.co/hoge1 -> http://example.com/hoge2
367 Assert.Equal(HttpMethod.Head, x.Method);
368 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
370 return this.CreateRedirectResponse("http://example.com/hoge2");
373 Assert.Equal("""<a href="http://example.com/hoge2">hogehoge</a>""",
374 await shortUrl.ExpandUrlHtmlAsync("""<a href="https://t.co/hoge1">hogehoge</a>"""));
376 Assert.Equal(0, handler.QueueCount);
380 public async Task ExpandUrlHtmlAsync_RelativeUriTest()
382 var handler = new HttpMessageHandlerMock();
383 using var http = new HttpClient(handler);
384 var shortUrl = new ShortUrl(http);
390 return this.CreateRedirectResponse("http://example.com/hoge");
393 Assert.Equal("""<a href="./hoge">hogehoge</a>""",
394 await shortUrl.ExpandUrlHtmlAsync("""<a href="./hoge">hogehoge</a>"""));
396 Assert.Equal(1, handler.QueueCount);
399 private HttpResponseMessage CreateRedirectResponse(string uriStr)
400 => this.CreateRedirectResponse(uriStr, UriKind.Absolute);
402 private HttpResponseMessage CreateRedirectResponse(string uriStr, UriKind uriKind)
404 var response = new HttpResponseMessage(HttpStatusCode.TemporaryRedirect);
405 response.Headers.Location = new Uri(uriStr, uriKind);
410 public async Task ShortenUrlAsync_TinyUrlTest()
412 var handler = new HttpMessageHandlerMock();
413 using var http = new HttpClient(handler);
414 var shortUrl = new ShortUrl(http);
416 handler.Enqueue(async x =>
418 Assert.Equal(HttpMethod.Post, x.Method);
419 Assert.Equal(new Uri("https://tinyurl.com/api-create.php"), x.RequestUri);
420 Assert.Equal("url=http%3A%2F%2Fexample.com%2Fhogehogehoge", await x.Content.ReadAsStringAsync());
422 return new HttpResponseMessage(HttpStatusCode.OK)
424 Content = new ByteArrayContent(Encoding.UTF8.GetBytes("http://tinyurl.com/hoge")),
428 Assert.Equal(new Uri("https://tinyurl.com/hoge"),
429 await shortUrl.ShortenUrlAsync(MyCommon.UrlConverter.TinyUrl, new Uri("http://example.com/hogehogehoge")));
431 Assert.Equal(0, handler.QueueCount);
435 public async Task ShortenUrlAsync_UxnuUrlTest()
437 var handler = new HttpMessageHandlerMock();
438 using var http = new HttpClient(handler);
439 var shortUrl = new ShortUrl(http);
443 Assert.Equal(HttpMethod.Get, x.Method);
444 Assert.Equal("https://ux.nu/api/short?format=plain&url=http:%2F%2Fexample.com%2Fhogehoge",
445 x.RequestUri.AbsoluteUri);
447 return new HttpResponseMessage(HttpStatusCode.OK)
449 Content = new ByteArrayContent(Encoding.UTF8.GetBytes("https://ux.nu/hoge")),
453 Assert.Equal(new Uri("https://ux.nu/hoge"),
454 await shortUrl.ShortenUrlAsync(MyCommon.UrlConverter.Uxnu, new Uri("http://example.com/hogehoge")));
456 Assert.Equal(0, handler.QueueCount);