Fixes to urltest binary, added and tweaked tests for 100% coverage of URL library (fixed a few URL library bugs in the process, too)
Change-Id: I24a1f014cb21b8ec0062ee79e3e6ba717b392496
This commit is contained in:
parent
90321887cc
commit
ff36880cc8
4 changed files with 210 additions and 142 deletions
72
lib/url.cpp
72
lib/url.cpp
|
@ -75,18 +75,20 @@ HTTP::URL::URL(const std::string &url){
|
|||
if (path.substr(0, 2) == "./"){path.erase(0, 2);}
|
||||
if (path.substr(0, 3) == "../"){path.erase(0, 3);}
|
||||
//RFC 2396 sec 5.2: check if URL ends with <name>/.. -> remove iff name != ..
|
||||
if (path.length() == 2 && path == "..")
|
||||
path = "";
|
||||
if (path.length() > 2 && path.substr(path.length() - 2) == ".."){
|
||||
// |<name>| == 1, so <name> != '..'
|
||||
if (path.length() == 4){
|
||||
path.erase(path.length() - 4, path.length());
|
||||
if (path.length() == 2 && path == ".."){path.clear();}
|
||||
if (path.length() == 1 && path == "."){path.clear();}
|
||||
if (path.length() > 2 && path.substr(path.length() - 3) == "/.."){
|
||||
if (path.length() <= 4){
|
||||
path.clear();
|
||||
}
|
||||
else if (path.length() > 4 && path.substr(path.length() - 5) != "../.."){
|
||||
size_t prevslash = path.rfind('/', path.length() - 4);
|
||||
path.erase(prevslash + 1, path.length());
|
||||
}
|
||||
}
|
||||
if (path.length() > 1 && path.substr(path.length() - 2) == "/."){
|
||||
path.erase(path.length()-1);
|
||||
}
|
||||
if (!isLocalPath()){
|
||||
path = Encodings::URL::decode(path);
|
||||
}
|
||||
|
@ -143,6 +145,7 @@ HTTP::URL::URL(const std::string &url){
|
|||
port = "";
|
||||
}
|
||||
}
|
||||
if (host.find(':') != std::string::npos){IPv6Addr = true;}
|
||||
}
|
||||
// if the host is numeric, assume it is a port, instead
|
||||
if (host.size() && is_numeric(host.c_str())){
|
||||
|
@ -174,7 +177,11 @@ uint16_t HTTP::URL::getDefaultPort() const{
|
|||
|
||||
/// Returns the file extension of the URL, or an empty string if none.
|
||||
std::string HTTP::URL::getExt() const{
|
||||
//No dot? No extension.
|
||||
if (path.rfind('.') == std::string::npos){return "";}
|
||||
//No dot before directory change? No extension.
|
||||
if (path.rfind('/') != std::string::npos && path.rfind('/') > path.rfind('.')){return "";}
|
||||
//Otherwise, anything behind the last dot
|
||||
return path.substr(path.rfind('.') + 1);
|
||||
}
|
||||
|
||||
|
@ -187,7 +194,11 @@ std::string HTTP::URL::getUrl() const{
|
|||
ret = "//";
|
||||
}
|
||||
if (user.size() || pass.size()){
|
||||
ret += Encodings::URL::encode(user) + ":" + Encodings::URL::encode(pass) + "@";
|
||||
if (!pass.size()){
|
||||
ret += Encodings::URL::encode(user) + "@";
|
||||
}else{
|
||||
ret += Encodings::URL::encode(user) + ":" + Encodings::URL::encode(pass) + "@";
|
||||
}
|
||||
}
|
||||
if (IPv6Addr){
|
||||
ret += "[" + host + "]";
|
||||
|
@ -196,13 +207,7 @@ std::string HTTP::URL::getUrl() const{
|
|||
}
|
||||
if (port.size() && getPort() != getDefaultPort()){ret += ":" + port;}
|
||||
ret += "/";
|
||||
if (protocol == "rtsp"){
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]#?&");}
|
||||
}else if (isLocalPath()){
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]+ ");}
|
||||
}else{
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]");}
|
||||
}
|
||||
ret += getEncodedPath();
|
||||
if (args.size()){ret += "?" + args;}
|
||||
if (frag.size()){ret += "#" + Encodings::URL::encode(frag, "/:=@[]#?&");}
|
||||
return ret;
|
||||
|
@ -213,6 +218,17 @@ std::string HTTP::URL::getFilePath() const{
|
|||
return "/" + path;
|
||||
}
|
||||
|
||||
std::string HTTP::URL::getEncodedPath() const{
|
||||
if (protocol == "rtsp"){
|
||||
if (path.size()){return Encodings::URL::encode(path, "/:=@[]#?&");}
|
||||
}else if (isLocalPath()){
|
||||
if (path.size()){return Encodings::URL::encode(path, "/:=@[]+ ");}
|
||||
}else{
|
||||
if (path.size()){return Encodings::URL::encode(path, "/:=@[]");}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/// Returns whether the URL is probably pointing to a local file
|
||||
bool HTTP::URL::isLocalPath() const{
|
||||
//Anything with a "file" protocol is explicitly a local file
|
||||
|
@ -240,13 +256,7 @@ std::string HTTP::URL::getProxyUrl() const{
|
|||
}
|
||||
if (port.size() && getPort() != getDefaultPort()){ret += ":" + port;}
|
||||
ret += "/";
|
||||
if (protocol == "rtsp"){
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]#?&");}
|
||||
}else if (isLocalPath()){
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]+ ");}
|
||||
}else{
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]");}
|
||||
}
|
||||
ret += getEncodedPath();
|
||||
if (args.size()){ret += "?" + args;}
|
||||
return ret;
|
||||
}
|
||||
|
@ -260,7 +270,11 @@ std::string HTTP::URL::getBareUrl() const{
|
|||
ret = "//";
|
||||
}
|
||||
if (user.size() || pass.size()){
|
||||
ret += Encodings::URL::encode(user) + ":" + Encodings::URL::encode(pass) + "@";
|
||||
if (!pass.size()){
|
||||
ret += Encodings::URL::encode(user) + "@";
|
||||
}else{
|
||||
ret += Encodings::URL::encode(user) + ":" + Encodings::URL::encode(pass) + "@";
|
||||
}
|
||||
}
|
||||
if (IPv6Addr){
|
||||
ret += "[" + host + "]";
|
||||
|
@ -269,13 +283,7 @@ std::string HTTP::URL::getBareUrl() const{
|
|||
}
|
||||
if (port.size() && getPort() != getDefaultPort()){ret += ":" + port;}
|
||||
ret += "/";
|
||||
if (protocol == "rtsp"){
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]#?&");}
|
||||
}else if (isLocalPath()){
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]+ ");}
|
||||
}else{
|
||||
if (path.size()){ret += Encodings::URL::encode(path, "/:=@[]");}
|
||||
}
|
||||
ret += getEncodedPath();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -288,11 +296,7 @@ std::string HTTP::URL::getBase() const{
|
|||
tmpUrl = getBareUrl();
|
||||
}
|
||||
size_t slashPos = tmpUrl.rfind('/');
|
||||
if (slashPos == std::string::npos){
|
||||
tmpUrl += "/";
|
||||
}else{
|
||||
tmpUrl.erase(slashPos + 1);
|
||||
}
|
||||
tmpUrl.erase(slashPos + 1);
|
||||
return tmpUrl;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace HTTP{
|
|||
std::string getExt() const;
|
||||
std::string getUrl() const;
|
||||
std::string getFilePath() const;
|
||||
std::string getEncodedPath() const;
|
||||
std::string getBase() const;
|
||||
std::string getBareUrl() const;
|
||||
std::string getProxyUrl() const;
|
||||
|
|
210
test/meson.build
210
test/meson.build
|
@ -12,100 +12,132 @@ websockettest = executable('websockettest', 'websocket.cpp', dependencies: libmi
|
|||
# Actual unit tests
|
||||
|
||||
urltest = executable('urltest', 'url.cpp', dependencies: libmist_dep)
|
||||
test('url test google', urltest,
|
||||
env : ['Protocol=https', 'Host=google.com', 'Local=No', 'Port=443', 'Path=directory/', 'Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
args : ['https://google.com/directory/subdirectory/..'])
|
||||
test('url test schmerkel', urltest,
|
||||
env : ['Protocol=http', 'Host=root', 'Local=No', 'Port=80', 'Path=home/mo','Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
args : ['http://root/home/schmerkel/../mo'])
|
||||
test('url test relpath', urltest,
|
||||
env : ['Protocol=https', 'Host=relpath.com', 'Local=No', 'Port=443', 'Path=','Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
args : ['https://relpath.com/rel/lang/../..'])
|
||||
test('url test relpath missing dot', urltest,
|
||||
env : ['Protocol=https', 'Host=relpath.com', 'Local=No', 'Port=443', 'Path=', 'Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
args : ['https://relpath.com/rel/./..'])
|
||||
test('url test relpath 1', urltest,
|
||||
env : ['Protocol=https', 'Host=relpath.com', 'Local=No', 'Port=443', 'Path=','Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
args : ['https://relpath.com/1/..'])
|
||||
test('url test relpath 123', urltest,
|
||||
env : ['Protocol=https', 'Host=relpath.com', 'Local=No', 'Port=443', 'Path=','Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
args : ['https://relpath.com/123/..'])
|
||||
test('url test relpath 2', urltest,
|
||||
env : ['Protocol=https', 'Host=relpath.com', 'Local=No', 'Port=443', 'Path=','Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
args : ['https://relpath.com/rel/../..'])
|
||||
test('url test relpath langer pad', urltest,
|
||||
env : ['Protocol=https', 'Host=relpath.com', 'Local=No', 'Port=443', 'Path=langer/', 'Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
args : ['https://relpath.com/langer/pad/..'])
|
||||
test('url test authority 3000', urltest,
|
||||
env : ['Protocol=protocol', 'Host=authority.nl', 'Local=No', 'Port=3000', 'Path=path/to/some/file.cpp', 'Query=bool=true&int=3', 'Fragment=frag', 'Username=uname', 'Password=pwd'],
|
||||
args : ['protocol://uname:pwd@authority.nl:3000/path/to/err/../some/file.cpp?bool=true&int=3#frag'])
|
||||
test('url test authority path', urltest,
|
||||
env : ['Protocol=protocol', 'Host=authority.nl', 'Local=No', 'Port=0', 'Path=path/', 'Query=', 'Fragment=', 'Username=uname', 'Password=pwd'],
|
||||
args : ['protocol://uname:pwd@authority.nl/path/weird/./..'])
|
||||
test('url test authority path wierd', urltest,
|
||||
env : ['Protocol=protocol', 'Host=authority.nl', 'Local=No', 'Port=0', 'Path=path/weird/', 'Query=', 'Fragment=', 'Username=uname', 'Password=pwd'],
|
||||
args : ['protocol://uname:pwd@authority.nl/path/weird/a/..'])
|
||||
test('url test authority p&at#h/', urltest,
|
||||
env : ['Protocol=protocol', 'Host=authority.nl', 'Local=No', 'Port=0', 'Path=p&at#h/', 'Query=', 'Fragment=', 'Username=uname', 'Password=pwd'],
|
||||
args : ['protocol://uname:pwd@authority.nl/p%26at%23h/'])
|
||||
test('url test authority p at!h/', urltest,
|
||||
env : ['Protocol=protocol', 'Host=authority.nl', 'Local=No', 'Port=0', 'Path=p at!h/', 'Query=', 'Fragment=', 'Username=uname', 'Password=pwd'],
|
||||
args : ['protocol://uname:pwd@authority.nl/p%20at%21h/'])
|
||||
# KATRI TODO Cannot test pass as env ' %27 , need escape char for meson string ''
|
||||
test('url test authority !"#$%&()/', urltest,
|
||||
env : ['Protocol=protocol', 'Host=authority.nl', 'Local=No', 'Port=0', 'Path= !"#$%&()/','Query=', 'Fragment=', 'Username=uname', 'Password=pwd'],
|
||||
args : ['protocol://uname:pwd@authority.nl/%20%21%22%23%24%25%26%28%29/'])
|
||||
test('url test authority *+,-.//', urltest,
|
||||
env : ['Protocol=protocol', 'Host=authority.nl', 'Local=No', 'Port=0', 'Path=*+,-.//', 'Query=', 'Fragment=', 'Username=uname', 'Password=pwd'],
|
||||
args : ['protocol://uname:pwd@authority.nl/%2A%2B%2C%2D%2E%2F/'])
|
||||
test('url test authority 0123456789/', urltest,
|
||||
env : ['Protocol=protocol', 'Host=authority.nl', 'Local=No', 'Port=0', 'Path=0123456789/', 'Query=', 'Fragment=', 'Username=uname', 'Password=pwd'],
|
||||
args : ['protocol://uname:pwd@authority.nl/%30%31%32%33%34%35%36%37%38%39/'])
|
||||
test('url test authority _;<=>?@/', urltest,
|
||||
env : ['Protocol=protocol', 'Host=authority.nl', 'Local=No', 'Port=0', 'Path=:;<=>?@/', 'Query=', 'Fragment=', 'Username=uname', 'Password=pwd'],
|
||||
args : ['protocol://uname:pwd@authority.nl/%3A%3B%3C%3D%3E%3F%40/'])
|
||||
test('url test authority ABCDEFGHI/', urltest,
|
||||
env : ['Protocol=protocol', 'Host=authority.nl', 'Local=No', 'Port=0', 'Path=ABCDEFGHI/', 'Query=', 'Fragment=', 'Username=uname', 'Password=pwd'],
|
||||
args : ['protocol://uname:pwd@authority.nl/%41%42%43%44%45%46%47%48%49/'])
|
||||
test('url test doe/iets', urltest,
|
||||
env : ['Protocol=file', 'Host=google.com', 'Local=No', 'Port=0', 'Path=doe/iets', 'Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
args : ['file://google.com/doe/iets'])
|
||||
test('url test sub1/sub2/', urltest,
|
||||
env : ['Protocol=file', 'Host=google.com', 'Local=No', 'Port=0', 'Path=sub1/sub2/', 'Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
args : ['file://google.com/sub1/sub2/'])
|
||||
test('url test sub1/sub2/ anders', urltest,
|
||||
env : ['Protocol=file', 'Host=google.com', 'Local=No', 'Port=0', 'Path=sub1/sub2/www.wiki.com/anders', 'Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
args : ['file://google.com/sub1/sub2/www.wiki.com/anders'])
|
||||
test('url test sub1/sub2/ relatief', urltest,
|
||||
env : ['Protocol=file', 'Host=google.com', 'Local=No', 'Port=0', 'Path=sub1/sub2/www.wiki.com/relatief/', 'Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
args : ['file://google.com/sub1/sub2/www.wiki.com/relatief/'])
|
||||
test('url test absoluut', urltest,
|
||||
env : ['Protocol=file', 'Host=google.com', 'Local=No', 'Port=0', 'Path=absoluut/', 'Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
args : ['file://google.com/absoluut/'])
|
||||
test('url test absoluut relatiefFile', urltest,
|
||||
env : ['Protocol=file', 'Host=google.com', 'Local=No', 'Port=0', 'Path=absoluut/relatiefFile', 'Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
args : ['file://google.com/absoluut/relatiefFile'])
|
||||
test('url test path empty', urltest,
|
||||
env : ['Protocol=http', 'Host=www.wiki.com', 'Local=No', 'Port=80', 'Path=', 'Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
args : ['http://www.wiki.com/'])
|
||||
test('url test path emoticons', urltest,
|
||||
env : ['Protocol=protocol', 'Host=authority.nl', 'Local=No', 'Port=0', 'Path=😋😄😡😵/', 'Query=', 'Fragment=', 'Username=uname', 'Password=pwd'],
|
||||
args : ['protocol://uname:pwd@authority.nl/😋😄😡😵/'])
|
||||
test('url test rtmp 1', urltest,
|
||||
env : ['Protocol=https', 'Host=2001:db8::1', 'Local=No', 'Port=159', 'Path=', 'Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
urltest_vm = {'T_PATH':'', 'T_QUERY':'', 'T_FRAG':'', 'T_USER':'', 'T_PASS':'', 'T_NORM':'', 'T_EXT':''}
|
||||
urltest_v = urltest_vm + {'T_PROTO':'', 'T_HOST':'', 'T_PORT':'0'}
|
||||
test('HTTPS URL with parent directory', urltest, suite: 'URL parser',
|
||||
env: urltest_v + {'T_PROTO':'https', 'T_HOST':'google.com', 'T_PORT':'443', 'T_PATH':'directory/', 'T_NORM':'https://google.com/directory/'},
|
||||
args: ['https://google.com/directory/subdirectory/..'])
|
||||
test('Partially cancelled out path', urltest, suite: 'URL parser',
|
||||
env: urltest_v + {'T_PROTO':'http', 'T_HOST':'root', 'T_PORT':'80', 'T_PATH':'home/mo', 'T_NORM':'http://root/home/mo'},
|
||||
args: ['http://root/home/schmerkel/../mo'])
|
||||
urltest_relpath = urltest_v + {'T_PROTO':'https', 'T_HOST':'relpath.com', 'T_PORT':'443', 'T_NORM':'https://relpath.com/'}
|
||||
test('Fully cancelled out path', urltest, suite: 'URL parser',
|
||||
env: urltest_relpath,
|
||||
args: ['https://relpath.com/rel/lang/../..'])
|
||||
test('Current directory reference stripping', urltest, suite: 'URL parser',
|
||||
env: urltest_relpath,
|
||||
args: ['https://relpath.com/rel/./..'])
|
||||
test('Empty directory stripping', urltest, suite: 'URL parser',
|
||||
env: urltest_relpath,
|
||||
args: ['https://relpath.com/////'])
|
||||
test('Numerical path deletion', urltest, suite: 'URL parser',
|
||||
env: urltest_relpath,
|
||||
args: ['https://relpath.com/123/..'])
|
||||
test('Leading single char path deletion', urltest, suite: 'URL parser',
|
||||
env: urltest_relpath,
|
||||
args: ['https://relpath.com/a/..'])
|
||||
test('Trailing current dir path deletion', urltest, suite: 'URL parser',
|
||||
env: urltest_relpath,
|
||||
args: ['https://relpath.com/.'])
|
||||
test('Trailing current dir path deletion', urltest, suite: 'URL parser',
|
||||
env: urltest_v + {'T_PATH':'bla/', 'T_NORM':'/bla/'},
|
||||
args: ['///bla/.'])
|
||||
test('Extension', urltest, suite: 'URL parser',
|
||||
env: urltest_v + {'T_EXT':'mp4', 'T_PATH':'test.mp4', 'T_NORM':'/test.mp4'},
|
||||
args: ['///test.mp4'])
|
||||
test('Parent of root directory', urltest, suite: 'URL parser',
|
||||
env: urltest_relpath,
|
||||
args: ['https://relpath.com/rel/../..'])
|
||||
test('All URL components present', urltest, suite: 'URL parser',
|
||||
env: {'T_PROTO':'prot', 'T_HOST':'a.bc', 'T_PORT':'3000', 'T_PATH':'path/to/some/file.cpp', 'T_QUERY':'bool=true&int=3', 'T_FRAG':'frag', 'T_USER':'uname', 'T_PASS':'pwd', 'T_NORM':'prot://uname:pwd@a.bc:3000/path/to/some/file.cpp?bool=true&int=3#frag'},
|
||||
args: ['prot://uname:pwd@a.bc:3000/path/to/err/../some/file.cpp?bool=true&int=3#frag'])
|
||||
test('Unknown port for custom protocol', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'prot', 'T_HOST':'authority.nl', 'T_PATH':'path/', 'T_NORM':'prot://authority.nl/path/'},
|
||||
args : ['prot://authority.nl/path/weird/./..'])
|
||||
test('Query/fragment chars before ? char (escaped)', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'prot', 'T_HOST':'authority.nl', 'T_PATH':'p&a=t#h/', 'T_NORM':'prot://authority.nl/p%26a=t%23h/'},
|
||||
args : ['prot://authority.nl/p%26a=t%23h/'])
|
||||
test('Query/fragment chars before ? char (unescaped)', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'prot', 'T_HOST':'authority.nl', 'T_PATH':'p&a=t', 'T_FRAG':'h/', 'T_NORM':'prot://authority.nl/p%26a=t#h/'},
|
||||
args : ['prot://authority.nl/p&a=t#h/'])
|
||||
test('Path with spaces', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'prot', 'T_HOST':'authority.nl', 'T_PATH':'p at!h/', 'T_NORM':'prot://authority.nl/p+at!h/'},
|
||||
args : ['prot://authority.nl/p%20at%21h/'])
|
||||
test('Escaped characters', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'prot', 'T_HOST':'authority.nl', 'T_PATH':' !"#$%&()/*+,-.//0123456789/:;<=>?@/', 'T_NORM':'prot://authority.nl/+!%22%23$%25%26()/*%2b,-.//0123456789/:;%3c=%3e%3f@/'},
|
||||
args : ['prot://authority.nl/%20%21%22%23%24%25%26%28%29/%2A%2B%2C%2D%2E%2F/%30%31%32%33%34%35%36%37%38%39/%3A%3B%3C%3D%3E%3F%40/'])
|
||||
test('Linking / Absolute', urltest, suite: 'URL parser',
|
||||
env : urltest_vm + {'T_PATH':'sub1/sub2/', 'T_NORM':'/sub1/sub2/'},
|
||||
args : ['file://google.com/doe/iets', '/sub1/sub2/'])
|
||||
test('Linking / Relative', urltest, suite: 'URL parser',
|
||||
env : urltest_vm + {'T_PATH':'sub1/sub2/www.wiki.com/anders', 'T_NORM':'/sub1/sub2/www.wiki.com/anders'},
|
||||
args : ['file://google.com/doe/iets', '/sub1/sub2/', 'www.wiki.com/anders'])
|
||||
test('Linking / Relative with current and parent dir', urltest, suite: 'URL parser',
|
||||
env : urltest_vm + {'T_PATH':'sub1/sub2/relatief/', 'T_NORM':'/sub1/sub2/relatief/'},
|
||||
args : ['file://google.com/doe/iets', '/sub1/sub2/', 'www.wiki.com/anders', './../relatief/'])
|
||||
test('Linking / Relative file in absolute directory', urltest, suite: 'URL parser',
|
||||
env : urltest_vm + {'T_PATH':'absoluut/relatiefFile', 'T_NORM':'/absoluut/relatiefFile'},
|
||||
args : ['file://google.com/doe/iets', '/sub1/sub2/', 'www.wiki.com/anders', './../relatief/', '/absoluut/', 'relatiefFile'])
|
||||
test('Linking / Protocol switch', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'http', 'T_HOST':'www.wiki.com', 'T_PORT':'80', 'T_NORM':'http://www.wiki.com/'},
|
||||
args : ['file://google.com/doe/iets', '/absoluut/', 'relatiefFile', 'http://www.wiki.com'])
|
||||
test('Linking / Protocol absolute', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'http', 'T_HOST':'example.com', 'T_PORT':'80', 'T_NORM':'http://example.com/'},
|
||||
args : ['http://www.wiki.com', '//example.com'])
|
||||
test('UTF-8 emoji in path', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'prot', 'T_HOST':'authority.nl', 'T_PATH':'😋😄😡😵/', 'T_NORM':'prot://authority.nl/%f0%9f%98%8b%f0%9f%98%84%f0%9f%98%a1%f0%9f%98%b5/'},
|
||||
args : ['prot://authority.nl/😋😄😡😵/'])
|
||||
test('UTF-8 reverse char in path', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'prot', 'T_HOST':'a.nl', 'T_PATH':'reversereverse/', 'T_NORM':'prot://a.nl/reverse%e2%80%8freverse/'},
|
||||
args : ['prot://a.nl/reverse%E2%80%8Freverse/'])
|
||||
test('IPv6 address', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'https', 'T_HOST':'2001:db8::1', 'T_PORT':'159', 'T_NORM':'https://[2001:db8::1]:159/'},
|
||||
args : ['https://[2001:db8::1]:159/'])
|
||||
test('url test rtpm 2', urltest,
|
||||
env : ['Protocol=rtmp', 'Host=2001:db8::1', 'Local=No', 'Port=1935', 'Path=','Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
test('IPv6 address with non-numeric port', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'https', 'T_HOST':'2001:db8::aa', 'T_PORT':'443', 'T_NORM':'https://[2001:db8::aa]/'},
|
||||
args : ['https://[2001:db8:]:aa/'])
|
||||
test('Bare IPv6 address', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'https', 'T_HOST':'2001:db8::1', 'T_PORT':'159', 'T_NORM':'https://[2001:db8::1]:159/'},
|
||||
args : ['https://2001:db8::1:159/'])
|
||||
test('Bare hexadecimal IPv6 address', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'https', 'T_HOST':'2001:db8::aa', 'T_PORT':'443', 'T_NORM':'https://[2001:db8::aa]/'},
|
||||
args : ['https://2001:db8::aa/'])
|
||||
test('Username but no password', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'http', 'T_HOST':'b', 'T_PORT':'80', 'T_USER':'a', 'T_NORM':'http://a@b/'},
|
||||
args : ['http://a@b'])
|
||||
test('Username and password linking', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'http', 'T_HOST':'c', 'T_PORT':'80', 'T_PASS':'b', 'T_USER':'a', 'T_NORM':'http://a:b@c/test', 'T_PATH':'test'},
|
||||
args : ['http://a:b@c', 'test'])
|
||||
test('Username but no password linking', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'http', 'T_HOST':'c', 'T_PORT':'80', 'T_USER':'a', 'T_NORM':'http://a@c/test', 'T_PATH':'test'},
|
||||
args : ['http://a@c', 'test'])
|
||||
test('Protocol-absolute base', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'', 'T_HOST':'test', 'T_NORM':'//test/'},
|
||||
args : ['//test'])
|
||||
test('Bare port number', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PORT':'42', 'T_NORM':'//:42/'},
|
||||
args : ['42'])
|
||||
test('Bare port number linking', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PORT':'42', 'T_NORM':'//:42/test', 'T_PATH':'test'},
|
||||
args : ['42', 'test'])
|
||||
test('Query string without path', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'', 'T_HOST':'test', 'T_QUERY':'test=test', 'T_NORM':'//test/?test=test'},
|
||||
args : ['//test?test=test'])
|
||||
test('RTMP IPv6 address', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'rtmp', 'T_HOST':'2001:db8::1', 'T_PORT':'1935', 'T_NORM':'rtmp://[2001:db8::1]/'},
|
||||
args : ['rtmp://[2001:db8::1]/'])
|
||||
test('url test rtpms', urltest,
|
||||
env : ['Protocol=rtmps', 'Host=2001:db8::1', 'Local=No', 'Port=443', 'Path=', 'Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
test('RTMPS', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'rtmps', 'T_HOST':'2001:db8::1', 'T_PORT':'443', 'T_NORM':'rtmps://[2001:db8::1]/'},
|
||||
args : ['rtmps://[2001:db8::1]/'])
|
||||
test('url test rtpm 2', urltest,
|
||||
env : ['Protocol=dtsc', 'Host=2001:db8::1', 'Local=No', 'Port=4200', 'Path=', 'Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
test('DTSC', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'dtsc', 'T_HOST':'2001:db8::1', 'T_PORT':'4200', 'T_NORM':'dtsc://[2001:db8::1]/'},
|
||||
args : ['dtsc://[2001:db8::1]/'])
|
||||
test('url test rtsp', urltest,
|
||||
env : ['Protocol=rtsp', 'Host=2001:db8::1', 'Local=No', 'Port=554', 'Path=', 'Query=', 'Fragment=', 'Username=', 'Password='],
|
||||
test('RTSP', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'rtsp', 'T_HOST':'2001:db8::1', 'T_PORT':'554', 'T_NORM':'rtsp://[2001:db8::1]/'},
|
||||
args : ['rtsp://[2001:db8::1]/'])
|
||||
test('RTSP linking', urltest, suite: 'URL parser',
|
||||
env : urltest_v + {'T_PROTO':'rtsp', 'T_HOST':'2001:db8::1', 'T_PORT':'554', 'T_NORM':'rtsp://[2001:db8::1]/test', 'T_PATH':'test'},
|
||||
args : ['rtsp://[2001:db8::1]/', 'test'])
|
||||
|
||||
|
||||
|
||||
|
|
69
test/url.cpp
69
test/url.cpp
|
@ -1,7 +1,34 @@
|
|||
#include "../lib/http_parser.cpp"
|
||||
#include <cassert>
|
||||
#include <mist/url.h>
|
||||
#include <mist/http_parser.h>
|
||||
#include <mist/json.h>
|
||||
#include <iostream>
|
||||
|
||||
/// Helper function that compares an environment variable against a string
|
||||
int checkStr(const char * envVar, const std::string & str){
|
||||
//Ignore test when no expected value set
|
||||
if (!getenv(envVar)){return 0;}
|
||||
//Environment value exists, do check
|
||||
if (str != getenv(envVar)){
|
||||
//Print error message on mismatch, detailing problem
|
||||
std::cerr << "ERROR: Value of " << envVar << " should be '" << getenv(envVar) << "' but was '" << str << "'" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Helper function that compares an environment variable against an integer
|
||||
int checkInt(const char * envVar, const uint64_t i){
|
||||
//Ignore test when no expected value set
|
||||
if (!getenv(envVar)){return 0;}
|
||||
//Environment value exists, do check
|
||||
if (i != JSON::Value(getenv(envVar)).asInt()){
|
||||
//Print error message on mismatch, detailing problem
|
||||
std::cerr << "ERROR: Value of " << envVar << " should be '" << getenv(envVar) << "' but was '" << i << "'" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
if (argc < 2){
|
||||
std::cout << "Usage: " << argv[0] << " URL" << std::endl;
|
||||
|
@ -9,34 +36,38 @@ int main(int argc, char **argv){
|
|||
}
|
||||
HTTP::URL u(argv[1]);
|
||||
for (int i = 1; i < argc; ++i){
|
||||
HTTP::URL prev = u;
|
||||
if (i > 1){u = u.link(argv[i]);}
|
||||
std::cout << argv[i] << " -> " << u.getUrl() << std::endl;
|
||||
std::cout << argv[i] << " -> " << (u.isLocalPath()?u.getFilePath():u.getUrl()) << std::endl;
|
||||
if (i > 1){
|
||||
std::cout << "Link from previous: " << u.getLinkFrom(prev) << std::endl;
|
||||
}
|
||||
std::cout << "Proxied URL: " << u.getProxyUrl() << std::endl;
|
||||
std::cout << "Protocol: " << u.protocol << std::endl;
|
||||
std::cout << "Host: " << u.host << " (Local: " << (Socket::isLocalhost(u.host) ? "Yes" : "No")
|
||||
<< ")" << std::endl;
|
||||
std::cout << "Port: " << u.getPort() << std::endl;
|
||||
std::cout << "Path: " << u.path << std::endl;
|
||||
std::cout << "Extension: " << u.getExt() << std::endl;
|
||||
std::cout << "Query: " << u.args << std::endl;
|
||||
std::cout << "Fragment: " << u.frag << std::endl;
|
||||
std::cout << "Username: " << u.user << std::endl;
|
||||
std::cout << "Password: " << u.pass << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
assert(u.protocol == std::getenv("Protocol"));
|
||||
assert(u.host == std::getenv("Host"));
|
||||
std::string ulocal;
|
||||
Socket::isLocalhost(u.host) ? ulocal = "Yes" : ulocal = "No";
|
||||
assert(ulocal == std::getenv("Local"));
|
||||
uint16_t uport = 0;
|
||||
std::stringstream ss(std::getenv("Port"));
|
||||
ss >> uport;
|
||||
assert(u.getPort() == uport);
|
||||
assert(u.path == std::getenv("Path"));
|
||||
assert(u.args == std::getenv("Query"));
|
||||
assert(u.frag == std::getenv("Fragment"));
|
||||
assert(u.user == std::getenv("Username"));
|
||||
assert(u.pass == std::getenv("Password"));
|
||||
|
||||
}
|
||||
return 0;
|
||||
|
||||
int ret = 0;
|
||||
//These checks only run when the environment variable corresponding to them is set
|
||||
ret += checkStr("T_PROTO", u.protocol);
|
||||
ret += checkStr("T_HOST", u.host);
|
||||
ret += checkInt("T_PORT", u.getPort());
|
||||
ret += checkStr("T_PATH", u.path);
|
||||
ret += checkStr("T_QUERY", u.args);
|
||||
ret += checkStr("T_FRAG", u.frag);
|
||||
ret += checkStr("T_USER", u.user);
|
||||
ret += checkStr("T_PASS", u.pass);
|
||||
ret += checkStr("T_EXT", u.getExt());
|
||||
ret += checkStr("T_NORM", u.isLocalPath()?u.getFilePath():u.getUrl());
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue