<commit_before>/*
 *  Copyright (c) 2014 The WebRTC 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 "testing/gtest/include/gtest/gtest.h"
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
#include "webrtc/modules/interface/module_common_types.h"
#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/compile_assert.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/system_wrappers/interface/thread_annotations.h"
#include "webrtc/system_wrappers/interface/thread_wrapper.h"
#include "webrtc/test/testsupport/gtest_disable.h"

namespace webrtc {

const int kSampleRateHz = 16000;
const int kNumSamples10ms = kSampleRateHz / 100;
const int kFrameSizeMs = 10;  // Multiple of 10.
const int kFrameSizeSamples = kFrameSizeMs / 10 * kNumSamples10ms;
const int kPayloadSizeBytes = kFrameSizeSamples * sizeof(int16_t);
const uint8_t kPayloadType = 111;

class RtpUtility {
 public:
  RtpUtility(int samples_per_packet, uint8_t payload_type)
      : samples_per_packet_(samples_per_packet), payload_type_(payload_type) {}

  virtual ~RtpUtility() {}

  void Populate(WebRtcRTPHeader* rtp_header) {
    rtp_header->header.sequenceNumber = 0xABCD;
    rtp_header->header.timestamp = 0xABCDEF01;
    rtp_header->header.payloadType = payload_type_;
    rtp_header->header.markerBit = false;
    rtp_header->header.ssrc = 0x1234;
    rtp_header->header.numCSRCs = 0;
    rtp_header->frameType = kAudioFrameSpeech;

    rtp_header->header.payload_type_frequency = kSampleRateHz;
    rtp_header->type.Audio.channel = 1;
    rtp_header->type.Audio.isCNG = false;
  }

  void Forward(WebRtcRTPHeader* rtp_header) {
    ++rtp_header->header.sequenceNumber;
    rtp_header->header.timestamp += samples_per_packet_;
  }

 private:
  int samples_per_packet_;
  uint8_t payload_type_;
};

class PacketizationCallbackStub : public AudioPacketizationCallback {
 public:
  PacketizationCallbackStub()
      : num_calls_(0),
        crit_sect_(CriticalSectionWrapper::CreateCriticalSection()) {}

  virtual int32_t SendData(
      FrameType frame_type,
      uint8_t payload_type,
      uint32_t timestamp,
      const uint8_t* payload_data,
      uint16_t payload_len_bytes,
      const RTPFragmentationHeader* fragmentation) OVERRIDE {
    CriticalSectionScoped lock(crit_sect_.get());
    ++num_calls_;
    return 0;
  }

  int num_calls() const {
    CriticalSectionScoped lock(crit_sect_.get());
    return num_calls_;
  }

 private:
  int num_calls_ GUARDED_BY(crit_sect_);
  const scoped_ptr<CriticalSectionWrapper> crit_sect_;
};

class AudioCodingModuleTest : public ::testing::Test {
 protected:
  AudioCodingModuleTest()
      : id_(1),
        rtp_utility_(new RtpUtility(kFrameSizeSamples, kPayloadType)),
        clock_(Clock::GetRealTimeClock()) {}

  ~AudioCodingModuleTest() {}

  void TearDown() {}

  void SetUp() {
    acm_.reset(AudioCodingModule::Create(id_, clock_));

    AudioCodingModule::Codec("L16", &codec_, kSampleRateHz, 1);
    codec_.pltype = kPayloadType;

    // Register L16 codec in ACM.
    ASSERT_EQ(0, acm_->RegisterReceiveCodec(codec_));
    ASSERT_EQ(0, acm_->RegisterSendCodec(codec_));

    rtp_utility_->Populate(&rtp_header_);

    input_frame_.sample_rate_hz_ = kSampleRateHz;
    input_frame_.samples_per_channel_ = kSampleRateHz * 10 / 1000;  // 10 ms.
    COMPILE_ASSERT(kSampleRateHz * 10 / 1000 <= AudioFrame::kMaxDataSizeSamples,
                   audio_frame_too_small);
    memset(input_frame_.data_,
           0,
           input_frame_.samples_per_channel_ * sizeof(input_frame_.data_[0]));

    ASSERT_EQ(0, acm_->RegisterTransportCallback(&packet_cb_));
  }

  void InsertPacketAndPullAudio() {
    InsertPacket();
    PullAudio();
  }

  void InsertPacket() {
    const uint8_t kPayload[kPayloadSizeBytes] = {0};
    ASSERT_EQ(0,
              acm_->IncomingPacket(kPayload, kPayloadSizeBytes, rtp_header_));
    rtp_utility_->Forward(&rtp_header_);
  }

  void PullAudio() {
    AudioFrame audio_frame;
    ASSERT_EQ(0, acm_->PlayoutData10Ms(-1, &audio_frame));
  }

  void InsertAudio() { ASSERT_EQ(0, acm_->Add10MsData(input_frame_)); }

  void Encode() {
    int32_t encoded_bytes = acm_->Process();
    // Expect to get one packet with two bytes per sample, or no packet at all,
    // depending on how many 10 ms blocks go into |codec_.pacsize|.
    EXPECT_TRUE(encoded_bytes == 2 * codec_.pacsize || encoded_bytes == 0);
  }

  const int id_;
  scoped_ptr<RtpUtility> rtp_utility_;
  scoped_ptr<AudioCodingModule> acm_;
  PacketizationCallbackStub packet_cb_;
  WebRtcRTPHeader rtp_header_;
  AudioFrame input_frame_;
  CodecInst codec_;
  Clock* clock_;
};

// Check if the statistics are initialized correctly. Before any call to ACM
// all fields have to be zero.
TEST_F(AudioCodingModuleTest, DISABLED_ON_ANDROID(InitializedToZero)) {
  AudioDecodingCallStats stats;
  acm_->GetDecodingCallStatistics(&stats);
  EXPECT_EQ(0, stats.calls_to_neteq);
  EXPECT_EQ(0, stats.calls_to_silence_generator);
  EXPECT_EQ(0, stats.decoded_normal);
  EXPECT_EQ(0, stats.decoded_cng);
  EXPECT_EQ(0, stats.decoded_plc);
  EXPECT_EQ(0, stats.decoded_plc_cng);
}

// Apply an initial playout delay. Calls to AudioCodingModule::PlayoutData10ms()
// should result in generating silence, check the associated field.
TEST_F(AudioCodingModuleTest, DISABLED_ON_ANDROID(SilenceGeneratorCalled)) {
  AudioDecodingCallStats stats;
  const int kInitialDelay = 100;

  acm_->SetInitialPlayoutDelay(kInitialDelay);

  int num_calls = 0;
  for (int time_ms = 0; time_ms < kInitialDelay;
       time_ms += kFrameSizeMs, ++num_calls) {
    InsertPacketAndPullAudio();
  }
  acm_->GetDecodingCallStatistics(&stats);
  EXPECT_EQ(0, stats.calls_to_neteq);
  EXPECT_EQ(num_calls, stats.calls_to_silence_generator);
  EXPECT_EQ(0, stats.decoded_normal);
  EXPECT_EQ(0, stats.decoded_cng);
  EXPECT_EQ(0, stats.decoded_plc);
  EXPECT_EQ(0, stats.decoded_plc_cng);
}

// Insert some packets and pull audio. Check statistics are valid. Then,
// simulate packet loss and check if PLC and PLC-to-CNG statistics are
// correctly updated.
TEST_F(AudioCodingModuleTest, DISABLED_ON_ANDROID(NetEqCalls)) {
  AudioDecodingCallStats stats;
  const int kNumNormalCalls = 10;

  for (int num_calls = 0; num_calls < kNumNormalCalls; ++num_calls) {
    InsertPacketAndPullAudio();
  }
  acm_->GetDecodingCallStatistics(&stats);
  EXPECT_EQ(kNumNormalCalls, stats.calls_to_neteq);
  EXPECT_EQ(0, stats.calls_to_silence_generator);
  EXPECT_EQ(kNumNormalCalls, stats.decoded_normal);
  EXPECT_EQ(0, stats.decoded_cng);
  EXPECT_EQ(0, stats.decoded_plc);
  EXPECT_EQ(0, stats.decoded_plc_cng);

  const int kNumPlc = 3;
  const int kNumPlcCng = 5;

  // Simulate packet-loss. NetEq first performs PLC then PLC fades to CNG.
  for (int n = 0; n < kNumPlc + kNumPlcCng; ++n) {
    PullAudio();
  }
  acm_->GetDecodingCallStatistics(&stats);
  EXPECT_EQ(kNumNormalCalls + kNumPlc + kNumPlcCng, stats.calls_to_neteq);
  EXPECT_EQ(0, stats.calls_to_silence_generator);
  EXPECT_EQ(kNumNormalCalls, stats.decoded_normal);
  EXPECT_EQ(0, stats.decoded_cng);
  EXPECT_EQ(kNumPlc, stats.decoded_plc);
  EXPECT_EQ(kNumPlcCng, stats.decoded_plc_cng);
}

TEST_F(AudioCodingModuleTest, VerifyOutputFrame) {
  AudioFrame audio_frame;
  const int kSampleRateHz = 32000;
  EXPECT_EQ(0, acm_->PlayoutData10Ms(kSampleRateHz, &audio_frame));
  EXPECT_EQ(id_, audio_frame.id_);
  EXPECT_EQ(0u, audio_frame.timestamp_);
  EXPECT_GT(audio_frame.num_channels_, 0);
  EXPECT_EQ(kSampleRateHz / 100, audio_frame.samples_per_channel_);
  EXPECT_EQ(kSampleRateHz, audio_frame.sample_rate_hz_);
}

TEST_F(AudioCodingModuleTest, FailOnZeroDesiredFrequency) {
  AudioFrame audio_frame;
  EXPECT_EQ(-1, acm_->PlayoutData10Ms(0, &audio_frame));
}

class AudioCodingModuleMtTest : public AudioCodingModuleTest {
 protected:
  static const int kNumPackets = 10000;
  static const int kNumPullCalls = 10000;

  AudioCodingModuleMtTest()
      : AudioCodingModuleTest(),
        send_thread_(ThreadWrapper::CreateThread(CbSendThread,
                                                 this,
                                                 kRealtimePriority,
                                                 "send")),
        insert_packet_thread_(ThreadWrapper::CreateThread(CbInsertPacketThread,
                                                          this,
                                                          kRealtimePriority,
                                                          "insert_packet")),
        pull_audio_thread_(ThreadWrapper::CreateThread(CbPullAudioThread,
                                                       this,
                                                       kRealtimePriority,
                                                       "pull_audio")),
        test_complete_(EventWrapper::Create()),
        send_count_(0),
        insert_packet_count_(0),
        pull_audio_count_(0),
        crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
        next_insert_packet_time_ms_(0),
        fake_clock_(new SimulatedClock(0)) {
    clock_ = fake_clock_;
  }

  ~AudioCodingModuleMtTest() {}

  void SetUp() {
    AudioCodingModuleTest::SetUp();
    unsigned int thread_id = 0;
    ASSERT_TRUE(send_thread_->Start(thread_id));
    ASSERT_TRUE(insert_packet_thread_->Start(thread_id));
    ASSERT_TRUE(pull_audio_thread_->Start(thread_id));
  }

  void TearDown() {
    AudioCodingModuleTest::TearDown();
    pull_audio_thread_->Stop();
    send_thread_->Stop();
    insert_packet_thread_->Stop();
  }

  EventTypeWrapper RunTest() { return test_complete_->Wait(60000); }

 private:
  static bool CbSendThread(void* context) {
    return reinterpret_cast<AudioCodingModuleMtTest*>(context)->CbSendImpl();
  }

  // The send thread doesn't have to care about the current simulated time,
  // since only the AcmReceiver is using the clock.
  bool CbSendImpl() {
    ++send_count_;
    InsertAudio();
    Encode();
    if (packet_cb_.num_calls() > kNumPackets) {
      CriticalSectionScoped lock(crit_sect_.get());
      if (pull_audio_count_ > kNumPullCalls) {
        // Both conditions for completion are met. End the test.
        test_complete_->Set();
      }
    }
    return true;
  }

  static bool CbInsertPacketThread(void* context) {
    return reinterpret_cast<AudioCodingModuleMtTest*>(context)
        ->CbInsertPacketImpl();
  }

  bool CbInsertPacketImpl() {
    {
      CriticalSectionScoped lock(crit_sect_.get());
      if (clock_->TimeInMilliseconds() < next_insert_packet_time_ms_) {
        return true;
      }
      next_insert_packet_time_ms_ += 10;
    }
    // Now we're not holding the crit sect when calling ACM.
    ++insert_packet_count_;
    InsertPacket();
    return true;
  }

  static bool CbPullAudioThread(void* context) {
    return reinterpret_cast<AudioCodingModuleMtTest*>(context)
        ->CbPullAudioImpl();
  }

  bool CbPullAudioImpl() {
    {
      CriticalSectionScoped lock(crit_sect_.get());
      // Don't let the insert thread fall behind.
      if (next_insert_packet_time_ms_ < clock_->TimeInMilliseconds()) {
        return true;
      }
      ++pull_audio_count_;
    }
    // Now we're not holding the crit sect when calling ACM.
    PullAudio();
    fake_clock_->AdvanceTimeMilliseconds(10);
    return true;
  }

  scoped_ptr<ThreadWrapper> send_thread_;
  scoped_ptr<ThreadWrapper> insert_packet_thread_;
  scoped_ptr<ThreadWrapper> pull_audio_thread_;
  const scoped_ptr<EventWrapper> test_complete_;
  int send_count_;
  int insert_packet_count_;
  int pull_audio_count_ GUARDED_BY(crit_sect_);
  const scoped_ptr<CriticalSectionWrapper> crit_sect_;
  int64_t next_insert_packet_time_ms_ GUARDED_BY(crit_sect_);
  SimulatedClock* fake_clock_;
};

TEST_F(AudioCodingModuleMtTest, DoTest) {
  EXPECT_EQ(kEventSignaled, RunTest());
}

}  // namespace webrtc
<commit_msg>Disable AudioCodingModuleMtTest due to memcheck and tsan failures.<commit_after>/*
 *  Copyright (c) 2014 The WebRTC 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 "testing/gtest/include/gtest/gtest.h"
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
#include "webrtc/modules/interface/module_common_types.h"
#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/compile_assert.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/system_wrappers/interface/thread_annotations.h"
#include "webrtc/system_wrappers/interface/thread_wrapper.h"
#include "webrtc/test/testsupport/gtest_disable.h"

namespace webrtc {

const int kSampleRateHz = 16000;
const int kNumSamples10ms = kSampleRateHz / 100;
const int kFrameSizeMs = 10;  // Multiple of 10.
const int kFrameSizeSamples = kFrameSizeMs / 10 * kNumSamples10ms;
const int kPayloadSizeBytes = kFrameSizeSamples * sizeof(int16_t);
const uint8_t kPayloadType = 111;

class RtpUtility {
 public:
  RtpUtility(int samples_per_packet, uint8_t payload_type)
      : samples_per_packet_(samples_per_packet), payload_type_(payload_type) {}

  virtual ~RtpUtility() {}

  void Populate(WebRtcRTPHeader* rtp_header) {
    rtp_header->header.sequenceNumber = 0xABCD;
    rtp_header->header.timestamp = 0xABCDEF01;
    rtp_header->header.payloadType = payload_type_;
    rtp_header->header.markerBit = false;
    rtp_header->header.ssrc = 0x1234;
    rtp_header->header.numCSRCs = 0;
    rtp_header->frameType = kAudioFrameSpeech;

    rtp_header->header.payload_type_frequency = kSampleRateHz;
    rtp_header->type.Audio.channel = 1;
    rtp_header->type.Audio.isCNG = false;
  }

  void Forward(WebRtcRTPHeader* rtp_header) {
    ++rtp_header->header.sequenceNumber;
    rtp_header->header.timestamp += samples_per_packet_;
  }

 private:
  int samples_per_packet_;
  uint8_t payload_type_;
};

class PacketizationCallbackStub : public AudioPacketizationCallback {
 public:
  PacketizationCallbackStub()
      : num_calls_(0),
        crit_sect_(CriticalSectionWrapper::CreateCriticalSection()) {}

  virtual int32_t SendData(
      FrameType frame_type,
      uint8_t payload_type,
      uint32_t timestamp,
      const uint8_t* payload_data,
      uint16_t payload_len_bytes,
      const RTPFragmentationHeader* fragmentation) OVERRIDE {
    CriticalSectionScoped lock(crit_sect_.get());
    ++num_calls_;
    return 0;
  }

  int num_calls() const {
    CriticalSectionScoped lock(crit_sect_.get());
    return num_calls_;
  }

 private:
  int num_calls_ GUARDED_BY(crit_sect_);
  const scoped_ptr<CriticalSectionWrapper> crit_sect_;
};

class AudioCodingModuleTest : public ::testing::Test {
 protected:
  AudioCodingModuleTest()
      : id_(1),
        rtp_utility_(new RtpUtility(kFrameSizeSamples, kPayloadType)),
        clock_(Clock::GetRealTimeClock()) {}

  ~AudioCodingModuleTest() {}

  void TearDown() {}

  void SetUp() {
    acm_.reset(AudioCodingModule::Create(id_, clock_));

    AudioCodingModule::Codec("L16", &codec_, kSampleRateHz, 1);
    codec_.pltype = kPayloadType;

    // Register L16 codec in ACM.
    ASSERT_EQ(0, acm_->RegisterReceiveCodec(codec_));
    ASSERT_EQ(0, acm_->RegisterSendCodec(codec_));

    rtp_utility_->Populate(&rtp_header_);

    input_frame_.sample_rate_hz_ = kSampleRateHz;
    input_frame_.samples_per_channel_ = kSampleRateHz * 10 / 1000;  // 10 ms.
    COMPILE_ASSERT(kSampleRateHz * 10 / 1000 <= AudioFrame::kMaxDataSizeSamples,
                   audio_frame_too_small);
    memset(input_frame_.data_,
           0,
           input_frame_.samples_per_channel_ * sizeof(input_frame_.data_[0]));

    ASSERT_EQ(0, acm_->RegisterTransportCallback(&packet_cb_));
  }

  void InsertPacketAndPullAudio() {
    InsertPacket();
    PullAudio();
  }

  void InsertPacket() {
    const uint8_t kPayload[kPayloadSizeBytes] = {0};
    ASSERT_EQ(0,
              acm_->IncomingPacket(kPayload, kPayloadSizeBytes, rtp_header_));
    rtp_utility_->Forward(&rtp_header_);
  }

  void PullAudio() {
    AudioFrame audio_frame;
    ASSERT_EQ(0, acm_->PlayoutData10Ms(-1, &audio_frame));
  }

  void InsertAudio() { ASSERT_EQ(0, acm_->Add10MsData(input_frame_)); }

  void Encode() {
    int32_t encoded_bytes = acm_->Process();
    // Expect to get one packet with two bytes per sample, or no packet at all,
    // depending on how many 10 ms blocks go into |codec_.pacsize|.
    EXPECT_TRUE(encoded_bytes == 2 * codec_.pacsize || encoded_bytes == 0);
  }

  const int id_;
  scoped_ptr<RtpUtility> rtp_utility_;
  scoped_ptr<AudioCodingModule> acm_;
  PacketizationCallbackStub packet_cb_;
  WebRtcRTPHeader rtp_header_;
  AudioFrame input_frame_;
  CodecInst codec_;
  Clock* clock_;
};

// Check if the statistics are initialized correctly. Before any call to ACM
// all fields have to be zero.
TEST_F(AudioCodingModuleTest, DISABLED_ON_ANDROID(InitializedToZero)) {
  AudioDecodingCallStats stats;
  acm_->GetDecodingCallStatistics(&stats);
  EXPECT_EQ(0, stats.calls_to_neteq);
  EXPECT_EQ(0, stats.calls_to_silence_generator);
  EXPECT_EQ(0, stats.decoded_normal);
  EXPECT_EQ(0, stats.decoded_cng);
  EXPECT_EQ(0, stats.decoded_plc);
  EXPECT_EQ(0, stats.decoded_plc_cng);
}

// Apply an initial playout delay. Calls to AudioCodingModule::PlayoutData10ms()
// should result in generating silence, check the associated field.
TEST_F(AudioCodingModuleTest, DISABLED_ON_ANDROID(SilenceGeneratorCalled)) {
  AudioDecodingCallStats stats;
  const int kInitialDelay = 100;

  acm_->SetInitialPlayoutDelay(kInitialDelay);

  int num_calls = 0;
  for (int time_ms = 0; time_ms < kInitialDelay;
       time_ms += kFrameSizeMs, ++num_calls) {
    InsertPacketAndPullAudio();
  }
  acm_->GetDecodingCallStatistics(&stats);
  EXPECT_EQ(0, stats.calls_to_neteq);
  EXPECT_EQ(num_calls, stats.calls_to_silence_generator);
  EXPECT_EQ(0, stats.decoded_normal);
  EXPECT_EQ(0, stats.decoded_cng);
  EXPECT_EQ(0, stats.decoded_plc);
  EXPECT_EQ(0, stats.decoded_plc_cng);
}

// Insert some packets and pull audio. Check statistics are valid. Then,
// simulate packet loss and check if PLC and PLC-to-CNG statistics are
// correctly updated.
TEST_F(AudioCodingModuleTest, DISABLED_ON_ANDROID(NetEqCalls)) {
  AudioDecodingCallStats stats;
  const int kNumNormalCalls = 10;

  for (int num_calls = 0; num_calls < kNumNormalCalls; ++num_calls) {
    InsertPacketAndPullAudio();
  }
  acm_->GetDecodingCallStatistics(&stats);
  EXPECT_EQ(kNumNormalCalls, stats.calls_to_neteq);
  EXPECT_EQ(0, stats.calls_to_silence_generator);
  EXPECT_EQ(kNumNormalCalls, stats.decoded_normal);
  EXPECT_EQ(0, stats.decoded_cng);
  EXPECT_EQ(0, stats.decoded_plc);
  EXPECT_EQ(0, stats.decoded_plc_cng);

  const int kNumPlc = 3;
  const int kNumPlcCng = 5;

  // Simulate packet-loss. NetEq first performs PLC then PLC fades to CNG.
  for (int n = 0; n < kNumPlc + kNumPlcCng; ++n) {
    PullAudio();
  }
  acm_->GetDecodingCallStatistics(&stats);
  EXPECT_EQ(kNumNormalCalls + kNumPlc + kNumPlcCng, stats.calls_to_neteq);
  EXPECT_EQ(0, stats.calls_to_silence_generator);
  EXPECT_EQ(kNumNormalCalls, stats.decoded_normal);
  EXPECT_EQ(0, stats.decoded_cng);
  EXPECT_EQ(kNumPlc, stats.decoded_plc);
  EXPECT_EQ(kNumPlcCng, stats.decoded_plc_cng);
}

TEST_F(AudioCodingModuleTest, VerifyOutputFrame) {
  AudioFrame audio_frame;
  const int kSampleRateHz = 32000;
  EXPECT_EQ(0, acm_->PlayoutData10Ms(kSampleRateHz, &audio_frame));
  EXPECT_EQ(id_, audio_frame.id_);
  EXPECT_EQ(0u, audio_frame.timestamp_);
  EXPECT_GT(audio_frame.num_channels_, 0);
  EXPECT_EQ(kSampleRateHz / 100, audio_frame.samples_per_channel_);
  EXPECT_EQ(kSampleRateHz, audio_frame.sample_rate_hz_);
}

TEST_F(AudioCodingModuleTest, FailOnZeroDesiredFrequency) {
  AudioFrame audio_frame;
  EXPECT_EQ(-1, acm_->PlayoutData10Ms(0, &audio_frame));
}

class AudioCodingModuleMtTest : public AudioCodingModuleTest {
 protected:
  static const int kNumPackets = 10000;
  static const int kNumPullCalls = 10000;

  AudioCodingModuleMtTest()
      : AudioCodingModuleTest(),
        send_thread_(ThreadWrapper::CreateThread(CbSendThread,
                                                 this,
                                                 kRealtimePriority,
                                                 "send")),
        insert_packet_thread_(ThreadWrapper::CreateThread(CbInsertPacketThread,
                                                          this,
                                                          kRealtimePriority,
                                                          "insert_packet")),
        pull_audio_thread_(ThreadWrapper::CreateThread(CbPullAudioThread,
                                                       this,
                                                       kRealtimePriority,
                                                       "pull_audio")),
        test_complete_(EventWrapper::Create()),
        send_count_(0),
        insert_packet_count_(0),
        pull_audio_count_(0),
        crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
        next_insert_packet_time_ms_(0),
        fake_clock_(new SimulatedClock(0)) {
    clock_ = fake_clock_;
  }

  ~AudioCodingModuleMtTest() {}

  void SetUp() {
    AudioCodingModuleTest::SetUp();
    unsigned int thread_id = 0;
    ASSERT_TRUE(send_thread_->Start(thread_id));
    ASSERT_TRUE(insert_packet_thread_->Start(thread_id));
    ASSERT_TRUE(pull_audio_thread_->Start(thread_id));
  }

  void TearDown() {
    AudioCodingModuleTest::TearDown();
    pull_audio_thread_->Stop();
    send_thread_->Stop();
    insert_packet_thread_->Stop();
  }

  EventTypeWrapper RunTest() { return test_complete_->Wait(60000); }

 private:
  static bool CbSendThread(void* context) {
    return reinterpret_cast<AudioCodingModuleMtTest*>(context)->CbSendImpl();
  }

  // The send thread doesn't have to care about the current simulated time,
  // since only the AcmReceiver is using the clock.
  bool CbSendImpl() {
    ++send_count_;
    InsertAudio();
    Encode();
    if (packet_cb_.num_calls() > kNumPackets) {
      CriticalSectionScoped lock(crit_sect_.get());
      if (pull_audio_count_ > kNumPullCalls) {
        // Both conditions for completion are met. End the test.
        test_complete_->Set();
      }
    }
    return true;
  }

  static bool CbInsertPacketThread(void* context) {
    return reinterpret_cast<AudioCodingModuleMtTest*>(context)
        ->CbInsertPacketImpl();
  }

  bool CbInsertPacketImpl() {
    {
      CriticalSectionScoped lock(crit_sect_.get());
      if (clock_->TimeInMilliseconds() < next_insert_packet_time_ms_) {
        return true;
      }
      next_insert_packet_time_ms_ += 10;
    }
    // Now we're not holding the crit sect when calling ACM.
    ++insert_packet_count_;
    InsertPacket();
    return true;
  }

  static bool CbPullAudioThread(void* context) {
    return reinterpret_cast<AudioCodingModuleMtTest*>(context)
        ->CbPullAudioImpl();
  }

  bool CbPullAudioImpl() {
    {
      CriticalSectionScoped lock(crit_sect_.get());
      // Don't let the insert thread fall behind.
      if (next_insert_packet_time_ms_ < clock_->TimeInMilliseconds()) {
        return true;
      }
      ++pull_audio_count_;
    }
    // Now we're not holding the crit sect when calling ACM.
    PullAudio();
    fake_clock_->AdvanceTimeMilliseconds(10);
    return true;
  }

  scoped_ptr<ThreadWrapper> send_thread_;
  scoped_ptr<ThreadWrapper> insert_packet_thread_;
  scoped_ptr<ThreadWrapper> pull_audio_thread_;
  const scoped_ptr<EventWrapper> test_complete_;
  int send_count_;
  int insert_packet_count_;
  int pull_audio_count_ GUARDED_BY(crit_sect_);
  const scoped_ptr<CriticalSectionWrapper> crit_sect_;
  int64_t next_insert_packet_time_ms_ GUARDED_BY(crit_sect_);
  SimulatedClock* fake_clock_;
};

TEST_F(AudioCodingModuleMtTest, DISABLED_DoTest) {
  EXPECT_EQ(kEventSignaled, RunTest());
}

}  // namespace webrtc
<|endoftext|>


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

#include "modules/canbus/vehicle/gem/protocol/wheel_speed_rpt_7a.h"

#include "gtest/gtest.h"

namespace apollo {
namespace canbus {
namespace gem {

class Wheelspeedrpt7aTest : public ::testing::Test {
 public:
  virtual void SetUp() {}
};

TEST_F(Wheelspeedrpt7aTest, reset) {
  Wheelspeedrpt7a wheelspeed;
  int32_t length = 8;
  ChassisDetail chassis_detail;
  uint8_t bytes[8] = {0x01, 0x02, 0x03, 0x04, 0x11, 0x12, 0x13, 0x14};
  wheelspeed.Parse(bytes, length, &chassis_detail);
  EXPECT_DOUBLE_EQ(chassis_detail.gem().wheel_speed_rpt_7a()\
.wheel_spd_rear_right(), 4884);
  EXPECT_DOUBLE_EQ(chassis_detail.gem().wheel_speed_rpt_7a()\
.wheel_spd_rear_left(), 4370);
  EXPECT_DOUBLE_EQ(chassis_detail.gem().wheel_speed_rpt_7a()\
.wheel_spd_front_right(), 772);
  EXPECT_DOUBLE_EQ(chassis_detail.gem().wheel_speed_rpt_7a()\
.wheel_spd_front_left(), 258);
}

}  // namespace gem
}  // namespace canbus
}  // namespace apollo

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

#include "modules/canbus/vehicle/gem/protocol/wheel_speed_rpt_7a.h"

#include "gtest/gtest.h"

namespace apollo {
namespace canbus {
namespace gem {

class Wheelspeedrpt7aTest : public ::testing::Test {
 public:
  virtual void SetUp() {}
};

TEST_F(Wheelspeedrpt7aTest, reset) {
  Wheelspeedrpt7a wheelspeed;
  int32_t length = 8;
  ChassisDetail chassis_detail;
  uint8_t bytes[8] = {0x01, 0x02, 0x03, 0x04, 0x11, 0x12, 0x13, 0x14};
  wheelspeed.Parse(bytes, length, &chassis_detail);
  EXPECT_DOUBLE_EQ(chassis_detail.gem().wheel_speed_rpt_7a()\
.wheel_spd_rear_right(), 4884);
  EXPECT_DOUBLE_EQ(chassis_detail.gem().wheel_speed_rpt_7a()\
.wheel_spd_rear_left(), 4370);
  EXPECT_DOUBLE_EQ(chassis_detail.gem().wheel_speed_rpt_7a()\
.wheel_spd_front_right(), 772);
  EXPECT_DOUBLE_EQ(chassis_detail.gem().wheel_speed_rpt_7a()\
.wheel_spd_front_left(), 258);
}

}  // namespace gem
}  // namespace canbus
}  // namespace apollo
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "vsenvironmentdetector.h"

#include <logging/translator.h>
#include <tools/qbsassert.h>
#include <tools/qttools.h>
#include <tools/stringconstants.h>
#include <tools/stringutils.h>

#include <QtCore/qdebug.h>
#include <QtCore/qdir.h>
#include <QtCore/qprocess.h>
#include <QtCore/qtemporaryfile.h>
#include <QtCore/qtextstream.h>

#ifdef Q_OS_WIN
#include <QtCore/qt_windows.h>
#include <shlobj.h>
#endif

namespace qbs {
namespace Internal {

static QString windowsSystem32Path()
{
#ifdef Q_OS_WIN
    wchar_t str[UNICODE_STRING_MAX_CHARS];
    if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_SYSTEM, NULL, 0, str)))
        return QString::fromUtf16(reinterpret_cast<ushort*>(str));
#endif
    return {};
}

VsEnvironmentDetector::VsEnvironmentDetector(QString vcvarsallPath)
    : m_windowsSystemDirPath(windowsSystem32Path())
    , m_vcvarsallPath(std::move(vcvarsallPath))
{
}

bool VsEnvironmentDetector::start(MSVC *msvc)
{
    return start(std::vector<MSVC *>{ msvc });
}

bool VsEnvironmentDetector::start(std::vector<MSVC *> msvcs)
{
    std::sort(msvcs.begin(), msvcs.end(), [] (const MSVC *a, const MSVC *b) -> bool {
        return a->vcInstallPath < b->vcInstallPath;
    });

    std::vector<MSVC *> compatibleMSVCs;
    QString lastVcInstallPath;
    bool someMSVCDetected = false;
    for (MSVC * const msvc : msvcs) {
        if (lastVcInstallPath != msvc->vcInstallPath) {
            lastVcInstallPath = msvc->vcInstallPath;
            if (!compatibleMSVCs.empty()) {
                if (startDetection(compatibleMSVCs))
                    someMSVCDetected = true;
                compatibleMSVCs.clear();
            }
        }
        compatibleMSVCs.push_back(msvc);
    }
    if (startDetection(compatibleMSVCs))
        someMSVCDetected = true;
    return someMSVCDetected;
}

QString VsEnvironmentDetector::findVcVarsAllBat(const MSVC &msvc,
                                                std::vector<QString> &searchedPaths) const
{
    // ### We can only rely on MSVC.vcInstallPath being set
    // when this is called from utilitiesextension.cpp :-(
    // If we knew the vsInstallPath at this point we could just use that
    // instead of searching for vcvarsall.bat candidates.
    QDir dir(msvc.vcInstallPath);
    for (;;) {
        if (!dir.cdUp())
            return {};
        if (dir.dirName() == QLatin1String("VC"))
            break;
    }
    const QString vcvarsallbat = QStringLiteral("vcvarsall.bat");
    QString path = vcvarsallbat;
    QString fullPath = dir.absoluteFilePath(path);
    if (dir.exists(path))
        return fullPath;
    else
        searchedPaths.push_back(fullPath);
    path = QStringLiteral("Auxiliary/Build/") + vcvarsallbat;
    fullPath = dir.absoluteFilePath(path);
    if (dir.exists(path))
        return fullPath;
    else
        searchedPaths.push_back(fullPath);
    return {};
}

bool VsEnvironmentDetector::startDetection(const std::vector<MSVC *> &compatibleMSVCs)
{
    std::vector<QString> searchedPaths;

    if (!m_vcvarsallPath.isEmpty() && !QFileInfo::exists(m_vcvarsallPath)) {
        m_errorString = Tr::tr("%1 does not exist.").arg(m_vcvarsallPath);
        return false;
    }

    const auto vcvarsallbat = !m_vcvarsallPath.isEmpty()
            ? m_vcvarsallPath
            : findVcVarsAllBat(**compatibleMSVCs.begin(), searchedPaths);
    if (vcvarsallbat.isEmpty()) {
        if (!searchedPaths.empty()) {
            m_errorString = Tr::tr(
                        "Cannot find 'vcvarsall.bat' at any of the following locations:\n\t")
                    + join(searchedPaths, QStringLiteral("\n\t"));
        } else {
            m_errorString = Tr::tr("Cannot find 'vcvarsall.bat'.");
        }
        return false;
    }

    QTemporaryFile tmpFile(QDir::tempPath() + QLatin1Char('/') + QStringLiteral("XXXXXX.bat"));
    if (!tmpFile.open()) {
        m_errorString = Tr::tr("Cannot open temporary file '%1' for writing.").arg(
                    tmpFile.fileName());
        return false;
    }

    writeBatchFile(&tmpFile, vcvarsallbat, compatibleMSVCs);
    tmpFile.flush();

    QProcess process;
    static const QString shellFilePath = QStringLiteral("cmd.exe");
    process.start(shellFilePath, QStringList()
                  << QStringLiteral("/C") << tmpFile.fileName());
    if (!process.waitForStarted()) {
        m_errorString = Tr::tr("Failed to start '%1'.").arg(shellFilePath);
        return false;
    }
    process.waitForFinished(-1);
    if (process.exitStatus() != QProcess::NormalExit) {
        m_errorString = Tr::tr("Process '%1' did not exit normally.").arg(shellFilePath);
        return false;
    }
    if (process.exitCode() != 0) {
        m_errorString = Tr::tr("Failed to detect Visual Studio environment.");
        return false;
    }
    parseBatOutput(process.readAllStandardOutput(), compatibleMSVCs);
    return true;

}

static void batClearVars(QTextStream &s, const QStringList &varnames)
{
    for (const QString &varname : varnames)
        s << "set " << varname << '=' << Qt::endl;
}

static void batPrintVars(QTextStream &s, const QStringList &varnames)
{
    for (const QString &varname : varnames)
        s << "echo " << varname << "=%" << varname << '%' << Qt::endl;
}

static QString vcArchitecture(const MSVC *msvc)
{
    QString vcArch = msvc->architecture;
    if (msvc->architecture == StringConstants::armv7Arch())
        vcArch = StringConstants::armArch();
    if (msvc->architecture == StringConstants::x86_64Arch())
        vcArch = StringConstants::amd64Arch();

    const QString hostPrefixes[] = {
        StringConstants::x86Arch(),
        QStringLiteral("amd64_"),
        QStringLiteral("x86_")
    };
    for (const QString &hostPrefix : hostPrefixes) {
        if (QFile::exists(msvc->clPathForArchitecture(hostPrefix + vcArch))) {
            vcArch.prepend(hostPrefix);
            break;
        }
    }

    return vcArch;
}

void VsEnvironmentDetector::writeBatchFile(QIODevice *device, const QString &vcvarsallbat,
                                           const std::vector<MSVC *> &msvcs) const
{
    const QStringList varnames = QStringList() << StringConstants::pathEnvVar()
            << QStringLiteral("INCLUDE") << QStringLiteral("LIB") << QStringLiteral("WindowsSdkDir")
            << QStringLiteral("WindowsSDKVersion") << QStringLiteral("VSINSTALLDIR");
    QTextStream s(device);
    using Qt::endl;
    s << "@echo off" << endl;
    // Avoid execution of powershell (in vsdevcmd.bat), which is not in the cleared PATH
    s << "set VSCMD_SKIP_SENDTELEMETRY=1" << endl;
    for (const MSVC *msvc : msvcs) {
        s << "echo --" << msvc->architecture << "--" << endl
          << "setlocal" << endl;
        batClearVars(s, varnames);
        s << "set PATH=" << m_windowsSystemDirPath << endl; // vcvarsall.bat needs tools from here
        s << "call \"" << vcvarsallbat << "\" " << vcArchitecture(msvc)
          << " || exit /b 1" << endl;
        batPrintVars(s, varnames);
        s << "endlocal" << endl;
    }
}

void VsEnvironmentDetector::parseBatOutput(const QByteArray &output, std::vector<MSVC *> msvcs)
{
    QString arch;
    QProcessEnvironment *targetEnv = nullptr;
    const auto lines = output.split('\n');
    for (QByteArray line : lines) {
        line = line.trimmed();
        if (line.isEmpty())
            continue;

        if (line.startsWith("--") && line.endsWith("--")) {
            line.remove(0, 2);
            line.chop(2);
            arch = QString::fromLocal8Bit(line);
            targetEnv = &msvcs.front()->environment;
            msvcs.erase(msvcs.begin());
        } else {
            int idx = line.indexOf('=');
            if (idx < 0)
                continue;
            QBS_CHECK(targetEnv);
            const QString name = QString::fromLocal8Bit(line.left(idx));
            QString value = QString::fromLocal8Bit(line.mid(idx + 1));
            if (name.compare(StringConstants::pathEnvVar(), Qt::CaseInsensitive) == 0)
                value.remove(m_windowsSystemDirPath);
            if (value.endsWith(QLatin1Char(';')))
                value.chop(1);
            if (value.endsWith(QLatin1Char('\\')))
                value.chop(1);
            targetEnv->insert(name, value);
        }
    }
}

} // namespace Internal
} // namespace qbs
<commit_msg>Remove deleting trailing slash from VS env vars<commit_after>/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "vsenvironmentdetector.h"

#include <logging/translator.h>
#include <tools/qbsassert.h>
#include <tools/qttools.h>
#include <tools/stringconstants.h>
#include <tools/stringutils.h>

#include <QtCore/qdebug.h>
#include <QtCore/qdir.h>
#include <QtCore/qprocess.h>
#include <QtCore/qtemporaryfile.h>
#include <QtCore/qtextstream.h>

#ifdef Q_OS_WIN
#include <QtCore/qt_windows.h>
#include <shlobj.h>
#endif

namespace qbs {
namespace Internal {

static QString windowsSystem32Path()
{
#ifdef Q_OS_WIN
    wchar_t str[UNICODE_STRING_MAX_CHARS];
    if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_SYSTEM, NULL, 0, str)))
        return QString::fromUtf16(reinterpret_cast<ushort*>(str));
#endif
    return {};
}

VsEnvironmentDetector::VsEnvironmentDetector(QString vcvarsallPath)
    : m_windowsSystemDirPath(windowsSystem32Path())
    , m_vcvarsallPath(std::move(vcvarsallPath))
{
}

bool VsEnvironmentDetector::start(MSVC *msvc)
{
    return start(std::vector<MSVC *>{ msvc });
}

bool VsEnvironmentDetector::start(std::vector<MSVC *> msvcs)
{
    std::sort(msvcs.begin(), msvcs.end(), [] (const MSVC *a, const MSVC *b) -> bool {
        return a->vcInstallPath < b->vcInstallPath;
    });

    std::vector<MSVC *> compatibleMSVCs;
    QString lastVcInstallPath;
    bool someMSVCDetected = false;
    for (MSVC * const msvc : msvcs) {
        if (lastVcInstallPath != msvc->vcInstallPath) {
            lastVcInstallPath = msvc->vcInstallPath;
            if (!compatibleMSVCs.empty()) {
                if (startDetection(compatibleMSVCs))
                    someMSVCDetected = true;
                compatibleMSVCs.clear();
            }
        }
        compatibleMSVCs.push_back(msvc);
    }
    if (startDetection(compatibleMSVCs))
        someMSVCDetected = true;
    return someMSVCDetected;
}

QString VsEnvironmentDetector::findVcVarsAllBat(const MSVC &msvc,
                                                std::vector<QString> &searchedPaths) const
{
    // ### We can only rely on MSVC.vcInstallPath being set
    // when this is called from utilitiesextension.cpp :-(
    // If we knew the vsInstallPath at this point we could just use that
    // instead of searching for vcvarsall.bat candidates.
    QDir dir(msvc.vcInstallPath);
    for (;;) {
        if (!dir.cdUp())
            return {};
        if (dir.dirName() == QLatin1String("VC"))
            break;
    }
    const QString vcvarsallbat = QStringLiteral("vcvarsall.bat");
    QString path = vcvarsallbat;
    QString fullPath = dir.absoluteFilePath(path);
    if (dir.exists(path))
        return fullPath;
    else
        searchedPaths.push_back(fullPath);
    path = QStringLiteral("Auxiliary/Build/") + vcvarsallbat;
    fullPath = dir.absoluteFilePath(path);
    if (dir.exists(path))
        return fullPath;
    else
        searchedPaths.push_back(fullPath);
    return {};
}

bool VsEnvironmentDetector::startDetection(const std::vector<MSVC *> &compatibleMSVCs)
{
    std::vector<QString> searchedPaths;

    if (!m_vcvarsallPath.isEmpty() && !QFileInfo::exists(m_vcvarsallPath)) {
        m_errorString = Tr::tr("%1 does not exist.").arg(m_vcvarsallPath);
        return false;
    }

    const auto vcvarsallbat = !m_vcvarsallPath.isEmpty()
            ? m_vcvarsallPath
            : findVcVarsAllBat(**compatibleMSVCs.begin(), searchedPaths);
    if (vcvarsallbat.isEmpty()) {
        if (!searchedPaths.empty()) {
            m_errorString = Tr::tr(
                        "Cannot find 'vcvarsall.bat' at any of the following locations:\n\t")
                    + join(searchedPaths, QStringLiteral("\n\t"));
        } else {
            m_errorString = Tr::tr("Cannot find 'vcvarsall.bat'.");
        }
        return false;
    }

    QTemporaryFile tmpFile(QDir::tempPath() + QLatin1Char('/') + QStringLiteral("XXXXXX.bat"));
    if (!tmpFile.open()) {
        m_errorString = Tr::tr("Cannot open temporary file '%1' for writing.").arg(
                    tmpFile.fileName());
        return false;
    }

    writeBatchFile(&tmpFile, vcvarsallbat, compatibleMSVCs);
    tmpFile.flush();

    QProcess process;
    static const QString shellFilePath = QStringLiteral("cmd.exe");
    process.start(shellFilePath, QStringList()
                  << QStringLiteral("/C") << tmpFile.fileName());
    if (!process.waitForStarted()) {
        m_errorString = Tr::tr("Failed to start '%1'.").arg(shellFilePath);
        return false;
    }
    process.waitForFinished(-1);
    if (process.exitStatus() != QProcess::NormalExit) {
        m_errorString = Tr::tr("Process '%1' did not exit normally.").arg(shellFilePath);
        return false;
    }
    if (process.exitCode() != 0) {
        m_errorString = Tr::tr("Failed to detect Visual Studio environment.");
        return false;
    }
    parseBatOutput(process.readAllStandardOutput(), compatibleMSVCs);
    return true;

}

static void batClearVars(QTextStream &s, const QStringList &varnames)
{
    for (const QString &varname : varnames)
        s << "set " << varname << '=' << Qt::endl;
}

static void batPrintVars(QTextStream &s, const QStringList &varnames)
{
    for (const QString &varname : varnames)
        s << "echo " << varname << "=%" << varname << '%' << Qt::endl;
}

static QString vcArchitecture(const MSVC *msvc)
{
    QString vcArch = msvc->architecture;
    if (msvc->architecture == StringConstants::armv7Arch())
        vcArch = StringConstants::armArch();
    if (msvc->architecture == StringConstants::x86_64Arch())
        vcArch = StringConstants::amd64Arch();

    const QString hostPrefixes[] = {
        StringConstants::x86Arch(),
        QStringLiteral("amd64_"),
        QStringLiteral("x86_")
    };
    for (const QString &hostPrefix : hostPrefixes) {
        if (QFile::exists(msvc->clPathForArchitecture(hostPrefix + vcArch))) {
            vcArch.prepend(hostPrefix);
            break;
        }
    }

    return vcArch;
}

void VsEnvironmentDetector::writeBatchFile(QIODevice *device, const QString &vcvarsallbat,
                                           const std::vector<MSVC *> &msvcs) const
{
    const QStringList varnames = QStringList() << StringConstants::pathEnvVar()
            << QStringLiteral("INCLUDE") << QStringLiteral("LIB") << QStringLiteral("WindowsSdkDir")
            << QStringLiteral("WindowsSDKVersion") << QStringLiteral("VSINSTALLDIR");
    QTextStream s(device);
    using Qt::endl;
    s << "@echo off" << endl;
    // Avoid execution of powershell (in vsdevcmd.bat), which is not in the cleared PATH
    s << "set VSCMD_SKIP_SENDTELEMETRY=1" << endl;
    for (const MSVC *msvc : msvcs) {
        s << "echo --" << msvc->architecture << "--" << endl
          << "setlocal" << endl;
        batClearVars(s, varnames);
        s << "set PATH=" << m_windowsSystemDirPath << endl; // vcvarsall.bat needs tools from here
        s << "call \"" << vcvarsallbat << "\" " << vcArchitecture(msvc)
          << " || exit /b 1" << endl;
        batPrintVars(s, varnames);
        s << "endlocal" << endl;
    }
}

void VsEnvironmentDetector::parseBatOutput(const QByteArray &output, std::vector<MSVC *> msvcs)
{
    QString arch;
    QProcessEnvironment *targetEnv = nullptr;
    const auto lines = output.split('\n');
    for (QByteArray line : lines) {
        line = line.trimmed();
        if (line.isEmpty())
            continue;

        if (line.startsWith("--") && line.endsWith("--")) {
            line.remove(0, 2);
            line.chop(2);
            arch = QString::fromLocal8Bit(line);
            targetEnv = &msvcs.front()->environment;
            msvcs.erase(msvcs.begin());
        } else {
            int idx = line.indexOf('=');
            if (idx < 0)
                continue;
            QBS_CHECK(targetEnv);
            const QString name = QString::fromLocal8Bit(line.left(idx));
            QString value = QString::fromLocal8Bit(line.mid(idx + 1));
            if (name.compare(StringConstants::pathEnvVar(), Qt::CaseInsensitive) == 0)
                value.remove(m_windowsSystemDirPath);
            if (value.endsWith(QLatin1Char(';')))
                value.chop(1);
            targetEnv->insert(name, value);
        }
    }
}

} // namespace Internal
} // namespace qbs
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2015 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 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.
 *
 ****************************************************************************/

/**
 * @file data_validator_group.cpp
 *
 * A data validation group to identify anomalies in data streams
 *
 * @author Lorenz Meier <lorenz@px4.io>
 */

#include "data_validator_group.h"
#include <ecl/ecl.h>

DataValidatorGroup::DataValidatorGroup(unsigned siblings) :
	_first(nullptr),
	_curr_best(-1),
	_prev_best(-1),
	_first_failover_time(0),
	_toggle_count(0)
{
	DataValidator *next = _first;

	for (unsigned i = 0; i < siblings; i++) {
		next = new DataValidator(next);
	}

	_first = next;
}

DataValidatorGroup::~DataValidatorGroup()
{

}

void
DataValidatorGroup::set_timeout(uint64_t timeout_interval_us)
{
	DataValidator *next = _first;

	while (next != nullptr) {
		next->set_timeout(timeout_interval_us);
		next = next->sibling();
	}
}

void
DataValidatorGroup::put(unsigned index, uint64_t timestamp, float val[3], uint64_t error_count, int priority)
{
	DataValidator *next = _first;
	unsigned i = 0;

	while (next != nullptr) {
		if (i == index) {
			next->put(timestamp, val, error_count, priority);
			break;
		}
		next = next->sibling();
		i++;
	}
}

float*
DataValidatorGroup::get_best(uint64_t timestamp, int *index)
{
	DataValidator *next = _first;

	// XXX This should eventually also include voting
	int pre_check_best = _curr_best;
	float pre_check_confidence = 1.0f;
	int pre_check_prio = -1;
	float max_confidence = -1.0f;
	int max_priority = -1000;
	int max_index = -1;
	DataValidator *best = nullptr;

	unsigned i = 0;

	while (next != nullptr) {
		float confidence = next->confidence(timestamp);

		if (i == pre_check_best) {
			pre_check_prio = next->priority();
			pre_check_confidence = confidence;
		}

		/*
		 * Switch if:
		 * 1) the confidence is higher and priority is equal or higher
		 * 2) the confidence is no less than 1% different and the priority is higher
		 */
		if (((max_confidence < MIN_REGULAR_CONFIDENCE) && (confidence >= MIN_REGULAR_CONFIDENCE)) ||
			(confidence > max_confidence && (next->priority() >= max_priority)) ||
			(fabsf(confidence - max_confidence) < 0.01f && (next->priority() > max_priority))
			) {
			max_index = i;
			max_confidence = confidence;
			max_priority = next->priority();
			best = next;
		}

		next = next->sibling();
		i++;
	}

	/* the current best sensor is not matching the previous best sensor */
	if (max_index != _curr_best) {

		bool true_failsafe = true;

		/* check wether the switch was a failsafe or preferring a higher priority sensor */
		if (pre_check_prio != -1 && pre_check_prio < max_priority &&
			fabsf(pre_check_confidence - max_confidence) < 0.1f) {
			/* this is not a failover */
			true_failsafe = false;
		}

		/* if we're no initialized, initialize the bookkeeping but do not count a failsafe */
		if (_curr_best < 0) {
			_prev_best = max_index;
		} else {
			/* we were initialized before, this is a real failsafe */
			_prev_best = pre_check_best;

			if (true_failsafe) {
				_toggle_count++;

				/* if this is the first time, log when we failed */
				if (_first_failover_time == 0) {
					_first_failover_time = timestamp;
				}
			}
		}

		/* for all cases we want to keep a record of the best index */
		_curr_best = max_index;
	}
	*index = max_index;
	return (best) ? best->value() : nullptr;
}

float
DataValidatorGroup::get_vibration_factor(uint64_t timestamp)
{
	DataValidator *next = _first;

	float vibe = 0.0f;

	/* find the best RMS value of a non-timed out sensor */
	while (next != nullptr) {

		if (next->confidence(timestamp) > 0.5f) {
			float* rms = next->rms();

			for (unsigned j = 0; j < 3; j++) {
				if (rms[j] > vibe) {
					vibe = rms[j];
				}
			}
		}

		next = next->sibling();
	}

	return vibe;
}

void
DataValidatorGroup::print()
{
	/* print the group's state */
	ECL_INFO("validator: best: %d, prev best: %d, failsafe: %s (# %u)",
		_curr_best, _prev_best, (_toggle_count > 0) ? "YES" : "NO",
		_toggle_count);

	DataValidator *next = _first;
	unsigned i = 0;

	while (next != nullptr) {
		if (next->used()) {
			ECL_INFO("sensor #%u, prio: %d", i, next->priority());
			next->print();
		}
		next = next->sibling();
		i++;
	}
}

unsigned
DataValidatorGroup::failover_count()
{
	return _toggle_count;
}
<commit_msg>Data validator: Fix compile warning on signedness<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2015 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 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.
 *
 ****************************************************************************/

/**
 * @file data_validator_group.cpp
 *
 * A data validation group to identify anomalies in data streams
 *
 * @author Lorenz Meier <lorenz@px4.io>
 */

#include "data_validator_group.h"
#include <ecl/ecl.h>

DataValidatorGroup::DataValidatorGroup(unsigned siblings) :
	_first(nullptr),
	_curr_best(-1),
	_prev_best(-1),
	_first_failover_time(0),
	_toggle_count(0)
{
	DataValidator *next = _first;

	for (unsigned i = 0; i < siblings; i++) {
		next = new DataValidator(next);
	}

	_first = next;
}

DataValidatorGroup::~DataValidatorGroup()
{

}

void
DataValidatorGroup::set_timeout(uint64_t timeout_interval_us)
{
	DataValidator *next = _first;

	while (next != nullptr) {
		next->set_timeout(timeout_interval_us);
		next = next->sibling();
	}
}

void
DataValidatorGroup::put(unsigned index, uint64_t timestamp, float val[3], uint64_t error_count, int priority)
{
	DataValidator *next = _first;
	unsigned i = 0;

	while (next != nullptr) {
		if (i == index) {
			next->put(timestamp, val, error_count, priority);
			break;
		}
		next = next->sibling();
		i++;
	}
}

float*
DataValidatorGroup::get_best(uint64_t timestamp, int *index)
{
	DataValidator *next = _first;

	// XXX This should eventually also include voting
	int pre_check_best = _curr_best;
	float pre_check_confidence = 1.0f;
	int pre_check_prio = -1;
	float max_confidence = -1.0f;
	int max_priority = -1000;
	int max_index = -1;
	DataValidator *best = nullptr;

	unsigned i = 0;

	while (next != nullptr) {
		float confidence = next->confidence(timestamp);

		if (static_cast<int>(i) == pre_check_best) {
			pre_check_prio = next->priority();
			pre_check_confidence = confidence;
		}

		/*
		 * Switch if:
		 * 1) the confidence is higher and priority is equal or higher
		 * 2) the confidence is no less than 1% different and the priority is higher
		 */
		if (((max_confidence < MIN_REGULAR_CONFIDENCE) && (confidence >= MIN_REGULAR_CONFIDENCE)) ||
			(confidence > max_confidence && (next->priority() >= max_priority)) ||
			(fabsf(confidence - max_confidence) < 0.01f && (next->priority() > max_priority))
			) {
			max_index = i;
			max_confidence = confidence;
			max_priority = next->priority();
			best = next;
		}

		next = next->sibling();
		i++;
	}

	/* the current best sensor is not matching the previous best sensor */
	if (max_index != _curr_best) {

		bool true_failsafe = true;

		/* check wether the switch was a failsafe or preferring a higher priority sensor */
		if (pre_check_prio != -1 && pre_check_prio < max_priority &&
			fabsf(pre_check_confidence - max_confidence) < 0.1f) {
			/* this is not a failover */
			true_failsafe = false;
		}

		/* if we're no initialized, initialize the bookkeeping but do not count a failsafe */
		if (_curr_best < 0) {
			_prev_best = max_index;
		} else {
			/* we were initialized before, this is a real failsafe */
			_prev_best = pre_check_best;

			if (true_failsafe) {
				_toggle_count++;

				/* if this is the first time, log when we failed */
				if (_first_failover_time == 0) {
					_first_failover_time = timestamp;
				}
			}
		}

		/* for all cases we want to keep a record of the best index */
		_curr_best = max_index;
	}
	*index = max_index;
	return (best) ? best->value() : nullptr;
}

float
DataValidatorGroup::get_vibration_factor(uint64_t timestamp)
{
	DataValidator *next = _first;

	float vibe = 0.0f;

	/* find the best RMS value of a non-timed out sensor */
	while (next != nullptr) {

		if (next->confidence(timestamp) > 0.5f) {
			float* rms = next->rms();

			for (unsigned j = 0; j < 3; j++) {
				if (rms[j] > vibe) {
					vibe = rms[j];
				}
			}
		}

		next = next->sibling();
	}

	return vibe;
}

void
DataValidatorGroup::print()
{
	/* print the group's state */
	ECL_INFO("validator: best: %d, prev best: %d, failsafe: %s (# %u)",
		_curr_best, _prev_best, (_toggle_count > 0) ? "YES" : "NO",
		_toggle_count);

	DataValidator *next = _first;
	unsigned i = 0;

	while (next != nullptr) {
		if (next->used()) {
			ECL_INFO("sensor #%u, prio: %d", i, next->priority());
			next->print();
		}
		next = next->sibling();
		i++;
	}
}

unsigned
DataValidatorGroup::failover_count()
{
	return _toggle_count;
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkExtractSelectedRows.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
/*-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/

#include "vtkExtractSelectedRows.h"

#include "vtkAnnotation.h"
#include "vtkAnnotationLayers.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkCommand.h"
#include "vtkConvertSelection.h"
#include "vtkDataArray.h"
#include "vtkEdgeListIterator.h"
#include "vtkEventForwarderCommand.h"
#include "vtkExtractSelection.h"
#include "vtkIdTypeArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPoints.h"
#include "vtkSelection.h"
#include "vtkSelectionNode.h"
#include "vtkSignedCharArray.h"
#include "vtkSmartPointer.h"
#include "vtkStringArray.h"
#include "vtkTable.h"
#include "vtkTree.h"
#include "vtkVertexListIterator.h"

#include <vtksys/stl/map>
#include <vtkstd/vector>

vtkCxxRevisionMacro(vtkExtractSelectedRows, "1.1");
vtkStandardNewMacro(vtkExtractSelectedRows);
//----------------------------------------------------------------------------
vtkExtractSelectedRows::vtkExtractSelectedRows()
{
  this->AddOriginalRowIdsArray = false;
  this->SetNumberOfInputPorts(3);
}

//----------------------------------------------------------------------------
vtkExtractSelectedRows::~vtkExtractSelectedRows()
{
}

//----------------------------------------------------------------------------
int vtkExtractSelectedRows::FillInputPortInformation(int port, vtkInformation* info)
{
  if (port == 0)
    {
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable");
    return 1;
    }
  else if (port == 1)
    {
    info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkSelection");
    return 1;
    }
  else if (port == 2)
    {
    info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkAnnotationLayers");
    return 1;
    }
  return 0;
}

//----------------------------------------------------------------------------
void vtkExtractSelectedRows::SetSelectionConnection(vtkAlgorithmOutput* in)
{
  this->SetInputConnection(1, in);
}

//----------------------------------------------------------------------------
void vtkExtractSelectedRows::SetAnnotationLayersConnection(vtkAlgorithmOutput* in)
{
  this->SetInputConnection(2, in);
}

//----------------------------------------------------------------------------
int vtkExtractSelectedRows::RequestData(
  vtkInformation* vtkNotUsed(request),
  vtkInformationVector** inputVector,
  vtkInformationVector* outputVector)
{
  vtkTable* input = vtkTable::GetData(inputVector[0]);
  vtkSelection* inputSelection = vtkSelection::GetData(inputVector[1]);
  vtkAnnotationLayers* inputAnnotations = vtkAnnotationLayers::GetData(inputVector[2]);
  vtkInformation* outInfo = outputVector->GetInformationObject(0);
  vtkTable* output = vtkTable::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));

  if(!inputSelection && !inputAnnotations)
    {
    vtkErrorMacro("No vtkSelection or vtkAnnotationLayers provided as input.");
    return 0;
    }

  vtkSmartPointer<vtkSelection> selection = vtkSmartPointer<vtkSelection>::New();
  int numSelections = 0;
  if(inputSelection)
    {
    selection->DeepCopy(inputSelection);
    numSelections++;
    }

  // If input annotations are provided, extract their selections only if
  // they are enabled and not hidden.
  if(inputAnnotations)
    {
    for(unsigned int i=0; i<inputAnnotations->GetNumberOfAnnotations(); ++i)
      {
      vtkAnnotation* a = inputAnnotations->GetAnnotation(i);
      if ((a->GetInformation()->Has(vtkAnnotation::ENABLE()) &&
          a->GetInformation()->Get(vtkAnnotation::ENABLE())==0) ||
          (a->GetInformation()->Has(vtkAnnotation::ENABLE()) &&
          a->GetInformation()->Get(vtkAnnotation::ENABLE())==1 &&
          a->GetInformation()->Has(vtkAnnotation::HIDE()) &&
          a->GetInformation()->Get(vtkAnnotation::HIDE())==0))
        {
        continue;
        }
      selection->Union(a->GetSelection());
      numSelections++;
      }
    }

  // Handle case where there was no input selection and no enabled, non-hidden
  // annotations
  if(numSelections == 0)
    {
    output->ShallowCopy(input);
    return 1;
    }

  // Convert the selection to an INDICES selection
  vtkSmartPointer<vtkSelection> converted;
  converted.TakeReference(vtkConvertSelection::ToSelectionType(
    selection, input, vtkSelectionNode::INDICES, 0, vtkSelectionNode::ROW));
  if (!converted.GetPointer())
    {
    vtkErrorMacro("Selection conversion to INDICES failed.");
    return 0;
    }

  vtkIdTypeArray* originalRowIds = vtkIdTypeArray::New();
  originalRowIds->SetName("vtkOriginalRowIds");

  output->GetRowData()->CopyStructure(input->GetRowData());
  for (unsigned int i = 0; i < converted->GetNumberOfNodes(); ++i)
    {
    vtkSelectionNode* node = converted->GetNode(i);
    if (node->GetFieldType() == vtkSelectionNode::ROW)
      {
      vtkIdTypeArray* list = vtkIdTypeArray::SafeDownCast(node->GetSelectionList());
      if (list)
        {
        vtkIdType numTuples = list->GetNumberOfTuples();
        for (vtkIdType j = 0; j < numTuples; ++j)
          {
          vtkIdType val = list->GetValue(j);
          output->InsertNextRow(input->GetRow(val));
          if (this->AddOriginalRowIdsArray)
            {
            originalRowIds->InsertNextValue(val);
            }
          }
        }
      }
    }
  if (this->AddOriginalRowIdsArray)
    {
    output->AddColumn(originalRowIds);
    }
  originalRowIds->Delete();
  return 1;
}

//----------------------------------------------------------------------------
void vtkExtractSelectedRows::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "AddOriginalRowIdsArray: " << this->AddOriginalRowIdsArray <<
    endl;
}
<commit_msg>BUG: don't segfault when trying to select from a vtkTable with 0 rows<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkExtractSelectedRows.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
/*-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/

#include "vtkExtractSelectedRows.h"

#include "vtkAnnotation.h"
#include "vtkAnnotationLayers.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkCommand.h"
#include "vtkConvertSelection.h"
#include "vtkDataArray.h"
#include "vtkEdgeListIterator.h"
#include "vtkEventForwarderCommand.h"
#include "vtkExtractSelection.h"
#include "vtkIdTypeArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPoints.h"
#include "vtkSelection.h"
#include "vtkSelectionNode.h"
#include "vtkSignedCharArray.h"
#include "vtkSmartPointer.h"
#include "vtkStringArray.h"
#include "vtkTable.h"
#include "vtkTree.h"
#include "vtkVertexListIterator.h"

#include <vtksys/stl/map>
#include <vtkstd/vector>

vtkCxxRevisionMacro(vtkExtractSelectedRows, "1.2");
vtkStandardNewMacro(vtkExtractSelectedRows);
//----------------------------------------------------------------------------
vtkExtractSelectedRows::vtkExtractSelectedRows()
{
  this->AddOriginalRowIdsArray = false;
  this->SetNumberOfInputPorts(3);
}

//----------------------------------------------------------------------------
vtkExtractSelectedRows::~vtkExtractSelectedRows()
{
}

//----------------------------------------------------------------------------
int vtkExtractSelectedRows::FillInputPortInformation(int port, vtkInformation* info)
{
  if (port == 0)
    {
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable");
    return 1;
    }
  else if (port == 1)
    {
    info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkSelection");
    return 1;
    }
  else if (port == 2)
    {
    info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkAnnotationLayers");
    return 1;
    }
  return 0;
}

//----------------------------------------------------------------------------
void vtkExtractSelectedRows::SetSelectionConnection(vtkAlgorithmOutput* in)
{
  this->SetInputConnection(1, in);
}

//----------------------------------------------------------------------------
void vtkExtractSelectedRows::SetAnnotationLayersConnection(vtkAlgorithmOutput* in)
{
  this->SetInputConnection(2, in);
}

//----------------------------------------------------------------------------
int vtkExtractSelectedRows::RequestData(
  vtkInformation* vtkNotUsed(request),
  vtkInformationVector** inputVector,
  vtkInformationVector* outputVector)
{
  vtkTable* input = vtkTable::GetData(inputVector[0]);
  vtkSelection* inputSelection = vtkSelection::GetData(inputVector[1]);
  vtkAnnotationLayers* inputAnnotations = vtkAnnotationLayers::GetData(inputVector[2]);
  vtkInformation* outInfo = outputVector->GetInformationObject(0);
  vtkTable* output = vtkTable::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));

  if(!inputSelection && !inputAnnotations)
    {
    vtkErrorMacro("No vtkSelection or vtkAnnotationLayers provided as input.");
    return 0;
    }

  vtkSmartPointer<vtkSelection> selection = vtkSmartPointer<vtkSelection>::New();
  int numSelections = 0;
  if(inputSelection)
    {
    selection->DeepCopy(inputSelection);
    numSelections++;
    }

  // If input annotations are provided, extract their selections only if
  // they are enabled and not hidden.
  if(inputAnnotations)
    {
    for(unsigned int i=0; i<inputAnnotations->GetNumberOfAnnotations(); ++i)
      {
      vtkAnnotation* a = inputAnnotations->GetAnnotation(i);
      if ((a->GetInformation()->Has(vtkAnnotation::ENABLE()) &&
          a->GetInformation()->Get(vtkAnnotation::ENABLE())==0) ||
          (a->GetInformation()->Has(vtkAnnotation::ENABLE()) &&
          a->GetInformation()->Get(vtkAnnotation::ENABLE())==1 &&
          a->GetInformation()->Has(vtkAnnotation::HIDE()) &&
          a->GetInformation()->Get(vtkAnnotation::HIDE())==0))
        {
        continue;
        }
      selection->Union(a->GetSelection());
      numSelections++;
      }
    }

  // Handle case where there was no input selection and no enabled, non-hidden
  // annotations
  if(numSelections == 0)
    {
    output->ShallowCopy(input);
    return 1;
    }

  // Convert the selection to an INDICES selection
  vtkSmartPointer<vtkSelection> converted;
  converted.TakeReference(vtkConvertSelection::ToSelectionType(
    selection, input, vtkSelectionNode::INDICES, 0, vtkSelectionNode::ROW));
  if (!converted.GetPointer())
    {
    vtkErrorMacro("Selection conversion to INDICES failed.");
    return 0;
    }

  vtkIdTypeArray* originalRowIds = vtkIdTypeArray::New();
  originalRowIds->SetName("vtkOriginalRowIds");

  output->GetRowData()->CopyStructure(input->GetRowData());

  //dodge segfault on empty tables
  if(converted->GetNumberOfNodes() > input->GetNumberOfRows())
    {
    vtkErrorMacro("Attempting to select more rows than the table contains.");
    return 0;
    }

  for (unsigned int i = 0; i < converted->GetNumberOfNodes(); ++i)
    {
    vtkSelectionNode* node = converted->GetNode(i);
    if (node->GetFieldType() == vtkSelectionNode::ROW)
      {
      vtkIdTypeArray* list = vtkIdTypeArray::SafeDownCast(node->GetSelectionList());
      if (list)
        {
        vtkIdType numTuples = list->GetNumberOfTuples();
        for (vtkIdType j = 0; j < numTuples; ++j)
          {
          vtkIdType val = list->GetValue(j);
          output->InsertNextRow(input->GetRow(val));
          if (this->AddOriginalRowIdsArray)
            {
            originalRowIds->InsertNextValue(val);
            }
          }
        }
      }
    }
  if (this->AddOriginalRowIdsArray)
    {
    output->AddColumn(originalRowIds);
    }
  originalRowIds->Delete();
  return 1;
}

//----------------------------------------------------------------------------
void vtkExtractSelectedRows::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "AddOriginalRowIdsArray: " << this->AddOriginalRowIdsArray <<
    endl;
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Adam Grandquist

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 */
/**
 * @author Adam Grandquist
 * @copyright Apache
 */

#include "ReQL-expr.hpp"

#include "ReQL.hpp"

#include <limits>

namespace ReQL {

Expr::Expr() {
  Query _val = expr(_reql_new_null());
  sub_query.push_back(_val);
  query = _reql_new_datum(_val.query);
}

Expr::Expr(_ReQL_Op val) {
  query = val;
}

Expr::Expr(std::string val) {
  Query _val = expr(_reql_new_string(val));
  sub_query.push_back(_val);
  query = _reql_new_datum(_val.query);
}

Expr::Expr(double val) {
  Query _val = expr(_reql_new_number(val));
  sub_query.push_back(_val);
  query = _reql_new_datum(_val.query);
}

Expr::Expr(bool val) {
  Query _val = expr(_reql_new_bool(val));
  sub_query.push_back(_val);
  query = _reql_new_datum(_val.query);
}

Expr::Expr(std::vector<Query> val) {
  if (val.size() > std::numeric_limits<std::uint32_t>::max()) {
    throw;
  }

  sub_query.assign(val.begin(), val.end());

  Query _val = expr(_reql_new_array(static_cast<std::uint32_t>(val.size())));

  sub_query.push_back(_val);

  for (auto iter=val.cbegin(); iter!=val.cend(); ++iter) {
    _reql_array_append(_val.query, iter->query);
  }

  query = _reql_new_make_array(_val.query);
}

Expr::Expr(std::map<std::string, Query> val) {
  if (val.size() > std::numeric_limits<std::uint32_t>::max()) {
    throw;
  }

  Query _val = expr(_reql_new_object(static_cast<std::uint32_t>(val.size())));

  sub_query.push_back(_val);

  for (auto iter=val.cbegin(); iter!=val.cend(); ++iter) {
    Query key(iter->first);
    sub_query.push_back(key);
    sub_query.push_back(iter->second);
    _reql_object_add(_val.query, key.query, iter->second.query);
  }

  query = _reql_new_make_obj(_val.query);
}

Expr::~Expr() {
  delete query;
}

Query expr() {
  return Query();
}

Query expr(_ReQL_Op val) {
  return Query(val);
}

Query expr(std::string val) {
  return Query(val);
}

Query expr(double val) {
  return Query(val);
}

Query expr(bool val) {
  return Query(val);
}

Query expr(std::vector<Query> val) {
  return Query(val);
}

Query expr(std::map<std::string, Query> val) {
  return Query(val);
}

}
<commit_msg>Catch and delete values that don't get owned properly.<commit_after>/*
Copyright 2014 Adam Grandquist

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 */
/**
 * @author Adam Grandquist
 * @copyright Apache
 */

#include "ReQL-expr.hpp"

#include "ReQL.hpp"

#include <limits>

namespace ReQL {

Expr::Expr() {
  Query _val = expr(_reql_new_null());
  sub_query.push_back(_val);
  query = _reql_new_datum(_val.query);
}

Expr::Expr(_ReQL_Op val) {
  query = val;
}

Expr::Expr(std::string val) {
  Query _val = expr(_reql_new_string(val));
  sub_query.push_back(_val);
  query = _reql_new_datum(_val.query);
}

Expr::Expr(double val) {
  Query _val = expr(_reql_new_number(val));
  sub_query.push_back(_val);
  query = _reql_new_datum(_val.query);
}

Expr::Expr(bool val) {
  Query _val = expr(_reql_new_bool(val));
  sub_query.push_back(_val);
  query = _reql_new_datum(_val.query);
}

Expr::Expr(std::vector<Query> val) {
  if (val.size() > std::numeric_limits<std::uint32_t>::max()) {
    throw;
  }

  sub_query.assign(val.begin(), val.end());

  Query _val = expr(_reql_new_array(static_cast<std::uint32_t>(val.size())));

  sub_query.push_back(_val);

  for (auto iter=val.cbegin(); iter!=val.cend(); ++iter) {
    _reql_array_append(_val.query, iter->query);
  }

  query = _reql_new_make_array(_val.query);
}

Expr::Expr(std::map<std::string, Query> val) {
  if (val.size() > std::numeric_limits<std::uint32_t>::max()) {
    throw;
  }

  Query _val = expr(_reql_new_object(static_cast<std::uint32_t>(val.size())));

  sub_query.push_back(_val);

  for (auto iter=val.cbegin(); iter!=val.cend(); ++iter) {
    Query key(iter->first);
    sub_query.push_back(key);
    sub_query.push_back(iter->second);
    _reql_object_add(_val.query, key.query, iter->second.query);
  }

  query = _reql_new_make_obj(_val.query);
}

Expr::~Expr() {
  switch (_reql_datum_type(query)) {
    case _REQL_R_ARRAY: {
      delete [] query->obj.datum.json.array.arr;
      break;
    }
    case _REQL_R_OBJECT: {
      delete [] query->obj.datum.json.object.pair;
      break;
    }
    default:
      break;
  }
  delete query;
}

Query expr() {
  return Query();
}

Query expr(_ReQL_Op val) {
  return Query(val);
}

Query expr(std::string val) {
  return Query(val);
}

Query expr(double val) {
  return Query(val);
}

Query expr(bool val) {
  return Query(val);
}

Query expr(std::vector<Query> val) {
  return Query(val);
}

Query expr(std::map<std::string, Query> val) {
  return Query(val);
}

}
<|endoftext|>


<commit_before>#include "SoapyAudio.hpp"

#ifdef USE_HAMLIB
RigThread::RigThread() {
    terminated.store(true);
}

RigThread::~RigThread() {

}

#ifdef __APPLE__
void *RigThread::threadMain() {
    terminated.store(false);
    run();
    return this;
};

void *RigThread::pthread_helper(void *context) {
    return ((RigThread *) context)->threadMain();
};
#else
void RigThread::threadMain() {
    terminated.store(false);
    run();
};
#endif

void RigThread::setup(rig_model_t rig_model, std::string rig_file, int serial_rate) {
    rigModel = rig_model;
    rigFile = rig_file;
    serialRate = serial_rate;
};

void RigThread::run() {
    int retcode, status;

    SoapySDR_log(SOAPY_SDR_DEBUG, "Rig thread starting.");

    rig = rig_init(rigModel);
	strncpy(rig->state.rigport.pathname, rigFile.c_str(), FILPATHLEN - 1);
	rig->state.rigport.parm.serial.rate = serialRate;
	retcode = rig_open(rig);
	char *info_buf = (char *)rig_get_info(rig);
    SoapySDR_logf(SOAPY_SDR_DEBUG, "Rig Info: %s", info_buf);

    while (!terminated.load()) {
        std::this_thread::sleep_for(std::chrono::milliseconds(150));
        if (freqChanged.load()) {
            status = rig_get_freq(rig, RIG_VFO_CURR, &freq);
            if (freq != newFreq) {
                freq = newFreq;
                rig_set_freq(rig, RIG_VFO_CURR, freq);
                SoapySDR_logf(SOAPY_SDR_DEBUG, "Set Rig Freq: %f", newFreq);
            }

            freqChanged.store(false);
        } else {
            status = rig_get_freq(rig, RIG_VFO_CURR, &freq);
        }

        SoapySDR_logf(SOAPY_SDR_DEBUG, "Rig Freq: %f", freq);
    }

    rig_close(rig);

    SoapySDR_log(SOAPY_SDR_DEBUG, "Rig thread exiting.");
};

freq_t RigThread::getFrequency() {
    if (freqChanged.load()) {
        return newFreq;
    } else {
        return freq;
    }
}

void RigThread::setFrequency(freq_t new_freq) {
    newFreq = new_freq;
    freqChanged.store(true);
}

void RigThread::terminate() {
    terminated.store(true);
};

bool RigThread::isTerminated() {
    return terminated.load();
}
#endif<commit_msg>Missing rig_cleanup.<commit_after>#include "SoapyAudio.hpp"

#ifdef USE_HAMLIB
RigThread::RigThread() {
    terminated.store(true);
}

RigThread::~RigThread() {

}

#ifdef __APPLE__
void *RigThread::threadMain() {
    terminated.store(false);
    run();
    return this;
};

void *RigThread::pthread_helper(void *context) {
    return ((RigThread *) context)->threadMain();
};
#else
void RigThread::threadMain() {
    terminated.store(false);
    run();
};
#endif

void RigThread::setup(rig_model_t rig_model, std::string rig_file, int serial_rate) {
    rigModel = rig_model;
    rigFile = rig_file;
    serialRate = serial_rate;
};

void RigThread::run() {
    int retcode, status;

    SoapySDR_log(SOAPY_SDR_DEBUG, "Rig thread starting.");

    rig = rig_init(rigModel);
	strncpy(rig->state.rigport.pathname, rigFile.c_str(), FILPATHLEN - 1);
	rig->state.rigport.parm.serial.rate = serialRate;
	retcode = rig_open(rig);
	char *info_buf = (char *)rig_get_info(rig);
    SoapySDR_logf(SOAPY_SDR_DEBUG, "Rig Info: %s", info_buf);

    while (!terminated.load()) {
        std::this_thread::sleep_for(std::chrono::milliseconds(150));
        if (freqChanged.load()) {
            status = rig_get_freq(rig, RIG_VFO_CURR, &freq);
            if (freq != newFreq) {
                freq = newFreq;
                rig_set_freq(rig, RIG_VFO_CURR, freq);
                SoapySDR_logf(SOAPY_SDR_DEBUG, "Set Rig Freq: %f", newFreq);
            }

            freqChanged.store(false);
        } else {
            status = rig_get_freq(rig, RIG_VFO_CURR, &freq);
        }

        SoapySDR_logf(SOAPY_SDR_DEBUG, "Rig Freq: %f", freq);
    }

    rig_close(rig);
    rig_cleanup(rig);

    SoapySDR_log(SOAPY_SDR_DEBUG, "Rig thread exiting.");
};

freq_t RigThread::getFrequency() {
    if (freqChanged.load()) {
        return newFreq;
    } else {
        return freq;
    }
}

void RigThread::setFrequency(freq_t new_freq) {
    newFreq = new_freq;
    freqChanged.store(true);
}

void RigThread::terminate() {
    terminated.store(true);
};

bool RigThread::isTerminated() {
    return terminated.load();
}
#endif<|endoftext|>


<commit_before>//
//  Decoder.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 30/12/20.
//  Copyright © 2020 Thomas Harte. All rights reserved.
//

#ifndef InstructionSets_PowerPC_Decoder_hpp
#define InstructionSets_PowerPC_Decoder_hpp

#include "Instruction.hpp"

namespace InstructionSet {
namespace PowerPC {

enum class Model {
	/// i.e. 32-bit, with POWER carry-over instructions.
	MPC601,
	/// i.e. 32-bit, no POWER instructions.
	MPC603,
	/// i.e. 64-bit.
	MPC620,
};

constexpr bool is64bit(Model model) {
	return model == Model::MPC620;
}

constexpr bool is32bit(Model model) {
	return !is64bit(model);
}

constexpr bool is601(Model model) {
	return model == Model::MPC601;
}

/*!
	Implements PowerPC instruction decoding.

	@c model Indicates the instruction set to decode.

	@c validate_reserved_bits If set to @c true, check that all
	reserved bits are 0 and produce an invalid opcode if not. Otherwise does no
	inspection of reserved bits.

	TODO: determine what specific models of PowerPC do re: reserved bits.
*/
template <Model model, bool validate_reserved_bits = false> struct Decoder {
	Instruction decode(uint32_t opcode);
};

}
}

#endif /* InstructionSets_PowerPC_Decoder_hpp */
<commit_msg>Improve accuracy of comment.<commit_after>//
//  Decoder.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 30/12/20.
//  Copyright © 2020 Thomas Harte. All rights reserved.
//

#ifndef InstructionSets_PowerPC_Decoder_hpp
#define InstructionSets_PowerPC_Decoder_hpp

#include "Instruction.hpp"

namespace InstructionSet {
namespace PowerPC {

enum class Model {
	/// i.e. 32-bit, with POWER carry-over instructions.
	MPC601,
	/// i.e. 32-bit, no POWER instructions.
	MPC603,
	/// i.e. 64-bit.
	MPC620,
};

constexpr bool is64bit(Model model) {
	return model == Model::MPC620;
}

constexpr bool is32bit(Model model) {
	return !is64bit(model);
}

constexpr bool is601(Model model) {
	return model == Model::MPC601;
}

/*!
	Implements PowerPC instruction decoding.

	@c model Indicates the instruction set to decode.

	@c validate_reserved_bits If set to @c true, check that all
	reserved bits are 0 or 1 as required and produce an invalid opcode if not.
	Otherwise does no inspection of reserved bits.

	TODO: determine what specific models of PowerPC do re: reserved bits.
*/
template <Model model, bool validate_reserved_bits = false> struct Decoder {
	Instruction decode(uint32_t opcode);
};

}
}

#endif /* InstructionSets_PowerPC_Decoder_hpp */
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkPathPriv.h"
#include "SkRecords.h"

namespace SkRecords {
    PreCachedPath::PreCachedPath(const SkPath& path) : SkPath(path) {
        this->updateBoundsCache();
#if 0  // Disabled to see if we ever really race on this.  It costs time, chromium:496982.
        SkPathPriv::FirstDirection junk;
        (void)SkPathPriv::CheapComputeFirstDirection(*this, &junk);
#endif
    }

    TypedMatrix::TypedMatrix(const SkMatrix& matrix) : SkMatrix(matrix) {
        (void)this->getType();
    }
}
<commit_msg>Pre-cache SkPath's genID in PreCachedPath too<commit_after>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkPathPriv.h"
#include "SkRecords.h"

namespace SkRecords {
    PreCachedPath::PreCachedPath(const SkPath& path) : SkPath(path) {
        this->updateBoundsCache();
        (void)this->getGenerationID();
#if 0  // Disabled to see if we ever really race on this.  It costs time, chromium:496982.
        SkPathPriv::FirstDirection junk;
        (void)SkPathPriv::CheapComputeFirstDirection(*this, &junk);
#endif
    }

    TypedMatrix::TypedMatrix(const SkMatrix& matrix) : SkMatrix(matrix) {
        (void)this->getType();
    }
}
<|endoftext|>