Google APIs Client Library for C++
json_playback_transport.h
Go to the documentation of this file.
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_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines