blob: 6c8a6f8bd1b06893363cde7481cfb279f204423b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "pagespeed/kernel/http/data_url.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/http/content_type.h"
namespace net_instaweb {
namespace {
const GoogleString kAsciiData =
"A_Rather=Long,But-conventional?looking_string#with;some:odd,characters.";
const GoogleString kAsciiDataBase64 =
"QV9SYXRoZXI9TG9uZyxCdXQtY29udmVudGlvbmFsP2xvb2tpbmdfc3RyaW5nI3dpdGg7c29"
"tZTpvZGQsY2hhcmFjdGVycy4=";
// A string with embedded NULs; we must construct it carefully to avoid
// truncation.
const char kMixedDataChars[] =
"This string\ncontains\0lots of\tunusual\xe3~characters\xd7\xa5";
const char kMixedDataBase64[] =
"VGhpcyBzdHJpbmcKY29udGFpbnMAbG90cyBvZgl1bnVzdWFs435jaGFyYWN0ZXJz16U=";
const char kPlainPrefix[] = "data:text/plain,";
const char kBase64Prefix[] = "data:text/plain;base64,";
const char kGifPlainPrefix[] = "data:image/gif,";
const char kGifBase64Prefix[] = "data:image/gif;base64,";
class DataUrlTest : public testing::Test {
public:
DataUrlTest()
: mixed_data_(kMixedDataChars, STATIC_STRLEN(kMixedDataChars)) { }
protected:
// Make a ContentType yield readable failure output. Needed this to fix bugs
// in the tests! (No actual program bugs found here...)
const char* Mime(const ContentType* type) {
if (type == NULL || type->mime_type() == NULL) {
return "NULL";
} else {
return type->mime_type();
}
}
void TestDecoding(const bool can_parse,
const bool can_decode,
const GoogleString& prefix,
const GoogleString& encoded,
const ContentType* type,
Encoding encoding,
const GoogleString& decoded) {
GoogleString url = prefix + encoded;
const ContentType* parsed_type;
Encoding parsed_encoding = UNKNOWN;
StringPiece parsed_encoded;
EXPECT_EQ(can_parse,
ParseDataUrl(url, &parsed_type,
&parsed_encoding, &parsed_encoded));
EXPECT_EQ(encoding, parsed_encoding);
EXPECT_EQ(type, parsed_type) << "type '" << Mime(type) <<
"' didn't match '" << Mime(parsed_type) << "'\n";
EXPECT_EQ(encoded, parsed_encoded);
GoogleString parsed_decoded;
EXPECT_EQ(can_decode,
DecodeDataUrlContent(encoding, parsed_encoded, &parsed_decoded));
EXPECT_EQ(decoded, parsed_decoded);
}
GoogleString mixed_data_;
private:
DISALLOW_COPY_AND_ASSIGN(DataUrlTest);
};
TEST_F(DataUrlTest, TestDataPlain) {
GoogleString url;
DataUrl(kContentTypeText, PLAIN, kAsciiData, &url);
EXPECT_EQ(kPlainPrefix + kAsciiData, url);
}
TEST_F(DataUrlTest, TestDataBase64) {
GoogleString url;
DataUrl(kContentTypeText, BASE64, kAsciiData, &url);
EXPECT_EQ(kBase64Prefix + kAsciiDataBase64, url);
}
TEST_F(DataUrlTest, TestData1Plain) {
GoogleString url;
DataUrl(kContentTypeGif, PLAIN, mixed_data_, &url);
EXPECT_EQ(kGifPlainPrefix + mixed_data_, url);
}
TEST_F(DataUrlTest, TestData1Base64) {
GoogleString url;
DataUrl(kContentTypeGif, BASE64, mixed_data_, &url);
EXPECT_EQ(StrCat(kGifBase64Prefix, kMixedDataBase64), url);
}
TEST_F(DataUrlTest, ParseDataPlain) {
TestDecoding(true, true, kPlainPrefix, kAsciiData,
&kContentTypeText, PLAIN, kAsciiData);
}
TEST_F(DataUrlTest, ParseDataBase64) {
TestDecoding(true, true, kBase64Prefix, kAsciiDataBase64,
&kContentTypeText, BASE64, kAsciiData);
}
TEST_F(DataUrlTest, ParseData1Plain) {
TestDecoding(true, true, kPlainPrefix, mixed_data_,
&kContentTypeText, PLAIN, mixed_data_);
}
TEST_F(DataUrlTest, ParseData1Base64) {
TestDecoding(true, true, kBase64Prefix, kMixedDataBase64,
&kContentTypeText, BASE64, mixed_data_);
}
TEST_F(DataUrlTest, ParseBadProtocol) {
TestDecoding(false, false, "http://www.google.com/", "",
NULL, UNKNOWN, "");
}
TEST_F(DataUrlTest, ParseNoComma) {
TestDecoding(false, false,
StrCat("data:text/plain;base64;", kMixedDataBase64), "",
NULL, UNKNOWN, "");
}
TEST_F(DataUrlTest, ParseNoMime) {
TestDecoding(true, true, "data:;base64,", kMixedDataBase64,
NULL, BASE64, mixed_data_);
}
TEST_F(DataUrlTest, ParseCorruptMime) {
TestDecoding(true, true, "data:#$!;base64,", kMixedDataBase64,
NULL, BASE64, mixed_data_);
}
TEST_F(DataUrlTest, ParseBadEncodingIsPlain) {
TestDecoding(true, true, "data:text/plain;mumbledypeg,", mixed_data_,
&kContentTypeText, PLAIN, mixed_data_);
}
TEST_F(DataUrlTest, ParseBadBase64) {
TestDecoding(true, false, kBase64Prefix, "@%#$%@#$%^@%%^%*%^&*",
&kContentTypeText, BASE64, "");
}
} // namespace
} // namespace net_instaweb