<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Log$
 * Revision 1.9  2003/10/02 19:20:42  peiyongz
 * fWhiteSpace moved to DatatypeValidator
 *
 * Revision 1.8  2003/10/01 01:09:35  knoaman
 * Refactoring of some code to improve performance.
 *
 * Revision 1.7  2003/09/30 21:31:37  peiyongz
 * Implementation of Serialization/Deserialization
 *
 * Revision 1.6  2003/09/29 21:47:35  peiyongz
 * Implementation of Serialization/Deserialization
 *
 * Revision 1.5  2003/05/15 18:53:27  knoaman
 * Partial implementation of the configurable memory manager.
 *
 * Revision 1.4  2002/12/18 14:17:55  gareth
 * Fix to bug #13438. When you eant a vector that calls delete[] on its members you should use RefArrayVectorOf.
 *
 * Revision 1.3  2002/11/04 14:53:28  tng
 * C++ Namespace Support.
 *
 * Revision 1.2  2002/09/24 19:44:40  tng
 * Performance: use XMLString::equals instead of XMLString::compareString
 *
 * Revision 1.1.1.1  2002/02/01 22:22:42  peiyongz
 * sane_include
 *
 * Revision 1.17  2001/10/09 20:54:35  peiyongz
 * init(): take 1 arg.
 *
 * Revision 1.16  2001/09/27 13:51:25  peiyongz
 * DTV Reorganization: ctor/init created to be used by derived class
 *
 * Revision 1.15  2001/09/25 15:58:14  peiyongz
 * Check baseValidator in assignAdditinoalFacet() and inheritAdditionalFacet()
 *
 * Revision 1.14  2001/09/24 15:31:13  peiyongz
 * DTV Reorganization: inherit from AbstractStringValidator
 *
 * Revision 1.12  2001/08/21 18:42:53  peiyongz
 * Bugzilla# 2816: cleanUp() declared with external linkage and called
 *                          before defined as inline
 *
 * Revision 1.11  2001/06/20 17:56:09  peiyongz
 * support for "fixed" option on constrainning facets
 *
 * Revision 1.10  2001/05/29 19:49:36  tng
 * Schema: Constraint Checking Fix in datatypeValidators.  By Pei Yong Zhang.
 *
 * Revision 1.9  2001/05/28 21:11:18  tng
 * Schema: Various DatatypeValidator fix.  By Pei Yong Zhang
 *
 * Revision 1.8  2001/05/23 16:05:11  tng
 * Schema: NormalizedString fix.  By Pei Yong Zhang.
 *
 * Revision 1.7  2001/05/23 15:45:25  tng
 * Schema: NormalizedString fix.  By Pei Yong Zhang.
 *
 * Revision 1.6  2001/05/18 13:36:48  tng
 * Schema: Catch RegularExpression exception and NumberFormatException
 *
 * Revision 1.5  2001/05/18 13:23:51  tng
 * Schema: Exception messages in DatatypeValidator.  By Pei Yong Zhang.
 *
 * Revision 1.4  2001/05/16 14:33:40  tng
 * Schema Constraint checking fix.
 *
 * Revision 1.3  2001/05/11 17:17:28  tng
 * Schema: DatatypeValidator fixes.  By Pei Yong Zhang.
 *
 * Revision 1.2  2001/05/11 13:27:29  tng
 * Copyright update.
 *
 * Revision 1.1  2001/05/09 18:43:42  tng
 * Add StringDatatypeValidator and BooleanDatatypeValidator.  By Pei Yong Zhang.
 *
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/validators/datatype/StringDatatypeValidator.hpp>
#include <xercesc/validators/schema/SchemaSymbols.hpp>
#include <xercesc/validators/datatype/InvalidDatatypeFacetException.hpp>
#include <xercesc/validators/datatype/InvalidDatatypeValueException.hpp>

XERCES_CPP_NAMESPACE_BEGIN

static const int BUF_LEN = 64;
static XMLCh value1[BUF_LEN+1];
static XMLCh value2[BUF_LEN+1];

// ---------------------------------------------------------------------------
//  Constructors and Destructor
// ---------------------------------------------------------------------------
StringDatatypeValidator::StringDatatypeValidator(MemoryManager* const manager)
:AbstractStringValidator(0, 0, 0, DatatypeValidator::String, manager)
{
    setWhiteSpace(DatatypeValidator::PRESERVE);
}

StringDatatypeValidator::StringDatatypeValidator(
                          DatatypeValidator*            const baseValidator
                        , RefHashTableOf<KVStringPair>* const facets
                        , RefArrayVectorOf<XMLCh>*      const enums
                        , const int                           finalSet
                        , MemoryManager* const                manager)
:AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::String, manager)
{
    setWhiteSpace(DatatypeValidator::PRESERVE);
    init(enums);
}

StringDatatypeValidator::~StringDatatypeValidator()
{}

DatatypeValidator* StringDatatypeValidator::newInstance
(
      RefHashTableOf<KVStringPair>* const facets
    , RefArrayVectorOf<XMLCh>* const      enums
    , const int                           finalSet
    , MemoryManager* const                manager
)
{
    return (DatatypeValidator*) new (manager) StringDatatypeValidator(this, facets, enums, finalSet, manager);
}

StringDatatypeValidator::StringDatatypeValidator(
                          DatatypeValidator*            const baseValidator
                        , RefHashTableOf<KVStringPair>* const facets
                        , const int                           finalSet
                        , const ValidatorType                 type
                        , MemoryManager* const                manager)
:AbstractStringValidator(baseValidator, facets, finalSet, type, manager)
{
    setWhiteSpace(DatatypeValidator::PRESERVE);
    // do not invoke init() here!!!
}

// ---------------------------------------------------------------------------
//  Utilities
// ---------------------------------------------------------------------------
void StringDatatypeValidator::assignAdditionalFacet(const XMLCh* const key
                                                  , const XMLCh* const value)
{
    if (XMLString::equals(key, SchemaSymbols::fgELT_WHITESPACE))
    {
        // whiteSpace = preserve | replace | collapse
        if (XMLString::equals(value, SchemaSymbols::fgWS_PRESERVE))
            setWhiteSpace(DatatypeValidator::PRESERVE);
        else if (XMLString::equals(value, SchemaSymbols::fgWS_REPLACE))
            setWhiteSpace(DatatypeValidator::REPLACE);
        else if (XMLString::equals(value, SchemaSymbols::fgWS_COLLAPSE))
            setWhiteSpace(DatatypeValidator::COLLAPSE);
        else
            ThrowXML1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_WS, value);
        //("whiteSpace value '" + ws + "' must be one of 'preserve', 'replace', 'collapse'.");

        setFacetsDefined(DatatypeValidator::FACET_WHITESPACE);
    }
    else
    {
        ThrowXML1(InvalidDatatypeFacetException
                , XMLExcepts::FACET_Invalid_Tag
                , key);
    }
}

void StringDatatypeValidator::inheritAdditionalFacet()
{
    StringDatatypeValidator *pBaseValidator = (StringDatatypeValidator*) getBaseValidator();

    if (!pBaseValidator)
        return;

    // inherit whitespace
    if (((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) !=0) &&
        ((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) == 0))
    {
        setWhiteSpace(getBaseValidator()->getWSFacet());
        setFacetsDefined(DatatypeValidator::FACET_WHITESPACE);
    }
}

void StringDatatypeValidator::checkAdditionalFacetConstraints() const
{

    StringDatatypeValidator *pBaseValidator = (StringDatatypeValidator*) getBaseValidator();

    if (!pBaseValidator)
        return;

    short    thisWSFacet = getWSFacet();
    short    baseWSFacet = pBaseValidator->getWSFacet();

    // check 4.3.6.c1 error: whitespace
    if (((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0) &&
        ((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0 ))
    {
        if ((baseWSFacet == DatatypeValidator::COLLAPSE) &&
            ((thisWSFacet == DatatypeValidator::PRESERVE) ||
             (thisWSFacet == DatatypeValidator::REPLACE)))
             ThrowXML(InvalidDatatypeFacetException, XMLExcepts::FACET_WS_collapse);

        if ((baseWSFacet == DatatypeValidator::REPLACE) &&
            (thisWSFacet == DatatypeValidator::PRESERVE))
            ThrowXML(InvalidDatatypeFacetException, XMLExcepts::FACET_WS_replace);

        if (((pBaseValidator->getFixed() & DatatypeValidator::FACET_WHITESPACE) !=0) &&
            ( thisWSFacet != baseWSFacet))
        {
            ThrowXML2(InvalidDatatypeFacetException
                        , XMLExcepts::FACET_whitespace_base_fixed
                        , getWSstring(thisWSFacet)
                        , getWSstring(baseWSFacet));
        }
    }

}

void StringDatatypeValidator::checkAdditionalFacet(const XMLCh* const content) const
{
    //
    // check WhiteSpace
    //
    if ((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0 )
    {
        if ( getWSFacet() == DatatypeValidator::REPLACE )
        {
            if (!XMLString::isWSReplaced(content))
                ThrowXML1(InvalidDatatypeValueException, XMLExcepts::VALUE_WS_replaced, content);
        }
        else if ( getWSFacet() == DatatypeValidator::COLLAPSE )
        {
            if (!XMLString::isWSCollapsed(content))
                ThrowXML1(InvalidDatatypeValueException, XMLExcepts::VALUE_WS_collapsed, content);
        }

    }
}

void StringDatatypeValidator::checkValueSpace(const XMLCh* const content)
{}

int StringDatatypeValidator::getLength(const XMLCh* const content) const
{
    return XMLString::stringLen(content);
}

/***
 * Support for Serialization/De-serialization
 ***/

IMPL_XSERIALIZABLE_TOCREATE(StringDatatypeValidator)

void StringDatatypeValidator::serialize(XSerializeEngine& serEng)
{
    AbstractStringValidator::serialize(serEng);
}

XERCES_CPP_NAMESPACE_END

/**
  * End of file StringDatatypeValidator.cpp
  */
<commit_msg>remove unused statics<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Log$
 * Revision 1.10  2003/11/24 05:11:06  neilg
 * remove unused statics
 *
 * Revision 1.9  2003/10/02 19:20:42  peiyongz
 * fWhiteSpace moved to DatatypeValidator
 *
 * Revision 1.8  2003/10/01 01:09:35  knoaman
 * Refactoring of some code to improve performance.
 *
 * Revision 1.7  2003/09/30 21:31:37  peiyongz
 * Implementation of Serialization/Deserialization
 *
 * Revision 1.6  2003/09/29 21:47:35  peiyongz
 * Implementation of Serialization/Deserialization
 *
 * Revision 1.5  2003/05/15 18:53:27  knoaman
 * Partial implementation of the configurable memory manager.
 *
 * Revision 1.4  2002/12/18 14:17:55  gareth
 * Fix to bug #13438. When you eant a vector that calls delete[] on its members you should use RefArrayVectorOf.
 *
 * Revision 1.3  2002/11/04 14:53:28  tng
 * C++ Namespace Support.
 *
 * Revision 1.2  2002/09/24 19:44:40  tng
 * Performance: use XMLString::equals instead of XMLString::compareString
 *
 * Revision 1.1.1.1  2002/02/01 22:22:42  peiyongz
 * sane_include
 *
 * Revision 1.17  2001/10/09 20:54:35  peiyongz
 * init(): take 1 arg.
 *
 * Revision 1.16  2001/09/27 13:51:25  peiyongz
 * DTV Reorganization: ctor/init created to be used by derived class
 *
 * Revision 1.15  2001/09/25 15:58:14  peiyongz
 * Check baseValidator in assignAdditinoalFacet() and inheritAdditionalFacet()
 *
 * Revision 1.14  2001/09/24 15:31:13  peiyongz
 * DTV Reorganization: inherit from AbstractStringValidator
 *
 * Revision 1.12  2001/08/21 18:42:53  peiyongz
 * Bugzilla# 2816: cleanUp() declared with external linkage and called
 *                          before defined as inline
 *
 * Revision 1.11  2001/06/20 17:56:09  peiyongz
 * support for "fixed" option on constrainning facets
 *
 * Revision 1.10  2001/05/29 19:49:36  tng
 * Schema: Constraint Checking Fix in datatypeValidators.  By Pei Yong Zhang.
 *
 * Revision 1.9  2001/05/28 21:11:18  tng
 * Schema: Various DatatypeValidator fix.  By Pei Yong Zhang
 *
 * Revision 1.8  2001/05/23 16:05:11  tng
 * Schema: NormalizedString fix.  By Pei Yong Zhang.
 *
 * Revision 1.7  2001/05/23 15:45:25  tng
 * Schema: NormalizedString fix.  By Pei Yong Zhang.
 *
 * Revision 1.6  2001/05/18 13:36:48  tng
 * Schema: Catch RegularExpression exception and NumberFormatException
 *
 * Revision 1.5  2001/05/18 13:23:51  tng
 * Schema: Exception messages in DatatypeValidator.  By Pei Yong Zhang.
 *
 * Revision 1.4  2001/05/16 14:33:40  tng
 * Schema Constraint checking fix.
 *
 * Revision 1.3  2001/05/11 17:17:28  tng
 * Schema: DatatypeValidator fixes.  By Pei Yong Zhang.
 *
 * Revision 1.2  2001/05/11 13:27:29  tng
 * Copyright update.
 *
 * Revision 1.1  2001/05/09 18:43:42  tng
 * Add StringDatatypeValidator and BooleanDatatypeValidator.  By Pei Yong Zhang.
 *
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/validators/datatype/StringDatatypeValidator.hpp>
#include <xercesc/validators/schema/SchemaSymbols.hpp>
#include <xercesc/validators/datatype/InvalidDatatypeFacetException.hpp>
#include <xercesc/validators/datatype/InvalidDatatypeValueException.hpp>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  Constructors and Destructor
// ---------------------------------------------------------------------------
StringDatatypeValidator::StringDatatypeValidator(MemoryManager* const manager)
:AbstractStringValidator(0, 0, 0, DatatypeValidator::String, manager)
{
    setWhiteSpace(DatatypeValidator::PRESERVE);
}

StringDatatypeValidator::StringDatatypeValidator(
                          DatatypeValidator*            const baseValidator
                        , RefHashTableOf<KVStringPair>* const facets
                        , RefArrayVectorOf<XMLCh>*      const enums
                        , const int                           finalSet
                        , MemoryManager* const                manager)
:AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::String, manager)
{
    setWhiteSpace(DatatypeValidator::PRESERVE);
    init(enums);
}

StringDatatypeValidator::~StringDatatypeValidator()
{}

DatatypeValidator* StringDatatypeValidator::newInstance
(
      RefHashTableOf<KVStringPair>* const facets
    , RefArrayVectorOf<XMLCh>* const      enums
    , const int                           finalSet
    , MemoryManager* const                manager
)
{
    return (DatatypeValidator*) new (manager) StringDatatypeValidator(this, facets, enums, finalSet, manager);
}

StringDatatypeValidator::StringDatatypeValidator(
                          DatatypeValidator*            const baseValidator
                        , RefHashTableOf<KVStringPair>* const facets
                        , const int                           finalSet
                        , const ValidatorType                 type
                        , MemoryManager* const                manager)
:AbstractStringValidator(baseValidator, facets, finalSet, type, manager)
{
    setWhiteSpace(DatatypeValidator::PRESERVE);
    // do not invoke init() here!!!
}

// ---------------------------------------------------------------------------
//  Utilities
// ---------------------------------------------------------------------------
void StringDatatypeValidator::assignAdditionalFacet(const XMLCh* const key
                                                  , const XMLCh* const value)
{
    if (XMLString::equals(key, SchemaSymbols::fgELT_WHITESPACE))
    {
        // whiteSpace = preserve | replace | collapse
        if (XMLString::equals(value, SchemaSymbols::fgWS_PRESERVE))
            setWhiteSpace(DatatypeValidator::PRESERVE);
        else if (XMLString::equals(value, SchemaSymbols::fgWS_REPLACE))
            setWhiteSpace(DatatypeValidator::REPLACE);
        else if (XMLString::equals(value, SchemaSymbols::fgWS_COLLAPSE))
            setWhiteSpace(DatatypeValidator::COLLAPSE);
        else
            ThrowXML1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_WS, value);
        //("whiteSpace value '" + ws + "' must be one of 'preserve', 'replace', 'collapse'.");

        setFacetsDefined(DatatypeValidator::FACET_WHITESPACE);
    }
    else
    {
        ThrowXML1(InvalidDatatypeFacetException
                , XMLExcepts::FACET_Invalid_Tag
                , key);
    }
}

void StringDatatypeValidator::inheritAdditionalFacet()
{
    StringDatatypeValidator *pBaseValidator = (StringDatatypeValidator*) getBaseValidator();

    if (!pBaseValidator)
        return;

    // inherit whitespace
    if (((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) !=0) &&
        ((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) == 0))
    {
        setWhiteSpace(getBaseValidator()->getWSFacet());
        setFacetsDefined(DatatypeValidator::FACET_WHITESPACE);
    }
}

void StringDatatypeValidator::checkAdditionalFacetConstraints() const
{

    StringDatatypeValidator *pBaseValidator = (StringDatatypeValidator*) getBaseValidator();

    if (!pBaseValidator)
        return;

    short    thisWSFacet = getWSFacet();
    short    baseWSFacet = pBaseValidator->getWSFacet();

    // check 4.3.6.c1 error: whitespace
    if (((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0) &&
        ((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0 ))
    {
        if ((baseWSFacet == DatatypeValidator::COLLAPSE) &&
            ((thisWSFacet == DatatypeValidator::PRESERVE) ||
             (thisWSFacet == DatatypeValidator::REPLACE)))
             ThrowXML(InvalidDatatypeFacetException, XMLExcepts::FACET_WS_collapse);

        if ((baseWSFacet == DatatypeValidator::REPLACE) &&
            (thisWSFacet == DatatypeValidator::PRESERVE))
            ThrowXML(InvalidDatatypeFacetException, XMLExcepts::FACET_WS_replace);

        if (((pBaseValidator->getFixed() & DatatypeValidator::FACET_WHITESPACE) !=0) &&
            ( thisWSFacet != baseWSFacet))
        {
            ThrowXML2(InvalidDatatypeFacetException
                        , XMLExcepts::FACET_whitespace_base_fixed
                        , getWSstring(thisWSFacet)
                        , getWSstring(baseWSFacet));
        }
    }

}

void StringDatatypeValidator::checkAdditionalFacet(const XMLCh* const content) const
{
    //
    // check WhiteSpace
    //
    if ((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0 )
    {
        if ( getWSFacet() == DatatypeValidator::REPLACE )
        {
            if (!XMLString::isWSReplaced(content))
                ThrowXML1(InvalidDatatypeValueException, XMLExcepts::VALUE_WS_replaced, content);
        }
        else if ( getWSFacet() == DatatypeValidator::COLLAPSE )
        {
            if (!XMLString::isWSCollapsed(content))
                ThrowXML1(InvalidDatatypeValueException, XMLExcepts::VALUE_WS_collapsed, content);
        }

    }
}

void StringDatatypeValidator::checkValueSpace(const XMLCh* const content)
{}

int StringDatatypeValidator::getLength(const XMLCh* const content) const
{
    return XMLString::stringLen(content);
}

/***
 * Support for Serialization/De-serialization
 ***/

IMPL_XSERIALIZABLE_TOCREATE(StringDatatypeValidator)

void StringDatatypeValidator::serialize(XSerializeEngine& serEng)
{
    AbstractStringValidator::serialize(serEng);
}

XERCES_CPP_NAMESPACE_END

/**
  * End of file StringDatatypeValidator.cpp
  */
<|endoftext|>


<commit_before>[#ftl]
#include "${headerFileName}"

// Constructor from other reference
${classname}::${classname}(JNIEnv *env, jobject ref)
: m_env(env)
, m_class(NewGlobalRef(findClass(env, m_name)))
, m_ref(NewGlobalRef(env, ref))
{
	// TODO: Assertion of type
}

// Constructor from other reference
${classname}::${classname}(const ${classname}& other)
: m_env(other.env)
, m_class(NewGlobalRef(findClass(env, m_name)))
, m_ref(NewGlobalRef(other.env, other.ref))
{
	// TODO: Assertion of type
}

// TODO: Constructor definitions

// Destructor
${classname}::~${classname}()
{
	DeleteGlobalRef(env, m_class);
	DeleteGlobalRef(env, m_ref);
}

char ${classname}::m_name = "${qualifiedName}";

[#list methods as method]
${method.returnType} ${classname}::${method.name}([#list method.parameters as parameter]
	 ${parameter.type} ${parameter.name}[#sep], [/#sep][/#list]);
{
	static const char[] name = "${method.name}";
	static const char[] signature = "${method.signature}";
	static const jmethodID mid = GetMethodId(m_env, m_class, signature);

	[#if !method.void]return [/#if]${method.jniFunction}(
		m_env, m_ref, mid[#list method.parameters as parameter][#if parameter?is_first],
		[/#if]${parameter.name}[#sep], [/#sep][/#list]);
}

[/#list]
<commit_msg>Changed template so that method id is not a static variable any longer<commit_after>[#ftl]
#include "${headerFileName}"

// Constructor from other reference
${classname}::${classname}(JNIEnv *env, jobject ref)
: m_env(env)
, m_class(NewGlobalRef(findClass(env, m_name)))
, m_ref(NewGlobalRef(env, ref))
{
	// TODO: Assertion of type
}

// Constructor from other reference
${classname}::${classname}(const ${classname}& other)
: m_env(other.env)
, m_class(NewGlobalRef(findClass(env, m_name)))
, m_ref(NewGlobalRef(other.env, other.ref))
{
	// TODO: Assertion of type
}

// TODO: Constructor definitions

// Destructor
${classname}::~${classname}()
{
	DeleteGlobalRef(env, m_class);
	DeleteGlobalRef(env, m_ref);
}

char ${classname}::m_name = "${qualifiedName}";

[#list methods as method]
${method.returnType} ${classname}::${method.name}([#list method.parameters as parameter]
	 ${parameter.type} ${parameter.name}[#sep], [/#sep][/#list]);
{
	static const char[] name = "${method.name}";
	static const char[] signature = "${method.signature}";
	jmethodID mid = GetMethodId(m_env, m_class, name, signature);

	[#if !method.void]return [/#if]${method.jniFunction}(
		m_env, m_ref, mid[#list method.parameters as parameter][#if parameter?is_first],
		[/#if]${parameter.name}[#sep], [/#sep][/#list]);
}

[/#list]
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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 "google/cloud/pubsub/snapshot_mutation_builder.h"
#include "google/cloud/pubsub/subscription.h"
#include "google/cloud/pubsub/subscription_admin_client.h"
#include "google/cloud/pubsub/testing/random_names.h"
#include "google/cloud/pubsub/testing/test_retry_policies.h"
#include "google/cloud/pubsub/topic_admin_client.h"
#include "google/cloud/pubsub/version.h"
#include "google/cloud/internal/getenv.h"
#include "google/cloud/internal/random.h"
#include "google/cloud/testing_util/assert_ok.h"
#include "google/cloud/testing_util/is_proto_equal.h"
#include "google/cloud/testing_util/scoped_environment.h"
#include "google/cloud/testing_util/status_matchers.h"
#include <gmock/gmock.h>

namespace google {
namespace cloud {
namespace pubsub {
inline namespace GOOGLE_CLOUD_CPP_PUBSUB_NS {
namespace {

using ::google::cloud::pubsub_testing::TestBackoffPolicy;
using ::google::cloud::pubsub_testing::TestRetryPolicy;
using ::google::cloud::testing_util::IsProtoEqual;
using ::google::cloud::testing_util::ScopedEnvironment;
using ::google::cloud::testing_util::StatusIs;
using ::testing::AnyOf;
using ::testing::Contains;
using ::testing::Not;

bool UsingEmulator() {
  return google::cloud::internal::GetEnv("PUBSUB_EMULATOR_HOST").has_value();
}

TEST(SubscriptionAdminIntegrationTest, SubscriptionCRUD) {
  auto project_id =
      google::cloud::internal::GetEnv("GOOGLE_CLOUD_PROJECT").value_or("");
  ASSERT_FALSE(project_id.empty());

  auto subscription_names = [](SubscriptionAdminClient client,
                               std::string const& project_id) {
    std::vector<std::string> names;
    for (auto& subscription : client.ListSubscriptions(project_id)) {
      EXPECT_STATUS_OK(subscription);
      if (!subscription) break;
      names.push_back(subscription->name());
    }
    return names;
  };

  auto snapshot_names = [](SubscriptionAdminClient client,
                           std::string const& project_id) {
    std::vector<std::string> names;
    for (auto& snapshot : client.ListSnapshots(project_id)) {
      EXPECT_STATUS_OK(snapshot);
      if (!snapshot) break;
      names.push_back(snapshot->name());
    }
    return names;
  };

  auto generator = google::cloud::internal::MakeDefaultPRNG();
  Topic topic(project_id, pubsub_testing::RandomTopicId(generator));
  Subscription subscription(project_id,
                            pubsub_testing::RandomSubscriptionId(generator));

  auto topic_admin = TopicAdminClient(MakeTopicAdminConnection());
  auto subscription_admin =
      SubscriptionAdminClient(MakeSubscriptionAdminConnection());

  EXPECT_THAT(subscription_names(subscription_admin, project_id),
              Not(Contains(subscription.FullName())));

  auto topic_metadata = topic_admin.CreateTopic(TopicBuilder(topic));
  ASSERT_THAT(topic_metadata, AnyOf(StatusIs(StatusCode::kOk),
                                    StatusIs(StatusCode::kAlreadyExists)));

  struct Cleanup {
    std::function<void()> action;
    explicit Cleanup(std::function<void()> a) : action(std::move(a)) {}
    ~Cleanup() { action(); }
  };
  Cleanup cleanup_topic{
      [&topic_admin, &topic] { topic_admin.DeleteTopic(topic); }};

  auto endpoint = "https://" + project_id + ".appspot.com/push";
  auto create_response = subscription_admin.CreateSubscription(
      topic, subscription,
      SubscriptionBuilder{}.set_push_config(
          PushConfigBuilder{}.set_push_endpoint(endpoint)));
  ASSERT_THAT(create_response, AnyOf(StatusIs(StatusCode::kOk),
                                     StatusIs(StatusCode::kAlreadyExists)));

  auto get_response = subscription_admin.GetSubscription(subscription);
  ASSERT_STATUS_OK(get_response);
  // We cannot compare the full protos because for push configs `Create...()`
  // returns less information than `Get` :shrug:
  EXPECT_EQ(create_response->name(), get_response->name());

  auto constexpr kTestDeadlineSeconds = 20;
  auto update_response = subscription_admin.UpdateSubscription(
      subscription, SubscriptionBuilder{}.set_ack_deadline(
                        std::chrono::seconds(kTestDeadlineSeconds)));
  ASSERT_STATUS_OK(update_response);
  EXPECT_EQ(kTestDeadlineSeconds, update_response->ack_deadline_seconds());

  EXPECT_THAT(subscription_names(subscription_admin, project_id),
              Contains(subscription.FullName()));

  auto modify_push_config_response = subscription_admin.ModifyPushSubscription(
      subscription, PushConfigBuilder{});
  EXPECT_STATUS_OK(modify_push_config_response);

  auto const topic_subscriptions = [&] {
    std::vector<std::string> names;
    for (auto& name : topic_admin.ListTopicSubscriptions(topic)) {
      EXPECT_STATUS_OK(name);
      names.push_back(std::move(*name));
    }
    return names;
  }();
  EXPECT_THAT(topic_subscriptions, Contains(subscription.FullName()));

  // To create snapshots we need at least one subscription, so we test those
  // here too.
  // TODO(#4792) - cannot test server-side assigned names, the emulator lacks
  //    support for them.
  Snapshot snapshot(project_id, pubsub_testing::RandomSnapshotId(generator));
  auto create_snapshot_response =
      subscription_admin.CreateSnapshot(subscription, snapshot);
  ASSERT_STATUS_OK(create_snapshot_response);
  EXPECT_EQ(snapshot.FullName(), create_snapshot_response->name());

  auto const topic_snapshots = [&] {
    std::vector<std::string> names;
    for (auto& name : topic_admin.ListTopicSnapshots(topic)) {
      EXPECT_STATUS_OK(name);
      names.push_back(std::move(*name));
    }
    return names;
  }();
  EXPECT_THAT(topic_snapshots, Contains(snapshot.FullName()));

  auto get_snapshot_response = subscription_admin.GetSnapshot(snapshot);
  ASSERT_STATUS_OK(get_snapshot_response);
  EXPECT_THAT(*get_snapshot_response, IsProtoEqual(*create_snapshot_response));

  // TODO(#4792) - the emulator does not support UpdateSnapshot()
  if (!UsingEmulator()) {
    auto update_snapshot_response = subscription_admin.UpdateSnapshot(
        snapshot,
        SnapshotMutationBuilder{}.add_label("test-label", "test-value"));
    ASSERT_STATUS_OK(update_snapshot_response);
    EXPECT_FALSE(update_snapshot_response->labels().empty());
  }

  auto seek_response = subscription_admin.Seek(subscription, snapshot);
  EXPECT_STATUS_OK(seek_response);

  EXPECT_THAT(snapshot_names(subscription_admin, project_id),
              Contains(snapshot.FullName()));
  auto delete_snapshot = subscription_admin.DeleteSnapshot(snapshot);
  EXPECT_STATUS_OK(delete_snapshot);
  EXPECT_THAT(snapshot_names(subscription_admin, project_id),
              Not(Contains(snapshot.FullName())));

  // TODO(#4792) - the emulator does not support DetachSubscription()
  // TODO(#4850) - completely disabled as we are not in the EAP
  //  if (!UsingEmulator()) {
  //    auto detach_response = topic_admin.DetachSubscription(subscription);
  //    ASSERT_STATUS_OK(detach_response);
  //  }

  auto delete_response = subscription_admin.DeleteSubscription(subscription);
  EXPECT_THAT(delete_response, AnyOf(StatusIs(StatusCode::kOk),
                                     StatusIs(StatusCode::kNotFound)));

  EXPECT_THAT(subscription_names(subscription_admin, project_id),
              Not(Contains(subscription.FullName())));
}

TEST(SubscriptionAdminIntegrationTest, CreateSubscriptionFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto create_response = client.CreateSubscription(
      Topic("--invalid-project--", "--invalid-topic--"),
      Subscription("--invalid-project--", "--invalid-subscription--"));
  ASSERT_FALSE(create_response.ok());
}

TEST(SubscriptionAdminIntegrationTest, GetSubscriptionFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto create_response = client.GetSubscription(
      Subscription("--invalid-project--", "--invalid-subscription--"));
  ASSERT_FALSE(create_response.ok());
}

TEST(SubscriptionAdminIntegrationTest, UpdateSubscriptionFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto create_response = client.UpdateSubscription(
      Subscription("--invalid-project--", "--invalid-subscription--"),
      SubscriptionBuilder{}.set_ack_deadline(std::chrono::seconds(20)));
  ASSERT_FALSE(create_response.ok());
}

TEST(SubscriptionAdminIntegrationTest, ListSubscriptionsFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto list = client.ListSubscriptions("--invalid-project--");
  auto i = list.begin();
  EXPECT_FALSE(i == list.end());
  EXPECT_FALSE(*i);
}

TEST(SubscriptionAdminIntegrationTest, DeleteSubscriptionFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto delete_response = client.DeleteSubscription(
      Subscription("--invalid-project--", "--invalid-subscription--"));
  ASSERT_FALSE(delete_response.ok());
}

TEST(SubscriptionAdminIntegrationTest, ModifyPushConfigFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto delete_response = client.ModifyPushSubscription(
      Subscription("--invalid-project--", "--invalid-subscription--"),
      PushConfigBuilder{});
  ASSERT_FALSE(delete_response.ok());
}

TEST(SubscriptionAdminIntegrationTest, CreateSnapshotFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto response = client.CreateSnapshot(
      Subscription("--invalid-project--", "--invalid-subscription--"));
  ASSERT_FALSE(response.ok());
}

TEST(SubscriptionAdminIntegrationTest, GetSnapshotFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto response = client.GetSnapshot(
      Snapshot("--invalid-project--", "--invalid-snapshot--"));
  ASSERT_FALSE(response.ok());
}

TEST(SubscriptionAdminIntegrationTest, ListSnapshotsFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto list = client.ListSnapshots("--invalid-project--");
  auto i = list.begin();
  EXPECT_FALSE(i == list.end());
  EXPECT_FALSE(*i);
}

TEST(SubscriptionAdminIntegrationTest, UpdateSnapshotFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto response = client.UpdateSnapshot(
      Snapshot("--invalid-project--", "--invalid-snapshot--"),
      SnapshotMutationBuilder{}.clear_labels());
  ASSERT_FALSE(response.ok());
}

TEST(SubscriptionAdminIntegrationTest, DeleteSnapshotFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto response = client.DeleteSnapshot(
      Snapshot("--invalid-project--", "--invalid-snapshot--"));
  ASSERT_FALSE(response.ok());
}

TEST(SubscriptionAdminIntegrationTest, SeekFailureTimestamp) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto response = client.Seek(
      Subscription("--invalid-project--", "--invalid-subscription--"),
      std::chrono::system_clock::now());
  ASSERT_FALSE(response.ok());
}

TEST(SubscriptionAdminIntegrationTest, SeekFailureSnapshot) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto response = client.Seek(
      Subscription("--invalid-project--", "--invalid-subscription--"),
      Snapshot("--invalid-project--", "--invalid-snapshot--"));
  ASSERT_FALSE(response.ok());
}

}  // namespace
}  // namespace GOOGLE_CLOUD_CPP_PUBSUB_NS
}  // namespace pubsub
}  // namespace cloud
}  // namespace google
<commit_msg>test(pubsub): enable DetachSubscription test (#5243)<commit_after>// Copyright 2020 Google LLC
//
// 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 "google/cloud/pubsub/snapshot_mutation_builder.h"
#include "google/cloud/pubsub/subscription.h"
#include "google/cloud/pubsub/subscription_admin_client.h"
#include "google/cloud/pubsub/testing/random_names.h"
#include "google/cloud/pubsub/testing/test_retry_policies.h"
#include "google/cloud/pubsub/topic_admin_client.h"
#include "google/cloud/pubsub/version.h"
#include "google/cloud/internal/getenv.h"
#include "google/cloud/internal/random.h"
#include "google/cloud/testing_util/assert_ok.h"
#include "google/cloud/testing_util/is_proto_equal.h"
#include "google/cloud/testing_util/scoped_environment.h"
#include "google/cloud/testing_util/status_matchers.h"
#include <gmock/gmock.h>

namespace google {
namespace cloud {
namespace pubsub {
inline namespace GOOGLE_CLOUD_CPP_PUBSUB_NS {
namespace {

using ::google::cloud::pubsub_testing::TestBackoffPolicy;
using ::google::cloud::pubsub_testing::TestRetryPolicy;
using ::google::cloud::testing_util::IsProtoEqual;
using ::google::cloud::testing_util::ScopedEnvironment;
using ::google::cloud::testing_util::StatusIs;
using ::testing::AnyOf;
using ::testing::Contains;
using ::testing::Not;

bool UsingEmulator() {
  return google::cloud::internal::GetEnv("PUBSUB_EMULATOR_HOST").has_value();
}

TEST(SubscriptionAdminIntegrationTest, SubscriptionCRUD) {
  auto project_id =
      google::cloud::internal::GetEnv("GOOGLE_CLOUD_PROJECT").value_or("");
  ASSERT_FALSE(project_id.empty());

  auto subscription_names = [](SubscriptionAdminClient client,
                               std::string const& project_id) {
    std::vector<std::string> names;
    for (auto& subscription : client.ListSubscriptions(project_id)) {
      EXPECT_STATUS_OK(subscription);
      if (!subscription) break;
      names.push_back(subscription->name());
    }
    return names;
  };

  auto snapshot_names = [](SubscriptionAdminClient client,
                           std::string const& project_id) {
    std::vector<std::string> names;
    for (auto& snapshot : client.ListSnapshots(project_id)) {
      EXPECT_STATUS_OK(snapshot);
      if (!snapshot) break;
      names.push_back(snapshot->name());
    }
    return names;
  };

  auto generator = google::cloud::internal::MakeDefaultPRNG();
  Topic topic(project_id, pubsub_testing::RandomTopicId(generator));
  Subscription subscription(project_id,
                            pubsub_testing::RandomSubscriptionId(generator));

  auto topic_admin = TopicAdminClient(MakeTopicAdminConnection());
  auto subscription_admin =
      SubscriptionAdminClient(MakeSubscriptionAdminConnection());

  EXPECT_THAT(subscription_names(subscription_admin, project_id),
              Not(Contains(subscription.FullName())));

  auto topic_metadata = topic_admin.CreateTopic(TopicBuilder(topic));
  ASSERT_THAT(topic_metadata, AnyOf(StatusIs(StatusCode::kOk),
                                    StatusIs(StatusCode::kAlreadyExists)));

  struct Cleanup {
    std::function<void()> action;
    explicit Cleanup(std::function<void()> a) : action(std::move(a)) {}
    ~Cleanup() { action(); }
  };
  Cleanup cleanup_topic{
      [&topic_admin, &topic] { topic_admin.DeleteTopic(topic); }};

  auto endpoint = "https://" + project_id + ".appspot.com/push";
  auto create_response = subscription_admin.CreateSubscription(
      topic, subscription,
      SubscriptionBuilder{}.set_push_config(
          PushConfigBuilder{}.set_push_endpoint(endpoint)));
  ASSERT_THAT(create_response, AnyOf(StatusIs(StatusCode::kOk),
                                     StatusIs(StatusCode::kAlreadyExists)));

  auto get_response = subscription_admin.GetSubscription(subscription);
  ASSERT_STATUS_OK(get_response);
  // We cannot compare the full protos because for push configs `Create...()`
  // returns less information than `Get` :shrug:
  EXPECT_EQ(create_response->name(), get_response->name());

  auto constexpr kTestDeadlineSeconds = 20;
  auto update_response = subscription_admin.UpdateSubscription(
      subscription, SubscriptionBuilder{}.set_ack_deadline(
                        std::chrono::seconds(kTestDeadlineSeconds)));
  ASSERT_STATUS_OK(update_response);
  EXPECT_EQ(kTestDeadlineSeconds, update_response->ack_deadline_seconds());

  EXPECT_THAT(subscription_names(subscription_admin, project_id),
              Contains(subscription.FullName()));

  auto modify_push_config_response = subscription_admin.ModifyPushSubscription(
      subscription, PushConfigBuilder{});
  EXPECT_STATUS_OK(modify_push_config_response);

  auto const topic_subscriptions = [&] {
    std::vector<std::string> names;
    for (auto& name : topic_admin.ListTopicSubscriptions(topic)) {
      EXPECT_STATUS_OK(name);
      names.push_back(std::move(*name));
    }
    return names;
  }();
  EXPECT_THAT(topic_subscriptions, Contains(subscription.FullName()));

  // To create snapshots we need at least one subscription, so we test those
  // here too.
  // TODO(#4792) - cannot test server-side assigned names, the emulator lacks
  //    support for them.
  Snapshot snapshot(project_id, pubsub_testing::RandomSnapshotId(generator));
  auto create_snapshot_response =
      subscription_admin.CreateSnapshot(subscription, snapshot);
  ASSERT_STATUS_OK(create_snapshot_response);
  EXPECT_EQ(snapshot.FullName(), create_snapshot_response->name());

  auto const topic_snapshots = [&] {
    std::vector<std::string> names;
    for (auto& name : topic_admin.ListTopicSnapshots(topic)) {
      EXPECT_STATUS_OK(name);
      names.push_back(std::move(*name));
    }
    return names;
  }();
  EXPECT_THAT(topic_snapshots, Contains(snapshot.FullName()));

  auto get_snapshot_response = subscription_admin.GetSnapshot(snapshot);
  ASSERT_STATUS_OK(get_snapshot_response);
  EXPECT_THAT(*get_snapshot_response, IsProtoEqual(*create_snapshot_response));

  // TODO(#4792) - the emulator does not support UpdateSnapshot()
  if (!UsingEmulator()) {
    auto update_snapshot_response = subscription_admin.UpdateSnapshot(
        snapshot,
        SnapshotMutationBuilder{}.add_label("test-label", "test-value"));
    ASSERT_STATUS_OK(update_snapshot_response);
    EXPECT_FALSE(update_snapshot_response->labels().empty());
  }

  auto seek_response = subscription_admin.Seek(subscription, snapshot);
  EXPECT_STATUS_OK(seek_response);

  EXPECT_THAT(snapshot_names(subscription_admin, project_id),
              Contains(snapshot.FullName()));
  auto delete_snapshot = subscription_admin.DeleteSnapshot(snapshot);
  EXPECT_STATUS_OK(delete_snapshot);
  EXPECT_THAT(snapshot_names(subscription_admin, project_id),
              Not(Contains(snapshot.FullName())));

  // TODO(#4792) - the emulator does not support DetachSubscription()
  if (!UsingEmulator()) {
    auto detach_response = topic_admin.DetachSubscription(subscription);
    ASSERT_STATUS_OK(detach_response);
  }

  auto delete_response = subscription_admin.DeleteSubscription(subscription);
  EXPECT_THAT(delete_response, AnyOf(StatusIs(StatusCode::kOk),
                                     StatusIs(StatusCode::kNotFound)));

  EXPECT_THAT(subscription_names(subscription_admin, project_id),
              Not(Contains(subscription.FullName())));
}

TEST(SubscriptionAdminIntegrationTest, CreateSubscriptionFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto create_response = client.CreateSubscription(
      Topic("--invalid-project--", "--invalid-topic--"),
      Subscription("--invalid-project--", "--invalid-subscription--"));
  ASSERT_FALSE(create_response.ok());
}

TEST(SubscriptionAdminIntegrationTest, GetSubscriptionFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto create_response = client.GetSubscription(
      Subscription("--invalid-project--", "--invalid-subscription--"));
  ASSERT_FALSE(create_response.ok());
}

TEST(SubscriptionAdminIntegrationTest, UpdateSubscriptionFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto create_response = client.UpdateSubscription(
      Subscription("--invalid-project--", "--invalid-subscription--"),
      SubscriptionBuilder{}.set_ack_deadline(std::chrono::seconds(20)));
  ASSERT_FALSE(create_response.ok());
}

TEST(SubscriptionAdminIntegrationTest, ListSubscriptionsFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto list = client.ListSubscriptions("--invalid-project--");
  auto i = list.begin();
  EXPECT_FALSE(i == list.end());
  EXPECT_FALSE(*i);
}

TEST(SubscriptionAdminIntegrationTest, DeleteSubscriptionFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto delete_response = client.DeleteSubscription(
      Subscription("--invalid-project--", "--invalid-subscription--"));
  ASSERT_FALSE(delete_response.ok());
}

TEST(SubscriptionAdminIntegrationTest, ModifyPushConfigFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto delete_response = client.ModifyPushSubscription(
      Subscription("--invalid-project--", "--invalid-subscription--"),
      PushConfigBuilder{});
  ASSERT_FALSE(delete_response.ok());
}

TEST(SubscriptionAdminIntegrationTest, CreateSnapshotFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto response = client.CreateSnapshot(
      Subscription("--invalid-project--", "--invalid-subscription--"));
  ASSERT_FALSE(response.ok());
}

TEST(SubscriptionAdminIntegrationTest, GetSnapshotFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto response = client.GetSnapshot(
      Snapshot("--invalid-project--", "--invalid-snapshot--"));
  ASSERT_FALSE(response.ok());
}

TEST(SubscriptionAdminIntegrationTest, ListSnapshotsFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto list = client.ListSnapshots("--invalid-project--");
  auto i = list.begin();
  EXPECT_FALSE(i == list.end());
  EXPECT_FALSE(*i);
}

TEST(SubscriptionAdminIntegrationTest, UpdateSnapshotFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto response = client.UpdateSnapshot(
      Snapshot("--invalid-project--", "--invalid-snapshot--"),
      SnapshotMutationBuilder{}.clear_labels());
  ASSERT_FALSE(response.ok());
}

TEST(SubscriptionAdminIntegrationTest, DeleteSnapshotFailure) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto response = client.DeleteSnapshot(
      Snapshot("--invalid-project--", "--invalid-snapshot--"));
  ASSERT_FALSE(response.ok());
}

TEST(SubscriptionAdminIntegrationTest, SeekFailureTimestamp) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto response = client.Seek(
      Subscription("--invalid-project--", "--invalid-subscription--"),
      std::chrono::system_clock::now());
  ASSERT_FALSE(response.ok());
}

TEST(SubscriptionAdminIntegrationTest, SeekFailureSnapshot) {
  // Use an invalid endpoint to force a connection error.
  ScopedEnvironment env("PUBSUB_EMULATOR_HOST", "localhost:1");
  auto client = SubscriptionAdminClient(MakeSubscriptionAdminConnection(
      {}, TestRetryPolicy(), TestBackoffPolicy()));
  auto response = client.Seek(
      Subscription("--invalid-project--", "--invalid-subscription--"),
      Snapshot("--invalid-project--", "--invalid-snapshot--"));
  ASSERT_FALSE(response.ok());
}

}  // namespace
}  // namespace GOOGLE_CLOUD_CPP_PUBSUB_NS
}  // namespace pubsub
}  // namespace cloud
}  // namespace google
<|endoftext|>


<commit_before>// Copyright (c) 2011-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <qt/walletframe.h>
#include <qt/walletmodel.h>

#include <qt/bitcoingui.h>
#include <qt/walletview.h>

#include <cassert>
#include <cstdio>

#include <QHBoxLayout>
#include <QLabel>

WalletFrame::WalletFrame(const PlatformStyle *_platformStyle, BitcoinGUI *_gui) :
    QFrame(_gui),
    gui(_gui),
    platformStyle(_platformStyle)
{
    // Leave HBox hook for adding a list view later
    QHBoxLayout *walletFrameLayout = new QHBoxLayout(this);
    setContentsMargins(0,0,0,0);
    walletStack = new QStackedWidget(this);
    walletFrameLayout->setContentsMargins(0,0,0,0);
    walletFrameLayout->addWidget(walletStack);

    QLabel *noWallet = new QLabel(tr("No wallet has been loaded."));
    noWallet->setAlignment(Qt::AlignCenter);
    walletStack->addWidget(noWallet);
}

WalletFrame::~WalletFrame()
{
}

void WalletFrame::setClientModel(ClientModel *_clientModel)
{
    this->clientModel = _clientModel;
}

bool WalletFrame::addWallet(WalletModel *walletModel)
{
    if (!gui || !clientModel || !walletModel) {
        return false;
    }

    const QString name = walletModel->getWalletName();
    if (mapWalletViews.count(name) > 0) {
        return false;
    }

    WalletView *walletView = new WalletView(platformStyle, this);
    walletView->setBitcoinGUI(gui);
    walletView->setClientModel(clientModel);
    walletView->setWalletModel(walletModel);
    walletView->showOutOfSyncWarning(bOutOfSync);

    WalletView* current_wallet_view = currentWalletView();
    if (current_wallet_view) {
        walletView->setCurrentIndex(current_wallet_view->currentIndex());
    } else {
        walletView->gotoOverviewPage();
    }

    walletStack->addWidget(walletView);
    mapWalletViews[name] = walletView;

    // Ensure a walletView is able to show the main window
    connect(walletView, SIGNAL(showNormalIfMinimized()), gui, SLOT(showNormalIfMinimized()));

    connect(walletView, SIGNAL(outOfSyncWarningClicked()), this, SLOT(outOfSyncWarningClicked()));

    return true;
}

bool WalletFrame::setCurrentWallet(const QString& name)
{
    if (mapWalletViews.count(name) == 0)
        return false;

    WalletView *walletView = mapWalletViews.value(name);
    walletStack->setCurrentWidget(walletView);
    assert(walletView);
    walletView->updateEncryptionStatus();
    return true;
}

bool WalletFrame::removeWallet(const QString &name)
{
    if (mapWalletViews.count(name) == 0)
        return false;

    WalletView *walletView = mapWalletViews.take(name);
    walletStack->removeWidget(walletView);
    return true;
}

void WalletFrame::removeAllWallets()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        walletStack->removeWidget(i.value());
    mapWalletViews.clear();
}

bool WalletFrame::handlePaymentRequest(const SendCoinsRecipient &recipient)
{
    WalletView *walletView = currentWalletView();
    if (!walletView)
        return false;

    return walletView->handlePaymentRequest(recipient);
}

void WalletFrame::showOutOfSyncWarning(bool fShow)
{
    bOutOfSync = fShow;
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->showOutOfSyncWarning(fShow);
}

void WalletFrame::gotoOverviewPage()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoOverviewPage();
}

void WalletFrame::gotoHistoryPage()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoHistoryPage();
}

void WalletFrame::gotoMultisigPage()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoMultisigPage();
}

void WalletFrame::gotoMintingPage()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoMintingPage();
}

void WalletFrame::gotoReceiveCoinsPage()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoReceiveCoinsPage();
}

void WalletFrame::gotoSendCoinsPage(QString addr)
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoSendCoinsPage(addr);
}

void WalletFrame::gotoSignMessageTab(QString addr)
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->gotoSignMessageTab(addr);
}

void WalletFrame::gotoVerifyMessageTab(QString addr)
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->gotoVerifyMessageTab(addr);
}

void WalletFrame::encryptWallet(bool status)
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->encryptWallet(status);
}

void WalletFrame::decryptForMinting(bool status)
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->decryptForMinting(status);
}

void WalletFrame::backupWallet()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->backupWallet();
}

void WalletFrame::changePassphrase()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->changePassphrase();
}

void WalletFrame::unlockWallet()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->unlockWallet();
}

void WalletFrame::usedSendingAddresses()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->usedSendingAddresses();
}

void WalletFrame::usedReceivingAddresses()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->usedReceivingAddresses();
}

WalletView *WalletFrame::currentWalletView()
{
    return qobject_cast<WalletView*>(walletStack->currentWidget());
}

void WalletFrame::outOfSyncWarningClicked()
{
    Q_EMIT requestedSyncWarningInfo();
}
<commit_msg>bugfix: Delete walletView in WalletFrame::removeWallet<commit_after>// Copyright (c) 2011-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <qt/walletframe.h>
#include <qt/walletmodel.h>

#include <qt/bitcoingui.h>
#include <qt/walletview.h>

#include <cassert>
#include <cstdio>

#include <QHBoxLayout>
#include <QLabel>

WalletFrame::WalletFrame(const PlatformStyle *_platformStyle, BitcoinGUI *_gui) :
    QFrame(_gui),
    gui(_gui),
    platformStyle(_platformStyle)
{
    // Leave HBox hook for adding a list view later
    QHBoxLayout *walletFrameLayout = new QHBoxLayout(this);
    setContentsMargins(0,0,0,0);
    walletStack = new QStackedWidget(this);
    walletFrameLayout->setContentsMargins(0,0,0,0);
    walletFrameLayout->addWidget(walletStack);

    QLabel *noWallet = new QLabel(tr("No wallet has been loaded."));
    noWallet->setAlignment(Qt::AlignCenter);
    walletStack->addWidget(noWallet);
}

WalletFrame::~WalletFrame()
{
}

void WalletFrame::setClientModel(ClientModel *_clientModel)
{
    this->clientModel = _clientModel;
}

bool WalletFrame::addWallet(WalletModel *walletModel)
{
    if (!gui || !clientModel || !walletModel) {
        return false;
    }

    const QString name = walletModel->getWalletName();
    if (mapWalletViews.count(name) > 0) {
        return false;
    }

    WalletView *walletView = new WalletView(platformStyle, this);
    walletView->setBitcoinGUI(gui);
    walletView->setClientModel(clientModel);
    walletView->setWalletModel(walletModel);
    walletView->showOutOfSyncWarning(bOutOfSync);

    WalletView* current_wallet_view = currentWalletView();
    if (current_wallet_view) {
        walletView->setCurrentIndex(current_wallet_view->currentIndex());
    } else {
        walletView->gotoOverviewPage();
    }

    walletStack->addWidget(walletView);
    mapWalletViews[name] = walletView;

    // Ensure a walletView is able to show the main window
    connect(walletView, SIGNAL(showNormalIfMinimized()), gui, SLOT(showNormalIfMinimized()));

    connect(walletView, SIGNAL(outOfSyncWarningClicked()), this, SLOT(outOfSyncWarningClicked()));

    return true;
}

bool WalletFrame::setCurrentWallet(const QString& name)
{
    if (mapWalletViews.count(name) == 0)
        return false;

    WalletView *walletView = mapWalletViews.value(name);
    walletStack->setCurrentWidget(walletView);
    assert(walletView);
    walletView->updateEncryptionStatus();
    return true;
}

bool WalletFrame::removeWallet(const QString &name)
{
    if (mapWalletViews.count(name) == 0)
        return false;

    WalletView *walletView = mapWalletViews.take(name);
    walletStack->removeWidget(walletView);
    delete walletView;
    return true;
}

void WalletFrame::removeAllWallets()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        walletStack->removeWidget(i.value());
    mapWalletViews.clear();
}

bool WalletFrame::handlePaymentRequest(const SendCoinsRecipient &recipient)
{
    WalletView *walletView = currentWalletView();
    if (!walletView)
        return false;

    return walletView->handlePaymentRequest(recipient);
}

void WalletFrame::showOutOfSyncWarning(bool fShow)
{
    bOutOfSync = fShow;
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->showOutOfSyncWarning(fShow);
}

void WalletFrame::gotoOverviewPage()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoOverviewPage();
}

void WalletFrame::gotoHistoryPage()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoHistoryPage();
}

void WalletFrame::gotoMultisigPage()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoMultisigPage();
}

void WalletFrame::gotoMintingPage()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoMintingPage();
}

void WalletFrame::gotoReceiveCoinsPage()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoReceiveCoinsPage();
}

void WalletFrame::gotoSendCoinsPage(QString addr)
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoSendCoinsPage(addr);
}

void WalletFrame::gotoSignMessageTab(QString addr)
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->gotoSignMessageTab(addr);
}

void WalletFrame::gotoVerifyMessageTab(QString addr)
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->gotoVerifyMessageTab(addr);
}

void WalletFrame::encryptWallet(bool status)
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->encryptWallet(status);
}

void WalletFrame::decryptForMinting(bool status)
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->decryptForMinting(status);
}

void WalletFrame::backupWallet()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->backupWallet();
}

void WalletFrame::changePassphrase()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->changePassphrase();
}

void WalletFrame::unlockWallet()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->unlockWallet();
}

void WalletFrame::usedSendingAddresses()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->usedSendingAddresses();
}

void WalletFrame::usedReceivingAddresses()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->usedReceivingAddresses();
}

WalletView *WalletFrame::currentWalletView()
{
    return qobject_cast<WalletView*>(walletStack->currentWidget());
}

void WalletFrame::outOfSyncWarningClicked()
{
    Q_EMIT requestedSyncWarningInfo();
}
<|endoftext|>


<commit_before><commit_msg>Updated flight control<commit_after>#include "ros/ros.h"
#include "std_msgs/Empty.h"
#include "geometry_msgs/Twist.h"
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include "ardrone_autonomy/Navdata.h"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>

ardrone_autonomy::Navdata msg_in;
geometry_msgs::Twist input;
image_transport::Publisher image_pub;

using namespace cv;

void imageCallback(const sensor_msgs::ImageConstPtr& msg)
{
  // sensor_msgs::CvBridge bridge;
  // namedWindow( "view", cv::WINDOW_AUTOSIZE );
    cv_bridge::CvImagePtr cv_ptr;
    try
    {
        if(msg_in.tags_count > 0){
            long int tagy = ((((long int)msg_in.tags_yc[0]) * 640)/1000 );
            long int tagx = ((((long int)msg_in.tags_xc[0]) * 480)/1000 );
            ROS_INFO(" [%u] [%u] ", tagx, tagx);
            cv_ptr = cv_bridge::toCvCopy(msg, "bgr8");
            circle(cv_ptr->image, Point(tagx,tagy),25, Scalar(129,221,150), -1 , 8,0);

            // sensor_msgs::ImagePtr new_img = cv_bridge::CvImage(std_msgs::Header(), "bgr8", cv_ptr->image).toImageMsg();
            // image_pub.publish(new_img);
        }
        else{
            cv_ptr = cv_bridge::toCvCopy(msg, "bgr8");
            // sensor_msgs::ImagePtr new_img = cv_bridge::CvImage(std_msgs::Header(), "bgr8", cv_ptr->image).toImageMsg();
            // image_pub.publish(new_img);
        }
   }
   catch (cv_bridge::Exception& e)
   {
     ROS_ERROR("cv_bridge exception: %s", e.what());
     return;
   }
     cv::imshow("view", cv_ptr->image);
}

void vision_dataCB(const geometry_msgs::Twist::ConstPtr& msg)
{
    // input = *msg;

    ROS_INFO("[%f], [%f], [%f], [%f], [%f], [%f]",msg->linear.x,msg->linear.y,msg->linear.z,msg->angular.x,msg->angular.y,msg->angular.z);
}
void tagCB(const ardrone_autonomy::Navdata& msg)
{
    msg_in = msg;
    if(msg.tags_count > 0)
    {
        // ROS_INFO("[%u], [%u]",msg.tags_xc[0],msg.tags_yc[0]);
        long int tagy = -1 * ((((long int)msg.tags_xc[0]) * 640)/1000 - 320);
        long int tagx = -1 * ((((long int)msg.tags_yc[0]) * 480)/1000 - 240);
        double tagy_f = ((double) tagy/320.0) * 0.5;
        double tagx_f = ((double) tagx/240.0) * 0.5;
        ROS_INFO("[%lf], [%lf]",tagx_f,tagy_f);
        input.linear.x = tagx_f;
        input.linear.y = tagy_f;
    }
    else
        ROS_INFO("No tags");
}

int main(int argc, char **argv)
{
    ros::init(argc, argv, "flight");
    ros::NodeHandle node;
    ros::Rate loop_rate(30);

    ros::Publisher take_off;
    ros::Publisher twist;
    ros::Publisher land;
    ros::Publisher emergency;

    ros::Subscriber vision_data;
    ros::Subscriber navdata;

    std_msgs::Empty msg;

    geometry_msgs::Twist hover;
    geometry_msgs::Twist move;

    input.linear.x = 0.0;
    input.linear.y = 0.0;
    input.linear.z = 10.0;
    input.angular.x = 0.0;
    input.angular.y = 0.0;
    input.angular.z = 0.0;

    hover.linear.x = 0.0;
    hover.linear.y = 0.0;
    hover.linear.z = 0.0;
    hover.angular.x = 0.0;
    hover.angular.y = 0.0;
    hover.angular.z = 0.0;

    // cv::namedWindow("view");
    // cv::startWindowThread();
    ROS_INFO("Drone Flight | Test 1.0");

    twist = node.advertise<geometry_msgs::Twist>("/cmd_vel", 1);
    take_off = node.advertise<std_msgs::Empty>("/ardrone/takeoff", 1);
    land = node.advertise<std_msgs::Empty>("/ardrone/land", 1);
    // vision_data = node.subscribe("/ardrone/vision_data",10, vision_dataCB);
    // navdata = node.subscribe("/tagdata", 10, tagCB);
    // image_transport::ImageTransport it_sub(node);
    // image_transport::Subscriber image_sub = it_sub.subscribe("/camera/image", 10, imageCallback);
    // image_transport::ImageTransport it_pub(node);
    // image_pub = it_pub.advertise("/new_image", 10);

    int cnt = 0;
    ROS_INFO("Flight Starting");
    // double time_count = (double)ros::Time::now().toSec();
    while( ros::ok()) {
        if(cnt < 5){
            cnt+=1;
            take_off.publish(msg);
            twist.publish(hover);
            ros::spinOnce();
        }

        else if(cnt < 15){
            cnt+=1;
            // take_off.publish(msg);
            twist.publish(input);
            ros::spinOnce();
        }
        else{
            twist.publish(hover);
            ros::spinOnce();
        }
        loop_rate.sleep();
    }
    // cv::destroyWindow("view");

}
    //ROS_INFO(time_count);
/*
    while (ros::ok())
    {
        if((double)ros::Time::now().toSec() < time_count + 4)
        {
            ROS_INFO("Taking Off");
        }

        while (((double)ros::Time::now().toSec() < time_count + 3.0) && ros::ok())
        {
            take_off.publish(msg);
            twist.publish(hover);
            ros::spinOnce();
            ROS_INFO("Taking OFF");
            loop_rate.sleep();
        }

        ROS_INFO("Hovering and Moving");
        twist.publish(hover);

        ros::spinOnce();
        loop_rate.sleep();

        while (((double)ros::Time::now().toSec() < time_count + 20.0) && ros::ok())
        {
            twist.publish(hover);
            // land.publish(msg);
            ros::spinOnce();
            ROS_INFO("Moving");
            loop_rate.sleep();
        }

        // ROS_INFO("Landing");
        while (((double)ros::Time::now().toSec() > time_count + 20.0) && ros::ok())
        {
            twist.publish(hover);
            land.publish(msg);
            ros::spinOnce();
            loop_rate.sleep();
        }

        if (((double)ros::Time::now().toSec() > time_count + 20.0)  && ros::ok())
        {
            ROS_INFO("Closing Flight");
            exit(0);
            ros::spinOnce();
            loop_rate.sleep();
        }
    }
}
*/<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include <iostream>
#include <sstream>

#include "db/test/Test.h"
#include "db/test/Tester.h"
#include "db/test/TestRunner.h"
#include "db/io/ByteArrayInputStream.h"
#include "db/mail/SmtpClient.h"
#include "db/mail/MailTemplateParser.h"
#include "db/mail/MailSpool.h"
#include "db/net/Url.h"

using namespace std;
using namespace db::io;
using namespace db::net;
using namespace db::test;
using namespace db::rt;

#ifdef WIN32
#define TMPDIR "c:/WINDOWS/Temp"
#else
#define TMPDIR "/tmp"
#endif

#define VALID_SMTP_SERVER "smtp://yuna.digitalbazaar.com:25"

void runSmtpClientTest(TestRunner& tr)
{
   tr.test("SmtpClient");

   // set url of mail server
   Url url(VALID_SMTP_SERVER);

   // set mail
   db::mail::Mail mail;
   mail.setSender("testuser@bitmunk.com");
   mail.addTo("support@bitmunk.com");
   mail.addCc("support@bitmunk.com");
   mail.setSubject("This is an autogenerated unit test email");
   mail.setBody("This is the test body");

   //mail.setHeader("MIME-Version", "1.0");
   //mail.setHeader("Content-Transfer-Encoding", "base64");

   // send mail
   db::mail::SmtpClient c;
   c.sendMail(&url, &mail);

   tr.passIfNoException();
}

void runMimeTest(TestRunner& tr)
{
   tr.group("Mime");

   tr.test("simple base64");
   {
      // set url of mail server
      Url url(VALID_SMTP_SERVER);

      // set mail
      db::mail::Mail mail;
      mail.setSender("testuser@bitmunk.com");
      mail.addTo("support@bitmunk.com");
      mail.setSubject("This is an autogenerated unit test MIME email");
      string body =
         "This is a body that is intended to test really long lines. A body "
         "containing a line that is over 1000 characters is not permitted when "
         "using SMTP unless the body is transfer-encoded. This particular "
         "body should be transfer-encoded using base64. This body has no line "
         "breaks whatsoever and is more than 1000 characters long. It ends with "
         "a whole bunch of the letter Z's. Like it's sleeping. Here come the "
         "Z's ... there are 1000 of them: ";
      body.append(1000, 'Z');
      body.append(". Thus ends the Z's and this body.");

      mail.setBody(body.c_str());

      // include mime header and content-transfer-encoding header to ensure
      // proper encoding and delivery
      mail.setHeader("MIME-Version", "1.0");
      mail.setHeader("Content-Transfer-Encoding", "base64");

      // send mail
      db::mail::SmtpClient c;
      c.sendMail(&url, &mail);
   }
   tr.passIfNoException();

   tr.test("template base64");
   {
      // create mail template
      const char* tpl =
         "MIME-Version: 1.0\r\n"
         "Content-Transfer-Encoding: base64\r\n"
         "Subject: This is an autogenerated unit test templated MIME email\r\n"
         "From: testuser@bitmunk.com\r\n"
         "To: support@bitmunk.com\r\n"
         "\r\n"
         "{body}";

      // create template parser
      db::mail::MailTemplateParser parser;

      // create input stream
      ByteArrayInputStream bais(tpl, strlen(tpl));

      // create variables
      DynamicObject vars;
      string body =
         "This is a body that is intended to test really long lines. A body "
         "containing a line that is over 1000 characters is not permitted when "
         "using SMTP unless the body is transfer-encoded. This particular "
         "body should be transfer-encoded using base64. This body has no line "
         "breaks whatsoever and is more than 1000 characters long. It ends with "
         "a whole bunch of the letter Z's. Like it's sleeping. Here come the "
         "Z's ... there are 1000 of them: ";
      body.append(1000, 'Z');
      body.append(". Thus ends the Z's and this body.");
      vars["body"] = body.c_str();

      // parse mail
      db::mail::Mail mail;
      parser.parse(&mail, vars, false, &bais);

      // set url of mail server
      Url url(VALID_SMTP_SERVER);

      // send mail
      db::mail::SmtpClient c;
      c.sendMail(&url, &mail);
   }
   tr.passIfNoException();
}

void runMailTemplateParser(TestRunner& tr)
{
   tr.test("MailTemplateParser");

   // create mail template
   const char* tpl =
      "Subject: This is an autogenerated unit test email\r\n"
      "From: testuser@bitmunk.com\r\n"
      "To: support@bitmunk.com\r\n"
      "Cc: support@bitmunk.com\r\n"
      "Bcc: {bccAddress1}\r\n"
      "\r\n"
      "This is the test body. I want $10.00.\n"
      "I used a variable: \\{bccAddress1\\} with the value of "
      "'{bccAddress1}'.\n"
      "Slash before variable \\\\{bccAddress1}.\n"
      "2 slashes before variable \\\\\\\\{bccAddress1}.\n"
      "Slash before escaped variable \\\\\\{bccAddress1\\}.\n"
      "2 slashes before escaped variable \\\\\\\\\\{bccAddress1\\}.\n"
      "{eggs}{bacon}{ham}{sausage}.";

   // create template parser
   db::mail::MailTemplateParser parser;

   // create input stream
   ByteArrayInputStream bais(tpl, strlen(tpl));

   // create variables
   DynamicObject vars;
   vars["bccAddress1"] = "support@bitmunk.com";
   vars["eggs"] = "This is a ";
   //vars["bacon"] -- no bacon
   vars["ham"] = "number ";
   vars["sausage"] = 5;

   // parse mail
   db::mail::Mail mail;
   parser.parse(&mail, vars, false, &bais);

   const char* expect =
      "This is the test body. I want $10.00.\r\n"
      "I used a variable: {bccAddress1} with the value of "
      "'support@bitmunk.com'.\r\n"
      "Slash before variable \\support@bitmunk.com.\r\n"
      "2 slashes before variable \\\\support@bitmunk.com.\r\n"
      "Slash before escaped variable \\{bccAddress1}.\r\n"
      "2 slashes before escaped variable \\\\{bccAddress1}.\r\n"
      "This is a number 5.\r\n";

   // get mail message
   db::mail::Message msg = mail.getMessage();

   // assert body parsed properly
   const char* body = msg["body"]->getString();
   assertStrCmp(body, expect);

   // create template from mail
   string generatedTemplate = mail.toTemplate();

   const char* genExpect =
      "CC: support@bitmunk.com\r\n"
      "From: testuser@bitmunk.com\r\n"
      "Subject: This is an autogenerated unit test email\r\n"
      "To: support@bitmunk.com\r\n"
      "\r\n"
      "This is the test body. I want $10.00.\r\n"
      "I used a variable: \\{bccAddress1\\} with the value of 'support@bitmunk.com'.\r\n"
      "Slash before variable \\\\support@bitmunk.com.\r\n"
      "2 slashes before variable \\\\\\\\support@bitmunk.com.\r\n"
      "Slash before escaped variable \\\\\\{bccAddress1\\}.\r\n"
      "2 slashes before escaped variable \\\\\\\\\\{bccAddress1\\}.\r\n"
      "This is a number 5.\r\n";

   assertStrCmp(generatedTemplate.c_str(), genExpect);
   //cout << "Generated template=\n" << generatedTemplate << std::endl;

//   // print out mail message
//   cout << "\nHeaders=\n";
//   DynamicObjectIterator i = msg["headers"].getIterator();
//   while(i->hasNext())
//   {
//      DynamicObject header = i->next();
//      DynamicObjectIterator doi = header.getIterator();
//      while(doi->hasNext())
//      {
//         cout << i->getName() << ": " << doi->next()->getString() << endl;
//      }
//   }
//
//   cout << "Expect=\n" << expect << endl;
//   cout << "Body=\n" << msg["body"]->getString() << endl;

//   // set url of mail server
//   Url url(VALID_SMTP_SERVER);
//
//   // send mail
//   db::mail::SmtpClient c;
//   c.sendMail(&url, &mail);

   tr.passIfNoException();
}

void mailSpoolTest(TestRunner& tr)
{
   tr.test("MailSpool");

   // create mail template
   const char* tpl =
      "Subject: This is an autogenerated unit test email\r\n"
      "From: testuser@bitmunk.com\r\n"
      "To: support@bitmunk.com\r\n"
      "Cc: support@bitmunk.com\r\n"
      "Bcc: {bccAddress1}\r\n"
      "\r\n"
      "This is the test body. I want $10.00.\n"
      "I used a variable: \\{bccAddress1\\} with the value of "
      "'{bccAddress1}'.\n"
      "Slash before variable \\\\{bccAddress1}.\n"
      "2 slashes before variable \\\\\\\\{bccAddress1}.\n"
      "Slash before escaped variable \\\\\\{bccAddress1\\}.\n"
      "2 slashes before escaped variable \\\\\\\\\\{bccAddress1\\}.\n"
      "{eggs}{bacon}{ham}{sausage}.";

   // create template parser
   db::mail::MailTemplateParser parser;

   // create input stream
   ByteArrayInputStream bais(tpl, strlen(tpl));

   // create variables
   DynamicObject vars;
   vars["bccAddress1"] = "support@bitmunk.com";
   vars["eggs"] = "This is a ";
   vars["bacon"] = ""; // -- no bacon
   vars["ham"] = "number ";
   vars["sausage"] = 5;

   // parse mail
   db::mail::Mail mail;
   parser.parse(&mail, vars, true, &bais);

   // get template
   string tpl1 = mail.toTemplate();

   // clean up old spool files
   File file(TMPDIR "/bmtestspool");
   File idxFile(TMPDIR "/bmtestspool.idx");
   idxFile->remove();
   file->remove();

   // create mail spool
   db::mail::MailSpool spool;
   spool.setFile(file);
   assertNoException();

   // spool mail
   spool.spool(&mail);
   assertNoException();

   // spool mail
   spool.spool(&mail);
   assertNoException();

   // spool mail
   spool.spool(&mail);
   assertNoException();

   // get mail
   db::mail::Mail m2;
   spool.getFirst(&m2);
   assertNoException();

   // assert templates are equal
   string tpl2 = m2.toTemplate();
   assertStrCmp(tpl1.c_str(), tpl2.c_str());

   // unwind
   spool.unwind();
   spool.unwind();
   assertNoException();

   // get mail
   db::mail::Mail m3;
   spool.getFirst(&m3);
   assertNoException();

   // assert templates are equal
   string tpl3 = m3.toTemplate();
   assertStrCmp(tpl1.c_str(), tpl3.c_str());

   // unwind
   spool.unwind();

   // get first mail (should exception, spool is empty)
   spool.getFirst(&m3);
   assertException();
   Exception::clearLast();

   tr.passIfNoException();
}

void runFailedMailSendTest(TestRunner& tr)
{
   tr.test("FailedMailSend");

   // set url of mail server
   Url url("");

   // set mail
   db::mail::Mail mail;
   mail.setSender("testuser@bitmunk.com");
   mail.addTo("support@bitmunk.com");
   mail.addCc("support@bitmunk.com");
   mail.setSubject("This is an autogenerated unit test email");
   mail.setBody("This is the test body");

   // create spool to store failed send
   db::mail::MailSpool spool;
   File spoolFile("/tmp/testmailspool");
   spool.setFile(spoolFile);

   // send mail
   db::mail::SmtpClient c;
   bool sent = c.sendMail(&url, &mail);
   assert(!sent);
   if(!sent)
   {
      // check for network errors, we want to spool the mail
      ExceptionRef e = Exception::getLast();
      if(strncmp(e->getType(), "db.net", 6) == 0)
      {
         Exception::clearLast();
         spool.spool(&mail);
         assertNoException();

         // now send the mail properly
         db::mail::Mail mail2;
         spool.getFirst(&mail2);
         assertNoException();
         spool.unwind();
         assertNoException();
         url.setUrl(VALID_SMTP_SERVER);
         c.sendMail(&url, &mail2);
         assertNoException();
      }
   }

   tr.passIfNoException();
}

class DbMailTester : public db::test::Tester
{
public:
   DbMailTester()
   {
      setName("mail");
   }

   /**
    * Run automatic unit tests.
    */
   virtual int runAutomaticTests(TestRunner& tr)
   {
      runMailTemplateParser(tr);
      mailSpoolTest(tr);
      return 0;
   }

   /**
    * Runs interactive unit tests.
    */
   virtual int runInteractiveTests(TestRunner& tr)
   {
      //runSmtpClientTest(tr);
      runMimeTest(tr);
      //runFailedMailSendTest(tr);
      return 0;
   }
};

#undef TMPDIR

#ifndef DB_TEST_NO_MAIN
DB_TEST_MAIN(DbMailTester)
#endif
<commit_msg>Changed valid mail server.<commit_after>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include <iostream>
#include <sstream>

#include "db/test/Test.h"
#include "db/test/Tester.h"
#include "db/test/TestRunner.h"
#include "db/io/ByteArrayInputStream.h"
#include "db/mail/SmtpClient.h"
#include "db/mail/MailTemplateParser.h"
#include "db/mail/MailSpool.h"
#include "db/net/Url.h"

using namespace std;
using namespace db::io;
using namespace db::net;
using namespace db::test;
using namespace db::rt;

#ifdef WIN32
#define TMPDIR "c:/WINDOWS/Temp"
#else
#define TMPDIR "/tmp"
#endif

#define VALID_SMTP_SERVER "smtp://mail.digitalbazaar.com:25"

void runSmtpClientTest(TestRunner& tr)
{
   tr.test("SmtpClient");

   // set url of mail server
   Url url(VALID_SMTP_SERVER);

   // set mail
   db::mail::Mail mail;
   mail.setSender("testuser@bitmunk.com");
   mail.addTo("support@bitmunk.com");
   mail.addCc("support@bitmunk.com");
   mail.setSubject("This is an autogenerated unit test email");
   mail.setBody("This is the test body");

   //mail.setHeader("MIME-Version", "1.0");
   //mail.setHeader("Content-Transfer-Encoding", "base64");

   // send mail
   db::mail::SmtpClient c;
   c.sendMail(&url, &mail);

   tr.passIfNoException();
}

void runMimeTest(TestRunner& tr)
{
   tr.group("Mime");

   tr.test("simple base64");
   {
      // set url of mail server
      Url url(VALID_SMTP_SERVER);

      // set mail
      db::mail::Mail mail;
      mail.setSender("testuser@bitmunk.com");
      mail.addTo("support@bitmunk.com");
      mail.setSubject("This is an autogenerated unit test MIME email");
      string body =
         "This is a body that is intended to test really long lines. A body "
         "containing a line that is over 1000 characters is not permitted when "
         "using SMTP unless the body is transfer-encoded. This particular "
         "body should be transfer-encoded using base64. This body has no line "
         "breaks whatsoever and is more than 1000 characters long. It ends with "
         "a whole bunch of the letter Z's. Like it's sleeping. Here come the "
         "Z's ... there are 1000 of them: ";
      body.append(1000, 'Z');
      body.append(". Thus ends the Z's and this body.");

      mail.setBody(body.c_str());

      // include mime header and content-transfer-encoding header to ensure
      // proper encoding and delivery
      mail.setHeader("MIME-Version", "1.0");
      mail.setHeader("Content-Transfer-Encoding", "base64");

      // send mail
      db::mail::SmtpClient c;
      c.sendMail(&url, &mail);
   }
   tr.passIfNoException();

   tr.test("template base64");
   {
      // create mail template
      const char* tpl =
         "MIME-Version: 1.0\r\n"
         "Content-Transfer-Encoding: base64\r\n"
         "Subject: This is an autogenerated unit test templated MIME email\r\n"
         "From: testuser@bitmunk.com\r\n"
         "To: support@bitmunk.com\r\n"
         "\r\n"
         "{body}";

      // create template parser
      db::mail::MailTemplateParser parser;

      // create input stream
      ByteArrayInputStream bais(tpl, strlen(tpl));

      // create variables
      DynamicObject vars;
      string body =
         "This is a body that is intended to test really long lines. A body "
         "containing a line that is over 1000 characters is not permitted when "
         "using SMTP unless the body is transfer-encoded. This particular "
         "body should be transfer-encoded using base64. This body has no line "
         "breaks whatsoever and is more than 1000 characters long. It ends with "
         "a whole bunch of the letter Z's. Like it's sleeping. Here come the "
         "Z's ... there are 1000 of them: ";
      body.append(1000, 'Z');
      body.append(". Thus ends the Z's and this body.");
      vars["body"] = body.c_str();

      // parse mail
      db::mail::Mail mail;
      parser.parse(&mail, vars, false, &bais);

      // set url of mail server
      Url url(VALID_SMTP_SERVER);

      // send mail
      db::mail::SmtpClient c;
      c.sendMail(&url, &mail);
   }
   tr.passIfNoException();
}

void runMailTemplateParser(TestRunner& tr)
{
   tr.test("MailTemplateParser");

   // create mail template
   const char* tpl =
      "Subject: This is an autogenerated unit test email\r\n"
      "From: testuser@bitmunk.com\r\n"
      "To: support@bitmunk.com\r\n"
      "Cc: support@bitmunk.com\r\n"
      "Bcc: {bccAddress1}\r\n"
      "\r\n"
      "This is the test body. I want $10.00.\n"
      "I used a variable: \\{bccAddress1\\} with the value of "
      "'{bccAddress1}'.\n"
      "Slash before variable \\\\{bccAddress1}.\n"
      "2 slashes before variable \\\\\\\\{bccAddress1}.\n"
      "Slash before escaped variable \\\\\\{bccAddress1\\}.\n"
      "2 slashes before escaped variable \\\\\\\\\\{bccAddress1\\}.\n"
      "{eggs}{bacon}{ham}{sausage}.";

   // create template parser
   db::mail::MailTemplateParser parser;

   // create input stream
   ByteArrayInputStream bais(tpl, strlen(tpl));

   // create variables
   DynamicObject vars;
   vars["bccAddress1"] = "support@bitmunk.com";
   vars["eggs"] = "This is a ";
   //vars["bacon"] -- no bacon
   vars["ham"] = "number ";
   vars["sausage"] = 5;

   // parse mail
   db::mail::Mail mail;
   parser.parse(&mail, vars, false, &bais);

   const char* expect =
      "This is the test body. I want $10.00.\r\n"
      "I used a variable: {bccAddress1} with the value of "
      "'support@bitmunk.com'.\r\n"
      "Slash before variable \\support@bitmunk.com.\r\n"
      "2 slashes before variable \\\\support@bitmunk.com.\r\n"
      "Slash before escaped variable \\{bccAddress1}.\r\n"
      "2 slashes before escaped variable \\\\{bccAddress1}.\r\n"
      "This is a number 5.\r\n";

   // get mail message
   db::mail::Message msg = mail.getMessage();

   // assert body parsed properly
   const char* body = msg["body"]->getString();
   assertStrCmp(body, expect);

   // create template from mail
   string generatedTemplate = mail.toTemplate();

   const char* genExpect =
      "CC: support@bitmunk.com\r\n"
      "From: testuser@bitmunk.com\r\n"
      "Subject: This is an autogenerated unit test email\r\n"
      "To: support@bitmunk.com\r\n"
      "\r\n"
      "This is the test body. I want $10.00.\r\n"
      "I used a variable: \\{bccAddress1\\} with the value of 'support@bitmunk.com'.\r\n"
      "Slash before variable \\\\support@bitmunk.com.\r\n"
      "2 slashes before variable \\\\\\\\support@bitmunk.com.\r\n"
      "Slash before escaped variable \\\\\\{bccAddress1\\}.\r\n"
      "2 slashes before escaped variable \\\\\\\\\\{bccAddress1\\}.\r\n"
      "This is a number 5.\r\n";

   assertStrCmp(generatedTemplate.c_str(), genExpect);
   //cout << "Generated template=\n" << generatedTemplate << std::endl;

//   // print out mail message
//   cout << "\nHeaders=\n";
//   DynamicObjectIterator i = msg["headers"].getIterator();
//   while(i->hasNext())
//   {
//      DynamicObject header = i->next();
//      DynamicObjectIterator doi = header.getIterator();
//      while(doi->hasNext())
//      {
//         cout << i->getName() << ": " << doi->next()->getString() << endl;
//      }
//   }
//
//   cout << "Expect=\n" << expect << endl;
//   cout << "Body=\n" << msg["body"]->getString() << endl;

//   // set url of mail server
//   Url url(VALID_SMTP_SERVER);
//
//   // send mail
//   db::mail::SmtpClient c;
//   c.sendMail(&url, &mail);

   tr.passIfNoException();
}

void mailSpoolTest(TestRunner& tr)
{
   tr.test("MailSpool");

   // create mail template
   const char* tpl =
      "Subject: This is an autogenerated unit test email\r\n"
      "From: testuser@bitmunk.com\r\n"
      "To: support@bitmunk.com\r\n"
      "Cc: support@bitmunk.com\r\n"
      "Bcc: {bccAddress1}\r\n"
      "\r\n"
      "This is the test body. I want $10.00.\n"
      "I used a variable: \\{bccAddress1\\} with the value of "
      "'{bccAddress1}'.\n"
      "Slash before variable \\\\{bccAddress1}.\n"
      "2 slashes before variable \\\\\\\\{bccAddress1}.\n"
      "Slash before escaped variable \\\\\\{bccAddress1\\}.\n"
      "2 slashes before escaped variable \\\\\\\\\\{bccAddress1\\}.\n"
      "{eggs}{bacon}{ham}{sausage}.";

   // create template parser
   db::mail::MailTemplateParser parser;

   // create input stream
   ByteArrayInputStream bais(tpl, strlen(tpl));

   // create variables
   DynamicObject vars;
   vars["bccAddress1"] = "support@bitmunk.com";
   vars["eggs"] = "This is a ";
   vars["bacon"] = ""; // -- no bacon
   vars["ham"] = "number ";
   vars["sausage"] = 5;

   // parse mail
   db::mail::Mail mail;
   parser.parse(&mail, vars, true, &bais);

   // get template
   string tpl1 = mail.toTemplate();

   // clean up old spool files
   File file(TMPDIR "/bmtestspool");
   File idxFile(TMPDIR "/bmtestspool.idx");
   idxFile->remove();
   file->remove();

   // create mail spool
   db::mail::MailSpool spool;
   spool.setFile(file);
   assertNoException();

   // spool mail
   spool.spool(&mail);
   assertNoException();

   // spool mail
   spool.spool(&mail);
   assertNoException();

   // spool mail
   spool.spool(&mail);
   assertNoException();

   // get mail
   db::mail::Mail m2;
   spool.getFirst(&m2);
   assertNoException();

   // assert templates are equal
   string tpl2 = m2.toTemplate();
   assertStrCmp(tpl1.c_str(), tpl2.c_str());

   // unwind
   spool.unwind();
   spool.unwind();
   assertNoException();

   // get mail
   db::mail::Mail m3;
   spool.getFirst(&m3);
   assertNoException();

   // assert templates are equal
   string tpl3 = m3.toTemplate();
   assertStrCmp(tpl1.c_str(), tpl3.c_str());

   // unwind
   spool.unwind();

   // get first mail (should exception, spool is empty)
   spool.getFirst(&m3);
   assertException();
   Exception::clearLast();

   tr.passIfNoException();
}

void runFailedMailSendTest(TestRunner& tr)
{
   tr.test("FailedMailSend");

   // set url of mail server
   Url url("");

   // set mail
   db::mail::Mail mail;
   mail.setSender("testuser@bitmunk.com");
   mail.addTo("support@bitmunk.com");
   mail.addCc("support@bitmunk.com");
   mail.setSubject("This is an autogenerated unit test email");
   mail.setBody("This is the test body");

   // create spool to store failed send
   db::mail::MailSpool spool;
   File spoolFile("/tmp/testmailspool");
   spool.setFile(spoolFile);

   // send mail
   db::mail::SmtpClient c;
   bool sent = c.sendMail(&url, &mail);
   assert(!sent);
   if(!sent)
   {
      // check for network errors, we want to spool the mail
      ExceptionRef e = Exception::getLast();
      if(strncmp(e->getType(), "db.net", 6) == 0)
      {
         Exception::clearLast();
         spool.spool(&mail);
         assertNoException();

         // now send the mail properly
         db::mail::Mail mail2;
         spool.getFirst(&mail2);
         assertNoException();
         spool.unwind();
         assertNoException();
         url.setUrl(VALID_SMTP_SERVER);
         c.sendMail(&url, &mail2);
         assertNoException();
      }
   }

   tr.passIfNoException();
}

class DbMailTester : public db::test::Tester
{
public:
   DbMailTester()
   {
      setName("mail");
   }

   /**
    * Run automatic unit tests.
    */
   virtual int runAutomaticTests(TestRunner& tr)
   {
      runMailTemplateParser(tr);
      mailSpoolTest(tr);
      return 0;
   }

   /**
    * Runs interactive unit tests.
    */
   virtual int runInteractiveTests(TestRunner& tr)
   {
      //runSmtpClientTest(tr);
      runMimeTest(tr);
      //runFailedMailSendTest(tr);
      return 0;
   }
};

#undef TMPDIR

#ifndef DB_TEST_NO_MAIN
DB_TEST_MAIN(DbMailTester)
#endif
<|endoftext|>