/*
This file is part of SYNC
Copyright (C) 2014-2019 Taler Systems SA
SYNC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3, or
(at your option) any later version.
SYNC is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public
License along with SYNC; see the file COPYING. If not, see
*/
/**
* @file lib/testing_api_cmd_backup_download.c
* @brief command to download data to the sync backend service.
* @author Christian Grothoff
*/
#include "platform.h"
#include "sync_service.h"
#include "sync_testing_lib.h"
#include
#include
/**
* State for a "backup download" CMD.
*/
struct BackupDownloadState
{
/**
* Eddsa public key.
*/
struct SYNC_AccountPublicKeyP sync_pub;
/**
* Hash of the upload (all zeros if there was no upload).
*/
const struct GNUNET_HashCode *upload_hash;
/**
* Hash of the previous upload (all zeros if there was no previous upload).
*/
const struct GNUNET_HashCode *prev_upload_hash;
/**
* The /backups POST operation handle.
*/
struct SYNC_DownloadOperation *download;
/**
* URL of the sync backend.
*/
const char *sync_url;
/**
* The interpreter state.
*/
struct TALER_TESTING_Interpreter *is;
/**
* Reference to upload command we expect to download.
*/
const char *upload_reference;
/**
* Expected status code.
*/
unsigned int http_status;
};
/**
* Function called with the results of a #SYNC_download().
*
* @param cls closure
* @param http_status HTTP status of the request
* @param ud details about the download operation
*/
static void
backup_download_cb (void *cls,
unsigned int http_status,
const struct SYNC_DownloadDetails *dd)
{
struct BackupDownloadState *bds = cls;
bds->download = NULL;
if (http_status != bds->http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u to command %s in %s:%u\n",
http_status,
bds->is->commands[bds->is->ip].label,
__FILE__,
__LINE__);
TALER_TESTING_interpreter_fail (bds->is);
return;
}
if (NULL != bds->upload_reference)
{
if ( (MHD_HTTP_OK == http_status) &&
(0 != GNUNET_memcmp (&dd->curr_backup_hash,
bds->upload_hash)) )
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (bds->is);
return;
}
if ( (MHD_HTTP_OK == http_status) &&
(0 != GNUNET_memcmp (&dd->prev_backup_hash,
bds->prev_upload_hash)) )
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (bds->is);
return;
}
}
TALER_TESTING_interpreter_next (bds->is);
}
/**
* Run a "backup download" CMD.
*
* @param cls closure.
* @param cmd command currently being run.
* @param is interpreter state.
*/
static void
backup_download_run (void *cls,
const struct TALER_TESTING_Command *cmd,
struct TALER_TESTING_Interpreter *is)
{
struct BackupDownloadState *bds = cls;
bds->is = is;
if (NULL != bds->upload_reference)
{
const struct TALER_TESTING_Command *upload_cmd;
const struct SYNC_AccountPublicKeyP *sync_pub;
upload_cmd = TALER_TESTING_interpreter_lookup_command
(is,
bds->upload_reference);
if (NULL == upload_cmd)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (bds->is);
return;
}
if (GNUNET_OK !=
SYNC_TESTING_get_trait_hash (upload_cmd,
SYNC_TESTING_TRAIT_HASH_CURRENT,
&bds->upload_hash))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (bds->is);
return;
}
if (GNUNET_OK !=
SYNC_TESTING_get_trait_hash (upload_cmd,
SYNC_TESTING_TRAIT_HASH_PREVIOUS,
&bds->prev_upload_hash))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (bds->is);
return;
}
if (GNUNET_OK !=
SYNC_TESTING_get_trait_account_pub (upload_cmd,
0,
&sync_pub))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (bds->is);
return;
}
bds->sync_pub = *sync_pub;
}
bds->download = SYNC_download (is->ctx,
bds->sync_url,
&bds->sync_pub,
&backup_download_cb,
bds);
if (NULL == bds->download)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (bds->is);
return;
}
}
/**
* Free the state of a "backup download" CMD, and possibly
* cancel it if it did not complete.
*
* @param cls closure.
* @param cmd command being freed.
*/
static void
backup_download_cleanup (void *cls,
const struct TALER_TESTING_Command *cmd)
{
struct BackupDownloadState *bds = cls;
if (NULL != bds->download)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Command '%s' did not complete (backup download)\n",
cmd->label);
SYNC_download_cancel (bds->download);
bds->download = NULL;
}
GNUNET_free (bds);
}
/**
* Make the "backup download" command.
*
* @param label command label
* @param sync_url base URL of the sync serving
* the policy store request.
* @param http_status expected HTTP status.
* @param upload_ref reference to upload command
* @return the command
*/
struct TALER_TESTING_Command
SYNC_TESTING_cmd_backup_download (const char *label,
const char *sync_url,
unsigned int http_status,
const char *upload_ref)
{
struct BackupDownloadState *bds;
GNUNET_assert (NULL != upload_ref);
bds = GNUNET_new (struct BackupDownloadState);
bds->http_status = http_status;
bds->sync_url = sync_url;
bds->upload_reference = upload_ref;
{
struct TALER_TESTING_Command cmd = {
.cls = bds,
.label = label,
.run = &backup_download_run,
.cleanup = &backup_download_cleanup
};
return cmd;
}
}
/**
* Make the "backup download" command for a non-existent upload.
*
* @param label command label
* @param sync_url base URL of the sync serving
* the policy store request.
* @return the command
*/
struct TALER_TESTING_Command
SYNC_TESTING_cmd_backup_nx (const char *label,
const char *sync_url)
{
struct BackupDownloadState *bds;
struct GNUNET_CRYPTO_EddsaPrivateKey priv;
bds = GNUNET_new (struct BackupDownloadState);
bds->http_status = MHD_HTTP_NOT_FOUND;
bds->sync_url = sync_url;
GNUNET_CRYPTO_eddsa_key_create (&priv);
GNUNET_CRYPTO_eddsa_key_get_public (&priv,
&bds->sync_pub.eddsa_pub);
{
struct TALER_TESTING_Command cmd = {
.cls = bds,
.label = label,
.run = &backup_download_run,
.cleanup = &backup_download_cleanup
};
return cmd;
}
}