Google APIs Client Library for C++
|
00001 /* 00002 * \copyright Copyright 2013 Google Inc. All Rights Reserved. 00003 * \license @{ 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 * 00017 * @} 00018 */ 00019 00020 00021 #ifndef APISERVING_CLIENTS_CPP_TRANSPORT_JSON_PLAYBACK_TRANSPORT_H_ 00022 #define APISERVING_CLIENTS_CPP_TRANSPORT_JSON_PLAYBACK_TRANSPORT_H_ 00023 00024 #include "googleapis/client/transport/http_transport.h" 00025 #include "googleapis/base/integral_types.h" 00026 #include "googleapis/base/macros.h" 00027 #include "googleapis/base/scoped_ptr.h" 00028 namespace googleapis { 00029 00030 namespace util { 00031 class Status; 00032 } // namespace util 00033 00034 namespace client { 00035 class DataReader; 00036 class JsonPlaybackTranscript; 00037 class HttpScribeCensor; 00038 00039 /* 00040 * A fake transport that plays back from a JSON scribed transcript. 00041 * @ingroup TransportLayerTesting 00042 * 00043 * This transport implementation can be used like any other, but it does 00044 * not connect to a real backend. Instead it acts as a _fake_ and will 00045 * attempt to pair requests with those in JSON transcript and use the 00046 * transcript to complete the request with a response or transport error. 00047 * 00048 * This is primarily intended to facilitate testing the application layer 00049 * without requiring the overhead, latency, and potential nondeterminissim 00050 * of using real-world servers. Plus you can hand code the transcript in whole 00051 * or part to inject errors or certain scenarios that might be difficult to 00052 * produce on demand for a test. 00053 * 00054 * To produce the transcript, you can inject a JsonScript into another 00055 * transport (such as CurlHttpTransport) and make the requests you wish to 00056 * playback later using this transport. 00057 * 00058 * To playback the transport use an instance of this class, or the 00059 * JsonPlaybackTransportFactory. For example if can set the default global 00060 * transport factory to a JsonPlaybackTransportFactory. Or you can give 00061 * a particular object (such as a ClientService instance) a 00062 * JsonPlaybackTransport. Load the JSON transcript into the trasnport (or 00063 * factory) then proceed as normal. 00064 * 00065 * @warning 00066 * For best recall and fidelity, you should set the HttpCensor on this 00067 * transport to one configured the same way as the JsonScribe when you 00068 * recorded the transcript. Otherwise the uncensored requests you are making 00069 * will not match the censored data in the transcript. 00070 * 00071 * @see JsonScribe 00072 */ 00073 class JsonPlaybackTransport : public HttpTransport { 00074 public: 00075 /* 00076 * Constructor with standard transport options. 00077 * 00078 * @param[in] options The standard options to configure the transport with. 00079 */ 00080 explicit JsonPlaybackTransport(const HttpTransportOptions& options); 00081 00082 /* 00083 * Standard destructor 00084 */ 00085 virtual ~JsonPlaybackTransport(); 00086 00087 /* 00088 * Implements the request factory method required by HttpTransport. 00089 * 00090 * @param[in] method The HTTP method to use for the request. 00091 * 00092 * @returns A new empty request that will use this fake transport when 00093 * executing. Use this request as if it were real. 00094 */ 00095 virtual HttpRequest* NewHttpRequest(const HttpRequest::HttpMethod& method); 00096 00097 /* 00098 * Loads the transcript from the reader. 00099 * 00100 * Alternatively you could use set_transport if you are sharing a transcript 00101 * across multiple transport instances. 00102 * 00103 * This method is not thread-safe, but you should only be performing it 00104 * once before you start executing messages. 00105 * 00106 * The transport instance will keep ownership of this transport instance 00107 * util another is loaded or the instance is deleted. 00108 * 00109 * @param[in] reader The reader to load the transcript from. 00110 * @return Whether the transcript could be loaded successfully. 00111 * 00112 * @see set_transport 00113 */ 00114 util::Status LoadTranscript(DataReader* reader); 00115 00116 /* 00117 * Sets the current transcript to the one provdied. 00118 * 00119 * This will override the transcript that was loaded 00120 * and owned by this instance. 00121 * 00122 * The transcript is thread-safe so can be shared across multiple 00123 * instaneces acting as a global transcript from a message stream 00124 * aggregated across all the transports sharing it. 00125 * 00126 * @param[in] t The caller maintains ownership of the transport. 00127 */ 00128 void set_transcript(JsonPlaybackTranscript* t) { transcript_ = t; } 00129 00130 /* 00131 * Returns the current transcript. 00132 * 00133 * @return The transcript may be the private one loaded into this instance 00134 * or might be a shared one that was explicitly set. NULL is returned 00135 * if there is no transcript bound yet. 00136 */ 00137 JsonPlaybackTranscript* transcript() const { return transcript_; } 00138 00139 /* 00140 * Sets the censor to use when resolving requests. 00141 * 00142 * It is important that this censors requests consistent to how they 00143 * were censored in the transcript or else the requests will not resolve 00144 * properly. 00145 * 00146 * @param[in] censor The caller retains ownership. 00147 */ 00148 void set_censor(HttpScribeCensor* censor) { censor_ = censor; } 00149 00150 /* 00151 * Returns the censor, if any. 00152 * 00153 * @return NULL if there is no censor. 00154 */ 00155 HttpScribeCensor* censor() const { return censor_; } 00156 00157 /* 00158 * The default id() attribute value identifying curl transport instances. 00159 */ 00160 static const StringPiece kTransportIdentifier; 00161 00162 private: 00163 scoped_ptr<JsonPlaybackTranscript> transcript_storage_; 00164 JsonPlaybackTranscript* transcript_; 00165 HttpScribeCensor* censor_; 00166 DISALLOW_COPY_AND_ASSIGN(JsonPlaybackTransport); 00167 }; 00168 00169 /* 00170 * A transport factory for creating JsonPlaybackTransport. 00171 * @ingroup TransportLayerTesting 00172 * 00173 * This is a standard HttpTransportFactory that can be used in place of 00174 * any other. 00175 * 00176 * You will need to configure it by loading a transcript and binding an 00177 * HttpScribeCensor. See the JsonPlaybackTransport for details regarding 00178 * the censor to use here for best results. 00179 * 00180 * @warning 00181 * The factory must remain valid over the lifetime of the instances it 00182 * creates because it owns the censor and transcript that those instances 00183 * are using. If you replace the censor and transcript on the instances 00184 * then you can destroy the fatory while those instances are still in use. 00185 */ 00186 class JsonPlaybackTransportFactory : public HttpTransportFactory { 00187 public: 00188 /* 00189 * The default consructor will use the default transport options. 00190 */ 00191 JsonPlaybackTransportFactory(); 00192 00193 /* 00194 * Standard constructor. 00195 */ 00196 explicit JsonPlaybackTransportFactory( 00197 const HttpTransportLayerConfig* config); 00198 00199 /* 00200 * Standard destructor. 00201 */ 00202 virtual ~JsonPlaybackTransportFactory(); 00203 00204 /* 00205 * Loads the transcript to be shared among all instances created. 00206 * 00207 * The factory will maintain ownership of this 00208 * @param[in] reader The reader containing the data output by a JsonScribe. 00209 * @return Whether the transcript could be loaded or not. 00210 */ 00211 util::Status LoadTranscript(DataReader* reader); 00212 00213 /* 00214 * Changes the censor used by this factory. 00215 * 00216 * @param censor Ownership is passed to the factory. 00217 * 00218 * @warning 00219 * The factory owns the censor given to instances it creates so this 00220 * method will invalidate the censor used by any outstanding instances unless 00221 * they had been explicitly replaced. 00222 */ 00223 void ResetCensor(HttpScribeCensor* censor); 00224 00225 /* 00226 * Returns the censor currently owned by the factory. 00227 */ 00228 HttpScribeCensor* censor() { return censor_.get(); } 00229 00230 protected: 00231 /* 00232 * Creates a new JsonPlaybackTransport instance configured with the 00233 * playback attributes specified in this factory. 00234 */ 00235 virtual HttpTransport* DoAlloc(const HttpTransportOptions& options); 00236 00237 private: 00238 scoped_ptr<JsonPlaybackTranscript> transcript_; 00239 scoped_ptr<HttpScribeCensor> censor_; 00240 DISALLOW_COPY_AND_ASSIGN(JsonPlaybackTransportFactory); 00241 }; 00242 00243 } // namespace client 00244 00245 } // namespace googleapis 00246 #endif // APISERVING_CLIENTS_CPP_TRANSPORT_JSON_PLAYBACK_TRANSPORT_H_