PageRenderTime 27ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/pagespeed/testing/pagespeed_test.h

http://page-speed.googlecode.com/
C Header | 360 lines | 217 code | 59 blank | 84 comment | 2 complexity | 222fac6ec0cb36d5caed6c18fcc35468 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, CC-BY-SA-3.0, LGPL-3.0
  1. // Copyright 2010 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #ifndef PAGESPEED_TESTING_PAGESPEED_TEST_H_
  15. #define PAGESPEED_TESTING_PAGESPEED_TEST_H_
  16. #include <map>
  17. #include <string>
  18. #include <vector>
  19. #include "base/at_exit.h"
  20. #include "base/memory/scoped_ptr.h"
  21. #include "pagespeed/core/image_attributes.h"
  22. #include "pagespeed/core/pagespeed_input.h"
  23. #include "pagespeed/core/resource.h"
  24. #include "pagespeed/core/result_provider.h"
  25. #include "pagespeed/core/rule.h"
  26. #include "pagespeed/core/rule_input.h"
  27. #include "pagespeed/proto/pagespeed_output.pb.h"
  28. #include "pagespeed/proto/pagespeed_proto_formatter.pb.h"
  29. #include "pagespeed/testing/fake_dom.h"
  30. #include "testing/gtest/include/gtest/gtest.h"
  31. namespace pagespeed {
  32. class Resource;
  33. class TopLevelBrowsingContext;
  34. } // namespace pagespeed
  35. namespace pagespeed_testing {
  36. void AssertProtoEq(const ::google::protobuf::MessageLite& a,
  37. const ::google::protobuf::MessageLite& b);
  38. // Helper method that simply invokes ASSERT_TRUE. Can be used in
  39. // functions that have a non-void return type (ASSERT_TRUE requires
  40. // its containing function to have a void return type).
  41. void AssertTrue(bool condition);
  42. // Read the file at the given path (relative to the root of the source
  43. // tree) into the dest buffer. Uses the --srcroot flag to determine
  44. // the proper location of the root of the source tree.
  45. bool ReadFileToString(const std::string& filename, std::string *dest);
  46. class FakeImageAttributesFactory
  47. : public pagespeed::ImageAttributesFactory {
  48. public:
  49. typedef std::map<const pagespeed::Resource*, std::pair<int,int> >
  50. ResourceSizeMap;
  51. explicit FakeImageAttributesFactory(const ResourceSizeMap& resource_size_map)
  52. : resource_size_map_(resource_size_map) {
  53. }
  54. virtual pagespeed::ImageAttributes* NewImageAttributes(
  55. const pagespeed::Resource* resource) const;
  56. private:
  57. ResourceSizeMap resource_size_map_;
  58. };
  59. // Helper method that returns the output from a TextFormatter for
  60. // the given Rule and Results.
  61. std::string DoFormatResultsAsText(pagespeed::Rule* rule,
  62. const pagespeed::RuleResults& rule_results);
  63. void DoFormatResultsAsProto(pagespeed::Rule* rule,
  64. const pagespeed::RuleResults& rule_results,
  65. pagespeed::FormattedResults* formatted_results);
  66. class PagespeedTest : public ::testing::Test {
  67. protected:
  68. // Some sample URLs that tests may choose to use.
  69. static const char* kUrl1;
  70. static const char* kUrl2;
  71. static const char* kUrl3;
  72. static const char* kUrl4;
  73. PagespeedTest();
  74. virtual ~PagespeedTest();
  75. // Derived classes should not override SetUp and TearDown. Derived
  76. // classes should override DoSetUp and DoTearDown instead.
  77. virtual void SetUp();
  78. virtual void TearDown();
  79. // Hooks for derived classes to override.
  80. virtual void DoSetUp();
  81. virtual void DoTearDown();
  82. // Freeze the PagespeedInput structure.
  83. virtual void Freeze();
  84. virtual void Freeze(bool expected_result);
  85. // Construct a new HTTP GET Resource with the specified URL and
  86. // status code, and add that resource to our PagespeedInput.
  87. // Return NULL if the resource was unable to be created or added to
  88. // the PagespeedInput.
  89. pagespeed::Resource* NewResource(const std::string& url, int status_code);
  90. // Construct the primary resource, an HTTP GET HTML
  91. // resource with a 200 status code. An associated FakeDomDocument
  92. // will be created for this resource, which is stored as the DOM
  93. // document of the PagespeedInput. The FakeDomDocument is available
  94. // via the document() method. This method must only be called once
  95. // per test.
  96. pagespeed::Resource* NewPrimaryResource(const std::string& url);
  97. // Construct an HTTP GET HTML resource with a 200 status code. An
  98. // associated FakeDomDocument will be created for this resource,
  99. // parented under the specified iframe and returned via the
  100. // out_document parameter, if specified.
  101. pagespeed::Resource* NewDocumentResource(const std::string& url,
  102. FakeDomElement* iframe = NULL,
  103. FakeDomDocument** out = NULL);
  104. // Construct a new HTTP GET Resource with the specified URL and
  105. // a 200 status code, and add that resource to our PagespeedInput.
  106. pagespeed::Resource* New200Resource(const std::string& url);
  107. // Construct a new HTTP GET redirect (302) Resource with the
  108. // specified source and destination URLs, and add that resource
  109. // to our PagespeedInput.
  110. pagespeed::Resource* New302Resource(const std::string& source,
  111. const std::string& destination);
  112. // Construct a new HTTP GET image (PNG) resource, and add that
  113. // resource to our PagespeedInput. Also create an associated DOM
  114. // node, parented under the specified parent, and returned via the
  115. // out parameter, if specified.
  116. pagespeed::Resource* NewPngResource(const std::string& url,
  117. FakeDomElement* parent = NULL,
  118. FakeDomElement** out = NULL);
  119. // Much like NewPngResource, but creates two resources -- a redirect from
  120. // url1 to url2, and a PNG at url2 -- and creates an IMG element with
  121. // src=url1. This is useful for testing that a rule is able to get the
  122. // content/dimensions/etc. of the image even though the DOM node refers to
  123. // the URL of the redirect rather than the actual image resource.
  124. pagespeed::Resource* NewRedirectedPngResource(const std::string& url1,
  125. const std::string& url2,
  126. FakeDomElement* parent = NULL,
  127. FakeDomElement** out = NULL);
  128. // Construct a new HTTP GET script resource, and add that
  129. // resource to our PagespeedInput. Also create an associated DOM
  130. // node, parented under the specified parent, and returned via the
  131. // out parameter, if specified.
  132. pagespeed::Resource* NewScriptResource(const std::string& url,
  133. FakeDomElement* parent = NULL,
  134. FakeDomElement** out = NULL);
  135. // Construct a new HTTP GET CSS resource, and add that
  136. // resource to our PagespeedInput. Also create an associated DOM
  137. // node, parented under the specified parent, and returned via the
  138. // out parameter, if specified.
  139. pagespeed::Resource* NewCssResource(const std::string& url,
  140. FakeDomElement* parent = NULL,
  141. FakeDomElement** out = NULL);
  142. // Set the top-level browsing context.
  143. bool SetTopLevelBrowsingContext(pagespeed::TopLevelBrowsingContext* context);
  144. // Create a new TopLevelBrowsingContext with the specified document,
  145. // and transfer its ownership to the PagespeedInput. If you call
  146. // this method, SetTopLevelBrowsingContext() is called for you
  147. // internally for the returned context.
  148. pagespeed::TopLevelBrowsingContext* NewTopLevelBrowsingContext(
  149. const pagespeed::Resource* document_resource);
  150. // Construct default html, head, and body DOM elements under the
  151. // document. NewPrimaryResource() must be called prior to calling
  152. // this method, in order to create a root document that these
  153. // elements can be parented under.
  154. void CreateHtmlHeadBodyElements();
  155. // Adds an ImageAttributesFactory to the PagespeedInput that can
  156. // returns ImageAttributes according to the ResourceSizeMap.
  157. bool AddFakeImageAttributesFactory(
  158. const FakeImageAttributesFactory::ResourceSizeMap& map);
  159. // Adds an InstrumentationData to the set of InstrumentationData for
  160. // the PagespeedInput. Can be called multiple times to add multiple
  161. // root InstrumentationData instances. Ownership of the
  162. // InstrumentationData instances is transferred to this object.
  163. void AddInstrumentationData(const pagespeed::InstrumentationData* data);
  164. bool SetOnloadTimeMillis(int onload_millis) {
  165. return pagespeed_input_->SetOnloadTimeMillis(onload_millis);
  166. }
  167. bool SetViewportWidthAndHeight(int width, int height) {
  168. return pagespeed_input_->SetViewportWidthAndHeight(width, height);
  169. }
  170. void SetInitialResourceIsCanonical(bool initial_resource_is_canonical) {
  171. pagespeed_input_->SetInitialResourceIsCanonical(
  172. initial_resource_is_canonical);
  173. }
  174. const pagespeed::PagespeedInput* pagespeed_input() {
  175. return pagespeed_input_.get();
  176. }
  177. pagespeed::Resource* primary_resource() const { return primary_resource_; }
  178. FakeDomDocument* document() { return document_; }
  179. FakeDomElement* html() { return html_; }
  180. FakeDomElement* head() { return head_; }
  181. FakeDomElement* body() { return body_; }
  182. // Add a resource. Do not call this method for resources constructed
  183. // using New*Resource, as those resources have already been added to
  184. // the PagespeedInput. Use this method only for backward
  185. // compatibility with tests that don't use the New*Resource()
  186. // methods to construct resouces.
  187. bool AddResource(pagespeed::Resource* resource);
  188. private:
  189. base::AtExitManager at_exit_manager_;
  190. pagespeed::InstrumentationDataVector instrumentation_data_;
  191. scoped_ptr<pagespeed::PagespeedInput> pagespeed_input_;
  192. pagespeed::Resource* primary_resource_;
  193. FakeDomDocument* document_;
  194. FakeDomElement* html_;
  195. FakeDomElement* head_;
  196. FakeDomElement* body_;
  197. };
  198. // A base testing class for use when writing rule tests.
  199. template <class RULE> class PagespeedRuleTest : public PagespeedTest {
  200. protected:
  201. PagespeedRuleTest()
  202. : rule_(new RULE()), provider_(*rule_.get(), &rule_results_, 0) {
  203. rule_results_.set_rule_name(rule_->name());
  204. }
  205. const pagespeed::RuleInput* rule_input() { return rule_input_.get(); }
  206. const pagespeed::RuleResults& rule_results() const { return rule_results_; }
  207. int num_results() const { return rule_results_.results_size(); }
  208. const pagespeed::Result& result(int i) const {
  209. return rule_results_.results(i);
  210. }
  211. const std::string& results_rule_name() const {
  212. return rule_results_.rule_name();
  213. }
  214. // Get a details instance of the specified type.
  215. template <class DETAILS> const DETAILS& details(int i) const {
  216. const pagespeed::ResultDetails& details = result(i).details();
  217. AssertTrue(details.HasExtension(DETAILS::message_set_extension));
  218. return details.GetExtension(DETAILS::message_set_extension);
  219. }
  220. virtual void SetUp() {
  221. PagespeedTest::SetUp();
  222. }
  223. virtual void TearDown() {
  224. rule_input_.reset();
  225. PagespeedTest::TearDown();
  226. }
  227. virtual void Freeze(bool expected_result) {
  228. PagespeedTest::Freeze(expected_result);
  229. rule_input_.reset(new pagespeed::RuleInput(*pagespeed_input()));
  230. rule_input_->Init();
  231. }
  232. virtual void Freeze() {
  233. Freeze(true);
  234. }
  235. bool AppendResults() {
  236. return rule_->AppendResults(*rule_input(), &provider_);
  237. }
  238. void CheckError() {
  239. Freeze();
  240. ASSERT_FALSE(AppendResults());
  241. ASSERT_EQ(0, num_results());
  242. }
  243. void CheckNoViolations() {
  244. Freeze();
  245. ASSERT_TRUE(AppendResults());
  246. ASSERT_EQ(0, num_results());
  247. }
  248. void CheckOneUrlViolation(const std::string& violation_url) {
  249. std::vector<std::string> expected;
  250. expected.push_back(violation_url);
  251. CheckExpectedUrlViolations(expected);
  252. }
  253. void CheckTwoUrlViolations(const std::string& violation_url1,
  254. const std::string& violation_url2) {
  255. std::vector<std::string> expected;
  256. expected.push_back(violation_url1);
  257. expected.push_back(violation_url2);
  258. CheckExpectedUrlViolations(expected);
  259. }
  260. void CheckExpectedUrlViolations(const std::vector<std::string>& expected) {
  261. Freeze();
  262. ASSERT_TRUE(AppendResults());
  263. ASSERT_EQ(num_results(), static_cast<int>(expected.size()));
  264. for (size_t idx = 0; idx < expected.size(); ++idx) {
  265. const pagespeed::Result& res = result(idx);
  266. ASSERT_EQ(res.resource_urls_size(), 1);
  267. EXPECT_EQ(expected[idx], res.resource_urls(0));
  268. }
  269. }
  270. std::string FormatResults() {
  271. return DoFormatResultsAsText(rule_.get(), rule_results_);
  272. }
  273. void FormatResultsAsProto(pagespeed::FormattedResults* formatted_results) {
  274. return DoFormatResultsAsProto(rule_.get(), rule_results_,
  275. formatted_results);
  276. }
  277. double ComputeRuleImpact() {
  278. return rule_->ComputeRuleImpact(*pagespeed_input()->input_information(),
  279. rule_results_);
  280. }
  281. void CheckRuleGroups(
  282. const std::vector<pagespeed::FormattedRuleResults::RuleGroup>& expected) {
  283. pagespeed::FormattedResults formatted_results;
  284. FormatResultsAsProto(&formatted_results);
  285. ASSERT_EQ(1, formatted_results.rule_results_size());
  286. const pagespeed::FormattedRuleResults& rule_results =
  287. formatted_results.rule_results(0);
  288. std::vector<pagespeed::FormattedRuleResults::RuleGroup> actual;
  289. for (int i = 0; i < rule_results.groups_size(); ++i) {
  290. actual.push_back(rule_results.groups(i));
  291. }
  292. EXPECT_EQ(expected, actual);
  293. }
  294. scoped_ptr<RULE> rule_;
  295. private:
  296. scoped_ptr<pagespeed::RuleInput> rule_input_;
  297. pagespeed::RuleResults rule_results_;
  298. pagespeed::ResultProvider provider_;
  299. };
  300. } // namespace pagespeed_testing
  301. #endif // PAGESPEED_TESTING_PAGESPEED_TEST_H_