OSDN Git Service

IApiConnectionLegacyを削除
[opentween/open-tween.git] / OpenTween.Tests / ShortUrlTest.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2014 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
4 //
5 // This file is part of OpenTween.
6 //
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)
10 // any later version.
11 //
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
15 // for more details.
16 //
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.
21
22 using System;
23 using System.Collections.Generic;
24 using System.Linq;
25 using System.Net;
26 using System.Net.Http;
27 using System.Text;
28 using System.Threading;
29 using System.Threading.Tasks;
30 using Xunit;
31 using Xunit.Extensions;
32
33 namespace OpenTween
34 {
35     public class ShortUrlTest
36     {
37         [Fact]
38         public async Task ExpandUrlAsync_Test()
39         {
40             var handler = new HttpMessageHandlerMock();
41             using var http = new HttpClient(handler);
42             var shortUrl = new ShortUrl(http);
43
44             // https://t.co/hoge1 -> http://example.com/hoge2
45             handler.Enqueue(x =>
46             {
47                 Assert.Equal(HttpMethod.Head, x.Method);
48                 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
49
50                 return this.CreateRedirectResponse("http://example.com/hoge2");
51             });
52
53             Assert.Equal(new Uri("http://example.com/hoge2"),
54                 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1")));
55
56             Assert.Equal(0, handler.QueueCount);
57         }
58
59         [Fact]
60         public async Task ExpandUrlAsync_IrregularUrlTest()
61         {
62             var handler = new HttpMessageHandlerMock();
63             using var http = new HttpClient(handler);
64             var shortUrl = new ShortUrl(http);
65
66             // https://www.flickr.com/photo.gne?short=hoge -> /photos/foo/11111/
67             handler.Enqueue(x =>
68             {
69                 Assert.Equal(HttpMethod.Head, x.Method);
70                 Assert.Equal(new Uri("https://www.flickr.com/photo.gne?short=hoge"), x.RequestUri);
71
72                 return this.CreateRedirectResponse("/photos/foo/11111/", UriKind.Relative);
73             });
74
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")));
77
78             Assert.Equal(0, handler.QueueCount);
79         }
80
81         [Fact]
82         public async Task ExpandUrlAsync_DisableExpandingTest()
83         {
84             var handler = new HttpMessageHandlerMock();
85             using var http = new HttpClient(handler);
86             var shortUrl = new ShortUrl(http);
87
88             shortUrl.DisableExpanding = true;
89
90             // https://t.co/hoge1 -> http://example.com/hoge2
91             handler.Enqueue(x =>
92             {
93                 // このリクエストは実行されないはず
94                 Assert.True(false);
95                 return this.CreateRedirectResponse("http://example.com/hoge2");
96             });
97
98             Assert.Equal(new Uri("https://t.co/hoge1"),
99                 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1")));
100
101             Assert.Equal(1, handler.QueueCount);
102         }
103
104         [Fact]
105         public async Task ExpandUrlAsync_RecursiveTest()
106         {
107             var handler = new HttpMessageHandlerMock();
108             using var http = new HttpClient(handler);
109             var shortUrl = new ShortUrl(http);
110
111             // https://t.co/hoge1 -> https://bit.ly/hoge2
112             handler.Enqueue(x =>
113             {
114                 Assert.Equal(HttpMethod.Head, x.Method);
115                 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
116
117                 return this.CreateRedirectResponse("https://bit.ly/hoge2");
118             });
119
120             // https://bit.ly/hoge2 -> http://example.com/hoge3
121             handler.Enqueue(x =>
122             {
123                 Assert.Equal(HttpMethod.Head, x.Method);
124                 Assert.Equal(new Uri("https://bit.ly/hoge2"), x.RequestUri);
125
126                 return this.CreateRedirectResponse("http://example.com/hoge3");
127             });
128
129             Assert.Equal(new Uri("http://example.com/hoge3"),
130                 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1")));
131
132             Assert.Equal(0, handler.QueueCount);
133         }
134
135         [Fact]
136         public async Task ExpandUrlAsync_RecursiveLimitTest()
137         {
138             var handler = new HttpMessageHandlerMock();
139             using var http = new HttpClient(handler);
140             var shortUrl = new ShortUrl(http);
141
142             // https://t.co/hoge1 -> https://bit.ly/hoge2
143             handler.Enqueue(x =>
144             {
145                 Assert.Equal(HttpMethod.Head, x.Method);
146                 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
147
148                 return this.CreateRedirectResponse("https://bit.ly/hoge2");
149             });
150
151             // https://bit.ly/hoge2 -> https://tinyurl.com/hoge3
152             handler.Enqueue(x =>
153             {
154                 Assert.Equal(HttpMethod.Head, x.Method);
155                 Assert.Equal(new Uri("https://bit.ly/hoge2"), x.RequestUri);
156
157                 return this.CreateRedirectResponse("https://tinyurl.com/hoge3");
158             });
159
160             // https://tinyurl.com/hoge3 -> http://example.com/hoge4
161             handler.Enqueue(x =>
162             {
163                 // このリクエストは実行されないはず
164                 Assert.True(false);
165                 return this.CreateRedirectResponse("http://example.com/hoge4");
166             });
167
168             Assert.Equal(new Uri("https://tinyurl.com/hoge3"),
169                 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1"), redirectLimit: 2));
170
171             Assert.Equal(1, handler.QueueCount);
172         }
173
174         [Fact]
175         public async Task ExpandUrlAsync_UpgradeToHttpsTest()
176         {
177             var handler = new HttpMessageHandlerMock();
178             using var http = new HttpClient(handler);
179             var shortUrl = new ShortUrl(http);
180
181             // http://t.co/hoge -> http://example.com/hoge
182             handler.Enqueue(x =>
183             {
184                 // https:// に変換されてリクエストが送信される
185                 Assert.Equal(HttpMethod.Head, x.Method);
186                 Assert.Equal(new Uri("https://t.co/hoge"), x.RequestUri);
187
188                 return this.CreateRedirectResponse("http://example.com/hoge");
189             });
190
191             Assert.Equal(new Uri("http://example.com/hoge"),
192                 await shortUrl.ExpandUrlAsync(new Uri("http://t.co/hoge")));
193
194             Assert.Equal(0, handler.QueueCount);
195         }
196
197         [Fact]
198         public async Task ExpandUrlAsync_InsecureDomainTest()
199         {
200             var handler = new HttpMessageHandlerMock();
201             using var http = new HttpClient(handler);
202             var shortUrl = new ShortUrl(http);
203
204             // http://tinami.jp/hoge -> http://example.com/hoge
205             handler.Enqueue(x =>
206             {
207                 // HTTPS非対応のドメインは http:// のままリクエストが送信される
208                 Assert.Equal(HttpMethod.Head, x.Method);
209                 Assert.Equal(new Uri("http://tinami.jp/hoge"), x.RequestUri);
210
211                 return this.CreateRedirectResponse("http://example.com/hoge");
212             });
213
214             Assert.Equal(new Uri("http://example.com/hoge"),
215                 await shortUrl.ExpandUrlAsync(new Uri("http://tinami.jp/hoge")));
216
217             Assert.Equal(0, handler.QueueCount);
218         }
219
220         [Fact]
221         public async Task ExpandUrlAsync_RelativeUriTest()
222         {
223             var handler = new HttpMessageHandlerMock();
224             using var http = new HttpClient(handler);
225             var shortUrl = new ShortUrl(http);
226
227             handler.Enqueue(x =>
228             {
229                 // このリクエストは実行されないはず
230                 Assert.True(false);
231                 return this.CreateRedirectResponse("");
232             });
233
234             // 相対 URI に対しては何も行わない
235             Assert.Equal(new Uri("./foo/bar", UriKind.Relative),
236                 await shortUrl.ExpandUrlAsync(new Uri("./foo/bar", UriKind.Relative)));
237
238             Assert.Equal(1, handler.QueueCount);
239         }
240
241         [Fact]
242         public async Task ExpandUrlAsync_RelativeRedirectTest()
243         {
244             var handler = new HttpMessageHandlerMock();
245             using var http = new HttpClient(handler);
246             var shortUrl = new ShortUrl(http);
247
248             // Location に相対 URL を指定したリダイレクト (テストに使う URL は適当)
249             // https://t.co/hogehoge -> /tetetete
250             handler.Enqueue(x =>
251             {
252                 Assert.Equal(HttpMethod.Head, x.Method);
253                 Assert.Equal(new Uri("https://t.co/hogehoge"), x.RequestUri);
254
255                 return this.CreateRedirectResponse("/tetetete", UriKind.Relative);
256             });
257
258             // https://t.co/tetetete -> http://example.com/tetetete
259             handler.Enqueue(x =>
260             {
261                 Assert.Equal(HttpMethod.Head, x.Method);
262                 Assert.Equal(new Uri("https://t.co/tetetete"), x.RequestUri);
263
264                 return this.CreateRedirectResponse("http://example.com/tetetete");
265             });
266
267             Assert.Equal(new Uri("http://example.com/tetetete"),
268                 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hogehoge")));
269
270             Assert.Equal(0, handler.QueueCount);
271         }
272
273         [Fact]
274         public async Task ExpandUrlAsync_String_Test()
275         {
276             var handler = new HttpMessageHandlerMock();
277             using var http = new HttpClient(handler);
278             var shortUrl = new ShortUrl(http);
279
280             // https://t.co/hoge1 -> http://example.com/hoge2
281             handler.Enqueue(x =>
282             {
283                 Assert.Equal(HttpMethod.Head, x.Method);
284                 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
285
286                 return this.CreateRedirectResponse("http://example.com/hoge2");
287             });
288
289             Assert.Equal("http://example.com/hoge2",
290                 await shortUrl.ExpandUrlAsync("https://t.co/hoge1"));
291
292             Assert.Equal(0, handler.QueueCount);
293         }
294
295         [Fact]
296         public async Task ExpandUrlAsync_String_SchemeLessUrlTest()
297         {
298             var handler = new HttpMessageHandlerMock();
299             using var http = new HttpClient(handler);
300             var shortUrl = new ShortUrl(http);
301
302             // https://t.co/hoge1 -> http://example.com/hoge2
303             handler.Enqueue(x =>
304             {
305                 Assert.Equal(HttpMethod.Head, x.Method);
306                 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
307
308                 return this.CreateRedirectResponse("http://example.com/hoge2");
309             });
310
311             // スキームが省略されたURL
312             Assert.Equal("http://example.com/hoge2",
313                 await shortUrl.ExpandUrlAsync("t.co/hoge1"));
314
315             Assert.Equal(0, handler.QueueCount);
316         }
317
318         [Fact]
319         public async Task ExpandUrlAsync_String_InvalidUrlTest()
320         {
321             var handler = new HttpMessageHandlerMock();
322             using var http = new HttpClient(handler);
323             var shortUrl = new ShortUrl(http);
324
325             handler.Enqueue(x =>
326             {
327                 // リクエストは送信されないはず
328                 Assert.True(false);
329                 return this.CreateRedirectResponse("http://example.com/hoge2");
330             });
331
332             // 不正なURL
333             Assert.Equal("..hogehoge..", await shortUrl.ExpandUrlAsync("..hogehoge.."));
334
335             Assert.Equal(1, handler.QueueCount);
336         }
337
338         [Fact]
339         public async Task ExpandUrlAsync_HttpErrorTest()
340         {
341             var handler = new HttpMessageHandlerMock();
342             using var http = new HttpClient(handler);
343             var shortUrl = new ShortUrl(http);
344
345             // https://t.co/hoge1 -> 503 Service Unavailable
346             handler.Enqueue(x =>
347             {
348                 return new HttpResponseMessage(HttpStatusCode.ServiceUnavailable);
349             });
350
351             Assert.Equal(new Uri("https://t.co/hoge1"),
352                 await shortUrl.ExpandUrlAsync(new Uri("https://t.co/hoge1")));
353
354             Assert.Equal(0, handler.QueueCount);
355         }
356
357         [Fact]
358         public async Task ExpandUrlHtmlAsync_Test()
359         {
360             var handler = new HttpMessageHandlerMock();
361             using var http = new HttpClient(handler);
362             var shortUrl = new ShortUrl(http);
363
364             // https://t.co/hoge1 -> http://example.com/hoge2
365             handler.Enqueue(x =>
366             {
367                 Assert.Equal(HttpMethod.Head, x.Method);
368                 Assert.Equal(new Uri("https://t.co/hoge1"), x.RequestUri);
369
370                 return this.CreateRedirectResponse("http://example.com/hoge2");
371             });
372
373             Assert.Equal("""<a href="http://example.com/hoge2">hogehoge</a>""",
374                 await shortUrl.ExpandUrlHtmlAsync("""<a href="https://t.co/hoge1">hogehoge</a>"""));
375
376             Assert.Equal(0, handler.QueueCount);
377         }
378
379         [Fact]
380         public async Task ExpandUrlHtmlAsync_RelativeUriTest()
381         {
382             var handler = new HttpMessageHandlerMock();
383             using var http = new HttpClient(handler);
384             var shortUrl = new ShortUrl(http);
385
386             handler.Enqueue(x =>
387             {
388                 // リクエストは送信されないはず
389                 Assert.True(false);
390                 return this.CreateRedirectResponse("http://example.com/hoge");
391             });
392
393             Assert.Equal("""<a href="./hoge">hogehoge</a>""",
394                 await shortUrl.ExpandUrlHtmlAsync("""<a href="./hoge">hogehoge</a>"""));
395
396             Assert.Equal(1, handler.QueueCount);
397         }
398
399         private HttpResponseMessage CreateRedirectResponse(string uriStr)
400             => this.CreateRedirectResponse(uriStr, UriKind.Absolute);
401
402         private HttpResponseMessage CreateRedirectResponse(string uriStr, UriKind uriKind)
403         {
404             var response = new HttpResponseMessage(HttpStatusCode.TemporaryRedirect);
405             response.Headers.Location = new Uri(uriStr, uriKind);
406             return response;
407         }
408
409         [Fact]
410         public async Task ShortenUrlAsync_TinyUrlTest()
411         {
412             var handler = new HttpMessageHandlerMock();
413             using var http = new HttpClient(handler);
414             var shortUrl = new ShortUrl(http);
415
416             handler.Enqueue(async x =>
417             {
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());
421
422                 return new HttpResponseMessage(HttpStatusCode.OK)
423                 {
424                     Content = new ByteArrayContent(Encoding.UTF8.GetBytes("http://tinyurl.com/hoge")),
425                 };
426             });
427
428             Assert.Equal(new Uri("https://tinyurl.com/hoge"),
429                 await shortUrl.ShortenUrlAsync(MyCommon.UrlConverter.TinyUrl, new Uri("http://example.com/hogehogehoge")));
430
431             Assert.Equal(0, handler.QueueCount);
432         }
433
434         [Fact]
435         public async Task ShortenUrlAsync_UxnuUrlTest()
436         {
437             var handler = new HttpMessageHandlerMock();
438             using var http = new HttpClient(handler);
439             var shortUrl = new ShortUrl(http);
440
441             handler.Enqueue(x =>
442             {
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);
446
447                 return new HttpResponseMessage(HttpStatusCode.OK)
448                 {
449                     Content = new ByteArrayContent(Encoding.UTF8.GetBytes("https://ux.nu/hoge")),
450                 };
451             });
452
453             Assert.Equal(new Uri("https://ux.nu/hoge"),
454                 await shortUrl.ShortenUrlAsync(MyCommon.UrlConverter.Uxnu, new Uri("http://example.com/hogehoge")));
455
456             Assert.Equal(0, handler.QueueCount);
457         }
458     }
459 }