Page Speed Optimization Libraries  1.9.32.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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 
40 #include "pagespeed/kernel/base/basictypes.h"
41 #include "pagespeed/kernel/base/scoped_ptr.h"
42 #include "pagespeed/kernel/base/string.h"
43 #include "pagespeed/kernel/base/string_util.h"
44 #include "pagespeed/kernel/base/timer.h"
45 #include "pagespeed/kernel/base/writer.h"
46 #include "pagespeed/kernel/html/html_element.h"
47 #include "pagespeed/kernel/html/html_name.h"
48 #include "pagespeed/kernel/html/html_parse_test_base.h"
49 #include "pagespeed/kernel/http/content_type.h"
50 #include "pagespeed/kernel/thread/worker_test_base.h"
51 #include "pagespeed/kernel/util/url_multipart_encoder.h"
52 
53 
54 namespace net_instaweb {
55 
56 class CachedResult;
57 class MessageHandler;
58 class MockScheduler;
59 class OutputPartitions;
60 class OutputResource;
61 class TestRewriteDriverFactory;
62 class UrlSegmentEncoder;
63 
66  public:
67  static const char kFilterId[];
68 
69  explicit TrimWhitespaceRewriter(OutputResourceKind kind) : kind_(kind) {
70  ClearStats();
71  }
72 
74  int num_rewrites() const { return num_rewrites_; }
75  void ClearStats() { num_rewrites_ = 0; }
76 
77  protected:
78  REFCOUNT_FRIEND_DECLARATION(TrimWhitespaceRewriter);
79  virtual ~TrimWhitespaceRewriter();
80 
81  virtual bool RewriteText(const StringPiece& url, const StringPiece& in,
82  GoogleString* out,
83  ServerContext* server_context);
84  virtual HtmlElement::Attribute* FindResourceAttribute(HtmlElement* element);
85  virtual OutputResourceKind kind() const { return kind_; }
86  virtual const char* id() const { return kFilterId; }
87  virtual const char* name() const { return "TrimWhitespace"; }
88 
89  private:
90  OutputResourceKind kind_;
91 
92  int num_rewrites_;
93 
94  DISALLOW_COPY_AND_ASSIGN(TrimWhitespaceRewriter);
95 };
96 
102  public:
103  static const char kFilterId[];
104 
106  RewriteDriver* driver)
107  : SimpleTextFilter(new TrimWhitespaceRewriter(kind), driver) {
108  }
109  virtual ~TrimWhitespaceSyncFilter();
110 
111  virtual void StartElementImpl(HtmlElement* element);
112  virtual const char* id() const { return kFilterId; }
113  virtual const char* name() const { return "TrimWhitespaceSync"; }
114 
115  private:
116  DISALLOW_COPY_AND_ASSIGN(TrimWhitespaceSyncFilter);
117 };
118 
121  public:
122  static const char kFilterId[];
123 
125  : kind_(kind), num_rewrites_(0) {}
126  static SimpleTextFilter* MakeFilter(OutputResourceKind kind,
127  RewriteDriver* driver,
128  UpperCaseRewriter** rewriter_out) {
129  *rewriter_out = new UpperCaseRewriter(kind);
130  return new SimpleTextFilter(*rewriter_out, driver);
131  }
132 
133  int num_rewrites() const { return num_rewrites_; }
134  void ClearStats() { num_rewrites_ = 0; }
135 
136  protected:
137  REFCOUNT_FRIEND_DECLARATION(UpperCaseRewriter);
138  virtual ~UpperCaseRewriter();
139 
140  virtual bool RewriteText(const StringPiece& url, const StringPiece& in,
141  GoogleString* out,
142  ServerContext* server_context) {
143  ++num_rewrites_;
144  in.CopyToString(out);
145  UpperString(out);
146  return in != *out;
147  }
148  virtual HtmlElement::Attribute* FindResourceAttribute(HtmlElement* element) {
149  if (element->keyword() == HtmlName::kLink) {
150  return element->FindAttribute(HtmlName::kHref);
151  }
152  return NULL;
153  }
154  virtual OutputResourceKind kind() const { return kind_; }
155  virtual const char* id() const { return kFilterId; }
156  virtual const char* name() const { return "UpperCase"; }
157 
158  private:
159  OutputResourceKind kind_;
160  int num_rewrites_;
161 
162  DISALLOW_COPY_AND_ASSIGN(UpperCaseRewriter);
163 };
164 
167 class NestedFilter : public RewriteFilter {
168  public:
170  static const bool kExpectNestedRewritesSucceed = true;
171  static const bool kExpectNestedRewritesFail = false;
172 
173  static const char kFilterId[];
174 
175  NestedFilter(RewriteDriver* driver, SimpleTextFilter* upper_filter,
176  UpperCaseRewriter* upper_rewriter, bool expected_nested_result)
177  : RewriteFilter(driver), upper_filter_(upper_filter),
178  upper_rewriter_(upper_rewriter), chain_(false),
179  check_nested_rewrite_result_(true),
180  expected_nested_rewrite_result_(expected_nested_result) {
181  ClearStats();
182  }
183 
185  int num_top_rewrites() const { return num_top_rewrites_; }
186  int num_sub_rewrites() const { return upper_rewriter_->num_rewrites(); }
187 
188  void ClearStats() {
189  num_top_rewrites_ = 0;
190  upper_rewriter_->ClearStats();
191  }
192 
194  void set_chain(bool x) { chain_ = x; }
195 
196  bool expected_nested_rewrite_result() const {
197  return expected_nested_rewrite_result_;
198  }
199 
200  void set_expected_nested_rewrite_result(bool x) {
201  expected_nested_rewrite_result_ = x;
202  }
203 
204  void set_check_nested_rewrite_result(bool x) {
205  check_nested_rewrite_result_ = x;
206  }
207 
208  protected:
209  virtual ~NestedFilter();
210 
211  class NestedSlot : public ResourceSlot {
212  public:
213  explicit NestedSlot(const ResourcePtr& resource) : ResourceSlot(resource) {}
214  virtual HtmlElement* element() const { return NULL; }
215  virtual void Render() {}
216  virtual GoogleString LocationString() { return "nested:"; }
217  };
218 
219  class Context : public SingleRewriteContext {
220  public:
221  Context(RewriteDriver* driver, NestedFilter* filter, bool chain)
222  : SingleRewriteContext(driver, NULL, NULL),
223  filter_(filter),
224  chain_(chain) {
225  }
226  virtual ~Context();
227  virtual void RewriteSingle(
228  const ResourcePtr& input, const OutputResourcePtr& output);
229  virtual void Harvest();
230 
231  protected:
232  virtual const char* id() const { return kFilterId; }
233  virtual OutputResourceKind kind() const { return kRewrittenResource; }
234 
235  private:
236  std::vector<GoogleString*> strings_;
237  NestedFilter* filter_;
238  bool chain_;
239  ResourceSlotVector nested_slots_;
240 
241  DISALLOW_COPY_AND_ASSIGN(Context);
242  };
243 
245  return new Context(driver(), this, chain_);
246  }
247 
248  void StartElementImpl(HtmlElement* element);
249  SimpleTextFilter* upper_filter() { return upper_filter_; }
250 
251  virtual const char* id() const { return kFilterId; }
252  virtual const char* Name() const { return "NestedFilter"; }
253  virtual void StartDocumentImpl() {}
254  virtual void EndElementImpl(HtmlElement* element) {}
255 
256  private:
258  SimpleTextFilter* upper_filter_;
259  UpperCaseRewriter* upper_rewriter_;
260  bool chain_;
261 
263  bool check_nested_rewrite_result_;
265  bool expected_nested_rewrite_result_;
266 
268  int num_top_rewrites_;
269 
270  DISALLOW_COPY_AND_ASSIGN(NestedFilter);
271 };
272 
278  public:
279  static const char kFilterId[];
280 
282  MockScheduler* scheduler,
283  int64 rewrite_delay_ms);
284  virtual ~CombiningFilter();
285 
286  class Combiner : public ResourceCombiner {
287  public:
288  Combiner(RewriteDriver* driver, RewriteFilter* filter)
290  driver, kContentTypeCss.file_extension() + 1, filter) {
291  }
292  OutputResourcePtr MakeOutput() {
293  return Combine(rewrite_driver_->message_handler());
294  }
295  bool Write(const ResourceVector& in, const OutputResourcePtr& out) {
296  return WriteCombination(in, out, rewrite_driver_->message_handler());
297  }
298 
299  virtual bool WritePiece(int index, const Resource* input,
300  OutputResource* combination,
301  Writer* writer, MessageHandler* handler) {
302  writer->Write(prefix_, handler);
304  index, input, combination, writer, handler);
305  }
306 
307  void set_prefix(const GoogleString& prefix) { prefix_ = prefix; }
308 
309  private:
310  virtual const ContentType* CombinationContentType() {
311  return &kContentTypeCss;
312  }
313 
314  GoogleString prefix_;
315  };
316 
317  virtual const char* id() const { return kFilterId; }
318 
319  class Context : public RewriteContext {
320  public:
321  Context(RewriteDriver* driver, CombiningFilter* filter,
322  MockScheduler* scheduler);
323 
324  void AddElement(HtmlElement* element, HtmlElement::Attribute* href,
325  const ResourcePtr& resource) {
326  ResourceSlotPtr slot(Driver()->GetSlot(resource, element, href));
327  AddSlot(slot);
328  }
329 
330  protected:
331  virtual bool Partition(OutputPartitions* partitions,
332  OutputResourceVector* outputs);
333 
334  virtual void Rewrite(int partition_index,
335  CachedResult* partition,
336  const OutputResourcePtr& output);
337  virtual bool OptimizationOnly() const {
338  return filter_->optimization_only();
339  }
340 
341  void DoRewrite(int partition_index,
342  CachedResult* partition,
343  OutputResourcePtr output);
344  virtual void Render();
345  virtual void WillNotRender();
346  virtual void Cancel();
347  void DisableRemovedSlots(CachedResult* partition);
348  virtual const UrlSegmentEncoder* encoder() const { return &encoder_; }
349  virtual const char* id() const { return kFilterId; }
350  virtual OutputResourceKind kind() const {
351  return filter_->on_the_fly_ ? kOnTheFlyResource : kRewrittenResource;
352  }
353 
354  private:
355  Combiner combiner_;
356  UrlMultipartEncoder encoder_;
357  MockScheduler* scheduler_;
358  int64 time_at_start_of_rewrite_us_;
359  CombiningFilter* filter_;
360  };
361 
362  virtual void StartDocumentImpl() {}
363  virtual void StartElementImpl(HtmlElement* element);
364  virtual void Flush() {
365  if (context_.get() != NULL) {
366  driver()->InitiateRewrite(context_.release());
367  }
368  }
369 
370  virtual void EndElementImpl(HtmlElement* element) {}
371  virtual const char* Name() const { return "Combining"; }
373  return new Context(driver(), this, scheduler_);
374  }
375  virtual const UrlSegmentEncoder* encoder() const { return &encoder_; }
376 
377  virtual bool ComputeOnTheFly() const { return on_the_fly_; }
378 
379  int num_rewrites() const { return num_rewrites_; }
380  int num_render() const { return num_render_; }
381  int num_will_not_render() const { return num_will_not_render_; }
382  int num_cancel() const { return num_cancel_; }
383 
384  void ClearStats() { num_rewrites_ = 0; }
385  int64 rewrite_delay_ms() const { return rewrite_delay_ms_; }
386  void set_rewrite_block_on(WorkerTestBase::SyncPoint* sync) {
387  rewrite_block_on_ = sync;
388  }
389 
390  void set_rewrite_signal_on(WorkerTestBase::SyncPoint* sync) {
391  rewrite_signal_on_ = sync;
392  }
393 
395  void set_prefix(const GoogleString& prefix) { prefix_ = prefix; }
396 
397  void set_on_the_fly(bool v) { on_the_fly_ = v; }
398 
399  void set_disable_successors(bool v) { disable_successors_ = v; }
400 
401  bool optimization_only() const { return optimization_only_; }
402  void set_optimization_only(bool o) { optimization_only_ = o; }
403 
404  private:
405  friend class Context;
406 
407  scoped_ptr<Context> context_;
408  UrlMultipartEncoder encoder_;
409  MockScheduler* scheduler_;
410  int num_rewrites_;
411  int num_render_;
412  int num_will_not_render_;
413  int num_cancel_;
414  int64 rewrite_delay_ms_;
415 
418  WorkerTestBase::SyncPoint* rewrite_block_on_;
419 
423  WorkerTestBase::SyncPoint* rewrite_signal_on_;
424  GoogleString prefix_;
425  bool on_the_fly_;
426  bool optimization_only_;
427  bool disable_successors_;
429 
431  DISALLOW_COPY_AND_ASSIGN(CombiningFilter);
432 };
433 
435  protected:
436  static const int64 kRewriteDeadlineMs = 20;
437 
440  static const int64 kOriginTtlMs = 12 * Timer::kMinuteMs;
443  static const int64 kLowOriginTtlMs = 5 * Timer::kSecondMs;
444 
447  GoogleString OriginTtlMaxAge() {
448  return StrCat("max-age=", Integer64ToString(
449  kOriginTtlMs / Timer::kSecondMs));
450  }
451 
453  std::pair<TestRewriteDriverFactory*, TestRewriteDriverFactory*> factories)
454  : RewriteTestBase(factories) {}
455  RewriteContextTestBase() {}
456  virtual ~RewriteContextTestBase();
457 
458  virtual void SetUp();
459  virtual void TearDown();
460  virtual bool AddBody() const { return false; }
461  virtual void ClearStats();
462 
463  void InitResources() { InitResourcesToDomain(kTestDomain); }
464  void InitResourcesToDomain(const char* domain);
465  void InitTrimFilters(OutputResourceKind kind);
466  void InitUpperFilter(OutputResourceKind kind, RewriteDriver* rewrite_driver);
467  void InitCombiningFilter(int64 rewrite_delay_ms);
468  void InitNestedFilter(bool expected_nested_rewrite_result);
469 
470  TrimWhitespaceRewriter* trim_filter_;
471  TrimWhitespaceRewriter* other_trim_filter_;
472  CombiningFilter* combining_filter_;
473  NestedFilter* nested_filter_;
474 };
475 
476 }
477 
478 #endif
virtual OutputResourceKind kind() const
Definition: rewrite_context_test_base.h:233
virtual const UrlSegmentEncoder * encoder() const
Definition: rewrite_context_test_base.h:348
Definition: rewrite_context_test_base.h:211
SingleRewriteContext(RewriteDriver *driver, RewriteContext *parent, ResourceContext *resource_context)
Definition: rewrite_context_test_base.h:286
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:377
Definition: rewrite_test_base.h:89
Definition: rewrite_context_test_base.h:277
RewriteDriver * rewrite_driver()
Definition: rewrite_test_base.h:505
virtual void StartDocumentImpl()
Definition: rewrite_context_test_base.h:362
Definition: resource_slot.h:52
Definition: output_resource_kind.h:28
Definition: simple_text_filter.h:46
Definition: rewrite_context_test_base.h:101
virtual void Rewrite(int partition_index, CachedResult *partition, const OutputResourcePtr &output)
Definition: resource.h:56
A similarly structured test-filter: this one just upper-cases its text.
Definition: rewrite_context_test_base.h:120
static const int64 kOriginTtlMs
Definition: rewrite_context_test_base.h:440
static const int64 kLowOriginTtlMs
Definition: rewrite_context_test_base.h:443
virtual const char * id() const
Returns the filter ID.
Definition: rewrite_context_test_base.h:349
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:460
virtual void Render()
Definition: rewrite_context_test_base.h:215
GoogleString OriginTtlMaxAge()
Definition: rewrite_context_test_base.h:447
Definition: rewrite_context_test_base.h:167
virtual bool WritePiece(int index, const Resource *input, OutputResource *combination, Writer *writer, MessageHandler *handler)
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:194
int num_rewrites() const
Stats.
Definition: rewrite_context_test_base.h:74
virtual GoogleString LocationString()
Definition: rewrite_context_test_base.h:216
virtual HtmlElement * element() const
Return HTML element associated with slot, or NULL if none (CSS, IPRO)
Definition: rewrite_context_test_base.h:214
Definition: rewrite_filter.h:37
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:395
Definition: server_context.h:101
Definition: rewrite_context.h:144
virtual bool OptimizationOnly() const
Definition: rewrite_context_test_base.h:337
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:170
Definition: rewrite_context_test_base.h:219
virtual OutputResourceKind kind() const
Definition: rewrite_context_test_base.h:350
virtual const char * id() const
Returns the filter ID.
Definition: rewrite_context_test_base.h:232
Definition: single_rewrite_context.h:36
Definition: rewrite_context_test_base.h:319
RewriteContext * MakeRewriteContext()
Definition: rewrite_context_test_base.h:372
Definition: rewrite_context_test_base.h:434
Definition: output_resource.h:44
OutputResourcePtr Combine(MessageHandler *handler)
Definition: simple_text_filter.h:48
virtual void StartDocumentImpl()
Definition: rewrite_context_test_base.h:253
int num_top_rewrites() const
Stats.
Definition: rewrite_context_test_base.h:185
virtual bool WritePiece(int index, const Resource *input, OutputResource *combination, Writer *writer, MessageHandler *handler)
Definition: rewrite_context_test_base.h:299
virtual const UrlSegmentEncoder * encoder() const
Definition: rewrite_context_test_base.h:375
Simple test filter just trims whitespace from the input resource.
Definition: rewrite_context_test_base.h:65
void AddSlot(const ResourceSlotPtr &slot)
RewriteContext * MakeRewriteContext()
Definition: rewrite_context_test_base.h:244
OutputResourceKind
Definition: output_resource_kind.h:26