<commit_before>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include "auth/Auth.h"
#include "common/ceph_argparse.h"
#include "common/common_init.h"
#include "common/ConfUtils.h"
#include "common/version.h"
#include "common/config.h"
#include "include/intarith.h"
#include "include/str_list.h"
#include "msg/msg_types.h"

#include <deque>
#include <stdarg.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <vector>

/*
 * Ceph argument parsing library
 *
 * We probably should eventually replace this with something standard like popt.
 * Until we do that, though, this file is the place for argv parsing
 * stuff to live.
 */

#undef dout
#undef pdout
#undef derr
#undef generic_dout
#undef dendl

static bool cmd_is_char(const char *cmd)
{
  return ((cmd[0] == '-') &&
    cmd[1] && !cmd[2]);
}

bool ceph_argparse_cmd_equals(const char *cmd, const char *opt, char char_opt,
			      unsigned int *val_pos)
{
  unsigned int i;
  unsigned int len = strlen(opt);

  *val_pos = 0;

  if (!*cmd)
    return false;

  if (char_opt && cmd_is_char(cmd))
    return (char_opt == cmd[1]);

  if ((cmd[0] != '-') || (cmd[1] != '-'))
    return false;

  for (i=0; i<len; i++) {
    if ((opt[i] == '_') || (opt[i] == '-')) {
      switch (cmd[i+2]) {
      case '-':
      case '_':
        continue;
      default:
        break;
      }
    }

    if (cmd[i+2] != opt[i])
      return false;
  }

  if (cmd[i+2] == '=')
    *val_pos = i+3;
  else if (cmd[i+2])
    return false;

  return true;
}

bool ceph_argparse_cmdline_val(void *field, int type, const char *val)
{
  switch (type) {
  case OPT_BOOL:
    if (strcasecmp(val, "false") == 0)
      *(bool *)field = false;
    else if (strcasecmp(val, "true") == 0)
      *(bool *)field = true;
    else
      *(bool *)field = (bool)atoi(val);
    break;
  case OPT_INT:
    *(int *)field = atoi(val);
    break;
  case OPT_LONGLONG:
    *(long long *)field = atoll(val);
    break;
  case OPT_STR:
    if (val)
      *(char **)field = strdup(val);
    else
      *(char **)field = NULL;
    break;
  case OPT_FLOAT:
    *(float *)field = atof(val);
    break;
  case OPT_DOUBLE:
    *(double *)field = strtod(val, NULL);
    break;
  case OPT_ADDR:
    ((entity_addr_t *)field)->parse(val);
    break;
  default:
    return false;
  }

  return true;
}

void env_to_vec(std::vector<const char*>& args)
{
  char *p = getenv("CEPH_ARGS");
  if (!p) return;

  static char buf[1000];
  int len = MIN(strlen(p), sizeof(buf)-1);  // bleh.
  memcpy(buf, p, len);
  buf[len] = 0;
  //cout << "CEPH_ARGS='" << p << ";" << endl;

  p = buf;
  while (*p && p < buf + len) {
    char *e = p;
    while (*e && *e != ' ')
      e++;
    *e = 0;
    args.push_back(p);
    //cout << "arg " << p << std::endl;
    p = e+1;
  }
}

void env_to_deq(std::deque<const char*>& args)
{
  char *p = getenv("CEPH_ARGS");
  if (!p) return;

  static char buf[1000];
  int len = MIN(strlen(p), sizeof(buf)-1);  // bleh.
  memcpy(buf, p, len);
  buf[len] = 0;

  p = buf;
  while (*p && p < buf + len) {
    char *e = p;
    while (*e && *e != ' ')
      e++;
    *e = 0;
    args.push_back(p);
    p = e+1;
  }
}

void argv_to_vec(int argc, const char **argv,
                 std::vector<const char*>& args)
{
  for (int i=1; i<argc; i++)
    args.push_back(argv[i]);
}

void argv_to_deq(int argc, const char **argv,
                 std::deque<const char*>& args)
{
  for (int i=1; i<argc; i++)
    args.push_back(argv[i]);
}

void vec_to_argv(std::vector<const char*>& args,
                 int& argc, const char **&argv)
{
  const char *myname = "asdf";
  if (argc && argv)
    myname = argv[0];
  argv = (const char**)malloc(sizeof(char*) * argc);
  argc = 1;
  argv[0] = myname;

  for (unsigned i=0; i<args.size(); i++)
    argv[argc++] = args[i];
}

bool parse_ip_port_vec(const char *s, vector<entity_addr_t>& vec)
{
  const char *p = s;
  const char *end = p + strlen(p);
  while (p < end) {
    entity_addr_t a;
    //cout << " parse at '" << p << "'" << std::endl;
    if (!a.parse(p, &p)) {
      //dout(0) << " failed to parse address '" << p << "'" << dendl;
      return false;
    }
    //cout << " got " << a << ", rest is '" << p << "'" << std::endl;
    vec.push_back(a);
    while (*p == ',' || *p == ' ')
      p++;
  }
  return true;
}

void parse_config_option_string(std::string& s)
{
  char b[s.length()+1];
  strcpy(b, s.c_str());
  std::vector<const char*> nargs;
  char *p = b;
  while (*p) {
    nargs.push_back(p);
    while (*p && *p != ' ') p++;
    if (!*p)
      break;
    *p++ = 0;
    while (*p && *p == ' ') p++;
  }
  g_conf.parse_argv(nargs);
}

// The defaults for CephInitParameters
CephInitParameters::CephInitParameters(uint32_t module_type, const char *conf_file_)
  : conf_file(conf_file_)
{
  const char *c = getenv("CEPH_CONF");
  if (c)
    conf_file = c;
  name.set(module_type, "admin");
}

std::list<std::string> CephInitParameters::
get_conf_files() const
{
  std::list<std::string> ret;
  get_str_list(conf_file, ret);
  return ret;
}

static void dashes_to_underscores(const char *input, char *output)
{
  char c = 0;
  char *o = output;
  const char *i = input;
  // first two characters are copied as-is
  *o = *i++;
  if (*o++ == '\0')
    return;
  *o = *i++;
  if (*o++ == '\0')
    return;
  for (; ((c = *i)); ++i) {
     if (c == '-')
       *o++ = '_';
     else
       *o++ = c;
  }
  *o++ = '\0';
}

bool ceph_argparse_flag(std::vector<const char*> &args,
	std::vector<const char*>::iterator &i, ...)
{
  const char *first = *i;
  char tmp[strlen(first)+1];
  dashes_to_underscores(first, tmp);
  first = tmp;
  const char *a;
  va_list ap;

  va_start(ap, i);
  while (1) {
    a = va_arg(ap, char*);
    if (a == NULL)
      return false;
    if (strcmp(a, first) == 0) {
      i = args.erase(i);
      return true;
    }
  }
}

bool ceph_argparse_witharg(std::vector<const char*> &args,
	std::vector<const char*>::iterator &i, std::string *ret, ...)
{
  const char *first = *i;
  char tmp[strlen(first)+1];
  dashes_to_underscores(first, tmp);
  first = tmp;
  const char *a;
  va_list ap;
  int strlen_a;

  // does this argument match any of the possibilities?
  va_start(ap, ret);
  while (1) {
    a = va_arg(ap, char*);
    if (a == NULL)
      return false;
    strlen_a = strlen(a);
    if (strncmp(a, first, strlen(a)) == 0) {
      if (first[strlen_a] == '=') {
	*ret = first + strlen_a + 1;
	i = args.erase(i);
	return true;
      }
      else if (first[strlen_a] == '\0') {
	// find second part (or not)
	if (i+1 == args.end()) {
	  std::cerr << "Option " << *i << " requires an argument." << std::endl;
	  _exit(1);
	}
	i = args.erase(i);
	*ret = *i;
	i = args.erase(i);
	return true;
      }
    }
  }
}

CephInitParameters ceph_argparse_early_args
	  (std::vector<const char*>& args, uint32_t module_type, int flags)
{
  const char *conf = (flags & CINIT_FLAG_NO_DEFAULT_CONFIG_FILE) ?
    "" : CEPH_CONF_FILE_DEFAULT;
  CephInitParameters iparams(module_type, conf);
  std::string val;
  for (std::vector<const char*>::iterator i = args.begin(); i != args.end(); ) {
    if (strcmp(*i, "--") == 0)
      break;
    else if (ceph_argparse_flag(args, i, "--version", "-v", (char*)NULL)) {
      cout << pretty_version_to_str() << std::endl;
      _exit(0);
    }
    else if (ceph_argparse_witharg(args, i, &val, "--conf", "-c", (char*)NULL)) {
      iparams.conf_file = val;
    }
    else if ((module_type != CEPH_ENTITY_TYPE_CLIENT) &&
	     (ceph_argparse_witharg(args, i, &val, "-i", (char*)NULL))) {
      iparams.name.set_id(val);
    }
    else if (ceph_argparse_witharg(args, i, &val, "--id", (char*)NULL)) {
      iparams.name.set_id(val);
    }
    else if (ceph_argparse_witharg(args, i, &val, "--name", "-n", (char*)NULL)) {
      if (!iparams.name.from_str(val)) {
	std::cerr << "You must pass a string of the form ID.TYPE to "
	  "the --name option." << std::endl;
	_exit(1);
      }
    }
    else {
      // ignore
      ++i;
    }
  }
  return iparams;
}

static void generic_usage(bool is_server)
{
  cout << "\
--conf/-c        Read configuration from the given configuration file\n\
-D               Run in the foreground.\n\
-f               Run in foreground. Show all log messages on stderr.\n\
--id             set ID\n\
--name           set ID.TYPE\n\
--version        show version and quit\n\
" << std::endl;

  if (is_server) {
    cout << "   --debug_ms N\n";
    cout << "        set message debug level (e.g. 1)\n";
  }
}

void generic_server_usage()
{
  generic_usage(true);
  exit(1);
}
void generic_client_usage()
{
  generic_usage(false);
  exit(1);
}
<commit_msg>ceph_argparse: fix silly usage message<commit_after>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include "auth/Auth.h"
#include "common/ceph_argparse.h"
#include "common/common_init.h"
#include "common/ConfUtils.h"
#include "common/version.h"
#include "common/config.h"
#include "include/intarith.h"
#include "include/str_list.h"
#include "msg/msg_types.h"

#include <deque>
#include <stdarg.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <vector>

/*
 * Ceph argument parsing library
 *
 * We probably should eventually replace this with something standard like popt.
 * Until we do that, though, this file is the place for argv parsing
 * stuff to live.
 */

#undef dout
#undef pdout
#undef derr
#undef generic_dout
#undef dendl

static bool cmd_is_char(const char *cmd)
{
  return ((cmd[0] == '-') &&
    cmd[1] && !cmd[2]);
}

bool ceph_argparse_cmd_equals(const char *cmd, const char *opt, char char_opt,
			      unsigned int *val_pos)
{
  unsigned int i;
  unsigned int len = strlen(opt);

  *val_pos = 0;

  if (!*cmd)
    return false;

  if (char_opt && cmd_is_char(cmd))
    return (char_opt == cmd[1]);

  if ((cmd[0] != '-') || (cmd[1] != '-'))
    return false;

  for (i=0; i<len; i++) {
    if ((opt[i] == '_') || (opt[i] == '-')) {
      switch (cmd[i+2]) {
      case '-':
      case '_':
        continue;
      default:
        break;
      }
    }

    if (cmd[i+2] != opt[i])
      return false;
  }

  if (cmd[i+2] == '=')
    *val_pos = i+3;
  else if (cmd[i+2])
    return false;

  return true;
}

bool ceph_argparse_cmdline_val(void *field, int type, const char *val)
{
  switch (type) {
  case OPT_BOOL:
    if (strcasecmp(val, "false") == 0)
      *(bool *)field = false;
    else if (strcasecmp(val, "true") == 0)
      *(bool *)field = true;
    else
      *(bool *)field = (bool)atoi(val);
    break;
  case OPT_INT:
    *(int *)field = atoi(val);
    break;
  case OPT_LONGLONG:
    *(long long *)field = atoll(val);
    break;
  case OPT_STR:
    if (val)
      *(char **)field = strdup(val);
    else
      *(char **)field = NULL;
    break;
  case OPT_FLOAT:
    *(float *)field = atof(val);
    break;
  case OPT_DOUBLE:
    *(double *)field = strtod(val, NULL);
    break;
  case OPT_ADDR:
    ((entity_addr_t *)field)->parse(val);
    break;
  default:
    return false;
  }

  return true;
}

void env_to_vec(std::vector<const char*>& args)
{
  char *p = getenv("CEPH_ARGS");
  if (!p) return;

  static char buf[1000];
  int len = MIN(strlen(p), sizeof(buf)-1);  // bleh.
  memcpy(buf, p, len);
  buf[len] = 0;
  //cout << "CEPH_ARGS='" << p << ";" << endl;

  p = buf;
  while (*p && p < buf + len) {
    char *e = p;
    while (*e && *e != ' ')
      e++;
    *e = 0;
    args.push_back(p);
    //cout << "arg " << p << std::endl;
    p = e+1;
  }
}

void env_to_deq(std::deque<const char*>& args)
{
  char *p = getenv("CEPH_ARGS");
  if (!p) return;

  static char buf[1000];
  int len = MIN(strlen(p), sizeof(buf)-1);  // bleh.
  memcpy(buf, p, len);
  buf[len] = 0;

  p = buf;
  while (*p && p < buf + len) {
    char *e = p;
    while (*e && *e != ' ')
      e++;
    *e = 0;
    args.push_back(p);
    p = e+1;
  }
}

void argv_to_vec(int argc, const char **argv,
                 std::vector<const char*>& args)
{
  for (int i=1; i<argc; i++)
    args.push_back(argv[i]);
}

void argv_to_deq(int argc, const char **argv,
                 std::deque<const char*>& args)
{
  for (int i=1; i<argc; i++)
    args.push_back(argv[i]);
}

void vec_to_argv(std::vector<const char*>& args,
                 int& argc, const char **&argv)
{
  const char *myname = "asdf";
  if (argc && argv)
    myname = argv[0];
  argv = (const char**)malloc(sizeof(char*) * argc);
  argc = 1;
  argv[0] = myname;

  for (unsigned i=0; i<args.size(); i++)
    argv[argc++] = args[i];
}

bool parse_ip_port_vec(const char *s, vector<entity_addr_t>& vec)
{
  const char *p = s;
  const char *end = p + strlen(p);
  while (p < end) {
    entity_addr_t a;
    //cout << " parse at '" << p << "'" << std::endl;
    if (!a.parse(p, &p)) {
      //dout(0) << " failed to parse address '" << p << "'" << dendl;
      return false;
    }
    //cout << " got " << a << ", rest is '" << p << "'" << std::endl;
    vec.push_back(a);
    while (*p == ',' || *p == ' ')
      p++;
  }
  return true;
}

void parse_config_option_string(std::string& s)
{
  char b[s.length()+1];
  strcpy(b, s.c_str());
  std::vector<const char*> nargs;
  char *p = b;
  while (*p) {
    nargs.push_back(p);
    while (*p && *p != ' ') p++;
    if (!*p)
      break;
    *p++ = 0;
    while (*p && *p == ' ') p++;
  }
  g_conf.parse_argv(nargs);
}

// The defaults for CephInitParameters
CephInitParameters::CephInitParameters(uint32_t module_type, const char *conf_file_)
  : conf_file(conf_file_)
{
  const char *c = getenv("CEPH_CONF");
  if (c)
    conf_file = c;
  name.set(module_type, "admin");
}

std::list<std::string> CephInitParameters::
get_conf_files() const
{
  std::list<std::string> ret;
  get_str_list(conf_file, ret);
  return ret;
}

static void dashes_to_underscores(const char *input, char *output)
{
  char c = 0;
  char *o = output;
  const char *i = input;
  // first two characters are copied as-is
  *o = *i++;
  if (*o++ == '\0')
    return;
  *o = *i++;
  if (*o++ == '\0')
    return;
  for (; ((c = *i)); ++i) {
     if (c == '-')
       *o++ = '_';
     else
       *o++ = c;
  }
  *o++ = '\0';
}

bool ceph_argparse_flag(std::vector<const char*> &args,
	std::vector<const char*>::iterator &i, ...)
{
  const char *first = *i;
  char tmp[strlen(first)+1];
  dashes_to_underscores(first, tmp);
  first = tmp;
  const char *a;
  va_list ap;

  va_start(ap, i);
  while (1) {
    a = va_arg(ap, char*);
    if (a == NULL)
      return false;
    if (strcmp(a, first) == 0) {
      i = args.erase(i);
      return true;
    }
  }
}

bool ceph_argparse_witharg(std::vector<const char*> &args,
	std::vector<const char*>::iterator &i, std::string *ret, ...)
{
  const char *first = *i;
  char tmp[strlen(first)+1];
  dashes_to_underscores(first, tmp);
  first = tmp;
  const char *a;
  va_list ap;
  int strlen_a;

  // does this argument match any of the possibilities?
  va_start(ap, ret);
  while (1) {
    a = va_arg(ap, char*);
    if (a == NULL)
      return false;
    strlen_a = strlen(a);
    if (strncmp(a, first, strlen(a)) == 0) {
      if (first[strlen_a] == '=') {
	*ret = first + strlen_a + 1;
	i = args.erase(i);
	return true;
      }
      else if (first[strlen_a] == '\0') {
	// find second part (or not)
	if (i+1 == args.end()) {
	  std::cerr << "Option " << *i << " requires an argument." << std::endl;
	  _exit(1);
	}
	i = args.erase(i);
	*ret = *i;
	i = args.erase(i);
	return true;
      }
    }
  }
}

CephInitParameters ceph_argparse_early_args
	  (std::vector<const char*>& args, uint32_t module_type, int flags)
{
  const char *conf = (flags & CINIT_FLAG_NO_DEFAULT_CONFIG_FILE) ?
    "" : CEPH_CONF_FILE_DEFAULT;
  CephInitParameters iparams(module_type, conf);
  std::string val;
  for (std::vector<const char*>::iterator i = args.begin(); i != args.end(); ) {
    if (strcmp(*i, "--") == 0)
      break;
    else if (ceph_argparse_flag(args, i, "--version", "-v", (char*)NULL)) {
      cout << pretty_version_to_str() << std::endl;
      _exit(0);
    }
    else if (ceph_argparse_witharg(args, i, &val, "--conf", "-c", (char*)NULL)) {
      iparams.conf_file = val;
    }
    else if ((module_type != CEPH_ENTITY_TYPE_CLIENT) &&
	     (ceph_argparse_witharg(args, i, &val, "-i", (char*)NULL))) {
      iparams.name.set_id(val);
    }
    else if (ceph_argparse_witharg(args, i, &val, "--id", (char*)NULL)) {
      iparams.name.set_id(val);
    }
    else if (ceph_argparse_witharg(args, i, &val, "--name", "-n", (char*)NULL)) {
      if (!iparams.name.from_str(val)) {
	std::cerr << "You must pass a string of the form TYPE.ID to "
	  "the --name option." << std::endl;
	_exit(1);
      }
    }
    else {
      // ignore
      ++i;
    }
  }
  return iparams;
}

static void generic_usage(bool is_server)
{
  cout << "\
--conf/-c        Read configuration from the given configuration file\n\
-D               Run in the foreground.\n\
-f               Run in foreground. Show all log messages on stderr.\n\
--id             set ID\n\
--name           set ID.TYPE\n\
--version        show version and quit\n\
" << std::endl;

  if (is_server) {
    cout << "   --debug_ms N\n";
    cout << "        set message debug level (e.g. 1)\n";
  }
}

void generic_server_usage()
{
  generic_usage(true);
  exit(1);
}
void generic_client_usage()
{
  generic_usage(false);
  exit(1);
}
<|endoftext|>


<commit_before>#include "util.h"

#include <stdint.h>
#include <vector>

#include "chainparams.h"
#include "key.h"
#include "main.h"
#include "pubkey.h"
#include "txdb.h"
#include "txmempool.h"
#include "zerocoin_v3.h"

#include "test/fixtures.h"
#include "test/testutil.h"

#include "wallet/db.h"
#include "wallet/wallet.h"

#include <boost/filesystem.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>

BOOST_FIXTURE_TEST_SUITE(sigma_transition, ZerocoinTestingSetup200)

/*
* 1. Create one denomination pair and check it can't be spend till 6 conf of mint
* 2. Make one more mint of denom pair and check it can't be spend till 6 conf
* 3. Create two spend transactions using same mint
* 4. Double spend with previous spend in last block
*/
BOOST_AUTO_TEST_CASE(sigma_transition_test)
{
    sigma::CSigmaState *sigmaState = sigma::CSigmaState::GetState();
    string denomination;
    vector<uint256> vtxid;

    denomination = "1";
    string stringError;
    // Make sure that transactions get to mempool
    pwalletMain->SetBroadcastTransactions(true);

    // Try to create a sigma mint. It must not be added to the mempool, because
    // Sigma is enabled at block "nMintV3SigmaStartBlock=400 for regtest".
    vector<pair<std::string, int>> denominationPairs;
    std::pair<std::string, int> denominationPair(denomination, 1);
    denominationPairs.push_back(denominationPair);

    // Create 400-200+1 = 201 new empty blocks. // consensus.nMintV3SigmaStartBlock = 400
    CreateAndProcessEmptyBlocks(201, scriptPubKey);

    // Create a zerocoin mint, it must still pass.
    BOOST_CHECK_MESSAGE(pwalletMain->CreateZerocoinMintModel(
        stringError, denominationPairs, ZEROCOIN), stringError + " - Create Mint failed");
    BOOST_CHECK_MESSAGE(mempool.size() == 1, "Mint was not added to mempool");

    // Sigma mints must also pass.
    BOOST_CHECK_MESSAGE(pwalletMain->CreateZerocoinMintModel(
        stringError, denominationPairs, SIGMA), stringError + " - Create Mint failed");
    BOOST_CHECK_MESSAGE(mempool.size() == 2, "Mint was not added to mempool");

    // Both transactions must be able to be added to the next block.
    int previousHeight = chainActive.Height();
    CBlock b = CreateAndProcessBlock({}, scriptPubKey);
    BOOST_CHECK_MESSAGE(previousHeight + 1 == chainActive.Height(), "Block not added to chain");
    BOOST_CHECK_MESSAGE(mempool.size() == 0, "Expected empty mempool.");

    // Create some zerocoin mints.
    for (int i = 0; i < 5; ++i) {
        BOOST_CHECK_MESSAGE(pwalletMain->CreateZerocoinMintModel(
            stringError, denominationPairs, ZEROCOIN), stringError + " - Create Mint failed");
    }
    BOOST_CHECK_MESSAGE(mempool.size() == 5, "Mint was not added to mempool");

    vtxid.clear();
    mempool.queryHashes(vtxid);
    vtxid.resize(1);

    // Process one more block. After this one, old zerocoin mints must not be allowed to mempool
    // any more, because for regtest consensus.nMintV2MempoolGracefulPeriod = 2.
    previousHeight = chainActive.Height();

    b = CreateAndProcessBlock(vtxid, scriptPubKey);
    BOOST_CHECK_MESSAGE(previousHeight + 1 == chainActive.Height(), "Block not added to chain");

    // Now this new mint must not be added to the mempool any more,
    // because consensus.nMintV2MempoolGracefulPeriod = 2;
    BOOST_CHECK_MESSAGE(pwalletMain->CreateZerocoinMintModel(
        stringError, denominationPairs, ZEROCOIN), stringError + " - Create Mint failed");

    // Check that mempool size did not change, so this mint was not added.
    BOOST_CHECK_MESSAGE(mempool.size() == 4, "Mint was added to mempool, but not expected to.");

    // Create 1 more block. All the mints must pass.
    previousHeight = chainActive.Height();
    b = CreateAndProcessBlock({}, scriptPubKey);
    BOOST_CHECK_MESSAGE(previousHeight + 1 == chainActive.Height(), "Block not added to chain");

    // Check that mempool got empty.
    BOOST_CHECK_MESSAGE(mempool.size() == 0, "Mempool did not get empty.");

    // Create 5 more empty blocks, so mints can be spent.
    CreateAndProcessEmptyBlocks(5, scriptPubKey);

    // Add an old spend to mempool.
    BOOST_CHECK_MESSAGE(
        pwalletMain->CreateZerocoinSpendModel(stringError, "", denomination.c_str(), false, true),
        "Spend not added to the mempool.");

    // Create a block containing old spend and try to add it to the chain.
    CBlock block = CreateBlock({}, scriptPubKey);

    // Create 5 more empty blocks, such that nZerocoinV2SpendStopBlock = 410 passes.
    CreateAndProcessEmptyBlocks(5, scriptPubKey);

    // Create an old spend, it must not be added to the mempool,
    // since nZerocoinV2SpendStopBlock = 410 have passed.
    BOOST_CHECK_MESSAGE(
        pwalletMain->CreateZerocoinSpendModel(stringError, "", denomination.c_str(), false, true),
        "Spend not added to the mempool.");
    BOOST_CHECK_MESSAGE(mempool.size() == 0, "Spend added to the mempool, but must not be added.");

    // Create 10 more empty blocks, such that nZerocoinV2SpendStopBlockInBlocks = 420 passes.
    CreateAndProcessEmptyBlocks(10, scriptPubKey);

    previousHeight = chainActive.Height();
    ProcessBlock(block);
    BOOST_CHECK_MESSAGE(previousHeight == chainActive.Height(),
        "Block added to chain, but must have been rejected.");

    vtxid.clear();
    mempool.clear();
    sigmaState->Reset();
}

BOOST_AUTO_TEST_SUITE_END()<commit_msg>Fix transition test<commit_after>#include "util.h"

#include <stdint.h>
#include <vector>

#include "chainparams.h"
#include "key.h"
#include "main.h"
#include "pubkey.h"
#include "txdb.h"
#include "txmempool.h"
#include "zerocoin_v3.h"

#include "test/fixtures.h"
#include "test/testutil.h"

#include "wallet/db.h"
#include "wallet/wallet.h"

#include <boost/filesystem.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>

BOOST_FIXTURE_TEST_SUITE(sigma_transition, ZerocoinTestingSetup200)

/*
* 1. Create one denomination pair and check it can't be spend till 6 conf of mint
* 2. Make one more mint of denom pair and check it can't be spend till 6 conf
* 3. Create two spend transactions using same mint
* 4. Double spend with previous spend in last block
*/
BOOST_AUTO_TEST_CASE(sigma_transition_test)
{
    sigma::CSigmaState *sigmaState = sigma::CSigmaState::GetState();
    string denomination;
    vector<uint256> vtxid;

    denomination = "1";
    string stringError;
    // Make sure that transactions get to mempool
    pwalletMain->SetBroadcastTransactions(true);

    // Try to create a sigma mint. It must not be added to the mempool, because
    // Sigma is enabled at block "nMintV3SigmaStartBlock=400 for regtest".
    vector<pair<std::string, int>> denominationPairs;
    std::pair<std::string, int> denominationPair(denomination, 2);
    denominationPairs.push_back(denominationPair);

    // Create 400-200+1 = 201 new empty blocks. // consensus.nMintV3SigmaStartBlock = 400
    CreateAndProcessEmptyBlocks(201, scriptPubKey);

    // Create a zerocoin mint, it must not pass.
    BOOST_CHECK_MESSAGE(!pwalletMain->CreateZerocoinMintModel(
        stringError, denominationPairs, ZEROCOIN), "Zerocoin mint creation is success");
    BOOST_CHECK_MESSAGE(mempool.size() == 0, "Mint was added to mempool");

    // Sigma mints must pass.
    BOOST_CHECK_MESSAGE(pwalletMain->CreateZerocoinMintModel(
        stringError, denominationPairs, SIGMA), stringError + " - Create Mint failed");
    BOOST_CHECK_MESSAGE(mempool.size() == 1, "Mint was not added to mempool");

    // a sigma mint transaction must be able to be added to the next block.
    int previousHeight = chainActive.Height();
    CBlock b = CreateAndProcessBlock({}, scriptPubKey);
    BOOST_CHECK_MESSAGE(previousHeight + 1 == chainActive.Height(), "Block not added to chain");
    BOOST_CHECK_MESSAGE(mempool.size() == 0, "Expected empty mempool.");

    // Create 5 more empty blocks, so mints can be spent.
    CreateAndProcessEmptyBlocks(5, scriptPubKey);

    // Try to spend zerocoin should fail.
    BOOST_CHECK_MESSAGE(
        !pwalletMain->CreateZerocoinSpendModel(stringError, "", denomination.c_str(), false, true),
        "Create zerocoin spend is success.");
    BOOST_CHECK_MESSAGE(mempool.size() == 0, "Zerocoin spend was added to mempool");

    // Try to spend zerocoin should be success.
    CWalletTx wtx;
    std::string thirdPartyAddress = "TXYb6pEWBDcxQvTxbFQ9sEV1c3rWUPGW3v";
    vector<string> denominationsForTx = {denomination};
    BOOST_CHECK_MESSAGE(
        pwalletMain->CreateZerocoinSpendModel(wtx, stringError, thirdPartyAddress, denominationsForTx),
        stringError + " - Spend failed");
    BOOST_CHECK_MESSAGE(mempool.size() == 1, "Sigma spend was not added to mempool");

    previousHeight = chainActive.Height();
    CreateAndProcessBlock({}, scriptPubKey);
    BOOST_CHECK_MESSAGE(previousHeight + 1 == chainActive.Height(), "Block not added to chain");
    BOOST_CHECK_MESSAGE(mempool.size() == 0, "Expected empty mempool.");

    vtxid.clear();
    mempool.clear();
    sigmaState->Reset();
}

BOOST_AUTO_TEST_SUITE_END()<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Monteverdi2
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi2 is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "mvdDatabaseBrowserWidget.h"
#include "ui_mvdDatabaseBrowserWidget.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)
#include <cassert>

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "Gui/mvdDatabaseTreeWidget.h"
#include "Gui/mvdTreeWidgetItem.h"

#define ENABLE_DISPLAY_ID 1

namespace mvd
{

/*
  TRANSLATOR mvd::DatabaseBrowserWidget

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
DatabaseBrowserWidget
::DatabaseBrowserWidget( QWidget* parent, Qt::WindowFlags flags  ):
  QWidget( parent, flags ),
  m_UI( new mvd::Ui::DatabaseBrowserWidget() ),
  m_StartDragPosition(),
  m_SearchText()
{
  m_UI->setupUi( this );

  SetupUI();

  /*
  // Devember 12th, 2013 - Trainee example.
  QPushButton* button=new QPushButton ("Click me", this);
  layout()->addWidget(button);
  */

  //
  // Forward signals.

  QObject::connect(
    m_UI->databaseTreeWidget,
    SIGNAL( ItemMoved( QTreeWidgetItem*, QTreeWidgetItem* ) ),
    // to:
    this,
    SIGNAL( ItemMoved( QTreeWidgetItem*, QTreeWidgetItem* ) )
  );

  QObject::connect(
    m_UI->databaseTreeWidget,
    SIGNAL( AddItemRequested( QTreeWidgetItem* ) ),
    // to:
    this,
    SIGNAL( AddItemRequested( QTreeWidgetItem* ) )
  );

  QObject::connect(
    m_UI->databaseTreeWidget,
    SIGNAL( DeleteItemRequested( QTreeWidgetItem* ) ),
    // to:
    this,
    SIGNAL( DeleteItemRequested( QTreeWidgetItem* ) )
  );

  QObject::connect(
    m_UI->databaseTreeWidget,
    SIGNAL( ItemTextChanged( QTreeWidgetItem*, int ) ),
    // to:
    this,
    SIGNAL( ItemTextChanged( QTreeWidgetItem*, int ) )
  );
}

/*******************************************************************************/
DatabaseBrowserWidget
::~DatabaseBrowserWidget()
{
  delete m_UI;
  m_UI = NULL;
}

/*****************************************************************************/
const QTreeWidgetItem*
DatabaseBrowserWidget
::GetRootItem() const
{
  return m_UI->databaseTreeWidget->invisibleRootItem();
}

/*****************************************************************************/
QTreeWidgetItem*
DatabaseBrowserWidget
::GetRootItem()
{
  return m_UI->databaseTreeWidget->invisibleRootItem();
}

/*****************************************************************************/
DatabaseBrowserWidget::QTreeWidgetItemList
DatabaseBrowserWidget
::GetItems() const
{
  return
    m_UI->databaseTreeWidget->findItems(
      "*",
      Qt::MatchWildcard | Qt::MatchRecursive,
      0
    );
}

/*******************************************************************************/
void
DatabaseBrowserWidgetTest
::Clear()
{
  m_UI->databaseTreeWidget->clear();
}

/*******************************************************************************/
QTreeWidgetItem*
DatabaseBrowserWidget
::InsertLeafItem( QTreeWidgetItem* parent,
                  const QString& text,
                  const QVariant& id,
                  const QStringList& columns )
{
  return
    InsertItem(
      parent,
      TreeWidgetItem::ITEM_TYPE_LEAF,
      text,
      id,
      columns
    );
}

/*******************************************************************************/
QTreeWidgetItem*
DatabaseBrowserWidget
::InsertItem( QTreeWidgetItem* parent,
              TreeWidgetItem::ItemType type,
              const QString& text,
              const QVariant& id,
              const QStringList& columns )
{
  TreeWidgetItem* item =
    new TreeWidgetItem(
      parent,
      text,
      id,
      columns,
      type
    );

  return item;
}

/*******************************************************************************/
QTreeWidgetItem*
DatabaseBrowserWidget
::InsertNodeItem( QTreeWidgetItem* parent,
                  const QString& text,
                  const QVariant& id,
                  const QStringList& columns )
{
  return
    InsertItem(
      parent,
      TreeWidgetItem::ITEM_TYPE_NODE,
      text,
      id,
      columns
    );
}

/*****************************************************************************/
void
DatabaseBrowserWidget
::SetupUI()
{
  //
  // Header columns.
  m_UI->databaseTreeWidget->headerItem()->setText( 1, "Id" );
  m_UI->databaseTreeWidget->headerItem()->setText( 2, "Info" );

// Conditionaly display some usefull columns.
// #if (!defined( _DEBUG ) && FORCE_DISABLE) || FORCE_ENABLE
#if (!defined( _DEBUG ) && 1) || 0
  m_UI->databaseTreeWidget->setColumnHidden( 1, true );
  m_UI->databaseTreeWidget->setColumnHidden( 2, true );
#endif

  // set placeholder text
#if (QT_VERSION >= 0x407000)
  m_UI->m_SearchLine->setPlaceholderText( tr( "Search Dataset..." ) );
#endif
}

/*******************************************************************************/
/*
DatabaseTreeWidget*
DatabaseBrowserWidget
::GetDatabaseTreeWidget()
{
  return m_UI->databaseTreeWidget;
}
*/

/*****************************************************************************/
void
DatabaseBrowserWidget
::SetCurrentDataset( const QString& hash )
{
  // qDebug() << this << "::SetCurrentDataset(" << hash << ")";

#if QT_VERSION < QT_VERSION_CHECK( 4, 8, 1 )
  // Workaround for MANTIS-934 (crash/memory corruption after having
  // imported second image).
#else
  assert( m_UI!=NULL );
  assert( m_UI->databaseTreeWidget!=NULL );

  QList< QTreeWidgetItem* > items(
    m_UI->databaseTreeWidget->findItems(
      hash,
      Qt::MatchExactly | Qt::MatchRecursive,
      TreeWidgetItem::COLUMN_INDEX_HASH
    )
  );

  assert( items.isEmpty() || items.size() == 1 );

  // qDebug()
  //   << ( items.isEmpty() ? "NONE" : items.first()->text( 0 ) )
  //   << m_UI->databaseTreeWidget->selectionModel()->selectedIndexes().size();

  m_UI->databaseTreeWidget->setCurrentItem(
    items.isEmpty()
    ? NULL
    : items.first(),
    TreeWidgetItem::COLUMN_INDEX_TEXT,
    QItemSelectionModel::Clear |
    QItemSelectionModel::Select |
    QItemSelectionModel::Current
  );
#endif
}

/*****************************************************************************/
void
DatabaseBrowserWidget
::InstallTreeEventFilter( QObject* eventFilter )
{
  m_UI->databaseTreeWidget->installEventFilter( eventFilter );
}

/*******************************************************************************/
/* SLOTS                                                                       */
/*******************************************************************************/
void
DatabaseBrowserWidget
::on_databaseTreeWidget_currentItemChanged( QTreeWidgetItem* current,
					    QTreeWidgetItem* previous )
{
  //
  // Current

  // TODO: Should be DatabaseModel::DatasetId but widgets should not depend on models!!!
  QString currentHash;

  TreeWidgetItem* currentItem = dynamic_cast< TreeWidgetItem* >( current );

  if( currentItem!=NULL && currentItem->parent()!=NULL )
    // if current is root and not NULL get the Id of the corresponding
    // Dataset.
    currentHash = currentItem->GetHash();

  //
  // Previous

  // TODO: Should be DatabaseModel::DatasetId but widgets should not depend on models!!!
  QString previousHash;

  TreeWidgetItem* previousItem = dynamic_cast< TreeWidgetItem* >( previous );

  if( previousItem!=NULL )
    previousHash = previousItem->GetHash();

  //
  // Emit event.
  emit CurrentDatasetChanged( currentHash, previousHash );
}

/*******************************************************************************/
void
DatabaseBrowserWidget
::on_m_SearchLine_textChanged( const QString& search )
{
  // qDebug() << this << "on_m_SearchLine_textChanged(" << search << ")";

  //
  // get the search text
  m_SearchText = search;

  QTreeWidgetItemList items( GetItems() );

  // qDebug() << items;

  for( QTreeWidgetItemList::iterator it( items.begin() );
       it!=items.end();
       ++it )
    {
    QTreeWidgetItem* qtwi = *it;
    assert( qtwi!=NULL );

    assert( qtwi==dynamic_cast< TreeWidgetItem* >( qtwi ) );
    TreeWidgetItem* item = dynamic_cast< TreeWidgetItem* >( qtwi );

    if( item==NULL )
      {
      // TODO: Implement general case when needed.
      }
    else
      {
      item->setHidden(
        item->GetType()==TreeWidgetItem::ITEM_TYPE_LEAF &&
        !item->GetText().contains( search, Qt::CaseInsensitive )
      );
      }

    // qDebug()
    //   << item->text( 0 ) << ":" << ( item->isHidden() ? "HIDDEN" : "VISIBLE" );
    }
}

} // end namespace 'mvd'
<commit_msg>COMP: Fixed error.<commit_after>/*=========================================================================

  Program:   Monteverdi2
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi2 is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "mvdDatabaseBrowserWidget.h"
#include "ui_mvdDatabaseBrowserWidget.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)
#include <cassert>

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "Gui/mvdDatabaseTreeWidget.h"
#include "Gui/mvdTreeWidgetItem.h"

#define ENABLE_DISPLAY_ID 1

namespace mvd
{

/*
  TRANSLATOR mvd::DatabaseBrowserWidget

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
DatabaseBrowserWidget
::DatabaseBrowserWidget( QWidget* parent, Qt::WindowFlags flags  ):
  QWidget( parent, flags ),
  m_UI( new mvd::Ui::DatabaseBrowserWidget() ),
  m_StartDragPosition(),
  m_SearchText()
{
  m_UI->setupUi( this );

  SetupUI();

  /*
  // Devember 12th, 2013 - Trainee example.
  QPushButton* button=new QPushButton ("Click me", this);
  layout()->addWidget(button);
  */

  //
  // Forward signals.

  QObject::connect(
    m_UI->databaseTreeWidget,
    SIGNAL( ItemMoved( QTreeWidgetItem*, QTreeWidgetItem* ) ),
    // to:
    this,
    SIGNAL( ItemMoved( QTreeWidgetItem*, QTreeWidgetItem* ) )
  );

  QObject::connect(
    m_UI->databaseTreeWidget,
    SIGNAL( AddItemRequested( QTreeWidgetItem* ) ),
    // to:
    this,
    SIGNAL( AddItemRequested( QTreeWidgetItem* ) )
  );

  QObject::connect(
    m_UI->databaseTreeWidget,
    SIGNAL( DeleteItemRequested( QTreeWidgetItem* ) ),
    // to:
    this,
    SIGNAL( DeleteItemRequested( QTreeWidgetItem* ) )
  );

  QObject::connect(
    m_UI->databaseTreeWidget,
    SIGNAL( ItemTextChanged( QTreeWidgetItem*, int ) ),
    // to:
    this,
    SIGNAL( ItemTextChanged( QTreeWidgetItem*, int ) )
  );
}

/*******************************************************************************/
DatabaseBrowserWidget
::~DatabaseBrowserWidget()
{
  delete m_UI;
  m_UI = NULL;
}

/*****************************************************************************/
const QTreeWidgetItem*
DatabaseBrowserWidget
::GetRootItem() const
{
  return m_UI->databaseTreeWidget->invisibleRootItem();
}

/*****************************************************************************/
QTreeWidgetItem*
DatabaseBrowserWidget
::GetRootItem()
{
  return m_UI->databaseTreeWidget->invisibleRootItem();
}

/*****************************************************************************/
DatabaseBrowserWidget::QTreeWidgetItemList
DatabaseBrowserWidget
::GetItems() const
{
  return
    m_UI->databaseTreeWidget->findItems(
      "*",
      Qt::MatchWildcard | Qt::MatchRecursive,
      0
    );
}

/*******************************************************************************/
void
DatabaseBrowserWidget
::Clear()
{
  m_UI->databaseTreeWidget->clear();
}

/*******************************************************************************/
QTreeWidgetItem*
DatabaseBrowserWidget
::InsertLeafItem( QTreeWidgetItem* parent,
                  const QString& text,
                  const QVariant& id,
                  const QStringList& columns )
{
  return
    InsertItem(
      parent,
      TreeWidgetItem::ITEM_TYPE_LEAF,
      text,
      id,
      columns
    );
}

/*******************************************************************************/
QTreeWidgetItem*
DatabaseBrowserWidget
::InsertItem( QTreeWidgetItem* parent,
              TreeWidgetItem::ItemType type,
              const QString& text,
              const QVariant& id,
              const QStringList& columns )
{
  TreeWidgetItem* item =
    new TreeWidgetItem(
      parent,
      text,
      id,
      columns,
      type
    );

  return item;
}

/*******************************************************************************/
QTreeWidgetItem*
DatabaseBrowserWidget
::InsertNodeItem( QTreeWidgetItem* parent,
                  const QString& text,
                  const QVariant& id,
                  const QStringList& columns )
{
  return
    InsertItem(
      parent,
      TreeWidgetItem::ITEM_TYPE_NODE,
      text,
      id,
      columns
    );
}

/*****************************************************************************/
void
DatabaseBrowserWidget
::SetupUI()
{
  //
  // Header columns.
  m_UI->databaseTreeWidget->headerItem()->setText( 1, "Id" );
  m_UI->databaseTreeWidget->headerItem()->setText( 2, "Info" );

// Conditionaly display some usefull columns.
// #if (!defined( _DEBUG ) && FORCE_DISABLE) || FORCE_ENABLE
#if (!defined( _DEBUG ) && 1) || 0
  m_UI->databaseTreeWidget->setColumnHidden( 1, true );
  m_UI->databaseTreeWidget->setColumnHidden( 2, true );
#endif

  // set placeholder text
#if (QT_VERSION >= 0x407000)
  m_UI->m_SearchLine->setPlaceholderText( tr( "Search Dataset..." ) );
#endif
}

/*******************************************************************************/
/*
DatabaseTreeWidget*
DatabaseBrowserWidget
::GetDatabaseTreeWidget()
{
  return m_UI->databaseTreeWidget;
}
*/

/*****************************************************************************/
void
DatabaseBrowserWidget
::SetCurrentDataset( const QString& hash )
{
  // qDebug() << this << "::SetCurrentDataset(" << hash << ")";

#if QT_VERSION < QT_VERSION_CHECK( 4, 8, 1 )
  // Workaround for MANTIS-934 (crash/memory corruption after having
  // imported second image).
#else
  assert( m_UI!=NULL );
  assert( m_UI->databaseTreeWidget!=NULL );

  QList< QTreeWidgetItem* > items(
    m_UI->databaseTreeWidget->findItems(
      hash,
      Qt::MatchExactly | Qt::MatchRecursive,
      TreeWidgetItem::COLUMN_INDEX_HASH
    )
  );

  assert( items.isEmpty() || items.size() == 1 );

  // qDebug()
  //   << ( items.isEmpty() ? "NONE" : items.first()->text( 0 ) )
  //   << m_UI->databaseTreeWidget->selectionModel()->selectedIndexes().size();

  m_UI->databaseTreeWidget->setCurrentItem(
    items.isEmpty()
    ? NULL
    : items.first(),
    TreeWidgetItem::COLUMN_INDEX_TEXT,
    QItemSelectionModel::Clear |
    QItemSelectionModel::Select |
    QItemSelectionModel::Current
  );
#endif
}

/*****************************************************************************/
void
DatabaseBrowserWidget
::InstallTreeEventFilter( QObject* eventFilter )
{
  m_UI->databaseTreeWidget->installEventFilter( eventFilter );
}

/*******************************************************************************/
/* SLOTS                                                                       */
/*******************************************************************************/
void
DatabaseBrowserWidget
::on_databaseTreeWidget_currentItemChanged( QTreeWidgetItem* current,
					    QTreeWidgetItem* previous )
{
  //
  // Current

  // TODO: Should be DatabaseModel::DatasetId but widgets should not depend on models!!!
  QString currentHash;

  TreeWidgetItem* currentItem = dynamic_cast< TreeWidgetItem* >( current );

  if( currentItem!=NULL && currentItem->parent()!=NULL )
    // if current is root and not NULL get the Id of the corresponding
    // Dataset.
    currentHash = currentItem->GetHash();

  //
  // Previous

  // TODO: Should be DatabaseModel::DatasetId but widgets should not depend on models!!!
  QString previousHash;

  TreeWidgetItem* previousItem = dynamic_cast< TreeWidgetItem* >( previous );

  if( previousItem!=NULL )
    previousHash = previousItem->GetHash();

  //
  // Emit event.
  emit CurrentDatasetChanged( currentHash, previousHash );
}

/*******************************************************************************/
void
DatabaseBrowserWidget
::on_m_SearchLine_textChanged( const QString& search )
{
  // qDebug() << this << "on_m_SearchLine_textChanged(" << search << ")";

  //
  // get the search text
  m_SearchText = search;

  QTreeWidgetItemList items( GetItems() );

  // qDebug() << items;

  for( QTreeWidgetItemList::iterator it( items.begin() );
       it!=items.end();
       ++it )
    {
    QTreeWidgetItem* qtwi = *it;
    assert( qtwi!=NULL );

    assert( qtwi==dynamic_cast< TreeWidgetItem* >( qtwi ) );
    TreeWidgetItem* item = dynamic_cast< TreeWidgetItem* >( qtwi );

    if( item==NULL )
      {
      // TODO: Implement general case when needed.
      }
    else
      {
      item->setHidden(
        item->GetType()==TreeWidgetItem::ITEM_TYPE_LEAF &&
        !item->GetText().contains( search, Qt::CaseInsensitive )
      );
      }

    // qDebug()
    //   << item->text( 0 ) << ":" << ( item->isHidden() ? "HIDDEN" : "VISIBLE" );
    }
}

} // end namespace 'mvd'
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gtest/gtest.h>

#include <set>
#include <string>
#include <vector>

#include <mesos/mesos.hpp>

#include "common/protobuf_utils.hpp"

#include "tests/mesos.hpp"

using std::set;
using std::string;
using std::vector;

namespace mesos {
namespace internal {
namespace tests {

// This tests that helper function `getRoles` can correctly
// get roles from multi-role FrameworkInfo and role from
// single-role FrameworkInfo.
TEST(ProtobufUtilTest, GetRoles)
{
  // Get roles from a multi-role framework.
  {
    FrameworkInfo frameworkInfo;
    frameworkInfo.add_capabilities()->set_type(
        FrameworkInfo::Capability::MULTI_ROLE);
    frameworkInfo.add_roles("bar");
    frameworkInfo.add_roles("qux");

    set<string> roles = protobuf::framework::getRoles(frameworkInfo);

    EXPECT_EQ(roles, set<string>({"qux", "bar"}));
  }

  // Get role from a single-role framework.
  {
    FrameworkInfo frameworkInfo;
    frameworkInfo.set_role("foo");

    set<string> roles = protobuf::framework::getRoles(frameworkInfo);

    EXPECT_EQ(roles, set<string>({"foo"}));
  }
}

// Tests that offer operations can be injected to include
// the appropriate allocation info, if not already set.
TEST(ProtobufUtilTest, InjectAllocationInfoInOfferOperation)
{
  Resources resources = Resources::parse("cpus:1").get();

  Resources allocatedResources = resources;
  allocatedResources.allocate("role");

  Resource::AllocationInfo allocationInfo;
  allocationInfo.set_role("role");

  // Test the LAUNCH case. This should be constructing a valid
  // task and executor, but for now this just sets the resources
  // in order to verify the allocation info injection.
  ExecutorInfo executorInfo;
  executorInfo.mutable_resources()->CopyFrom(resources);

  TaskInfo taskInfo;
  taskInfo.mutable_resources()->CopyFrom(resources);
  taskInfo.mutable_executor()->CopyFrom(executorInfo);

  Offer::Operation launch = LAUNCH({taskInfo});
  protobuf::injectAllocationInfo(&launch, allocationInfo);

  ASSERT_EQ(1, launch.launch().task_infos_size());

  EXPECT_EQ(allocatedResources,
            launch.launch().task_infos(0).resources());

  EXPECT_EQ(allocatedResources,
            launch.launch().task_infos(0).executor().resources());

  // Test the LAUNCH_GROUP case. This should be constructing a valid
  // task and executor, but for now this just sets the resources in
  // order to verify the allocation info injection.
  TaskGroupInfo taskGroupInfo;
  taskGroupInfo.add_tasks()->CopyFrom(taskInfo);

  Offer::Operation launchGroup = LAUNCH_GROUP(executorInfo, taskGroupInfo);
  protobuf::injectAllocationInfo(&launchGroup, allocationInfo);

  ASSERT_EQ(1, launchGroup.launch_group().task_group().tasks_size());

  EXPECT_EQ(allocatedResources,
            launchGroup.launch_group().task_group().tasks(0).resources());

  EXPECT_EQ(allocatedResources,
            launchGroup.launch_group().task_group().tasks(0).executor()
              .resources());

  // Test the RESERVE case. This should be constructing a valid
  // reservation, but for now this just sets the resources in
  // order to verify the allocation info injection.
  Offer::Operation reserve = RESERVE(resources);
  protobuf::injectAllocationInfo(&reserve, allocationInfo);

  EXPECT_EQ(allocatedResources, reserve.reserve().resources());

  // Test the UNRESERVE case. This should be constructing a valid
  // reservation, but for now this just sets the resources in
  // order to verify the allocation info injection.
  Offer::Operation unreserve = UNRESERVE(resources);
  protobuf::injectAllocationInfo(&unreserve, allocationInfo);

  EXPECT_EQ(allocatedResources, unreserve.unreserve().resources());

  // Test the CREATE case. This should be constructing a valid
  // volume, but for now this just sets the resources in order
  // to verify the allocation info injection.
  Offer::Operation create = CREATE(resources);
  protobuf::injectAllocationInfo(&create, allocationInfo);

  EXPECT_EQ(allocatedResources, create.create().volumes());

  // Test the DESTROY case. This should be constructing a valid
  // volume, but for now this just sets the resources in order
  // to verify the allocation info injection.
  Offer::Operation destroy = DESTROY(resources);
  protobuf::injectAllocationInfo(&destroy, allocationInfo);

  EXPECT_EQ(allocatedResources, destroy.destroy().volumes());
}

// This tests that Capabilities are correctly constructed
// from given FrameworkInfo Capabilities.
TEST(ProtobufUtilTest, FrameworkCapabilities)
{
  auto toTypeSet = [](
      const protobuf::framework::Capabilities& capabilities) {
    set<FrameworkInfo::Capability::Type> result;

    if (capabilities.revocableResources) {
      result.insert(FrameworkInfo::Capability::REVOCABLE_RESOURCES);
    }
    if (capabilities.taskKillingState) {
      result.insert(FrameworkInfo::Capability::TASK_KILLING_STATE);
    }
    if (capabilities.gpuResources) {
      result.insert(FrameworkInfo::Capability::GPU_RESOURCES);
    }
    if (capabilities.sharedResources) {
      result.insert(FrameworkInfo::Capability::SHARED_RESOURCES);
    }
    if (capabilities.partitionAware) {
      result.insert(FrameworkInfo::Capability::PARTITION_AWARE);
    }
    if (capabilities.multiRole) {
      result.insert(FrameworkInfo::Capability::MULTI_ROLE);
    }

    return result;
  };

  auto typeSetToCapabilityVector = [](
      const set<FrameworkInfo::Capability::Type>& capabilitiesTypes) {
    vector<FrameworkInfo::Capability> result;

    foreach (FrameworkInfo::Capability::Type type, capabilitiesTypes) {
      FrameworkInfo::Capability capability;
      capability.set_type(type);

      result.push_back(capability);
    }

    return result;
  };

  // We test the `Capabilities` construction by converting back
  // to types and checking for equality with the original types.
  auto backAndForth = [=](const set<FrameworkInfo::Capability::Type>& types) {
    protobuf::framework::Capabilities capabilities(
        typeSetToCapabilityVector(types));

    return toTypeSet(capabilities);
  };

  set<FrameworkInfo::Capability::Type> expected;

  expected = { FrameworkInfo::Capability::REVOCABLE_RESOURCES };
  EXPECT_EQ(expected, backAndForth(expected));

  expected = { FrameworkInfo::Capability::TASK_KILLING_STATE };
  EXPECT_EQ(expected, backAndForth(expected));

  expected = { FrameworkInfo::Capability::GPU_RESOURCES };
  EXPECT_EQ(expected, backAndForth(expected));

  expected = { FrameworkInfo::Capability::SHARED_RESOURCES };
  EXPECT_EQ(expected, backAndForth(expected));

  expected = { FrameworkInfo::Capability::PARTITION_AWARE };
  EXPECT_EQ(expected, backAndForth(expected));

  expected = { FrameworkInfo::Capability::MULTI_ROLE };
  EXPECT_EQ(expected, backAndForth(expected));
}

// This tests that Capabilities are correctly constructed
// from given Agent Capabilities.
TEST(ProtobufUtilTest, AgentCapabilities)
{
  // TODO(jay_guo): consider applying the same test style in
  // FrameworkCapabilities when we have more capabilities in agent.
  RegisterSlaveMessage registerSlaveMessage;
  registerSlaveMessage.add_agent_capabilities()->set_type(
      SlaveInfo::Capability::MULTI_ROLE);

  protobuf::slave::Capabilities capabilities(
      registerSlaveMessage.agent_capabilities());

  ASSERT_TRUE(capabilities.multiRole);
}

} // namespace tests {
} // namespace internal {
} // namespace mesos {
<commit_msg>Augmented a test to check protobuf::stripAllocationInfo.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gtest/gtest.h>

#include <set>
#include <string>
#include <vector>

#include <mesos/mesos.hpp>

#include "common/protobuf_utils.hpp"

#include "tests/mesos.hpp"

using std::set;
using std::string;
using std::vector;

namespace mesos {
namespace internal {
namespace tests {

// This tests that helper function `getRoles` can correctly
// get roles from multi-role FrameworkInfo and role from
// single-role FrameworkInfo.
TEST(ProtobufUtilTest, GetRoles)
{
  // Get roles from a multi-role framework.
  {
    FrameworkInfo frameworkInfo;
    frameworkInfo.add_capabilities()->set_type(
        FrameworkInfo::Capability::MULTI_ROLE);
    frameworkInfo.add_roles("bar");
    frameworkInfo.add_roles("qux");

    set<string> roles = protobuf::framework::getRoles(frameworkInfo);

    EXPECT_EQ(roles, set<string>({"qux", "bar"}));
  }

  // Get role from a single-role framework.
  {
    FrameworkInfo frameworkInfo;
    frameworkInfo.set_role("foo");

    set<string> roles = protobuf::framework::getRoles(frameworkInfo);

    EXPECT_EQ(roles, set<string>({"foo"}));
  }
}

// Tests that allocation info can be injected to and stripped from
// offer operations.
TEST(ProtobufUtilTest, InjectAndStripAllocationInfoInOfferOperation)
{
  Resources unallocatedResources = Resources::parse("cpus:1").get();

  Resources allocatedResources = unallocatedResources;
  allocatedResources.allocate("role");

  Resource::AllocationInfo allocationInfo;
  allocationInfo.set_role("role");

  ExecutorInfo executorInfo;
  executorInfo.mutable_resources()->CopyFrom(unallocatedResources);

  TaskInfo taskInfo;
  taskInfo.mutable_resources()->CopyFrom(unallocatedResources);
  taskInfo.mutable_executor()->CopyFrom(executorInfo);

  {
    // Test the LAUNCH case. This should be constructing a valid
    // task and executor, but for now this just sets the resources
    // in order to verify the allocation info injection and stripping.
    Offer::Operation launch = LAUNCH({taskInfo});
    protobuf::injectAllocationInfo(&launch, allocationInfo);

    ASSERT_EQ(1, launch.launch().task_infos_size());

    EXPECT_EQ(allocatedResources,
              launch.launch().task_infos(0).resources());

    EXPECT_EQ(allocatedResources,
              launch.launch().task_infos(0).executor().resources());

    protobuf::stripAllocationInfo(&launch);

    EXPECT_EQ(unallocatedResources,
              launch.launch().task_infos(0).resources());

    EXPECT_EQ(unallocatedResources,
              launch.launch().task_infos(0).executor().resources());
  }

  {
    // Test the LAUNCH_GROUP case. This should be constructing a valid
    // task and executor, but for now this just sets the resources in
    // order to verify the allocation info injection.
    TaskGroupInfo taskGroupInfo;
    taskGroupInfo.add_tasks()->CopyFrom(taskInfo);

    Offer::Operation launchGroup = LAUNCH_GROUP(executorInfo, taskGroupInfo);
    protobuf::injectAllocationInfo(&launchGroup, allocationInfo);

    ASSERT_EQ(1, launchGroup.launch_group().task_group().tasks_size());

    EXPECT_EQ(allocatedResources,
              launchGroup.launch_group().task_group().tasks(0).resources());

    EXPECT_EQ(allocatedResources,
              launchGroup.launch_group().task_group().tasks(0).executor()
                .resources());

    protobuf::stripAllocationInfo(&launchGroup);

    EXPECT_EQ(unallocatedResources,
              launchGroup.launch_group().task_group().tasks(0).resources());

    EXPECT_EQ(unallocatedResources,
              launchGroup.launch_group().task_group().tasks(0).executor()
                .resources());
  }

  {
    // Test the RESERVE case. This should be constructing a valid
    // reservation, but for now this just sets the resources in
    // order to verify the allocation info injection.
    Offer::Operation reserve = RESERVE(unallocatedResources);
    protobuf::injectAllocationInfo(&reserve, allocationInfo);

    EXPECT_EQ(allocatedResources, reserve.reserve().resources());

    protobuf::stripAllocationInfo(&reserve);

    EXPECT_EQ(unallocatedResources, reserve.reserve().resources());
  }

  {
    // Test the UNRESERVE case. This should be constructing a valid
    // reservation, but for now this just sets the resources in
    // order to verify the allocation info injection.
    Offer::Operation unreserve = UNRESERVE(unallocatedResources);
    protobuf::injectAllocationInfo(&unreserve, allocationInfo);

    EXPECT_EQ(allocatedResources, unreserve.unreserve().resources());

    protobuf::stripAllocationInfo(&unreserve);

    EXPECT_EQ(unallocatedResources, unreserve.unreserve().resources());
  }

  {
    // Test the CREATE case. This should be constructing a valid
    // volume, but for now this just sets the resources in order
    // to verify the allocation info injection.
    Offer::Operation create = CREATE(unallocatedResources);
    protobuf::injectAllocationInfo(&create, allocationInfo);

    EXPECT_EQ(allocatedResources, create.create().volumes());

    protobuf::stripAllocationInfo(&create);

    EXPECT_EQ(unallocatedResources, create.create().volumes());
  }

  {
    // Test the DESTROY case. This should be constructing a valid
    // volume, but for now this just sets the resources in order
    // to verify the allocation info injection.
    Offer::Operation destroy = DESTROY(unallocatedResources);
    protobuf::injectAllocationInfo(&destroy, allocationInfo);

    EXPECT_EQ(allocatedResources, destroy.destroy().volumes());

    protobuf::stripAllocationInfo(&destroy);

    EXPECT_EQ(unallocatedResources, destroy.destroy().volumes());
  }
}

// This tests that Capabilities are correctly constructed
// from given FrameworkInfo Capabilities.
TEST(ProtobufUtilTest, FrameworkCapabilities)
{
  auto toTypeSet = [](
      const protobuf::framework::Capabilities& capabilities) {
    set<FrameworkInfo::Capability::Type> result;

    if (capabilities.revocableResources) {
      result.insert(FrameworkInfo::Capability::REVOCABLE_RESOURCES);
    }
    if (capabilities.taskKillingState) {
      result.insert(FrameworkInfo::Capability::TASK_KILLING_STATE);
    }
    if (capabilities.gpuResources) {
      result.insert(FrameworkInfo::Capability::GPU_RESOURCES);
    }
    if (capabilities.sharedResources) {
      result.insert(FrameworkInfo::Capability::SHARED_RESOURCES);
    }
    if (capabilities.partitionAware) {
      result.insert(FrameworkInfo::Capability::PARTITION_AWARE);
    }
    if (capabilities.multiRole) {
      result.insert(FrameworkInfo::Capability::MULTI_ROLE);
    }

    return result;
  };

  auto typeSetToCapabilityVector = [](
      const set<FrameworkInfo::Capability::Type>& capabilitiesTypes) {
    vector<FrameworkInfo::Capability> result;

    foreach (FrameworkInfo::Capability::Type type, capabilitiesTypes) {
      FrameworkInfo::Capability capability;
      capability.set_type(type);

      result.push_back(capability);
    }

    return result;
  };

  // We test the `Capabilities` construction by converting back
  // to types and checking for equality with the original types.
  auto backAndForth = [=](const set<FrameworkInfo::Capability::Type>& types) {
    protobuf::framework::Capabilities capabilities(
        typeSetToCapabilityVector(types));

    return toTypeSet(capabilities);
  };

  set<FrameworkInfo::Capability::Type> expected;

  expected = { FrameworkInfo::Capability::REVOCABLE_RESOURCES };
  EXPECT_EQ(expected, backAndForth(expected));

  expected = { FrameworkInfo::Capability::TASK_KILLING_STATE };
  EXPECT_EQ(expected, backAndForth(expected));

  expected = { FrameworkInfo::Capability::GPU_RESOURCES };
  EXPECT_EQ(expected, backAndForth(expected));

  expected = { FrameworkInfo::Capability::SHARED_RESOURCES };
  EXPECT_EQ(expected, backAndForth(expected));

  expected = { FrameworkInfo::Capability::PARTITION_AWARE };
  EXPECT_EQ(expected, backAndForth(expected));

  expected = { FrameworkInfo::Capability::MULTI_ROLE };
  EXPECT_EQ(expected, backAndForth(expected));
}

// This tests that Capabilities are correctly constructed
// from given Agent Capabilities.
TEST(ProtobufUtilTest, AgentCapabilities)
{
  // TODO(jay_guo): consider applying the same test style in
  // FrameworkCapabilities when we have more capabilities in agent.
  RegisterSlaveMessage registerSlaveMessage;
  registerSlaveMessage.add_agent_capabilities()->set_type(
      SlaveInfo::Capability::MULTI_ROLE);

  protobuf::slave::Capabilities capabilities(
      registerSlaveMessage.agent_capabilities());

  ASSERT_TRUE(capabilities.multiRole);
}

} // namespace tests {
} // namespace internal {
} // namespace mesos {
<|endoftext|>


<commit_before>// interval_map.cpp
//
#include "dataserver/numeric/interval_map.h"

#if SDL_DEBUG
namespace sdl { namespace {

class unit_test {
    void test1();
public:
    unit_test() {
        if (0) {
            test1();
        }
    }
};
static unit_test s_test;

void unit_test::test1()
{
    SDL_TRACE_FUNCTION;

	typedef int key_t;
	typedef int val_t;
	typedef interval_map<key_t, val_t> map_type;

	map_type test(-1);
	enum { N = 111 };
	enum { M = 1000 };
	enum { M2 = 1 };
	for (int j = 0; j < M; ++j)
	for (int j2 = 0; j2 < M2; ++j2)
	{
		typedef std::vector<key_t> vector_key_t;
		typedef std::vector<val_t> vector_val_t;
		vector_key_t dkeyBegin, dkeyEnd;
		vector_val_t dval;
		const bool print = (0 == j) && (0 == j2);
		if (print) {
			std::cout << "assign:\n";
		}
		for (int i = 0; i < N; ++i)
		{
			const key_t keyBegin = rand() % 100;
			const key_t keyEnd = keyBegin + rand() % 100;
			const val_t val = rand() % 100;
			dkeyBegin.push_back(keyBegin);
			dkeyEnd.push_back(keyEnd);
			dval.push_back(val);
			if (print) {
				std::cout << i << ": (" << keyBegin << "," << keyEnd << "," << val << ")\n";
			}
			test.assign(keyBegin, keyEnd, val);
		}
		if (print) {
			std::cout << "trace map:\n";
		}
		auto it = test.map().begin();
		for (; it != test.map().end(); ++it) {
			if (print) {
				std::cout
					<< "key = " << it->first << ", "
					<< "val = " << it->second << "\n";
			}
			if (it != test.map().begin()) {
				auto it2 = it; --it2;
				if (it2->second == it->second) // error !
				{
					map_type test2(-1);
					for (size_t k = 0; k < dkeyBegin.size(); ++k)
					{
						std::cout << k << ": (" << dkeyBegin[k] << "," << dkeyEnd[k] << "," << dval[k] << ")\n";
						test2.assign(dkeyBegin[k], dkeyEnd[k], dval[k]);
					}
				}
				assert(it2->second != it->second);
				assert(it2->first < it->first);
			}
		}
	}
}

}} // sdl
#endif //#if SDL_DEBUG
<commit_msg>interval_map.cpp<commit_after>// interval_map.cpp
//
#include "dataserver/numeric/interval_map.h"

#if SDL_DEBUG
namespace sdl { namespace {

class unit_test {
    void test1();
public:
    unit_test() {
        if (0) {
            test1();
        }
    }
};
static unit_test s_test;

void unit_test::test1()
{
	typedef int key_t;
	typedef int val_t;
	typedef interval_map<key_t, val_t> map_type;

	map_type test(-1);
	enum { N = 111 };
	enum { M = 1000 };
	enum { M2 = 1 };
	for (int j = 0; j < M; ++j) {
	for (int j2 = 0; j2 < M2; ++j2)	{
		typedef std::vector<key_t> vector_key_t;
		typedef std::vector<val_t> vector_val_t;
		vector_key_t dkeyBegin, dkeyEnd;
		vector_val_t dval;
		for (int i = 0; i < N; ++i) {
			const key_t keyBegin = rand() % 100;
			const key_t keyEnd = keyBegin + rand() % 100;
			const val_t val = rand() % 100;
			dkeyBegin.push_back(keyBegin);
			dkeyEnd.push_back(keyEnd);
			dval.push_back(val);
			test.assign(keyBegin, keyEnd, val);
		}
        if (!test.map().empty()) {
            const auto end = test.map().end();
		    auto it = test.map().begin();
            ++it;
		    for (; it != end; ++it) {
				auto it2 = it; --it2;
				SDL_ASSERT(it2->second != it->second);
				SDL_ASSERT(it2->first < it->first);
		    }
        }
    }}
}

}} // sdl
#endif //#if SDL_DEBUG
<|endoftext|>


<commit_before>#include <davix.hpp>
#include <tools/davix_tool_params.hpp>
#include <tools/davix_tool_util.hpp>
#include <cstdio>

using namespace Davix;
using namespace std;

const std::string scope_main = "Davix::Tools::davix";

static void performanceCallback(const PerformanceData& perfData, void *udata)
{
    (void) udata;
    std::cout << perfData.totalTransferred()
              << " (" << perfData.avgTransfer() << " bytes/sec)"
              << std::endl;
}

static std::string help_msg(const std::string & cmd_path)(){
    std::string help_msg = fmt::format("Usage : {} ", cmd_path);
    help_msg += Tool::get_copy_description_options();
    help_msg += Tool::get_common_options();

    return help_msg;
}

int main(int argc, char** argv){
    int retcode=-1;
    Tool::OptParams opts;
    DavixError* tmp_err=NULL;
    opts.help_msg = help_msg(argv[0]);

    if( (retcode= Tool::parse_davix_options(argc, argv, opts, &tmp_err)) ==0){
        Context c;
        if( (retcode = Tool::configureAuth(opts)) == 0){
            configureContext(c, opts);
            DavixCopy copy(c, &opts.params);
            copy.setPerformanceCallback(performanceCallback, NULL);
            copy.copy(opts.vec_arg[0], opts.vec_arg[1],
                      1, &tmp_err);
        }
    }
    Tool::errorPrint(&tmp_err);
    return retcode;
}
<commit_msg>Fixed compilation of davix_tool_copy_main.cpp<commit_after>#include <davix.hpp>
#include <tools/davix_tool_params.hpp>
#include <tools/davix_tool_util.hpp>
#include <cstdio>

using namespace Davix;
using namespace std;

const std::string scope_main = "Davix::Tools::davix";

static void performanceCallback(const PerformanceData& perfData, void *udata)
{
    (void) udata;
    std::cout << perfData.totalTransferred()
              << " (" << perfData.avgTransfer() << " bytes/sec)"
              << std::endl;
}

static std::string help_msg(const std::string & cmd_path){
    std::string help_str = fmt::format("Usage : {} ", cmd_path);
    help_str += Tool::get_copy_description_options();
    help_str += Tool::get_common_options();

    return help_str;
}

int main(int argc, char** argv){
    int retcode=-1;
    Tool::OptParams opts;
    DavixError* tmp_err=NULL;
    opts.help_msg = help_msg(argv[0]);

    if( (retcode= Tool::parse_davix_options(argc, argv, opts, &tmp_err)) ==0){
        Context c;
        if( (retcode = Tool::configureAuth(opts)) == 0){
            configureContext(c, opts);
            DavixCopy copy(c, &opts.params);
            copy.setPerformanceCallback(performanceCallback, NULL);
            copy.copy(opts.vec_arg[0], opts.vec_arg[1],
                      1, &tmp_err);
        }
    }
    Tool::errorPrint(&tmp_err);
    return retcode;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <assert.h>
#include <errno.h>
#include <cstdio>
#include <cstdarg>
#include <string.h>

#include <algorithm>
#include <string>
#include <vector>

#include "native_client/src/include/nacl_string.h"
#include "native_client/src/include/portability.h"
#include "native_client/src/trusted/validator/ncfileutil.h"
#include "native_client/src/trusted/cpu_features/arch/arm/cpu_arm.h"
#include "native_client/src/trusted/validator_arm/model.h"
#include "native_client/src/trusted/validator_arm/problem_reporter.h"
#include "native_client/src/trusted/validator_arm/validator.h"

using nacl_arm_val::SfiValidator;
using nacl_arm_val::CodeSegment;
using nacl_arm_val::ProblemReporter;
using nacl_arm_dec::MAY_BE_SAFE;

using std::string;
using std::vector;

/*
 * Reports problems in an easily-parsed textual format, for consumption by a
 * validation-reporting script.
 *
 * The format is as follows:
 *   ncval: <hex vaddr> <decimal safety> <problem ID string> <hex ref vaddr>
 *
 * For possible safety levels, see inst_classes.h.
 *
 * For possible problem ID strings, see validator.h.
 */
class NcvalProblemReporter : public ProblemReporter {
 protected:
  virtual void ReportProblemMessage(nacl_arm_dec::Violation violation,
                                    uint32_t vaddr,
                                    const char* message);
};

void NcvalProblemReporter::
ReportProblemMessage(nacl_arm_dec::Violation violation,
                     uint32_t vaddr,
                     const char* message) {
  UNREFERENCED_PARAMETER(vaddr);
  UNREFERENCED_PARAMETER(violation);
  printf("%8"NACL_PRIx32": %s\n", vaddr, message);
}

const uint32_t kOneGig = 1U * 1024 * 1024 * 1024;

int validate(const ncfile *ncf, const NaClCPUFeaturesArm *cpu_features) {
  SfiValidator validator(
      16,  // bytes per bundle
      // TODO(cbiffle): maybe check region sizes from ELF headers?
      //                verify that instructions are in right region
      kOneGig,  // code region size
      kOneGig,  // data region size
      nacl_arm_dec::RegisterList(nacl_arm_dec::Register::Tp()),
      nacl_arm_dec::RegisterList(nacl_arm_dec::Register::Sp()),
      cpu_features);

  NcvalProblemReporter reporter;

  Elf_Shdr *shdr = ncf->sheaders;

  vector<CodeSegment> segments;
  for (int i = 0; i < ncf->shnum; i++) {
    if ((shdr[i].sh_flags & SHF_EXECINSTR) != SHF_EXECINSTR) {
      continue;
    }

    CodeSegment segment(ncf->data + (shdr[i].sh_addr - ncf->vbase),
        shdr[i].sh_addr, shdr[i].sh_size);
    segments.push_back(segment);
  }

  std::sort(segments.begin(), segments.end());

  bool success = validator.validate(segments, &reporter);
  if (!success) return 1;
  return 0;
}

int main(int argc, const char *argv[]) {
  static const char cond_mem_access_flag[] =
      "--conditional_memory_access_allowed_for_sfi";

  static const char number_runs_flag[] =
      "--number_runs";

  NaClCPUFeaturesArm cpu_features;
  NaClClearCPUFeaturesArm(&cpu_features);

  int exit_code = EXIT_FAILURE;
  bool print_usage = false;
  bool run_validation = false;
  int number_runs = 1;
  std::string filename;
  ncfile *ncf = NULL;

  for (int i = 1; i < argc; ++i) {
    std::string current_arg = argv[i];
    if (current_arg == "--usage" ||
        current_arg == "--help") {
      print_usage = true;
      run_validation = false;
      break;
    } else if (current_arg == number_runs_flag) {
      // next argument is the number of runs to try. Used when timing
      // performance, and want to run many times to get a good average
      // time result.
      ++i;
      if (i < argc) {
        number_runs = atoi(argv[i]);
      } else {
        // No value to got with argument, fail to run.
        print_usage = true;
        run_validation = false;
      }
    } else if (current_arg == cond_mem_access_flag) {
      // This flag is disallowed by default: not all ARM CPUs support it,
      // so be pessimistic unless the user asks for it.
      NaClSetCPUFeatureArm(&cpu_features, NaClCPUFeatureArm_CanUseTstMem, 1);
    } else if (!filename.empty()) {
      fprintf(stderr, "Error: multiple files specified.\n");
      print_usage = true;
      run_validation = false;
      break;
    } else {
      filename = current_arg;
      run_validation = true;
    }
  }

  if (filename.empty()) {
    fprintf(stderr, "Error: no file specified.\n");
    print_usage = true;
    run_validation = false;
  } else {
    ncf = nc_loadfile(filename.c_str());
    if (!ncf) {
      int err = errno;
      fprintf(stderr, "Error: unable to load file %s: %s.\n",
              filename.c_str(), strerror(err));
      print_usage = true;
      run_validation = false;
    }
  }

  if (print_usage) {
    fprintf(stderr, "Usage: %s [options] <filename>\n", argv[0]);
    fprintf(stderr, "   %s\n", cond_mem_access_flag);
    fprintf(stderr, "      Allow conditions on memory access.\n");
    fprintf(stderr, "   %s n\n", number_runs_flag);
    fprintf(stderr, "      Validate input n times.\n");
    fprintf(stderr, "      Used for performance timing.\n");
  }

  // TODO(cbiffle): check OS ABI, ABI version, align mask

  if (run_validation) {
    exit_code = 0;
    for (int i = 0; i < number_runs; ++i) {
      exit_code |= validate(ncf, &cpu_features);
    }
    if (exit_code == 0)
      printf("Valid.\n");
    else
      printf("Invalid.\n");
  }

  if (ncf)
      nc_freefile(ncf);

  return exit_code;
}
<commit_msg>Allow passing raw code on command line of validator.<commit_after>/*
 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <assert.h>
#include <errno.h>
#include <cstdio>
#include <cstdarg>
#include <string.h>

#include <algorithm>
#include <string>
#include <vector>

#include "native_client/src/include/nacl_string.h"
#include "native_client/src/include/portability.h"
#include "native_client/src/trusted/validator/ncfileutil.h"
#include "native_client/src/trusted/cpu_features/arch/arm/cpu_arm.h"
#include "native_client/src/trusted/validator_arm/model.h"
#include "native_client/src/trusted/validator_arm/problem_reporter.h"
#include "native_client/src/trusted/validator_arm/validator.h"

using nacl_arm_val::SfiValidator;
using nacl_arm_val::CodeSegment;
using nacl_arm_val::ProblemReporter;
using nacl_arm_dec::MAY_BE_SAFE;

using std::string;
using std::vector;

/*
 * Reports problems in an easily-parsed textual format, for consumption by a
 * validation-reporting script.
 *
 * The format is as follows:
 *   ncval: <hex vaddr> <decimal safety> <problem ID string> <hex ref vaddr>
 *
 * For possible safety levels, see inst_classes.h.
 *
 * For possible problem ID strings, see validator.h.
 */
class NcvalProblemReporter : public ProblemReporter {
 protected:
  virtual void ReportProblemMessage(nacl_arm_dec::Violation violation,
                                    uint32_t vaddr,
                                    const char* message);
};

void NcvalProblemReporter::
ReportProblemMessage(nacl_arm_dec::Violation violation,
                     uint32_t vaddr,
                     const char* message) {
  UNREFERENCED_PARAMETER(vaddr);
  UNREFERENCED_PARAMETER(violation);
  printf("%8"NACL_PRIx32": %s\n", vaddr, message);
}

const uint32_t kOneGig = 1U * 1024 * 1024 * 1024;

int validate(const ncfile *ncf, const NaClCPUFeaturesArm *cpu_features) {
  SfiValidator validator(
      16,  // bytes per bundle
      // TODO(cbiffle): maybe check region sizes from ELF headers?
      //                verify that instructions are in right region
      kOneGig,  // code region size
      kOneGig,  // data region size
      nacl_arm_dec::RegisterList(nacl_arm_dec::Register::Tp()),
      nacl_arm_dec::RegisterList(nacl_arm_dec::Register::Sp()),
      cpu_features);

  NcvalProblemReporter reporter;

  Elf_Shdr *shdr = ncf->sheaders;

  vector<CodeSegment> segments;
  for (int i = 0; i < ncf->shnum; i++) {
    if ((shdr[i].sh_flags & SHF_EXECINSTR) != SHF_EXECINSTR) {
      continue;
    }

    CodeSegment segment(ncf->data + (shdr[i].sh_addr - ncf->vbase),
        shdr[i].sh_addr, shdr[i].sh_size);
    segments.push_back(segment);
  }

  std::sort(segments.begin(), segments.end());

  bool success = validator.validate(segments, &reporter);
  if (!success) return 1;
  return 0;
}

static inline uint8_t as_hex(char c) {
  if (c >= '0' && c <= '9') return c - '0';
  if (c >= 'a' && c <= 'f') return c - 'a' + 0xa;
  if (c >= 'A' && c <= 'F') return c - 'A' + 0xa;
  CHECK(false);
  return 0;
}

int check_code(const std::string& code) {
  NaClCPUFeaturesArm cpu_features;
  SfiValidator validator(
      16,  // bytes per bundle
      kOneGig,  // code region size
      kOneGig,  // data region size
      nacl_arm_dec::RegisterList(nacl_arm_dec::Register::Tp()),
      nacl_arm_dec::RegisterList(nacl_arm_dec::Register::Sp()),
      &cpu_features);
  NcvalProblemReporter reporter;

  uint8_t* code_buf = new uint8_t[code.length()];
  uint32_t code_len = 0;
  for (uint32_t i = 0; i < code.length(); i += 3) {
    code_buf[code_len++] = (as_hex(code[i]) << 4) | as_hex(code[i+1]);
  }
  printf("Validating code: ");
  for (uint32_t i = 0; i < code_len; i++) {
    printf("%02x ", code_buf[i]);
  }
  printf("\n");

  vector<CodeSegment> segments;
  CodeSegment segment(code_buf, 0, code_len);
  segments.push_back(segment);
  bool success = validator.validate(segments, &reporter);
  if (success) {
    printf("valid!\n");
    return 0;
  } else {
    printf("invalid\n");
    return 1;
  }
}

int main(int argc, const char *argv[]) {
  static const char cond_mem_access_flag[] =
      "--conditional_memory_access_allowed_for_sfi";

  static const char number_runs_flag[] =
      "--number_runs";

  NaClCPUFeaturesArm cpu_features;
  NaClClearCPUFeaturesArm(&cpu_features);

  int exit_code = EXIT_FAILURE;
  bool print_usage = false;
  bool run_validation = false;
  int number_runs = 1;
  std::string filename;
  ncfile *ncf = NULL;
  std::string code;

  for (int i = 1; i < argc; ++i) {
    std::string current_arg = argv[i];
    if (current_arg == "--usage" ||
        current_arg == "--help") {
      print_usage = true;
      run_validation = false;
      break;
    } else if (current_arg == number_runs_flag) {
      // next argument is the number of runs to try. Used when timing
      // performance, and want to run many times to get a good average
      // time result.
      ++i;
      if (i < argc) {
        number_runs = atoi(argv[i]);
      } else {
        // No value to got with argument, fail to run.
        print_usage = true;
        run_validation = false;
      }
    } else if (current_arg == cond_mem_access_flag) {
      // This flag is disallowed by default: not all ARM CPUs support it,
      // so be pessimistic unless the user asks for it.
      NaClSetCPUFeatureArm(&cpu_features, NaClCPUFeatureArm_CanUseTstMem, 1);
    } else if (current_arg == "--check" && i + 1 < argc) {
      code = argv[i+1];
      i++;
    } else if (!filename.empty()) {
      fprintf(stderr, "Error: multiple files specified.\n");
      print_usage = true;
      run_validation = false;
      break;
    } else {
      filename = current_arg;
      run_validation = true;
    }
  }

  if (!code.empty()) {
      return check_code(code);
  }

  if (filename.empty()) {
    fprintf(stderr, "Error: no file specified.\n");
    print_usage = true;
    run_validation = false;
  } else {
    ncf = nc_loadfile(filename.c_str());
    if (!ncf) {
      int err = errno;
      fprintf(stderr, "Error: unable to load file %s: %s.\n",
              filename.c_str(), strerror(err));
      print_usage = true;
      run_validation = false;
    }
  }

  if (print_usage) {
    fprintf(stderr, "Usage: %s [options] <filename>\n", argv[0]);
    fprintf(stderr, "   %s\n", cond_mem_access_flag);
    fprintf(stderr, "      Allow conditions on memory access.\n");
    fprintf(stderr, "   %s n\n", number_runs_flag);
    fprintf(stderr, "      Validate input n times.\n");
    fprintf(stderr, "      Used for performance timing.\n");
  }

  // TODO(cbiffle): check OS ABI, ABI version, align mask

  if (run_validation) {
    exit_code = 0;
    for (int i = 0; i < number_runs; ++i) {
      exit_code |= validate(ncf, &cpu_features);
    }
    if (exit_code == 0)
      printf("Valid.\n");
    else
      printf("Invalid.\n");
  }

  if (ncf)
      nc_freefile(ncf);

  return exit_code;
}
<|endoftext|>


<commit_before>/*
 *   Copyright (c) 2020 Project CHIP Authors
 *   All rights reserved.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */

#include "PairingCommand.h"
#include "platform/PlatformManager.h"
#include <controller/ExampleOperationalCredentialsIssuer.h>
#include <crypto/CHIPCryptoPAL.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/support/logging/CHIPLogging.h>
#include <protocols/secure_channel/PASESession.h>

#include <setup_payload/ManualSetupPayloadParser.h>
#include <setup_payload/QRCodeSetupPayloadParser.h>

using namespace ::chip;
using namespace ::chip::Controller;

CHIP_ERROR PairingCommand::RunCommand()
{
    CurrentCommissioner().RegisterPairingDelegate(this);
    return RunInternal(mNodeId);
}

CHIP_ERROR PairingCommand::RunInternal(NodeId remoteId)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    switch (mPairingMode)
    {
    case PairingMode::None:
        err = Unpair(remoteId);
        break;
    case PairingMode::QRCode:
        err = PairWithCode(remoteId);
        break;
    case PairingMode::ManualCode:
        err = PairWithCode(remoteId);
        break;
    case PairingMode::QRCodePaseOnly:
    case PairingMode::ManualCodePaseOnly:
        err = PaseWithCode(remoteId);
        break;
    case PairingMode::Ble:
        err = Pair(remoteId, PeerAddress::BLE());
        break;
    case PairingMode::OnNetwork:
        err = PairWithMdns(remoteId);
        break;
    case PairingMode::SoftAP:
        err = Pair(remoteId, PeerAddress::UDP(mRemoteAddr.address, mRemotePort));
        break;
    case PairingMode::Ethernet:
        err = Pair(remoteId, PeerAddress::UDP(mRemoteAddr.address, mRemotePort));
        break;
    }

    return err;
}

CommissioningParameters PairingCommand::GetCommissioningParameters()
{
    switch (mNetworkType)
    {
    case PairingNetworkType::WiFi:
        return CommissioningParameters().SetWiFiCredentials(Controller::WiFiCredentials(mSSID, mPassword));
    case PairingNetworkType::Thread:
        return CommissioningParameters().SetThreadOperationalDataset(mOperationalDataset);
    case PairingNetworkType::Ethernet:
    case PairingNetworkType::None:
        return CommissioningParameters();
    }
    return CommissioningParameters();
}

CHIP_ERROR PairingCommand::PaseWithCode(NodeId remoteId)
{
    return CurrentCommissioner().EstablishPASEConnection(remoteId, mOnboardingPayload);
}

CHIP_ERROR PairingCommand::PairWithCode(NodeId remoteId)
{
    CommissioningParameters commissioningParams = GetCommissioningParameters();
    return CurrentCommissioner().PairDevice(remoteId, mOnboardingPayload, commissioningParams);
}

CHIP_ERROR PairingCommand::Pair(NodeId remoteId, PeerAddress address)
{
    RendezvousParameters params =
        RendezvousParameters().SetSetupPINCode(mSetupPINCode).SetDiscriminator(mDiscriminator).SetPeerAddress(address);
    CommissioningParameters commissioningParams = GetCommissioningParameters();
    return CurrentCommissioner().PairDevice(remoteId, params, commissioningParams);
}

CHIP_ERROR PairingCommand::PairWithMdns(NodeId remoteId)
{
    Dnssd::DiscoveryFilter filter(mFilterType);
    switch (mFilterType)
    {
    case chip::Dnssd::DiscoveryFilterType::kNone:
        break;
    case chip::Dnssd::DiscoveryFilterType::kShortDiscriminator:
    case chip::Dnssd::DiscoveryFilterType::kLongDiscriminator:
    case chip::Dnssd::DiscoveryFilterType::kCompressedFabricId:
    case chip::Dnssd::DiscoveryFilterType::kVendorId:
    case chip::Dnssd::DiscoveryFilterType::kDeviceType:
        filter.code = mDiscoveryFilterCode;
        break;
    case chip::Dnssd::DiscoveryFilterType::kCommissioningMode:
        break;
    case chip::Dnssd::DiscoveryFilterType::kCommissioner:
        filter.code = 1;
        break;
    case chip::Dnssd::DiscoveryFilterType::kInstanceName:
        filter.code         = 0;
        filter.instanceName = mDiscoveryFilterInstanceName;
        break;
    }

    CurrentCommissioner().RegisterDeviceDiscoveryDelegate(this);
    return CurrentCommissioner().DiscoverCommissionableNodes(filter);
}

CHIP_ERROR PairingCommand::Unpair(NodeId remoteId)
{
    CHIP_ERROR err = CurrentCommissioner().UnpairDevice(remoteId);
    SetCommandExitStatus(err);
    return err;
}

void PairingCommand::OnStatusUpdate(DevicePairingDelegate::Status status)
{
    switch (status)
    {
    case DevicePairingDelegate::Status::SecurePairingSuccess:
        ChipLogProgress(chipTool, "Secure Pairing Success");
        break;
    case DevicePairingDelegate::Status::SecurePairingFailed:
        ChipLogError(chipTool, "Secure Pairing Failed");
        break;
    }
}

void PairingCommand::OnPairingComplete(CHIP_ERROR err)
{
    if (err == CHIP_NO_ERROR)
    {
        ChipLogProgress(chipTool, "Pairing Success");
        if (mPairingMode == PairingMode::QRCodePaseOnly || mPairingMode == PairingMode::ManualCodePaseOnly)
        {
            SetCommandExitStatus(err);
        }
    }
    else
    {
        ChipLogProgress(chipTool, "Pairing Failure: %s", ErrorStr(err));
    }

    if (err != CHIP_NO_ERROR)
    {
        SetCommandExitStatus(err);
    }
}

void PairingCommand::OnPairingDeleted(CHIP_ERROR err)
{
    if (err == CHIP_NO_ERROR)
    {
        ChipLogProgress(chipTool, "Pairing Deleted Success");
    }
    else
    {
        ChipLogProgress(chipTool, "Pairing Deleted Failure: %s", ErrorStr(err));
    }

    SetCommandExitStatus(err);
}

void PairingCommand::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err)
{
    if (err == CHIP_NO_ERROR)
    {
        ChipLogProgress(chipTool, "Device commissioning completed with success");
    }
    else
    {
        ChipLogProgress(chipTool, "Device commissioning Failure: %s", ErrorStr(err));
    }

    SetCommandExitStatus(err);
}

void PairingCommand::OnDiscoveredDevice(const chip::Dnssd::DiscoveredNodeData & nodeData)
{
    // Ignore nodes with closed comissioning window
    VerifyOrReturn(nodeData.commissioningMode != 0);

    const uint16_t port = nodeData.port;
    char buf[chip::Inet::IPAddress::kMaxStringLength];
    nodeData.ipAddress[0].ToString(buf);
    ChipLogProgress(chipTool, "Discovered Device: %s:%u", buf, port);

    // Stop Mdns discovery. Is it the right method ?
    CurrentCommissioner().RegisterDeviceDiscoveryDelegate(nullptr);

    Inet::InterfaceId interfaceId = nodeData.ipAddress[0].IsIPv6LinkLocal() ? nodeData.interfaceId : Inet::InterfaceId::Null();
    PeerAddress peerAddress       = PeerAddress::UDP(nodeData.ipAddress[0], port, interfaceId);
    CHIP_ERROR err                = Pair(mNodeId, peerAddress);
    if (CHIP_NO_ERROR != err)
    {
        SetCommandExitStatus(err);
    }
}
<commit_msg>chip-tool: use correct interface when specified (#16833)<commit_after>/*
 *   Copyright (c) 2020 Project CHIP Authors
 *   All rights reserved.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */

#include "PairingCommand.h"
#include "platform/PlatformManager.h"
#include <controller/ExampleOperationalCredentialsIssuer.h>
#include <crypto/CHIPCryptoPAL.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/support/logging/CHIPLogging.h>
#include <protocols/secure_channel/PASESession.h>

#include <setup_payload/ManualSetupPayloadParser.h>
#include <setup_payload/QRCodeSetupPayloadParser.h>

using namespace ::chip;
using namespace ::chip::Controller;

CHIP_ERROR PairingCommand::RunCommand()
{
    CurrentCommissioner().RegisterPairingDelegate(this);
    return RunInternal(mNodeId);
}

CHIP_ERROR PairingCommand::RunInternal(NodeId remoteId)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    switch (mPairingMode)
    {
    case PairingMode::None:
        err = Unpair(remoteId);
        break;
    case PairingMode::QRCode:
        err = PairWithCode(remoteId);
        break;
    case PairingMode::ManualCode:
        err = PairWithCode(remoteId);
        break;
    case PairingMode::QRCodePaseOnly:
    case PairingMode::ManualCodePaseOnly:
        err = PaseWithCode(remoteId);
        break;
    case PairingMode::Ble:
        err = Pair(remoteId, PeerAddress::BLE());
        break;
    case PairingMode::OnNetwork:
        err = PairWithMdns(remoteId);
        break;
    case PairingMode::SoftAP:
        err = Pair(remoteId, PeerAddress::UDP(mRemoteAddr.address, mRemotePort, mRemoteAddr.interfaceId));
        break;
    case PairingMode::Ethernet:
        err = Pair(remoteId, PeerAddress::UDP(mRemoteAddr.address, mRemotePort, mRemoteAddr.interfaceId));
        break;
    }

    return err;
}

CommissioningParameters PairingCommand::GetCommissioningParameters()
{
    switch (mNetworkType)
    {
    case PairingNetworkType::WiFi:
        return CommissioningParameters().SetWiFiCredentials(Controller::WiFiCredentials(mSSID, mPassword));
    case PairingNetworkType::Thread:
        return CommissioningParameters().SetThreadOperationalDataset(mOperationalDataset);
    case PairingNetworkType::Ethernet:
    case PairingNetworkType::None:
        return CommissioningParameters();
    }
    return CommissioningParameters();
}

CHIP_ERROR PairingCommand::PaseWithCode(NodeId remoteId)
{
    return CurrentCommissioner().EstablishPASEConnection(remoteId, mOnboardingPayload);
}

CHIP_ERROR PairingCommand::PairWithCode(NodeId remoteId)
{
    CommissioningParameters commissioningParams = GetCommissioningParameters();
    return CurrentCommissioner().PairDevice(remoteId, mOnboardingPayload, commissioningParams);
}

CHIP_ERROR PairingCommand::Pair(NodeId remoteId, PeerAddress address)
{
    RendezvousParameters params =
        RendezvousParameters().SetSetupPINCode(mSetupPINCode).SetDiscriminator(mDiscriminator).SetPeerAddress(address);
    CommissioningParameters commissioningParams = GetCommissioningParameters();
    return CurrentCommissioner().PairDevice(remoteId, params, commissioningParams);
}

CHIP_ERROR PairingCommand::PairWithMdns(NodeId remoteId)
{
    Dnssd::DiscoveryFilter filter(mFilterType);
    switch (mFilterType)
    {
    case chip::Dnssd::DiscoveryFilterType::kNone:
        break;
    case chip::Dnssd::DiscoveryFilterType::kShortDiscriminator:
    case chip::Dnssd::DiscoveryFilterType::kLongDiscriminator:
    case chip::Dnssd::DiscoveryFilterType::kCompressedFabricId:
    case chip::Dnssd::DiscoveryFilterType::kVendorId:
    case chip::Dnssd::DiscoveryFilterType::kDeviceType:
        filter.code = mDiscoveryFilterCode;
        break;
    case chip::Dnssd::DiscoveryFilterType::kCommissioningMode:
        break;
    case chip::Dnssd::DiscoveryFilterType::kCommissioner:
        filter.code = 1;
        break;
    case chip::Dnssd::DiscoveryFilterType::kInstanceName:
        filter.code         = 0;
        filter.instanceName = mDiscoveryFilterInstanceName;
        break;
    }

    CurrentCommissioner().RegisterDeviceDiscoveryDelegate(this);
    return CurrentCommissioner().DiscoverCommissionableNodes(filter);
}

CHIP_ERROR PairingCommand::Unpair(NodeId remoteId)
{
    CHIP_ERROR err = CurrentCommissioner().UnpairDevice(remoteId);
    SetCommandExitStatus(err);
    return err;
}

void PairingCommand::OnStatusUpdate(DevicePairingDelegate::Status status)
{
    switch (status)
    {
    case DevicePairingDelegate::Status::SecurePairingSuccess:
        ChipLogProgress(chipTool, "Secure Pairing Success");
        break;
    case DevicePairingDelegate::Status::SecurePairingFailed:
        ChipLogError(chipTool, "Secure Pairing Failed");
        break;
    }
}

void PairingCommand::OnPairingComplete(CHIP_ERROR err)
{
    if (err == CHIP_NO_ERROR)
    {
        ChipLogProgress(chipTool, "Pairing Success");
        if (mPairingMode == PairingMode::QRCodePaseOnly || mPairingMode == PairingMode::ManualCodePaseOnly)
        {
            SetCommandExitStatus(err);
        }
    }
    else
    {
        ChipLogProgress(chipTool, "Pairing Failure: %s", ErrorStr(err));
    }

    if (err != CHIP_NO_ERROR)
    {
        SetCommandExitStatus(err);
    }
}

void PairingCommand::OnPairingDeleted(CHIP_ERROR err)
{
    if (err == CHIP_NO_ERROR)
    {
        ChipLogProgress(chipTool, "Pairing Deleted Success");
    }
    else
    {
        ChipLogProgress(chipTool, "Pairing Deleted Failure: %s", ErrorStr(err));
    }

    SetCommandExitStatus(err);
}

void PairingCommand::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err)
{
    if (err == CHIP_NO_ERROR)
    {
        ChipLogProgress(chipTool, "Device commissioning completed with success");
    }
    else
    {
        ChipLogProgress(chipTool, "Device commissioning Failure: %s", ErrorStr(err));
    }

    SetCommandExitStatus(err);
}

void PairingCommand::OnDiscoveredDevice(const chip::Dnssd::DiscoveredNodeData & nodeData)
{
    // Ignore nodes with closed comissioning window
    VerifyOrReturn(nodeData.commissioningMode != 0);

    const uint16_t port = nodeData.port;
    char buf[chip::Inet::IPAddress::kMaxStringLength];
    nodeData.ipAddress[0].ToString(buf);
    ChipLogProgress(chipTool, "Discovered Device: %s:%u", buf, port);

    // Stop Mdns discovery. Is it the right method ?
    CurrentCommissioner().RegisterDeviceDiscoveryDelegate(nullptr);

    Inet::InterfaceId interfaceId = nodeData.ipAddress[0].IsIPv6LinkLocal() ? nodeData.interfaceId : Inet::InterfaceId::Null();
    PeerAddress peerAddress       = PeerAddress::UDP(nodeData.ipAddress[0], port, interfaceId);
    CHIP_ERROR err                = Pair(mNodeId, peerAddress);
    if (CHIP_NO_ERROR != err)
    {
        SetCommandExitStatus(err);
    }
}
<|endoftext|>