blob: ec3cc8475c7a95bdb1ef50265647a2a2a8945f62 [file] [log] [blame]
Brian Silverman70325d62015-09-20 17:00:43 -04001// Copyright (c) 2006, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14// * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30// ---
31//
32// Intended usage of TemplateDictionaryPeer:
33// Use this class if you need to TEST that a dictionary has certain
34// expected contents. This should be fairly uncommon outside the
35// template directory.
36//
37
38
39#ifndef TEMPLATE_TEMPLATE_TEST_UTIL_H_
40#define TEMPLATE_TEMPLATE_TEST_UTIL_H_
41
42#include "config_for_unittests.h"
43#include <time.h> // for time_t
44#include <string> // for string
45#include <vector> // for vector<>
46#include HASH_MAP_H // UNUSED
47#include <ctemplate/template.h> // for Template::num_deletes_
48#include <ctemplate/template_cache.h> // for TemplateCache
49#include <ctemplate/template_dictionary.h> // for TemplateDictionary
50#include <ctemplate/template_dictionary_interface.h>
51#include <ctemplate/template_enums.h> // for Strip
52#include <ctemplate/template_namelist.h>
53#include <ctemplate/template_string.h> // for TemplateString, TemplateId
54
55namespace ctemplate {
56
57using std::string;
58
59class PerExpandData;
60class TemplateCache;
61class TemplateDictionary;
62
63inline TemplateId GlobalIdForTest(const char* ptr, int len) {
64 return TemplateString(ptr, len).GetGlobalId();
65}
66
67// Call this to create a StaticTemplateString for testing when the ptr is
68// not guaranteed to be allocated for the entire length of the test.
69#define STS_INIT_FOR_TEST(ptr, len, arena) \
70 { { arena->Memdup(ptr, len), len, GOOGLE_NAMESPACE::GlobalIdForTest(ptr, len) } };
71
72extern const std::string FLAGS_test_tmpdir;
73
74// These are routines that are useful for creating template files for testing.
75
76// Deletes all files named *template* in dir.
77void CreateOrCleanTestDir(const string& dirname);
78// This delets all files named *template*, and also sets dirname to be
79// the directory that all future StringToFile calls will place their
80// templates.
81void CreateOrCleanTestDirAndSetAsTmpdir(const string& dirname);
82
83// This writes s to the given file. We want to make sure that every
84// time we create a file, it has a different mtime (just like would
85// be the case in real life), so we use a mock clock. Filenames created
86// by this routine will all have an mtime of around Jan 1, 2000.
87void StringToFile(const string& s, const string& filename);
88
89// This is the (mock) time used when creating the last file in StringToFile.
90time_t Now();
91
92// This writes s to a file and returns the filename.
93string StringToTemplateFile(const string& s);
94
95// This writes s to a file and then loads it into a template object.
96Template* StringToTemplate(const string& s, Strip strip);
97
98// This is esp. useful for calling from within gdb.
99// The gdb nice-ness is balanced by the need for the caller to delete the buf.
100const char* ExpandIs(const Template* tpl, const TemplateDictionary *dict,
101 PerExpandData* per_expand_data, bool expected);
102
103void AssertExpandWithDataIs(const Template* tpl,
104 const TemplateDictionary *dict,
105 PerExpandData* per_expand_data,
106 const string& is, bool expected);
107
108void AssertExpandIs(const Template* tpl, const TemplateDictionary *dict,
109 const string& is, bool expected);
110
111void AssertExpandWithCacheIs(TemplateCache* cache,
112 const string& filename, Strip strip,
113 const TemplateDictionary *dict,
114 PerExpandData* per_expand_data,
115 const string& is, bool expected);
116
117class TemporaryRegisterTemplate {
118 public:
119 explicit TemporaryRegisterTemplate(const char* name);
120 ~TemporaryRegisterTemplate();
121 private:
122 GOOGLE_NAMESPACE::TemplateNamelist::NameListType* old_namelist_;
123 GOOGLE_NAMESPACE::TemplateNamelist::NameListType namelist_;
124
125 // disallow copy constructor and assignment
126 TemporaryRegisterTemplate(const TemporaryRegisterTemplate&);
127 void operator=(const TemporaryRegisterTemplate&);
128};
129
130// For friendship reasons, we make this a top-level class rather
131// than a nested class. It's used only in TemplateDictionaryPeer.
132// We take ownership of the iterator passed to us. To make sure that
133// isn't a problem, we make this class not-copyable.
134class TemplateDictionaryPeerIterator {
135 public:
136 explicit TemplateDictionaryPeerIterator(
137 TemplateDictionaryInterface::Iterator* it) : it_(it) { }
138 ~TemplateDictionaryPeerIterator() { delete it_; }
139 bool HasNext() const { return it_->HasNext(); }
140 const TemplateDictionaryInterface& Next() { return it_->Next(); }
141 private:
142 TemplateDictionaryInterface::Iterator* it_;
143 TemplateDictionaryPeerIterator(const TemplateDictionaryPeerIterator&);
144 TemplateDictionaryPeerIterator& operator=(
145 const TemplateDictionaryPeerIterator&);
146};
147
148// This class is meant for use in unittests. This class wraps the
149// TemplateDictionary and provides access to internal data that should
150// not be used in production code. If you need this kind of
151// functionality in production, use TemplateDictionaryWrapper or
152// TemplateDictionaryInterface; see top of file for details.
153//
154// Example Usage:
155// TemplateDictionary dict("test dictionary");
156// FillDictionaryValues(&dict);
157//
158// TemplateDictionaryPeer peer(&dict);
159// EXPECT_EQ("5", peer.GetSectionValue("width"));
160class TemplateDictionaryPeer {
161 public:
162 explicit TemplateDictionaryPeer(const TemplateDictionary* dict)
163 : dict_(dict) {}
164
165 // Returns whether the named variable has value equal to "expected".
166 bool ValueIs(const TemplateString& variable,
167 const TemplateString& expected) const;
168
169 // DEPRECATED: Returns the value of the named variable. Does not
170 // deal properly with values that have an internal NUL. Use ValueIs
171 // for new code.
172 const char* GetSectionValue(const TemplateString& variable) const;
173
174 // Returns true if the named section is hidden.
175 bool IsHiddenSection(const TemplateString& name) const;
176
177 // IsUnhiddenSection
178 // Returns true if the section has been marked visible and false otherwise.
179 bool IsUnhiddenSection(const TemplateString& name) const;
180
181 // Returns true if the named sub-template is hidden.
182 bool IsHiddenTemplate(const TemplateString& name) const;
183
184 // Retrieves TemplateDictionary instances for the given section name. The
185 // caller does not assume ownership of the returned TemplateDictionary
186 // instances. The number of instances is returned. All prior entries in
187 // the dicts vector are cleared.
188 //
189 // NOTE: This method assumes that old-style template dictionaries are not in
190 // use. That is, it assumes that all section dictionaries have been added
191 // with AddSectionDictionary rather than AddOldstyleSectionDictionary.
192 int GetSectionDictionaries(const TemplateString& section_name,
193 std::vector<const TemplateDictionary*>* dicts)
194 const;
195
196 // Retrieves included TemplateDictionary instances for the given name. The
197 // caller does not assume ownership of the returned TemplateDictionary
198 // instances. The number of instances is returned. All prior entries in
199 // the dicts vector are cleared.
200 //
201 // NOTE: This method assumes that old-style template dictionaries are not in
202 // use. That is, it assumes that all section dictionaries have been added
203 // with AddIncludeDictionary rather than AddOldstyleIncludeDictionary.
204 int GetIncludeDictionaries(const TemplateString& section_name,
205 std::vector<const TemplateDictionary*>* dicts)
206 const;
207
208 const char* GetIncludeTemplateName(const TemplateString& variable,
209 int dictnum) const;
210
211 typedef TemplateDictionaryPeerIterator Iterator;
212
213 Iterator* CreateTemplateIterator(const TemplateString& section)
214 const {
215 return new Iterator(dict_->CreateTemplateIterator(section));
216 }
217
218 Iterator* CreateSectionIterator(const TemplateString& section)
219 const {
220 return new Iterator(dict_->CreateSectionIterator(section));
221 }
222
223 // Returns the filename associated with the TemplateDictionary.
224 const char* GetFilename() const;
225
226 private:
227 const TemplateDictionary* dict_; // Not owned.
228
229 // disallow copy constructor and assignment
230 TemplateDictionaryPeer(const TemplateDictionaryPeer&);
231 void operator=(const TemplateDictionaryPeer&);
232};
233
234class TemplateCachePeer {
235 public:
236 TemplateCachePeer(TemplateCache* cache)
237 : cache_(cache) {}
238
239 struct TemplateCacheKey : public TemplateCache::TemplateCacheKey {
240 TemplateCacheKey(const string& key, int strip) {
241 this->first = GlobalIdForTest(key.data(), key.length());
242 this->second = strip;
243 }
244 };
245
246 TemplateCache::TemplateMap* parsed_template_cache() {
247 return cache_->parsed_template_cache_;
248 }
249
250 bool TemplateIsCached(const TemplateCacheKey key) const {
251 return cache_->TemplateIsCached(key);
252 }
253
254 const Template* GetTemplate(const TemplateString& key, Strip strip) const {
255 return cache_->GetTemplate(key, strip);
256 }
257
258 int Refcount(const TemplateCacheKey key) const {
259 return cache_->Refcount(key);
260 }
261
262 void DoneWithGetTemplatePtrs() {
263 cache_->DoneWithGetTemplatePtrs();
264 }
265 void ClearCache() {
266 cache_->ClearCache();
267 }
268
269 static int NumTotalTemplateDeletes() {
270 return Template::num_deletes();
271 }
272
273 private:
274 TemplateCache* cache_; // Not owned.
275
276 // Don't allow copying
277 TemplateCachePeer(const TemplateCachePeer&);
278 void operator=(const TemplateCachePeer&);
279};
280
281}
282
283#endif // TEMPLATE_TEMPLATE_TEST_UTIL_H_