blob: af3d5e105f3df0afce708962aef327516376d46a [file] [log] [blame]
// Copyright 2020 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "starboard/loader_app/app_key_internal.h"
#include <string>
#include "starboard/string.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace starboard {
namespace loader_app {
typedef struct URLWithExtractedAndEncoded {
// The initial URL to be handled.
const char* url;
// The application key extracted from |url|.
const char* extracted;
// The base64 encoded |extracted|.
const char* encoded;
} URLWithExtractedAndEncoded;
// The URLs below were taken from url/url_parse_unittest.cc.
const URLWithExtractedAndEncoded kURLWithExtractedAndEncoded[] = {
{
"http://user:pass@foo:21/bar;par?b#c",
"http://foo:21/bar;par",
"aHR0cDovL2ZvbzoyMS9iYXI7cGFy",
},
{
"http:foo.com",
"http:foo.com",
"aHR0cDpmb28uY29t",
},
{
"\t :foo.com \n",
"\t :foo.com \n",
"CSAgIDpmb28uY29tICAgCg==",
},
{
" foo.com ",
" foo.com ",
"IGZvby5jb20gIA==",
},
{
"a:\t foo.com",
"a:\t foo.com",
"YToJIGZvby5jb20=",
},
{
"http://f:21/ b ? d # e ",
"http://f:21/ b ",
"aHR0cDovL2Y6MjEvIGIg",
},
{
"http://f:/c",
"http://f:/c",
"aHR0cDovL2Y6L2M=",
},
{
"http://f:0/c",
"http://f:0/c",
"aHR0cDovL2Y6MC9j",
},
{
"http://f:00000000000000/c",
"http://f:00000000000000/c",
"aHR0cDovL2Y6MDAwMDAwMDAwMDAwMDAvYw==",
},
{
"http://f:00000000000000000000080/c",
"http://f:00000000000000000000080/c",
"aHR0cDovL2Y6MDAwMDAwMDAwMDAwMDAwMDAwMDAwODAvYw==",
},
{
"http://f:b/c",
"http://f:b/c",
"aHR0cDovL2Y6Yi9j",
},
{
"http://f: /c",
"http://f: /c",
"aHR0cDovL2Y6IC9j",
},
{
"http://f:\n/c",
"http://f:\n/c",
"aHR0cDovL2Y6Ci9j",
},
{
"http://f:fifty-two/c",
"http://f:fifty-two/c",
"aHR0cDovL2Y6ZmlmdHktdHdvL2M=",
},
{
"http://f:999999/c",
"http://f:999999/c",
"aHR0cDovL2Y6OTk5OTk5L2M=",
},
{
"http://f: 21 / b ? d # e ",
"http://f: 21 / b ",
"aHR0cDovL2Y6IDIxIC8gYiA=",
},
{
"",
"",
"",
},
{
" \t",
" \t",
"ICAJ",
},
{
":foo.com/",
":foo.com/",
"OmZvby5jb20v",
},
{
":foo.com\\",
":foo.com\\",
"OmZvby5jb21c",
},
{
":",
":",
"Og==",
},
{
":a",
":a",
"OmE=",
},
{
":/",
":/",
"Oi8=",
},
{
":\\",
":\\",
"Olw=",
},
{
":#",
":",
"Og==",
},
{
"#",
"",
"",
},
{
"#/",
"",
"",
},
{
"#\\",
"",
"",
},
{
"#;?",
"",
"",
},
{
"?",
"",
"",
},
{
"/",
"/",
"Lw==",
},
{
":23",
":23",
"OjIz",
},
{
"/:23",
"/:23",
"LzoyMw==",
},
{
"//",
"//",
"Ly8=",
},
{
"::",
"::",
"Ojo=",
},
{
"::23",
"::23",
"OjoyMw==",
},
{
"foo://",
"foo://",
"Zm9vOi8v",
},
{
"http://a:b@c:29/d",
"http://c:29/d",
"aHR0cDovL2M6MjkvZA==",
},
{
"http::@c:29",
"http::@c:29",
"aHR0cDo6QGM6Mjk=",
},
{
"http://&a:foo(b]c@d:2/",
"http://d:2/",
"aHR0cDovL2Q6Mi8=",
},
{
"http://::@c@d:2",
"http://c@d:2",
"aHR0cDovL2NAZDoy",
},
{
"http://foo.com:b@d/",
"http://d/",
"aHR0cDovL2Qv",
},
{
"http://foo.com/\\@",
"http://",
"aHR0cDovLw==",
},
{
"http:\\\\foo.com\\",
"http:\\\\foo.com\\",
"aHR0cDpcXGZvby5jb21c",
},
{
"http:\\\\a\\b:c\\d@foo.com\\",
"http:\\\\a\\b:c\\d@foo.com\\",
"aHR0cDpcXGFcYjpjXGRAZm9vLmNvbVw=",
},
{
"foo:/",
"foo:/",
"Zm9vOi8=",
},
{
"foo:/bar.com/",
"foo:/bar.com/",
"Zm9vOi9iYXIuY29tLw==",
},
{
"foo://///////",
"foo://///////",
"Zm9vOi8vLy8vLy8vLw==",
},
{
"foo://///////bar.com/",
"foo://///////bar.com/",
"Zm9vOi8vLy8vLy8vL2Jhci5jb20v",
},
{
"foo:////://///",
"foo:////://///",
"Zm9vOi8vLy86Ly8vLy8=",
},
{
"c:/foo",
"c:/foo",
"YzovZm9v",
},
{
"//foo/bar",
"//foo/bar",
"Ly9mb28vYmFy",
},
{
"http://foo/path;a??e#f#g",
"http://foo/path;a",
"aHR0cDovL2Zvby9wYXRoO2E=",
},
{
"http://foo/abcd?efgh?ijkl",
"http://foo/abcd",
"aHR0cDovL2Zvby9hYmNk",
},
{
"http://foo/abcd#foo?bar",
"http://foo/abcd",
"aHR0cDovL2Zvby9hYmNk",
},
{
"[61:24:74]:98",
"[61:24:74]:98",
"WzYxOjI0Ojc0XTo5OA==",
},
{
"http://[61:27]:98",
"http://[61:27]:98",
"aHR0cDovL1s2MToyN106OTg=",
},
{
"http:[61:27]/:foo",
"http:[61:27]/:foo",
"aHR0cDpbNjE6MjddLzpmb28=",
},
{
"http://[1::2]:3:4",
"http://[1::2]:3:4",
"aHR0cDovL1sxOjoyXTozOjQ=",
},
{
"http://2001::1",
"http://2001::1",
"aHR0cDovLzIwMDE6OjE=",
},
{
"http://[2001::1",
"http://[2001::1",
"aHR0cDovL1syMDAxOjox",
},
{
"http://2001::1]",
"http://2001::1]",
"aHR0cDovLzIwMDE6OjFd",
},
{
"http://2001::1]:80",
"http://2001::1]:80",
"aHR0cDovLzIwMDE6OjFdOjgw",
},
{
"http://[2001::1]",
"http://[2001::1]",
"aHR0cDovL1syMDAxOjoxXQ==",
},
{
"http://[2001::1]:80",
"http://[2001::1]:80",
"aHR0cDovL1syMDAxOjoxXTo4MA==",
},
{
"http://[[::]]",
"http://[[::]]",
"aHR0cDovL1tbOjpdXQ==",
},
{
"file:server",
"file:server",
"ZmlsZTpzZXJ2ZXI=",
},
{
" file: server \t",
" file: server \t",
"ICBmaWxlOiBzZXJ2ZXIgIAk=",
},
{
"FiLe:c|",
"FiLe:c|",
"RmlMZTpjfA==",
},
{
"FILE:/\\\\/server/file",
"FILE:/\\\\/server/file",
"RklMRTovXFwvc2VydmVyL2ZpbGU=",
},
{
"file://server/",
"file://server/",
"ZmlsZTovL3NlcnZlci8=",
},
{
"file://localhost/c:/",
"file://localhost/c:/",
"ZmlsZTovL2xvY2FsaG9zdC9jOi8=",
},
{
"file://127.0.0.1/c|\\",
"file://127.0.0.1/c|\\",
"ZmlsZTovLzEyNy4wLjAuMS9jfFw=",
},
{
"file:/",
"file:/",
"ZmlsZTov",
},
{
"file:",
"file:",
"ZmlsZTo=",
},
{
"file:c:\\fo\\b",
"file:c:\\fo\\b",
"ZmlsZTpjOlxmb1xi",
},
{
"file:/c:\\foo/bar",
"file:/c:\\foo/bar",
"ZmlsZTovYzpcZm9vL2Jhcg==",
},
{
"file://c:/f\\b",
"file://c:/f\\b",
"ZmlsZTovL2M6L2ZcYg==",
},
{
"file:///C:/foo",
"file:///C:/foo",
"ZmlsZTovLy9DOi9mb28=",
},
{
"file://///\\/\\/c:\\f\\b",
"file://///\\/\\/c:\\f\\b",
"ZmlsZTovLy8vL1wvXC9jOlxmXGI=",
},
{
"file:server/file",
"file:server/file",
"ZmlsZTpzZXJ2ZXIvZmlsZQ==",
},
{
"file:/server/file",
"file:/server/file",
"ZmlsZTovc2VydmVyL2ZpbGU=",
},
{
"file://server/file",
"file://server/file",
"ZmlsZTovL3NlcnZlci9maWxl",
},
{
"file:///server/file",
"file:///server/file",
"ZmlsZTovLy9zZXJ2ZXIvZmlsZQ==",
},
{
"file://\\server/file",
"file://\\server/file",
"ZmlsZTovL1xzZXJ2ZXIvZmlsZQ==",
},
{
"file:////server/file",
"file:////server/file",
"ZmlsZTovLy8vc2VydmVyL2ZpbGU=",
},
{
"file:///C:/foo.html?#",
"file:///C:/foo.html",
"ZmlsZTovLy9DOi9mb28uaHRtbA==",
},
{
"file:///C:/foo.html?query=yes#ref",
"file:///C:/foo.html",
"ZmlsZTovLy9DOi9mb28uaHRtbA==",
},
{
"file:",
"file:",
"ZmlsZTo=",
},
{
"file:path",
"file:path",
"ZmlsZTpwYXRo",
},
{
"file:path/",
"file:path/",
"ZmlsZTpwYXRoLw==",
},
{
"file:path/f.txt",
"file:path/f.txt",
"ZmlsZTpwYXRoL2YudHh0",
},
{
"file:/",
"file:/",
"ZmlsZTov",
},
{
"file:/path",
"file:/path",
"ZmlsZTovcGF0aA==",
},
{
"file:/path/",
"file:/path/",
"ZmlsZTovcGF0aC8=",
},
{
"file:/path/f.txt",
"file:/path/f.txt",
"ZmlsZTovcGF0aC9mLnR4dA==",
},
{
"file://",
"file://",
"ZmlsZTovLw==",
},
{
"file://server",
"file://server",
"ZmlsZTovL3NlcnZlcg==",
},
{
"file://server/",
"file://server/",
"ZmlsZTovL3NlcnZlci8=",
},
{
"file://server/f.txt",
"file://server/f.txt",
"ZmlsZTovL3NlcnZlci9mLnR4dA==",
},
{
"file:///",
"file:///",
"ZmlsZTovLy8=",
},
{
"file:///path",
"file:///path",
"ZmlsZTovLy9wYXRo",
},
{
"file:///path/",
"file:///path/",
"ZmlsZTovLy9wYXRoLw==",
},
{
"file:///path/f.txt",
"file:///path/f.txt",
"ZmlsZTovLy9wYXRoL2YudHh0",
},
{
"file:////",
"file:////",
"ZmlsZTovLy8v",
},
{
"file:////path",
"file:////path",
"ZmlsZTovLy8vcGF0aA==",
},
{
"file:////path/",
"file:////path/",
"ZmlsZTovLy8vcGF0aC8=",
},
{
"file:////path/f.txt",
"file:////path/f.txt",
"ZmlsZTovLy8vcGF0aC9mLnR4dA==",
},
{
"path/f.txt",
"path/f.txt",
"cGF0aC9mLnR4dA==",
},
{
"path:80/f.txt",
"path:80/f.txt",
"cGF0aDo4MC9mLnR4dA==",
},
{
"path/f.txt:80",
"path/f.txt:80",
"cGF0aC9mLnR4dDo4MA==",
},
{
"/path/f.txt",
"/path/f.txt",
"L3BhdGgvZi50eHQ=",
},
{
"/path:80/f.txt",
"/path:80/f.txt",
"L3BhdGg6ODAvZi50eHQ=",
},
{
"/path/f.txt:80",
"/path/f.txt:80",
"L3BhdGgvZi50eHQ6ODA=",
},
{
"//server/f.txt",
"//server/f.txt",
"Ly9zZXJ2ZXIvZi50eHQ=",
},
{
"//server:80/f.txt",
"//server:80/f.txt",
"Ly9zZXJ2ZXI6ODAvZi50eHQ=",
},
{
"//server/f.txt:80",
"//server/f.txt:80",
"Ly9zZXJ2ZXIvZi50eHQ6ODA=",
},
{
"///path/f.txt",
"///path/f.txt",
"Ly8vcGF0aC9mLnR4dA==",
},
{
"///path:80/f.txt",
"///path:80/f.txt",
"Ly8vcGF0aDo4MC9mLnR4dA==",
},
{
"///path/f.txt:80",
"///path/f.txt:80",
"Ly8vcGF0aC9mLnR4dDo4MA==",
},
{
"////path/f.txt",
"////path/f.txt",
"Ly8vL3BhdGgvZi50eHQ=",
},
{
"////path:80/f.txt",
"////path:80/f.txt",
"Ly8vL3BhdGg6ODAvZi50eHQ=",
},
{
"////path/f.txt:80",
"////path/f.txt:80",
"Ly8vL3BhdGgvZi50eHQ6ODA=",
},
{
"file:///foo.html?#",
"file:///foo.html",
"ZmlsZTovLy9mb28uaHRtbA==",
},
{
"file:///foo.html?q=y#ref",
"file:///foo.html",
"ZmlsZTovLy9mb28uaHRtbA==",
},
};
TEST(AppKeyTest, SunnyDayExtractAppKey) {
for (const URLWithExtractedAndEncoded& expected :
kURLWithExtractedAndEncoded) {
std::string actual = ExtractAppKey(expected.url);
EXPECT_EQ(std::string(expected.extracted), actual);
actual = EncodeAppKey(actual);
EXPECT_EQ(std::string(expected.encoded), actual);
}
}
TEST(AppKeyTest, SunnyDayExtractAppKeySanitizesResult) {
// This magic is 11111011 11110000 in binary and thus begins with '+' and '/'
// when base64 encoded.
uint8_t magic[3] = {0xFB, 0xF0, 0x00};
const std::string actual =
ExtractAppKey(reinterpret_cast<const char*>(magic));
// Check that the '+' and '/' characters were replaced with '-' and '_'.
EXPECT_EQ("\xFB\xF0", actual);
EXPECT_EQ("-_A=", EncodeAppKey(actual));
}
} // namespace loader_app
} // namespace starboard