blob: 9783bec3f65ad0e85281c138b75a45a01054f70f [file] [log] [blame]
/*
* Copyright 2010 Google Inc.
*
* 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.
*/
// Unit-test QueryParams.
#include "pagespeed/kernel/http/query_params.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/google_url.h"
namespace {
const char kQueryUrl[] = "http://test.com/?a=1&b&c=2&d=&a=3";
const char kGoodQueryString[] = "x=1&y&z=&x=2";
const char kBadQueryString[] = "a=1\n2&b&c=\"<! ^>\"\r3&d=\t&a=3#4";
const char kSanitizedBadQueryString[] = "a=12&b&c=%22%3C!%20^%3E%223&d=&a=3";
} // namespace
namespace net_instaweb {
class QueryParamsTest : public testing::Test {
protected:
QueryParamsTest() { }
virtual void SetUp() {
gurl_.Reset(kQueryUrl);
query_params_.ParseFromUrl(gurl_);
}
GoogleUrl gurl_;
QueryParams query_params_;
private:
DISALLOW_COPY_AND_ASSIGN(QueryParamsTest);
};
TEST_F(QueryParamsTest, TestParseFromUrl) {
ASSERT_EQ(5, query_params_.size());
EXPECT_STREQ("a", query_params_.name(0));
EXPECT_STREQ("1", *(query_params_.EscapedValue(0)));
EXPECT_STREQ("b", query_params_.name(1));
EXPECT_EQ(NULL, query_params_.EscapedValue(1));
EXPECT_STREQ("c", query_params_.name(2));
EXPECT_STREQ("2", *(query_params_.EscapedValue(2)));
EXPECT_STREQ("d", query_params_.name(3));
EXPECT_STREQ("", *(query_params_.EscapedValue(3)));
EXPECT_STREQ("a", query_params_.name(4));
EXPECT_STREQ("3", *(query_params_.EscapedValue(4)));
EXPECT_STREQ(gurl_.Query(), query_params_.ToEscapedString());
}
TEST_F(QueryParamsTest, TestParseFromUntrustedString) {
// First try a string that doesn't have anything "unsafe".
QueryParams query_params1;
query_params1.ParseFromUntrustedString(kGoodQueryString);
ASSERT_EQ(4, query_params1.size());
EXPECT_STREQ("x", query_params1.name(0));
EXPECT_STREQ("1", *query_params1.EscapedValue(0));
EXPECT_STREQ("y", query_params1.name(1));
EXPECT_EQ(NULL, query_params1.EscapedValue(1));
EXPECT_STREQ("z", query_params1.name(2));
EXPECT_STREQ("", *query_params1.EscapedValue(2));
EXPECT_STREQ("x", query_params1.name(3));
EXPECT_STREQ("2", *query_params1.EscapedValue(3));
EXPECT_STREQ(kGoodQueryString, query_params1.ToEscapedString());
// Now try a string that has crazy stuff in it.
QueryParams query_params2;
query_params2.ParseFromUntrustedString(kBadQueryString);
ASSERT_EQ(5, query_params2.size());
EXPECT_STREQ("a", query_params2.name(0));
EXPECT_STREQ("12", *query_params2.EscapedValue(0));
EXPECT_STREQ("b", query_params2.name(1));
EXPECT_EQ(NULL, query_params2.EscapedValue(1));
EXPECT_STREQ("c", query_params2.name(2));
EXPECT_STREQ("%22%3C!%20^%3E%223", *query_params2.EscapedValue(2));
EXPECT_STREQ("d", query_params2.name(3));
EXPECT_STREQ("", *query_params2.EscapedValue(3));
EXPECT_STREQ("a", query_params2.name(4));
EXPECT_STREQ("3", *query_params2.EscapedValue(4));
EXPECT_STREQ(kSanitizedBadQueryString, query_params2.ToEscapedString());
}
TEST_F(QueryParamsTest, TestLookup) {
ConstStringStarVector v;
ASSERT_TRUE(query_params_.LookupEscaped("a", &v));
ASSERT_EQ(2, v.size());
EXPECT_STREQ("1", *(v[0]));
EXPECT_STREQ("3", *(v[1]));
ASSERT_TRUE(query_params_.LookupEscaped("b", &v));
ASSERT_EQ(1, v.size());
EXPECT_EQ(NULL, v[0]);
ASSERT_TRUE(query_params_.LookupEscaped("c", &v));
ASSERT_EQ(1, v.size());
EXPECT_STREQ("2", *(v[0]));
ASSERT_TRUE(query_params_.LookupEscaped("d", &v));
ASSERT_EQ(1, v.size());
EXPECT_STREQ("", *(v[0]));
}
TEST_F(QueryParamsTest, TestRemove) {
query_params_.RemoveAll("a");
EXPECT_STREQ("b&c=2&d=", query_params_.ToEscapedString());
EXPECT_EQ(3, query_params_.size());
query_params_.RemoveAll("b");
EXPECT_STREQ("c=2&d=", query_params_.ToEscapedString());
EXPECT_EQ(2, query_params_.size());
query_params_.RemoveAll("c");
EXPECT_STREQ("d=", query_params_.ToEscapedString());
EXPECT_EQ(1, query_params_.size());
query_params_.RemoveAll("d");
EXPECT_STREQ("", query_params_.ToEscapedString());
EXPECT_EQ(0, query_params_.size());
}
TEST_F(QueryParamsTest, TestClear) {
query_params_.Clear();
EXPECT_STREQ("", query_params_.ToEscapedString());
EXPECT_EQ(0, query_params_.size());
}
TEST_F(QueryParamsTest, TestAEqualsBEquals1) {
GoogleUrl gurl("http://test.com/?a=b=1");
ASSERT_TRUE(gurl.IsWebValid());
query_params_.Clear();
query_params_.ParseFromUrl(gurl);
ASSERT_EQ(1, query_params_.size());
ASSERT_EQ(GoogleString("a"), query_params_.name(0));
ASSERT_EQ(GoogleString("b=1"), *(query_params_.EscapedValue(0)));
}
TEST_F(QueryParamsTest, EscapedQuery) {
GoogleUrl gurl("http://example.com/a?b=<value requiring escapes>");
ASSERT_TRUE(gurl.IsWebValid());
// Note that GoogleUrl::Escape will turn " " into "+", but the escaper
// built into the GoogleUrl constructor will turn " " into "%20".
EXPECT_STREQ("b=%3Cvalue%20requiring%20escapes%3E", gurl.Query());
query_params_.Clear();
query_params_.ParseFromUrl(gurl);
ASSERT_EQ(1, query_params_.size());
EXPECT_STREQ("b", query_params_.name(0));
GoogleString unescaped_value;
ASSERT_TRUE(query_params_.UnescapedValue(0, &unescaped_value));
EXPECT_STREQ("<value requiring escapes>", unescaped_value);
}
TEST_F(QueryParamsTest, QueryParamWithAndWithoutValues) {
GoogleUrl gurl("http://example.com/a?b=c&d&e=&f");
ASSERT_TRUE(gurl.IsWebValid());
query_params_.Clear();
query_params_.ParseFromUrl(gurl);
GoogleString unescaped;
// A normal query param, b=c, we get back "c".
EXPECT_STREQ("b", query_params_.name(0));
EXPECT_STREQ("c", *query_params_.EscapedValue(0));
EXPECT_TRUE(query_params_.UnescapedValue(0, &unescaped));
EXPECT_STREQ("c", unescaped);
// "d" does not have an equals sign. NULL is returned for the value.
EXPECT_STREQ("d", query_params_.name(1));
EXPECT_TRUE(NULL == query_params_.EscapedValue(1));
EXPECT_FALSE(query_params_.UnescapedValue(1, &unescaped));
// "e" has an equals sign, but no value before the next "&", so
// we get back an empty string.
EXPECT_STREQ("e", query_params_.name(2));
EXPECT_STREQ("", *query_params_.EscapedValue(2));
EXPECT_TRUE(query_params_.UnescapedValue(2, &unescaped));
EXPECT_STREQ("", unescaped);
}
} // namespace net_instaweb