<commit_before>/* Copyright (c) 2014 Quanta Research Cambridge, Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "StdDmaIndication.h"
#include "MMURequest.h"
#include "Ov7670ControllerRequest.h"
#include "Ov7670ControllerIndication.h"
#include "pthread.h"

int slaveaddr[3];
int addr;

int rdClock[64];
int rdData[64];
int rdOutEn[64];
volatile int rdSample[64];
volatile int cursor = 0;
volatile int phase = 0;
sem_t bit_sem;

class Ov7670ControllerIndication : public Ov7670ControllerIndicationWrapper {
  int datacount;
  int gapcount;
public:
  Ov7670ControllerIndication(unsigned int id) : Ov7670ControllerIndicationWrapper(id), datacount(0), gapcount(0) {}
  ~Ov7670ControllerIndication() {}
  virtual void i2cResponse(uint8_t bus, uint8_t data) {
    fprintf(stderr, "i2c bus %d device %d addr %x response %02x\n", bus, slaveaddr[bus], addr, data);
  }
  virtual void pinResponse(uint8_t sdaIn) {
    int pos = (phase == 2) ? cursor-1 : cursor;
    if (pos > 0) {
      int newsample = (rdSample[cursor] << 1) | sdaIn;
      fprintf(stderr, "i2c cursor %3d phase %d sda %d %d %d\n", cursor, phase, sdaIn, rdSample[cursor], newsample);
      rdSample[cursor] = newsample;
    }
    sem_post(&bit_sem);
  }
  virtual void vsync(uint32_t cycles, uint8_t href) {
    //fprintf(stderr, "vsync %8d href %d\n", cycles, href);
    if (datacount) {
      fprintf(stderr, "vsync datacount=%8d gapcount=%8d\n", datacount, gapcount);
      datacount = 0;
      gapcount = 0;
    }
  }
  virtual void data(uint8_t first, uint8_t gap, uint8_t data) {
    //if (gap) fprintf(stderr, "data %8x first %d gap %d\n", data, first, gap);
    datacount++;
    if (gap) gapcount++;
  }
  virtual void frameStarted(uint8_t first) {
    //if (first) fprintf(stderr, "frameStarted %d\n", first);
  }
  virtual void frameTransferred() {
    //fprintf(stderr, "frameTransferred\n");
  }
  virtual void data4(uint32_t data) {
  }
};

void enqueueStart()
{
  rdClock[cursor] = 0b110;
  rdData[cursor] = 0b100;
  rdOutEn[cursor] = 0b111;
  cursor++;
}
void enqueueStop()
{
  rdClock[cursor] = 0b001;
  rdData[cursor] = 0b011;
  rdOutEn[cursor] = 0b111;
  cursor++;
}
void enqueueIdle()
{
  rdClock[cursor] = 0b111;
  rdData[cursor] = 0b111;
  rdOutEn[cursor] = 0b111;
  cursor++;
}
void enqueueBitOut(int b)
{
    rdClock[cursor] = 0b010;
    rdData[cursor] = b ? 0b111 : 0b000;
    rdOutEn[cursor] = 0b111;
    cursor++;
}
void enqueueBitIn()
{
    rdClock[cursor] = 0b010;
    rdData[cursor] = 0;
    rdOutEn[cursor] = 0b000;
    cursor++;
}
void enqueueAck()
{
    rdClock[cursor] = 0b010;
    rdData[cursor] = 0;
    rdOutEn[cursor] = 0b000;
    cursor++;
}
void enqueueMAck()
{
    rdClock[cursor] = 0b010;
    rdData[cursor] = 0b111;
    rdOutEn[cursor] = 0b111;
    cursor++;
}

int bit(int v, int pos)
{
  return (v >> pos) & 1;
}

int main(int argc, const char **argv)
{
  Ov7670ControllerRequestProxy device(IfcNames_Ov7670ControllerRequestS2H);
  Ov7670ControllerIndication deviceResponse(IfcNames_Ov7670ControllerIndicationH2S);
  MMURequestProxy *mmuRequest = new MMURequestProxy(IfcNames_MMURequestS2H);
  DmaManager *dma = new DmaManager(mmuRequest);
  MemServerRequestProxy *memServerRequest = new MemServerRequestProxy(IfcNames_MemServerRequestS2H);
  MemServerIndication *memServerIndication = new MemServerIndication(memServerRequest, IfcNames_MemServerIndicationH2S);
  MMUIndication mmuIndication(dma, IfcNames_MMUIndicationH2S);

  int len = 640*480*4;
  int nfbAlloc = portalAlloc(4096, 0);
  unsigned int *nfbBuffer = (unsigned int *)portalMmap(nfbAlloc, 4096);
  unsigned int ref_nfbAlloc = dma->reference(nfbAlloc);
  int fbAlloc = portalAlloc(len, 0);
  unsigned int *fbBuffer = (unsigned int *)portalMmap(fbAlloc, len);
  unsigned int ref_fbAlloc = dma->reference(fbAlloc);

  device.setPowerDown(0);
  device.setReset(0);
  sleep(1);
  device.setReset(1);
  fprintf(stderr, "ref_fbAlloc=%d\n", ref_fbAlloc);
  device.setFramePointer(ref_fbAlloc);
  // hsync instead of href
  //device.i2cRequest(0, 1, 0x21, 0x15, 0x40);
  // always has href
  device.i2cRequest(0, 1, slaveaddr[0], 0x3c, 0x80);

  slaveaddr[0] = 0x21;
  slaveaddr[1] = 0x1e;
  slaveaddr[2] = 0x69;
  addr = 0x5a;

  cursor = 0;
  // START symbol
  enqueueStart();
  for (int s = 6; s >= 0; s--) {
    enqueueBitOut(bit(slaveaddr[0], s));
  }
  enqueueBitOut(0); // write
  enqueueAck();
  for (int s = 7; s >= 0; s--) {
    enqueueBitOut(bit(addr, s));
  }
  enqueueAck();
  //enqueueStop();
  //enqueueIdle();
  //enqueueStart();
  for (int s = 6; s >= 0; s--) {
    enqueueBitOut(bit(slaveaddr[0], s));
  }
  enqueueBitOut(1); // read
  enqueueAck();
  for (int s = 7; s >= 0; s--) {
    enqueueBitIn();
  }
  enqueueMAck();
  enqueueStop();
  enqueueIdle();
  int max_cursor = cursor;

  for (int i = 0; i < cursor; i++) {
    fprintf(stderr, "CYCLE %3d CLK %d OUT %d OE %d IN %x\n", i, rdClock[i], rdData[i], rdOutEn[i], rdSample[i]);
  }
  cursor = 0;
  sem_init(&bit_sem, 0, 0);
  for (int i = 0; i < max_cursor; i++) {
    cursor = i;
    for (phase = 2; phase >= 0; phase--) {
      device.pinRequest(bit(rdOutEn[i], phase), bit(rdClock[i], phase), bit(rdData[i], phase));
      sem_wait(&bit_sem);
    }
  }
  for (int i = 0; i < max_cursor; i++) {
    fprintf(stderr, "CYCLE %3d CLK %d OUT %d OE %d IN %x\n", i, rdClock[i], rdData[i], rdOutEn[i], rdSample[i]);
  }
  return 0;

  for (int i = 0; i < 128; i++) {
    int write = 0;
    int val = 0x33;
    addr = i;
    device.i2cRequest(0, write, slaveaddr[0], addr, val);
    device.i2cRequest(1, write, slaveaddr[1], addr, val);
    device.i2cRequest(2, write, slaveaddr[2], addr, val);
    if (0) {
    // product ID: 0x76
    device.i2cRequest(0, 0, slaveaddr[0], 0x0a, 0);
    // product VER: 0x70
    device.i2cRequest(0, 0, slaveaddr[0], 0x0b, 0);
    // mfg id: 0x7F
    device.i2cRequest(0, 0, slaveaddr[0], 0x1c, 0);
    // mfg id: 0xA2
    device.i2cRequest(0, 0, slaveaddr[0], 0x1d, 0);
    }
    sleep(1);
  }
  for (int i = 0; i < 64; i++)
    fprintf(stderr, " %02x", fbBuffer[i] & 0xff);
  fprintf(stderr, "\n");
  return 0;
}
<commit_msg>use a semaphore after i2c read instead of sleep(1)<commit_after>/* Copyright (c) 2014 Quanta Research Cambridge, Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "StdDmaIndication.h"
#include "MMURequest.h"
#include "Ov7670ControllerRequest.h"
#include "Ov7670ControllerIndication.h"
#include "pthread.h"

int slaveaddr[3];
int addr;

int rdClock[64];
int rdData[64];
int rdOutEn[64];
volatile int rdSample[64];
volatile int cursor = 0;
volatile int phase = 0;
sem_t bit_sem;

class Ov7670ControllerIndication : public Ov7670ControllerIndicationWrapper {
  int datacount;
  int gapcount;
public:
  Ov7670ControllerIndication(unsigned int id) : Ov7670ControllerIndicationWrapper(id), datacount(0), gapcount(0) {}
  ~Ov7670ControllerIndication() {}
  virtual void i2cResponse(uint8_t bus, uint8_t data) {
    fprintf(stderr, "i2c bus %d device %d addr %x response %02x\n", bus, slaveaddr[bus], addr, data);
    sem_post(&bit_sem);
  }
  virtual void pinResponse(uint8_t sdaIn) {
    int pos = (phase == 2) ? cursor-1 : cursor;
    if (pos > 0) {
      int newsample = (rdSample[cursor] << 1) | sdaIn;
      fprintf(stderr, "i2c cursor %3d phase %d sda %d %d %d\n", cursor, phase, sdaIn, rdSample[cursor], newsample);
      rdSample[cursor] = newsample;
    }
    sem_post(&bit_sem);
  }
  virtual void vsync(uint32_t cycles, uint8_t href) {
    //fprintf(stderr, "vsync %8d href %d\n", cycles, href);
    if (datacount) {
      fprintf(stderr, "vsync datacount=%8d gapcount=%8d\n", datacount, gapcount);
      datacount = 0;
      gapcount = 0;
    }
  }
  virtual void data(uint8_t first, uint8_t gap, uint8_t data) {
    //if (gap) fprintf(stderr, "data %8x first %d gap %d\n", data, first, gap);
    datacount++;
    if (gap) gapcount++;
  }
  virtual void frameStarted(uint8_t first) {
    //if (first) fprintf(stderr, "frameStarted %d\n", first);
  }
  virtual void frameTransferred() {
    //fprintf(stderr, "frameTransferred\n");
  }
  virtual void data4(uint32_t data) {
  }
};

void enqueueStart()
{
  rdClock[cursor] = 0b110;
  rdData[cursor] = 0b100;
  rdOutEn[cursor] = 0b111;
  cursor++;
}
void enqueueStop()
{
  rdClock[cursor] = 0b001;
  rdData[cursor] = 0b011;
  rdOutEn[cursor] = 0b111;
  cursor++;
}
void enqueueIdle()
{
  rdClock[cursor] = 0b111;
  rdData[cursor] = 0b111;
  rdOutEn[cursor] = 0b111;
  cursor++;
}
void enqueueBitOut(int b)
{
    rdClock[cursor] = 0b010;
    rdData[cursor] = b ? 0b111 : 0b000;
    rdOutEn[cursor] = 0b111;
    cursor++;
}
void enqueueBitIn()
{
    rdClock[cursor] = 0b010;
    rdData[cursor] = 0;
    rdOutEn[cursor] = 0b000;
    cursor++;
}
void enqueueAck()
{
    rdClock[cursor] = 0b010;
    rdData[cursor] = 0;
    rdOutEn[cursor] = 0b000;
    cursor++;
}
void enqueueMAck()
{
    rdClock[cursor] = 0b010;
    rdData[cursor] = 0b111;
    rdOutEn[cursor] = 0b111;
    cursor++;
}

int bit(int v, int pos)
{
  return (v >> pos) & 1;
}

int main(int argc, const char **argv)
{
  Ov7670ControllerRequestProxy device(IfcNames_Ov7670ControllerRequestS2H);
  Ov7670ControllerIndication deviceResponse(IfcNames_Ov7670ControllerIndicationH2S);
  MMURequestProxy *mmuRequest = new MMURequestProxy(IfcNames_MMURequestS2H);
  DmaManager *dma = new DmaManager(mmuRequest);
  MemServerRequestProxy *memServerRequest = new MemServerRequestProxy(IfcNames_MemServerRequestS2H);
  MemServerIndication *memServerIndication = new MemServerIndication(memServerRequest, IfcNames_MemServerIndicationH2S);
  MMUIndication mmuIndication(dma, IfcNames_MMUIndicationH2S);

  int len = 640*480*4;
  int nfbAlloc = portalAlloc(4096, 0);
  unsigned int *nfbBuffer = (unsigned int *)portalMmap(nfbAlloc, 4096);
  unsigned int ref_nfbAlloc = dma->reference(nfbAlloc);
  int fbAlloc = portalAlloc(len, 0);
  unsigned int *fbBuffer = (unsigned int *)portalMmap(fbAlloc, len);
  unsigned int ref_fbAlloc = dma->reference(fbAlloc);

  sem_init(&bit_sem, 0, 0);

  device.setPowerDown(0);
  device.setReset(0);
  sleep(1);
  device.setReset(1);
  sleep(1);
  fprintf(stderr, "ref_fbAlloc=%d\n", ref_fbAlloc);
  device.setFramePointer(ref_fbAlloc);

  // register reset
  device.i2cRequest(0, 1, 0x21, 0x12, 0x80);

  // hsync instead of href
  //device.i2cRequest(0, 1, 0x21, 0x15, 0x40);
  // always has href
  // device.i2cRequest(0, 1, slaveaddr[0], 0x3c, 0x80);

  slaveaddr[0] = 0x21;
  slaveaddr[1] = 0x1e;
  slaveaddr[2] = 0x69;
  addr = 0x5a;

  if (0) {
    cursor = 0;
    // START symbol
    enqueueStart();
    for (int s = 6; s >= 0; s--) {
      enqueueBitOut(bit(slaveaddr[0], s));
    }
    enqueueBitOut(0); // write
    enqueueAck();
    for (int s = 7; s >= 0; s--) {
      enqueueBitOut(bit(addr, s));
    }
    enqueueAck();
    //enqueueStop();
    //enqueueIdle();
    //enqueueStart();
    for (int s = 6; s >= 0; s--) {
      enqueueBitOut(bit(slaveaddr[0], s));
    }
    enqueueBitOut(1); // read
    enqueueAck();
    for (int s = 7; s >= 0; s--) {
      enqueueBitIn();
    }
    enqueueMAck();
    enqueueStop();
    enqueueIdle();
    int max_cursor = cursor;

    for (int i = 0; i < cursor; i++) {
      fprintf(stderr, "CYCLE %3d CLK %d OUT %d OE %d IN %x\n", i, rdClock[i], rdData[i], rdOutEn[i], rdSample[i]);
    }
    cursor = 0;
    for (int i = 0; i < max_cursor; i++) {
      cursor = i;
      for (phase = 2; phase >= 0; phase--) {
	device.pinRequest(bit(rdOutEn[i], phase), bit(rdClock[i], phase), bit(rdData[i], phase));
	sem_wait(&bit_sem);
      }
    }
    for (int i = 0; i < max_cursor; i++) {
      fprintf(stderr, "CYCLE %3d CLK %d OUT %d OE %d IN %x\n", i, rdClock[i], rdData[i], rdOutEn[i], rdSample[i]);
    }
    return 0;
  }

  for (int i = 0; i < 128; i++) {
    int write = 0;
    int val = 0x33;
    addr = i;
    device.i2cRequest(0, write, slaveaddr[0], addr, val);
    if (!write) sem_wait(&bit_sem);

    device.i2cRequest(1, write, slaveaddr[1], addr, val);
    if (!write) sem_wait(&bit_sem);

    device.i2cRequest(2, write, slaveaddr[2], addr, val);
    if (!write) sem_wait(&bit_sem);

  }
  if (1) {
    // product ID: 0x76
    device.i2cRequest(0, 0, slaveaddr[0], 0x0a, 0);
    sem_wait(&bit_sem);

    // product VER: 0x70
    device.i2cRequest(0, 0, slaveaddr[0], 0x0b, 0);
    sem_wait(&bit_sem);

    // mfg id: 0x7F
    device.i2cRequest(0, 0, slaveaddr[0], 0x1c, 0);
    sem_wait(&bit_sem);

    // mfg id: 0xA2
    device.i2cRequest(0, 0, slaveaddr[0], 0x1d, 0);
    sem_wait(&bit_sem);
  }
  for (int i = 0; i < 64; i++)
    fprintf(stderr, " %02x", fbBuffer[i] & 0xff);
  fprintf(stderr, "\n");
  return 0;
}
<|endoftext|>


<commit_before>#include "machine.h"

void Machine::init(short id, int start_t = 0){
	this->id = id;
	this->start_t = start_t;
	this->stop_t = start_t;
}

int Machine::get_id(){
	return id;
}

int Machine::get_start_t(){
	return start_t;
}

int Machine::get_stop_t(){
	return stop_t;
}

vector<Task> Machine::get_tasks(){
	return tasks;
}

void Machine::set_start_t(int t){
	this->start_t = t;
	this->stop_t = t;
}

void Machine::set_stop_t(int t){
	this->stop_t = t;
}

int Machine::add(Task task, vector<Maitenance> maitenance_v){
	if (id == 1){
		int overlay = 0;
		int maitenance_id = 0;

		for (unsigned int i = 0; i < maitenance_v.size(); i++){
			if(maitenance_v[i].get_start_t() <= stop_t && maitenance_v[i].get_stop_t() > stop_t) this->stop_t = maitenance_v[i].get_stop_t();
			if(maitenance_v[i].get_start_t() > stop_t){
				int task_t = (overlay == 0)?(task.get_op_t(1)):(task.get_punished_op_t());
				if(maitenance_v[i].get_start_t() <= task_t){
					overlay++;
					if(overlay == 1) maitenance_id = i;
				}else if(overlay <= 1) break;
				if(overlay > 1) return maitenance_v[maitenance_id].get_start_t();
			}
		}

		task.set_start_t(1, this->stop_t);
		if(overlay == 0) this->stop_t += task.get_op_t(1);
		else{
			this->stop_t += maitenance_v[maitenance_id].get_duration() + task.get_punished_op_t();
			task.punish(maitenance_v[maitenance_id].get_stop_t());
		}
		tasks.push_back(task);
	}else if( id == 2){
		task.set_start_t(2, this->stop_t);
		tasks.push_back(task);
		this->stop_t += task.get_op_t(2);
	}
	return 0;
}
<commit_msg>Fixed maitenance overflow<commit_after>#include "machine.h"

void Machine::init(short id, int start_t = 0){
	this->id = id;
	this->start_t = start_t;
	this->stop_t = start_t;
}

int Machine::get_id(){
	return id;
}

int Machine::get_start_t(){
	return start_t;
}

int Machine::get_stop_t(){
	return stop_t;
}

vector<Task> Machine::get_tasks(){
	return tasks;
}

void Machine::set_start_t(int t){
	this->start_t = t;
	this->stop_t = t;
}

void Machine::set_stop_t(int t){
	this->stop_t = t;
}

int Machine::add(Task task, vector<Maitenance> maitenance_v){
	if (id == 1){
		int overlay = 0;
		int maitenance_id = 0;

		for (unsigned int i = 0; i < maitenance_v.size(); i++){
			if(maitenance_v[i].get_start_t() <= stop_t && maitenance_v[i].get_stop_t() > stop_t) this->stop_t = maitenance_v[i].get_stop_t();
			if(maitenance_v[i].get_start_t() > stop_t){
				int task_t = (overlay == 0)?(task.get_op_t(1)):(task.get_punished_op_t()) + this->stop_t;
				if(maitenance_v[i].get_start_t() <= task_t){
					overlay++;
					if(overlay == 1) maitenance_id = i;
				}else if(overlay <= 1) break;
				if(overlay > 1) return maitenance_v[maitenance_id].get_start_t();
			}
		}

		task.set_start_t(1, this->stop_t);
		if(overlay == 0) this->stop_t += task.get_op_t(1);
		else{
			this->stop_t += maitenance_v[maitenance_id].get_duration() + task.get_punished_op_t();
			task.punish(maitenance_v[maitenance_id].get_stop_t());
		}
		tasks.push_back(task);
	}else if( id == 2){
		task.set_start_t(2, this->stop_t);
		tasks.push_back(task);
		this->stop_t += task.get_op_t(2);
	}
	return 0;
}
<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include "scraps/TaskThread.h"

using namespace scraps;

// Realtime tests almost always fail with Valgrind
#ifndef VALGRIND
TEST(TaskThread, basicFunctionality) {
    TaskThread scheduler;

    auto argFunc = [](int x, float y, double z) {};

    auto f1 = scheduler.async(argFunc, 1, 2, 3);
    auto f2 = scheduler.async(argFunc, 1, 2.0f, 3.0);
    f1.wait();
    f2.wait();

    scheduler.asyncAt(std::chrono::steady_clock::now() + 5ms, argFunc, 1, 2, 3);
    scheduler.asyncAfter(5ms, argFunc, 1, 2, 3);

    std::this_thread::sleep_for(10ms);

    int first = 0;
    scheduler.asyncAfter(10ms,
                         [&] {
                             if (first == 0)
                                 first = 1;
                         });
    scheduler.asyncAfter(5ms,
                         [&] {
                             if (first == 0)
                                 first = 2;
                         });

    std::this_thread::sleep_for(20ms);

    EXPECT_EQ(first, 2);
}

TEST(TaskThread, timingFunctionality) {
    TaskThread scheduler;

    auto now = std::chrono::steady_clock::now();

    const auto threshold = 30ms;

    auto speedCheck = [=] { EXPECT_LT(std::chrono::steady_clock::now().time_since_epoch().count(), (now + threshold).time_since_epoch().count()); };

    for (int i = 0; i < 50; ++i) {
        scheduler.async(speedCheck);
    }

    now = std::chrono::steady_clock::now();

    for (auto i = 1us; i < 50us; i += 1us) {
        scheduler.asyncAt(now + i * 2, speedCheck);
        scheduler.asyncAfter(i, speedCheck);
    }

    std::this_thread::sleep_for(20ms);

    now = std::chrono::steady_clock::now();

    auto timeCheck = [&](auto duration) {
        auto d = std::chrono::steady_clock::now() - (now + duration);
        EXPECT_GT(d, -threshold);
        EXPECT_LT(d, threshold);
    };

    scheduler.asyncAfter(5ms, timeCheck, 5ms);

    scheduler.asyncAt(now + 5ms, timeCheck, 5ms);

    std::this_thread::sleep_for(50ms);
}

TEST(TaskThread, futuresFunctionality) {
    TaskThread scheduler;
    auto now = std::chrono::steady_clock::now();

    auto f = scheduler.asyncAfter(5ms, [&] { return 17; });
    EXPECT_EQ(f.valid(), true);
    EXPECT_EQ(f.get(), 17);

    #if !SCRAPS_MOBILE
        const auto threshold = 8ms;
    #else
        const auto threshold = 20ms;
    #endif

    EXPECT_LT(std::chrono::steady_clock::now(), now + threshold);
}

TEST(TaskThread, cancelClearFunctionality) {
    bool executed = false;

    {
        TaskThread scheduler;
        scheduler.asyncAfter(5ms, [&] { executed = true; });
    }

    EXPECT_EQ(executed, false);

    {
        TaskThread scheduler;
        scheduler.asyncAfter(5ms, [&] { executed = true; });
        scheduler.clear();
        EXPECT_EQ(executed, false);
    }
}

TEST(TaskThread, scopeFunctionality) {
    {
        TaskThread scheduler;

        TaskThread::TaskScope scope;

        bool executed1 = false;
        scheduler.async(scope, [&] { executed1 = true; });

        std::this_thread::sleep_for(10ms);

        scope.endScope();

        bool executed2 = false;
        scheduler.async(scope, [&] { executed2 = true; });

        std::this_thread::sleep_for(10ms);

        EXPECT_EQ(executed1, true);
        EXPECT_EQ(executed2, false);
    }

    {
        TaskThread scheduler;

        auto scope = std::make_unique<TaskThread::TaskScope>();

        bool executed1 = false;
        scheduler.async(*scope,
                        [&] {
                            executed1 = true;
                            std::this_thread::sleep_for(100ms);
                        });

        bool executed2 = false;
        scheduler.asyncAfter(*scope, 1ms, [&] { executed2 = true; });

        std::this_thread::sleep_for(10ms); // let the first task get going, but not end yet before resetting the scope

        scope.reset(); // will block until task1 is done

        EXPECT_EQ(executed1, true);
        EXPECT_EQ(executed2, false);
    }
}

TEST(TaskThread, scopeRemoval) {
    {
        TaskThread scheduler;

        TaskThread::TaskScope scope;

        auto test     = std::make_shared<int>(7);
        auto weakTest = std::weak_ptr<int>{test};

        EXPECT_EQ((bool)weakTest.lock(), true);

        scheduler.async(scope, [test = std::move(test)]{});

        std::this_thread::sleep_for(10ms);

        scope.endScope();

        EXPECT_EQ((bool)test, false);
        EXPECT_EQ((bool)weakTest.lock(), false);
    }

    {
        TaskThread scheduler;

        TaskThread::TaskScope scope;

        auto test     = std::make_shared<int>(7);
        auto weakTest = std::weak_ptr<int>{test};

        EXPECT_EQ((bool)weakTest.lock(), true);

        scheduler.asyncAfter(scope, 5s, [test = std::move(test)]{});

        EXPECT_EQ((bool)weakTest.lock(), true);

        scope.endScope();

        EXPECT_EQ((bool)test, false);
        EXPECT_EQ((bool)weakTest.lock(), false);
    }

    {
        TaskThread scheduler;

        TaskThread::TaskScope scope;

        auto test     = std::make_shared<int>(7);
        auto weakTest = std::weak_ptr<int>{test};

        EXPECT_EQ((bool)weakTest.lock(), true);

        scheduler.asyncAfter(scope, 50ms, [test = std::move(test)]{});

        std::this_thread::sleep_for(100ms);

        EXPECT_EQ((bool)test, false);
        EXPECT_EQ((bool)weakTest.lock(), false);
    }
}
#endif // VALGRIND
<commit_msg>Increase threshold for TaskThread unit tests<commit_after>#include "gtest/gtest.h"

#include "scraps/TaskThread.h"

using namespace scraps;

// Realtime tests almost always fail with Valgrind
#ifndef VALGRIND
TEST(TaskThread, basicFunctionality) {
    TaskThread scheduler;

    auto argFunc = [](int x, float y, double z) {};

    auto f1 = scheduler.async(argFunc, 1, 2, 3);
    auto f2 = scheduler.async(argFunc, 1, 2.0f, 3.0);
    f1.wait();
    f2.wait();

    scheduler.asyncAt(std::chrono::steady_clock::now() + 5ms, argFunc, 1, 2, 3);
    scheduler.asyncAfter(5ms, argFunc, 1, 2, 3);

    std::this_thread::sleep_for(10ms);

    int first = 0;
    scheduler.asyncAfter(10ms,
                         [&] {
                             if (first == 0)
                                 first = 1;
                         });
    scheduler.asyncAfter(5ms,
                         [&] {
                             if (first == 0)
                                 first = 2;
                         });

    std::this_thread::sleep_for(20ms);

    EXPECT_EQ(first, 2);
}

TEST(TaskThread, timingFunctionality) {
    TaskThread scheduler;

    auto now = std::chrono::steady_clock::now();

    const auto threshold = 30ms;

    auto speedCheck = [=] { EXPECT_LT(std::chrono::steady_clock::now().time_since_epoch().count(), (now + threshold).time_since_epoch().count()); };

    for (int i = 0; i < 50; ++i) {
        scheduler.async(speedCheck);
    }

    now = std::chrono::steady_clock::now();

    for (auto i = 1us; i < 50us; i += 1us) {
        scheduler.asyncAt(now + i * 2, speedCheck);
        scheduler.asyncAfter(i, speedCheck);
    }

    std::this_thread::sleep_for(20ms);

    now = std::chrono::steady_clock::now();

    auto timeCheck = [&](auto duration) {
        auto d = std::chrono::steady_clock::now() - (now + duration);
        EXPECT_GT(d, -threshold);
        EXPECT_LT(d, threshold);
    };

    scheduler.asyncAfter(5ms, timeCheck, 5ms);

    scheduler.asyncAt(now + 5ms, timeCheck, 5ms);

    std::this_thread::sleep_for(50ms);
}

TEST(TaskThread, futuresFunctionality) {
    TaskThread scheduler;
    auto now = std::chrono::steady_clock::now();

    auto f = scheduler.asyncAfter(5ms, [&] { return 17; });
    EXPECT_EQ(f.valid(), true);
    EXPECT_EQ(f.get(), 17);

    const auto threshold = 20ms;

    EXPECT_LT(std::chrono::steady_clock::now(), now + threshold);
}

TEST(TaskThread, cancelClearFunctionality) {
    bool executed = false;

    {
        TaskThread scheduler;
        scheduler.asyncAfter(5ms, [&] { executed = true; });
    }

    EXPECT_EQ(executed, false);

    {
        TaskThread scheduler;
        scheduler.asyncAfter(5ms, [&] { executed = true; });
        scheduler.clear();
        EXPECT_EQ(executed, false);
    }
}

TEST(TaskThread, scopeFunctionality) {
    {
        TaskThread scheduler;

        TaskThread::TaskScope scope;

        bool executed1 = false;
        scheduler.async(scope, [&] { executed1 = true; });

        std::this_thread::sleep_for(10ms);

        scope.endScope();

        bool executed2 = false;
        scheduler.async(scope, [&] { executed2 = true; });

        std::this_thread::sleep_for(10ms);

        EXPECT_EQ(executed1, true);
        EXPECT_EQ(executed2, false);
    }

    {
        TaskThread scheduler;

        auto scope = std::make_unique<TaskThread::TaskScope>();

        bool executed1 = false;
        scheduler.async(*scope,
                        [&] {
                            executed1 = true;
                            std::this_thread::sleep_for(100ms);
                        });

        bool executed2 = false;
        scheduler.asyncAfter(*scope, 1ms, [&] { executed2 = true; });

        std::this_thread::sleep_for(10ms); // let the first task get going, but not end yet before resetting the scope

        scope.reset(); // will block until task1 is done

        EXPECT_EQ(executed1, true);
        EXPECT_EQ(executed2, false);
    }
}

TEST(TaskThread, scopeRemoval) {
    {
        TaskThread scheduler;

        TaskThread::TaskScope scope;

        auto test     = std::make_shared<int>(7);
        auto weakTest = std::weak_ptr<int>{test};

        EXPECT_EQ((bool)weakTest.lock(), true);

        scheduler.async(scope, [test = std::move(test)]{});

        std::this_thread::sleep_for(10ms);

        scope.endScope();

        EXPECT_EQ((bool)test, false);
        EXPECT_EQ((bool)weakTest.lock(), false);
    }

    {
        TaskThread scheduler;

        TaskThread::TaskScope scope;

        auto test     = std::make_shared<int>(7);
        auto weakTest = std::weak_ptr<int>{test};

        EXPECT_EQ((bool)weakTest.lock(), true);

        scheduler.asyncAfter(scope, 5s, [test = std::move(test)]{});

        EXPECT_EQ((bool)weakTest.lock(), true);

        scope.endScope();

        EXPECT_EQ((bool)test, false);
        EXPECT_EQ((bool)weakTest.lock(), false);
    }

    {
        TaskThread scheduler;

        TaskThread::TaskScope scope;

        auto test     = std::make_shared<int>(7);
        auto weakTest = std::weak_ptr<int>{test};

        EXPECT_EQ((bool)weakTest.lock(), true);

        scheduler.asyncAfter(scope, 50ms, [test = std::move(test)]{});

        std::this_thread::sleep_for(100ms);

        EXPECT_EQ((bool)test, false);
        EXPECT_EQ((bool)weakTest.lock(), false);
    }
}
#endif // VALGRIND
<|endoftext|>


<commit_before>#include "gtest/gtest.h"
#include "braincloud/BrainCloudClient.h"
#include "TestResult.h"
#include "TestBCFile.h"
#include "braincloud/http_codes.h"
#include "braincloud/reason_codes.h"

//#define UPLOAD_TIMEOUT_SECS 30
#define SLEEP_INTERVAL_MS 300

int TestBCFile::createFile(const char * in_path, int in_size)
{
    FILE* fp = NULL;
    fp = fopen(in_path, "w");
    if (fp == NULL)
    {
        return -1;
    }
    for (int i = 0; i < in_size; ++i)
    {
        fputc('!', fp);
    }
    fseek(fp, 0, SEEK_END);
    int fileLen = ftell(fp);
    fclose(fp);
    fp = NULL;
    return fileLen;
}

bool TestBCFile::simpleUpload(int mb, const std::string & cloudPath, const std::string & cloudFilename, std::string & out_uploadId)
{
    std::string localPath = cloudFilename;
    createFile(localPath.c_str(), mb * 1024 * 1024);

    TestResult tr;
    m_bc->getFileService()->uploadFile(cloudPath.c_str(), cloudFilename.c_str(), true, true, localPath.c_str(), &tr);
    if (!tr.run(m_bc))
    {
        return false;
    }
    out_uploadId = tr.m_response["data"]["fileDetails"]["uploadId"].asString();

    m_bc->registerFileUploadCallback(this);
    while (_completedUploadDetails.size() == 0 && _failedUploadDetails.size() == 0)
    {
        int64_t transferred = m_bc->getFileService()->getUploadBytesTransferred(out_uploadId.c_str());
        int64_t total = m_bc->getFileService()->getUploadTotalBytesToTransfer(out_uploadId.c_str());
        double progress = m_bc->getFileService()->getUploadProgress(out_uploadId.c_str());
        printf("%lld transfered %lld total %f progress\n", transferred, total, progress);

        m_bc->runCallbacks();
        TestResult::sleep(SLEEP_INTERVAL_MS);
    }
    m_bc->deregisterFileUploadCallback();
    return true;
}

void TestBCFile::fileUploadCompleted(const char * in_fileUploadId, const std::string & in_jsonResponse)
{
    std::cout << "FileUploadCompleted callback hit" << std::endl;

    UploadCompletedDetails details;
    details._fileUploadId = in_fileUploadId;
    details._jsonResponse = in_jsonResponse;
    _completedUploadDetails.push_back(details);
}

void TestBCFile::fileUploadFailed(const char * in_fileUploadId, int in_statusCode, int in_reasonCode, const std::string & in_jsonResponse)
{
    std::cout << "FileUploadFailed callback hit status(" << in_statusCode << ") reason(" << in_reasonCode << ") id(" << in_fileUploadId << ")" << std::endl;

    UploadFailedDetails details;
    details._fileUploadId = in_fileUploadId;
    details._statusCode = in_statusCode;
    details._reasonCode = in_reasonCode;
    details._jsonResponse = in_jsonResponse;
    _failedUploadDetails.push_back(details);
}

// marmalade does not support file uploads... yet!
#if !defined(IW_SDK)

TEST_F(TestBCFile, UploadSimpleFile)
{
    std::string uploadId;
    if (!simpleUpload(5, "", "uploadsimplefile.txt", uploadId))
    {
        return;
    }

    ASSERT_EQ(_completedUploadDetails.size(), 1);
    ASSERT_EQ(_failedUploadDetails.size(), 0);
}

TEST_F(TestBCFile, UploadSimpleFileAndCancel)
{
    std::string localPath = "uploadsimplefile.txt";
    createFile(localPath.c_str(), 3*1024*1024);

    TestResult tr;
    m_bc->registerFileUploadCallback(this);
    m_bc->getFileService()->uploadFile("", localPath.c_str(), true, true, localPath.c_str(), &tr);
    if (!tr.run(m_bc))
    {
        return;
    }
    std::string uploadId = tr.m_response["data"]["fileDetails"]["uploadId"].asString();

    bool transferHasStarted = false;
    while(!transferHasStarted)
    {
        m_bc->runCallbacks();
        int64_t transferred = m_bc->getFileService()->getUploadBytesTransferred(uploadId.c_str());
        int64_t total = m_bc->getFileService()->getUploadTotalBytesToTransfer(uploadId.c_str());
        double progress = m_bc->getFileService()->getUploadProgress(uploadId.c_str());
        printf("%lld transfered %lld total %f progress\n", transferred, total, progress);

        if (transferred > 0)
        {
            transferHasStarted = true;
            break; // We don't want to get hit by the sleep
        }
        TestResult::sleep(SLEEP_INTERVAL_MS);
    }
    if (!transferHasStarted)
    {
        m_bc->deregisterFileUploadCallback();
        ASSERT_TRUE(transferHasStarted);
        return;
    }

    printf("Cancelling upload\n");
    m_bc->getFileService()->cancelUpload(uploadId.c_str());
    while (_completedUploadDetails.size() == 0 && _failedUploadDetails.size() == 0)
    {
        m_bc->runCallbacks();
        TestResult::sleep(SLEEP_INTERVAL_MS);
    }
    m_bc->deregisterFileUploadCallback();

    ASSERT_EQ(_failedUploadDetails.size(), 1);
    ASSERT_EQ(_completedUploadDetails.size(), 0);
    ASSERT_EQ(_failedUploadDetails[0]._statusCode, HTTP_CLIENT_NETWORK_ERROR);
    ASSERT_EQ(_failedUploadDetails[0]._reasonCode, CLIENT_UPLOAD_FILE_CANCELLED);
}

TEST_F(TestBCFile, ListUserFiles)
{
    TestResult tr;
    m_bc->getFileService()->listUserFiles(&tr);
    tr.run(m_bc);
}

TEST_F(TestBCFile, UploadMultipleFiles)
{
	m_bc->registerFileUploadCallback(this);

    std::vector<std::string> uploadIds;
    int numTransfers = 3;
    for (int i = 0; i < numTransfers; ++i)
    {
        std::string localPath = "uploadmultiplefile"  + std::to_string(i + 1) + ".txt";
        createFile(localPath.c_str(), 2*1024*1024);

        TestResult tr;
        m_bc->getFileService()->uploadFile("", localPath.c_str(), true, true, localPath.c_str(), &tr);
        if (!tr.run(m_bc))
        {
            return;
        }
        std::string uploadId = tr.m_response["data"]["fileDetails"]["uploadId"].asString();
        uploadIds.push_back(uploadId);
    }

    int timeoutMs = 120000;
    while (_completedUploadDetails.size() + _failedUploadDetails.size() < numTransfers && timeoutMs > 0)
    {
        m_bc->runCallbacks();
        for (int i = 0; i < numTransfers; ++i)
        {
            int64_t transferred = m_bc->getFileService()->getUploadBytesTransferred(uploadIds[i].c_str());
            int64_t total = m_bc->getFileService()->getUploadTotalBytesToTransfer(uploadIds[i].c_str());
            double progress = m_bc->getFileService()->getUploadProgress(uploadIds[i].c_str());
            if (transferred >= 0)
            {
                printf("File%d %lld transfered %lld total %f progress\n", i+1, transferred, total, progress);
            }
        }

        timeoutMs -= SLEEP_INTERVAL_MS;
        TestResult::sleep(SLEEP_INTERVAL_MS);
    }
    m_bc->deregisterFileUploadCallback();

    ASSERT_TRUE(timeoutMs >= 0);
    ASSERT_EQ(_completedUploadDetails.size(), numTransfers);
    ASSERT_EQ(_failedUploadDetails.size(), 0);

    // Delete them. expect errors if the test failed, that's fine
    // So brainCloud doesn't grow indefinitely.
    for (int i = 0; i < numTransfers; ++i)
    {
        TestResult tr;
        std::string localPath = "uploadmultiplefile"  + std::to_string(i + 1) + ".txt";
        m_bc->getFileService()->deleteUserFile("", localPath.c_str(), &tr);
        tr.run(m_bc);
    }
}

TEST_F(TestBCFile, DeleteUserFile)
{
    std::string uploadId;
    if (!simpleUpload(19, "", "uploadsimplefile.txt", uploadId))
    {
        return;
    }

    ASSERT_EQ(_completedUploadDetails.size(), 1);
    ASSERT_EQ(_failedUploadDetails.size(), 0);

    TestResult tr;
    m_bc->getFileService()->deleteUserFile("", "uploadsimplefile.txt", &tr);
    tr.run(m_bc);
}

TEST_F(TestBCFile, GetCDNUrl)
{
	std::string uploadId;
	if (!simpleUpload(19, "", "uploadsimplefile.txt", uploadId))
	{
		return;
	}

	ASSERT_EQ(_completedUploadDetails.size(), 1);
	ASSERT_EQ(_failedUploadDetails.size(), 0);

	TestResult tr;
	m_bc->getFileService()->getCDNUrl("", "uploadsimplefile.txt", &tr);
	tr.run(m_bc);

	m_bc->getFileService()->deleteUserFile("", "uploadsimplefile.txt", &tr);
	tr.run(m_bc);
}

// this test requires use of a bandwidth limiter
// so it's normally commented out
/*
TEST_F(TestBCFile, LowRateTimeout)
{
    m_bc->setUploadLowTransferRateThreshold(500);
    m_bc->setUploadLowTransferRateTimeout(15);

    std::string uploadId;
    if (!simpleUpload(19, "", "uploadsimplefile.txt", uploadId))
    {
        return;
    }

    ASSERT_EQ(_completedUploadDetails.size(), 0);
    ASSERT_EQ(_failedUploadDetails.size(), 1);
    ASSERT_EQ(_failedUploadDetails[0]._statusCode, HTTP_CUSTOM);
    ASSERT_EQ(_failedUploadDetails[0]._reasonCode, CLIENT_UPLOAD_FILE_TIMED_OUT);
}
*/

#endif //!IW_SDK<commit_msg>Shorter sleep so can stop faster in release<commit_after>#include "gtest/gtest.h"
#include "braincloud/BrainCloudClient.h"
#include "TestResult.h"
#include "TestBCFile.h"
#include "braincloud/http_codes.h"
#include "braincloud/reason_codes.h"

//#define UPLOAD_TIMEOUT_SECS 30
#define SLEEP_INTERVAL_MS 300

int TestBCFile::createFile(const char * in_path, int in_size)
{
    FILE* fp = NULL;
    fp = fopen(in_path, "w");
    if (fp == NULL)
    {
        return -1;
    }
    for (int i = 0; i < in_size; ++i)
    {
        fputc('!', fp);
    }
    fseek(fp, 0, SEEK_END);
    int fileLen = ftell(fp);
    fclose(fp);
    fp = NULL;
    return fileLen;
}

bool TestBCFile::simpleUpload(int mb, const std::string & cloudPath, const std::string & cloudFilename, std::string & out_uploadId)
{
    std::string localPath = cloudFilename;
    createFile(localPath.c_str(), mb * 1024 * 1024);

    TestResult tr;
    m_bc->getFileService()->uploadFile(cloudPath.c_str(), cloudFilename.c_str(), true, true, localPath.c_str(), &tr);
    if (!tr.run(m_bc))
    {
        return false;
    }
    out_uploadId = tr.m_response["data"]["fileDetails"]["uploadId"].asString();

    m_bc->registerFileUploadCallback(this);
    while (_completedUploadDetails.size() == 0 && _failedUploadDetails.size() == 0)
    {
        int64_t transferred = m_bc->getFileService()->getUploadBytesTransferred(out_uploadId.c_str());
        int64_t total = m_bc->getFileService()->getUploadTotalBytesToTransfer(out_uploadId.c_str());
        double progress = m_bc->getFileService()->getUploadProgress(out_uploadId.c_str());
        printf("%lld transfered %lld total %f progress\n", transferred, total, progress);

        m_bc->runCallbacks();
        TestResult::sleep(SLEEP_INTERVAL_MS);
    }
    m_bc->deregisterFileUploadCallback();
    return true;
}

void TestBCFile::fileUploadCompleted(const char * in_fileUploadId, const std::string & in_jsonResponse)
{
    std::cout << "FileUploadCompleted callback hit" << std::endl;

    UploadCompletedDetails details;
    details._fileUploadId = in_fileUploadId;
    details._jsonResponse = in_jsonResponse;
    _completedUploadDetails.push_back(details);
}

void TestBCFile::fileUploadFailed(const char * in_fileUploadId, int in_statusCode, int in_reasonCode, const std::string & in_jsonResponse)
{
    std::cout << "FileUploadFailed callback hit status(" << in_statusCode << ") reason(" << in_reasonCode << ") id(" << in_fileUploadId << ")" << std::endl;

    UploadFailedDetails details;
    details._fileUploadId = in_fileUploadId;
    details._statusCode = in_statusCode;
    details._reasonCode = in_reasonCode;
    details._jsonResponse = in_jsonResponse;
    _failedUploadDetails.push_back(details);
}

// marmalade does not support file uploads... yet!
#if !defined(IW_SDK)

TEST_F(TestBCFile, UploadSimpleFile)
{
    std::string uploadId;
    if (!simpleUpload(5, "", "uploadsimplefile.txt", uploadId))
    {
        return;
    }

    ASSERT_EQ(_completedUploadDetails.size(), 1);
    ASSERT_EQ(_failedUploadDetails.size(), 0);
}

TEST_F(TestBCFile, UploadSimpleFileAndCancel)
{
    std::string localPath = "uploadsimplefile.txt";
    createFile(localPath.c_str(), 3*1024*1024);

    TestResult tr;
    m_bc->registerFileUploadCallback(this);
    m_bc->getFileService()->uploadFile("", localPath.c_str(), true, true, localPath.c_str(), &tr);
    if (!tr.run(m_bc))
    {
        return;
    }
    std::string uploadId = tr.m_response["data"]["fileDetails"]["uploadId"].asString();

    bool transferHasStarted = false;
    while(!transferHasStarted)
    {
        m_bc->runCallbacks();
        int64_t transferred = m_bc->getFileService()->getUploadBytesTransferred(uploadId.c_str());
        int64_t total = m_bc->getFileService()->getUploadTotalBytesToTransfer(uploadId.c_str());
        double progress = m_bc->getFileService()->getUploadProgress(uploadId.c_str());
        printf("%lld transfered %lld total %f progress\n", transferred, total, progress);

        if (transferred > 0)
        {
            transferHasStarted = true;
            break; // We don't want to get hit by the sleep
        }
        TestResult::sleep(10);
    }
    if (!transferHasStarted)
    {
        m_bc->deregisterFileUploadCallback();
        ASSERT_TRUE(transferHasStarted);
        return;
    }

    printf("Cancelling upload\n");
    m_bc->getFileService()->cancelUpload(uploadId.c_str());
    while (_completedUploadDetails.size() == 0 && _failedUploadDetails.size() == 0)
    {
        m_bc->runCallbacks();
        TestResult::sleep(SLEEP_INTERVAL_MS);
    }
    m_bc->deregisterFileUploadCallback();

    ASSERT_EQ(_failedUploadDetails.size(), 1);
    ASSERT_EQ(_completedUploadDetails.size(), 0);
    ASSERT_EQ(_failedUploadDetails[0]._statusCode, HTTP_CLIENT_NETWORK_ERROR);
    ASSERT_EQ(_failedUploadDetails[0]._reasonCode, CLIENT_UPLOAD_FILE_CANCELLED);
}

TEST_F(TestBCFile, ListUserFiles)
{
    TestResult tr;
    m_bc->getFileService()->listUserFiles(&tr);
    tr.run(m_bc);
}

TEST_F(TestBCFile, UploadMultipleFiles)
{
	m_bc->registerFileUploadCallback(this);

    std::vector<std::string> uploadIds;
    int numTransfers = 3;
    for (int i = 0; i < numTransfers; ++i)
    {
        std::string localPath = "uploadmultiplefile"  + std::to_string(i + 1) + ".txt";
        createFile(localPath.c_str(), 2*1024*1024);

        TestResult tr;
        m_bc->getFileService()->uploadFile("", localPath.c_str(), true, true, localPath.c_str(), &tr);
        if (!tr.run(m_bc))
        {
            return;
        }
        std::string uploadId = tr.m_response["data"]["fileDetails"]["uploadId"].asString();
        uploadIds.push_back(uploadId);
    }

    int timeoutMs = 120000;
    while (_completedUploadDetails.size() + _failedUploadDetails.size() < numTransfers && timeoutMs > 0)
    {
        m_bc->runCallbacks();
        for (int i = 0; i < numTransfers; ++i)
        {
            int64_t transferred = m_bc->getFileService()->getUploadBytesTransferred(uploadIds[i].c_str());
            int64_t total = m_bc->getFileService()->getUploadTotalBytesToTransfer(uploadIds[i].c_str());
            double progress = m_bc->getFileService()->getUploadProgress(uploadIds[i].c_str());
            if (transferred >= 0)
            {
                printf("File%d %lld transfered %lld total %f progress\n", i+1, transferred, total, progress);
            }
        }

        timeoutMs -= SLEEP_INTERVAL_MS;
        TestResult::sleep(SLEEP_INTERVAL_MS);
    }
    m_bc->deregisterFileUploadCallback();

    ASSERT_TRUE(timeoutMs >= 0);
    ASSERT_EQ(_completedUploadDetails.size(), numTransfers);
    ASSERT_EQ(_failedUploadDetails.size(), 0);

    // Delete them. expect errors if the test failed, that's fine
    // So brainCloud doesn't grow indefinitely.
    for (int i = 0; i < numTransfers; ++i)
    {
        TestResult tr;
        std::string localPath = "uploadmultiplefile"  + std::to_string(i + 1) + ".txt";
        m_bc->getFileService()->deleteUserFile("", localPath.c_str(), &tr);
        tr.run(m_bc);
    }
}

TEST_F(TestBCFile, DeleteUserFile)
{
    std::string uploadId;
    if (!simpleUpload(19, "", "uploadsimplefile.txt", uploadId))
    {
        return;
    }

    ASSERT_EQ(_completedUploadDetails.size(), 1);
    ASSERT_EQ(_failedUploadDetails.size(), 0);

    TestResult tr;
    m_bc->getFileService()->deleteUserFile("", "uploadsimplefile.txt", &tr);
    tr.run(m_bc);
}

TEST_F(TestBCFile, GetCDNUrl)
{
	std::string uploadId;
	if (!simpleUpload(19, "", "uploadsimplefile.txt", uploadId))
	{
		return;
	}

	ASSERT_EQ(_completedUploadDetails.size(), 1);
	ASSERT_EQ(_failedUploadDetails.size(), 0);

	TestResult tr;
	m_bc->getFileService()->getCDNUrl("", "uploadsimplefile.txt", &tr);
	tr.run(m_bc);

	m_bc->getFileService()->deleteUserFile("", "uploadsimplefile.txt", &tr);
	tr.run(m_bc);
}

// this test requires use of a bandwidth limiter
// so it's normally commented out
/*
TEST_F(TestBCFile, LowRateTimeout)
{
    m_bc->setUploadLowTransferRateThreshold(500);
    m_bc->setUploadLowTransferRateTimeout(15);

    std::string uploadId;
    if (!simpleUpload(19, "", "uploadsimplefile.txt", uploadId))
    {
        return;
    }

    ASSERT_EQ(_completedUploadDetails.size(), 0);
    ASSERT_EQ(_failedUploadDetails.size(), 1);
    ASSERT_EQ(_failedUploadDetails[0]._statusCode, HTTP_CUSTOM);
    ASSERT_EQ(_failedUploadDetails[0]._reasonCode, CLIENT_UPLOAD_FILE_TIMED_OUT);
}
*/

#endif //!IW_SDK<|endoftext|>


<commit_before>#ifndef TESTHELPER_HPP
#define TESTHELPER_HPP
#include "../../3rdParty/catch/catch.hpp"
#include <chrono>
#include <ratio>
#include <future>

namespace TestHelper {
	namespace Config {
		//3 second test timeout
		typedef std::chrono::duration<float, std::ratio_multiply<std::chrono::seconds::period, std::ratio<3>>> test_timeout;
	}
	template<typename T>
	static T get_with_timeout(std::future<T>& future_to_wait_for)
	{
		const auto status = future_to_wait_for.wait_for(TestHelper::Config::test_timeout(1));
		REQUIRE(status != std::future_status::deferred);
		REQUIRE(status != std::future_status::timeout);
		if (status == std::future_status::ready) {
			return future_to_wait_for.get();
		}
	};
}
#endif<commit_msg>Increased test timeout to 10 seconds to stop travis ci from failing, I assume this is becauase it is a very slow vm, that gets suspended alot.<commit_after>#ifndef TESTHELPER_HPP
#define TESTHELPER_HPP
#include "../../3rdParty/catch/catch.hpp"
#include <chrono>
#include <ratio>
#include <future>

namespace TestHelper {
	namespace Config {
		//3 second test timeout
		typedef std::chrono::duration<float, std::ratio_multiply<std::chrono::seconds::period, std::ratio<10>>> test_timeout;
	}
	template<typename T>
	static T get_with_timeout(std::future<T>& future_to_wait_for)
	{
		const auto status = future_to_wait_for.wait_for(TestHelper::Config::test_timeout(1));
		REQUIRE(status != std::future_status::deferred);
		REQUIRE(status != std::future_status::timeout);
		if (status == std::future_status::ready) {
			return future_to_wait_for.get();
		}
	};
}
#endif<|endoftext|>


<commit_before>#include <QtTest/QtTest>

#include "tarsnaptask.h"

class TestTask : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void sleep_ok();
    void sleep_fail();
    void sleep_crash();
    void sleep_filenotfound();
    void cmd_filenotfound();

private:
    QString get_script(QString scriptname);
};

void TestTask::initTestCase()
{
    QCoreApplication::setOrganizationName(TEST_NAME);
}

QString TestTask::get_script(QString scriptname)
{
    QDir dir = QDir(QCoreApplication::applicationDirPath());

#ifdef Q_OS_OSX
    // Handle the OSX app bundle.
    dir.cdUp();
    dir.cdUp();
    dir.cdUp();
#endif

    return dir.absolutePath() + "/" + scriptname;
}

#define RUN_SCRIPT(scriptname)                                                 \
    TarsnapTask *task = new TarsnapTask();                                     \
    QSignalSpy   sig_started(task, SIGNAL(started(QVariant)));                 \
    QSignalSpy   sig_fin(task,                                                 \
                       SIGNAL(finished(QVariant, int, QString, QString)));     \
    QSignalSpy sig_dequeue(task, SIGNAL(dequeue()));                           \
                                                                               \
    task->setCommand("/bin/sh");                                               \
    task->setArguments(QStringList(get_script(scriptname)));                   \
    task->run();                                                               \
    QVERIFY(sig_started.count() == 1);                                         \
    QVERIFY(sig_dequeue.count() == 1);                                         \
    delete task;

void TestTask::sleep_ok()
{
    RUN_SCRIPT("sleep-1-exit-0.sh");
    // We got a "finished" signal, with exit code 0.
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == 0);
}

void TestTask::sleep_fail()
{
    RUN_SCRIPT("sleep-1-exit-1.sh");
    // We got a "finished" signal, with exit code 1.
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == 1);
}

void TestTask::sleep_crash()
{
    RUN_SCRIPT("sleep-1-crash.sh");
    // Despite the crash, we should still get a "finished" signal.
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == EXIT_CRASHED);
}

void TestTask::sleep_filenotfound()
{
    // This script should not exist.
    RUN_SCRIPT("sleep-1-filenotfound.sh");
    // We got a "finished" signal, with sh exit code 127 ("command not found").
    QVERIFY(sig_fin.count() == 1);
#if defined(Q_OS_FREEBSD)
    // Bug in FreeBSD
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == 2);
#else
    // POSIX standard error code for "command not found"
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == 127);
#endif
}

void TestTask::cmd_filenotfound()
{
    TarsnapTask *task = new TarsnapTask();
    QSignalSpy   sig_started(task, SIGNAL(started(QVariant)));
    QSignalSpy sig_fin(task, SIGNAL(finished(QVariant, int, QString, QString)));
    QSignalSpy sig_dequeue(task, SIGNAL(dequeue()));

    task->setCommand("/fake/dir/fake-cmd");
    task->run();
    // We got a "finished" signal, with exit code EXIT_DID_NOT_START.
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == EXIT_DID_NOT_START);

    delete task;
}

QTEST_MAIN(TestTask)
#include "test-task.moc"
<commit_msg>Free a "hidden" TSettings<commit_after>#include <QtTest/QtTest>

#include "tarsnaptask.h"

#include <TSettings.h>

class TestTask : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void cleanupTestCase();

    void sleep_ok();
    void sleep_fail();
    void sleep_crash();
    void sleep_filenotfound();
    void cmd_filenotfound();

private:
    QString get_script(QString scriptname);
};

void TestTask::initTestCase()
{
    QCoreApplication::setOrganizationName(TEST_NAME);
}

void TestTask::cleanupTestCase()
{
    // TSettings is used inside ConsoleLog (debug.cpp), which is used by
    // TarsnapTask.
    TSettings::destroy();
}

QString TestTask::get_script(QString scriptname)
{
    QDir dir = QDir(QCoreApplication::applicationDirPath());

#ifdef Q_OS_OSX
    // Handle the OSX app bundle.
    dir.cdUp();
    dir.cdUp();
    dir.cdUp();
#endif

    return dir.absolutePath() + "/" + scriptname;
}

#define RUN_SCRIPT(scriptname)                                                 \
    TarsnapTask *task = new TarsnapTask();                                     \
    QSignalSpy   sig_started(task, SIGNAL(started(QVariant)));                 \
    QSignalSpy   sig_fin(task,                                                 \
                       SIGNAL(finished(QVariant, int, QString, QString)));     \
    QSignalSpy sig_dequeue(task, SIGNAL(dequeue()));                           \
                                                                               \
    task->setCommand("/bin/sh");                                               \
    task->setArguments(QStringList(get_script(scriptname)));                   \
    task->run();                                                               \
    QVERIFY(sig_started.count() == 1);                                         \
    QVERIFY(sig_dequeue.count() == 1);                                         \
    delete task;

void TestTask::sleep_ok()
{
    RUN_SCRIPT("sleep-1-exit-0.sh");
    // We got a "finished" signal, with exit code 0.
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == 0);
}

void TestTask::sleep_fail()
{
    RUN_SCRIPT("sleep-1-exit-1.sh");
    // We got a "finished" signal, with exit code 1.
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == 1);
}

void TestTask::sleep_crash()
{
    RUN_SCRIPT("sleep-1-crash.sh");
    // Despite the crash, we should still get a "finished" signal.
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == EXIT_CRASHED);
}

void TestTask::sleep_filenotfound()
{
    // This script should not exist.
    RUN_SCRIPT("sleep-1-filenotfound.sh");
    // We got a "finished" signal, with sh exit code 127 ("command not found").
    QVERIFY(sig_fin.count() == 1);
#if defined(Q_OS_FREEBSD)
    // Bug in FreeBSD
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == 2);
#else
    // POSIX standard error code for "command not found"
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == 127);
#endif
}

void TestTask::cmd_filenotfound()
{
    TarsnapTask *task = new TarsnapTask();
    QSignalSpy   sig_started(task, SIGNAL(started(QVariant)));
    QSignalSpy sig_fin(task, SIGNAL(finished(QVariant, int, QString, QString)));
    QSignalSpy sig_dequeue(task, SIGNAL(dequeue()));

    task->setCommand("/fake/dir/fake-cmd");
    task->run();
    // We got a "finished" signal, with exit code EXIT_DID_NOT_START.
    QVERIFY(sig_fin.count() == 1);
    QVERIFY(sig_fin.takeFirst().at(1).toInt() == EXIT_DID_NOT_START);

    delete task;
}

QTEST_MAIN(TestTask)
#include "test-task.moc"
<|endoftext|>


<commit_before>#include "manager.hpp"
#include <string.h>

using namespace std;
using namespace moodycamel;
using namespace headers;
using namespace chrono;

void Manager::initNetmap(){

	if(geteuid() != 0){
		fatal("You need to be root in order to use Netmap!");
	}

	routingTable = make_shared<LinuxTable>(this->interfaces);
	//routingTable->print_table();
	curLPM = make_shared<LPM>(*(routingTable.get()));

	nmreq_root.nr_version = NETMAP_API;
	nmreq_root.nr_tx_slots = 2048;
	nmreq_root.nr_rx_slots = 2048;
	nmreq_root.nr_tx_rings = numWorkers;
	nmreq_root.nr_rx_rings = numWorkers;
	nmreq_root.nr_ringid = 0;
	nmreq_root.nr_flags = NR_REG_NIC_SW;
	nmreq_root.nr_cmd = 0;
	nmreq_root.nr_arg1 = 0;
	nmreq_root.nr_arg2 = 1;
	nmreq_root.nr_arg3 = 256;

	int iface_num=0;

	for(auto iface : interfacesToUse){
		logInfo("Manager::initNetmap Preparing interface " + iface);
		int fd = 0;
		fds.push_back(fd = open("/dev/netmap", O_RDWR));
		strncpy(nmreq_root.nr_name, iface.c_str(), 16);
		ioctl(fd, NIOCREGIF, &nmreq_root);
		if(!mmapRegion){
			mmapRegion = mmap(0, nmreq_root.nr_memsize,
					PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
			if(mmapRegion == MAP_FAILED){
				logErr("Manager::initNetmap() mmap() failed (netmap module loaded?)");
				logErr("error: " + string(strerror(errno)));
				abort();
			}
		}
		if(nmreq_root.nr_tx_rings != numWorkers){
			stringstream sstream;
			sstream << "Could not set the correct amount of TX rings!" << endl;
			sstream << "Present: " << nmreq_root.nr_tx_rings << endl;
			sstream << "Expected: " << numWorkers << endl;
			sstream << "Please use the following command" << endl;
			sstream << "ethtool -L " << iface  <<" combined " << numWorkers << endl;
			fatal(sstream.str());
		}
		if(nmreq_root.nr_rx_rings != numWorkers){
			stringstream sstream;
			sstream << "Could not set the correct amount of RX rings!" << endl;
			sstream << "Present: " << nmreq_root.nr_rx_rings << endl;
			sstream << "Expected: " << numWorkers << endl;
			sstream << "Please use the following command" << endl;
			sstream << "ethtool -L " << iface  <<" combined " << numWorkers << endl;
			fatal(sstream.str());
		}

		netmap_if* nifp = NETMAP_IF(mmapRegion, nmreq_root.nr_offset);
		netmapIfs.push_back(nifp);

		netmapTxRings.resize(netmapTxRings.size()+1);
		netmapRxRings.resize(netmapRxRings.size()+1);

		for(uint32_t i=0; i<nifp->ni_tx_rings+1; i++){
			netmapTxRings[iface_num].push_back(NETMAP_TXRING(nifp, i));
		}
		for(uint32_t i=0; i<nifp->ni_rx_rings+1; i++){
			netmapRxRings[iface_num].push_back(NETMAP_RXRING(nifp, i));
		}

		for(uint32_t bufIdx = nifp->ni_bufs_head; bufIdx;
				bufIdx = * reinterpret_cast<uint32_t*>(NETMAP_BUF(netmapTxRings[0][0], bufIdx))){
			freeBufs.push_back(bufIdx);
		}
		logDebug("Having " + int2str(freeBufs.size()) + " free buffers at the moment");

		shared_ptr<Interface> iface_ptr;
		for(auto i : interfaces){
			if(iface == i->name){
				iface_ptr = i;
				break;
			}
		}
		if(iface_ptr == nullptr){
			fatal("Manager::initNetmap something went wrong: netmap interface not found in netlink context");
		}

		iface_ptr->netmapIndex = iface_num++;
	}

	logInfo("Manager::initNetmap Interface preparations finished.\n");

	for(unsigned int i=0; i<numWorkers; i++){
		inRings.emplace_back(make_shared<ConcurrentQueue<frame>>(RING_SIZE));
		outRings.emplace_back(make_shared<ConcurrentQueue<frame>>(RING_SIZE));
	}

	routingTable->buildNextHopList();
	routingTable->print_table();
	numInterfaces = netmapIfs.size();
};

std::vector<shared_ptr<Interface>> Manager::fillNetLink(){
	vector<shared_ptr<Interface>> interfaces = Netlink::getAllInterfaces();
	sort(interfaces.begin(), interfaces.end());
	return interfaces;
};

void Manager::startWorkerThreads(){
	arpTable.createCurrentTable(routingTable);
	for(unsigned i=0; i<numWorkers; i++){
		workers.push_back(new Worker(curLPM, arpTable.getCurrentTable(),
			inRings[i], outRings[i], interfaces));
	}
};

void Manager::process(){
	// Prepare poll fd set
	pollfd* pfds = new pollfd[numInterfaces];
	for(unsigned int i=0; i<numInterfaces; i++){
		pfds[i].fd = fds[i];
		pfds[i].events = POLLOUT | POLLIN;
	}
	// use poll to get new frames
	if(0 > poll(pfds, numInterfaces, -1)){
		fatal("poll() failed");
	}

	// Run over all interfaces and rings -> enqueue new frames for workers
	for(uint16_t iface=0; iface < numInterfaces; iface++){
		// netmap rings
		for(unsigned int worker=0; worker < numWorkers; worker++){
			netmap_ring* ring = netmapRxRings[iface][worker];
			uint32_t numFrames = nm_ring_space(ring);
			numFrames = min(numFrames, (uint32_t) freeBufs.size());
			uint32_t slotIdx = ring->head;

			for(uint32_t frameIdx=0; frameIdx < numFrames; frameIdx++){
				frame f;
				f.buf_ptr = reinterpret_cast<uint8_t*>(
						NETMAP_BUF(ring, ring->slot[slotIdx].buf_idx));
				f.len = ring->slot[slotIdx].len;
				f.iface = iface;
				f.vlan = 0;

				logDebug("Manager::process received frame from iface: " + int2str(f.iface)
						+ ", length: " + int2str(f.len)
						+ ", buf_idx: " + int2str(ring->slot[slotIdx].buf_idx)
						+ ", buf_ptr: 0x" + int2strHex((uint64_t) f.buf_ptr));

				assert(inRings[worker] != NULL);
				inRings[worker]->try_enqueue(f);
				logDebug("Manager::process enqueue new frame");

				ring->slot[slotIdx].buf_idx = freeBufs.back();
				ring->slot[slotIdx].flags = NS_BUF_CHANGED;
				freeBufs.pop_back();
				logDebug("Manager::process replacement rx buf_idx: "
						+ int2str(ring->slot[slotIdx].buf_idx));
				slotIdx = nm_ring_next(ring, slotIdx);
				ring->head = slotIdx;
				ring->cur = slotIdx;
			}
		}

		// TODO host ring
	}

	// Run over all frames processed by the workers and enqueue to netmap
	for(unsigned int worker=0; worker < numWorkers; worker++){
		frame frame;
		while(outRings[worker]->try_dequeue(frame)){
			// Check for discard/host/arp flag
			unsigned int ringid;
			if(frame.iface & frame::IFACE_HOST){
				logDebug("Manager::process Forwarding frame to kernel");
				ringid = numWorkers;
			} else if(frame.iface & frame::IFACE_ARP){
				logDebug("Manager::process handling ARP frame");
				ringid = worker;
				arpTable.handleFrame(frame);
			} else if(frame.iface & frame::IFACE_NOMAC){
				logDebug("Manager::process no MAC for target");
				ringid = worker;
				ipv4* ipv4_hdr = reinterpret_cast<ipv4*>(frame.buf_ptr + sizeof(ether));
				uint32_t ip = ipv4_hdr->d_ip;
				auto it = missingMACs.find(ip);
				if(it == missingMACs.end()){
					stringstream sstream;
					sstream << "Manager::process no ARP request sent yet,";
					sstream << " sending now via interface ";
					sstream << (frame.iface & frame::IFACE_ID);
					logDebug(sstream.str());
					macRequest mr;
					mr.ip = ip;
					mr.iface = frame.iface & frame::IFACE_ID;
					mr.time = steady_clock::now();
					arpTable.prepareRequest(ip, frame.iface & frame::IFACE_ID, frame);
					missingMACs[ip] = mr;
				} else {
					//duration<double> diff = it->second.time - steady_clock::now();
					//if(diff.count() < 0.5){
					if(false){
						// Give it a bit more time and just discard the frame
						frame.iface |= frame::IFACE_DISCARD;
						logDebug("Manager::process no new ARP request");
					} else {
						// Send out a new ARP Request
						arpTable.prepareRequest(ip, frame.iface & frame::IFACE_ID, frame);
						logDebug("Manager::process prepare new ARP request");
					}
				}
			} else {
				ringid = worker;
			}

			if(frame.iface & frame::IFACE_DISCARD){
				// Just reclaim buffer
				logDebug("Manager::process discarding frame");
				freeBufs.push_back(NETMAP_BUF_IDX(netmapTxRings[0][0], frame.buf_ptr));
				continue;
			}

			uint16_t iface = frame.iface & frame::IFACE_ID;
			netmap_ring* ring = netmapTxRings[iface][ringid];
			uint32_t slotIdx = ring->head;

			// Make sure frame has at least minimum size
			if(frame.len < 60){
				frame.len = 60;
			}

#if 1
			freeBufs.push_back(ring->slot[slotIdx].buf_idx);
			ring->slot[slotIdx].buf_idx = NETMAP_BUF_IDX(ring, frame.buf_ptr);
			ring->slot[slotIdx].flags = NS_BUF_CHANGED;
#else
			memcpy(NETMAP_BUF(ring, ring->slot[slotIdx].buf_idx),
				frame.buf_ptr, frame.len);
			freeBufs.push_back(NETMAP_BUF_IDX(ring, frame.buf_ptr));
#endif
			ring->slot[slotIdx].len = frame.len;
			ring->head = nm_ring_next(ring, ring->head);
			ring->cur = ring->head;

			logDebug("Manager::process sending frame to netmap,\n    iface: " + int2str(iface)
					+ ", slotIdx: " + int2str(slotIdx)
					+ ", buf_idx: " + int2str(ring->slot[slotIdx].buf_idx)
					+ ", length: " + int2str(ring->slot[slotIdx].len));

			logDebug("Manager::process Hexdump of frame:");
#if DEBUG
			neolib::hex_dump(NETMAP_BUF(ring, ring->slot[slotIdx].buf_idx),
				ring->slot[slotIdx].len , cerr);
#endif

		}
	}
}

void Manager::printInterfaces(){
	for(auto i : interfaces){
		logDebug(i->toString());
	}
};
<commit_msg>use bulk ops in parts of the manager<commit_after>#include "manager.hpp"
#include <string.h>

using namespace std;
using namespace moodycamel;
using namespace headers;
using namespace chrono;

void Manager::initNetmap(){

	if(geteuid() != 0){
		fatal("You need to be root in order to use Netmap!");
	}

	routingTable = make_shared<LinuxTable>(this->interfaces);
	//routingTable->print_table();
	curLPM = make_shared<LPM>(*(routingTable.get()));

	nmreq_root.nr_version = NETMAP_API;
	nmreq_root.nr_tx_slots = 2048;
	nmreq_root.nr_rx_slots = 2048;
	nmreq_root.nr_tx_rings = numWorkers;
	nmreq_root.nr_rx_rings = numWorkers;
	nmreq_root.nr_ringid = 0;
	nmreq_root.nr_flags = NR_REG_NIC_SW;
	nmreq_root.nr_cmd = 0;
	nmreq_root.nr_arg1 = 0;
	nmreq_root.nr_arg2 = 1;
	nmreq_root.nr_arg3 = 256;

	int iface_num=0;

	for(auto iface : interfacesToUse){
		logInfo("Manager::initNetmap Preparing interface " + iface);
		int fd = 0;
		fds.push_back(fd = open("/dev/netmap", O_RDWR));
		strncpy(nmreq_root.nr_name, iface.c_str(), 16);
		ioctl(fd, NIOCREGIF, &nmreq_root);
		if(!mmapRegion){
			mmapRegion = mmap(0, nmreq_root.nr_memsize,
					PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
			if(mmapRegion == MAP_FAILED){
				logErr("Manager::initNetmap() mmap() failed (netmap module loaded?)");
				logErr("error: " + string(strerror(errno)));
				abort();
			}
		}
		if(nmreq_root.nr_tx_rings != numWorkers){
			stringstream sstream;
			sstream << "Could not set the correct amount of TX rings!" << endl;
			sstream << "Present: " << nmreq_root.nr_tx_rings << endl;
			sstream << "Expected: " << numWorkers << endl;
			sstream << "Please use the following command" << endl;
			sstream << "ethtool -L " << iface  <<" combined " << numWorkers << endl;
			fatal(sstream.str());
		}
		if(nmreq_root.nr_rx_rings != numWorkers){
			stringstream sstream;
			sstream << "Could not set the correct amount of RX rings!" << endl;
			sstream << "Present: " << nmreq_root.nr_rx_rings << endl;
			sstream << "Expected: " << numWorkers << endl;
			sstream << "Please use the following command" << endl;
			sstream << "ethtool -L " << iface  <<" combined " << numWorkers << endl;
			fatal(sstream.str());
		}

		netmap_if* nifp = NETMAP_IF(mmapRegion, nmreq_root.nr_offset);
		netmapIfs.push_back(nifp);

		netmapTxRings.resize(netmapTxRings.size()+1);
		netmapRxRings.resize(netmapRxRings.size()+1);

		for(uint32_t i=0; i<nifp->ni_tx_rings+1; i++){
			netmapTxRings[iface_num].push_back(NETMAP_TXRING(nifp, i));
		}
		for(uint32_t i=0; i<nifp->ni_rx_rings+1; i++){
			netmapRxRings[iface_num].push_back(NETMAP_RXRING(nifp, i));
		}

		for(uint32_t bufIdx = nifp->ni_bufs_head; bufIdx;
				bufIdx = * reinterpret_cast<uint32_t*>(NETMAP_BUF(netmapTxRings[0][0], bufIdx))){
			freeBufs.push_back(bufIdx);
		}
		logDebug("Having " + int2str(freeBufs.size()) + " free buffers at the moment");

		shared_ptr<Interface> iface_ptr;
		for(auto i : interfaces){
			if(iface == i->name){
				iface_ptr = i;
				break;
			}
		}
		if(iface_ptr == nullptr){
			fatal("Manager::initNetmap something went wrong: netmap interface not found in netlink context");
		}

		iface_ptr->netmapIndex = iface_num++;
	}

	logInfo("Manager::initNetmap Interface preparations finished.\n");

	for(unsigned int i=0; i<numWorkers; i++){
		inRings.emplace_back(make_shared<ConcurrentQueue<frame>>(RING_SIZE));
		outRings.emplace_back(make_shared<ConcurrentQueue<frame>>(RING_SIZE));
	}

	routingTable->buildNextHopList();
	routingTable->print_table();
	numInterfaces = netmapIfs.size();
};

std::vector<shared_ptr<Interface>> Manager::fillNetLink(){
	vector<shared_ptr<Interface>> interfaces = Netlink::getAllInterfaces();
	sort(interfaces.begin(), interfaces.end());
	return interfaces;
};

void Manager::startWorkerThreads(){
	arpTable.createCurrentTable(routingTable);
	for(unsigned i=0; i<numWorkers; i++){
		workers.push_back(new Worker(curLPM, arpTable.getCurrentTable(),
			inRings[i], outRings[i], interfaces));
	}
};

void Manager::process(){
	// Prepare poll fd set
	pollfd* pfds = new pollfd[numInterfaces];
	for(unsigned int i=0; i<numInterfaces; i++){
		pfds[i].fd = fds[i];
		pfds[i].events = POLLOUT | POLLIN;
	}
	// use poll to get new frames
	if(0 > poll(pfds, numInterfaces, -1)){
		fatal("poll() failed");
	}

	// Run over all interfaces and rings -> enqueue new frames for workers
	for(uint16_t iface=0; iface < numInterfaces; iface++){
		// netmap rings
		for(unsigned int worker=0; worker < numWorkers; worker++){
			netmap_ring* ring = netmapRxRings[iface][worker];
			while(nm_ring_space(ring)){
				uint32_t numFrames = nm_ring_space(ring);
				numFrames = min(numFrames, (uint32_t) freeBufs.size());
#define MANAGER_BULK_SIZE 64
				if(numFrames > MANAGER_BULK_SIZE){
					numFrames = MANAGER_BULK_SIZE;
				}
				uint32_t slotIdx = ring->head;
				frame f[MANAGER_BULK_SIZE];
				for(uint32_t i=0; i<numFrames; i++){

					f[i].buf_ptr = reinterpret_cast<uint8_t*>(
							NETMAP_BUF(ring, ring->slot[slotIdx].buf_idx));
					f[i].len = ring->slot[slotIdx].len;
					f[i].iface = iface;
					f[i].vlan = 0;

					logDebug("Manager::process received frame from iface: " + int2str(f[i].iface)
							+ ", length: " + int2str(f[i].len)
							+ ", buf_idx: " + int2str(ring->slot[slotIdx].buf_idx)
							+ ", buf_ptr: 0x" + int2strHex((uint64_t) f[i].buf_ptr));

					ring->slot[slotIdx].buf_idx = freeBufs.back();
					ring->slot[slotIdx].flags = NS_BUF_CHANGED;
					freeBufs.pop_back();
					logDebug("Manager::process replacement rx buf_idx: "
							+ int2str(ring->slot[slotIdx].buf_idx));

					slotIdx = nm_ring_next(ring, slotIdx);
					ring->head = slotIdx;
					ring->cur = slotIdx;
				}

				inRings[worker]->try_enqueue_bulk(f, numFrames);
				logDebug("Manager::process enqueue new frames");
			}
		}
		// TODO host ring
	}

	// Run over all frames processed by the workers and enqueue to netmap
	for(unsigned int worker=0; worker < numWorkers; worker++){
		frame frame;
		while(outRings[worker]->try_dequeue(frame)){
			// Check for discard/host/arp flag
			unsigned int ringid;
			if(frame.iface & frame::IFACE_HOST){
				logDebug("Manager::process Forwarding frame to kernel");
				ringid = numWorkers;
			} else if(frame.iface & frame::IFACE_ARP){
				logDebug("Manager::process handling ARP frame");
				ringid = worker;
				arpTable.handleFrame(frame);
			} else if(frame.iface & frame::IFACE_NOMAC){
				logDebug("Manager::process no MAC for target");
				ringid = worker;
				ipv4* ipv4_hdr = reinterpret_cast<ipv4*>(frame.buf_ptr + sizeof(ether));
				uint32_t ip = ipv4_hdr->d_ip;
				auto it = missingMACs.find(ip);
				if(it == missingMACs.end()){
					stringstream sstream;
					sstream << "Manager::process no ARP request sent yet,";
					sstream << " sending now via interface ";
					sstream << (frame.iface & frame::IFACE_ID);
					logDebug(sstream.str());
					macRequest mr;
					mr.ip = ip;
					mr.iface = frame.iface & frame::IFACE_ID;
					mr.time = steady_clock::now();
					arpTable.prepareRequest(ip, frame.iface & frame::IFACE_ID, frame);
					missingMACs[ip] = mr;
				} else {
					//duration<double> diff = it->second.time - steady_clock::now();
					//if(diff.count() < 0.5){
					if(false){
						// Give it a bit more time and just discard the frame
						frame.iface |= frame::IFACE_DISCARD;
						logDebug("Manager::process no new ARP request");
					} else {
						// Send out a new ARP Request
						arpTable.prepareRequest(ip, frame.iface & frame::IFACE_ID, frame);
						logDebug("Manager::process prepare new ARP request");
					}
				}
			} else {
				ringid = worker;
			}

			if(frame.iface & frame::IFACE_DISCARD){
				// Just reclaim buffer
				logDebug("Manager::process discarding frame");
				freeBufs.push_back(NETMAP_BUF_IDX(netmapTxRings[0][0], frame.buf_ptr));
				continue;
			}

			uint16_t iface = frame.iface & frame::IFACE_ID;
			netmap_ring* ring = netmapTxRings[iface][ringid];
			uint32_t slotIdx = ring->head;

			// Make sure frame has at least minimum size
			if(frame.len < 60){
				frame.len = 60;
			}

#if 1
			freeBufs.push_back(ring->slot[slotIdx].buf_idx);
			ring->slot[slotIdx].buf_idx = NETMAP_BUF_IDX(ring, frame.buf_ptr);
			ring->slot[slotIdx].flags = NS_BUF_CHANGED;
#else
			memcpy(NETMAP_BUF(ring, ring->slot[slotIdx].buf_idx),
				frame.buf_ptr, frame.len);
			freeBufs.push_back(NETMAP_BUF_IDX(ring, frame.buf_ptr));
#endif
			ring->slot[slotIdx].len = frame.len;
			ring->head = nm_ring_next(ring, ring->head);
			ring->cur = ring->head;

			logDebug("Manager::process sending frame to netmap,\n    iface: " + int2str(iface)
					+ ", slotIdx: " + int2str(slotIdx)
					+ ", buf_idx: " + int2str(ring->slot[slotIdx].buf_idx)
					+ ", length: " + int2str(ring->slot[slotIdx].len));

			logDebug("Manager::process Hexdump of frame:");
#if DEBUG
			neolib::hex_dump(NETMAP_BUF(ring, ring->slot[slotIdx].buf_idx),
				ring->slot[slotIdx].len , cerr);
#endif

		}
	}
}

void Manager::printInterfaces(){
	for(auto i : interfaces){
		logDebug(i->toString());
	}
};
<|endoftext|>


<commit_before>#include <tests/Base.hh>

#include <aleph/topology/Partitions.hh>

#include <aleph/topology/Simplex.hh>
#include <aleph/topology/SimplicialComplex.hh>

#include <vector>

// FIXME: remove after debugging
#include <iostream>

template <class T> void test()
{
  ALEPH_TEST_BEGIN( "Bisection" );

  using Simplex           = aleph::topology::Simplex<T>;
  using SimplicialComplex = aleph::topology::SimplicialComplex<Simplex>;
  using VertexType        = typename Simplex::VertexType;

  SimplicialComplex K;

  K.push_back( Simplex( VertexType(0), 0 ) ); K.push_back( Simplex( VertexType(1), 0 ) );
  K.push_back( Simplex( VertexType(2), 0 ) ); K.push_back( Simplex( VertexType(3), 0 ) );
  K.push_back( Simplex( VertexType(4), 0 ) ); K.push_back( Simplex( VertexType(5), 0 ) );

  K.push_back( Simplex( {0,1}, 1 ) );
  K.push_back( Simplex( {0,2}, 1 ) );
  K.push_back( Simplex( {1,2}, 1 ) );

  K.push_back( Simplex( {3,4}, 1 ) );
  K.push_back( Simplex( {3,5}, 1 ) );
  K.push_back( Simplex( {4,5}, 1 ) );

  K.push_back( Simplex( {2,3}, 1 ) );

  K.push_back( Simplex( {3,4,5}, 1 ) );
  K.push_back( Simplex( {0,1,2}, 1 ) );

  // Technically, this invalidates the simplicial complex, but I am only
  // interested in figuring out whether the partition will *ignore* this
  // simplex.
  K.push_back( Simplex( {0,1,2,3}, 1 ) );

  auto complexes = bisect( K );

  ALEPH_ASSERT_EQUAL( complexes.size(), 2 );

  auto&& K1 = complexes.front();
  auto&& K2 = complexes.back();

  ALEPH_ASSERT_EQUAL( K1.size(), K2.size() );

  ALEPH_TEST_END();
}

int main( int, char** )
{
#ifdef ALEPH_WITH_EIGEN
  test<float> ();
  test<double>();
#endif
}
<commit_msg>Cleaned up unit test for partitions<commit_after>#include <tests/Base.hh>

#include <aleph/topology/Partitions.hh>

#include <aleph/topology/Simplex.hh>
#include <aleph/topology/SimplicialComplex.hh>

#include <vector>

template <class T> void test()
{
  ALEPH_TEST_BEGIN( "Bisection" );

  using Simplex           = aleph::topology::Simplex<T>;
  using SimplicialComplex = aleph::topology::SimplicialComplex<Simplex>;
  using VertexType        = typename Simplex::VertexType;

  SimplicialComplex K;

  K.push_back( Simplex( VertexType(0), 0 ) ); K.push_back( Simplex( VertexType(1), 0 ) );
  K.push_back( Simplex( VertexType(2), 0 ) ); K.push_back( Simplex( VertexType(3), 0 ) );
  K.push_back( Simplex( VertexType(4), 0 ) ); K.push_back( Simplex( VertexType(5), 0 ) );

  K.push_back( Simplex( {0,1}, 1 ) );
  K.push_back( Simplex( {0,2}, 1 ) );
  K.push_back( Simplex( {1,2}, 1 ) );

  K.push_back( Simplex( {3,4}, 1 ) );
  K.push_back( Simplex( {3,5}, 1 ) );
  K.push_back( Simplex( {4,5}, 1 ) );

  K.push_back( Simplex( {2,3}, 1 ) );

  K.push_back( Simplex( {3,4,5}, 1 ) );
  K.push_back( Simplex( {0,1,2}, 1 ) );

  // Technically, this invalidates the simplicial complex, but I am only
  // interested in figuring out whether the partition will *ignore* this
  // simplex.
  K.push_back( Simplex( {0,1,2,3}, 1 ) );

  auto complexes = bisect( K );

  ALEPH_ASSERT_EQUAL( complexes.size(), 2 );

  auto&& K1 = complexes.front();
  auto&& K2 = complexes.back();

  ALEPH_ASSERT_EQUAL( K1.size(), K2.size() );

  ALEPH_TEST_END();
}

int main( int, char** )
{
#ifdef ALEPH_WITH_EIGEN
  test<float> ();
  test<double>();
#endif
}
<|endoftext|>


<commit_before>
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE libstorage

#include <iostream>
#include <boost/test/unit_test.hpp>

#include "storage/Environment.h"
#include "storage/Storage.h"
#include "storage/DevicegraphImpl.h"
#include "storage/UsedFeatures.h"

#include "testsuite/helpers/TsCmp.h"

using namespace std;
using namespace storage;

BOOST_AUTO_TEST_CASE(probe)
{
    set_logger(get_stdout_logger());

    Environment environment(true, ProbeMode::READ_MOCKUP, TargetMode::DIRECT);
    environment.set_mockup_filename("dasd1-mockup.xml");

    Storage storage(environment);
    storage.probe();

    const Devicegraph* probed = storage.get_probed();
    // probed->save("dasd1-devicegraph.xml");

    probed->check();

    Devicegraph* staging = storage.get_staging();

    staging->load("dasd1-devicegraph.xml");
    staging->check();

    TsCmpDevicegraph cmp(*probed, *staging);
    BOOST_CHECK_MESSAGE(cmp.ok(), cmp);
}
<commit_msg>- extended unit test<commit_after>
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE libstorage

#include <iostream>
#include <boost/test/unit_test.hpp>

#include "storage/Environment.h"
#include "storage/Storage.h"
#include "storage/DevicegraphImpl.h"
#include "storage/UsedFeatures.h"

#include "testsuite/helpers/TsCmp.h"

using namespace std;
using namespace storage;

BOOST_AUTO_TEST_CASE(probe)
{
    set_logger(get_stdout_logger());

    Environment environment(true, ProbeMode::READ_MOCKUP, TargetMode::DIRECT);
    environment.set_mockup_filename("dasd1-mockup.xml");

    Storage storage(environment);
    storage.probe();

    const Devicegraph* probed = storage.get_probed();

    probed->check();

    Devicegraph* staging = storage.get_staging();

    staging->load("dasd1-devicegraph.xml");
    staging->check();

    TsCmpDevicegraph cmp(*probed, *staging);
    BOOST_CHECK_MESSAGE(cmp.ok(), cmp);

    BOOST_CHECK_BITWISE_EQUAL(probed->used_features(), UF_EXT2 | UF_EXT4 | UF_SWAP | UF_NFS | UF_DASD);
}
<|endoftext|>


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

#if defined(HAVE_CONFIG_H)
#include "config/pivx-config.h"
#endif

#include "mapport.h"

#include "clientversion.h"
#include "logging.h"
#include "net.h"
#include "netaddress.h"
#include "netbase.h"
#include "threadinterrupt.h"
#include "util/system.h"

#ifdef USE_UPNP
#include <miniupnpc/miniupnpc.h>
#include <miniupnpc/upnpcommands.h>
#include <miniupnpc/upnperrors.h>
// The minimum supported miniUPnPc API version is set to 10. This keeps compatibility
// with Ubuntu 16.04 LTS and Debian 8 libminiupnpc-dev packages.
static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed");
#endif

#include <cassert>
#include <chrono>
#include <functional>
#include <string>
#include <thread>

#ifdef USE_UPNP
static CThreadInterrupt g_upnp_interrupt;
static std::thread g_upnp_thread;
void ThreadMapPort()
{
    std::string port = strprintf("%u", GetListenPort());
    const char* multicastif = 0;
    const char* minissdpdpath = 0;
    struct UPNPDev* devlist = 0;
    char lanaddr[64];

    int error = 0;
#if MINIUPNPC_API_VERSION < 14
    devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
#else
    devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error);
#endif

    struct UPNPUrls urls;
    struct IGDdatas data;
    int r;

    r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
    if (r == 1) {
        if (fDiscover) {
            char externalIPAddress[40];
            r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
            if (r != UPNPCOMMAND_SUCCESS) {
                LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r);
            } else {
                if (externalIPAddress[0]) {
                    CNetAddr resolved;
                    if (LookupHost(externalIPAddress, resolved, false)) {
                        LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString().c_str());
                        AddLocal(resolved, LOCAL_UPNP);
                    }
                } else {
                    LogPrintf("UPnP: GetExternalIPAddress failed.\n");
                }
            }
        }

        std::string strDesc = PACKAGE_NAME " " + FormatFullVersion();

        do {
            r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");

            if (r != UPNPCOMMAND_SUCCESS) {
                LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", port, port, lanaddr, r, strupnperror(r));
            } else {
                LogPrintf("UPnP Port Mapping successful.\n");
            }
        } while(g_upnp_interrupt.sleep_for(std::chrono::minutes(20)));

        r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
        LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r);
        freeUPNPDevlist(devlist); devlist = nullptr;
        FreeUPNPUrls(&urls);
    } else {
        LogPrintf("No valid UPnP IGDs found\n");
        freeUPNPDevlist(devlist);
        devlist = 0;
        if (r != 0)
            FreeUPNPUrls(&urls);
    }
}

void StartMapPort()
{
    if (!g_upnp_thread.joinable()) {
        assert(!g_upnp_interrupt);
        g_upnp_thread = std::thread(std::bind(&TraceThread<void (*)()>, "upnp", &ThreadMapPort));
    }
}

void InterruptMapPort()
{
    if (g_upnp_thread.joinable()) {
        g_upnp_interrupt();
    }
}

void StopMapPort()
{
    if (g_upnp_thread.joinable()) {
        g_upnp_thread.join();
        g_upnp_interrupt.reset();
    }
}

#else
void StartMapPort()
{
    // Intentionally left blank.
}
void InterruptMapPort()
{
    // Intentionally left blank.
}
void StopMapPort()
{
    // Intentionally left blank.
}
#endif
<commit_msg>refactor: Replace magic number with named constant<commit_after>// Copyright (c) 2011-2020 The Bitcoin Core developers
// Copyright (c) 2021 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include "config/pivx-config.h"
#endif

#include "mapport.h"

#include "clientversion.h"
#include "logging.h"
#include "net.h"
#include "netaddress.h"
#include "netbase.h"
#include "threadinterrupt.h"
#include "util/system.h"

#ifdef USE_UPNP
#include <miniupnpc/miniupnpc.h>
#include <miniupnpc/upnpcommands.h>
#include <miniupnpc/upnperrors.h>
// The minimum supported miniUPnPc API version is set to 10. This keeps compatibility
// with Ubuntu 16.04 LTS and Debian 8 libminiupnpc-dev packages.
static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed");
#endif

#include <cassert>
#include <chrono>
#include <functional>
#include <string>
#include <thread>

#ifdef USE_UPNP
static CThreadInterrupt g_upnp_interrupt;
static std::thread g_upnp_thread;

static constexpr auto PORT_MAPPING_REANNOUNCE_PERIOD = std::chrono::minutes(20);

void ThreadMapPort()
{
    std::string port = strprintf("%u", GetListenPort());
    const char* multicastif = 0;
    const char* minissdpdpath = 0;
    struct UPNPDev* devlist = 0;
    char lanaddr[64];

    int error = 0;
#if MINIUPNPC_API_VERSION < 14
    devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
#else
    devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error);
#endif

    struct UPNPUrls urls;
    struct IGDdatas data;
    int r;

    r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
    if (r == 1) {
        if (fDiscover) {
            char externalIPAddress[40];
            r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
            if (r != UPNPCOMMAND_SUCCESS) {
                LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r);
            } else {
                if (externalIPAddress[0]) {
                    CNetAddr resolved;
                    if (LookupHost(externalIPAddress, resolved, false)) {
                        LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString().c_str());
                        AddLocal(resolved, LOCAL_UPNP);
                    }
                } else {
                    LogPrintf("UPnP: GetExternalIPAddress failed.\n");
                }
            }
        }

        std::string strDesc = PACKAGE_NAME " " + FormatFullVersion();

        do {
            r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");

            if (r != UPNPCOMMAND_SUCCESS) {
                LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", port, port, lanaddr, r, strupnperror(r));
            } else {
                LogPrintf("UPnP Port Mapping successful.\n");
            }
        } while(g_upnp_interrupt.sleep_for(PORT_MAPPING_REANNOUNCE_PERIOD));

        r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
        LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r);
        freeUPNPDevlist(devlist); devlist = nullptr;
        FreeUPNPUrls(&urls);
    } else {
        LogPrintf("No valid UPnP IGDs found\n");
        freeUPNPDevlist(devlist);
        devlist = 0;
        if (r != 0)
            FreeUPNPUrls(&urls);
    }
}

void StartMapPort()
{
    if (!g_upnp_thread.joinable()) {
        assert(!g_upnp_interrupt);
        g_upnp_thread = std::thread(std::bind(&TraceThread<void (*)()>, "upnp", &ThreadMapPort));
    }
}

void InterruptMapPort()
{
    if (g_upnp_thread.joinable()) {
        g_upnp_interrupt();
    }
}

void StopMapPort()
{
    if (g_upnp_thread.joinable()) {
        g_upnp_thread.join();
        g_upnp_interrupt.reset();
    }
}

#else
void StartMapPort()
{
    // Intentionally left blank.
}
void InterruptMapPort()
{
    // Intentionally left blank.
}
void StopMapPort()
{
    // Intentionally left blank.
}
#endif
<|endoftext|>


<commit_before>#include "command.hh"
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
#include "eval.hh"
#include "json.hh"
#include "value-to-json.hh"

using namespace nix;

struct CmdEval : MixJSON, InstallablesCommand
{
    std::string name() override
    {
        return "eval";
    }

    std::string description() override
    {
        return "evaluate a Nix expression";
    }

    void run(ref<Store> store) override
    {
        auto state = getEvalState();

        auto jsonOut = json ? std::make_unique<JSONList>(std::cout) : nullptr;

        for (auto & i : installables) {
            auto v = i->toValue(*state);
            if (json) {
                PathSet context;
                auto jsonElem = jsonOut->placeholder();
                printValueAsJSON(*state, true, *v, jsonElem, context);
            } else {
                state->forceValueDeep(*v);
                std::cout << *v << "\n";
            }
        }
    }
};

static RegisterCommand r1(make_ref<CmdEval>());
<commit_msg>nix eval: Add a --raw flag<commit_after>#include "command.hh"
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
#include "eval.hh"
#include "json.hh"
#include "value-to-json.hh"

using namespace nix;

struct CmdEval : MixJSON, InstallablesCommand
{
    bool raw = false;

    CmdEval()
    {
        mkFlag(0, "raw", "print strings unquoted", &raw);
    }

    std::string name() override
    {
        return "eval";
    }

    std::string description() override
    {
        return "evaluate a Nix expression";
    }

    void run(ref<Store> store) override
    {
        if (raw && json)
            throw UsageError("--raw and --json are mutually exclusive");

        auto state = getEvalState();

        auto jsonOut = json ? std::make_unique<JSONList>(std::cout) : nullptr;

        for (auto & i : installables) {
            auto v = i->toValue(*state);
            if (raw) {
                std::cout << state->forceString(*v);
            } else if (json) {
                PathSet context;
                auto jsonElem = jsonOut->placeholder();
                printValueAsJSON(*state, true, *v, jsonElem, context);
            } else {
                state->forceValueDeep(*v);
                std::cout << *v << "\n";
            }
        }
    }
};

static RegisterCommand r1(make_ref<CmdEval>());
<|endoftext|>


<commit_before>void build(Solution &s)
{
    auto &tgbot = s.addTarget<StaticLibraryTarget>("reo7sp.tgbot", "1.2.0");
    {
        tgbot += Git("https://github.com/reo7sp/tgbot-cpp", "v{M}.{m}");

        tgbot += cpp11;

        tgbot.Public += "org.sw.demo.boost.property_tree"_dep;
        tgbot.Public += "org.sw.demo.openssl.ssl"_dep;
        tgbot.Public += "org.sw.demo.boost.system"_dep;
        tgbot.Public += "org.sw.demo.boost.date_time"_dep;
        tgbot.Public += "org.sw.demo.badger.curl.libcurl"_dep, "HAVE_CURL"_def;
        tgbot.Public += "org.sw.demo.boost.asio"_dep;
    }

    auto &t = tgbot.addExecutable("test");
    {
        t.Scope = TargetScope::Test;
        t += "test/.*"_rr;
        t += "test"_idir;
        t += "SW_BUILD"_def;
        t += tgbot;
        t += "org.sw.demo.boost.test"_dep;
    }

    tgbot.addTest(t);
}
<commit_msg>Add cpp11 for test also.<commit_after>void build(Solution &s)
{
    auto &tgbot = s.addTarget<StaticLibraryTarget>("reo7sp.tgbot", "1.2.0");
    {
        tgbot += Git("https://github.com/reo7sp/tgbot-cpp", "v{M}.{m}");

        tgbot += cpp11;

        tgbot.Public += "org.sw.demo.boost.property_tree"_dep;
        tgbot.Public += "org.sw.demo.openssl.ssl"_dep;
        tgbot.Public += "org.sw.demo.boost.system"_dep;
        tgbot.Public += "org.sw.demo.boost.date_time"_dep;
        tgbot.Public += "org.sw.demo.badger.curl.libcurl"_dep, "HAVE_CURL"_def;
        tgbot.Public += "org.sw.demo.boost.asio"_dep;
    }

    auto &t = tgbot.addExecutable("test");
    {
        t.Scope = TargetScope::Test;
        t += cpp11;
        t += "test/.*"_rr;
        t += "test"_idir;
        t += "SW_BUILD"_def;
        t += tgbot;
        t += "org.sw.demo.boost.test"_dep;
    }

    tgbot.addTest(t);
}
<|endoftext|>