Page Speed Optimization Libraries  1.11.33.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
rewrite_context_test_base.h
Go to the documentation of this file.
1 /*
2  * Copyright 2011 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http:///www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
18 
21 
22 #ifndef NET_INSTAWEB_REWRITER_PUBLIC_REWRITE_CONTEXT_TEST_BASE_H_
23 #define NET_INSTAWEB_REWRITER_PUBLIC_REWRITE_CONTEXT_TEST_BASE_H_
24 
26 
27 #include <utility>
28 #include <vector>
29 
30 #include "net/instaweb/rewriter/cached_result.pb.h"
43 #include "pagespeed/kernel/base/basictypes.h"
44 #include "pagespeed/kernel/base/message_handler.h"
45 #include "pagespeed/kernel/base/scoped_ptr.h"
46 #include "pagespeed/kernel/base/string.h"
47 #include "pagespeed/kernel/base/string_util.h"
48 #include "pagespeed/kernel/base/timer.h"
49 #include "pagespeed/kernel/base/writer.h"
50 #include "pagespeed/kernel/html/html_element.h"
51 #include "pagespeed/kernel/html/html_name.h"
52 #include "pagespeed/kernel/html/html_parse_test_base.h"
53 #include "pagespeed/kernel/http/content_type.h"
54 #include "pagespeed/kernel/thread/worker_test_base.h"
55 #include "pagespeed/kernel/util/url_multipart_encoder.h"
56 #include "pagespeed/kernel/util/url_segment_encoder.h"
57 
58 
59 namespace net_instaweb {
60 
61 class MockScheduler;
62 
65  public:
66  static const char kFilterId[];
67 
68  explicit TrimWhitespaceRewriter(OutputResourceKind kind) : kind_(kind) {
69  ClearStats();
70  }
71 
73  int num_rewrites() const { return num_rewrites_; }
74  void ClearStats() { num_rewrites_ = 0; }
75 
76  protected:
77  REFCOUNT_FRIEND_DECLARATION(TrimWhitespaceRewriter);
78  virtual ~TrimWhitespaceRewriter();
79 
80  virtual bool RewriteText(const StringPiece& url, const StringPiece& in,
81  GoogleString* out,
82  ServerContext* server_context);
83  virtual HtmlElement::Attribute* FindResourceAttribute(HtmlElement* element);
84  virtual OutputResourceKind kind() const { return kind_; }
85  virtual const char* id() const { return kFilterId; }
86  virtual const char* name() const { return "TrimWhitespace"; }
87 
88  private:
89  OutputResourceKind kind_;
90 
91  int num_rewrites_;
92 
93 
94 };
95 
101  public:
102  static const char kFilterId[];
103 
105  RewriteDriver* driver)
106  : SimpleTextFilter(new TrimWhitespaceRewriter(kind), driver) {
107  }
108  virtual ~TrimWhitespaceSyncFilter();
109 
110  virtual void StartElementImpl(HtmlElement* element);
111  virtual const char* id() const { return kFilterId; }
112  virtual const char* name() const { return "TrimWhitespaceSync"; }
113 
114  private:
115 
116 };
117 
120  public:
121  static const char kFilterId[];
122 
124  : kind_(kind), num_rewrites_(0) {}
125  static SimpleTextFilter* MakeFilter(OutputResourceKind kind,
126  RewriteDriver* driver,
127  UpperCaseRewriter** rewriter_out) {
128  *rewriter_out = new UpperCaseRewriter(kind);
129  return new SimpleTextFilter(*rewriter_out, driver);
130  }
131 
132  int num_rewrites() const { return num_rewrites_; }
133  void ClearStats() { num_rewrites_ = 0; }
134 
135  protected:
136  REFCOUNT_FRIEND_DECLARATION(UpperCaseRewriter);
137  virtual ~UpperCaseRewriter();
138 
139  virtual bool RewriteText(const StringPiece& url, const StringPiece& in,
140  GoogleString* out,
141  ServerContext* server_context) {
142  ++num_rewrites_;
143  in.CopyToString(out);
144  UpperString(out);
145  return in != *out;
146  }
147  virtual HtmlElement::Attribute* FindResourceAttribute(HtmlElement* element) {
148  if (element->keyword() == HtmlName::kLink) {
149  return element->FindAttribute(HtmlName::kHref);
150  }
151  return NULL;
152  }
153  virtual OutputResourceKind kind() const { return kind_; }
154  virtual const char* id() const { return kFilterId; }
155  virtual const char* name() const { return "UpperCase"; }
156 
157  private:
158  OutputResourceKind kind_;
159  int num_rewrites_;
160 
161 
162 };
163 
166 class NestedFilter : public RewriteFilter {
167  public:
169  static const bool kExpectNestedRewritesSucceed = true;
170  static const bool kExpectNestedRewritesFail = false;
171 
172  static const char kFilterId[];
173 
174  NestedFilter(RewriteDriver* driver, SimpleTextFilter* upper_filter,
175  UpperCaseRewriter* upper_rewriter, bool expected_nested_result)
176  : RewriteFilter(driver), upper_filter_(upper_filter),
177  upper_rewriter_(upper_rewriter), chain_(false),
178  check_nested_rewrite_result_(true),
179  expected_nested_rewrite_result_(expected_nested_result) {
180  ClearStats();
181  }
182 
184  int num_top_rewrites() const { return num_top_rewrites_; }
185  int num_sub_rewrites() const { return upper_rewriter_->num_rewrites(); }
186 
187  void ClearStats() {
188  num_top_rewrites_ = 0;
189  upper_rewriter_->ClearStats();
190  }
191 
193  void set_chain(bool x) { chain_ = x; }
194 
195  bool expected_nested_rewrite_result() const {
196  return expected_nested_rewrite_result_;
197  }
198 
199  void set_expected_nested_rewrite_result(bool x) {
200  expected_nested_rewrite_result_ = x;
201  }
202 
203  void set_check_nested_rewrite_result(bool x) {
204  check_nested_rewrite_result_ = x;
205  }
206 
207  protected:
208  virtual ~NestedFilter();
209 
210  class NestedSlot : public ResourceSlot {
211  public:
212  explicit NestedSlot(const ResourcePtr& resource) : ResourceSlot(resource) {}
213  virtual HtmlElement* element() const { return NULL; }
214  virtual void Render() {}
215  virtual GoogleString LocationString() const { return "nested:"; }
216  };
217 
218  class Context : public SingleRewriteContext {
219  public:
220  Context(RewriteDriver* driver, NestedFilter* filter, bool chain)
221  : SingleRewriteContext(driver, NULL, NULL),
222  filter_(filter),
223  chain_(chain) {
224  }
225  virtual ~Context();
226  virtual void RewriteSingle(
227  const ResourcePtr& input, const OutputResourcePtr& output);
228  virtual void Harvest();
229 
230  protected:
231  virtual const char* id() const { return kFilterId; }
232  virtual OutputResourceKind kind() const { return kRewrittenResource; }
233 
234  private:
235  std::vector<GoogleString*> strings_;
236  NestedFilter* filter_;
237  bool chain_;
238  ResourceSlotVector nested_slots_;
239 
240 
241  };
242 
244  return new Context(driver(), this, chain_);
245  }
246 
247  virtual void StartElementImpl(HtmlElement* element);
248  SimpleTextFilter* upper_filter() { return upper_filter_; }
249 
250  virtual const char* id() const { return kFilterId; }
251  virtual const char* Name() const { return "NestedFilter"; }
252  virtual void StartDocumentImpl() {}
253  virtual void EndElementImpl(HtmlElement* element) {}
254 
255  private:
257  SimpleTextFilter* upper_filter_;
258  UpperCaseRewriter* upper_rewriter_;
259  bool chain_;
260 
262  bool check_nested_rewrite_result_;
264  bool expected_nested_rewrite_result_;
265 
267  int num_top_rewrites_;
268 
269 
270 };
271 
277  public:
278  static const char kFilterId[];
279 
281  MockScheduler* scheduler,
282  int64 rewrite_delay_ms);
283  virtual ~CombiningFilter();
284 
285  class Combiner : public ResourceCombiner {
286  public:
287  Combiner(RewriteDriver* driver, RewriteFilter* filter)
289  driver, kContentTypeCss.file_extension() + 1, filter) {
290  }
291  OutputResourcePtr MakeOutput() {
292  return Combine(rewrite_driver_->message_handler());
293  }
294  bool Write(const ResourceVector& in, const OutputResourcePtr& out) {
295  return WriteCombination(in, out, rewrite_driver_->message_handler());
296  }
297 
298  virtual bool WritePiece(int index, int num_pieces, const Resource* input,
299  OutputResource* combination,
300  Writer* writer, MessageHandler* handler) {
301  writer->Write(prefix_, handler);
303  index, num_pieces, input, combination, writer, handler);
304  }
305 
306  void set_prefix(const GoogleString& prefix) { prefix_ = prefix; }
307 
308  private:
309  virtual const ContentType* CombinationContentType() {
310  return &kContentTypeCss;
311  }
312 
313  GoogleString prefix_;
314  };
315 
316  virtual const char* id() const { return kFilterId; }
317 
318  class Context : public RewriteContext {
319  public:
320  Context(RewriteDriver* driver, CombiningFilter* filter,
321  MockScheduler* scheduler);
322 
323  void AddElement(HtmlElement* element, HtmlElement::Attribute* href,
324  const ResourcePtr& resource) {
325  ResourceSlotPtr slot(Driver()->GetSlot(resource, element, href));
326  AddSlot(slot);
327  }
328 
329  protected:
330  virtual bool Partition(OutputPartitions* partitions,
331  OutputResourceVector* outputs);
332 
333  virtual void Rewrite(int partition_index,
334  CachedResult* partition,
335  const OutputResourcePtr& output);
336  virtual bool OptimizationOnly() const {
337  return filter_->optimization_only();
338  }
339 
340  void DoRewrite(int partition_index,
341  CachedResult* partition,
342  OutputResourcePtr output);
343  virtual void Render();
344  virtual void WillNotRender();
345  virtual void Cancel();
346  void DisableRemovedSlots(CachedResult* partition);
347  virtual const UrlSegmentEncoder* encoder() const { return &encoder_; }
348  virtual const char* id() const { return kFilterId; }
349  virtual OutputResourceKind kind() const {
350  return filter_->on_the_fly_ ? kOnTheFlyResource : kRewrittenResource;
351  }
352 
353  private:
354  Combiner combiner_;
355  UrlMultipartEncoder encoder_;
356  MockScheduler* scheduler_;
357  int64 time_at_start_of_rewrite_us_;
358  CombiningFilter* filter_;
359  };
360 
361  virtual void StartDocumentImpl() {}
362  virtual void StartElementImpl(HtmlElement* element);
363  virtual void Flush() {
364  if (context_.get() != NULL) {
365  driver()->InitiateRewrite(context_.release());
366  }
367  }
368 
369  virtual void EndElementImpl(HtmlElement* element) {}
370  virtual const char* Name() const { return "Combining"; }
372  return new Context(driver(), this, scheduler_);
373  }
374  virtual const UrlSegmentEncoder* encoder() const { return &encoder_; }
375 
376  virtual bool ComputeOnTheFly() const { return on_the_fly_; }
377 
378  int num_rewrites() const { return num_rewrites_; }
379  int num_render() const { return num_render_; }
380  int num_will_not_render() const { return num_will_not_render_; }
381  int num_cancel() const { return num_cancel_; }
382 
383  void ClearStats() { num_rewrites_ = 0; }
384  int64 rewrite_delay_ms() const { return rewrite_delay_ms_; }
385  void set_rewrite_block_on(WorkerTestBase::SyncPoint* sync) {
386  rewrite_block_on_ = sync;
387  }
388 
389  void set_rewrite_signal_on(WorkerTestBase::SyncPoint* sync) {
390  rewrite_signal_on_ = sync;
391  }
392 
394  void set_prefix(const GoogleString& prefix) { prefix_ = prefix; }
395 
396  void set_on_the_fly(bool v) { on_the_fly_ = v; }
397 
398  void set_disable_successors(bool v) { disable_successors_ = v; }
399 
400  bool optimization_only() const { return optimization_only_; }
401  void set_optimization_only(bool o) { optimization_only_ = o; }
402 
403  private:
404  friend class Context;
405 
406  scoped_ptr<Context> context_;
407  UrlMultipartEncoder encoder_;
408  MockScheduler* scheduler_;
409  int num_rewrites_;
410  int num_render_;
411  int num_will_not_render_;
412  int num_cancel_;
413  int64 rewrite_delay_ms_;
414 
417  WorkerTestBase::SyncPoint* rewrite_block_on_;
418 
422  WorkerTestBase::SyncPoint* rewrite_signal_on_;
423  GoogleString prefix_;
424  bool on_the_fly_;
425  bool optimization_only_;
426  bool disable_successors_;
428 
430 
431 };
432 
434  protected:
435  static const int64 kRewriteDeadlineMs = 20;
436 
439  static const int64 kOriginTtlMs = 12 * Timer::kMinuteMs;
442  static const int64 kLowOriginTtlMs = 5 * Timer::kSecondMs;
443 
446  GoogleString OriginTtlMaxAge() {
447  return StrCat("max-age=", Integer64ToString(
448  kOriginTtlMs / Timer::kSecondMs));
449  }
450 
451  explicit RewriteContextTestBase(
452  std::pair<TestRewriteDriverFactory*, TestRewriteDriverFactory*> factories)
453  : RewriteTestBase(factories) {}
454  RewriteContextTestBase() {}
455  virtual ~RewriteContextTestBase();
456 
457  virtual void SetUp();
458  virtual void TearDown();
459  virtual bool AddBody() const { return false; }
460  virtual void ClearStats();
461 
462  void InitResources() { InitResourcesToDomain(kTestDomain); }
463  void InitResourcesToDomain(const char* domain);
464  void InitTrimFilters(OutputResourceKind kind);
465  void InitUpperFilter(OutputResourceKind kind, RewriteDriver* rewrite_driver);
466  void InitCombiningFilter(int64 rewrite_delay_ms);
467  void InitNestedFilter(bool expected_nested_rewrite_result);
468 
469  TrimWhitespaceRewriter* trim_filter_;
470  TrimWhitespaceRewriter* other_trim_filter_;
471  CombiningFilter* combining_filter_;
472  NestedFilter* nested_filter_;
473 };
474 
475 }
476 
477 #endif
virtual bool WritePiece(int index, int num_pieces, const Resource *input, OutputResource *combination, Writer *writer, MessageHandler *handler)
Definition: rewrite_context_test_base.h:298
virtual OutputResourceKind kind() const
Definition: rewrite_context_test_base.h:232
virtual const UrlSegmentEncoder * encoder() const
Definition: rewrite_context_test_base.h:347
Definition: rewrite_context_test_base.h:210
virtual bool WritePiece(int index, int num_pieces, const Resource *input, OutputResource *combination, Writer *writer, MessageHandler *handler)
virtual GoogleString LocationString() const
Definition: rewrite_context_test_base.h:215
SingleRewriteContext(RewriteDriver *driver, RewriteContext *parent, ResourceContext *resource_context)
Definition: rewrite_context_test_base.h:285
ResourceCombiner(RewriteDriver *rewrite_driver, const StringPiece &extension, RewriteFilter *filter)
Note: extension should not include the leading dot here.
virtual bool ComputeOnTheFly() const
Definition: rewrite_context_test_base.h:376
Definition: rewrite_test_base.h:91
virtual RewriteContext * MakeRewriteContext()
Definition: rewrite_context_test_base.h:243
Definition: rewrite_context_test_base.h:276
RewriteDriver * rewrite_driver()
Definition: rewrite_test_base.h:519
virtual void StartDocumentImpl()
Definition: rewrite_context_test_base.h:361
Definition: resource_slot.h:53
Definition: output_resource_kind.h:28
Definition: simple_text_filter.h:46
Definition: rewrite_context_test_base.h:100
virtual void Rewrite(int partition_index, CachedResult *partition, const OutputResourcePtr &output)
Definition: resource.h:57
A similarly structured test-filter: this one just upper-cases its text.
Definition: rewrite_context_test_base.h:119
static const int64 kOriginTtlMs
Definition: rewrite_context_test_base.h:439
static const int64 kLowOriginTtlMs
Definition: rewrite_context_test_base.h:442
virtual const char * id() const
Returns the filter ID.
Definition: rewrite_context_test_base.h:348
virtual bool Partition(OutputPartitions *partitions, OutputResourceVector *outputs)
virtual void RewriteSingle(const ResourcePtr &input, const OutputResourcePtr &output)
Subclasses of SingleRewriteContext must override this:
virtual bool AddBody() const
Definition: rewrite_context_test_base.h:459
virtual void Render()
Definition: rewrite_context_test_base.h:214
GoogleString OriginTtlMaxAge()
Definition: rewrite_context_test_base.h:446
Definition: rewrite_context_test_base.h:166
void set_chain(bool x)
Set this to true to create a chain of nested rewrites on the same slot.
Definition: rewrite_context_test_base.h:193
int num_rewrites() const
Stats.
Definition: rewrite_context_test_base.h:73
virtual HtmlElement * element() const
Return HTML element associated with slot, or NULL if none (CSS, IPRO)
Definition: rewrite_context_test_base.h:213
Definition: rewrite_filter.h:35
Definition: resource_combiner.h:57
virtual bool WriteCombination(const ResourceVector &combine_resources, const OutputResourcePtr &combination, MessageHandler *handler)
Definition: rewrite_driver.h:98
void set_prefix(const GoogleString &prefix)
Each entry in combination will be prefixed with this.
Definition: rewrite_context_test_base.h:394
Definition: server_context.h:100
Definition: rewrite_context.h:146
virtual bool OptimizationOnly() const
Definition: rewrite_context_test_base.h:336
bool InitiateRewrite(RewriteContext *rewrite_context) LOCKS_EXCLUDED(rewrite_mutex())
Derived from some input resource URL or URLs.
Definition: output_resource_kind.h:27
static const bool kExpectNestedRewritesSucceed
For use with NestedFilter constructor.
Definition: rewrite_context_test_base.h:169
Definition: rewrite_context_test_base.h:218
virtual OutputResourceKind kind() const
Definition: rewrite_context_test_base.h:349
virtual const char * id() const
Returns the filter ID.
Definition: rewrite_context_test_base.h:231
Definition: single_rewrite_context.h:36
Definition: rewrite_context_test_base.h:318
RewriteContext * MakeRewriteContext()
Definition: rewrite_context_test_base.h:371
Definition: rewrite_context_test_base.h:433
Definition: output_resource.h:44
OutputResourcePtr Combine(MessageHandler *handler)
Definition: simple_text_filter.h:48
virtual void StartDocumentImpl()
Definition: rewrite_context_test_base.h:252
int num_top_rewrites() const
Stats.
Definition: rewrite_context_test_base.h:184
virtual const UrlSegmentEncoder * encoder() const
Definition: rewrite_context_test_base.h:374
Simple test filter just trims whitespace from the input resource.
Definition: rewrite_context_test_base.h:64
void AddSlot(const ResourceSlotPtr &slot)
OutputResourceKind
Definition: output_resource_kind.h:26