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))
43 var shortUrl = new ShortUrl(http);
45 // https://t.co/hoge1 -> http://example.com/hoge2
48 Assert.Equal(HttpMethod.Head, x.Method);
49 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
51 return this.CreateRedirectResponse("http://example.com/hoge2");
54 Assert.Equal(new Uri("http://example.com/hoge2"),
55 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1")));
57 Assert.Equal(0, handler.QueueCount);
62 public async Task ExpandUrlAsync_IrregularUrlTest()
64 var handler = new HttpMessageHandlerMock();
65 using (var http = new HttpClient(handler))
67 var shortUrl = new ShortUrl(http);
69 // https://www.flickr.com/photo.gne?short=hoge -> /photos/foo/11111/
72 Assert.Equal(HttpMethod.Head, x.Method);
73 Assert.Equal(new Uri("https://www.flickr.com/photo.gne?short=hoge"), x.RequestUri);
75 return this.CreateRedirectResponse("/photos/foo/11111/", UriKind.Relative);
78 Assert.Equal(new Uri("https://www.flickr.com/photos/foo/11111/"),
79 await shortUrl.ExpandUrlAsync(new Uri("https://www.flickr.com/photo.gne?short=hoge")));
81 Assert.Equal(0, handler.QueueCount);
86 public async Task ExpandUrlAsync_DisableExpandingTest()
88 var handler = new HttpMessageHandlerMock();
89 using (var http = new HttpClient(handler))
91 var shortUrl = new ShortUrl(http);
93 shortUrl.DisableExpanding = true;
95 // https://t.co/hoge1 -> http://example.com/hoge2
100 return this.CreateRedirectResponse("http://example.com/hoge2");
103 Assert.Equal(new Uri("https://t.co/hoge1"),
104 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1")));
106 Assert.Equal(1, handler.QueueCount);
111 public async Task ExpandUrlAsync_RecursiveTest()
113 var handler = new HttpMessageHandlerMock();
114 using (var http = new HttpClient(handler))
116 var shortUrl = new ShortUrl(http);
118 // https://t.co/hoge1 -> https://bit.ly/hoge2
121 Assert.Equal(HttpMethod.Head, x.Method);
122 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
124 return this.CreateRedirectResponse("https://bit.ly/hoge2");
127 // https://bit.ly/hoge2 -> http://example.com/hoge3
130 Assert.Equal(HttpMethod.Head, x.Method);
131 Assert.Equal(new Uri("https://bit.ly/hoge2"), x.RequestUri);
133 return this.CreateRedirectResponse("http://example.com/hoge3");
136 Assert.Equal(new Uri("http://example.com/hoge3"),
137 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1")));
139 Assert.Equal(0, handler.QueueCount);
144 public async Task ExpandUrlAsync_RecursiveLimitTest()
146 var handler = new HttpMessageHandlerMock();
147 using (var http = new HttpClient(handler))
149 var shortUrl = new ShortUrl(http);
151 // https://t.co/hoge1 -> https://bit.ly/hoge2
154 Assert.Equal(HttpMethod.Head, x.Method);
155 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
157 return this.CreateRedirectResponse("https://bit.ly/hoge2");
160 // https://bit.ly/hoge2 -> https://tinyurl.com/hoge3
163 Assert.Equal(HttpMethod.Head, x.Method);
164 Assert.Equal(new Uri("https://bit.ly/hoge2"), x.RequestUri);
166 return this.CreateRedirectResponse("https://tinyurl.com/hoge3");
169 // https://tinyurl.com/hoge3 -> http://example.com/hoge4
174 return this.CreateRedirectResponse("http://example.com/hoge4");
177 Assert.Equal(new Uri("https://tinyurl.com/hoge3"),
178 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1"), redirectLimit: 2));
180 Assert.Equal(1, handler.QueueCount);
185 public async Task ExpandUrlAsync_UpgradeToHttpsTest()
187 var handler = new HttpMessageHandlerMock();
188 using (var http = new HttpClient(handler))
190 var shortUrl = new ShortUrl(http);
192 // http://t.co/hoge -> http://example.com/hoge
195 // https:// に変換されてリクエストが送信される
196 Assert.Equal(HttpMethod.Head, x.Method);
197 Assert.Equal(new Uri("https://t.co/hoge"), x.RequestUri);
199 return this.CreateRedirectResponse("http://example.com/hoge");
202 Assert.Equal(new Uri("http://example.com/hoge"),
203 await shortUrl.ExpandUrlAsync(new Uri("http://t.co/hoge")));
205 Assert.Equal(0, handler.QueueCount);
210 public async Task ExpandUrlAsync_InsecureDomainTest()
212 var handler = new HttpMessageHandlerMock();
213 using (var http = new HttpClient(handler))
215 var shortUrl = new ShortUrl(http);
217 // http://tinami.jp/hoge -> http://example.com/hoge
220 // HTTPS非対応のドメインは http:// のままリクエストが送信される
221 Assert.Equal(HttpMethod.Head, x.Method);
222 Assert.Equal(new Uri("http://tinami.jp/hoge"), x.RequestUri);
224 return this.CreateRedirectResponse("http://example.com/hoge");
227 Assert.Equal(new Uri("http://example.com/hoge"),
228 await shortUrl.ExpandUrlAsync(new Uri("http://tinami.jp/hoge")));
230 Assert.Equal(0, handler.QueueCount);
235 public async Task ExpandUrlAsync_RelativeUriTest()
237 var handler = new HttpMessageHandlerMock();
238 using (var http = new HttpClient(handler))
240 var shortUrl = new ShortUrl(http);
246 return this.CreateRedirectResponse("");
249 // 相対 URI に対しては何も行わない
250 Assert.Equal(new Uri("./foo/bar", UriKind.Relative),
251 await shortUrl.ExpandUrlAsync(new Uri("./foo/bar", UriKind.Relative)));
253 Assert.Equal(1, handler.QueueCount);
258 public async Task ExpandUrlAsync_RelativeRedirectTest()
260 var handler = new HttpMessageHandlerMock();
261 using (var http = new HttpClient(handler))
263 var shortUrl = new ShortUrl(http);
265 // Location に相対 URL を指定したリダイレクト (テストに使う URL は適当)
266 // https://t.co/hogehoge -> /tetetete
269 Assert.Equal(HttpMethod.Head, x.Method);
270 Assert.Equal(new Uri("https://t.co/hogehoge"), x.RequestUri);
272 return this.CreateRedirectResponse("/tetetete", UriKind.Relative);
275 // https://t.co/tetetete -> http://example.com/tetetete
278 Assert.Equal(HttpMethod.Head, x.Method);
279 Assert.Equal(new Uri("https://t.co/tetetete"), x.RequestUri);
281 return this.CreateRedirectResponse("http://example.com/tetetete");
284 Assert.Equal(new Uri("http://example.com/tetetete"),
285 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hogehoge")));
287 Assert.Equal(0, handler.QueueCount);
292 public async Task ExpandUrlAsync_String_Test()
294 var handler = new HttpMessageHandlerMock();
295 using (var http = new HttpClient(handler))
297 var shortUrl = new ShortUrl(http);
299 // https://t.co/hoge1 -> http://example.com/hoge2
302 Assert.Equal(HttpMethod.Head, x.Method);
303 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
305 return this.CreateRedirectResponse("http://example.com/hoge2");
308 Assert.Equal("http://example.com/hoge2",
309 await shortUrl.ExpandUrlAsync("https://t.co/hoge1"));
311 Assert.Equal(0, handler.QueueCount);
316 public async Task ExpandUrlAsync_String_SchemeLessUrlTest()
318 var handler = new HttpMessageHandlerMock();
319 using (var http = new HttpClient(handler))
321 var shortUrl = new ShortUrl(http);
323 // https://t.co/hoge1 -> http://example.com/hoge2
326 Assert.Equal(HttpMethod.Head, x.Method);
327 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
329 return this.CreateRedirectResponse("http://example.com/hoge2");
333 Assert.Equal("http://example.com/hoge2",
334 await shortUrl.ExpandUrlAsync("t.co/hoge1"));
336 Assert.Equal(0, handler.QueueCount);
341 public async Task ExpandUrlAsync_String_InvalidUrlTest()
343 var handler = new HttpMessageHandlerMock();
344 using (var http = new HttpClient(handler))
346 var shortUrl = new ShortUrl(http);
352 return this.CreateRedirectResponse("http://example.com/hoge2");
356 Assert.Equal("..hogehoge..", await shortUrl.ExpandUrlAsync("..hogehoge.."));
358 Assert.Equal(1, handler.QueueCount);
363 public async Task ExpandUrlAsync_HttpErrorTest()
365 var handler = new HttpMessageHandlerMock();
366 using (var http = new HttpClient(handler))
368 var shortUrl = new ShortUrl(http);
370 // https://t.co/hoge1 -> 503 Service Unavailable
373 return new HttpResponseMessage(HttpStatusCode.ServiceUnavailable);
376 Assert.Equal(new Uri("https://t.co/hoge1"),
377 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1")));
379 Assert.Equal(0, handler.QueueCount);
384 public async Task ExpandUrlHtmlAsync_Test()
386 var handler = new HttpMessageHandlerMock();
387 using (var http = new HttpClient(handler))
389 var shortUrl = new ShortUrl(http);
391 // https://t.co/hoge1 -> http://example.com/hoge2
394 Assert.Equal(HttpMethod.Head, x.Method);
395 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
397 return this.CreateRedirectResponse("http://example.com/hoge2");
400 Assert.Equal("<a href=\"http://example.com/hoge2\">hogehoge</a>",
401 await shortUrl.ExpandUrlHtmlAsync("<a href=\"https://t.co/hoge1\">hogehoge</a>"));
403 Assert.Equal(0, handler.QueueCount);
408 public async Task ExpandUrlHtmlAsync_RelativeUriTest()
410 var handler = new HttpMessageHandlerMock();
411 using (var http = new HttpClient(handler))
413 var shortUrl = new ShortUrl(http);
419 return this.CreateRedirectResponse("http://example.com/hoge");
422 Assert.Equal("<a href=\"./hoge\">hogehoge</a>",
423 await shortUrl.ExpandUrlHtmlAsync("<a href=\"./hoge\">hogehoge</a>"));
425 Assert.Equal(1, handler.QueueCount);
429 private HttpResponseMessage CreateRedirectResponse(string uriStr)
430 => this.CreateRedirectResponse(uriStr, UriKind.Absolute);
432 private HttpResponseMessage CreateRedirectResponse(string uriStr, UriKind uriKind)
434 var response = new HttpResponseMessage(HttpStatusCode.TemporaryRedirect);
435 response.Headers.Location = new Uri(uriStr, uriKind);
440 public async Task ShortenUrlAsync_TinyUrlTest()
442 var handler = new HttpMessageHandlerMock();
443 using (var http = new HttpClient(handler))
445 var shortUrl = new ShortUrl(http);
447 handler.Enqueue(async x =>
449 Assert.Equal(HttpMethod.Post, x.Method);
450 Assert.Equal(new Uri("https://tinyurl.com/api-create.php"), x.RequestUri);
451 Assert.Equal("url=http%3A%2F%2Fexample.com%2Fhogehogehoge", await x.Content.ReadAsStringAsync());
453 return new HttpResponseMessage(HttpStatusCode.OK)
455 Content = new ByteArrayContent(Encoding.UTF8.GetBytes("http://tinyurl.com/hoge")),
459 Assert.Equal(new Uri("https://tinyurl.com/hoge"),
460 await shortUrl.ShortenUrlAsync(MyCommon.UrlConverter.TinyUrl, new Uri("http://example.com/hogehogehoge")));
462 Assert.Equal(0, handler.QueueCount);
467 public async Task ShortenUrlAsync_UxnuUrlTest()
469 var handler = new HttpMessageHandlerMock();
470 using (var http = new HttpClient(handler))
472 var shortUrl = new ShortUrl(http);
476 Assert.Equal(HttpMethod.Get, x.Method);
477 Assert.Equal("https://ux.nu/api/short?format=plain&url=http:%2F%2Fexample.com%2Fhogehoge",
478 x.RequestUri.AbsoluteUri);
480 return new HttpResponseMessage(HttpStatusCode.OK)
482 Content = new ByteArrayContent(Encoding.UTF8.GetBytes("https://ux.nu/hoge")),
486 Assert.Equal(new Uri("https://ux.nu/hoge"),
487 await shortUrl.ShortenUrlAsync(MyCommon.UrlConverter.Uxnu, new Uri("http://example.com/hogehoge")));
489 Assert.Equal(0, handler.QueueCount);