anastasis

Credential backup and recovery protocol and service
Log | Files | Refs | Submodules | README | LICENSE

anastasis_testing_lib.h (22404B)


      1 /*
      2   This file is part of Anastasis
      3   Copyright (C) 2020 Anastasis SARL
      4 
      5   Anastasis is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   Anastasis; see the file COPYING.GPL.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file include/anastasis_testing_lib.h
     18  * @brief API for writing an interpreter to test Taler components
     19  * @author Christian Grothoff <christian@grothoff.org>
     20  * @author Dennis Neufeld
     21  * @author Dominik Meister
     22  */
     23 #ifndef ANASTASIS_TESTING_LIB_H
     24 #define ANASTASIS_TESTING_LIB_H
     25 
     26 #include "anastasis.h"
     27 #include <taler/taler_testing_lib.h>
     28 #include <microhttpd.h>
     29 
     30 /* ********************* Helper functions ********************* */
     31 
     32 #define ANASTASIS_FAIL() \
     33         do {GNUNET_break (0); return NULL; } while (0)
     34 
     35 
     36 /**
     37  * Create headers for a trait with name @a name for
     38  * statically allocated data of type @a type.
     39  */
     40 #define ANASTASIS_TESTING_MAKE_DECL_SIMPLE_TRAIT(name,type)   \
     41         enum GNUNET_GenericReturnValue                          \
     42         ANASTASIS_TESTING_get_trait_ ## name (                    \
     43           const struct TALER_TESTING_Command *cmd,              \
     44           type **ret);                                          \
     45         struct TALER_TESTING_Trait                              \
     46         ANASTASIS_TESTING_make_trait_ ## name (                   \
     47           type * value);
     48 
     49 
     50 /**
     51  * Create C implementation for a trait with name @a name for statically
     52  * allocated data of type @a type.
     53  */
     54 #define ANASTASIS_TESTING_MAKE_IMPL_SIMPLE_TRAIT(name,type)  \
     55         enum GNUNET_GenericReturnValue                         \
     56         ANASTASIS_TESTING_get_trait_ ## name (                   \
     57           const struct TALER_TESTING_Command *cmd,             \
     58           type * *ret)                                          \
     59         {                                                      \
     60           if (NULL == cmd->traits) return GNUNET_SYSERR;       \
     61           return cmd->traits (cmd->cls,                        \
     62                               (const void **) ret,             \
     63                               TALER_S (name),                  \
     64                               0);                              \
     65         }                                                      \
     66         struct TALER_TESTING_Trait                             \
     67         ANASTASIS_TESTING_make_trait_ ## name (                  \
     68           type * value)                                        \
     69         {                                                      \
     70           struct TALER_TESTING_Trait ret = {                   \
     71             .trait_name = TALER_S (name),                      \
     72             .ptr = (const void *) value                        \
     73           };                                                   \
     74           return ret;                                          \
     75         }
     76 
     77 
     78 /**
     79  * Create headers for a trait with name @a name for
     80  * statically allocated data of type @a type.
     81  */
     82 #define ANASTASIS_TESTING_MAKE_DECL_INDEXED_TRAIT(name,type)  \
     83         enum GNUNET_GenericReturnValue                          \
     84         ANASTASIS_TESTING_get_trait_ ## name (                    \
     85           const struct TALER_TESTING_Command *cmd,              \
     86           unsigned int index,                                   \
     87           type **ret);                                          \
     88         struct TALER_TESTING_Trait                              \
     89         ANASTASIS_TESTING_make_trait_ ## name (                   \
     90           unsigned int index,                                   \
     91           type *value);
     92 
     93 
     94 /**
     95  * Create C implementation for a trait with name @a name for statically
     96  * allocated data of type @a type.
     97  */
     98 #define ANASTASIS_TESTING_MAKE_IMPL_INDEXED_TRAIT(name,type) \
     99         enum GNUNET_GenericReturnValue                         \
    100         ANASTASIS_TESTING_get_trait_ ## name (                   \
    101           const struct TALER_TESTING_Command *cmd,             \
    102           unsigned int index,                                  \
    103           type * *ret)                                          \
    104         {                                                      \
    105           if (NULL == cmd->traits) return GNUNET_SYSERR;       \
    106           return cmd->traits (cmd->cls,                        \
    107                               (const void **) ret,             \
    108                               TALER_S (name),                  \
    109                               index);                          \
    110         }                                                      \
    111         struct TALER_TESTING_Trait                             \
    112         ANASTASIS_TESTING_make_trait_ ## name (                  \
    113           unsigned int index,                                  \
    114           type * value)                                        \
    115         {                                                      \
    116           struct TALER_TESTING_Trait ret = {                   \
    117             .index = index,                                    \
    118             .trait_name = TALER_S (name),                      \
    119             .ptr = (const void *) value                        \
    120           };                                                   \
    121           return ret;                                          \
    122         }
    123 
    124 
    125 /**
    126  * Call #op on all simple traits.
    127  */
    128 #define ANASTASIS_TESTING_SIMPLE_TRAITS(op) \
    129         op (hash, const struct GNUNET_HashCode)  \
    130         op (truth, const struct ANASTASIS_Truth *)  \
    131         op (policy, const struct ANASTASIS_Policy *)  \
    132         op (provider_salt, const struct ANASTASIS_CRYPTO_ProviderSaltP)  \
    133         op (core_secret, const void)  \
    134         op (truth_key, const struct ANASTASIS_CRYPTO_TruthKeyP)  \
    135         op (account_pub, const struct ANASTASIS_CRYPTO_AccountPublicKeyP)  \
    136         op (account_priv, const struct ANASTASIS_CRYPTO_AccountPrivateKeyP)  \
    137         op (payment_secret, const struct ANASTASIS_PaymentSecretP)  \
    138         op (truth_uuid, const struct ANASTASIS_CRYPTO_TruthUUIDP)  \
    139         op (eks, const struct ANASTASIS_CRYPTO_EncryptedKeyShareP)  \
    140         op (code, const char) \
    141         op (filename, const char)
    142 
    143 
    144 /**
    145  * Call #op on all indexed traits.
    146  */
    147 #define ANASTASIS_TESTING_INDEXED_TRAITS(op)                         \
    148         op (challenges, const struct ANASTASIS_Challenge *)
    149 
    150 
    151 ANASTASIS_TESTING_SIMPLE_TRAITS (ANASTASIS_TESTING_MAKE_DECL_SIMPLE_TRAIT)
    152 
    153 ANASTASIS_TESTING_INDEXED_TRAITS (ANASTASIS_TESTING_MAKE_DECL_INDEXED_TRAIT)
    154 
    155 
    156 /**
    157  * Prepare the merchant execution.  Create tables and check if
    158  * the port is available.
    159  *
    160  * @param config_filename configuration filename.
    161  *
    162  * @return the base url, or NULL upon errors.  Must be freed
    163  *         by the caller.
    164  */
    165 char *
    166 TALER_TESTING_prepare_merchant (const char *config_filename);
    167 
    168 
    169 /**
    170  * Start the merchant backend process.  Assume the port
    171  * is available and the database is clean.  Use the "prepare
    172  * merchant" function to do such tasks.
    173  *
    174  * @param config_filename configuration filename.
    175  *
    176  * @return the process, or NULL if the process could not
    177  *         be started.
    178  */
    179 struct GNUNET_Process *
    180 TALER_TESTING_run_merchant (const char *config_filename,
    181                             const char *merchant_url);
    182 
    183 
    184 /**
    185  * Start the anastasis backend process.  Assume the port
    186  * is available and the database is clean.  Use the "prepare
    187  * anastasis" function to do such tasks.
    188  *
    189  * @param config_filename configuration filename.
    190  * @param anastasis_url URL to use to confirm service running
    191  * @return the process, or NULL if the process could not
    192  *         be started.
    193  */
    194 struct GNUNET_Process *
    195 ANASTASIS_TESTING_run_anastasis (const char *config_filename,
    196                                  const char *anastasis_url);
    197 
    198 
    199 /**
    200  * Construct a file name for the "file" authorization method to write a
    201  * challenge code to.  The plugin only accepts names inside the directory
    202  * configured as "[authorization-file] DIRECTORY", so the name is derived
    203  * from that configuration and a fresh subdirectory is created underneath
    204  * it.
    205  *
    206  * @param config_filename configuration filename.
    207  *
    208  * @return the file name, or NULL upon errors.  Must be freed
    209  *         by the caller.
    210  */
    211 char *
    212 ANASTASIS_TESTING_make_file_challenge_name (const char *config_filename);
    213 
    214 
    215 /**
    216  * Prepare the anastasis execution.  Create tables and check if
    217  * the port is available.
    218  *
    219  * @param config_filename configuration filename.
    220  *
    221  * @return the base url, or NULL upon errors.  Must be freed
    222  *         by the caller.
    223  */
    224 char *
    225 ANASTASIS_TESTING_prepare_anastasis (const char *config_filename);
    226 
    227 
    228 /* ************** Specific interpreter commands ************ */
    229 
    230 
    231 /**
    232  * Types of options for performing the upload. Used as a bitmask.
    233  */
    234 enum ANASTASIS_TESTING_PolicyStoreOption
    235 {
    236   /**
    237    * Do everything by the book.
    238    */
    239   ANASTASIS_TESTING_PSO_NONE = 0,
    240 
    241   /**
    242    * Use random hash for previous upload instead of correct
    243    * previous hash.
    244    */
    245   ANASTASIS_TESTING_PSO_PREV_HASH_WRONG = 1,
    246 
    247   /**
    248    * Request payment.
    249    */
    250   ANASTASIS_TESTING_PSO_REQUEST_PAYMENT = 2,
    251 
    252   /**
    253    * Reference payment order ID from linked previous upload.
    254    */
    255   ANASTASIS_TESTING_PSO_REFERENCE_ORDER_ID = 4
    256 
    257 };
    258 
    259 
    260 /**
    261  * Make a "policy store" command.
    262  *
    263  * @param label command label
    264  * @param anastasis_url base URL of the anastasis serving
    265  *        the policy store request.
    266  * @param prev_upload reference to a previous upload we are
    267  *        supposed to update, NULL for none
    268  * @param http_status expected HTTP status.
    269  * @param pso policy store options
    270  * @param recovery_data recovery data to post
    271  * @param recovery_data_size size of recovery/policy data
    272  * @return the command
    273  */
    274 struct TALER_TESTING_Command
    275 ANASTASIS_TESTING_cmd_policy_store (
    276   const char *label,
    277   const char *anastasis_url,
    278   const char *prev_upload,
    279   unsigned int http_status,
    280   enum ANASTASIS_TESTING_PolicyStoreOption pso,
    281   const void *recovery_data,
    282   size_t recovery_data_size);
    283 
    284 
    285 /**
    286  * Make the "policy lookup" command.
    287  *
    288  * @param label command label
    289  * @param anastasis_url base URL of the ANASTASIS serving
    290  *        the policy store request.
    291  * @param http_status expected HTTP status.
    292  * @param upload_ref reference to upload command
    293  * @return the command
    294  */
    295 struct TALER_TESTING_Command
    296 ANASTASIS_TESTING_cmd_policy_lookup (const char *label,
    297                                      const char *anastasis_url,
    298                                      unsigned int http_status,
    299                                      const char *upload_ref);
    300 
    301 
    302 /**
    303  * Make the "policy lookup" command for a non-existent upload.
    304  *
    305  * @param label command label
    306  * @param anastasis_url base URL of the ANASTASIS serving
    307  *        the policy lookup request.
    308  * @return the command
    309  */
    310 struct TALER_TESTING_Command
    311 ANASTASIS_TESTING_cmd_policy_nx (const char *label,
    312                                  const char *anastasis_url);
    313 
    314 
    315 /**
    316  * Types of options for performing the upload. Used as a bitmask.
    317  */
    318 enum ANASTASIS_TESTING_TruthStoreOption
    319 {
    320   /**
    321    * Do everything by the book.
    322    */
    323   ANASTASIS_TESTING_TSO_NONE = 0,
    324 
    325   /**
    326    * Re-use UUID of previous upload instead of creating a random one.
    327    */
    328   ANASTASIS_TESTING_TSO_REFERENCE_UUID = 1,
    329 
    330   /**
    331    * Explicitly request payment.
    332    */
    333   ANASTASIS_TESTING_TSO_REQUEST_PAYMENT = 2,
    334 
    335   /**
    336    * Reference payment order ID from linked previous upload.
    337    */
    338   ANASTASIS_TESTING_TSO_REFERENCE_ORDER_ID = 4
    339 
    340 };
    341 
    342 
    343 /**
    344  * Make the "truth store" command.
    345  *
    346  * @param label command label
    347  * @param anastasis_url base URL of the anastasis serving
    348  *        the truth store request.
    349  * @param prev_upload reference to a previous upload to get a payment ID from
    350  * @param method what authentication method is being used
    351  * @param mime_type MIME type of @a truth_data
    352  * @param truth_data_size number of bytes in @a truth_data
    353  * @param truth_data recovery data to post /truth (in plaintext)
    354  * @param tso flags
    355  * @param http_status expected HTTP status.
    356  * @return the command
    357  */
    358 struct TALER_TESTING_Command
    359 ANASTASIS_TESTING_cmd_truth_store (const char *label,
    360                                    const char *anastasis_url,
    361                                    const char *prev_upload,
    362                                    const char *method,
    363                                    const char *mime_type,
    364                                    size_t truth_data_size,
    365                                    const void *truth_data,
    366                                    enum ANASTASIS_TESTING_TruthStoreOption tso,
    367                                    unsigned int http_status);
    368 
    369 
    370 /**
    371  * Make the "truth store" command for a secure question.
    372  *
    373  * @param label command label
    374  * @param anastasis_url base URL of the anastasis serving
    375  *        the truth store request.
    376  * @param prev_upload reference to a previous upload to get a payment ID from
    377  * @param answer the answer to the question
    378  * @param tso flags
    379  * @param http_status expected HTTP status.
    380  * @return the command
    381  */
    382 struct TALER_TESTING_Command
    383 ANASTASIS_TESTING_cmd_truth_question (
    384   const char *label,
    385   const char *anastasis_url,
    386   const char *prev_upload,
    387   const char *answer,
    388   enum ANASTASIS_TESTING_TruthStoreOption tso,
    389   unsigned int http_status);
    390 
    391 
    392 /**
    393  * Make a "truth challenge" command.
    394  *
    395  * @param label command label
    396  * @param anastasis_url base URL of the ANASTASIS serving
    397  *        the keyshare lookup request.
    398  * @param answer (response to challenge)
    399  * @param payment_ref reference to the payment request
    400  * @param upload_ref reference to upload command
    401  * @param http_status expected HTTP status
    402  * @return the command
    403  */
    404 struct TALER_TESTING_Command
    405 ANASTASIS_TESTING_cmd_truth_challenge (
    406   const char *label,
    407   const char *anastasis_url,
    408   const char *payment_ref,
    409   const char *upload_ref,
    410   unsigned int http_status);
    411 
    412 
    413 /**
    414  * Make a "truth solve" command.
    415  *
    416  * @param label command label
    417  * @param anastasis_url base URL of the ANASTASIS serving
    418  *        the keyshare lookup request.
    419  * @param answer (response to challenge)
    420  * @param payment_ref reference to the payment request
    421  * @param upload_ref reference to upload command
    422  * @param lookup_mode 0 for security question, 1 for
    423  *          code-based
    424  * @param http_status expected HTTP status
    425  * @return the command
    426  */
    427 struct TALER_TESTING_Command
    428 ANASTASIS_TESTING_cmd_truth_solve (
    429   const char *label,
    430   const char *anastasis_url,
    431   const char *answer,
    432   const char *payment_ref,
    433   const char *upload_ref,
    434   int lookup_mode,
    435   unsigned int http_status);
    436 
    437 
    438 /**
    439  * Make the "/config" command.
    440  *
    441  * @param label command label
    442  * @param anastasis_url base URL of the ANASTASIS serving
    443  *        the /config request.
    444  * @param http_status expected HTTP status.
    445  * @return the command
    446  */
    447 struct TALER_TESTING_Command
    448 ANASTASIS_TESTING_cmd_config (const char *label,
    449                               const char *anastasis_url,
    450                               unsigned int http_status);
    451 
    452 /* ********************* test truth upload ********************* */
    453 
    454 /**
    455  * Creates a sample of id_data.
    456  *
    457  * @param id_data some sample data (e.g. AHV, name, surname, ...)
    458  * @return truth in json format
    459  */
    460 json_t *
    461 ANASTASIS_TESTING_make_id_data_example (const char *id_data);
    462 
    463 
    464 /**
    465  * Make the "truth upload" command.
    466  *
    467  * @param label command label
    468  * @param anastasis_url base URL of the anastasis serving our requests.
    469  * @param id_data ID data to generate user identifier
    470  * @param method specifies escrow method
    471  * @param instructions specifies what the client/user has to do
    472  * @param mime_type mime type of truth_data
    473  * @param truth_data some truth data (e.g. hash of answer to a secret question)
    474  * @param truth_data_size size of truth_data
    475  * @param http_status expected HTTP status
    476  * @param tso truth upload options
    477  * @param upload_ref reference to the previous upload
    478  * @return the command
    479  */
    480 struct TALER_TESTING_Command
    481 ANASTASIS_TESTING_cmd_truth_upload (
    482   const char *label,
    483   const char *anastasis_url,
    484   const json_t *id_data,
    485   const char *method,
    486   const char *instructions,
    487   const char *mime_type,
    488   const void *truth_data,
    489   size_t truth_data_size,
    490   unsigned int http_status,
    491   enum ANASTASIS_TESTING_TruthStoreOption tso,
    492   const char *upload_ref);
    493 
    494 
    495 /**
    496  * Make the "truth upload" command for a security question.
    497  *
    498  * @param label command label
    499  * @param anastasis_url base URL of the anastasis serving our requests.
    500  * @param id_data ID data to generate user identifier
    501  * @param instructions specifies what the client/user has to do
    502  * @param mime_type mime type of truth_data
    503  * @param answer the answer to the security question
    504  * @param http_status expected HTTP status
    505  * @param tso truth upload options
    506  * @param salt_ref reference to command downloading provider salt
    507  * @return the command
    508  */
    509 struct TALER_TESTING_Command
    510 ANASTASIS_TESTING_cmd_truth_upload_question (
    511   const char *label,
    512   const char *anastasis_url,
    513   const json_t *id_data,
    514   const char *instructions,
    515   const char *mime_type,
    516   const void *answer,
    517   unsigned int http_status,
    518   enum ANASTASIS_TESTING_TruthStoreOption tso,
    519   const char *salt_ref);
    520 
    521 /* ********************* test policy create ********************* */
    522 
    523 
    524 /**
    525  * Make the "policy create" command.
    526  *
    527  * @param label command label
    528  * @param ... NULL-terminated list of truth upload commands
    529  * @return the command
    530  */
    531 struct TALER_TESTING_Command
    532 ANASTASIS_TESTING_cmd_policy_create (const char *label,
    533                                      ...);
    534 
    535 
    536 /* ********************* test secret share ********************* */
    537 
    538 
    539 /**
    540  * Types of options for performing the secret sharing. Used as a bitmask.
    541  */
    542 enum ANASTASIS_TESTING_SecretShareOption
    543 {
    544   /**
    545    * Do everything by the book.
    546    */
    547   ANASTASIS_TESTING_SSO_NONE = 0,
    548 
    549   /**
    550    * Request payment.
    551    */
    552   ANASTASIS_TESTING_SSO_REQUEST_PAYMENT = 2,
    553 
    554   /**
    555    * Reference payment order ID from linked previous upload.
    556    */
    557   ANASTASIS_TESTING_SSO_REFERENCE_ORDER_ID = 4
    558 
    559 };
    560 
    561 /**
    562  * Make the "secret share" command.
    563  *
    564  * @param label command label
    565  * @param anastasis_url base URL of the anastasis serving our requests.
    566  * @param config_ref reference to /config operation for @a anastasis_url
    567  * @param prev_secret_share reference to a previous secret share command
    568  * @param id_data ID data to generate user identifier
    569  * @param core_secret core secret to backup/recover
    570  * @param core_secret_size size of @a core_secret
    571  * @param want_status expected status.
    572  * @param sso secret share options
    573  * @param ... NULL-terminated list of policy create commands
    574  * @return the command
    575  */
    576 struct TALER_TESTING_Command
    577 ANASTASIS_TESTING_cmd_secret_share (
    578   const char *label,
    579   const char *anastasis_url,
    580   const char *config_ref,
    581   const char *prev_secret_share,
    582   const json_t *id_data,
    583   const void *core_secret,
    584   size_t core_secret_size,
    585   enum ANASTASIS_ShareStatus want_status,
    586   enum ANASTASIS_TESTING_SecretShareOption sso,
    587   ...);
    588 
    589 
    590 /* ********************* test recover secret ********************* */
    591 
    592 /**
    593  * Types of options for performing the secret recovery. Used as a bitmask.
    594  */
    595 enum ANASTASIS_TESTING_RecoverSecretOption
    596 {
    597   /**
    598    * Do everything by the book.
    599    */
    600   ANASTASIS_TESTING_RSO_NONE = 0,
    601 
    602   /**
    603    * Request payment.
    604    */
    605   ANASTASIS_TESTING_RSO_REQUEST_PAYMENT = 2,
    606 
    607   /**
    608    * Reference payment order ID from linked previous download.
    609    */
    610   ANASTASIS_TESTING_RSO_REFERENCE_ORDER_ID = 4
    611 
    612 };
    613 
    614 
    615 /**
    616  * Make the "recover secret" command.
    617  *
    618  * @param label command label
    619  * @param anastasis_url base URL of the anastasis serving our requests.
    620  * @param id_data identfication data from the user
    621  * @param version of the recovery document to download
    622  * @param rso recover secret options
    623  * @param download_ref salt download reference
    624  * @param core_secret_ref reference to core secret
    625  *         we expect to recover
    626  * @return the command
    627  */
    628 struct TALER_TESTING_Command
    629 ANASTASIS_TESTING_cmd_recover_secret (
    630   const char *label,
    631   const char *anastasis_url,
    632   const json_t *id_data,
    633   unsigned int version,
    634   enum ANASTASIS_TESTING_RecoverSecretOption rso,
    635   const char *download_ref,
    636   const char *core_secret_ref);
    637 
    638 
    639 /**
    640  * Make "recover secret finish" command.
    641  *
    642  * @param label command label
    643  * @param recover_label label of a "recover secret" command to wait for
    644  * @param timeout how long to wait at most
    645  * @return the command
    646  */
    647 struct TALER_TESTING_Command
    648 ANASTASIS_TESTING_cmd_recover_secret_finish (
    649   const char *label,
    650   const char *recover_label,
    651   struct GNUNET_TIME_Relative timeout);
    652 
    653 
    654 /* ********************* test challenge answer ********************* */
    655 
    656 /**
    657  * Create a "challenge start" command. Suitable for the "file"
    658  * authorization plugin.
    659  *
    660  * @param label command label
    661  * @param payment_ref reference to payment made for this challenge
    662  * @param challenge_ref reference to the recovery process
    663  * @param challenge_index defines the index of the trait to solve
    664  * @param expected_cs expected reply type
    665  * @return the command
    666  */
    667 struct TALER_TESTING_Command
    668 ANASTASIS_TESTING_cmd_challenge_start (
    669   const char *label,
    670   const char *payment_ref,
    671   const char *challenge_ref,
    672   unsigned int challenge_index,
    673   enum ANASTASIS_ChallengeStartStatus expected_cs);
    674 
    675 
    676 /**
    677  * Make the "challenge answer" command.
    678  *
    679  * @param label command label
    680  * @param payment_ref reference to payment made for this challenge
    681  * @param challenge_ref reference to the recovery process
    682  * @param challenge_index defines the index of the trait to solve
    683  * @param answer to the challenge
    684  * @param mode 0 for no plugin needed (security question)
    685  *             1 for plugin needed to authenticate
    686  * @param expected_cs expected reply type
    687  * @return the command
    688  */
    689 struct TALER_TESTING_Command
    690 ANASTASIS_TESTING_cmd_challenge_answer (
    691   const char *label,
    692   const char *payment_ref,
    693   const char *challenge_ref,
    694   unsigned int challenge_index,
    695   const char *answer,
    696   unsigned int mode,
    697   enum ANASTASIS_ChallengeAnswerStatus expected_cs);
    698 
    699 
    700 #endif