<commit_before>/*
 *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#include "third_party/googletest/src/include/gtest/gtest.h"
#include "test/codec_factory.h"
#include "test/encode_test_driver.h"
#include "test/i420_video_source.h"
#include "test/util.h"
namespace {

#if CONFIG_VP8_ENCODER

// lookahead range: [kLookAheadMin, kLookAheadMax).
const int kLookAheadMin = 5;
const int kLookAheadMax = 26;

class AltRefTest : public ::libvpx_test::EncoderTest,
                   public ::libvpx_test::CodecTestWithParam<int> {
 protected:
  AltRefTest() : EncoderTest(GET_PARAM(0)), altref_count_(0) {}
  virtual ~AltRefTest() {}

  virtual void SetUp() {
    InitializeConfig();
    SetMode(libvpx_test::kTwoPassGood);
  }

  virtual void BeginPassHook(unsigned int pass) { altref_count_ = 0; }

  virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
                                  libvpx_test::Encoder *encoder) {
    if (video->frame() == 1) {
      encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
      encoder->Control(VP8E_SET_CPUUSED, 3);
    }
  }

  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
    if (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE) ++altref_count_;
  }

  int altref_count() const { return altref_count_; }

 private:
  int altref_count_;
};

TEST_P(AltRefTest, MonotonicTimestamps) {
  const vpx_rational timebase = { 33333333, 1000000000 };
  cfg_.g_timebase = timebase;
  cfg_.rc_target_bitrate = 1000;
  cfg_.g_lag_in_frames = GET_PARAM(1);

  libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                     timebase.den, timebase.num, 0, 30);
  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
  EXPECT_GE(altref_count(), 1);
}

VP8_INSTANTIATE_TEST_CASE(AltRefTest,
                          ::testing::Range(kLookAheadMin, kLookAheadMax));

#endif  // CONFIG_VP8_ENCODER

class AltRefForcedKeyTestLarge
    : public ::libvpx_test::EncoderTest,
      public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
 protected:
  AltRefForcedKeyTestLarge()
      : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)),
        cpu_used_(GET_PARAM(2)), forced_kf_frame_num_(1), frame_num_(0) {}
  virtual ~AltRefForcedKeyTestLarge() {}

  virtual void SetUp() {
    InitializeConfig();
    SetMode(encoding_mode_);
    cfg_.rc_end_usage = VPX_VBR;
    cfg_.g_threads = 0;
  }

  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
                                  ::libvpx_test::Encoder *encoder) {
    if (video->frame() == 0) {
      encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
      encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
#if CONFIG_VP9_ENCODER
      // override test default for tile columns if necessary.
      if (GET_PARAM(0) == &libvpx_test::kVP9) {
        encoder->Control(VP9E_SET_TILE_COLUMNS, 6);
      }
#endif
    }
    frame_flags_ =
        (video->frame() == forced_kf_frame_num_) ? VPX_EFLAG_FORCE_KF : 0;
  }

  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
    if (frame_num_ == forced_kf_frame_num_) {
      ASSERT_TRUE(!!(pkt->data.frame.flags & VPX_FRAME_IS_KEY))
          << "Frame #" << frame_num_ << " isn't a keyframe!";
    }
    ++frame_num_;
  }

  ::libvpx_test::TestMode encoding_mode_;
  int cpu_used_;
  unsigned int forced_kf_frame_num_;
  unsigned int frame_num_;
};

TEST_P(AltRefForcedKeyTestLarge, Frame1IsKey) {
  const vpx_rational timebase = { 1, 30 };
  const int lag_values[] = { 3, 15, 25, -1 };

  forced_kf_frame_num_ = 1;
  for (int i = 0; lag_values[i] != -1; ++i) {
    frame_num_ = 0;
    cfg_.g_lag_in_frames = lag_values[i];
    libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       timebase.den, timebase.num, 0, 30);
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
  }
}

TEST_P(AltRefForcedKeyTestLarge, ForcedFrameIsKey) {
  const vpx_rational timebase = { 1, 30 };
  const int lag_values[] = { 3, 15, 25, -1 };

  for (int i = 0; lag_values[i] != -1; ++i) {
    frame_num_ = 0;
    forced_kf_frame_num_ = lag_values[i] - 1;
    cfg_.g_lag_in_frames = lag_values[i];
    libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       timebase.den, timebase.num, 0, 30);
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
  }
}

VP8_INSTANTIATE_TEST_CASE(AltRefForcedKeyTestLarge,
                          ::testing::Values(::libvpx_test::kOnePassGood),
                          ::testing::Range(0, 9));

VP9_INSTANTIATE_TEST_CASE(AltRefForcedKeyTestLarge,
                          ::testing::Values(::libvpx_test::kOnePassGood),
                          ::testing::Range(0, 9));
}  // namespace
<commit_msg>altref test: comment out 'pass'<commit_after>/*
 *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#include "third_party/googletest/src/include/gtest/gtest.h"
#include "test/codec_factory.h"
#include "test/encode_test_driver.h"
#include "test/i420_video_source.h"
#include "test/util.h"
namespace {

#if CONFIG_VP8_ENCODER

// lookahead range: [kLookAheadMin, kLookAheadMax).
const int kLookAheadMin = 5;
const int kLookAheadMax = 26;

class AltRefTest : public ::libvpx_test::EncoderTest,
                   public ::libvpx_test::CodecTestWithParam<int> {
 protected:
  AltRefTest() : EncoderTest(GET_PARAM(0)), altref_count_(0) {}
  virtual ~AltRefTest() {}

  virtual void SetUp() {
    InitializeConfig();
    SetMode(libvpx_test::kTwoPassGood);
  }

  virtual void BeginPassHook(unsigned int /*pass*/) { altref_count_ = 0; }

  virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
                                  libvpx_test::Encoder *encoder) {
    if (video->frame() == 1) {
      encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
      encoder->Control(VP8E_SET_CPUUSED, 3);
    }
  }

  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
    if (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE) ++altref_count_;
  }

  int altref_count() const { return altref_count_; }

 private:
  int altref_count_;
};

TEST_P(AltRefTest, MonotonicTimestamps) {
  const vpx_rational timebase = { 33333333, 1000000000 };
  cfg_.g_timebase = timebase;
  cfg_.rc_target_bitrate = 1000;
  cfg_.g_lag_in_frames = GET_PARAM(1);

  libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                     timebase.den, timebase.num, 0, 30);
  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
  EXPECT_GE(altref_count(), 1);
}

VP8_INSTANTIATE_TEST_CASE(AltRefTest,
                          ::testing::Range(kLookAheadMin, kLookAheadMax));

#endif  // CONFIG_VP8_ENCODER

class AltRefForcedKeyTestLarge
    : public ::libvpx_test::EncoderTest,
      public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
 protected:
  AltRefForcedKeyTestLarge()
      : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)),
        cpu_used_(GET_PARAM(2)), forced_kf_frame_num_(1), frame_num_(0) {}
  virtual ~AltRefForcedKeyTestLarge() {}

  virtual void SetUp() {
    InitializeConfig();
    SetMode(encoding_mode_);
    cfg_.rc_end_usage = VPX_VBR;
    cfg_.g_threads = 0;
  }

  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
                                  ::libvpx_test::Encoder *encoder) {
    if (video->frame() == 0) {
      encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
      encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
#if CONFIG_VP9_ENCODER
      // override test default for tile columns if necessary.
      if (GET_PARAM(0) == &libvpx_test::kVP9) {
        encoder->Control(VP9E_SET_TILE_COLUMNS, 6);
      }
#endif
    }
    frame_flags_ =
        (video->frame() == forced_kf_frame_num_) ? VPX_EFLAG_FORCE_KF : 0;
  }

  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
    if (frame_num_ == forced_kf_frame_num_) {
      ASSERT_TRUE(!!(pkt->data.frame.flags & VPX_FRAME_IS_KEY))
          << "Frame #" << frame_num_ << " isn't a keyframe!";
    }
    ++frame_num_;
  }

  ::libvpx_test::TestMode encoding_mode_;
  int cpu_used_;
  unsigned int forced_kf_frame_num_;
  unsigned int frame_num_;
};

TEST_P(AltRefForcedKeyTestLarge, Frame1IsKey) {
  const vpx_rational timebase = { 1, 30 };
  const int lag_values[] = { 3, 15, 25, -1 };

  forced_kf_frame_num_ = 1;
  for (int i = 0; lag_values[i] != -1; ++i) {
    frame_num_ = 0;
    cfg_.g_lag_in_frames = lag_values[i];
    libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       timebase.den, timebase.num, 0, 30);
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
  }
}

TEST_P(AltRefForcedKeyTestLarge, ForcedFrameIsKey) {
  const vpx_rational timebase = { 1, 30 };
  const int lag_values[] = { 3, 15, 25, -1 };

  for (int i = 0; lag_values[i] != -1; ++i) {
    frame_num_ = 0;
    forced_kf_frame_num_ = lag_values[i] - 1;
    cfg_.g_lag_in_frames = lag_values[i];
    libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
                                       timebase.den, timebase.num, 0, 30);
    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
  }
}

VP8_INSTANTIATE_TEST_CASE(AltRefForcedKeyTestLarge,
                          ::testing::Values(::libvpx_test::kOnePassGood),
                          ::testing::Range(0, 9));

VP9_INSTANTIATE_TEST_CASE(AltRefForcedKeyTestLarge,
                          ::testing::Values(::libvpx_test::kOnePassGood),
                          ::testing::Range(0, 9));
}  // namespace
<|endoftext|>


<commit_before>#include <catch.hpp>

#include "build.h"

#include "generators.h"
#include "in_memory_file_system.h"

namespace shk {
namespace detail {

TEST_CASE("Build") {
  InMemoryFileSystem fs;
  Paths paths(fs);

  const Step empty{};

  Step single_output;
  single_output.outputs = { paths.get("a") };

  Step single_output_b;
  single_output_b.outputs = { paths.get("b") };

  Step multiple_outputs;
  multiple_outputs.outputs = { paths.get("c"), paths.get("d") };

  Step single_input;
  single_input.inputs = { paths.get("a") };

  Step single_implicit_input;
  single_implicit_input.implicit_inputs = { paths.get("a") };

  Step single_dependency;
  single_dependency.dependencies = { paths.get("a") };

  SECTION("computeOutputFileMap") {
    SECTION("basics") {
      CHECK(computeOutputFileMap({}).empty());
      CHECK(computeOutputFileMap({ empty }).empty());
      CHECK(computeOutputFileMap({ single_input }).empty());
      CHECK(computeOutputFileMap({ single_implicit_input }).empty());
      CHECK(computeOutputFileMap({ single_dependency }).empty());
    }

    SECTION("single output") {
      const auto map = computeOutputFileMap({ single_output });
      CHECK(map.size() == 1);
      const auto it = map.find(paths.get("a"));
      REQUIRE(it != map.end());
      CHECK(it->second == 0);
    }

    SECTION("multiple outputs") {
      auto map = computeOutputFileMap({
          single_output, single_output_b, multiple_outputs });
      CHECK(map.size() == 4);
      CHECK(map[paths.get("a")] == 0);
      CHECK(map[paths.get("b")] == 1);
      CHECK(map[paths.get("c")] == 2);
      CHECK(map[paths.get("d")] == 2);
    }

    SECTION("duplicate outputs") {
      CHECK_THROWS_AS(
          computeOutputFileMap({ single_output, single_output }), BuildError);
    }
  }

  SECTION("rootSteps") {
  }

  SECTION("computeStepsToBuild") {
  }

  SECTION("computeReadySteps") {
  }

  SECTION("cycleErrorMessage") {
  }

  SECTION("computeBuild") {
  }

  SECTION("computeInvocationEntry") {
  }

  SECTION("computeStepHashes") {
  }

  SECTION("isClean") {
  }

  SECTION("computeCleanSteps") {
  }

  SECTION("discardCleanSteps") {
  }

  SECTION("outputsWereChanged") {
  }

  SECTION("deleteOldOutputs") {
  }

  SECTION("deleteStaleOutputs") {
  }

  SECTION("build") {
  }
}

}  // namespace detail
}  // namespace shk
<commit_msg>Unit test detail::rootSteps<commit_after>#include <catch.hpp>

#include "build.h"

#include "generators.h"
#include "in_memory_file_system.h"

namespace shk {
namespace detail {
namespace {

std::vector<StepIndex> rootSteps(
    const std::vector<Step> &steps) {
  return ::shk::detail::rootSteps(steps, computeOutputFileMap(steps));
}

}  // anonymous namespace

TEST_CASE("Build") {
  InMemoryFileSystem fs;
  Paths paths(fs);

  const Step empty{};

  Step single_output;
  single_output.outputs = { paths.get("a") };

  Step single_output_b;
  single_output_b.outputs = { paths.get("b") };

  Step multiple_outputs;
  multiple_outputs.outputs = { paths.get("c"), paths.get("d") };

  Step single_input;
  single_input.inputs = { paths.get("a") };

  Step single_implicit_input;
  single_implicit_input.implicit_inputs = { paths.get("a") };

  Step single_dependency;
  single_dependency.dependencies = { paths.get("a") };

  SECTION("computeOutputFileMap") {
    SECTION("basics") {
      CHECK(computeOutputFileMap({}).empty());
      CHECK(computeOutputFileMap({ empty }).empty());
      CHECK(computeOutputFileMap({ single_input }).empty());
      CHECK(computeOutputFileMap({ single_implicit_input }).empty());
      CHECK(computeOutputFileMap({ single_dependency }).empty());
    }

    SECTION("single output") {
      const auto map = computeOutputFileMap({ single_output });
      CHECK(map.size() == 1);
      const auto it = map.find(paths.get("a"));
      REQUIRE(it != map.end());
      CHECK(it->second == 0);
    }

    SECTION("multiple outputs") {
      auto map = computeOutputFileMap({
          single_output, single_output_b, multiple_outputs });
      CHECK(map.size() == 4);
      CHECK(map[paths.get("a")] == 0);
      CHECK(map[paths.get("b")] == 1);
      CHECK(map[paths.get("c")] == 2);
      CHECK(map[paths.get("d")] == 2);
    }

    SECTION("duplicate outputs") {
      CHECK_THROWS_AS(
          computeOutputFileMap({ single_output, single_output }), BuildError);
    }
  }

  SECTION("rootSteps") {
    CHECK(rootSteps({}).empty());
    CHECK(rootSteps({ single_output }) == std::vector<StepIndex>{ 0 });
    CHECK(
        rootSteps({ single_output, single_output_b }) ==
        (std::vector<StepIndex>{ 0, 1 }));
    CHECK(
        rootSteps({ single_output, single_input }) ==
        std::vector<StepIndex>{ 1 });
    CHECK(
        rootSteps({ single_output, single_implicit_input }) ==
        std::vector<StepIndex>{ 1 });
    CHECK(
        rootSteps({ single_output, single_dependency }) ==
        std::vector<StepIndex>{ 1 });
    CHECK(
        rootSteps({ single_dependency, single_output }) ==
        std::vector<StepIndex>{ 0 });
    CHECK(
        rootSteps({ single_dependency, single_output, multiple_outputs }) ==
        (std::vector<StepIndex>{ 0, 2 }));
  }

  SECTION("computeStepsToBuild") {
  }

  SECTION("computeReadySteps") {
  }

  SECTION("cycleErrorMessage") {
  }

  SECTION("computeBuild") {
  }

  SECTION("computeInvocationEntry") {
  }

  SECTION("computeStepHashes") {
  }

  SECTION("isClean") {
  }

  SECTION("computeCleanSteps") {
  }

  SECTION("discardCleanSteps") {
  }

  SECTION("outputsWereChanged") {
  }

  SECTION("deleteOldOutputs") {
  }

  SECTION("deleteStaleOutputs") {
  }

  SECTION("build") {
  }
}

}  // namespace detail
}  // namespace shk
<|endoftext|>


<commit_before>/**************************************************************************\
**
**  tGridList.cpp
**
**  Functions for derived classes tGridList and tGridListIter. The classes
**  are declared in tGridList.h.
**
**  Modifications:
**   - added "MoveToActiveBack()" function, 12/97 GT
**
**  $Id: tMeshList.cpp,v 1.2 1998-01-21 20:16:12 gtucker Exp $
\**************************************************************************/

#include <assert.h>
#include "tGridList.h"

template< class NodeType >                     //tGridtList
tGridList< NodeType >::
tGridList()
{
   nActiveNodes = 0;
   lastactive = 0;
     //cout << "                  from tGridList()" << first << endl;
}

template< class NodeType >                     //tGridtList
tGridList< NodeType >::
tGridList( const tGridList< NodeType > *original )
        : tList< NodeType >( original )
{
   nActiveNodes = original->nActiveNodes;
   if( original->lastactive != 0 ) lastactive = original->lastactive;
   else lastactive = 0;
     //cout << "                  from tGridList( original )" << first << endl;
}

template< class NodeType >                     //tGridtList
tGridList< NodeType >::
~tGridList()
{
     //cout << "                  from ~tGridList()" << first << endl;
}

//overloaded assignment operator
template< class NodeType >                     //tGridList
const tGridList< NodeType > &tGridList< NodeType >::
operator=( const tGridList< NodeType > &right )
{
   if( this != &right )
   {
      tList< NodeType >::operator=( right );
      lastactive = right.lastactive;
      nActiveNodes = right.nActiveNodes;
   }
     //cout << "tGridList assigned" << first << endl;
   return *this;
}

//overloaded equality operator:
template< class NodeType >                      //tGridList
int tGridList< NodeType >::
operator==( const tGridList< NodeType > &right ) const
{
   if( tList< NodeType >::operator!=( right ) ) return 0;
   if( nActiveNodes != right.nActiveNodes ) return 0;
   if( lastactive != right.lastactive ) return 0;
   return 1;
}

//overloaded inequality operator:
template< class NodeType >                      //tGridList
int tGridList< NodeType >::
operator!=( const tGridList< NodeType > &right ) const
{
   if( tList< NodeType >::operator!=( right ) ) return 1;
   if( nActiveNodes != right.nActiveNodes ) return 1;
   if( lastactive != right.lastactive ) return 1;
   return 0;
}

template< class NodeType >                      //tGridList
int tGridList< NodeType >::
getActiveSize() const {return nActiveNodes;}

template< class NodeType >                      //tGridList
tListNode< NodeType > *
tGridList< NodeType >::
getLastActive() const {return lastactive;}

template< class NodeType >                     //tGridtList
void tGridList< NodeType >::
setNActiveNodes( int val ) {nActiveNodes = ( val >= 0 ) ? val : 0;}

template< class NodeType >                     //tGridtList
int tGridList< NodeType >::
isActiveEmpty() const
{
     //cout << "checking if tGridList empty of active nodes" << endl;
   if( lastactive == 0 )
   {
        //cout << "tGridList is empty of active nodes" << endl;
      return 1;
   }
   else
   {
        //cout << "tGridList is not empty of active nodes" << endl;
      return 0;
   }
}

template< class NodeType >                     //tGridtList
int tGridList< NodeType >::
isBoundEmpty() const
{
   if( lastactive == last ) return 1;
   else return 0;
}

template< class NodeType >                     //tGridtList
void tGridList< NodeType >::
insertAtBoundFront( const NodeType &value )
{
   tListNode< NodeType > * newPtr = getNewNode( value );
     //cout << "add new node at boundary front of tGridList" << endl;
   assert( newPtr>0 );
   assert( this != 0 );

   if( isEmpty() )  // Case list empty
   {
      first = last = newPtr;
   }
   else if( lastactive==0 ) // Case active part of list empty
   {
        //cout << "Case no active nodes" << endl;
      newPtr->next = first;
      first = newPtr;
   }
   else  // Usual case: list and active part of list NOT empty
   {
      newPtr->next = lastactive->next;
      lastactive->next = newPtr;
      if( lastactive==last ) last = newPtr; // Case: new is last (only) bdy
   }

     //nNodes++;  // why commented out? why not increment nnodes & nactive?
     //cout << "added node to front of boundary tGridList" << endl;

}

template< class NodeType >                     //tGridtList
int tGridList< NodeType >::
removeFromBoundFront( NodeType &value )
{
   assert( &value != 0 );
   if( isEmpty() ) return 0;
   else if( last == lastactive ) return 0;
   else
   {
      tListNode< NodeType > * temp = lastactive->next;
      if( first == last ) first = last = 0;
      else lastactive->next = lastactive->next->next;
      value = temp->data;
      delete temp;
      nNodes--;
      return 1;
   }
}

template< class NodeType >                     //tGridtList
void tGridList< NodeType >::
insertAtActiveBack( const NodeType &value )
{
   tListNode< NodeType > * newPtr = getNewNode( value );
     //cout << "add new node at active back of tGridList" << endl;
   assert( this != 0 );
   //cout << " isActiveEmpty() = " << isActiveEmpty() << endl;
   if( isEmpty() )
   {
      first = last = lastactive = newPtr;
   }
   else if( !( isEmpty() ) && isActiveEmpty() && !( isBoundEmpty() ) )
   {
      lastactive = newPtr;
      lastactive->next = first;
      first = lastactive;
      //cout << "first = lastactive: " << first->getDataRef().getID()
      //   << " " << lastactive->getDataRef().getID() << endl;
      //newPtr->next = first;
      //first = lastactive = newPtr;
   }
   else if( !( isEmpty() ) && isBoundEmpty() )
   {
      newPtr->next = lastactive->next;
      lastactive->next = newPtr;
      lastactive = newPtr;
      last = lastactive;
   }
   else
   {
      newPtr->next = lastactive->next;
      lastactive->next = newPtr;
      lastactive = newPtr;
   }
   if( isBoundEmpty() ) last = lastactive;
     //nNodes++;
   nActiveNodes++;
     //cout << "added node to back of active tGridList" << endl;
}

template< class NodeType >                     //tGridtList
int tGridList< NodeType >::
removeFromActiveBack( NodeType &value )
{
   if( isEmpty() ) return 0;
   else
   {
      tListNode< NodeType > * temp = lastactive;
      if( first == lastactive ) lastactive = 0;
      if( first == last ) first = last = 0;
      else
      {
         tListNode< NodeType > * current = first;
         while( current->next != lastactive ) current = current->next;
         current->next = lastactive->next;
         lastactive->next = 0;
         lastactive = current;
      }
      value = temp->data;
      delete temp;
      nNodes--;
      nActiveNodes--;
      return 1;
   }
}

//delete next node
template< class NodeType >                         //tList
int tGridList< NodeType >::
removeNext( NodeType &value, tListNode< NodeType > * ptr )
{
   if( ptr->next == 0 ) return 0;
   if( ptr == 0 ) return 0;
   if( ptr->next == lastactive ) return removeFromActiveBack( value );
   if( ptr == lastactive ) return removeFromBoundFront( value );
   if( tList< NodeType >::removeNext( value, ptr ) )
   {
      if( !( value.getBoundaryFlag() ) ) nActiveNodes--;
      return 1;
   }
   return 0;
}

//delete previous node
template< class NodeType >                         //tList
int tGridList< NodeType >::
removePrev( NodeType &value, tListNode< NodeType > * ptr )
{
   if( ptr == 0 ) return 0;
   if( ptr == first && last->next == 0 ) return 0;
   if( lastactive->next == ptr ) return removeFromActiveBack( value );
   if( tList< NodeType >::removePrev( value, ptr ) )
   {
      if( !( value.getBoundaryFlag() ) ) nActiveNodes--;
      return 1;
   }
   return 0;
}

//'move' utilities
template< class NodeType >                         //tList
void tGridList< NodeType >::
moveToBack( tListNode< NodeType > * mvnode )
{
   if( mvnode != last )
   {
      if( mvnode == lastactive )
      {
         for( tListNode< NodeType > * prev = first;
              prev->next != mvnode;
              prev = prev->next );
         lastactive = prev;
      }
      tList< NodeType >::moveToBack( mvnode );
   }
}

template< class NodeType >                         //tList
void tGridList< NodeType >::
moveToFront( tListNode< NodeType > * mvnode )
{
   if( mvnode != first )
   {
      if( mvnode == lastactive )
      {
         for( tListNode< NodeType > * prev = first;
              prev->next != mvnode;
              prev = prev->next );
         lastactive = prev;
      }
      tList< NodeType >::moveToFront( mvnode );
   }
}

template< class NodeType >                         //tList
void tGridList< NodeType >::
moveToActiveBack( tListNode< NodeType > * mvnode )
{
   if( mvnode != lastactive )
   {
      // Detach mvnode from its position on the list
      if( mvnode == first ) first = first->next;
      else
      {
         tListNode< NodeType > * prev = first;
         while( prev->next != mvnode ) prev = prev->next;
         prev->next = mvnode->next;
      }

      // Insert it at the end of the active part of the list
      mvnode->next = lastactive->next;
      lastactive->next = mvnode;
      if( lastactive == last )
      {
         last = mvnode;
         // If it's a circular list, make sure to preserve circularity
         if( last->next != 0 ) last->next = first;
      }
      lastactive = mvnode;
   }
}

template< class NodeType >                         //tList
void tGridList< NodeType >::
insertAtFront( const NodeType &value )
{
   tList< NodeType >::insertAtFront( value );
   if( isActiveEmpty() ) lastactive = first;
   nActiveNodes++;
}

template< class NodeType >                         //tList
int tGridList< NodeType >::
removeFromFront( NodeType &value )
{
   if( !( isActiveEmpty() ) )
   {
      nActiveNodes--;
      if( lastactive == first ) lastactive = 0;
   }
   return tList< NodeType >::removeFromFront( value );
}

template< class NodeType >                         //tList
void tGridList< NodeType >::
Flush()
{
   tList< NodeType >::Flush();
   lastactive = 0;
   nActiveNodes = 0;
}

/**************************************************************************\
**
**         Utilities for derived class tGridListIter
**
\**************************************************************************/

template< class NodeType >   //tGridListIter
tGridListIter< NodeType >::
tGridListIter()
{
     //cout << "    from tGridListIter()" << endl;
}

template< class NodeType >   //tGridListIter
tGridListIter< NodeType >::
tGridListIter( tGridList< NodeType > &list )
        : tListIter< NodeType >( list )
{
   assert( &list != 0 );
     //gridlistPtr = &list;
   curnode = /*grid*/listPtr->first;
     //if( listPtr->first != 0 ) assert( curnode != 0 );
     //cout << "    from tGridListIter( list )" << endl;
}

template< class NodeType >   //tGridListIter
tGridListIter< NodeType >::
tGridListIter( tGridList< NodeType > *ptr )
        : tListIter< NodeType >( ptr )
{
   assert( ptr != 0 );
     //gridlistPtr = &list;
   curnode = /*grid*/listPtr->first;
   assert( curnode != 0 );
     //cout << "    from tGridListIter( ptr )" << endl;
}

template< class NodeType >   //tGridListIter
tGridListIter< NodeType >::
~tGridListIter()
{
     //cout << "    from ~tGridListIter()" << endl;
}

template< class NodeType >   //tGridListIter
int tGridListIter< NodeType >::
LastActive()
{
     tGridList< NodeType > *gridlistPtr;
   gridlistPtr = ( tGridList< NodeType > * ) listPtr;
   assert( gridlistPtr != 0 );
   curnode = gridlistPtr->lastactive;
   if( curnode != 0 ) return 1;
   else return 0;
}

template< class NodeType >   //tGridListIter
int tGridListIter< NodeType >::
FirstBoundary()
{
   tGridList< NodeType > *gridlistPtr;
   gridlistPtr = ( tGridList< NodeType > * ) listPtr;
   assert( gridlistPtr != 0 );
   curnode = gridlistPtr->lastactive->next;
   if( curnode != 0 ) return 1;
   else return 0;
}

template< class NodeType >   //tGridListIter
int tGridListIter< NodeType >::
IsActive()
{
   int act;
   act = curnode->getDataRef().getBoundaryFlag();
   if( act == kNonBoundary ) return 1;
   else return 0;
}

template< class NodeType >   //tGridListIter
NodeType *tGridListIter< NodeType >::
LastActiveP()
{
   tGridList< NodeType > *gridlistPtr;
   gridlistPtr = ( tGridList< NodeType > * ) listPtr;
   assert( gridlistPtr != 0 );
   curnode = gridlistPtr->lastactive;
   if( curnode != 0 ) return curnode->getDataPtrNC();
   else return 0;
}

/* (transferred to base class tListIter)
template< class NodeType >        //tGridListIter
NodeType * tGridListIter< NodeType >::
FirstP()
{
   assert( listPtr != 0 );
   curnode = listPtr->getFirst();
   if( curnode != 0 ) return curnode->getDataPtrNC();
   else return 0;
}

template< class NodeType >        //tGridListIter
NodeType * tGridListIter< NodeType >::
NextP()
{
   assert( listPtr != 0 );
   if( curnode == 0 )
   {
      curnode = listPtr->getFirst();
      if( curnode != 0 ) return curnode->getDataPtrNC();
      else return 0;
   }
   curnode = curnode->getNextNC();
   if( curnode != 0 ) return curnode->getDataPtrNC();
   else return 0;
}
*/
<commit_msg>*** empty log message ***<commit_after>/**************************************************************************\
**
**  tGridList.cpp
**
**  Functions for derived classes tGridList and tGridListIter. The classes
**  are declared in tGridList.h.
**
**  Modifications:
**   - added "MoveToActiveBack()" function, 12/97 GT
**
**  $Id: tMeshList.cpp,v 1.3 1998-01-31 19:19:43 stlancas Exp $
\**************************************************************************/

#include <assert.h>
#include "tGridList.h"

template< class NodeType >                     //tGridtList
tGridList< NodeType >::
tGridList()
{
   nActiveNodes = 0;
   lastactive = 0;
     //cout << "                  from tGridList()" << first << endl;
}

template< class NodeType >                     //tGridtList
tGridList< NodeType >::
tGridList( const tGridList< NodeType > *original )
        : tList< NodeType >( original )
{
   nActiveNodes = original->nActiveNodes;
   if( original->lastactive != 0 ) lastactive = original->lastactive;
   else lastactive = 0;
     //cout << "                  from tGridList( original )" << first << endl;
}

template< class NodeType >                     //tGridtList
tGridList< NodeType >::
~tGridList()
{
     //cout << "                  from ~tGridList()" << first << endl;
}

//overloaded assignment operator
template< class NodeType >                     //tGridList
const tGridList< NodeType > &tGridList< NodeType >::
operator=( const tGridList< NodeType > &right )
{
   if( this != &right )
   {
      tList< NodeType >::operator=( right );
      lastactive = right.lastactive;
      nActiveNodes = right.nActiveNodes;
   }
     //cout << "tGridList assigned" << first << endl;
   return *this;
}

//overloaded equality operator:
template< class NodeType >                      //tGridList
int tGridList< NodeType >::
operator==( const tGridList< NodeType > &right ) const
{
   if( tList< NodeType >::operator!=( right ) ) return 0;
   if( nActiveNodes != right.nActiveNodes ) return 0;
   if( lastactive != right.lastactive ) return 0;
   return 1;
}

//overloaded inequality operator:
template< class NodeType >                      //tGridList
int tGridList< NodeType >::
operator!=( const tGridList< NodeType > &right ) const
{
   if( tList< NodeType >::operator!=( right ) ) return 1;
   if( nActiveNodes != right.nActiveNodes ) return 1;
   if( lastactive != right.lastactive ) return 1;
   return 0;
}

template< class NodeType >                      //tGridList
int tGridList< NodeType >::
getActiveSize() const {return nActiveNodes;}

template< class NodeType >                      //tGridList
tListNode< NodeType > *
tGridList< NodeType >::
getLastActive() const {return lastactive;}

template< class NodeType >                     //tGridtList
void tGridList< NodeType >::
setNActiveNodes( int val ) {nActiveNodes = ( val >= 0 ) ? val : 0;}

template< class NodeType >                     //tGridtList
int tGridList< NodeType >::
isActiveEmpty() const
{
     //cout << "checking if tGridList empty of active nodes" << endl;
   if( lastactive == 0 )
   {
        //cout << "tGridList is empty of active nodes" << endl;
      return 1;
   }
   else
   {
        //cout << "tGridList is not empty of active nodes" << endl;
      return 0;
   }
}

template< class NodeType >                     //tGridtList
int tGridList< NodeType >::
isBoundEmpty() const
{
   if( lastactive == last ) return 1;
   else return 0;
}

template< class NodeType >                     //tGridtList
void tGridList< NodeType >::
insertAtBoundFront( const NodeType &value )
{
   tListNode< NodeType > * newPtr = getNewNode( value );
     //cout << "add new node at boundary front of tGridList" << endl;
   assert( newPtr>0 );
   assert( this != 0 );

   if( isEmpty() )  // Case list empty
   {
      first = last = newPtr;
   }
   else if( lastactive==0 ) // Case active part of list empty
   {
        //cout << "Case no active nodes" << endl;
      newPtr->next = first;
      first = newPtr;
   }
   else  // Usual case: list and active part of list NOT empty
   {
      newPtr->next = lastactive->next;
      lastactive->next = newPtr;
      if( lastactive==last ) last = newPtr; // Case: new is last (only) bdy
   }

     //nNodes++;  // why commented out? why not increment nnodes & nactive?
     //cout << "added node to front of boundary tGridList" << endl;

}

template< class NodeType >                     //tGridtList
int tGridList< NodeType >::
removeFromBoundFront( NodeType &value )
{
   assert( &value != 0 );
   if( isEmpty() ) return 0;
   else if( last == lastactive ) return 0;
   else
   {
      tListNode< NodeType > * temp = lastactive->next;
      if( first == last ) first = last = 0;
      else lastactive->next = lastactive->next->next;
      value = temp->data;
      delete temp;
      nNodes--;
      return 1;
   }
}

template< class NodeType >                     //tGridtList
void tGridList< NodeType >::
insertAtActiveBack( const NodeType &value )
{
   tListNode< NodeType > * newPtr = getNewNode( value );
     //cout << "add new node at active back of tGridList" << endl;
   assert( this != 0 );
   //cout << " isActiveEmpty() = " << isActiveEmpty() << endl;
   if( isEmpty() )
   {
      first = last = lastactive = newPtr;
   }
   else if( !( isEmpty() ) && isActiveEmpty() && !( isBoundEmpty() ) )
   {
      lastactive = newPtr;
      lastactive->next = first;
      first = lastactive;
      //cout << "first = lastactive: " << first->getDataRef().getID()
      //   << " " << lastactive->getDataRef().getID() << endl;
      //newPtr->next = first;
      //first = lastactive = newPtr;
   }
   else if( !( isEmpty() ) && isBoundEmpty() )
   {
      newPtr->next = lastactive->next;
      lastactive->next = newPtr;
      lastactive = newPtr;
      last = lastactive;
   }
   else
   {
      newPtr->next = lastactive->next;
      lastactive->next = newPtr;
      lastactive = newPtr;
   }
   if( isBoundEmpty() ) last = lastactive;
     //nNodes++;
   nActiveNodes++;
     //cout << "added node to back of active tGridList" << endl;
}

template< class NodeType >                     //tGridtList
int tGridList< NodeType >::
removeFromActiveBack( NodeType &value )
{
   if( isEmpty() ) return 0;
   else
   {
      tListNode< NodeType > * temp = lastactive;
      if( first == lastactive ) lastactive = 0;
      if( first == last ) first = last = 0;
      else
      {
         tListNode< NodeType > * current = first;
         while( current->next != lastactive ) current = current->next;
         current->next = lastactive->next;
         lastactive->next = 0;
         lastactive = current;
      }
      value = temp->data;
      delete temp;
      nNodes--;
      nActiveNodes--;
      return 1;
   }
}

//delete next node
template< class NodeType >                         //tList
int tGridList< NodeType >::
removeNext( NodeType &value, tListNode< NodeType > * ptr )
{
   if( ptr->next == 0 ) return 0;
   if( ptr == 0 ) return 0;
   if( ptr->next == lastactive ) return removeFromActiveBack( value );
   if( ptr == lastactive ) return removeFromBoundFront( value );
   if( tList< NodeType >::removeNext( value, ptr ) )
   {
      if( !( value.getBoundaryFlag() ) ) nActiveNodes--;
      return 1;
   }
   return 0;
}

//delete previous node
template< class NodeType >                         //tList
int tGridList< NodeType >::
removePrev( NodeType &value, tListNode< NodeType > * ptr )
{
   if( ptr == 0 ) return 0;
   if( ptr == first && last->next == 0 ) return 0;
   if( lastactive->next == ptr ) return removeFromActiveBack( value );
   if( tList< NodeType >::removePrev( value, ptr ) )
   {
      if( !( value.getBoundaryFlag() ) ) nActiveNodes--;
      return 1;
   }
   return 0;
}

//'move' utilities
template< class NodeType >                         //tList
void tGridList< NodeType >::
moveToBack( tListNode< NodeType > * mvnode )
{
   tListNode< NodeType > * prev;
   if( mvnode != last )
   {
      if( mvnode == lastactive )
      {
         for( prev = first; prev->next != mvnode; prev = prev->next );
         lastactive = prev;
      }
      tList< NodeType >::moveToBack( mvnode );
   }
}

template< class NodeType >                         //tList
void tGridList< NodeType >::
moveToFront( tListNode< NodeType > * mvnode )
{
   tListNode< NodeType > *prev;
   if( mvnode != first )
   {
      if( mvnode == lastactive )
      {
         for( prev = first; prev->next != mvnode; prev = prev->next );
         lastactive = prev;
      }
      tList< NodeType >::moveToFront( mvnode );
   }
}

template< class NodeType >                         //tList
void tGridList< NodeType >::
moveToActiveBack( tListNode< NodeType > * mvnode )
{
   tListNode< NodeType > * prev;
   if( mvnode != lastactive )
   {
      // Detach mvnode from its position on the list
      if( mvnode == first ) first = first->next;
      else
      {
         prev = first;
         while( prev->next != mvnode ) prev = prev->next;
         prev->next = mvnode->next;
      }

      // Insert it at the end of the active part of the list
      mvnode->next = lastactive->next;
      lastactive->next = mvnode;
      if( lastactive == last )
      {
         last = mvnode;
         // If it's a circular list, make sure to preserve circularity
         if( last->next != 0 ) last->next = first;
      }
      lastactive = mvnode;
   }
}

template< class NodeType >                         //tList
void tGridList< NodeType >::
insertAtFront( const NodeType &value )
{
   tList< NodeType >::insertAtFront( value );
   if( isActiveEmpty() ) lastactive = first;
   nActiveNodes++;
}

template< class NodeType >                         //tList
int tGridList< NodeType >::
removeFromFront( NodeType &value )
{
   if( !( isActiveEmpty() ) )
   {
      nActiveNodes--;
      if( lastactive == first ) lastactive = 0;
   }
   return tList< NodeType >::removeFromFront( value );
}

template< class NodeType >                         //tList
void tGridList< NodeType >::
Flush()
{
   tList< NodeType >::Flush();
   lastactive = 0;
   nActiveNodes = 0;
}

/**************************************************************************\
**
**         Utilities for derived class tGridListIter
**
\**************************************************************************/

template< class NodeType >   //tGridListIter
tGridListIter< NodeType >::
tGridListIter()
{
     //cout << "    from tGridListIter()" << endl;
}

template< class NodeType >   //tGridListIter
tGridListIter< NodeType >::
tGridListIter( tGridList< NodeType > &list )
        : tListIter< NodeType >( list )
{
   assert( &list != 0 );
     //gridlistPtr = &list;
   curnode = /*grid*/listPtr->first;
     //if( listPtr->first != 0 ) assert( curnode != 0 );
     //cout << "    from tGridListIter( list )" << endl;
}

template< class NodeType >   //tGridListIter
tGridListIter< NodeType >::
tGridListIter( tGridList< NodeType > *ptr )
        : tListIter< NodeType >( ptr )
{
   assert( ptr != 0 );
     //gridlistPtr = &list;
   curnode = /*grid*/listPtr->first;
   assert( curnode != 0 );
     //cout << "    from tGridListIter( ptr )" << endl;
}

template< class NodeType >   //tGridListIter
tGridListIter< NodeType >::
~tGridListIter()
{
     //cout << "    from ~tGridListIter()" << endl;
}

template< class NodeType >   //tGridListIter
int tGridListIter< NodeType >::
LastActive()
{
     tGridList< NodeType > *gridlistPtr;
   gridlistPtr = ( tGridList< NodeType > * ) listPtr;
   assert( gridlistPtr != 0 );
   curnode = gridlistPtr->lastactive;
   if( curnode != 0 ) return 1;
   else return 0;
}

template< class NodeType >   //tGridListIter
int tGridListIter< NodeType >::
FirstBoundary()
{
   tGridList< NodeType > *gridlistPtr;
   gridlistPtr = ( tGridList< NodeType > * ) listPtr;
   assert( gridlistPtr != 0 );
   curnode = gridlistPtr->lastactive->next;
   if( curnode != 0 ) return 1;
   else return 0;
}

template< class NodeType >   //tGridListIter
int tGridListIter< NodeType >::
IsActive()
{
   int act;
   act = curnode->getDataRef().getBoundaryFlag();
   if( act == kNonBoundary ) return 1;
   else return 0;
}

template< class NodeType >   //tGridListIter
NodeType *tGridListIter< NodeType >::
LastActiveP()
{
   tGridList< NodeType > *gridlistPtr;
   gridlistPtr = ( tGridList< NodeType > * ) listPtr;
   assert( gridlistPtr != 0 );
   curnode = gridlistPtr->lastactive;
   if( curnode != 0 ) return curnode->getDataPtrNC();
   else return 0;
}

/* (transferred to base class tListIter)
template< class NodeType >        //tGridListIter
NodeType * tGridListIter< NodeType >::
FirstP()
{
   assert( listPtr != 0 );
   curnode = listPtr->getFirst();
   if( curnode != 0 ) return curnode->getDataPtrNC();
   else return 0;
}

template< class NodeType >        //tGridListIter
NodeType * tGridListIter< NodeType >::
NextP()
{
   assert( listPtr != 0 );
   if( curnode == 0 )
   {
      curnode = listPtr->getFirst();
      if( curnode != 0 ) return curnode->getDataPtrNC();
      else return 0;
   }
   curnode = curnode->getNextNC();
   if( curnode != 0 ) return curnode->getDataPtrNC();
   else return 0;
}
*/
<|endoftext|>


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

class SessionTest : public ::testing::Test {
protected:
	Susi::Session session;
};

TEST_F(SessionTest, Init) {
	EXPECT_FALSE(session.isDead());
}

TEST_F(SessionTest, Attribs) {
	// read value that does not exist
	EXPECT_TRUE(session.getAttribute("super").isNull());
	// set value to string
	session.setAttribute("real", "testResult");
	// read just set value
	auto result = session.getAttribute("real");
	EXPECT_FALSE(result.isNull());

	std::string resultStr = result;
	EXPECT_EQ("testResult", resultStr);

	// reset value
	session.setAttribute("real", "new result");
	// read just reset value
	auto result1 = session.getAttribute("real");
	EXPECT_FALSE(result1.isNull());

	std::string resultStr1 = result1;
	EXPECT_EQ("new result", resultStr1);

	// set value to bool
	session.setAttribute("boolean", true);
	// read just set value
	auto result2 = session.getAttribute("boolean");
	EXPECT_FALSE(result2.isNull());

	bool result2_bool = result2;
	EXPECT_EQ(true, result2_bool);

	// set value to array
	Susi::Util::Any array{Susi::Util::Any::Array{1,2,3,4}};
	session.setAttribute("array", array);
	// read just set value
	auto result3 = session.getAttribute("array");
	EXPECT_FALSE(result3.isNull());
	EXPECT_EQ(array,result3);

	// push an element to an array attribute
	session.pushAttribute("array", 5);
	auto result4 = session.getAttribute("array");
	EXPECT_FALSE(result4.isNull());

	Susi::Util::Any array4{Susi::Util::Any::Array{Susi::Util::Any::Array{1,2,3,4},Susi::Util::Any{5}}};
	EXPECT_EQ(array4.toJSONString(),result4.toJSONString());

	int result4_int = result4[1];
	EXPECT_EQ(5,result4_int);

	// push an element to an attribute
	std::vector<Susi::Util::Any> array2 = {"new result", 5};
	session.pushAttribute("real", 5);
	auto result5 = session.getAttribute("real");
	EXPECT_FALSE(result5.isNull());
	EXPECT_EQ(array2[0].toJSONString(),result5[0].toJSONString());
	EXPECT_EQ(array2[1].toJSONString(),result5[1].toJSONString());

	// set value with empty string as key
	session.setAttribute("", "empty Test");
	// try to get value of empty string as key
	auto result6 = session.getAttribute("");
	EXPECT_TRUE(result6.isNull());
}

TEST_F(SessionTest, Die) {
	auto session = Susi::Session();
	session.die();
	EXPECT_TRUE(session.isDead());
}
<commit_msg>[Session] added multi attr tests;<commit_after>#include <gtest/gtest.h>
#include "sessions/Session.h"

class SessionTest : public ::testing::Test {
protected:
	Susi::Session session;
};

TEST_F(SessionTest, Init) {
	EXPECT_FALSE(session.isDead());
}

TEST_F(SessionTest, Attribs) {
	// read value that does not exist
	EXPECT_TRUE(session.getAttribute("super").isNull());
	// set value to string
	session.setAttribute("real", "testResult");
	// read just set value
	auto result = session.getAttribute("real");
	EXPECT_FALSE(result.isNull());

	std::string resultStr = result;
	EXPECT_EQ("testResult", resultStr);

	// reset value
	session.setAttribute("real", "new result");
	// read just reset value
	auto result1 = session.getAttribute("real");
	EXPECT_FALSE(result1.isNull());

	std::string resultStr1 = result1;
	EXPECT_EQ("new result", resultStr1);

	// set value to bool
	session.setAttribute("boolean", true);
	// read just set value
	auto result2 = session.getAttribute("boolean");
	EXPECT_FALSE(result2.isNull());

	bool result2_bool = result2;
	EXPECT_EQ(true, result2_bool);

	// set value to array
	Susi::Util::Any array{Susi::Util::Any::Array{1,2,3,4}};
	session.setAttribute("array", array);
	// read just set value
	auto result3 = session.getAttribute("array");
	EXPECT_FALSE(result3.isNull());
	EXPECT_EQ(array,result3);

	// push an element to an array attribute
	session.pushAttribute("array", 5);
	auto result4 = session.getAttribute("array");
	EXPECT_FALSE(result4.isNull());

	Susi::Util::Any array4{Susi::Util::Any::Array{Susi::Util::Any::Array{1,2,3,4},Susi::Util::Any{5}}};
	EXPECT_EQ(array4.toJSONString(),result4.toJSONString());

	int result4_int = result4[1];
	EXPECT_EQ(5,result4_int);

	// push an element to an attribute
	std::vector<Susi::Util::Any> array2 = {"new result", 5};
	session.pushAttribute("real", 5);
	auto result5 = session.getAttribute("real");
	EXPECT_FALSE(result5.isNull());
	EXPECT_EQ(array2[0].toJSONString(),result5[0].toJSONString());
	EXPECT_EQ(array2[1].toJSONString(),result5[1].toJSONString());

	// set value with empty string as key
	session.setAttribute("", "empty Test");
	// try to get value of empty string as key
	auto result6 = session.getAttribute("");
	EXPECT_TRUE(result6.isNull());

	// set multi atrribute
	session.pushAttribute("multi", 1);
	session.pushAttribute("multi", 2);
	session.pushAttribute("multi", 3);
	auto result7 = session.getAttribute("multi");
	EXPECT_EQ("[1,2,3]",result7.toJSONString());

	// remove multi attribute
	session.removeAttribute("multi");
	auto result8 = session.getAttribute("multi");
	EXPECT_TRUE(result8.isNull());

	// remove multi atrribute again
	auto result9 = session.removeAttribute("multi");
	EXPECT_FALSE(result9);
}

TEST_F(SessionTest, Die) {
	auto session = Susi::Session();
	session.die();
	EXPECT_TRUE(session.isDead());
}
<|endoftext|>


<commit_before>// This file is part of the dune-pymor project:
//   https://github.com/pymor/dune-pymor
// Copyright holders: Stephan Rave, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#include <dune/stuff/test/main.hxx>

#include <utility>

#include <dune/common/typetraits.hh>

#include <dune/stuff/common/float_cmp.hh>
#include <dune/stuff/la/container/common.hh>
#include <dune/stuff/la/container/eigen.hh>
#include <dune/stuff/common/exceptions.hh>

#include <dune/pymor/parameters/base.hh>
#include <dune/pymor/parameters/functional.hh>
#include <dune/pymor/functionals/interfaces.hh>
#include <dune/pymor/functionals/default.hh>
#include <dune/pymor/functionals/affine.hh>

using namespace Dune;
using namespace Dune::Pymor;

typedef testing::Types<
                        Stuff::LA::CommonDenseVector< double >
#if HAVE_EIGEN
                      , Stuff::LA::EigenDenseVector< double >
#endif
                      > VectorTypes;

static const size_t dim = 4;

template< class VectorType >
struct VectorBasedTest
  : public ::testing::Test
{
  void check() const
  {
    // static tests
    typedef Functionals::VectorBased< VectorType >  FunctionalType;
    typedef typename FunctionalType::Traits         Traits;
    // * of the traits
    typedef typename Traits::derived_type T_derived_type;
    static_assert(std::is_same< FunctionalType, T_derived_type >::value,
                  "FunctionalType::Traits::derived_type is wrong!");
    typedef typename Traits::SourceType   T_SourceType;
    typedef typename Traits::ScalarType   T_ScalarType;
    typedef typename Traits::FrozenType   T_FrozenType;
    // * of the class itself (aka the derived type)
    typedef typename FunctionalType::SourceType     D_SourceType;
    typedef typename FunctionalType::ScalarType     D_ScalarType;
    typedef typename FunctionalType::ContainerType  D_ContainerType;
    typedef typename FunctionalType::FrozenType     D_FrozenType;
    static_assert(std::is_same< D_ContainerType, VectorType >::value,
                  "FunctionalType::ContainerType is wrong!");
    // * of the class as the interface
    typedef FunctionalInterface< Traits >       InterfaceType;
    typedef typename InterfaceType::SourceType  I_SourceType;
    typedef typename InterfaceType::ScalarType  I_ScalarType;
    typedef typename InterfaceType::FrozenType  I_FrozenType;
    // dynamic tests
    // * of the class itself (aka the derived type)
    const FunctionalType d_from_ptr(new VectorType(dim, D_ScalarType(1)));
    FunctionalType d_from_shared_ptr(std::make_shared< VectorType >(dim));
    d_from_shared_ptr = d_from_ptr;
    FunctionalType DUNE_UNUSED(d_copy_constructor)(d_from_ptr); // <- at this point, all functionals share the same vector!
    const bool d_linear = d_from_ptr.linear();
    if (!d_linear) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    const DUNE_STUFF_SSIZE_T d_dim_source = d_from_ptr.dim_source();
    if (d_dim_source != dim) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, d_dim_source);
    const VectorType source(dim, D_ScalarType(1));
    const D_ScalarType d_apply = d_from_ptr.apply(source);
    if (Stuff::Common::FloatCmp::ne(d_apply, D_ScalarType(dim)))
      DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, d_apply);
    // * of the class as the interface
    const InterfaceType& i_from_ptr = static_cast< const InterfaceType& >(d_from_ptr);
    const bool i_linear = i_from_ptr.linear();
    if (!i_linear) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    const DUNE_STUFF_SSIZE_T i_dim_source = i_from_ptr.dim_source();
    if (i_dim_source != dim) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, i_dim_source);
    const I_ScalarType i_apply = i_from_ptr.apply(source);
    if (Stuff::Common::FloatCmp::ne(i_apply, I_ScalarType(dim)))
      DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, i_apply);
  }
}; // struct VectorBasedTest

TYPED_TEST_CASE(VectorBasedTest, VectorTypes);
TYPED_TEST(VectorBasedTest, FUNCTIONALS) {
  this->check();
}

template< class VectorType >
struct LinearAffinelyDecomposedVectorBasedTest
  : public ::testing::Test
{
  void check() const
  {
    // static tests
    typedef Functionals::LinearAffinelyDecomposedVectorBased< VectorType >  FunctionalType;
    typedef typename FunctionalType::Traits Traits;
    // * of the traits
    typedef typename Traits::derived_type T_derived_type;
    static_assert(std::is_same< FunctionalType, T_derived_type >::value,
                  "FunctionalType::Traits::derived_type is wrong!");
    typedef typename Traits::ComponentType ComponentType;
    // * of the class itself (aka the derived type)
    typedef typename FunctionalType::ComponentType  D_ComponentType;
    typedef typename FunctionalType::FrozenType     D_FrozenType;
    typedef typename FunctionalType::ScalarType     D_ScalarType;
    typedef typename FunctionalType::AffinelyDecomposedVectorType D_AffinelyDecomposedVectorType;
    // * of the class as the interface
    typedef AffinelyDecomposedFunctionalInterface< Traits > InterfaceType;
    typedef typename InterfaceType::derived_type I_derived_type;
    static_assert(std::is_same< FunctionalType, I_derived_type >::value,
                  "InterfaceType::derived_type is wrong!");
    typedef typename InterfaceType::ComponentType I_ComponentType;
    typedef typename InterfaceType::FrozenType    I_FrozenType;
    typedef typename InterfaceType::ScalarType    I_ScalarType;
    // dynamic tests
    // * of the class itself (aka the derived type)
    D_AffinelyDecomposedVectorType affinelyDecomposedVector(new VectorType(dim, 1));
    affinelyDecomposedVector.register_component(new VectorType(dim, 1),
                                                new ParameterFunctional("diffusion", 1, "diffusion"));
    affinelyDecomposedVector.register_component(new VectorType(dim, 1),
                                                new ParameterFunctional("force", 2, "force[0]"));
    const Parameter mu = {{"diffusion", "force"},
                          {{1.0}, {1.0, 1.0}}};
    if (affinelyDecomposedVector.parameter_type() != mu.type())
      DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected,
                       "\nmu.type()                                 = " << mu.type()
                       << "\naffinelyDecomposedVector.parameter_type() = "
                       << affinelyDecomposedVector.parameter_type());
    FunctionalType d_functional(affinelyDecomposedVector);
    if (!d_functional.parametric()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    if (d_functional.parameter_type() != mu.type())
      DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected,
                       "\nmu.type()         = " << mu.type()
                       << "\n.parameter_type() = " << d_functional.parameter_type());
    const DUNE_STUFF_SSIZE_T d_num_components = d_functional.num_components();
    if (d_num_components != 2) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, d_num_components);
    for (DUNE_STUFF_SSIZE_T qq = 0; qq < d_num_components; ++qq) {
      D_ComponentType component = d_functional.component(qq);
      if (component.parametric()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
      ParameterFunctional DUNE_UNUSED(coefficient) = d_functional.coefficient(qq);
    }
    if (!d_functional.has_affine_part()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    D_ComponentType d_affine_part = d_functional.affine_part();
    if (d_affine_part.parametric()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    D_FrozenType d_frozen = d_functional.freeze_parameter(mu);
    if (d_frozen.parametric()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    VectorType source(dim, D_ScalarType(1));
    D_ScalarType d_apply = d_functional.apply(source, mu);
    D_ScalarType d_frozen_apply = d_frozen.apply(source);
    if (Stuff::Common::FloatCmp::ne(d_apply, d_frozen_apply))
      DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected,
                 "\nd_apply        = " << d_apply << "\nd_frozen_apply = " << d_frozen_apply);
    // * of the class as the interface
    InterfaceType& i_functional = static_cast< InterfaceType& >(d_functional);
    if (!i_functional.parametric()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    if (i_functional.parameter_type() != mu.type())
      DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected,
                       "\nmu.type()         = " << mu.type()
                       << "\n.parameter_type() = " << i_functional.parameter_type());
    const DUNE_STUFF_SSIZE_T i_num_components = i_functional.num_components();
    if (i_num_components != 2) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, i_num_components);
    for (int qq = 0; qq < i_num_components; ++qq) {
      I_ComponentType component = i_functional.component(qq);
      if (component.parametric()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
      ParameterFunctional DUNE_UNUSED(coefficient) = i_functional.coefficient(qq);
    }
    if (!i_functional.has_affine_part()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    I_ComponentType i_affine_part = d_functional.affine_part();
    if (i_affine_part.parametric()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    I_FrozenType i_frozen = i_functional.freeze_parameter(mu);
    if (i_frozen.parametric()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    I_ScalarType i_apply = i_functional.apply(source, mu);
    I_ScalarType i_frozen_apply = i_frozen.apply(source);
    if (Stuff::Common::FloatCmp::ne(i_apply, i_frozen_apply))
      DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected,
                 "\ni_apply        = " << i_apply << "\ni_frozen_apply = " << i_frozen_apply);
  }
}; // struct LinearAffinelyDecomposedVectorBasedTest

TYPED_TEST_CASE(LinearAffinelyDecomposedVectorBasedTest, VectorTypes);
TYPED_TEST(LinearAffinelyDecomposedVectorBasedTest, FUNCTIONALS) {
  this->check();
}
<commit_msg>[test.functionals] add IstlDenseVector<commit_after>// This file is part of the dune-pymor project:
//   https://github.com/pymor/dune-pymor
// Copyright holders: Stephan Rave, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#include <dune/stuff/test/main.hxx>

#include <utility>

#include <dune/common/typetraits.hh>

#include <dune/stuff/common/float_cmp.hh>
#include <dune/stuff/la/container/common.hh>
#include <dune/stuff/la/container/eigen.hh>
#include <dune/stuff/la/container/istl.hh>
#include <dune/stuff/common/exceptions.hh>

#include <dune/pymor/parameters/base.hh>
#include <dune/pymor/parameters/functional.hh>
#include <dune/pymor/functionals/interfaces.hh>
#include <dune/pymor/functionals/default.hh>
#include <dune/pymor/functionals/affine.hh>

using namespace Dune;
using namespace Dune::Pymor;

typedef testing::Types<
                        Stuff::LA::CommonDenseVector< double >
#if HAVE_EIGEN
                      , Stuff::LA::EigenDenseVector< double >
#endif
#if HAVE_DUNE_ISTL
                      , Stuff::LA::IstlDenseVector< double >
#endif
                      > VectorTypes;

static const size_t dim = 4;

template< class VectorType >
struct VectorBasedTest
  : public ::testing::Test
{
  void check() const
  {
    // static tests
    typedef Functionals::VectorBased< VectorType >  FunctionalType;
    typedef typename FunctionalType::Traits         Traits;
    // * of the traits
    typedef typename Traits::derived_type T_derived_type;
    static_assert(std::is_same< FunctionalType, T_derived_type >::value,
                  "FunctionalType::Traits::derived_type is wrong!");
    typedef typename Traits::SourceType   T_SourceType;
    typedef typename Traits::ScalarType   T_ScalarType;
    typedef typename Traits::FrozenType   T_FrozenType;
    // * of the class itself (aka the derived type)
    typedef typename FunctionalType::SourceType     D_SourceType;
    typedef typename FunctionalType::ScalarType     D_ScalarType;
    typedef typename FunctionalType::ContainerType  D_ContainerType;
    typedef typename FunctionalType::FrozenType     D_FrozenType;
    static_assert(std::is_same< D_ContainerType, VectorType >::value,
                  "FunctionalType::ContainerType is wrong!");
    // * of the class as the interface
    typedef FunctionalInterface< Traits >       InterfaceType;
    typedef typename InterfaceType::SourceType  I_SourceType;
    typedef typename InterfaceType::ScalarType  I_ScalarType;
    typedef typename InterfaceType::FrozenType  I_FrozenType;
    // dynamic tests
    // * of the class itself (aka the derived type)
    const FunctionalType d_from_ptr(new VectorType(dim, D_ScalarType(1)));
    FunctionalType d_from_shared_ptr(std::make_shared< VectorType >(dim));
    d_from_shared_ptr = d_from_ptr;
    FunctionalType DUNE_UNUSED(d_copy_constructor)(d_from_ptr); // <- at this point, all functionals share the same vector!
    const bool d_linear = d_from_ptr.linear();
    if (!d_linear) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    const DUNE_STUFF_SSIZE_T d_dim_source = d_from_ptr.dim_source();
    if (d_dim_source != dim) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, d_dim_source);
    const VectorType source(dim, D_ScalarType(1));
    const D_ScalarType d_apply = d_from_ptr.apply(source);
    if (Stuff::Common::FloatCmp::ne(d_apply, D_ScalarType(dim)))
      DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, d_apply);
    // * of the class as the interface
    const InterfaceType& i_from_ptr = static_cast< const InterfaceType& >(d_from_ptr);
    const bool i_linear = i_from_ptr.linear();
    if (!i_linear) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    const DUNE_STUFF_SSIZE_T i_dim_source = i_from_ptr.dim_source();
    if (i_dim_source != dim) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, i_dim_source);
    const I_ScalarType i_apply = i_from_ptr.apply(source);
    if (Stuff::Common::FloatCmp::ne(i_apply, I_ScalarType(dim)))
      DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, i_apply);
  }
}; // struct VectorBasedTest

TYPED_TEST_CASE(VectorBasedTest, VectorTypes);
TYPED_TEST(VectorBasedTest, FUNCTIONALS) {
  this->check();
}

template< class VectorType >
struct LinearAffinelyDecomposedVectorBasedTest
  : public ::testing::Test
{
  void check() const
  {
    // static tests
    typedef Functionals::LinearAffinelyDecomposedVectorBased< VectorType >  FunctionalType;
    typedef typename FunctionalType::Traits Traits;
    // * of the traits
    typedef typename Traits::derived_type T_derived_type;
    static_assert(std::is_same< FunctionalType, T_derived_type >::value,
                  "FunctionalType::Traits::derived_type is wrong!");
    typedef typename Traits::ComponentType ComponentType;
    // * of the class itself (aka the derived type)
    typedef typename FunctionalType::ComponentType  D_ComponentType;
    typedef typename FunctionalType::FrozenType     D_FrozenType;
    typedef typename FunctionalType::ScalarType     D_ScalarType;
    typedef typename FunctionalType::AffinelyDecomposedVectorType D_AffinelyDecomposedVectorType;
    // * of the class as the interface
    typedef AffinelyDecomposedFunctionalInterface< Traits > InterfaceType;
    typedef typename InterfaceType::derived_type I_derived_type;
    static_assert(std::is_same< FunctionalType, I_derived_type >::value,
                  "InterfaceType::derived_type is wrong!");
    typedef typename InterfaceType::ComponentType I_ComponentType;
    typedef typename InterfaceType::FrozenType    I_FrozenType;
    typedef typename InterfaceType::ScalarType    I_ScalarType;
    // dynamic tests
    // * of the class itself (aka the derived type)
    D_AffinelyDecomposedVectorType affinelyDecomposedVector(new VectorType(dim, 1));
    affinelyDecomposedVector.register_component(new VectorType(dim, 1),
                                                new ParameterFunctional("diffusion", 1, "diffusion"));
    affinelyDecomposedVector.register_component(new VectorType(dim, 1),
                                                new ParameterFunctional("force", 2, "force[0]"));
    const Parameter mu = {{"diffusion", "force"},
                          {{1.0}, {1.0, 1.0}}};
    if (affinelyDecomposedVector.parameter_type() != mu.type())
      DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected,
                       "\nmu.type()                                 = " << mu.type()
                       << "\naffinelyDecomposedVector.parameter_type() = "
                       << affinelyDecomposedVector.parameter_type());
    FunctionalType d_functional(affinelyDecomposedVector);
    if (!d_functional.parametric()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    if (d_functional.parameter_type() != mu.type())
      DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected,
                       "\nmu.type()         = " << mu.type()
                       << "\n.parameter_type() = " << d_functional.parameter_type());
    const DUNE_STUFF_SSIZE_T d_num_components = d_functional.num_components();
    if (d_num_components != 2) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, d_num_components);
    for (DUNE_STUFF_SSIZE_T qq = 0; qq < d_num_components; ++qq) {
      D_ComponentType component = d_functional.component(qq);
      if (component.parametric()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
      ParameterFunctional DUNE_UNUSED(coefficient) = d_functional.coefficient(qq);
    }
    if (!d_functional.has_affine_part()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    D_ComponentType d_affine_part = d_functional.affine_part();
    if (d_affine_part.parametric()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    D_FrozenType d_frozen = d_functional.freeze_parameter(mu);
    if (d_frozen.parametric()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    VectorType source(dim, D_ScalarType(1));
    D_ScalarType d_apply = d_functional.apply(source, mu);
    D_ScalarType d_frozen_apply = d_frozen.apply(source);
    if (Stuff::Common::FloatCmp::ne(d_apply, d_frozen_apply))
      DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected,
                 "\nd_apply        = " << d_apply << "\nd_frozen_apply = " << d_frozen_apply);
    // * of the class as the interface
    InterfaceType& i_functional = static_cast< InterfaceType& >(d_functional);
    if (!i_functional.parametric()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    if (i_functional.parameter_type() != mu.type())
      DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected,
                       "\nmu.type()         = " << mu.type()
                       << "\n.parameter_type() = " << i_functional.parameter_type());
    const DUNE_STUFF_SSIZE_T i_num_components = i_functional.num_components();
    if (i_num_components != 2) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, i_num_components);
    for (int qq = 0; qq < i_num_components; ++qq) {
      I_ComponentType component = i_functional.component(qq);
      if (component.parametric()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
      ParameterFunctional DUNE_UNUSED(coefficient) = i_functional.coefficient(qq);
    }
    if (!i_functional.has_affine_part()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    I_ComponentType i_affine_part = d_functional.affine_part();
    if (i_affine_part.parametric()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    I_FrozenType i_frozen = i_functional.freeze_parameter(mu);
    if (i_frozen.parametric()) DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected, "");
    I_ScalarType i_apply = i_functional.apply(source, mu);
    I_ScalarType i_frozen_apply = i_frozen.apply(source);
    if (Stuff::Common::FloatCmp::ne(i_apply, i_frozen_apply))
      DUNE_THROW(Stuff::Exceptions::results_are_not_as_expected,
                 "\ni_apply        = " << i_apply << "\ni_frozen_apply = " << i_frozen_apply);
  }
}; // struct LinearAffinelyDecomposedVectorBasedTest

TYPED_TEST_CASE(LinearAffinelyDecomposedVectorBasedTest, VectorTypes);
TYPED_TEST(LinearAffinelyDecomposedVectorBasedTest, FUNCTIONALS) {
  this->check();
}
<|endoftext|>


<commit_before>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu_rasterizer.h"

#include <string>
#include <utility>

#include "flutter/common/threads.h"
#include "flutter/glue/trace_event.h"
#include "flutter/shell/common/picture_serializer.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/common/shell.h"
#include "third_party/skia/include/core/SkPicture.h"

namespace shell {

GPURasterizer::GPURasterizer(std::unique_ptr<flow::ProcessInfo> info)
    : compositor_context_(std::move(info)), weak_factory_(this) {
  auto weak_ptr = weak_factory_.GetWeakPtr();
  blink::Threads::Gpu()->PostTask(
      [weak_ptr]() { Shell::Shared().AddRasterizer(weak_ptr); });
}

GPURasterizer::~GPURasterizer() {
  weak_factory_.InvalidateWeakPtrs();
  Shell::Shared().PurgeRasterizers();
}

ftl::WeakPtr<Rasterizer> GPURasterizer::GetWeakRasterizerPtr() {
  return weak_factory_.GetWeakPtr();
}

void GPURasterizer::Setup(std::unique_ptr<Surface> surface,
                          ftl::Closure continuation,
                          ftl::AutoResetWaitableEvent* setup_completion_event) {
  surface_ = std::move(surface);

  continuation();

  setup_completion_event->Signal();
}

void GPURasterizer::Clear(SkColor color, const SkISize& size) {
  if (surface_ == nullptr) {
    return;
  }

  auto frame = surface_->AcquireFrame(size);

  if (frame == nullptr) {
    return;
  }

  SkCanvas* canvas = frame->SkiaCanvas();

  if (canvas == nullptr) {
    return;
  }

  canvas->clear(color);

  frame->Submit();
}

void GPURasterizer::Teardown(
    ftl::AutoResetWaitableEvent* teardown_completion_event) {
  if (surface_) {
    surface_.reset();
  }
  last_layer_tree_.reset();
  compositor_context_.OnGrContextDestroyed();
  teardown_completion_event->Signal();
}

flow::LayerTree* GPURasterizer::GetLastLayerTree() {
  return last_layer_tree_.get();
}

void GPURasterizer::Draw(
    ftl::RefPtr<flutter::Pipeline<flow::LayerTree>> pipeline) {
  TRACE_EVENT0("flutter", "GPURasterizer::Draw");

  flutter::Pipeline<flow::LayerTree>::Consumer consumer =
      std::bind(&GPURasterizer::DoDraw, this, std::placeholders::_1);

  // Consume as many pipeline items as possible. But yield the event loop
  // between successive tries.
  switch (pipeline->Consume(consumer)) {
    case flutter::PipelineConsumeResult::MoreAvailable: {
      auto weak_this = weak_factory_.GetWeakPtr();
      blink::Threads::Gpu()->PostTask([weak_this, pipeline]() {
        if (weak_this) {
          weak_this->Draw(pipeline);
        }
      });
      break;
    }
    default:
      break;
  }
}

void GPURasterizer::DoDraw(std::unique_ptr<flow::LayerTree> layer_tree) {
  if (!layer_tree || !surface_) {
    return;
  }

  // There is no way for the compositor to know how long the layer tree
  // construction took. Fortunately, the layer tree does. Grab that time
  // for instrumentation.
  compositor_context_.engine_time().SetLapTime(layer_tree->construction_time());

  DrawToSurface(*layer_tree);

  NotifyNextFrameOnce();

  last_layer_tree_ = std::move(layer_tree);
}

void GPURasterizer::DrawToSurface(flow::LayerTree& layer_tree) {
  auto frame = surface_->AcquireFrame(layer_tree.frame_size());

  if (frame == nullptr) {
    return;
  }

  auto canvas = frame->SkiaCanvas();

  if (canvas == nullptr) {
    return;
  }

  auto compositor_frame =
      compositor_context_.AcquireFrame(surface_->GetContext(), canvas);

  canvas->clear(SK_ColorBLACK);

  layer_tree.Raster(compositor_frame);

  frame->Submit();
}

void GPURasterizer::AddNextFrameCallback(ftl::Closure nextFrameCallback) {
  nextFrameCallback_ = nextFrameCallback;
}

void GPURasterizer::NotifyNextFrameOnce() {
  if (nextFrameCallback_) {
    blink::Threads::Platform()->PostTask([weak_this = weak_factory_.GetWeakPtr()] {
      TRACE_EVENT0("flutter", "GPURasterizer::NotifyNextFrameOnce");
      if (weak_this) {
        ftl::Closure callback = weak_this->nextFrameCallback_;
        callback();
        weak_this->nextFrameCallback_ = nullptr;
      }
    });
  }
}

}  // namespace shell
<commit_msg>Avoid race condition into NotifyNextFrameOnce (#3980)<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu_rasterizer.h"

#include <string>
#include <utility>

#include "flutter/common/threads.h"
#include "flutter/glue/trace_event.h"
#include "flutter/shell/common/picture_serializer.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/common/shell.h"
#include "third_party/skia/include/core/SkPicture.h"

namespace shell {

GPURasterizer::GPURasterizer(std::unique_ptr<flow::ProcessInfo> info)
    : compositor_context_(std::move(info)), weak_factory_(this) {
  auto weak_ptr = weak_factory_.GetWeakPtr();
  blink::Threads::Gpu()->PostTask(
      [weak_ptr]() { Shell::Shared().AddRasterizer(weak_ptr); });
}

GPURasterizer::~GPURasterizer() {
  weak_factory_.InvalidateWeakPtrs();
  Shell::Shared().PurgeRasterizers();
}

ftl::WeakPtr<Rasterizer> GPURasterizer::GetWeakRasterizerPtr() {
  return weak_factory_.GetWeakPtr();
}

void GPURasterizer::Setup(std::unique_ptr<Surface> surface,
                          ftl::Closure continuation,
                          ftl::AutoResetWaitableEvent* setup_completion_event) {
  surface_ = std::move(surface);

  continuation();

  setup_completion_event->Signal();
}

void GPURasterizer::Clear(SkColor color, const SkISize& size) {
  if (surface_ == nullptr) {
    return;
  }

  auto frame = surface_->AcquireFrame(size);

  if (frame == nullptr) {
    return;
  }

  SkCanvas* canvas = frame->SkiaCanvas();

  if (canvas == nullptr) {
    return;
  }

  canvas->clear(color);

  frame->Submit();
}

void GPURasterizer::Teardown(
    ftl::AutoResetWaitableEvent* teardown_completion_event) {
  if (surface_) {
    surface_.reset();
  }
  last_layer_tree_.reset();
  compositor_context_.OnGrContextDestroyed();
  teardown_completion_event->Signal();
}

flow::LayerTree* GPURasterizer::GetLastLayerTree() {
  return last_layer_tree_.get();
}

void GPURasterizer::Draw(
    ftl::RefPtr<flutter::Pipeline<flow::LayerTree>> pipeline) {
  TRACE_EVENT0("flutter", "GPURasterizer::Draw");

  flutter::Pipeline<flow::LayerTree>::Consumer consumer =
      std::bind(&GPURasterizer::DoDraw, this, std::placeholders::_1);

  // Consume as many pipeline items as possible. But yield the event loop
  // between successive tries.
  switch (pipeline->Consume(consumer)) {
    case flutter::PipelineConsumeResult::MoreAvailable: {
      auto weak_this = weak_factory_.GetWeakPtr();
      blink::Threads::Gpu()->PostTask([weak_this, pipeline]() {
        if (weak_this) {
          weak_this->Draw(pipeline);
        }
      });
      break;
    }
    default:
      break;
  }
}

void GPURasterizer::DoDraw(std::unique_ptr<flow::LayerTree> layer_tree) {
  if (!layer_tree || !surface_) {
    return;
  }

  // There is no way for the compositor to know how long the layer tree
  // construction took. Fortunately, the layer tree does. Grab that time
  // for instrumentation.
  compositor_context_.engine_time().SetLapTime(layer_tree->construction_time());

  DrawToSurface(*layer_tree);

  NotifyNextFrameOnce();

  last_layer_tree_ = std::move(layer_tree);
}

void GPURasterizer::DrawToSurface(flow::LayerTree& layer_tree) {
  auto frame = surface_->AcquireFrame(layer_tree.frame_size());

  if (frame == nullptr) {
    return;
  }

  auto canvas = frame->SkiaCanvas();

  if (canvas == nullptr) {
    return;
  }

  auto compositor_frame =
      compositor_context_.AcquireFrame(surface_->GetContext(), canvas);

  canvas->clear(SK_ColorBLACK);

  layer_tree.Raster(compositor_frame);

  frame->Submit();
}

void GPURasterizer::AddNextFrameCallback(ftl::Closure nextFrameCallback) {
  nextFrameCallback_ = nextFrameCallback;
}

void GPURasterizer::NotifyNextFrameOnce() {
  if (nextFrameCallback_) {
    blink::Threads::Platform()->PostTask([callback = nextFrameCallback_] {
      TRACE_EVENT0("flutter", "GPURasterizer::NotifyNextFrameOnce");
      callback();
    });
    nextFrameCallback_ = nullptr;
  }
}

}  // namespace shell
<|endoftext|>


<commit_before>#include "CppUnitLite/TestHarness.h"
#include "CppUnitLite/test.h"
#include "BloomFilter.h"
#include <fstream>
#include <sstream>
#include <string>
#include <cerrno>
#include "util.h"
#include "string.h"
#include <iostream>
#include <set>

using namespace std;

TEST(BloomFilter, isBitSetSetBit)
{
  BloomFilter b(10, 3);

  // First bit in a byte
  CHECK(!b.isBitSet(0))
  b.setBit(0);
  CHECK(b.isBitSet(0))

  // Last bit in a byte
  CHECK(!b.isBitSet(7))
  b.setBit(7);
  CHECK(b.isBitSet(7))
  for (int i = 1; i <= 6; i++) {
    CHECK(!b.isBitSet(i));
  }
  CHECK(b.isBitSet(0));

  // Second bit in non first byte
  CHECK(!b.isBitSet(9))
  b.setBit(9);
  CHECK(b.isBitSet(9))
  CHECK(!b.isBitSet(1));
}

// Generates a simple hash function for the specified prime
TEST(BloomFilter, SimpleHashFn)
{
  HashFn H(2);
  int hash = H("hi", 2);

  CHECK(hash == ((int)'h') * pow(2, 1) + ((int)'i') * pow(2, 0));
}

// Detects when elements are in the set and not in the set
TEST(BloomFilter, Basic)
{
   BloomFilter b;
   b.add("Brian");
   b.add("Ronald");
   b.add("Bondy");
   CHECK(b.exists("Brian"));
   CHECK(!b.exists("Brian2"));
   CHECK(!b.exists("Bria"));

   CHECK(b.exists("Ronald"));
   CHECK(!b.exists("Ronald2"));
   CHECK(!b.exists("onald2"));

   CHECK(b.exists("Bondy"));
   CHECK(!b.exists("BrianRonaldBondy"));
   CHECK(!b.exists("RonaldBondy"));
}

void genRandomBuffer(char *s, const int len) {
  for (int i = 0; i < len; ++i) {
    s[i] = rand() % 256;
  }
  s[len] = 0;
}

class BasicHashFn : public HashFn {
public:
  BasicHashFn(int base) : HashFn(0) {
    this->base = base;
  }

  virtual int operator()(const char *input, int len) {
    int total = base;
    for (int i = 0; i < len; i++) {
      total += input[i];
    }
    return total;
  }
private:
  int base;
};

// Can handle long strings
TEST(BloomFilter, BasicLongStrings)
{
  const int bufSize = 20000;
  char id1[bufSize];
  char id2[bufSize];
  char id3[bufSize];
  genRandomBuffer(id1, bufSize);
  genRandomBuffer(id2, bufSize);
  genRandomBuffer(id3, bufSize);

  BasicHashFn hashFns[2] = {BasicHashFn(0), BasicHashFn(1023)};
  BloomFilter b(10, 5000, hashFns, sizeof(hashFns)/sizeof(hashFns[0]));

   b.add(id1, bufSize);
   b.add(id2, bufSize);
   CHECK(b.exists(id1, bufSize));
   CHECK(b.exists(id2, bufSize));
   CHECK(!b.exists("hello"));
   CHECK(!b.exists(id3, bufSize));
}

// supports substringExists
TEST(BloomFilter, substringExists)
{
  BloomFilter b;
  b.add("abc");
  b.add("hello");
  b.add("world");
  CHECK(b.substringExists("hello", 5));
  // Only substrings of length 5 should exist in the bloom filter
  CHECK(!b.substringExists("ell", 3));
  CHECK(b.substringExists("wow ok hello!!!!", 5));
  CHECK(!b.substringExists("he!lloworl!d", 5));
}

// Can return false positives for a saturated set
TEST(BloomFilter, falsePositives)
{
   BloomFilter b(2, 2);
   b.add("fdada");
   b.add("fdada31");
   b.add("fdada1111");
   b.add("fdada11311");
   b.add("fdada13131");
   CHECK(b.exists("test"));
}

 // It cannot return false negatives
 TEST(BloomFilter, noFalseNegatives)
 {
   BloomFilter b;
   char sz[64];
   for (int i = 0; i < 100000; i++) {
     sprintf(sz, "test-%i", i);
     b.add(sz);
   }
   for (int i = 0; i < 100000; i++) {
     sprintf(sz, "test-%i", i);
     CHECK(b.exists(sz));
   }
 }<commit_msg>Add some live example tests<commit_after>#include "CppUnitLite/TestHarness.h"
#include "CppUnitLite/test.h"
#include "BloomFilter.h"
#include <fstream>
#include <sstream>
#include <string>
#include <cerrno>
#include "util.h"
#include "string.h"
#include <iostream>
#include <set>

using namespace std;

TEST(BloomFilter, isBitSetSetBit)
{
  BloomFilter b(10, 3);

  // First bit in a byte
  CHECK(!b.isBitSet(0))
  b.setBit(0);
  CHECK(b.isBitSet(0))

  // Last bit in a byte
  CHECK(!b.isBitSet(7))
  b.setBit(7);
  CHECK(b.isBitSet(7))
  for (int i = 1; i <= 6; i++) {
    CHECK(!b.isBitSet(i));
  }
  CHECK(b.isBitSet(0));

  // Second bit in non first byte
  CHECK(!b.isBitSet(9))
  b.setBit(9);
  CHECK(b.isBitSet(9))
  CHECK(!b.isBitSet(1));
}

// Generates a simple hash function for the specified prime
TEST(BloomFilter, SimpleHashFn)
{
  HashFn H(2);
  int hash = H("hi", 2);

  CHECK(hash == ((int)'h') * pow(2, 1) + ((int)'i') * pow(2, 0));
}

// Detects when elements are in the set and not in the set
TEST(BloomFilter, Basic)
{
   BloomFilter b;
   b.add("Brian");
   b.add("Ronald");
   b.add("Bondy");
   CHECK(b.exists("Brian"));
   CHECK(!b.exists("Brian2"));
   CHECK(!b.exists("Bria"));

   CHECK(b.exists("Ronald"));
   CHECK(!b.exists("Ronald2"));
   CHECK(!b.exists("onald2"));

   CHECK(b.exists("Bondy"));
   CHECK(!b.exists("BrianRonaldBondy"));
   CHECK(!b.exists("RonaldBondy"));
}

void genRandomBuffer(char *s, const int len) {
  for (int i = 0; i < len; ++i) {
    s[i] = rand() % 256;
  }
  s[len] = 0;
}

class BasicHashFn : public HashFn {
public:
  BasicHashFn(int base) : HashFn(0) {
    this->base = base;
  }

  virtual int operator()(const char *input, int len) {
    int total = base;
    for (int i = 0; i < len; i++) {
      total += input[i];
    }
    return total;
  }
private:
  int base;
};

// Can handle long strings
TEST(BloomFilter, BasicLongStrings)
{
  const int bufSize = 20000;
  char id1[bufSize];
  char id2[bufSize];
  char id3[bufSize];
  genRandomBuffer(id1, bufSize);
  genRandomBuffer(id2, bufSize);
  genRandomBuffer(id3, bufSize);

  BasicHashFn hashFns[2] = {BasicHashFn(0), BasicHashFn(1023)};
  BloomFilter b(10, 5000, hashFns, sizeof(hashFns)/sizeof(hashFns[0]));

   b.add(id1, bufSize);
   b.add(id2, bufSize);
   CHECK(b.exists(id1, bufSize));
   CHECK(b.exists(id2, bufSize));
   CHECK(!b.exists("hello"));
   CHECK(!b.exists(id3, bufSize));
}

// supports substringExists
TEST(BloomFilter, substringExists)
{
  BloomFilter b;
  b.add("abc");
  b.add("hello");
  b.add("world");
  CHECK(b.substringExists("hello", 5));
  // Only substrings of length 5 should exist in the bloom filter
  CHECK(!b.substringExists("ell", 3));
  CHECK(b.substringExists("wow ok hello!!!!", 5));
  CHECK(!b.substringExists("he!lloworl!d", 5));
}

// Can return false positives for a saturated set
TEST(BloomFilter, falsePositives)
{
   BloomFilter b(2, 2);
   b.add("fdada");
   b.add("fdada31");
   b.add("fdada1111");
   b.add("fdada11311");
   b.add("fdada13131");
   CHECK(b.exists("test"));
}

 // It cannot return false negatives
 TEST(BloomFilter, noFalseNegatives)
 {
   BloomFilter b;
   char sz[64];
   for (int i = 0; i < 100000; i++) {
     sprintf(sz, "test-%i", i);
     b.add(sz);
   }
   for (int i = 0; i < 100000; i++) {
     sprintf(sz, "test-%i", i);
     CHECK(b.exists(sz));
   }
 }

 // Works with some live examples
 TEST(BloomFilter, liveExamples)
 {
   BloomFilter b;
   b.add("googlesy");
   const char *url1 = "http://tpc.googlesyndication.com/safeframe/1-0-2/html/container.html#xpc=sf-gdn-exp-2&p=http%3A//slashdot.org";
   const char *url2 = "https://tpc.googlesyndication.com/pagead/gadgets/suggestion_autolayout_V2/suggestion_autolayout_V2.html#t=15174732506449260991&p=http%3A%2F%2Ftpc.googlesyndication.com";
   CHECK(b.substringExists("googlesy", 8));
   CHECK(b.substringExists(url1, 8));
   CHECK(b.substringExists(url2, 8));
 }
<|endoftext|>


<commit_before>#include "parser.hh"
#include "test.hh"
#include <string>

TEST_SUITE(
    nolang::Parser parser;

    TEST_CASE(empty_case,
        parser.parse("test.nolang", "");
        TEST_ASSERT_TRUE(parser.success())
    )

    TEST_CASE(basic_parser,
        std::string data = "";

        data += "main =>\n";
        data += "    40 + 2\n";

        parser.parse("test.nolang", data);

        TEST_ASSERT_TRUE(parser.success())
    )

    TEST_CASE(fail_case,
        parser.parse("test.nolang", "+");
        TEST_ASSERT_FALSE(parser.success())
    )
)
<commit_msg>More test cases<commit_after>#include "parser.hh"
#include "test.hh"
#include <string>

TEST_SUITE(
    nolang::Parser parser;

    TEST_CASE(empty_case,
        parser.parse("test.nolang", "");
        TEST_ASSERT_TRUE(parser.success())
    )

    TEST_CASE(basic_parser,
        std::string data = "";

        data += "main =>\n";
        data += "    40 + 2\n";

        parser.parse("test.nolang", data);

        TEST_ASSERT_TRUE(parser.success())
    )

    TEST_CASE(invalid_top_level,
        parser.parse("test.nolang", "+");
        TEST_ASSERT_FALSE(parser.success())
    )

    TEST_CASE(empty_main_fail,
        parser.parse("test.nolang", "main =>");
        TEST_ASSERT_FALSE(parser.success())
    )

    TEST_CASE(empty_main_ok,
        parser.parse("test.nolang", "main =>\n");
        TEST_ASSERT_TRUE(parser.success())
    )

    TEST_CASE(empty_main_with_import,
        parser.parse("test.nolang", "import sys\nmain =>\n");
        TEST_ASSERT_TRUE(parser.success())
    )
)
<|endoftext|>


<commit_before>/*

Copyright (c) 2008, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/session.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/alert_types.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/time.hpp"
#include <boost/tuple/tuple.hpp>

#include "test.hpp"
#include "setup_transfer.hpp"

void test_swarm(bool super_seeding = false, bool strict = false, bool seed_mode = false, bool time_critical = false)
{
	using namespace libtorrent;

	// in case the previous run was terminated
	error_code ec;
	remove_all("./tmp1_swarm", ec);
	remove_all("./tmp2_swarm", ec);
	remove_all("./tmp3_swarm", ec);

	session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48000, 49000), "0.0.0.0", 0);
	session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49000, 50000), "0.0.0.0", 0);
	session ses3(fingerprint("LT", 0, 1, 0, 0), std::make_pair(50000, 51000), "0.0.0.0", 0);

	// this is to avoid everything finish from a single peer
	// immediately. To make the swarm actually connect all
	// three peers before finishing.
	float rate_limit = 100000;
	ses1.set_upload_rate_limit(int(rate_limit));
	ses2.set_download_rate_limit(int(rate_limit));
	ses3.set_download_rate_limit(int(rate_limit));
	ses2.set_upload_rate_limit(int(rate_limit / 2));
	ses3.set_upload_rate_limit(int(rate_limit / 2));

	session_settings settings;
	settings.allow_multiple_connections_per_ip = true;
	settings.ignore_limits_on_local_network = false;
	settings.strict_super_seeding = strict;
	ses1.set_settings(settings);
	ses2.set_settings(settings);
	ses3.set_settings(settings);

#ifndef TORRENT_DISABLE_ENCRYPTION
	pe_settings pes;
	pes.out_enc_policy = pe_settings::forced;
	pes.in_enc_policy = pe_settings::forced;
	ses1.set_pe_settings(pes);
	ses2.set_pe_settings(pes);
	ses3.set_pe_settings(pes);
#endif

	torrent_handle tor1;
	torrent_handle tor2;
	torrent_handle tor3;

	add_torrent_params p;
	p.seed_mode = seed_mode;
	// test using piece sizes smaller than 16kB
	boost::tie(tor1, tor2, tor3) = setup_transfer(&ses1, &ses2, &ses3, true
		, false, true, "_swarm", 32 * 1024, 0, super_seeding, &p);

	int mask = alert::all_categories & ~(alert::progress_notification | alert::performance_warning);
	ses1.set_alert_mask(mask);
	ses2.set_alert_mask(mask);
	ses3.set_alert_mask(mask);

	if (time_critical)
	{
		tor2.set_piece_deadline(2, seconds(0));
		tor2.set_piece_deadline(5, seconds(1));
		tor2.set_piece_deadline(8, seconds(2));
	}

	float sum_dl_rate2 = 0.f;
	float sum_dl_rate3 = 0.f;
	int count_dl_rates2 = 0;
	int count_dl_rates3 = 0;

	for (int i = 0; i < 80; ++i)
	{
		print_alerts(ses1, "ses1");
		print_alerts(ses2, "ses2");
		print_alerts(ses3, "ses3");

		torrent_status st1 = tor1.status();
		torrent_status st2 = tor2.status();
		torrent_status st3 = tor3.status();

		if (st2.progress < 1.f && st2.progress > 0.5f)
		{
			sum_dl_rate2 += st2.download_payload_rate;
			++count_dl_rates2;
		}
		if (st3.progress < 1.f && st3.progress > 0.5f)
		{
			sum_dl_rate3 += st3.download_rate;
			++count_dl_rates3;
		}

		std::cerr
			<< "\033[33m" << int(st1.upload_payload_rate / 1000.f) << "kB/s "
			<< st1.num_peers << ": "
			<< "\033[32m" << int(st2.download_payload_rate / 1000.f) << "kB/s "
			<< "\033[31m" << int(st2.upload_payload_rate / 1000.f) << "kB/s "
			<< "\033[0m" << int(st2.progress * 100) << "% "
			<< st2.num_peers << " - "
			<< "\033[32m" << int(st3.download_payload_rate / 1000.f) << "kB/s "
			<< "\033[31m" << int(st3.upload_payload_rate / 1000.f) << "kB/s "
			<< "\033[0m" << int(st3.progress * 100) << "% "
			<< st3.num_peers
			<< std::endl;

		if (tor2.is_seed() && tor3.is_seed()) break;
		test_sleep(1000);
	}

	TEST_CHECK(tor2.is_seed());
	TEST_CHECK(tor3.is_seed());

	float average2 = sum_dl_rate2 / float(count_dl_rates2);
	float average3 = sum_dl_rate3 / float(count_dl_rates3);

	std::cerr << average2 << std::endl;
	std::cerr << "average rate: " << (average2 / 1000.f) << "kB/s - "
		<< (average3 / 1000.f) << "kB/s" << std::endl;

	if (tor2.is_seed() && tor3.is_seed()) std::cerr << "done\n";

	// make sure the files are deleted
	ses1.remove_torrent(tor1, session::delete_files);
	ses2.remove_torrent(tor2, session::delete_files);
	ses3.remove_torrent(tor3, session::delete_files);

	std::auto_ptr<alert> a = ses1.pop_alert();
	ptime end = time_now() + seconds(20);
	while (a.get() == 0 || dynamic_cast<torrent_deleted_alert*>(a.get()) == 0)
	{
		if (ses1.wait_for_alert(end - time_now()) == 0)
		{
			std::cerr << "wait_for_alert() expired" << std::endl;
			break;
		}
		a = ses1.pop_alert();
		assert(a.get());
		std::cerr << a->message() << std::endl;
	}

	TEST_CHECK(dynamic_cast<torrent_deleted_alert*>(a.get()) != 0);

	// there shouldn't be any alerts generated from now on
	// make sure that the timer in wait_for_alert() works
	// this should time out (ret == 0) and it should take
	// about 2 seconds
	ptime start = time_now_hires();
	alert const* ret;
	while ((ret = ses1.wait_for_alert(seconds(2))))
	{
		a = ses1.pop_alert();
		std::cerr << ret->message() << std::endl;
		start = time_now();
	}
	TEST_CHECK(time_now_hires() - start < seconds(3));
	TEST_CHECK(time_now_hires() - start >= seconds(2));

	TEST_CHECK(!exists("./tmp1_swarm/temporary"));
	TEST_CHECK(!exists("./tmp2_swarm/temporary"));
	TEST_CHECK(!exists("./tmp3_swarm/temporary"));

	remove_all("./tmp1_swarm", ec);
	remove_all("./tmp2_swarm", ec);
	remove_all("./tmp3_swarm", ec);
}

int test_main()
{
	using namespace libtorrent;

	// with time critical pieces
	test_swarm(false, false, false, true);

	// with seed mode
	test_swarm(false, false, true);

	test_swarm();

	// with super seeding
	test_swarm(true);

	// with strict super seeding
	test_swarm(true, true);

	return 0;
}

<commit_msg>fixed test_swarm build<commit_after>/*

Copyright (c) 2008, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/session.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/alert_types.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/time.hpp"
#include <boost/tuple/tuple.hpp>

#include "test.hpp"
#include "setup_transfer.hpp"

void test_swarm(bool super_seeding = false, bool strict = false, bool seed_mode = false, bool time_critical = false)
{
	using namespace libtorrent;

	// in case the previous run was terminated
	error_code ec;
	remove_all("./tmp1_swarm", ec);
	remove_all("./tmp2_swarm", ec);
	remove_all("./tmp3_swarm", ec);

	session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48000, 49000), "0.0.0.0", 0);
	session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49000, 50000), "0.0.0.0", 0);
	session ses3(fingerprint("LT", 0, 1, 0, 0), std::make_pair(50000, 51000), "0.0.0.0", 0);

	// this is to avoid everything finish from a single peer
	// immediately. To make the swarm actually connect all
	// three peers before finishing.
	float rate_limit = 100000;
	ses1.set_upload_rate_limit(int(rate_limit));
	ses2.set_download_rate_limit(int(rate_limit));
	ses3.set_download_rate_limit(int(rate_limit));
	ses2.set_upload_rate_limit(int(rate_limit / 2));
	ses3.set_upload_rate_limit(int(rate_limit / 2));

	session_settings settings;
	settings.allow_multiple_connections_per_ip = true;
	settings.ignore_limits_on_local_network = false;
	settings.strict_super_seeding = strict;
	ses1.set_settings(settings);
	ses2.set_settings(settings);
	ses3.set_settings(settings);

#ifndef TORRENT_DISABLE_ENCRYPTION
	pe_settings pes;
	pes.out_enc_policy = pe_settings::forced;
	pes.in_enc_policy = pe_settings::forced;
	ses1.set_pe_settings(pes);
	ses2.set_pe_settings(pes);
	ses3.set_pe_settings(pes);
#endif

	torrent_handle tor1;
	torrent_handle tor2;
	torrent_handle tor3;

	add_torrent_params p;
	p.seed_mode = seed_mode;
	// test using piece sizes smaller than 16kB
	boost::tie(tor1, tor2, tor3) = setup_transfer(&ses1, &ses2, &ses3, true
		, false, true, "_swarm", 32 * 1024, 0, super_seeding, &p);

	int mask = alert::all_categories & ~(alert::progress_notification | alert::performance_warning);
	ses1.set_alert_mask(mask);
	ses2.set_alert_mask(mask);
	ses3.set_alert_mask(mask);

	if (time_critical)
	{
		tor2.set_piece_deadline(2, 0);
		tor2.set_piece_deadline(5, 1000);
		tor2.set_piece_deadline(8, 2000);
	}

	float sum_dl_rate2 = 0.f;
	float sum_dl_rate3 = 0.f;
	int count_dl_rates2 = 0;
	int count_dl_rates3 = 0;

	for (int i = 0; i < 80; ++i)
	{
		print_alerts(ses1, "ses1");
		print_alerts(ses2, "ses2");
		print_alerts(ses3, "ses3");

		torrent_status st1 = tor1.status();
		torrent_status st2 = tor2.status();
		torrent_status st3 = tor3.status();

		if (st2.progress < 1.f && st2.progress > 0.5f)
		{
			sum_dl_rate2 += st2.download_payload_rate;
			++count_dl_rates2;
		}
		if (st3.progress < 1.f && st3.progress > 0.5f)
		{
			sum_dl_rate3 += st3.download_rate;
			++count_dl_rates3;
		}

		std::cerr
			<< "\033[33m" << int(st1.upload_payload_rate / 1000.f) << "kB/s "
			<< st1.num_peers << ": "
			<< "\033[32m" << int(st2.download_payload_rate / 1000.f) << "kB/s "
			<< "\033[31m" << int(st2.upload_payload_rate / 1000.f) << "kB/s "
			<< "\033[0m" << int(st2.progress * 100) << "% "
			<< st2.num_peers << " - "
			<< "\033[32m" << int(st3.download_payload_rate / 1000.f) << "kB/s "
			<< "\033[31m" << int(st3.upload_payload_rate / 1000.f) << "kB/s "
			<< "\033[0m" << int(st3.progress * 100) << "% "
			<< st3.num_peers
			<< std::endl;

		if (tor2.is_seed() && tor3.is_seed()) break;
		test_sleep(1000);
	}

	TEST_CHECK(tor2.is_seed());
	TEST_CHECK(tor3.is_seed());

	float average2 = sum_dl_rate2 / float(count_dl_rates2);
	float average3 = sum_dl_rate3 / float(count_dl_rates3);

	std::cerr << average2 << std::endl;
	std::cerr << "average rate: " << (average2 / 1000.f) << "kB/s - "
		<< (average3 / 1000.f) << "kB/s" << std::endl;

	if (tor2.is_seed() && tor3.is_seed()) std::cerr << "done\n";

	// make sure the files are deleted
	ses1.remove_torrent(tor1, session::delete_files);
	ses2.remove_torrent(tor2, session::delete_files);
	ses3.remove_torrent(tor3, session::delete_files);

	std::auto_ptr<alert> a = ses1.pop_alert();
	ptime end = time_now() + seconds(20);
	while (a.get() == 0 || dynamic_cast<torrent_deleted_alert*>(a.get()) == 0)
	{
		if (ses1.wait_for_alert(end - time_now()) == 0)
		{
			std::cerr << "wait_for_alert() expired" << std::endl;
			break;
		}
		a = ses1.pop_alert();
		assert(a.get());
		std::cerr << a->message() << std::endl;
	}

	TEST_CHECK(dynamic_cast<torrent_deleted_alert*>(a.get()) != 0);

	// there shouldn't be any alerts generated from now on
	// make sure that the timer in wait_for_alert() works
	// this should time out (ret == 0) and it should take
	// about 2 seconds
	ptime start = time_now_hires();
	alert const* ret;
	while ((ret = ses1.wait_for_alert(seconds(2))))
	{
		a = ses1.pop_alert();
		std::cerr << ret->message() << std::endl;
		start = time_now();
	}
	TEST_CHECK(time_now_hires() - start < seconds(3));
	TEST_CHECK(time_now_hires() - start >= seconds(2));

	TEST_CHECK(!exists("./tmp1_swarm/temporary"));
	TEST_CHECK(!exists("./tmp2_swarm/temporary"));
	TEST_CHECK(!exists("./tmp3_swarm/temporary"));

	remove_all("./tmp1_swarm", ec);
	remove_all("./tmp2_swarm", ec);
	remove_all("./tmp3_swarm", ec);
}

int test_main()
{
	using namespace libtorrent;

	// with time critical pieces
	test_swarm(false, false, false, true);

	// with seed mode
	test_swarm(false, false, true);

	test_swarm();

	// with super seeding
	test_swarm(true);

	// with strict super seeding
	test_swarm(true, true);

	return 0;
}

<|endoftext|>