<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SDR_ANIMATION_SCHEDULER_HXX
#define _SDR_ANIMATION_SCHEDULER_HXX

#include <sal/types.h>
#include <vcl/timer.hxx>
#include <svx/svxdllapi.h>

//////////////////////////////////////////////////////////////////////////////
// event class

namespace sdr
{
    namespace animation
    {
        class Event
        {
            // time of event in ms
            sal_uInt32                                      mnTime;

            // pointer for simply linked list
            Event*                                          mpNext;

        public:
            // constructor/destructor
            Event(sal_uInt32 nTime);
            SVX_DLLPUBLIC virtual ~Event();

            // access to mpNext
            Event* GetNext() const;
            void SetNext(Event* pNew);

            // get/set time
            sal_uInt32 GetTime() const;
            void SetTime(sal_uInt32 nNew);

            // execute event
            virtual void Trigger(sal_uInt32 nTime) = 0;
        };
    } // end of namespace animation
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////
// eventlist class

namespace sdr
{
    namespace animation
    {
        class EventList
        {
            // pointer to first entry
            Event*                                          mpHead;

        public:
            // constructor/destructor
            EventList();
            SVX_DLLPUBLIC virtual ~EventList();

            // insert/remove time dependent
            void Insert(Event* pNew);
            void Remove(Event* pOld);

            // clear list
            void Clear();

            // get first
            Event* GetFirst();
        };
    } // end of namespace animation
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////
// scheduler class

namespace sdr
{
    namespace animation
    {
        class Scheduler : public Timer
        {
            // time in ms
            sal_uInt32                                      mnTime;

            // next delta time
            sal_uInt32                                      mnDeltaTime;

            // list of events
            EventList                                       maList;

            // Flag which remembers if this timer is paused. Default
            // is false.
            bool                                            mbIsPaused;

        public:
            // constructor/destructor
            Scheduler();
            SVX_DLLPUBLIC virtual ~Scheduler();

            // From baseclass Timer, the timeout call
            SVX_DLLPUBLIC virtual void Timeout();

            // get time
            sal_uInt32 GetTime();

            // #i38135#
            void SetTime(sal_uInt32 nTime);

            // reset
            void Reset(sal_uInt32 nTime);

            // execute all ripe events, removes executed ones from the scheduler
            void triggerEvents();

            // re-start or stop timer according to event list
            void checkTimeout();

            // insert/remove events, wrapper to EventList methods
            void InsertEvent(Event* pNew);
            void RemoveEvent(Event* pOld);

            // get/set pause
            bool IsPaused() const { return mbIsPaused; }
            void SetPaused(bool bNew);
        };
    } // end of namespace animation
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////

#endif //_SDR_ANIMATION_SCHEDULER_HXX

// eof
<commit_msg>Port cws-koheicopyborder-svx.diff from ooo-build.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SDR_ANIMATION_SCHEDULER_HXX
#define _SDR_ANIMATION_SCHEDULER_HXX

#include <sal/types.h>
#include <vcl/timer.hxx>
#include <svx/svxdllapi.h>

//////////////////////////////////////////////////////////////////////////////
// event class

namespace sdr
{
    namespace animation
    {
        class Event
        {
            // time of event in ms
            sal_uInt32                                      mnTime;

            // pointer for simply linked list
            Event*                                          mpNext;

        public:
            // constructor/destructor
            Event(sal_uInt32 nTime);
            SVX_DLLPUBLIC virtual ~Event();

            // access to mpNext
            Event* GetNext() const;
            void SetNext(Event* pNew);

            // get/set time
            sal_uInt32 GetTime() const;
            void SVX_DLLPUBLIC SetTime(sal_uInt32 nNew);

            // execute event
            virtual void Trigger(sal_uInt32 nTime) = 0;
        };
    } // end of namespace animation
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////
// eventlist class

namespace sdr
{
    namespace animation
    {
        class EventList
        {
            // pointer to first entry
            Event*                                          mpHead;

        public:
            // constructor/destructor
            EventList();
            SVX_DLLPUBLIC virtual ~EventList();

            // insert/remove time dependent
            void Insert(Event* pNew);
            void Remove(Event* pOld);

            // clear list
            void Clear();

            // get first
            Event* GetFirst();
        };
    } // end of namespace animation
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////
// scheduler class

namespace sdr
{
    namespace animation
    {
        class Scheduler : public Timer
        {
            // time in ms
            sal_uInt32                                      mnTime;

            // next delta time
            sal_uInt32                                      mnDeltaTime;

            // list of events
            EventList                                       maList;

            // Flag which remembers if this timer is paused. Default
            // is false.
            bool                                            mbIsPaused;

        public:
            // constructor/destructor
            Scheduler();
            SVX_DLLPUBLIC virtual ~Scheduler();

            // From baseclass Timer, the timeout call
            SVX_DLLPUBLIC virtual void Timeout();

            // get time
            sal_uInt32 GetTime();

            // #i38135#
            void SetTime(sal_uInt32 nTime);

            // reset
            void Reset(sal_uInt32 nTime);

            // execute all ripe events, removes executed ones from the scheduler
            void triggerEvents();

            // re-start or stop timer according to event list
            void checkTimeout();

            // insert/remove events, wrapper to EventList methods
            void SVX_DLLPUBLIC InsertEvent(Event* pNew);
            void RemoveEvent(Event* pOld);

            // get/set pause
            bool IsPaused() const { return mbIsPaused; }
            void SetPaused(bool bNew);
        };
    } // end of namespace animation
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////

#endif //_SDR_ANIMATION_SCHEDULER_HXX

// eof
<|endoftext|>


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

#include "RCSResourceObject.h"
#include "OCPlatform.h"

using namespace OC::OCPlatform;
using namespace OIC::Service;

struct CloseApp{};

constexpr int RESOURCE_TEMP = 1;
constexpr int RESOURCE_LIGHT = 2;

constexpr int DEFALUT_SERVER = 1;
constexpr int CUSTOM_SERVER = 2;

constexpr int INCREASE = 1;
constexpr int DECREASE = 2;

const std::string BASELINE_INTERFACE = "oic.if.baseline";
const std::string ACTUATOR_INTERFACE = "oic.if.a";
const std::string SENSOR_INTERFACE = "oic.if.s";
const std::string CUSTOM_INTERFACE = "test.custom";

typedef void (*DisplayControlMenuFunc)();
typedef std::function<void()> Run;

Run g_currentRun;

bool g_isPresenceStarted = false;

RCSResourceObject::Ptr g_resource;

int processUserInput(int min, int max)
{
    assert(min <= max);

    int input;

    std::cin >> input;

    if (!std::cin.fail())
    {
        if(input == max + 1) throw CloseApp();
        if(min <= input && input <= max) return input;
    }

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    throw std::runtime_error("Invalid Input, please try again");
}

void displayControlTemperatureMenu()
{
    std::cout << "========================================================\n";
    std::cout << INCREASE << ". Increase Temperature by 1 degree          \n";
    std::cout << DECREASE << ". Decrease Temperature by 1 degree          \n";
    std::cout << DECREASE + 1 << ". Quit                                  \n";
    std::cout << "========================================================\n";
}

void displayControlLightMenu()
{
    std::cout << "========================================================\n";
    std::cout << INCREASE << ". Increase Brightness by 1 stage            \n";
    std::cout << DECREASE << ". Decrease Brightness by 1 stage            \n";
    std::cout << DECREASE + 1 << ". Quit                                  \n";
    std::cout << "========================================================\n";
}

void printAttributes(const RCSResourceAttributes& attrs)
{
    for(const auto& attr : attrs)
    {
        std::cout << "\tkey : " << attr.key() << "\n\tvalue : "
                  << attr.value().toString() << std::endl;
    }
}

RCSGetResponse requestHandlerForGet(const RCSRequest&, RCSResourceAttributes& attrs)
{
    std::cout << "Received a Get request from Client" << std::endl;
    printAttributes(attrs);

    {
        RCSResourceObject::LockGuard lock(g_resource);
        std::cout << "\nSending response to Client : " << std::endl;
        printAttributes(g_resource->getAttributes());
    }

    return RCSGetResponse::defaultAction();
}

RCSSetResponse requestHandlerForSet(const RCSRequest&, RCSResourceAttributes& attrs)
{
    std::cout << "Received a Set request from Client" << std::endl;
    printAttributes(attrs);

    return RCSSetResponse::defaultAction();
}

void initServer(const std::string& resourceUri, const std::string& resourceType,
        const std::string& attrKey)
{
    g_resource = RCSResourceObject::Builder(resourceUri, resourceType, ACTUATOR_INTERFACE)
            .addInterface(CUSTOM_INTERFACE)
            .addInterface(SENSOR_INTERFACE)
            .setDefaultInterface(BASELINE_INTERFACE)
            .setDiscoverable(true)
            .setObservable(true)
            .build();

    g_resource->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
    g_resource->setSetRequestHandlerPolicy(RCSResourceObject::SetRequestHandlerPolicy::NEVER);
    g_resource->setAttribute(attrKey, 0);
}

void updateAttribute(const std::string& attrKey, int control)
{
    const int diff = control == INCREASE ? 1 : - 1;

    {
        RCSResourceObject::LockGuard lock(g_resource);
        auto& attrs = g_resource->getAttributes();
        attrs[attrKey] = attrs[attrKey].get<int>() + diff;
    }

    if(control == INCREASE)
    {
        std::cout << attrKey << " increased." << std::endl;
    }
    else
    {
        std::cout << attrKey << " decreased." << std::endl;
    }
    std::cout << "\nCurrent " << attrKey << ": "
            << g_resource->getAttributeValue(attrKey).get<int>() << std::endl;
}

void runResourceControl(DisplayControlMenuFunc displayMenuFunc, const std::string& attrKey)
{
    displayMenuFunc();
    updateAttribute(attrKey, processUserInput(INCREASE, DECREASE));
}

void runResourceTypeSelection(int resourceMode)
{
    std::cout << "========================================================\n";
    std::cout << "Select Resource Type                                    \n";
    std::cout << RESOURCE_TEMP << ". Temperature                          \n";
    std::cout << RESOURCE_LIGHT << ". Light                               \n";
    std::cout << RESOURCE_LIGHT + 1 << ". Quit                            \n";
    std::cout << "========================================================\n";

    int resourceType = processUserInput(RESOURCE_TEMP, RESOURCE_LIGHT);
    DisplayControlMenuFunc displayMenuFunc;
    std::string attrKey;

    switch (resourceType)
    {
        case RESOURCE_TEMP:
            attrKey = "Temperature";
            initServer("/a/TempSensor", "oic.r.temperaturesensor", attrKey);

            displayMenuFunc = displayControlTemperatureMenu;
            break;

        case RESOURCE_LIGHT:
            attrKey = "Brightness";
            initServer("/a/light", "oic.r.light", attrKey);

            displayMenuFunc = displayControlLightMenu;
            break;
    }

    if (resourceMode == CUSTOM_SERVER)
    {
        g_resource->setGetRequestHandler(requestHandlerForGet);
        g_resource->setSetRequestHandler(requestHandlerForSet);
    }

    g_currentRun = std::bind(runResourceControl, displayMenuFunc, std::move(attrKey));
}

void runResourceModeSelection()
{
    std::cout << "========================================================          \n";
    std::cout << DEFALUT_SERVER << ". Creation of Simple Resource Without Handlers  \n";
    std::cout << CUSTOM_SERVER << ". Creation of Resource With Set and Get Handlers \n";
    std::cout << CUSTOM_SERVER + 1 << ". Quit                                       \n";
    std::cout << "========================================================          \n";

    g_currentRun = std::bind(runResourceTypeSelection,
            processUserInput(DEFALUT_SERVER, CUSTOM_SERVER));
}

void runPresenceSelection()
{
    constexpr int PRESENCE_ON = 1;
    constexpr int PRESENCE_OFF = 2;

    std::cout << "========================================================\n";
    std::cout << PRESENCE_ON << ". Presence On                            \n";
    std::cout << PRESENCE_OFF << ". Presence Off                          \n";
    std::cout << PRESENCE_OFF + 1 << ". Quit                              \n";
    std::cout << "========================================================\n";

    if (processUserInput(PRESENCE_ON, PRESENCE_OFF) == PRESENCE_ON)
    {
        g_isPresenceStarted = true;
        startPresence(3);
    }

    g_currentRun = runResourceModeSelection;
}

int main(void)
{
    g_currentRun = runPresenceSelection;

    while(true)
    {
        try
        {
            g_currentRun();
        }
        catch(const std::exception& e)
        {
            std::cout << e.what() << std::endl;
        }
        catch(const CloseApp&)
        {
            break;
        }
    }
    std::cout << "Stopping the server" << std::endl;

    g_resource.reset();

    if(g_isPresenceStarted)
    {
        stopPresence();
    }
}

<commit_msg>resource-container: Change file permission of SampleResource sources<commit_after>/******************************************************************
 *
 * Copyright 2015 Samsung Electronics All Rights Reserved.
 *
 *
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************/

#include "RCSResourceObject.h"
#include "OCPlatform.h"

using namespace OC::OCPlatform;
using namespace OIC::Service;

struct CloseApp{};

constexpr int RESOURCE_TEMP = 1;
constexpr int RESOURCE_LIGHT = 2;

constexpr int DEFALUT_SERVER = 1;
constexpr int CUSTOM_SERVER = 2;

constexpr int INCREASE = 1;
constexpr int DECREASE = 2;

const std::string BASELINE_INTERFACE = "oic.if.baseline";
const std::string ACTUATOR_INTERFACE = "oic.if.a";
const std::string SENSOR_INTERFACE = "oic.if.s";
const std::string CUSTOM_INTERFACE = "test.custom";

typedef void (*DisplayControlMenuFunc)();
typedef std::function<void()> Run;

Run g_currentRun;

bool g_isPresenceStarted = false;

RCSResourceObject::Ptr g_resource;

int processUserInput(int min, int max)
{
    assert(min <= max);

    int input;

    std::cin >> input;

    if (!std::cin.fail())
    {
        if(input == max + 1) throw CloseApp();
        if(min <= input && input <= max) return input;
    }

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    throw std::runtime_error("Invalid Input, please try again");
}

void displayControlTemperatureMenu()
{
    std::cout << "========================================================\n";
    std::cout << INCREASE << ". Increase Temperature by 1 degree          \n";
    std::cout << DECREASE << ". Decrease Temperature by 1 degree          \n";
    std::cout << DECREASE + 1 << ". Quit                                  \n";
    std::cout << "========================================================\n";
}

void displayControlLightMenu()
{
    std::cout << "========================================================\n";
    std::cout << INCREASE << ". Increase Brightness by 1 stage            \n";
    std::cout << DECREASE << ". Decrease Brightness by 1 stage            \n";
    std::cout << DECREASE + 1 << ". Quit                                  \n";
    std::cout << "========================================================\n";
}

void printAttributes(const RCSResourceAttributes& attrs)
{
    for(const auto& attr : attrs)
    {
        std::cout << "\tkey : " << attr.key() << "\n\tvalue : "
                  << attr.value().toString() << std::endl;
    }
}

RCSGetResponse requestHandlerForGet(const RCSRequest&, RCSResourceAttributes& attrs)
{
    std::cout << "Received a Get request from Client" << std::endl;
    printAttributes(attrs);

    {
        RCSResourceObject::LockGuard lock(g_resource);
        std::cout << "\nSending response to Client : " << std::endl;
        printAttributes(g_resource->getAttributes());
    }

    return RCSGetResponse::defaultAction();
}

RCSSetResponse requestHandlerForSet(const RCSRequest&, RCSResourceAttributes& attrs)
{
    std::cout << "Received a Set request from Client" << std::endl;
    printAttributes(attrs);

    return RCSSetResponse::defaultAction();
}

void initServer(const std::string& resourceUri, const std::string& resourceType,
        const std::string& attrKey)
{
    g_resource = RCSResourceObject::Builder(resourceUri, resourceType, ACTUATOR_INTERFACE)
            .addInterface(CUSTOM_INTERFACE)
            .addInterface(SENSOR_INTERFACE)
            .setDefaultInterface(BASELINE_INTERFACE)
            .setDiscoverable(true)
            .setObservable(true)
            .build();

    g_resource->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
    g_resource->setSetRequestHandlerPolicy(RCSResourceObject::SetRequestHandlerPolicy::NEVER);
    g_resource->setAttribute(attrKey, 0);
}

void updateAttribute(const std::string& attrKey, int control)
{
    const int diff = control == INCREASE ? 1 : - 1;

    {
        RCSResourceObject::LockGuard lock(g_resource);
        auto& attrs = g_resource->getAttributes();
        attrs[attrKey] = attrs[attrKey].get<int>() + diff;
    }

    if(control == INCREASE)
    {
        std::cout << attrKey << " increased." << std::endl;
    }
    else
    {
        std::cout << attrKey << " decreased." << std::endl;
    }
    std::cout << "\nCurrent " << attrKey << ": "
            << g_resource->getAttributeValue(attrKey).get<int>() << std::endl;
}

void runResourceControl(DisplayControlMenuFunc displayMenuFunc, const std::string& attrKey)
{
    displayMenuFunc();
    updateAttribute(attrKey, processUserInput(INCREASE, DECREASE));
}

void runResourceTypeSelection(int resourceMode)
{
    std::cout << "========================================================\n";
    std::cout << "Select Resource Type                                    \n";
    std::cout << RESOURCE_TEMP << ". Temperature                          \n";
    std::cout << RESOURCE_LIGHT << ". Light                               \n";
    std::cout << RESOURCE_LIGHT + 1 << ". Quit                            \n";
    std::cout << "========================================================\n";

    int resourceType = processUserInput(RESOURCE_TEMP, RESOURCE_LIGHT);
    DisplayControlMenuFunc displayMenuFunc;
    std::string attrKey;

    switch (resourceType)
    {
        case RESOURCE_TEMP:
            attrKey = "Temperature";
            initServer("/a/TempSensor", "oic.r.temperaturesensor", attrKey);

            displayMenuFunc = displayControlTemperatureMenu;
            break;

        case RESOURCE_LIGHT:
            attrKey = "Brightness";
            initServer("/a/light", "oic.r.light", attrKey);

            displayMenuFunc = displayControlLightMenu;
            break;
    }

    if (resourceMode == CUSTOM_SERVER)
    {
        g_resource->setGetRequestHandler(requestHandlerForGet);
        g_resource->setSetRequestHandler(requestHandlerForSet);
    }

    g_currentRun = std::bind(runResourceControl, displayMenuFunc, std::move(attrKey));
}

void runResourceModeSelection()
{
    std::cout << "========================================================          \n";
    std::cout << DEFALUT_SERVER << ". Creation of Simple Resource Without Handlers  \n";
    std::cout << CUSTOM_SERVER << ". Creation of Resource With Set and Get Handlers \n";
    std::cout << CUSTOM_SERVER + 1 << ". Quit                                       \n";
    std::cout << "========================================================          \n";

    g_currentRun = std::bind(runResourceTypeSelection,
            processUserInput(DEFALUT_SERVER, CUSTOM_SERVER));
}

void runPresenceSelection()
{
    constexpr int PRESENCE_ON = 1;
    constexpr int PRESENCE_OFF = 2;

    std::cout << "========================================================\n";
    std::cout << PRESENCE_ON << ". Presence On                            \n";
    std::cout << PRESENCE_OFF << ". Presence Off                          \n";
    std::cout << PRESENCE_OFF + 1 << ". Quit                              \n";
    std::cout << "========================================================\n";

    if (processUserInput(PRESENCE_ON, PRESENCE_OFF) == PRESENCE_ON)
    {
        g_isPresenceStarted = true;
        startPresence(3);
    }

    g_currentRun = runResourceModeSelection;
}

int main(void)
{
    g_currentRun = runPresenceSelection;

    while(true)
    {
        try
        {
            g_currentRun();
        }
        catch(const std::exception& e)
        {
            std::cout << e.what() << std::endl;
        }
        catch(const CloseApp&)
        {
            break;
        }
    }
    std::cout << "Stopping the server" << std::endl;

    g_resource.reset();

    if(g_isPresenceStarted)
    {
        stopPresence();
    }
}

<|endoftext|>


<commit_before>/**
 * Filter Traffic DPDK example application
 * =======================================
 * An application that listens to one or more DPDK ports (a.k.a DPDK devices), captures all traffic
 * and matches packets by user-defined matching criteria. Matching criteria is given on startup and can contain one or more of the following:
 * source IP, destination IP, source TCP/UDP port, destination TCP/UDP port and TCP or UDP protocol. Matching is done per flow, meaning the first packet
 * received on a flow is matched against the matching criteria and if it's matched then all packets of the same flow will be matched too.
 * Packets that are matched can be send to a DPDK port and/or be save to a pcap file.
 * In addition the application collect statistics on received and matched packets: number of packets per protocol, number of matched flows and number
 * of matched packets.
 *
 * The application uses the concept of worker threads. Number of cores can be set by the user or set to default (default is all machine cores minus one
 * management core). Each core is assigned with one worker thread. The application divides the DPDK ports and RX queues equally between worker threads.
 * For example: if there are 2 DPDK ports to listen to, each one with 6 RX queues and there are 3 worker threads, then worker #1 will get RX queues
 * 1-4 of port 1, worker #2 will get RX queues 5-6 of port 1 and RX queues 1-2 of port 2, and worker #3 will get RX queues 3-6 of port 2.
 * Each worker thread does exactly the same work: receiving packets, collecting packet statistics, matching flows and sending/saving matched packets
 *
 * __Important__: this application (like all applications using DPDK) should be run as 'sudo'
 */

#include "Common.h"
#include "AppWorkerThread.h"

#include "DpdkDeviceList.h"
#include "IPv4Layer.h"
#include "TcpLayer.h"
#include "UdpLayer.h"
#include "SystemUtils.h"
#include "PcapPlusPlusVersion.h"
#include "TablePrinter.h"

#include <vector>
#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <signal.h>
#include <getopt.h>
#include <string>
#include <sstream>
#include <unistd.h>

using namespace pcpp;

#define DEFAULT_MBUF_POOL_SIZE 4095

static struct option FilterTrafficOptions[] =
{
	{"dpdk-ports",  required_argument, 0, 'd'},
	{"core-mask",  optional_argument, 0, 'c'},
	{"mbuf-pool-size",  optional_argument, 0, 'm'},
	{"help", optional_argument, 0, 'h'},
	{"version", optional_argument, 0, 'v'},
	{"list", optional_argument, 0, 'l'},
	{0, 0, 0, 0}
};

/**
 * Print application usage
 */
void printUsage()
{
	printf("\nUsage:\n"
                 "------\n"
                        "%s [-hvl] [-c CORE_MASK] [-m POOL_SIZE] -d PORT_1,PORT_2\n"
			"\nOptions:\n\n"
			"    -h|--help                                  : Displays this help message and exits\n"
                        "    -v|--version                               : Displays the current version and exits\n"
			"    -l|--list                                  : Print the list of DPDK ports and exists\n"
			"    -d|--dpdk-ports PORT_1,PORT_2              : A comma-separated list of two DPDK port numbers to be bridged.\n"
			"                                                 To see all available DPDK ports use the -l switch\n"
			"    -c|--core-mask            CORE_MASK        : Core mask of cores to use. For example: use 7 (binary 0111) to use cores 0,1,2.\n"
			"                                                 Default is using all cores except management core\n"
			"    -m|--mbuf-pool-size       POOL_SIZE        : DPDK mBuf pool size to initialize DPDK with. Default value is 4095\n\n", AppName::get().c_str());
}

/**
 * Print application version
 */
void printAppVersion()
{
	printf("%s %s\n", AppName::get().c_str(), getPcapPlusPlusVersionFull().c_str());
	printf("Built: %s\n", getBuildDateTime().c_str());
	printf("Built from: %s\n", getGitInfo().c_str());
	exit(0);
}

/**
 * Print to console all available DPDK ports. Used by the -l switch
 */
void listDpdkPorts()
{
	CoreMask coreMaskToUse = getCoreMaskForAllMachineCores();

	// initialize DPDK
	if (!DpdkDeviceList::initDpdk(coreMaskToUse, DEFAULT_MBUF_POOL_SIZE))
	{
		EXIT_WITH_ERROR("couldn't initialize DPDK");
	}

	printf("DPDK port list:\n");

	// go over all available DPDK devices and print info for each one
	vector<DpdkDevice*> deviceList = DpdkDeviceList::getInstance().getDpdkDeviceList();
	for (vector<DpdkDevice*>::iterator iter = deviceList.begin(); iter != deviceList.end(); iter++)
	{
		DpdkDevice* dev = *iter;
		printf("    Port #%d: MAC address='%s'; PCI address='%s'; PMD='%s'\n",
				dev->getDeviceId(),
				dev->getMacAddress().toString().c_str(),
				dev->getPciAddress().toString().c_str(),
				dev->getPMDName().c_str());
	}
}

struct DpdkBridgeArgs
{
	bool shouldStop;
	std::vector<DpdkWorkerThread*>* workerThreadsVector;

	DpdkBridgeArgs() : shouldStop(false), workerThreadsVector(NULL) {}
};

/**
 * The callback to be called when application is terminated by ctrl-c. Do cleanup and print summary stats
 */
void onApplicationInterrupted(void* cookie)
{
	DpdkBridgeArgs* args = (DpdkBridgeArgs*)cookie;

	printf("\n\nApplication stopped\n");

	// stop worker threads
	DpdkDeviceList::getInstance().stopDpdkWorkerThreads();

	// create table printer
	std::vector<std::string> columnNames;
	std::vector<int> columnWidths;
	PacketStats::getStatsColumns(columnNames, columnWidths);
	TablePrinter printer(columnNames, columnWidths);

	// print final stats for every worker thread plus sum of all threads and free worker threads memory
	PacketStats aggregatedStats;
	for (std::vector<DpdkWorkerThread*>::iterator iter = args->workerThreadsVector->begin(); iter != args->workerThreadsVector->end(); iter++)
	{
		AppWorkerThread* thread = (AppWorkerThread*)(*iter);
		PacketStats threadStats = thread->getStats();
		aggregatedStats.collectStats(threadStats);
		printer.printRow(threadStats.getStatValuesAsString("|"), '|');
		delete thread;
	}

	printer.printSeparator();
	printer.printRow(aggregatedStats.getStatValuesAsString("|"), '|');

	args->shouldStop = true;
}

/**
 * main method of the application. Responsible for parsing user args, preparing worker thread configuration, creating the worker threads and activate them.
 * At program termination worker threads are stopped, statistics are collected from them and printed to console
 */
int main(int argc, char* argv[])
{
	AppName::init(argc, argv);

	std::vector<int> dpdkPortVec;

	CoreMask coreMaskToUse = getCoreMaskForAllMachineCores();

	int sendPacketsToPort = -1;

	int optionIndex = 0;
	char opt = 0;

	uint32_t mBufPoolSize = DEFAULT_MBUF_POOL_SIZE;

	while((opt = getopt_long (argc, argv, "d:c:m:hvl", FilterTrafficOptions, &optionIndex)) != -1)
	{
		switch (opt)
		{
			case 0:
			{
				break;
			}
			case 'd':
			{
				string portListAsString = string(optarg);
				stringstream stream(portListAsString);
				string portAsString;
				int port;
				// break comma-separated string into string list
				while(getline(stream, portAsString, ','))
				{
					char c;
					std::stringstream stream2(portAsString);
					stream2 >> port;
					if (stream2.fail() || stream2.get(c))
					{
						// not an integer
						EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is invalid");
					}
					dpdkPortVec.push_back(port);
				}
				// verify list contains two ports
				if(dpdkPortVec.size()!=2)
				{
					EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK list must contain two values");
				}
				break;
			}
			case 'c':
			{
				coreMaskToUse = atoi(optarg);
				break;
			}
			case 'm':
			{
				mBufPoolSize = atoi(optarg);
				break;
			}
			case 'h':
			{
				printUsage();
				exit(0);
			}
			case 'v':
			{
				printAppVersion();
				break;
			}
			case 'l':
			{
				listDpdkPorts();
				exit(0);
			}
			default:
			{
				printUsage();
				exit(0);
			}
		}
	}

	// verify list is not empty
	if (dpdkPortVec.empty())
	{
		EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is empty. Please use the -d switch");
	}

	// extract core vector from core mask
	vector<SystemCore> coresToUse;
	createCoreVectorFromCoreMask(coreMaskToUse, coresToUse);

	// need minimum of 2 cores to start - 1 management core + 1 (or more) worker thread(s)
	if (coresToUse.size() < 2)
	{
		EXIT_WITH_ERROR("Needed minimum of 2 cores to start the application");
	}

	// initialize DPDK
	if (!DpdkDeviceList::initDpdk(coreMaskToUse, mBufPoolSize))
	{
		EXIT_WITH_ERROR("Couldn't initialize DPDK");
	}

	// removing DPDK master core from core mask because DPDK worker threads cannot run on master core
	coreMaskToUse = coreMaskToUse & ~(DpdkDeviceList::getInstance().getDpdkMasterCore().Mask);

	// re-calculate cores to use after removing master core
	coresToUse.clear();
	createCoreVectorFromCoreMask(coreMaskToUse, coresToUse);

	// collect the list of DPDK devices
	vector<DpdkDevice*> dpdkDevicesToUse;
	for (vector<int>::iterator iter = dpdkPortVec.begin(); iter != dpdkPortVec.end(); iter++)
	{
		DpdkDevice* dev = DpdkDeviceList::getInstance().getDeviceByPort(*iter);
		if (dev == NULL)
		{
			EXIT_WITH_ERROR("DPDK device for port %d doesn't exist", *iter);
		}
		dpdkDevicesToUse.push_back(dev);
	}

	// go over all devices and open them
	for (vector<DpdkDevice*>::iterator iter = dpdkDevicesToUse.begin(); iter != dpdkDevicesToUse.end(); iter++)
	{
		if (!(*iter)->openMultiQueues(1,1))
		{
			EXIT_WITH_ERROR("Couldn't open DPDK device #%d, PMD '%s'", (*iter)->getDeviceId(), (*iter)->getPMDName().c_str());
		}
	}

	// get DPDK device to send packets to (or NULL if doesn't exist)
	DpdkDevice* sendPacketsTo = DpdkDeviceList::getInstance().getDeviceByPort(sendPacketsToPort);
	if (sendPacketsTo != NULL && !sendPacketsTo->isOpened() &&  !sendPacketsTo->open())
	{
		EXIT_WITH_ERROR("Could not open port#%d for sending matched packets", sendPacketsToPort);
	}

	// prepare configuration for every core
	AppWorkerConfig workerConfigArr[2];
	workerConfigArr[0].CoreId = coresToUse.at(0).Id;
	workerConfigArr[0].RxDevice = dpdkDevicesToUse.at(0);
	workerConfigArr[0].TxDevice = dpdkDevicesToUse.at(1);
	workerConfigArr[1].CoreId = coresToUse.at(1).Id;
	workerConfigArr[1].RxDevice = dpdkDevicesToUse.at(1);
	workerConfigArr[1].TxDevice = dpdkDevicesToUse.at(0);

	// create worker thread for every core
	vector<DpdkWorkerThread*> workerThreadVec;
	workerThreadVec.push_back(new AppWorkerThread(workerConfigArr[0]));
	workerThreadVec.push_back(new AppWorkerThread(workerConfigArr[1]));

	// start all worker threads
	if (!DpdkDeviceList::getInstance().startDpdkWorkerThreads(coreMaskToUse, workerThreadVec))
	{
		EXIT_WITH_ERROR("Couldn't start worker threads");
	}

	// register the on app close event to print summary stats on app termination
	DpdkBridgeArgs args;
	args.workerThreadsVector = &workerThreadVec;
	ApplicationEventHandler::getInstance().onApplicationInterrupted(onApplicationInterrupted, &args);

	// infinite loop (until program is terminated)
	while (!args.shouldStop)
	{
		sleep(5);
	}
}
<commit_msg>Fix minimun core quantity validation<commit_after>/**
 * Filter Traffic DPDK example application
 * =======================================
 * An application that listens to one or more DPDK ports (a.k.a DPDK devices), captures all traffic
 * and matches packets by user-defined matching criteria. Matching criteria is given on startup and can contain one or more of the following:
 * source IP, destination IP, source TCP/UDP port, destination TCP/UDP port and TCP or UDP protocol. Matching is done per flow, meaning the first packet
 * received on a flow is matched against the matching criteria and if it's matched then all packets of the same flow will be matched too.
 * Packets that are matched can be send to a DPDK port and/or be save to a pcap file.
 * In addition the application collect statistics on received and matched packets: number of packets per protocol, number of matched flows and number
 * of matched packets.
 *
 * The application uses the concept of worker threads. Number of cores can be set by the user or set to default (default is all machine cores minus one
 * management core). Each core is assigned with one worker thread. The application divides the DPDK ports and RX queues equally between worker threads.
 * For example: if there are 2 DPDK ports to listen to, each one with 6 RX queues and there are 3 worker threads, then worker #1 will get RX queues
 * 1-4 of port 1, worker #2 will get RX queues 5-6 of port 1 and RX queues 1-2 of port 2, and worker #3 will get RX queues 3-6 of port 2.
 * Each worker thread does exactly the same work: receiving packets, collecting packet statistics, matching flows and sending/saving matched packets
 *
 * __Important__: this application (like all applications using DPDK) should be run as 'sudo'
 */

#include "Common.h"
#include "AppWorkerThread.h"

#include "DpdkDeviceList.h"
#include "IPv4Layer.h"
#include "TcpLayer.h"
#include "UdpLayer.h"
#include "SystemUtils.h"
#include "PcapPlusPlusVersion.h"
#include "TablePrinter.h"

#include <vector>
#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <signal.h>
#include <getopt.h>
#include <string>
#include <sstream>
#include <unistd.h>

using namespace pcpp;

#define DEFAULT_MBUF_POOL_SIZE 4095

static struct option FilterTrafficOptions[] =
{
	{"dpdk-ports",  required_argument, 0, 'd'},
	{"core-mask",  optional_argument, 0, 'c'},
	{"mbuf-pool-size",  optional_argument, 0, 'm'},
	{"help", optional_argument, 0, 'h'},
	{"version", optional_argument, 0, 'v'},
	{"list", optional_argument, 0, 'l'},
	{0, 0, 0, 0}
};

/**
 * Print application usage
 */
void printUsage()
{
	printf("\nUsage:\n"
                 "------\n"
                        "%s [-hvl] [-c CORE_MASK] [-m POOL_SIZE] -d PORT_1,PORT_2\n"
			"\nOptions:\n\n"
			"    -h|--help                                  : Displays this help message and exits\n"
                        "    -v|--version                               : Displays the current version and exits\n"
			"    -l|--list                                  : Print the list of DPDK ports and exists\n"
			"    -d|--dpdk-ports PORT_1,PORT_2              : A comma-separated list of two DPDK port numbers to be bridged.\n"
			"                                                 To see all available DPDK ports use the -l switch\n"
			"    -c|--core-mask            CORE_MASK        : Core mask of cores to use. For example: use 7 (binary 0111) to use cores 0,1,2.\n"
			"                                                 Default is using all cores except management core\n"
			"    -m|--mbuf-pool-size       POOL_SIZE        : DPDK mBuf pool size to initialize DPDK with. Default value is 4095\n\n", AppName::get().c_str());
}

/**
 * Print application version
 */
void printAppVersion()
{
	printf("%s %s\n", AppName::get().c_str(), getPcapPlusPlusVersionFull().c_str());
	printf("Built: %s\n", getBuildDateTime().c_str());
	printf("Built from: %s\n", getGitInfo().c_str());
	exit(0);
}

/**
 * Print to console all available DPDK ports. Used by the -l switch
 */
void listDpdkPorts()
{
	CoreMask coreMaskToUse = getCoreMaskForAllMachineCores();

	// initialize DPDK
	if (!DpdkDeviceList::initDpdk(coreMaskToUse, DEFAULT_MBUF_POOL_SIZE))
	{
		EXIT_WITH_ERROR("couldn't initialize DPDK");
	}

	printf("DPDK port list:\n");

	// go over all available DPDK devices and print info for each one
	vector<DpdkDevice*> deviceList = DpdkDeviceList::getInstance().getDpdkDeviceList();
	for (vector<DpdkDevice*>::iterator iter = deviceList.begin(); iter != deviceList.end(); iter++)
	{
		DpdkDevice* dev = *iter;
		printf("    Port #%d: MAC address='%s'; PCI address='%s'; PMD='%s'\n",
				dev->getDeviceId(),
				dev->getMacAddress().toString().c_str(),
				dev->getPciAddress().toString().c_str(),
				dev->getPMDName().c_str());
	}
}

struct DpdkBridgeArgs
{
	bool shouldStop;
	std::vector<DpdkWorkerThread*>* workerThreadsVector;

	DpdkBridgeArgs() : shouldStop(false), workerThreadsVector(NULL) {}
};

/**
 * The callback to be called when application is terminated by ctrl-c. Do cleanup and print summary stats
 */
void onApplicationInterrupted(void* cookie)
{
	DpdkBridgeArgs* args = (DpdkBridgeArgs*)cookie;

	printf("\n\nApplication stopped\n");

	// stop worker threads
	DpdkDeviceList::getInstance().stopDpdkWorkerThreads();

	// create table printer
	std::vector<std::string> columnNames;
	std::vector<int> columnWidths;
	PacketStats::getStatsColumns(columnNames, columnWidths);
	TablePrinter printer(columnNames, columnWidths);

	// print final stats for every worker thread plus sum of all threads and free worker threads memory
	PacketStats aggregatedStats;
	for (std::vector<DpdkWorkerThread*>::iterator iter = args->workerThreadsVector->begin(); iter != args->workerThreadsVector->end(); iter++)
	{
		AppWorkerThread* thread = (AppWorkerThread*)(*iter);
		PacketStats threadStats = thread->getStats();
		aggregatedStats.collectStats(threadStats);
		printer.printRow(threadStats.getStatValuesAsString("|"), '|');
		delete thread;
	}

	printer.printSeparator();
	printer.printRow(aggregatedStats.getStatValuesAsString("|"), '|');

	args->shouldStop = true;
}

/**
 * main method of the application. Responsible for parsing user args, preparing worker thread configuration, creating the worker threads and activate them.
 * At program termination worker threads are stopped, statistics are collected from them and printed to console
 */
int main(int argc, char* argv[])
{
	AppName::init(argc, argv);

	std::vector<int> dpdkPortVec;

	CoreMask coreMaskToUse = getCoreMaskForAllMachineCores();

	int sendPacketsToPort = -1;

	int optionIndex = 0;
	char opt = 0;

	uint32_t mBufPoolSize = DEFAULT_MBUF_POOL_SIZE;

	while((opt = getopt_long (argc, argv, "d:c:m:hvl", FilterTrafficOptions, &optionIndex)) != -1)
	{
		switch (opt)
		{
			case 0:
			{
				break;
			}
			case 'd':
			{
				string portListAsString = string(optarg);
				stringstream stream(portListAsString);
				string portAsString;
				int port;
				// break comma-separated string into string list
				while(getline(stream, portAsString, ','))
				{
					char c;
					std::stringstream stream2(portAsString);
					stream2 >> port;
					if (stream2.fail() || stream2.get(c))
					{
						// not an integer
						EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is invalid");
					}
					dpdkPortVec.push_back(port);
				}
				// verify list contains two ports
				if(dpdkPortVec.size()!=2)
				{
					EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK list must contain two values");
				}
				break;
			}
			case 'c':
			{
				coreMaskToUse = atoi(optarg);
				break;
			}
			case 'm':
			{
				mBufPoolSize = atoi(optarg);
				break;
			}
			case 'h':
			{
				printUsage();
				exit(0);
			}
			case 'v':
			{
				printAppVersion();
				break;
			}
			case 'l':
			{
				listDpdkPorts();
				exit(0);
			}
			default:
			{
				printUsage();
				exit(0);
			}
		}
	}

	// verify list is not empty
	if (dpdkPortVec.empty())
	{
		EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is empty. Please use the -d switch");
	}

	// extract core vector from core mask
	vector<SystemCore> coresToUse;
	createCoreVectorFromCoreMask(coreMaskToUse, coresToUse);

	// need minimum of 3 cores to start - 1 management core + 1 (or more) worker thread(s)
	if (coresToUse.size() < 3)
	{
		EXIT_WITH_ERROR("Needed minimum of 3 cores to start the application");
	}

	// initialize DPDK
	if (!DpdkDeviceList::initDpdk(coreMaskToUse, mBufPoolSize))
	{
		EXIT_WITH_ERROR("Couldn't initialize DPDK");
	}

	// removing DPDK master core from core mask because DPDK worker threads cannot run on master core
	coreMaskToUse = coreMaskToUse & ~(DpdkDeviceList::getInstance().getDpdkMasterCore().Mask);

	// re-calculate cores to use after removing master core
	coresToUse.clear();
	createCoreVectorFromCoreMask(coreMaskToUse, coresToUse);

	// collect the list of DPDK devices
	vector<DpdkDevice*> dpdkDevicesToUse;
	for (vector<int>::iterator iter = dpdkPortVec.begin(); iter != dpdkPortVec.end(); iter++)
	{
		DpdkDevice* dev = DpdkDeviceList::getInstance().getDeviceByPort(*iter);
		if (dev == NULL)
		{
			EXIT_WITH_ERROR("DPDK device for port %d doesn't exist", *iter);
		}
		dpdkDevicesToUse.push_back(dev);
	}

	// go over all devices and open them
	for (vector<DpdkDevice*>::iterator iter = dpdkDevicesToUse.begin(); iter != dpdkDevicesToUse.end(); iter++)
	{
		if (!(*iter)->openMultiQueues(1,1))
		{
			EXIT_WITH_ERROR("Couldn't open DPDK device #%d, PMD '%s'", (*iter)->getDeviceId(), (*iter)->getPMDName().c_str());
		}
	}

	// get DPDK device to send packets to (or NULL if doesn't exist)
	DpdkDevice* sendPacketsTo = DpdkDeviceList::getInstance().getDeviceByPort(sendPacketsToPort);
	if (sendPacketsTo != NULL && !sendPacketsTo->isOpened() &&  !sendPacketsTo->open())
	{
		EXIT_WITH_ERROR("Could not open port#%d for sending matched packets", sendPacketsToPort);
	}

	// prepare configuration for every core
	AppWorkerConfig workerConfigArr[2];
	workerConfigArr[0].CoreId = coresToUse.at(0).Id;
	workerConfigArr[0].RxDevice = dpdkDevicesToUse.at(0);
	workerConfigArr[0].TxDevice = dpdkDevicesToUse.at(1);
	workerConfigArr[1].CoreId = coresToUse.at(1).Id;
	workerConfigArr[1].RxDevice = dpdkDevicesToUse.at(1);
	workerConfigArr[1].TxDevice = dpdkDevicesToUse.at(0);

	// create worker thread for every core
	vector<DpdkWorkerThread*> workerThreadVec;
	workerThreadVec.push_back(new AppWorkerThread(workerConfigArr[0]));
	workerThreadVec.push_back(new AppWorkerThread(workerConfigArr[1]));

	// start all worker threads
	if (!DpdkDeviceList::getInstance().startDpdkWorkerThreads(coreMaskToUse, workerThreadVec))
	{
		EXIT_WITH_ERROR("Couldn't start worker threads");
	}

	// register the on app close event to print summary stats on app termination
	DpdkBridgeArgs args;
	args.workerThreadsVector = &workerThreadVec;
	ApplicationEventHandler::getInstance().onApplicationInterrupted(onApplicationInterrupted, &args);

	// infinite loop (until program is terminated)
	while (!args.shouldStop)
	{
		sleep(5);
	}
}
<|endoftext|>


<commit_before>// -*- mode: c++; c-basic-offset:4 -*-

// This file is part of libdap, A C++ implementation of the OPeNDAP Data
// Access Protocol.

// Copyright (c) 2013 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.

#include "config.h"

#include <cppunit/TestFixture.h>
#include <cppunit/TestAssert.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/CompilerOutputter.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <stdint.h>

#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstring>

#include "D4StreamUnMarshaller.h"

#include "Type.h"

#include "GetOpt.h"
#include "debug.h"
#include "test_config.h"

static bool debug = false;

#undef DBG
#define DBG(x) do { if (debug) (x); } while(false);

#if WORDS_BIGENDIAN
const static string path = string(TEST_SRC_DIR) + "/D4-marshaller/big-endian";
#else
const static string path = string(TEST_SRC_DIR) + "/D4-marshaller/little-endian";
#endif

using namespace std;
using namespace libdap;
using namespace CppUnit;

class D4UnMarshallerTest: public CppUnit::TestFixture {

    CPPUNIT_TEST_SUITE (D4UnMarshallerTest);

    CPPUNIT_TEST (test_scalars);
    CPPUNIT_TEST (test_real_scalars);
    CPPUNIT_TEST (test_str);
    CPPUNIT_TEST (test_opaque);
    CPPUNIT_TEST (test_vector);

    CPPUNIT_TEST_SUITE_END( );

    static inline bool is_host_big_endian()
    {
#ifdef COMPUTE_ENDIAN_AT_RUNTIME

        dods_int16 i = 0x0100;
        char *c = reinterpret_cast<char*>(&i);
        return *c;

#else

#ifdef __BIG_ENDIAN__
        return true;
#else
        return false;
#endif

#endif
    }

public:
    D4UnMarshallerTest()
    {
    }

    void setUp()
    {
    }

    void tearDown()
    {
    }

    void test_scalars()
    {
        fstream in;
        in.exceptions(ostream::failbit | ostream::badbit);

        // computes checksums and writes data
        try {
            string file = path + "/test_scalars_1_bin.dat";
            DBG(cerr << "file: " << file << endl);
            in.open(file.c_str(), fstream::binary | fstream::in);

            // Don't use is_host_big_endian() because these tests should
            // never 'twiddle bytes' They are always testing little to little
            // of big to big
            D4StreamUnMarshaller dsm(in, 0 /*is_host_big_endian()*/);

            dods_byte b;
            dsm.get_byte(b);
            CPPUNIT_ASSERT(b == 17);
            string ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            // Same checksum for both big- and little-endian
            CPPUNIT_ASSERT(ck == "b8b2cf7f");

            dods_int16 i1;
            dsm.get_int16(i1);
            CPPUNIT_ASSERT(i1 == 17);
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            // little-endian || big-endian checksum values
            CPPUNIT_ASSERT(ck == "120031ef" || ck == "2b69320d");

            dods_int32 i2;
            dsm.get_int32(i2);
            CPPUNIT_ASSERT(i2 == 17);
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "c9e1efe6" || ck == "4bf4ffee");

            dods_int64 i3;
            dsm.get_int64(i3);
            CPPUNIT_ASSERT(i3 == 17);
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "d533eedc" || ck == "0f92ff9b");

            dods_uint16 ui1;
            dsm.get_uint16(ui1);
            CPPUNIT_ASSERT(ui1 == 17);
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "120031ef" || ck == "2b69320d");

            dods_uint32 ui2;
            dsm.get_uint32(ui2);
            CPPUNIT_ASSERT(ui2 == 17);
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "c9e1efe6" || ck == "4bf4ffee");

            dods_uint64 ui3;
            dsm.get_uint64(ui3);
            CPPUNIT_ASSERT(ui3 == 17);
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "d533eedc" || ck == "0f92ff9b");
        }
        catch (Error &e) {
            cerr << "Error: " << e.get_error_message() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
        catch (istream::failure &e) {
            cerr << "File error: " << e.what() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
    }

    void test_real_scalars()
    {
        fstream in;
        in.exceptions(ostream::failbit | ostream::badbit);

        // computes checksums and writes data
        try {
            string file = path + "/test_scalars_2_bin.dat";
            in.open(file.c_str(), fstream::binary | fstream::in);
            D4StreamUnMarshaller dsm(in, 0);

            dods_float32 r1;
            dsm.get_float32(r1);
            CPPUNIT_ASSERT(r1 == 17.0);
            string ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "d3c5bc59" || ck == "edcaaa7c");

            dods_float64 r2;
            dsm.get_float64(r2);
            CPPUNIT_ASSERT(r2 == 17.0);
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "d5a3994b" || ck == "42abb362");
        }
        catch (Error &e) {
            cerr << "Error: " << e.get_error_message() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
        catch (istream::failure &e) {
            cerr << "File error: " << e.what() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
    }

    void test_str()
    {
        fstream in;
        in.exceptions(ostream::failbit | ostream::badbit);

        // computes checksums and writes data
        try {
            string file = path + "/test_scalars_3_bin.dat";
            in.open(file.c_str(), fstream::binary | fstream::in);
            D4StreamUnMarshaller dsm(in, 0);

            string s;
            dsm.get_str(s);
            CPPUNIT_ASSERT(s == "This is a test string with 40 characters");
            string ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "af117544");

            string u;
            dsm.get_url(u);
            CPPUNIT_ASSERT(u == "http://www.opendap.org/lame/unit/test");
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "41e10081");
        }
        catch (Error &e) {
            cerr << "Error: " << e.get_error_message() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
        catch (istream::failure &e) {
            cerr << "File error: " << e.what() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
    }

    void test_opaque()
    {
        fstream in;
        in.exceptions(ostream::failbit | ostream::badbit);

        // computes checksums and writes data
        try {
            string file = path + "/test_opaque_1_bin.dat";
            in.open(file.c_str(), fstream::binary | fstream::in);
            D4StreamUnMarshaller dsm(in, 0);

            char *buf2;
            int64_t len;
            dsm.get_opaque_dap4(&buf2, len);
            CPPUNIT_ASSERT(len == 32768);
            for (int i = 0; i < 32768; ++i)
                CPPUNIT_ASSERT(buf2[i] == i % (1 << 7));
            string ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "199ad7f5");

            delete buf2;
        }
        catch (Error &e) {
            cerr << "Error: " << e.get_error_message() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
        catch (istream::failure &e) {
            cerr << "File error: " << e.what() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
    }

    void test_vector()
    {
        fstream in;
        in.exceptions(ostream::failbit | ostream::badbit);

        // computes checksums and writes data
        try {
            string file = path + "/test_vector_1_bin.dat";
            in.open(file.c_str(), fstream::binary | fstream::in);
            D4StreamUnMarshaller dsm(in, 0);

            vector<unsigned char> buf1(32768);
            dsm.get_vector(reinterpret_cast<char*>(&buf1[0]), 32768);
            for (int i = 0; i < 32768; ++i)
                CPPUNIT_ASSERT(buf1[i] == i % (1 << 7));
            string ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "199ad7f5" || ck == "199ad7f5");

            vector<dods_int32> buf2(32768);
            dsm.get_vector(reinterpret_cast<char*>(&buf2[0]), 32768, sizeof(dods_int32));
            for (int i = 0; i < 32768; ++i)
                CPPUNIT_ASSERT(buf2[i] == i % (1 << 9));
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "5c1bf29f" || ck == "8efd2d3d");

            vector<dods_float64> buf3(32768);
            dsm.get_vector_float64(reinterpret_cast<char*>(&buf3[0]), 32768);
            for (int i = 0; i < 32768; ++i) {
                if (buf3[i] != i % (1 << 9)) cerr << "buf3[" << i << "]: " << buf3[i] << endl;
                CPPUNIT_ASSERT(buf3[i] == i % (1 << 9));
            }
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "aafc2a91" || ck == "7bdf9931");
        }
        catch (Error &e) {
            cerr << "Error: " << e.get_error_message() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
        catch (istream::failure &e) {
            cerr << "File error: " << e.what() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
    }

};

CPPUNIT_TEST_SUITE_REGISTRATION (D4UnMarshallerTest);

int main(int argc, char*argv[])
{
    GetOpt getopt(argc, argv, "dh");
    int option_char;

    while ((option_char = getopt()) != -1)
        switch (option_char) {
        case 'd':
            debug = true;  // debug is a static global
            break;
        case 'h': {     // help - show test names
            cerr << "Usage: D4UnMarshallerTest has the following tests:" << endl;
            const std::vector<Test*> &tests = D4UnMarshallerTest::suite()->getTests();
            unsigned int prefix_len = D4UnMarshallerTest::suite()->getName().append("::").length();
            for (std::vector<Test*>::const_iterator i = tests.begin(), e = tests.end(); i != e; ++i) {
                cerr << (*i)->getName().replace(0, prefix_len, "") << endl;
            }
            break;
        }
        default:
            break;
        }

    CppUnit::TextTestRunner runner;
    runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());

    bool wasSuccessful = true;
    string test = "";
    int i = getopt.optind;
    if (i == argc) {
        // run them all
        wasSuccessful = runner.run("");
    }
    else {
        for (; i < argc; ++i) {
            if (debug) cerr << "Running " << argv[i] << endl;
            test = D4UnMarshallerTest::suite()->getName().append("::").append(argv[i]);
            wasSuccessful = wasSuccessful && runner.run(test);
        }
    }

    return wasSuccessful ? 0 : 1;
}
<commit_msg>Fixed memory error in D4UnMarshallerTest.<commit_after>// -*- mode: c++; c-basic-offset:4 -*-

// This file is part of libdap, A C++ implementation of the OPeNDAP Data
// Access Protocol.

// Copyright (c) 2013 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.

#include "config.h"

#include <cppunit/TestFixture.h>
#include <cppunit/TestAssert.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/CompilerOutputter.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <stdint.h>

#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstring>

#include "D4StreamUnMarshaller.h"

#include "Type.h"

#include "GetOpt.h"
#include "debug.h"
#include "test_config.h"

static bool debug = false;

#undef DBG
#define DBG(x) do { if (debug) (x); } while(false);

#if WORDS_BIGENDIAN
const static string path = string(TEST_SRC_DIR) + "/D4-marshaller/big-endian";
#else
const static string path = string(TEST_SRC_DIR) + "/D4-marshaller/little-endian";
#endif

using namespace std;
using namespace libdap;
using namespace CppUnit;

class D4UnMarshallerTest: public CppUnit::TestFixture {

    CPPUNIT_TEST_SUITE (D4UnMarshallerTest);

    CPPUNIT_TEST (test_scalars);
    CPPUNIT_TEST (test_real_scalars);
    CPPUNIT_TEST (test_str);
    CPPUNIT_TEST (test_opaque);
    CPPUNIT_TEST (test_vector);

    CPPUNIT_TEST_SUITE_END( );

    static inline bool is_host_big_endian()
    {
#ifdef COMPUTE_ENDIAN_AT_RUNTIME

        dods_int16 i = 0x0100;
        char *c = reinterpret_cast<char*>(&i);
        return *c;

#else

#ifdef __BIG_ENDIAN__
        return true;
#else
        return false;
#endif

#endif
    }

public:
    D4UnMarshallerTest()
    {
    }

    void setUp()
    {
    }

    void tearDown()
    {
    }

    void test_scalars()
    {
        fstream in;
        in.exceptions(ostream::failbit | ostream::badbit);

        // computes checksums and writes data
        try {
            string file = path + "/test_scalars_1_bin.dat";
            DBG(cerr << "file: " << file << endl);
            in.open(file.c_str(), fstream::binary | fstream::in);

            // Don't use is_host_big_endian() because these tests should
            // never 'twiddle bytes' They are always testing little to little
            // of big to big
            D4StreamUnMarshaller dsm(in, 0 /*is_host_big_endian()*/);

            dods_byte b;
            dsm.get_byte(b);
            CPPUNIT_ASSERT(b == 17);
            string ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            // Same checksum for both big- and little-endian
            CPPUNIT_ASSERT(ck == "b8b2cf7f");

            dods_int16 i1;
            dsm.get_int16(i1);
            CPPUNIT_ASSERT(i1 == 17);
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            // little-endian || big-endian checksum values
            CPPUNIT_ASSERT(ck == "120031ef" || ck == "2b69320d");

            dods_int32 i2;
            dsm.get_int32(i2);
            CPPUNIT_ASSERT(i2 == 17);
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "c9e1efe6" || ck == "4bf4ffee");

            dods_int64 i3;
            dsm.get_int64(i3);
            CPPUNIT_ASSERT(i3 == 17);
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "d533eedc" || ck == "0f92ff9b");

            dods_uint16 ui1;
            dsm.get_uint16(ui1);
            CPPUNIT_ASSERT(ui1 == 17);
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "120031ef" || ck == "2b69320d");

            dods_uint32 ui2;
            dsm.get_uint32(ui2);
            CPPUNIT_ASSERT(ui2 == 17);
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "c9e1efe6" || ck == "4bf4ffee");

            dods_uint64 ui3;
            dsm.get_uint64(ui3);
            CPPUNIT_ASSERT(ui3 == 17);
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "d533eedc" || ck == "0f92ff9b");
        }
        catch (Error &e) {
            cerr << "Error: " << e.get_error_message() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
        catch (istream::failure &e) {
            cerr << "File error: " << e.what() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
    }

    void test_real_scalars()
    {
        fstream in;
        in.exceptions(ostream::failbit | ostream::badbit);

        // computes checksums and writes data
        try {
            string file = path + "/test_scalars_2_bin.dat";
            in.open(file.c_str(), fstream::binary | fstream::in);
            D4StreamUnMarshaller dsm(in, 0);

            dods_float32 r1;
            dsm.get_float32(r1);
            CPPUNIT_ASSERT(r1 == 17.0);
            string ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "d3c5bc59" || ck == "edcaaa7c");

            dods_float64 r2;
            dsm.get_float64(r2);
            CPPUNIT_ASSERT(r2 == 17.0);
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "d5a3994b" || ck == "42abb362");
        }
        catch (Error &e) {
            cerr << "Error: " << e.get_error_message() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
        catch (istream::failure &e) {
            cerr << "File error: " << e.what() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
    }

    void test_str()
    {
        fstream in;
        in.exceptions(ostream::failbit | ostream::badbit);

        // computes checksums and writes data
        try {
            string file = path + "/test_scalars_3_bin.dat";
            in.open(file.c_str(), fstream::binary | fstream::in);
            D4StreamUnMarshaller dsm(in, 0);

            string s;
            dsm.get_str(s);
            CPPUNIT_ASSERT(s == "This is a test string with 40 characters");
            string ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "af117544");

            string u;
            dsm.get_url(u);
            CPPUNIT_ASSERT(u == "http://www.opendap.org/lame/unit/test");
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "41e10081");
        }
        catch (Error &e) {
            cerr << "Error: " << e.get_error_message() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
        catch (istream::failure &e) {
            cerr << "File error: " << e.what() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
    }

    void test_opaque()
    {
        fstream in;
        in.exceptions(ostream::failbit | ostream::badbit);

        // computes checksums and writes data
        try {
            string file = path + "/test_opaque_1_bin.dat";
            in.open(file.c_str(), fstream::binary | fstream::in);
            D4StreamUnMarshaller dsm(in, 0);

            char *buf2;
            int64_t len;
            dsm.get_opaque_dap4(&buf2, len);
            CPPUNIT_ASSERT(len == 32768);
            for (int i = 0; i < 32768; ++i)
                CPPUNIT_ASSERT(buf2[i] == i % (1 << 7));
            string ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "199ad7f5");

            delete[] buf2;
        }
        catch (Error &e) {
            cerr << "Error: " << e.get_error_message() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
        catch (istream::failure &e) {
            cerr << "File error: " << e.what() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
    }

    void test_vector()
    {
        fstream in;
        in.exceptions(ostream::failbit | ostream::badbit);

        // computes checksums and writes data
        try {
            string file = path + "/test_vector_1_bin.dat";
            in.open(file.c_str(), fstream::binary | fstream::in);
            D4StreamUnMarshaller dsm(in, 0);

            vector<unsigned char> buf1(32768);
            dsm.get_vector(reinterpret_cast<char*>(&buf1[0]), 32768);
            for (int i = 0; i < 32768; ++i)
                CPPUNIT_ASSERT(buf1[i] == i % (1 << 7));
            string ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "199ad7f5" || ck == "199ad7f5");

            vector<dods_int32> buf2(32768);
            dsm.get_vector(reinterpret_cast<char*>(&buf2[0]), 32768, sizeof(dods_int32));
            for (int i = 0; i < 32768; ++i)
                CPPUNIT_ASSERT(buf2[i] == i % (1 << 9));
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "5c1bf29f" || ck == "8efd2d3d");

            vector<dods_float64> buf3(32768);
            dsm.get_vector_float64(reinterpret_cast<char*>(&buf3[0]), 32768);
            for (int i = 0; i < 32768; ++i) {
                if (buf3[i] != i % (1 << 9)) cerr << "buf3[" << i << "]: " << buf3[i] << endl;
                CPPUNIT_ASSERT(buf3[i] == i % (1 << 9));
            }
            ck = dsm.get_checksum_str();
            DBG(cerr << "ck: " << ck << endl);
            CPPUNIT_ASSERT(ck == "aafc2a91" || ck == "7bdf9931");
        }
        catch (Error &e) {
            cerr << "Error: " << e.get_error_message() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
        catch (istream::failure &e) {
            cerr << "File error: " << e.what() << endl;
            CPPUNIT_FAIL("Caught an exception.");
        }
    }

};

CPPUNIT_TEST_SUITE_REGISTRATION (D4UnMarshallerTest);

int main(int argc, char*argv[])
{
    GetOpt getopt(argc, argv, "dh");
    int option_char;

    while ((option_char = getopt()) != -1)
        switch (option_char) {
        case 'd':
            debug = true;  // debug is a static global
            break;
        case 'h': {     // help - show test names
            cerr << "Usage: D4UnMarshallerTest has the following tests:" << endl;
            const std::vector<Test*> &tests = D4UnMarshallerTest::suite()->getTests();
            unsigned int prefix_len = D4UnMarshallerTest::suite()->getName().append("::").length();
            for (std::vector<Test*>::const_iterator i = tests.begin(), e = tests.end(); i != e; ++i) {
                cerr << (*i)->getName().replace(0, prefix_len, "") << endl;
            }
            break;
        }
        default:
            break;
        }

    CppUnit::TextTestRunner runner;
    runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());

    bool wasSuccessful = true;
    string test = "";
    int i = getopt.optind;
    if (i == argc) {
        // run them all
        wasSuccessful = runner.run("");
    }
    else {
        for (; i < argc; ++i) {
            if (debug) cerr << "Running " << argv[i] << endl;
            test = D4UnMarshallerTest::suite()->getName().append("::").append(argv[i]);
            wasSuccessful = wasSuccessful && runner.run(test);
        }
    }

    return wasSuccessful ? 0 : 1;
}
<|endoftext|>


<commit_before>/*  This file is part of the Kate project.
 *
 *  Copyright (C) 2012 Christoph Cullmann <cullmann@kde.org>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 */

#include "kateprojectinfoviewcodeanalysis.h"
#include "kateprojectpluginview.h"

#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QFileInfo>

#include <klocalizedstring.h>
#include <kmessagewidget.h>

KateProjectInfoViewCodeAnalysis::KateProjectInfoViewCodeAnalysis(KateProjectPluginView *pluginView, KateProject *project)
    : QWidget()
    , m_pluginView(pluginView)
    , m_project(project)
    , m_messageWidget(0)
    , m_startStopAnalysis(new QPushButton(i18n("Start Analysis...")))
    , m_treeView(new QTreeView())
    , m_model(new QStandardItemModel(m_treeView))
    , m_analyzer(0)
{
    /**
     * default style
     */
    m_treeView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    m_treeView->setUniformRowHeights(true);
    m_treeView->setRootIsDecorated(false);
    m_model->setHorizontalHeaderLabels(QStringList() << QStringLiteral("File") << QStringLiteral("Line") << QStringLiteral("Severity") << QStringLiteral("Message"));

    /**
     * attach model
     * kill selection model
     */
    QItemSelectionModel *m = m_treeView->selectionModel();
    m_treeView->setModel(m_model);
    delete m;

    m_treeView->setSortingEnabled(true);
    m_treeView->sortByColumn(1, Qt::AscendingOrder);
    m_treeView->sortByColumn(2, Qt::AscendingOrder);

    /**
     * layout widget
     */
    QVBoxLayout *layout = new QVBoxLayout;
    layout->setSpacing(0);
    layout->addWidget(m_treeView);
    QHBoxLayout *hlayout = new QHBoxLayout;
    layout->addLayout(hlayout);
    hlayout->setSpacing(0);
    hlayout->addStretch();
    hlayout->addWidget(m_startStopAnalysis);
    setLayout(layout);

    /**
     * connect needed signals
     */
    connect(m_startStopAnalysis, SIGNAL(clicked(bool)), this, SLOT(slotStartStopClicked()));
    connect(m_treeView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(slotClicked(const QModelIndex &)));
}

KateProjectInfoViewCodeAnalysis::~KateProjectInfoViewCodeAnalysis()
{
}

void KateProjectInfoViewCodeAnalysis::slotStartStopClicked()
{
    /**
     * get files for cppcheck
     */
    QStringList files = m_project->files().filter(QRegExp(QStringLiteral("\\.(cpp|cxx|cc|c\\+\\+|c|tpp|txx)$")));

    /**
     * clear existing entries
     */
    m_model->removeRows(0, m_model->rowCount(), QModelIndex());

    /**
     * launch cppcheck
     */
    m_analyzer = new QProcess(this);
    m_analyzer->setProcessChannelMode(QProcess::MergedChannels);

    connect(m_analyzer, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
    connect(m_analyzer, SIGNAL(finished(int, QProcess::ExitStatus)),
            this, SLOT(finished(int, QProcess::ExitStatus)));

    QStringList args;
    args << QStringLiteral("-q") << QStringLiteral("--inline-suppr") << QStringLiteral("--enable=all") << QStringLiteral("--template={file}////{line}////{severity}////{message}") << QStringLiteral("--file-list=-");
    m_analyzer->start(QStringLiteral("cppcheck"), args);

    if (m_messageWidget) {
        delete m_messageWidget;
        m_messageWidget = 0;
    }

    if (!m_analyzer->waitForStarted()) {
        m_messageWidget = new KMessageWidget();
        m_messageWidget->setCloseButtonVisible(true);
        m_messageWidget->setMessageType(KMessageWidget::Warning);
        m_messageWidget->setWordWrap(false);
        m_messageWidget->setText(i18n("Please install 'cppcheck'."));
        static_cast<QVBoxLayout *>(layout())->insertWidget(0, m_messageWidget);
        m_messageWidget->animatedShow();
        return;
    }
    /**
     * write files list and close write channel
     */
    m_analyzer->write(files.join(QStringLiteral("\n")).toLocal8Bit());
    m_analyzer->closeWriteChannel();
}

void KateProjectInfoViewCodeAnalysis::slotReadyRead()
{
    /**
     * get results of analysis
     */
    while (m_analyzer->canReadLine()) {
        /**
         * get one line, split it, skip it, if too few elements
         */
        QString line = QString::fromLocal8Bit(m_analyzer->readLine());
        QStringList elements = line.split(QRegExp(QStringLiteral("////")), QString::SkipEmptyParts);
        if (elements.size() < 4) {
            continue;
        }

        /**
         * feed into model
         */
        QList<QStandardItem *> items;
        QStandardItem *fileNameItem = new QStandardItem(QFileInfo(elements[0]).fileName());
        fileNameItem->setToolTip(elements[0]);
        items << fileNameItem;
        items << new QStandardItem(elements[1]);
        items << new QStandardItem(elements[2]);
        const auto message = elements[3].simplified();
        auto messageItem = new QStandardItem(message);
        messageItem->setToolTip(message);
        items << messageItem;
        m_model->appendRow(items);
    }

    /**
     * tree view polish ;)
     */
    m_treeView->resizeColumnToContents(2);
    m_treeView->resizeColumnToContents(1);
    m_treeView->resizeColumnToContents(0);
}

void KateProjectInfoViewCodeAnalysis::slotClicked(const QModelIndex &index)
{
    /**
     * get path
     */
    QString filePath = m_model->item(index.row(), 0)->toolTip();
    if (filePath.isEmpty()) {
        return;
    }

    /**
     * create view
     */
    KTextEditor::View *view = m_pluginView->mainWindow()->openUrl(QUrl::fromLocalFile(filePath));
    if (!view) {
        return;
    }

    /**
     * set cursor, if possible
     */
    int line = m_model->item(index.row(), 1)->text().toInt();
    if (line >= 1) {
        view->setCursorPosition(KTextEditor::Cursor(line - 1, 0));
    }
}

void KateProjectInfoViewCodeAnalysis::finished(int exitCode, QProcess::ExitStatus)
{
  m_messageWidget = new KMessageWidget();
  m_messageWidget->setCloseButtonVisible(true);
  m_messageWidget->setWordWrap(false);

  if (exitCode == 0) {
    m_messageWidget->setMessageType(KMessageWidget::Information);
    m_messageWidget->setText(i18n("Analysis finished."));
  } else {
    // unfortunately, output was eaten by slotReadyRead()
    // TODO: get stderr output, show it here
    m_messageWidget->setMessageType(KMessageWidget::Warning);
    m_messageWidget->setText(i18n("Analysis failed!"));
  }
  static_cast<QVBoxLayout*>(layout ())->insertWidget(0, m_messageWidget);
  m_messageWidget->animatedShow ();
}
<commit_msg>add i18n calls to make the strings translatable<commit_after>/*  This file is part of the Kate project.
 *
 *  Copyright (C) 2012 Christoph Cullmann <cullmann@kde.org>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 */

#include "kateprojectinfoviewcodeanalysis.h"
#include "kateprojectpluginview.h"

#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QFileInfo>

#include <klocalizedstring.h>
#include <kmessagewidget.h>

KateProjectInfoViewCodeAnalysis::KateProjectInfoViewCodeAnalysis(KateProjectPluginView *pluginView, KateProject *project)
    : QWidget()
    , m_pluginView(pluginView)
    , m_project(project)
    , m_messageWidget(0)
    , m_startStopAnalysis(new QPushButton(i18n("Start Analysis...")))
    , m_treeView(new QTreeView())
    , m_model(new QStandardItemModel(m_treeView))
    , m_analyzer(0)
{
    /**
     * default style
     */
    m_treeView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    m_treeView->setUniformRowHeights(true);
    m_treeView->setRootIsDecorated(false);
    m_model->setHorizontalHeaderLabels(QStringList() << i18n("File") << i18n("Line") << i18n("Severity") << i18n("Message"));

    /**
     * attach model
     * kill selection model
     */
    QItemSelectionModel *m = m_treeView->selectionModel();
    m_treeView->setModel(m_model);
    delete m;

    m_treeView->setSortingEnabled(true);
    m_treeView->sortByColumn(1, Qt::AscendingOrder);
    m_treeView->sortByColumn(2, Qt::AscendingOrder);

    /**
     * layout widget
     */
    QVBoxLayout *layout = new QVBoxLayout;
    layout->setSpacing(0);
    layout->addWidget(m_treeView);
    QHBoxLayout *hlayout = new QHBoxLayout;
    layout->addLayout(hlayout);
    hlayout->setSpacing(0);
    hlayout->addStretch();
    hlayout->addWidget(m_startStopAnalysis);
    setLayout(layout);

    /**
     * connect needed signals
     */
    connect(m_startStopAnalysis, SIGNAL(clicked(bool)), this, SLOT(slotStartStopClicked()));
    connect(m_treeView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(slotClicked(const QModelIndex &)));
}

KateProjectInfoViewCodeAnalysis::~KateProjectInfoViewCodeAnalysis()
{
}

void KateProjectInfoViewCodeAnalysis::slotStartStopClicked()
{
    /**
     * get files for cppcheck
     */
    QStringList files = m_project->files().filter(QRegExp(QStringLiteral("\\.(cpp|cxx|cc|c\\+\\+|c|tpp|txx)$")));

    /**
     * clear existing entries
     */
    m_model->removeRows(0, m_model->rowCount(), QModelIndex());

    /**
     * launch cppcheck
     */
    m_analyzer = new QProcess(this);
    m_analyzer->setProcessChannelMode(QProcess::MergedChannels);

    connect(m_analyzer, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
    connect(m_analyzer, SIGNAL(finished(int, QProcess::ExitStatus)),
            this, SLOT(finished(int, QProcess::ExitStatus)));

    QStringList args;
    args << QStringLiteral("-q") << QStringLiteral("--inline-suppr") << QStringLiteral("--enable=all") << QStringLiteral("--template={file}////{line}////{severity}////{message}") << QStringLiteral("--file-list=-");
    m_analyzer->start(QStringLiteral("cppcheck"), args);

    if (m_messageWidget) {
        delete m_messageWidget;
        m_messageWidget = 0;
    }

    if (!m_analyzer->waitForStarted()) {
        m_messageWidget = new KMessageWidget();
        m_messageWidget->setCloseButtonVisible(true);
        m_messageWidget->setMessageType(KMessageWidget::Warning);
        m_messageWidget->setWordWrap(false);
        m_messageWidget->setText(i18n("Please install 'cppcheck'."));
        static_cast<QVBoxLayout *>(layout())->insertWidget(0, m_messageWidget);
        m_messageWidget->animatedShow();
        return;
    }
    /**
     * write files list and close write channel
     */
    m_analyzer->write(files.join(QStringLiteral("\n")).toLocal8Bit());
    m_analyzer->closeWriteChannel();
}

void KateProjectInfoViewCodeAnalysis::slotReadyRead()
{
    /**
     * get results of analysis
     */
    while (m_analyzer->canReadLine()) {
        /**
         * get one line, split it, skip it, if too few elements
         */
        QString line = QString::fromLocal8Bit(m_analyzer->readLine());
        QStringList elements = line.split(QRegExp(QStringLiteral("////")), QString::SkipEmptyParts);
        if (elements.size() < 4) {
            continue;
        }

        /**
         * feed into model
         */
        QList<QStandardItem *> items;
        QStandardItem *fileNameItem = new QStandardItem(QFileInfo(elements[0]).fileName());
        fileNameItem->setToolTip(elements[0]);
        items << fileNameItem;
        items << new QStandardItem(elements[1]);
        items << new QStandardItem(elements[2]);
        const auto message = elements[3].simplified();
        auto messageItem = new QStandardItem(message);
        messageItem->setToolTip(message);
        items << messageItem;
        m_model->appendRow(items);
    }

    /**
     * tree view polish ;)
     */
    m_treeView->resizeColumnToContents(2);
    m_treeView->resizeColumnToContents(1);
    m_treeView->resizeColumnToContents(0);
}

void KateProjectInfoViewCodeAnalysis::slotClicked(const QModelIndex &index)
{
    /**
     * get path
     */
    QString filePath = m_model->item(index.row(), 0)->toolTip();
    if (filePath.isEmpty()) {
        return;
    }

    /**
     * create view
     */
    KTextEditor::View *view = m_pluginView->mainWindow()->openUrl(QUrl::fromLocalFile(filePath));
    if (!view) {
        return;
    }

    /**
     * set cursor, if possible
     */
    int line = m_model->item(index.row(), 1)->text().toInt();
    if (line >= 1) {
        view->setCursorPosition(KTextEditor::Cursor(line - 1, 0));
    }
}

void KateProjectInfoViewCodeAnalysis::finished(int exitCode, QProcess::ExitStatus)
{
  m_messageWidget = new KMessageWidget();
  m_messageWidget->setCloseButtonVisible(true);
  m_messageWidget->setWordWrap(false);

  if (exitCode == 0) {
    m_messageWidget->setMessageType(KMessageWidget::Information);
    m_messageWidget->setText(i18n("Analysis finished."));
  } else {
    // unfortunately, output was eaten by slotReadyRead()
    // TODO: get stderr output, show it here
    m_messageWidget->setMessageType(KMessageWidget::Warning);
    m_messageWidget->setText(i18n("Analysis failed!"));
  }
  static_cast<QVBoxLayout*>(layout ())->insertWidget(0, m_messageWidget);
  m_messageWidget->animatedShow ();
}
<|endoftext|>