<commit_before>/*
 *
 * Copyright 2014, Google Inc.
 * 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 Google Inc. 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 <chrono>
#include <thread>

#include "test/core/util/test_config.h"
#include "test/cpp/util/echo_duplicate.pb.h"
#include "test/cpp/util/echo.pb.h"
#include "src/cpp/util/time.h"
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/status.h>
#include <grpc++/stream.h>
#include "test/core/util/port.h"
#include <gtest/gtest.h>

#include <grpc/grpc.h>
#include <grpc/support/thd.h>
#include <grpc/support/time.h>

using grpc::cpp::test::util::EchoRequest;
using grpc::cpp::test::util::EchoResponse;
using std::chrono::system_clock;

namespace grpc {
namespace testing {

namespace {

// When echo_deadline is requested, deadline seen in the ServerContext is set in
// the response in seconds.
void MaybeEchoDeadline(ServerContext* context, const EchoRequest* request,
                       EchoResponse* response) {
  if (request->has_param() && request->param().echo_deadline()) {
    gpr_timespec deadline = gpr_inf_future;
    if (context->absolute_deadline() != system_clock::time_point::max()) {
      Timepoint2Timespec(context->absolute_deadline(), &deadline);
    }
    response->mutable_param()->set_request_deadline(deadline.tv_sec);
  }
}
}  // namespace

class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
 public:
  Status Echo(ServerContext* context, const EchoRequest* request,
              EchoResponse* response) override {
    response->set_message(request->message());
    MaybeEchoDeadline(context, request, response);
    return Status::OK;
  }

  // Unimplemented is left unimplemented to test the returned error.

  Status RequestStream(ServerContext* context,
                       ServerReader<EchoRequest>* reader,
                       EchoResponse* response) override {
    EchoRequest request;
    response->set_message("");
    while (reader->Read(&request)) {
      response->mutable_message()->append(request.message());
    }
    return Status::OK;
  }

  // Return 3 messages.
  // TODO(yangg) make it generic by adding a parameter into EchoRequest
  Status ResponseStream(ServerContext* context, const EchoRequest* request,
                        ServerWriter<EchoResponse>* writer) override {
    EchoResponse response;
    response.set_message(request->message() + "0");
    writer->Write(response);
    response.set_message(request->message() + "1");
    writer->Write(response);
    response.set_message(request->message() + "2");
    writer->Write(response);

    return Status::OK;
  }

  Status BidiStream(
      ServerContext* context,
      ServerReaderWriter<EchoResponse, EchoRequest>* stream) override {
    EchoRequest request;
    EchoResponse response;
    while (stream->Read(&request)) {
      gpr_log(GPR_INFO, "recv msg %s", request.message().c_str());
      response.set_message(request.message());
      stream->Write(response);
    }
    return Status::OK;
  }
};

class TestServiceImplDupPkg
    : public ::grpc::cpp::test::util::duplicate::TestService::Service {
 public:
  Status Echo(ServerContext* context, const EchoRequest* request,
              EchoResponse* response) override {
    response->set_message("no package");
    return Status::OK;
  }
};

class End2endTest : public ::testing::Test {
 protected:
  void SetUp() override {
    int port = grpc_pick_unused_port_or_die();
    server_address_ << "localhost:" << port;
    // Setup server
    ServerBuilder builder;
    builder.AddPort(server_address_.str());
    builder.RegisterService(&service_);
    builder.RegisterService(&dup_pkg_service_);
    server_ = builder.BuildAndStart();
  }

  void TearDown() override { server_->Shutdown(); }

  void ResetStub() {
    std::shared_ptr<ChannelInterface> channel =
        CreateChannel(server_address_.str(), ChannelArguments());
    stub_.reset(grpc::cpp::test::util::TestService::NewStub(channel));
  }

  std::unique_ptr<grpc::cpp::test::util::TestService::Stub> stub_;
  std::unique_ptr<Server> server_;
  std::ostringstream server_address_;
  TestServiceImpl service_;
  TestServiceImplDupPkg dup_pkg_service_;
};

static void SendRpc(grpc::cpp::test::util::TestService::Stub* stub,
                    int num_rpcs) {
  EchoRequest request;
  EchoResponse response;
  request.set_message("Hello");

  for (int i = 0; i < num_rpcs; ++i) {
    ClientContext context;
    Status s = stub->Echo(&context, request, &response);
    EXPECT_EQ(response.message(), request.message());
    EXPECT_TRUE(s.IsOk());
  }
}

TEST_F(End2endTest, SimpleRpc) {
  ResetStub();
  SendRpc(stub_.get(), 1);
}

TEST_F(End2endTest, MultipleRpcs) {
  ResetStub();
  std::vector<std::thread*> threads;
  for (int i = 0; i < 10; ++i) {
    threads.push_back(new std::thread(SendRpc, stub_.get(), 10));
  }
  for (int i = 0; i < 10; ++i) {
    threads[i]->join();
    delete threads[i];
  }
}

// Set a 10us deadline and make sure proper error is returned.
TEST_F(End2endTest, RpcDeadlineExpires) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  request.set_message("Hello");

  ClientContext context;
  std::chrono::system_clock::time_point deadline =
      std::chrono::system_clock::now() + std::chrono::microseconds(10);
  context.set_absolute_deadline(deadline);
  Status s = stub_->Echo(&context, request, &response);
  EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, s.code());
}

// Set a long but finite deadline.
TEST_F(End2endTest, RpcLongDeadline) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  request.set_message("Hello");

  ClientContext context;
  std::chrono::system_clock::time_point deadline =
      std::chrono::system_clock::now() + std::chrono::hours(1);
  context.set_absolute_deadline(deadline);
  Status s = stub_->Echo(&context, request, &response);
  EXPECT_EQ(response.message(), request.message());
  EXPECT_TRUE(s.IsOk());
}

// Ask server to echo back the deadline it sees.
TEST_F(End2endTest, EchoDeadline) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  request.set_message("Hello");
  request.mutable_param()->set_echo_deadline(true);

  ClientContext context;
  std::chrono::system_clock::time_point deadline =
      std::chrono::system_clock::now() + std::chrono::seconds(100);
  context.set_absolute_deadline(deadline);
  Status s = stub_->Echo(&context, request, &response);
  EXPECT_EQ(response.message(), request.message());
  EXPECT_TRUE(s.IsOk());
  gpr_timespec sent_deadline;
  Timepoint2Timespec(deadline, &sent_deadline);
  // Allow 1 second error.
  EXPECT_LE(response.param().request_deadline() - sent_deadline.tv_sec, 1);
  EXPECT_GE(response.param().request_deadline() - sent_deadline.tv_sec, -1);
}

// Ask server to echo back the deadline it sees. The rpc has no deadline.
TEST_F(End2endTest, EchoDeadlineForNoDeadlineRpc) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  request.set_message("Hello");
  request.mutable_param()->set_echo_deadline(true);

  ClientContext context;
  Status s = stub_->Echo(&context, request, &response);
  EXPECT_EQ(response.message(), request.message());
  EXPECT_TRUE(s.IsOk());
  EXPECT_EQ(response.param().request_deadline(), gpr_inf_future.tv_sec);
}

TEST_F(End2endTest, UnimplementedRpc) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  request.set_message("Hello");

  ClientContext context;
  Status s = stub_->Unimplemented(&context, request, &response);
  EXPECT_FALSE(s.IsOk());
  EXPECT_EQ(s.code(), grpc::StatusCode::UNIMPLEMENTED);
  EXPECT_EQ(s.details(), "");
  EXPECT_EQ(response.message(), "");
}

TEST_F(End2endTest, RequestStreamOneRequest) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  ClientContext context;

  ClientWriter<EchoRequest>* stream = stub_->RequestStream(&context, &response);
  request.set_message("hello");
  EXPECT_TRUE(stream->Write(request));
  stream->WritesDone();
  Status s = stream->Finish();
  EXPECT_EQ(response.message(), request.message());
  EXPECT_TRUE(s.IsOk());

  delete stream;
}

TEST_F(End2endTest, RequestStreamTwoRequests) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  ClientContext context;

  ClientWriter<EchoRequest>* stream = stub_->RequestStream(&context, &response);
  request.set_message("hello");
  EXPECT_TRUE(stream->Write(request));
  EXPECT_TRUE(stream->Write(request));
  stream->WritesDone();
  Status s = stream->Finish();
  EXPECT_EQ(response.message(), "hellohello");
  EXPECT_TRUE(s.IsOk());

  delete stream;
}

TEST_F(End2endTest, ResponseStream) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  ClientContext context;
  request.set_message("hello");

  ClientReader<EchoResponse>* stream =
      stub_->ResponseStream(&context, &request);
  EXPECT_TRUE(stream->Read(&response));
  EXPECT_EQ(response.message(), request.message() + "0");
  EXPECT_TRUE(stream->Read(&response));
  EXPECT_EQ(response.message(), request.message() + "1");
  EXPECT_TRUE(stream->Read(&response));
  EXPECT_EQ(response.message(), request.message() + "2");
  EXPECT_FALSE(stream->Read(&response));

  Status s = stream->Finish();
  EXPECT_TRUE(s.IsOk());

  delete stream;
}

TEST_F(End2endTest, BidiStream) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  ClientContext context;
  grpc::string msg("hello");

  ClientReaderWriter<EchoRequest, EchoResponse>* stream =
      stub_->BidiStream(&context);

  request.set_message(msg + "0");
  EXPECT_TRUE(stream->Write(request));
  EXPECT_TRUE(stream->Read(&response));
  EXPECT_EQ(response.message(), request.message());

  request.set_message(msg + "1");
  EXPECT_TRUE(stream->Write(request));
  EXPECT_TRUE(stream->Read(&response));
  EXPECT_EQ(response.message(), request.message());

  request.set_message(msg + "2");
  EXPECT_TRUE(stream->Write(request));
  EXPECT_TRUE(stream->Read(&response));
  EXPECT_EQ(response.message(), request.message());

  stream->WritesDone();
  EXPECT_FALSE(stream->Read(&response));

  Status s = stream->Finish();
  EXPECT_TRUE(s.IsOk());

  delete stream;
}

// Talk to the two services with the same name but different package names.
// The two stubs are created on the same channel.
TEST_F(End2endTest, DiffPackageServices) {
  std::shared_ptr<ChannelInterface> channel =
      CreateChannel(server_address_.str(), ChannelArguments());

  EchoRequest request;
  EchoResponse response;
  request.set_message("Hello");

  std::unique_ptr<grpc::cpp::test::util::TestService::Stub> stub(
      grpc::cpp::test::util::TestService::NewStub(channel));
  ClientContext context;
  Status s = stub->Echo(&context, request, &response);
  EXPECT_EQ(response.message(), request.message());
  EXPECT_TRUE(s.IsOk());

  std::unique_ptr<grpc::cpp::test::util::duplicate::TestService::Stub>
      dup_pkg_stub(
          grpc::cpp::test::util::duplicate::TestService::NewStub(channel));
  ClientContext context2;
  s = dup_pkg_stub->Echo(&context2, request, &response);
  EXPECT_EQ("no package", response.message());
  EXPECT_TRUE(s.IsOk());
}

// rpc and stream should fail on bad credentials.
TEST_F(End2endTest, BadCredentials) {
  std::unique_ptr<Credentials> bad_creds =
      CredentialsFactory::ServiceAccountCredentials("", "",
                                                    std::chrono::seconds(1));
  EXPECT_EQ(nullptr, bad_creds.get());
  std::shared_ptr<ChannelInterface> channel =
      CreateChannel(server_address_.str(), bad_creds, ChannelArguments());
  std::unique_ptr<grpc::cpp::test::util::TestService::Stub> stub(
      grpc::cpp::test::util::TestService::NewStub(channel));
  EchoRequest request;
  EchoResponse response;
  ClientContext context;
  grpc::string msg("hello");

  Status s = stub->Echo(&context, request, &response);
  EXPECT_EQ("", response.message());
  EXPECT_FALSE(s.IsOk());
  EXPECT_EQ(StatusCode::UNKNOWN, s.code());
  EXPECT_EQ("Rpc sent on a lame channel.", s.details());

  ClientContext context2;
  ClientReaderWriter<EchoRequest, EchoResponse>* stream =
      stub->BidiStream(&context2);
  s = stream->Finish();
  EXPECT_FALSE(s.IsOk());
  EXPECT_EQ(StatusCode::UNKNOWN, s.code());
  EXPECT_EQ("Rpc sent on a lame channel.", s.details());

  delete stream;
}

}  // namespace testing
}  // namespace grpc

int main(int argc, char** argv) {
  grpc_test_init(argc, argv);
  grpc_init();
  ::testing::InitGoogleTest(&argc, argv);
  int result = RUN_ALL_TESTS();
  grpc_shutdown();
  return result;
}
<commit_msg>Make end2end_test use fewer threads<commit_after>/*
 *
 * Copyright 2014, Google Inc.
 * 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 Google Inc. 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 <chrono>
#include <thread>

#include "test/core/util/test_config.h"
#include "test/cpp/util/echo_duplicate.pb.h"
#include "test/cpp/util/echo.pb.h"
#include "src/cpp/util/time.h"
#include "src/cpp/server/thread_pool.h"
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/status.h>
#include <grpc++/stream.h>
#include "test/core/util/port.h"
#include <gtest/gtest.h>

#include <grpc/grpc.h>
#include <grpc/support/thd.h>
#include <grpc/support/time.h>

using grpc::cpp::test::util::EchoRequest;
using grpc::cpp::test::util::EchoResponse;
using std::chrono::system_clock;

namespace grpc {
namespace testing {

namespace {

// When echo_deadline is requested, deadline seen in the ServerContext is set in
// the response in seconds.
void MaybeEchoDeadline(ServerContext* context, const EchoRequest* request,
                       EchoResponse* response) {
  if (request->has_param() && request->param().echo_deadline()) {
    gpr_timespec deadline = gpr_inf_future;
    if (context->absolute_deadline() != system_clock::time_point::max()) {
      Timepoint2Timespec(context->absolute_deadline(), &deadline);
    }
    response->mutable_param()->set_request_deadline(deadline.tv_sec);
  }
}

}  // namespace

class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
 public:
  Status Echo(ServerContext* context, const EchoRequest* request,
              EchoResponse* response) override {
    response->set_message(request->message());
    MaybeEchoDeadline(context, request, response);
    return Status::OK;
  }

  // Unimplemented is left unimplemented to test the returned error.

  Status RequestStream(ServerContext* context,
                       ServerReader<EchoRequest>* reader,
                       EchoResponse* response) override {
    EchoRequest request;
    response->set_message("");
    while (reader->Read(&request)) {
      response->mutable_message()->append(request.message());
    }
    return Status::OK;
  }

  // Return 3 messages.
  // TODO(yangg) make it generic by adding a parameter into EchoRequest
  Status ResponseStream(ServerContext* context, const EchoRequest* request,
                        ServerWriter<EchoResponse>* writer) override {
    EchoResponse response;
    response.set_message(request->message() + "0");
    writer->Write(response);
    response.set_message(request->message() + "1");
    writer->Write(response);
    response.set_message(request->message() + "2");
    writer->Write(response);

    return Status::OK;
  }

  Status BidiStream(
      ServerContext* context,
      ServerReaderWriter<EchoResponse, EchoRequest>* stream) override {
    EchoRequest request;
    EchoResponse response;
    while (stream->Read(&request)) {
      gpr_log(GPR_INFO, "recv msg %s", request.message().c_str());
      response.set_message(request.message());
      stream->Write(response);
    }
    return Status::OK;
  }
};

class TestServiceImplDupPkg
    : public ::grpc::cpp::test::util::duplicate::TestService::Service {
 public:
  Status Echo(ServerContext* context, const EchoRequest* request,
              EchoResponse* response) override {
    response->set_message("no package");
    return Status::OK;
  }
};

class End2endTest : public ::testing::Test {
 protected:
  End2endTest() : thread_pool_(2) {}

  void SetUp() override {
    int port = grpc_pick_unused_port_or_die();
    server_address_ << "localhost:" << port;
    // Setup server
    ServerBuilder builder;
    builder.AddPort(server_address_.str());
    builder.RegisterService(&service_);
    builder.RegisterService(&dup_pkg_service_);
    builder.SetThreadPool(&thread_pool_);
    server_ = builder.BuildAndStart();
  }

  void TearDown() override { server_->Shutdown(); }

  void ResetStub() {
    std::shared_ptr<ChannelInterface> channel =
        CreateChannel(server_address_.str(), ChannelArguments());
    stub_.reset(grpc::cpp::test::util::TestService::NewStub(channel));
  }

  std::unique_ptr<grpc::cpp::test::util::TestService::Stub> stub_;
  std::unique_ptr<Server> server_;
  std::ostringstream server_address_;
  TestServiceImpl service_;
  TestServiceImplDupPkg dup_pkg_service_;
  ThreadPool thread_pool_;
};

static void SendRpc(grpc::cpp::test::util::TestService::Stub* stub,
                    int num_rpcs) {
  EchoRequest request;
  EchoResponse response;
  request.set_message("Hello");

  for (int i = 0; i < num_rpcs; ++i) {
    ClientContext context;
    Status s = stub->Echo(&context, request, &response);
    EXPECT_EQ(response.message(), request.message());
    EXPECT_TRUE(s.IsOk());
  }
}

TEST_F(End2endTest, SimpleRpc) {
  ResetStub();
  SendRpc(stub_.get(), 1);
}

TEST_F(End2endTest, MultipleRpcs) {
  ResetStub();
  std::vector<std::thread*> threads;
  for (int i = 0; i < 10; ++i) {
    threads.push_back(new std::thread(SendRpc, stub_.get(), 10));
  }
  for (int i = 0; i < 10; ++i) {
    threads[i]->join();
    delete threads[i];
  }
}

// Set a 10us deadline and make sure proper error is returned.
TEST_F(End2endTest, RpcDeadlineExpires) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  request.set_message("Hello");

  ClientContext context;
  std::chrono::system_clock::time_point deadline =
      std::chrono::system_clock::now() + std::chrono::microseconds(10);
  context.set_absolute_deadline(deadline);
  Status s = stub_->Echo(&context, request, &response);
  EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, s.code());
}

// Set a long but finite deadline.
TEST_F(End2endTest, RpcLongDeadline) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  request.set_message("Hello");

  ClientContext context;
  std::chrono::system_clock::time_point deadline =
      std::chrono::system_clock::now() + std::chrono::hours(1);
  context.set_absolute_deadline(deadline);
  Status s = stub_->Echo(&context, request, &response);
  EXPECT_EQ(response.message(), request.message());
  EXPECT_TRUE(s.IsOk());
}

// Ask server to echo back the deadline it sees.
TEST_F(End2endTest, EchoDeadline) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  request.set_message("Hello");
  request.mutable_param()->set_echo_deadline(true);

  ClientContext context;
  std::chrono::system_clock::time_point deadline =
      std::chrono::system_clock::now() + std::chrono::seconds(100);
  context.set_absolute_deadline(deadline);
  Status s = stub_->Echo(&context, request, &response);
  EXPECT_EQ(response.message(), request.message());
  EXPECT_TRUE(s.IsOk());
  gpr_timespec sent_deadline;
  Timepoint2Timespec(deadline, &sent_deadline);
  // Allow 1 second error.
  EXPECT_LE(response.param().request_deadline() - sent_deadline.tv_sec, 1);
  EXPECT_GE(response.param().request_deadline() - sent_deadline.tv_sec, -1);
}

// Ask server to echo back the deadline it sees. The rpc has no deadline.
TEST_F(End2endTest, EchoDeadlineForNoDeadlineRpc) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  request.set_message("Hello");
  request.mutable_param()->set_echo_deadline(true);

  ClientContext context;
  Status s = stub_->Echo(&context, request, &response);
  EXPECT_EQ(response.message(), request.message());
  EXPECT_TRUE(s.IsOk());
  EXPECT_EQ(response.param().request_deadline(), gpr_inf_future.tv_sec);
}

TEST_F(End2endTest, UnimplementedRpc) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  request.set_message("Hello");

  ClientContext context;
  Status s = stub_->Unimplemented(&context, request, &response);
  EXPECT_FALSE(s.IsOk());
  EXPECT_EQ(s.code(), grpc::StatusCode::UNIMPLEMENTED);
  EXPECT_EQ(s.details(), "");
  EXPECT_EQ(response.message(), "");
}

TEST_F(End2endTest, RequestStreamOneRequest) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  ClientContext context;

  ClientWriter<EchoRequest>* stream = stub_->RequestStream(&context, &response);
  request.set_message("hello");
  EXPECT_TRUE(stream->Write(request));
  stream->WritesDone();
  Status s = stream->Finish();
  EXPECT_EQ(response.message(), request.message());
  EXPECT_TRUE(s.IsOk());

  delete stream;
}

TEST_F(End2endTest, RequestStreamTwoRequests) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  ClientContext context;

  ClientWriter<EchoRequest>* stream = stub_->RequestStream(&context, &response);
  request.set_message("hello");
  EXPECT_TRUE(stream->Write(request));
  EXPECT_TRUE(stream->Write(request));
  stream->WritesDone();
  Status s = stream->Finish();
  EXPECT_EQ(response.message(), "hellohello");
  EXPECT_TRUE(s.IsOk());

  delete stream;
}

TEST_F(End2endTest, ResponseStream) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  ClientContext context;
  request.set_message("hello");

  ClientReader<EchoResponse>* stream =
      stub_->ResponseStream(&context, &request);
  EXPECT_TRUE(stream->Read(&response));
  EXPECT_EQ(response.message(), request.message() + "0");
  EXPECT_TRUE(stream->Read(&response));
  EXPECT_EQ(response.message(), request.message() + "1");
  EXPECT_TRUE(stream->Read(&response));
  EXPECT_EQ(response.message(), request.message() + "2");
  EXPECT_FALSE(stream->Read(&response));

  Status s = stream->Finish();
  EXPECT_TRUE(s.IsOk());

  delete stream;
}

TEST_F(End2endTest, BidiStream) {
  ResetStub();
  EchoRequest request;
  EchoResponse response;
  ClientContext context;
  grpc::string msg("hello");

  ClientReaderWriter<EchoRequest, EchoResponse>* stream =
      stub_->BidiStream(&context);

  request.set_message(msg + "0");
  EXPECT_TRUE(stream->Write(request));
  EXPECT_TRUE(stream->Read(&response));
  EXPECT_EQ(response.message(), request.message());

  request.set_message(msg + "1");
  EXPECT_TRUE(stream->Write(request));
  EXPECT_TRUE(stream->Read(&response));
  EXPECT_EQ(response.message(), request.message());

  request.set_message(msg + "2");
  EXPECT_TRUE(stream->Write(request));
  EXPECT_TRUE(stream->Read(&response));
  EXPECT_EQ(response.message(), request.message());

  stream->WritesDone();
  EXPECT_FALSE(stream->Read(&response));

  Status s = stream->Finish();
  EXPECT_TRUE(s.IsOk());

  delete stream;
}

// Talk to the two services with the same name but different package names.
// The two stubs are created on the same channel.
TEST_F(End2endTest, DiffPackageServices) {
  std::shared_ptr<ChannelInterface> channel =
      CreateChannel(server_address_.str(), ChannelArguments());

  EchoRequest request;
  EchoResponse response;
  request.set_message("Hello");

  std::unique_ptr<grpc::cpp::test::util::TestService::Stub> stub(
      grpc::cpp::test::util::TestService::NewStub(channel));
  ClientContext context;
  Status s = stub->Echo(&context, request, &response);
  EXPECT_EQ(response.message(), request.message());
  EXPECT_TRUE(s.IsOk());

  std::unique_ptr<grpc::cpp::test::util::duplicate::TestService::Stub>
      dup_pkg_stub(
          grpc::cpp::test::util::duplicate::TestService::NewStub(channel));
  ClientContext context2;
  s = dup_pkg_stub->Echo(&context2, request, &response);
  EXPECT_EQ("no package", response.message());
  EXPECT_TRUE(s.IsOk());
}

// rpc and stream should fail on bad credentials.
TEST_F(End2endTest, BadCredentials) {
  std::unique_ptr<Credentials> bad_creds =
      CredentialsFactory::ServiceAccountCredentials("", "",
                                                    std::chrono::seconds(1));
  EXPECT_EQ(nullptr, bad_creds.get());
  std::shared_ptr<ChannelInterface> channel =
      CreateChannel(server_address_.str(), bad_creds, ChannelArguments());
  std::unique_ptr<grpc::cpp::test::util::TestService::Stub> stub(
      grpc::cpp::test::util::TestService::NewStub(channel));
  EchoRequest request;
  EchoResponse response;
  ClientContext context;
  grpc::string msg("hello");

  Status s = stub->Echo(&context, request, &response);
  EXPECT_EQ("", response.message());
  EXPECT_FALSE(s.IsOk());
  EXPECT_EQ(StatusCode::UNKNOWN, s.code());
  EXPECT_EQ("Rpc sent on a lame channel.", s.details());

  ClientContext context2;
  ClientReaderWriter<EchoRequest, EchoResponse>* stream =
      stub->BidiStream(&context2);
  s = stream->Finish();
  EXPECT_FALSE(s.IsOk());
  EXPECT_EQ(StatusCode::UNKNOWN, s.code());
  EXPECT_EQ("Rpc sent on a lame channel.", s.details());

  delete stream;
}

}  // namespace testing
}  // namespace grpc

int main(int argc, char** argv) {
  grpc_test_init(argc, argv);
  grpc_init();
  ::testing::InitGoogleTest(&argc, argv);
  int result = RUN_ALL_TESTS();
  grpc_shutdown();
  return result;
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2016 gRPC authors.
 *
 * 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 "test/cpp/util/cli_credentials.h"

#include <gflags/gflags.h>

DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls.");
DEFINE_bool(use_auth, false, "Whether to create default google credentials.");
DEFINE_string(
    access_token, "",
    "The access token that will be sent to the server to authenticate RPCs.");
DEFINE_string(
    ssl_target, "",
    "If not empty, treat the server host name as this for ssl/tls certificate "
    "validation.");

namespace grpc {
namespace testing {

std::shared_ptr<grpc::ChannelCredentials> CliCredentials::GetCredentials()
    const {
  if (!FLAGS_access_token.empty()) {
    if (FLAGS_use_auth) {
      fprintf(stderr,
              "warning: use_auth is ignored when access_token is provided.");
    }

    return grpc::CompositeChannelCredentials(
        grpc::SslCredentials(grpc::SslCredentialsOptions()),
        grpc::AccessTokenCredentials(FLAGS_access_token));
  }

  if (FLAGS_use_auth) {
    return grpc::GoogleDefaultCredentials();
  }

  if (FLAGS_enable_ssl) {
    return grpc::SslCredentials(grpc::SslCredentialsOptions());
  }

  return grpc::InsecureChannelCredentials();
}

const grpc::string CliCredentials::GetCredentialUsage() const {
  return "    --enable_ssl             ; Set whether to use tls\n"
         "    --use_auth               ; Set whether to create default google"
         " credentials\n"
         "    --access_token           ; Set the access token in metadata,"
         " overrides --use_auth\n"
         "    --ssl_target             ; Set server host for tls validation\n";
}

const grpc::string CliCredentials::GetSslTargetNameOverride() const {
  bool use_tls = FLAGS_enable_ssl ||
      (FLAGS_access_token.empty() && FLAGS_use_auth);
  return use_tls ? FLAGS_ssl_target : "";
}

}  // namespace testing
}  // namespace grpc
<commit_msg>More clang format<commit_after>/*
 *
 * Copyright 2016 gRPC authors.
 *
 * 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 "test/cpp/util/cli_credentials.h"

#include <gflags/gflags.h>

DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls.");
DEFINE_bool(use_auth, false, "Whether to create default google credentials.");
DEFINE_string(
    access_token, "",
    "The access token that will be sent to the server to authenticate RPCs.");
DEFINE_string(
    ssl_target, "",
    "If not empty, treat the server host name as this for ssl/tls certificate "
    "validation.");

namespace grpc {
namespace testing {

std::shared_ptr<grpc::ChannelCredentials> CliCredentials::GetCredentials()
    const {
  if (!FLAGS_access_token.empty()) {
    if (FLAGS_use_auth) {
      fprintf(stderr,
              "warning: use_auth is ignored when access_token is provided.");
    }

    return grpc::CompositeChannelCredentials(
        grpc::SslCredentials(grpc::SslCredentialsOptions()),
        grpc::AccessTokenCredentials(FLAGS_access_token));
  }

  if (FLAGS_use_auth) {
    return grpc::GoogleDefaultCredentials();
  }

  if (FLAGS_enable_ssl) {
    return grpc::SslCredentials(grpc::SslCredentialsOptions());
  }

  return grpc::InsecureChannelCredentials();
}

const grpc::string CliCredentials::GetCredentialUsage() const {
  return "    --enable_ssl             ; Set whether to use tls\n"
         "    --use_auth               ; Set whether to create default google"
         " credentials\n"
         "    --access_token           ; Set the access token in metadata,"
         " overrides --use_auth\n"
         "    --ssl_target             ; Set server host for tls validation\n";
}

const grpc::string CliCredentials::GetSslTargetNameOverride() const {
  bool use_tls =
      FLAGS_enable_ssl || (FLAGS_access_token.empty() && FLAGS_use_auth);
  return use_tls ? FLAGS_ssl_target : "";
}

}  // namespace testing
}  // namespace grpc
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (C) 2012 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 mixer.cpp
 *
 * Control channel input/output mixer and failsafe.
 */

#include <nuttx/config.h>
#include <nuttx/arch.h>

#include <sys/types.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sched.h>

#include <debug.h>

#include <drivers/drv_pwm_output.h>
#include <drivers/drv_hrt.h>
#include <drivers/device/device.h>

#include <systemlib/mixer/mixer.h>

extern "C" {
//#define DEBUG
#include "px4io.h"
}

/*
 * Maximum interval in us before FMU signal is considered lost
 */
#define FMU_INPUT_DROP_LIMIT_US		200000

/* XXX need to move the RC_CHANNEL_FUNCTION out of rc_channels.h and into systemlib */
#define ROLL     0
#define PITCH    1
#define YAW      2
#define THROTTLE 3
#define OVERRIDE 4

/* current servo arm/disarm state */
bool mixer_servos_armed = false;

/* selected control values and count for mixing */
static uint16_t *control_values;
static int control_count;

static uint16_t rc_channel_data[PX4IO_INPUT_CHANNELS];

static int	mixer_callback(uintptr_t handle,
			       uint8_t control_group,
			       uint8_t control_index,
			       float &control);

static MixerGroup mixer_group(mixer_callback, 0);

void
mixer_tick(void)
{
	bool should_arm;

	/* check that we are receiving fresh data from the FMU */
	if ((hrt_absolute_time() - system_state.fmu_data_received_time) > FMU_INPUT_DROP_LIMIT_US) {
		/* too many frames without FMU input, time to go to failsafe */
		system_state.mixer_manual_override = true;
		system_state.mixer_fmu_available = false;
		lib_lowprintf("RX timeout\n");
	}

	/*
	 * Decide which set of inputs we're using.
	 */

	/* this is for planes, where manual override makes sense */
	if (system_state.manual_override_ok) {
		/* if everything is ok */
		if (!system_state.mixer_manual_override && system_state.mixer_fmu_available) {
			/* we have recent control data from the FMU */
			control_count = PX4IO_CONTROL_CHANNELS;
			control_values = &system_state.fmu_channel_data[0];

		} else if (system_state.rc_channels > 0) {
			/* when override is on or the fmu is not available, but RC is present */
			control_count = system_state.rc_channels;

			sched_lock();

			/* remap roll, pitch, yaw and throttle from RC specific to internal ordering */
			rc_channel_data[ROLL]     = system_state.rc_channel_data[system_state.rc_map[ROLL] - 1];
			rc_channel_data[PITCH]    = system_state.rc_channel_data[system_state.rc_map[PITCH] - 1];
			rc_channel_data[YAW]      = system_state.rc_channel_data[system_state.rc_map[YAW] - 1];
			rc_channel_data[THROTTLE] = system_state.rc_channel_data[system_state.rc_map[THROTTLE] - 1];
			//rc_channel_data[OVERRIDE] = system_state.rc_channel_data[system_state.rc_map[OVERRIDE] - 1];

			/* get the remaining channels, no remapping needed */
			for (unsigned i = 4; i < system_state.rc_channels; i++) {
				rc_channel_data[i] = system_state.rc_channel_data[i];
			}

			/* scale the control inputs */
			rc_channel_data[THROTTLE] = ((float)(rc_channel_data[THROTTLE] - system_state.rc_min[THROTTLE]) /
				(float)(system_state.rc_max[THROTTLE] - system_state.rc_min[THROTTLE])) * 1000.0f + 1000;

			if (rc_channel_data[THROTTLE] > 2000) {
				rc_channel_data[THROTTLE] = 2000;
			}

			if (rc_channel_data[THROTTLE] < 1000) {
				rc_channel_data[THROTTLE] = 1000;
			}

			// lib_lowprintf("Tmin: %d Ttrim: %d Tmax: %d T: %d \n",
			// 	(int)(system_state.rc_min[THROTTLE]), (int)(system_state.rc_trim[THROTTLE]),
			// 	(int)(system_state.rc_max[THROTTLE]), (int)(rc_channel_data[THROTTLE]));

			control_values = &rc_channel_data[0];
			sched_unlock();
		} else {
			/* we have no control input (no FMU, no RC) */

			// XXX builtin failsafe would activate here
			control_count = 0;
		}
		//lib_lowprintf("R: %d P: %d Y: %d T: %d \n", control_values[0], control_values[1], control_values[2], control_values[3]);

	/* this is for multicopters, etc. where manual override does not make sense */
	} else {
		/* if the fmu is available whe are good */
		if (system_state.mixer_fmu_available) {
			control_count = PX4IO_CONTROL_CHANNELS;
			control_values = &system_state.fmu_channel_data[0];
		/* we better shut everything off */
		} else {
			control_count = 0;
		}
	}

	/*
	 * Run the mixers if we have any control data at all.
	 */
	if (control_count > 0) {
		float	outputs[IO_SERVO_COUNT];
		unsigned mixed;

		/* mix */
		mixed = mixer_group.mix(&outputs[0], IO_SERVO_COUNT);

		/* scale to PWM and update the servo outputs as required */
		for (unsigned i = 0; i < IO_SERVO_COUNT; i++) {
			if (i < mixed) {
				/* scale to servo output */
				system_state.servos[i] = (outputs[i] * 500.0f) + 1500;

			} else {
				/* set to zero to inhibit PWM pulse output */
				system_state.servos[i] = 0;
			}

			/*
			 * If we are armed, update the servo output.
			 */
			if (system_state.armed && system_state.arm_ok) {
				up_pwm_servo_set(i, system_state.servos[i]);
			}
		}
	}

	/*
	 * Decide whether the servos should be armed right now.
	 * A sufficient reason is armed state and either FMU or RC control inputs
	 */

	should_arm = system_state.armed && system_state.arm_ok && (control_count > 0);

	if (should_arm && !mixer_servos_armed) {
		/* need to arm, but not armed */
		up_pwm_servo_arm(true);
		mixer_servos_armed = true;

	} else if (!should_arm && mixer_servos_armed) {
		/* armed but need to disarm */
		up_pwm_servo_arm(false);
		mixer_servos_armed = false;
	}
}

static int
mixer_callback(uintptr_t handle,
	       uint8_t control_group,
	       uint8_t control_index,
	       float &control)
{
	/* if the control index refers to an input that's not valid, we can't return it */
	if (control_index >= control_count)
		return -1;

	/* scale from current PWM units (1000-2000) to mixer input values */
	if (system_state.manual_override_ok && system_state.mixer_manual_override && control_index == 3) {
		control = ((float)control_values[control_index] - 1000.0f) / 1000.0f;
	} else {
		control = ((float)control_values[control_index] - 1500.0f) / 500.0f;
	}

	return 0;
}

static char mixer_text[256];
static unsigned mixer_text_length = 0;

void
mixer_handle_text(const void *buffer, size_t length)
{

	px4io_mixdata	*msg = (px4io_mixdata *)buffer;

	debug("mixer text %u", length);

	if (length < sizeof(px4io_mixdata))
		return;

	unsigned	text_length = length - sizeof(px4io_mixdata);

	switch (msg->action) {
	case F2I_MIXER_ACTION_RESET:
		debug("reset");
		mixer_group.reset();
		mixer_text_length = 0;

		/* FALLTHROUGH */
	case F2I_MIXER_ACTION_APPEND:
		debug("append %d", length);

		/* check for overflow - this is really fatal */
		if ((mixer_text_length + text_length + 1) > sizeof(mixer_text))
			return;

		/* append mixer text and nul-terminate */
		memcpy(&mixer_text[mixer_text_length], msg->text, text_length);
		mixer_text_length += text_length;
		mixer_text[mixer_text_length] = '\0';
		debug("buflen %u", mixer_text_length);

		/* process the text buffer, adding new mixers as their descriptions can be parsed */
		unsigned resid = mixer_text_length;
		mixer_group.load_from_buf(&mixer_text[0], resid);

		/* if anything was parsed */
		if (resid != mixer_text_length) {
			debug("used %u", mixer_text_length - resid);

			/* copy any leftover text to the base of the buffer for re-use */
			if (resid > 0)
				memcpy(&mixer_text[0], &mixer_text[mixer_text_length - resid], resid);

			mixer_text_length = resid;
		}

		break;
	}
}
<commit_msg>Strip some debugging<commit_after>/****************************************************************************
 *
 *   Copyright (C) 2012 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 mixer.cpp
 *
 * Control channel input/output mixer and failsafe.
 */

#include <nuttx/config.h>
#include <nuttx/arch.h>

#include <sys/types.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sched.h>

#include <debug.h>

#include <drivers/drv_pwm_output.h>
#include <drivers/drv_hrt.h>
#include <drivers/device/device.h>

#include <systemlib/mixer/mixer.h>

extern "C" {
//#define DEBUG
#include "px4io.h"
}

/*
 * Maximum interval in us before FMU signal is considered lost
 */
#define FMU_INPUT_DROP_LIMIT_US		200000

/* XXX need to move the RC_CHANNEL_FUNCTION out of rc_channels.h and into systemlib */
#define ROLL     0
#define PITCH    1
#define YAW      2
#define THROTTLE 3
#define OVERRIDE 4

/* current servo arm/disarm state */
bool mixer_servos_armed = false;

/* selected control values and count for mixing */
static uint16_t *control_values;
static int control_count;

static uint16_t rc_channel_data[PX4IO_INPUT_CHANNELS];

static int	mixer_callback(uintptr_t handle,
			       uint8_t control_group,
			       uint8_t control_index,
			       float &control);

static MixerGroup mixer_group(mixer_callback, 0);

void
mixer_tick(void)
{
	bool should_arm;

	/* check that we are receiving fresh data from the FMU */
	if ((hrt_absolute_time() - system_state.fmu_data_received_time) > FMU_INPUT_DROP_LIMIT_US) {
		/* too many frames without FMU input, time to go to failsafe */
		system_state.mixer_manual_override = true;
		system_state.mixer_fmu_available = false;
	}

	/*
	 * Decide which set of inputs we're using.
	 */

	/* this is for planes, where manual override makes sense */
	if (system_state.manual_override_ok) {
		/* if everything is ok */
		if (!system_state.mixer_manual_override && system_state.mixer_fmu_available) {
			/* we have recent control data from the FMU */
			control_count = PX4IO_CONTROL_CHANNELS;
			control_values = &system_state.fmu_channel_data[0];

		} else if (system_state.rc_channels > 0) {
			/* when override is on or the fmu is not available, but RC is present */
			control_count = system_state.rc_channels;

			sched_lock();

			/* remap roll, pitch, yaw and throttle from RC specific to internal ordering */
			rc_channel_data[ROLL]     = system_state.rc_channel_data[system_state.rc_map[ROLL] - 1];
			rc_channel_data[PITCH]    = system_state.rc_channel_data[system_state.rc_map[PITCH] - 1];
			rc_channel_data[YAW]      = system_state.rc_channel_data[system_state.rc_map[YAW] - 1];
			rc_channel_data[THROTTLE] = system_state.rc_channel_data[system_state.rc_map[THROTTLE] - 1];
			//rc_channel_data[OVERRIDE] = system_state.rc_channel_data[system_state.rc_map[OVERRIDE] - 1];

			/* get the remaining channels, no remapping needed */
			for (unsigned i = 4; i < system_state.rc_channels; i++) {
				rc_channel_data[i] = system_state.rc_channel_data[i];
			}

			/* scale the control inputs */
			rc_channel_data[THROTTLE] = ((float)(rc_channel_data[THROTTLE] - system_state.rc_min[THROTTLE]) /
				(float)(system_state.rc_max[THROTTLE] - system_state.rc_min[THROTTLE])) * 1000.0f + 1000;

			if (rc_channel_data[THROTTLE] > 2000) {
				rc_channel_data[THROTTLE] = 2000;
			}

			if (rc_channel_data[THROTTLE] < 1000) {
				rc_channel_data[THROTTLE] = 1000;
			}

			// lib_lowprintf("Tmin: %d Ttrim: %d Tmax: %d T: %d \n",
			// 	(int)(system_state.rc_min[THROTTLE]), (int)(system_state.rc_trim[THROTTLE]),
			// 	(int)(system_state.rc_max[THROTTLE]), (int)(rc_channel_data[THROTTLE]));

			control_values = &rc_channel_data[0];
			sched_unlock();
		} else {
			/* we have no control input (no FMU, no RC) */

			// XXX builtin failsafe would activate here
			control_count = 0;
		}
		//lib_lowprintf("R: %d P: %d Y: %d T: %d \n", control_values[0], control_values[1], control_values[2], control_values[3]);

	/* this is for multicopters, etc. where manual override does not make sense */
	} else {
		/* if the fmu is available whe are good */
		if (system_state.mixer_fmu_available) {
			control_count = PX4IO_CONTROL_CHANNELS;
			control_values = &system_state.fmu_channel_data[0];
		/* we better shut everything off */
		} else {
			control_count = 0;
		}
	}

	/*
	 * Run the mixers if we have any control data at all.
	 */
	if (control_count > 0) {
		float	outputs[IO_SERVO_COUNT];
		unsigned mixed;

		/* mix */
		mixed = mixer_group.mix(&outputs[0], IO_SERVO_COUNT);

		/* scale to PWM and update the servo outputs as required */
		for (unsigned i = 0; i < IO_SERVO_COUNT; i++) {
			if (i < mixed) {
				/* scale to servo output */
				system_state.servos[i] = (outputs[i] * 500.0f) + 1500;

			} else {
				/* set to zero to inhibit PWM pulse output */
				system_state.servos[i] = 0;
			}

			/*
			 * If we are armed, update the servo output.
			 */
			if (system_state.armed && system_state.arm_ok) {
				up_pwm_servo_set(i, system_state.servos[i]);
			}
		}
	}

	/*
	 * Decide whether the servos should be armed right now.
	 * A sufficient reason is armed state and either FMU or RC control inputs
	 */

	should_arm = system_state.armed && system_state.arm_ok && (control_count > 0);

	if (should_arm && !mixer_servos_armed) {
		/* need to arm, but not armed */
		up_pwm_servo_arm(true);
		mixer_servos_armed = true;

	} else if (!should_arm && mixer_servos_armed) {
		/* armed but need to disarm */
		up_pwm_servo_arm(false);
		mixer_servos_armed = false;
	}
}

static int
mixer_callback(uintptr_t handle,
	       uint8_t control_group,
	       uint8_t control_index,
	       float &control)
{
	/* if the control index refers to an input that's not valid, we can't return it */
	if (control_index >= control_count)
		return -1;

	/* scale from current PWM units (1000-2000) to mixer input values */
	if (system_state.manual_override_ok && system_state.mixer_manual_override && control_index == 3) {
		control = ((float)control_values[control_index] - 1000.0f) / 1000.0f;
	} else {
		control = ((float)control_values[control_index] - 1500.0f) / 500.0f;
	}

	return 0;
}

static char mixer_text[256];
static unsigned mixer_text_length = 0;

void
mixer_handle_text(const void *buffer, size_t length)
{

	px4io_mixdata	*msg = (px4io_mixdata *)buffer;

	debug("mixer text %u", length);

	if (length < sizeof(px4io_mixdata))
		return;

	unsigned	text_length = length - sizeof(px4io_mixdata);

	switch (msg->action) {
	case F2I_MIXER_ACTION_RESET:
		debug("reset");
		mixer_group.reset();
		mixer_text_length = 0;

		/* FALLTHROUGH */
	case F2I_MIXER_ACTION_APPEND:
		debug("append %d", length);

		/* check for overflow - this is really fatal */
		if ((mixer_text_length + text_length + 1) > sizeof(mixer_text))
			return;

		/* append mixer text and nul-terminate */
		memcpy(&mixer_text[mixer_text_length], msg->text, text_length);
		mixer_text_length += text_length;
		mixer_text[mixer_text_length] = '\0';
		debug("buflen %u", mixer_text_length);

		/* process the text buffer, adding new mixers as their descriptions can be parsed */
		unsigned resid = mixer_text_length;
		mixer_group.load_from_buf(&mixer_text[0], resid);

		/* if anything was parsed */
		if (resid != mixer_text_length) {
			debug("used %u", mixer_text_length - resid);

			/* copy any leftover text to the base of the buffer for re-use */
			if (resid > 0)
				memcpy(&mixer_text[0], &mixer_text[mixer_text_length - resid], resid);

			mixer_text_length = resid;
		}

		break;
	}
}
<|endoftext|>


<commit_before>// Copyright (c) Steinwurf ApS 2016.
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.

#include <storage/operator_equal.hpp>
#include <storage/storage.hpp>

#include <cstdint>
#include <vector>

#include <gtest/gtest.h>

TEST(test_operator_equal, equal)
{
    std::vector<uint8_t> d1(10, 1);
    std::vector<uint8_t> d2(10, 2);
    std::vector<uint8_t> d3(15, 3);

    EXPECT_EQ(storage::storage(d1), storage::storage(d1));
    EXPECT_NE(storage::storage(d1), storage::storage(d2));
    EXPECT_NE(storage::storage(d1), storage::storage(d3));
}
<commit_msg>improve operator_equal test<commit_after>// Copyright (c) Steinwurf ApS 2016.
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.

#include <storage/operator_equal.hpp>
#include <storage/storage.hpp>

#include <cstdint>
#include <vector>

#include <gtest/gtest.h>

TEST(test_operator_equal, equal)
{
    std::vector<uint8_t> d1(10, 1);
    std::vector<uint8_t> d2(10, 2);
    std::vector<uint8_t> d3(15, 1);
    std::vector<uint8_t> d3_2(15, 1);

    EXPECT_EQ(storage::storage(d1), storage::storage(d1));
    EXPECT_NE(storage::storage(d1), storage::storage(d2));
    EXPECT_NE(storage::storage(d1), storage::storage(d3));
    EXPECT_NE(storage::storage(d1), storage::storage(d3_2));
    EXPECT_EQ(storage::storage(d3), storage::storage(d3_2));
}
<|endoftext|>


<commit_before>#pragma once
#include "../utils/pool.hpp"
#include <limits>
#include <utility>

template<unsigned int K, class Data>
class Kdtree {
public:

	class N {
	public:
		double point[K];
		Data data;
	private:
		friend class Kdtree<K, Data>;
		unsigned int split;
		N *left, *right;
	};

	Kdtree();

	// Insert inserts a binding from the point to the data into the tree.
	void insert(double[K], Data);

	// Nearest returns a pointer to the nearest node in the tree, or NULL on error.
	const N* nearest(double[K]) const;

	// Size returns the number of points in the tree.
	unsigned long size() const;

private:

	N *insert(N*, unsigned int, N*);
	std::pair<const N*, double> nearest(const N*, double[], double*) const;
	double sqdist(const N*, double[]) const;

	N *root;
	unsigned long num;
	Pool<N> nodes;
};

template<unsigned int K, class Data>
Kdtree<K, Data>::Kdtree() : root(NULL), num(0) {
}

template<unsigned int K, class Data>
void Kdtree<K, Data>::insert(double pt[K], Data d) {
	N *n = nodes.construct();
	for (unsigned int i = 0; i < K; i++)
		n->point[i] = pt[i];
	n->data = d;
	root = insert(root, 0, n);
	num++;
}

template<unsigned int K, class Data>
typename Kdtree<K, Data>::N* Kdtree<K, Data>::insert(N *t, unsigned int depth, N *n) {
	if (!t) {
		n->split = depth % K;
		n->left = n->right = NULL;
		return n;
	}

	unsigned int s = t->split;
	if (n->point[s] < t->point[s])
		t->left = insert(t->left, depth+1, n);
	else
		t->right = insert(t->right, depth+1, n);
	return t;
}

template<unsigned int K, class Data>
const typename Kdtree<K, Data>::N* Kdtree<K, Data>::nearest(double pt[K]) const {
	double r = std::numeric_limits<double>::infinity();
	return nearest(root, pt, &r).first;
}

template<unsigned int K, class Data>
std::pair<const typename Kdtree<K, Data>::N*, double> Kdtree<K, Data>::nearest(const N *t, double pt[], double *range) const {
	if (!t)
		return std::make_pair<const N*, double>(NULL, std::numeric_limits<double>::infinity());

	unsigned int s = t->split;
	double diff = pt[s] - t->point[s];

	N *thisSide = t->right;
	N *otherSide = t->left;
	if (diff < 0) {
		thisSide = t->left;
		otherSide = t->right;
		diff = -diff;
	}

	auto near = nearest(thisSide, pt, range);

	if (diff*diff > *range)
		return near;

	double d = sqdist(t, pt);
	if (d <= *range) {
		near = std::make_pair(t, d);
		*range = std::min(near.second, *range);

	}

	auto m = nearest(otherSide, pt, range);
	if (m.second < near.second)
		near = m;

	return near;
}

template<unsigned int K, class Data>
double Kdtree<K, Data>::sqdist(const N *n, double pt[]) const {
	if (!n)
		return std::numeric_limits<double>::infinity();

	double s = 0;
	for (unsigned int i = 0; i < K; i++) {
		double d = n->point[i] - pt[i];
		s += d*d;
	}
	return s;
}

template<unsigned int K, class Data>
unsigned long Kdtree<K, Data>::size() const {
	return num;
}<commit_msg>structs: simplify the KD-tree traversal.<commit_after>#pragma once
#include "../utils/pool.hpp"
#include <limits>
#include <utility>

template<unsigned int K, class Data>
class Kdtree {
public:

	class N {
	public:
		double point[K];
		Data data;
	private:
		friend class Kdtree<K, Data>;
		unsigned int split;
		N *left, *right;
	};

	Kdtree();

	// Insert inserts a binding from the point to the data into the tree.
	void insert(double[K], Data);

	// Nearest returns a pointer to the nearest node in the tree, or NULL on error.
	const N* nearest(double[K]) const;

	// Size returns the number of points in the tree.
	unsigned long size() const;

private:

	N *insert(N*, unsigned int, N*);
	const N* nearest(const N*, double[], double*) const;
	double sqdist(const N*, double[]) const;

	N *root;
	unsigned long num;
	Pool<N> nodes;
};

template<unsigned int K, class Data>
Kdtree<K, Data>::Kdtree() : root(NULL), num(0) {
}

template<unsigned int K, class Data>
void Kdtree<K, Data>::insert(double pt[K], Data d) {
	N *n = nodes.construct();
	for (unsigned int i = 0; i < K; i++)
		n->point[i] = pt[i];
	n->data = d;
	root = insert(root, 0, n);
	num++;
}

template<unsigned int K, class Data>
typename Kdtree<K, Data>::N* Kdtree<K, Data>::insert(N *t, unsigned int depth, N *n) {
	if (!t) {
		n->split = depth % K;
		n->left = n->right = NULL;
		return n;
	}

	unsigned int s = t->split;
	if (n->point[s] < t->point[s])
		t->left = insert(t->left, depth+1, n);
	else
		t->right = insert(t->right, depth+1, n);
	return t;
}

template<unsigned int K, class Data>
const typename Kdtree<K, Data>::N* Kdtree<K, Data>::nearest(double pt[K]) const {
	double r = std::numeric_limits<double>::infinity();
	return nearest(root, pt, &r);
}

template<unsigned int K, class Data>
const typename Kdtree<K, Data>::N* Kdtree<K, Data>::nearest(const N *t, double pt[], double *range) const {
	if (!t)
		return NULL;

	unsigned int s = t->split;
	double diff = pt[s] - t->point[s];

	N *thisSide = t->right;
	N *otherSide = t->left;
	if (diff < 0) {
		thisSide = t->left;
		otherSide = t->right;
		diff = -diff;
	}

	const N* n = nearest(thisSide, pt, range);

	if (diff*diff > *range)
		return n;

	double d = sqdist(t, pt);
	if (d <= *range) {
		n = t;
		*range = std::min(d, *range);
	}

	const N *m = nearest(otherSide, pt, range);
	if (m)
		n = m;

	return n;
}

template<unsigned int K, class Data>
double Kdtree<K, Data>::sqdist(const N *n, double pt[]) const {
	if (!n)
		return std::numeric_limits<double>::infinity();

	double s = 0;
	for (unsigned int i = 0; i < K; i++) {
		double d = n->point[i] - pt[i];
		s += d*d;
	}
	return s;
}

template<unsigned int K, class Data>
unsigned long Kdtree<K, Data>::size() const {
	return num;
}<|endoftext|>


<commit_before>
#include "allocore/ui/al_PresetMapper.hpp"

using namespace al;

void PresetMapper::readEntries(std::string path)
{
	Dir presetDir(path);
	while (presetDir.read()) {
		FileInfo entry = presetDir.entry();
		if (entry.type() == FileInfo::DIR) {
			readEntries(entry.name());
		} else if (entry.type() == FileInfo::REG) {
			if (entry.name().size() > 4 && entry.name().substr(entry.name().size() - 4) == ".txt") {
				std::cout << "Found map: " << entry.name();
			}
		}
	}
}

PresetMapper::~PresetMapper() { }

PresetMapper &PresetMapper::registerPresetHandler(PresetHandler &handler) {
	mPresetHandler = &handler;
	if (mFindAutomatically) {
		findPresetMaps();
	}
	return *this;
}

bool PresetMapper::archive(std::string mapName, bool overwrite)
{
	bool ok = true;
	std::string fullPath = mPresetHandler->buildMapPath(mapName) + "_archive";
	if (overwrite) {
		if(File::isDirectory(fullPath)) {
			if (!Dir::removeRecursively(fullPath)) {
				std::cout << "Error removing directory: " << fullPath << " aborting preset map archiving." << std::endl;
				return false;
			}
		} else {
			if (File::remove(fullPath) != 0) {
				std::cout << "Error removing file: " << fullPath << " aborting preset map archiving." << std::endl;
				return false;
			}
		}
		if (!Dir::make(fullPath)) {
			std::cout << "Error creating preset map archive directory " << fullPath << std::endl;
			return false;
		}
	} else {
		int counter = 0;
		while (File::isDirectory(fullPath)) {
			std::string newName = mapName + "_" + std::to_string(counter++);
			fullPath = mPresetHandler->buildMapPath(newName) + "_archive";
			if (counter == 0) { // We've wrapped and run out of names...
				std::cout << "Out of names for preset map archive." << std::endl;
				return false;
			}
		}
		if (!Dir::make(fullPath)) {
			std::cout << "Error creating preset map archive directory " << fullPath << std::endl;
			return false;
		}
	}
	std::map<int, std::string> presetMap = mPresetHandler->readPresetMap(mapName);
	for(auto const &preset : presetMap) {
		std::string presetFilename = mPresetHandler->getCurrentPath() + preset.second + ".preset";
		if (!File::copy(presetFilename, fullPath)) {
			std::cout << "Error copying preset " << presetFilename << " when archiving preset map." << std::endl;
			ok = false;
		}
	}
	if (!File::copy(mPresetHandler->buildMapPath(mapName), fullPath + "default.presetMap")) {
		std::cout << "Error copying map: " << mapName << " when archiving preset map." << std::endl;
		ok = false;
	}

	return ok;
}

bool PresetMapper::load(std::string archiveName)
{
	if (! (archiveName.size() > 18 && archiveName.substr(archiveName.size() - 18) == ".presetMap_archive") ) {
		archiveName +=".presetMap_archive";
	}
	std::string mapPath = mPresetHandler->getRootPath() + archiveName;
	if (File::isDirectory(mapPath)) {
		mPresetHandler->setSubDirectory(archiveName);
		mPresetHandler->setCurrentPresetMap("default");
	} else {
		std::cout << "Error loading archive: " << archiveName << std::endl;
		return false;
	}
	return true;
}

std::vector<std::string> PresetMapper::listAvailableMaps(bool showArchives)
{
	std::vector<std::string> mapList;
	Dir mapperDir(mPresetHandler->getCurrentPath());

	// TODO it makes more sense to sort entries alphabetically
	while(mapperDir.read()) {
		const FileInfo &info = mapperDir.entry();
		if (info.type() == FileInfo::DIR && showArchives) {
			std::string name = info.name();
			if ( (name.size() > 18 && name.substr(name.size() - 18) == ".presetMap_archive")) {
				mapList.push_back(name);
			}
		} else if (info.type() == FileInfo::REG && !showArchives) {
			std::string name = info.name();
			if ( (name.size() > 4 && name.substr(name.size() - 4) == ".txt")
			     || (name.size() > 10 && name.substr(name.size() - 10) == ".presetMap")) {
				mapList.push_back(name);
			}
		}
	}
	return mapList;
}

bool PresetMapper::consumeMessage(osc::Message &m, std::string rootOSCPath)
{
	if(m.addressPattern() == rootOSCPath + "/map" && m.typeTags() == "s"){
		std::string val;
		m >> val;
		std::cout << "OSC: Recall preset map: " << val << std::endl;
		this->load(val);
		return true;
	}
	return false;
}

bool PresetMapper::restore(std::string mapName, bool overwrite, bool autoCreate)
{
	bool ok = true;
	if (mapName.size() > 18 && mapName.substr(mapName.size() - 18) == ".presetMap_archive") { // restore from archive
		std::cout << "Restoring archive " << mapName << std::endl;
		Dir mapDirectory(mPresetHandler->getCurrentPath() + mapName);
		std::string mapNewName = mapName.substr(0, mapName.size() - sizeof("_archive") + 1);
		while (mapDirectory.read()) {
			const FileInfo &entry = mapDirectory.entry();
			if (entry.type() == FileInfo::REG) {
				if (entry.name().substr(entry.name().size() - 7) == ".preset") {
					if (overwrite && File::exists(mPresetHandler->getCurrentPath() + "/" + entry.name())) {
						File::remove(mPresetHandler->getCurrentPath() + entry.name());
					}
					if (!File::copy(mPresetHandler->getCurrentPath() + mapName + "/" + entry.name(),
					                mPresetHandler->getCurrentPath() + entry.name())) {
						std::cout << "Error restoring preset " << entry.name() << " for " << mapName << std::endl;
						ok = false;
					}
				} else if (entry.name() == "default.presetMap") {

					if (overwrite && File::exists(mPresetHandler->getCurrentPath() + "/" + mapNewName)) {
						File::remove(mPresetHandler->getCurrentPath() + "/" + entry.name());
					}

					if (!File::copy(mPresetHandler->getCurrentPath() + "/" + mapName + "/default.presetMap",
					                mPresetHandler->getCurrentPath() + "/" + mapNewName)) {
						std::cout << "Error restoring preset map " << mapNewName << " for " << mapName << std::endl;
						ok = false;
					}
				} else {
					std::cout << "PresetMapper::restore() invalid file: " << entry.name() << std::endl;
				}
			}
		}
		mPresetHandler->setCurrentPresetMap(mapNewName, autoCreate);
	} else { // set preset map directly
		mPresetHandler->setCurrentPresetMap(mapName, autoCreate);
	}
	return ok;
}

void PresetMapper::findPresetMaps() {
	std::string presetsPath = mPresetHandler->getCurrentPath();

	Dir presetDir(presetsPath);
	while (presetDir.read()) {
		FileInfo entry = presetDir.entry();
		if (entry.name().size() > 4 && entry.name().substr(entry.name().size() - 4) == ".txt") {
			std::cout << "Found map: " << entry.name() << std::endl;
		}
	}
}
<commit_msg>Fixed issue setting preset map archive sub dir<commit_after>
#include "allocore/ui/al_PresetMapper.hpp"

using namespace al;

void PresetMapper::readEntries(std::string path)
{
	Dir presetDir(path);
	while (presetDir.read()) {
		FileInfo entry = presetDir.entry();
		if (entry.type() == FileInfo::DIR) {
			readEntries(entry.name());
		} else if (entry.type() == FileInfo::REG) {
			if (entry.name().size() > 4 && entry.name().substr(entry.name().size() - 4) == ".txt") {
				std::cout << "Found map: " << entry.name();
			}
		}
	}
}

PresetMapper::~PresetMapper() { }

PresetMapper &PresetMapper::registerPresetHandler(PresetHandler &handler) {
	mPresetHandler = &handler;
	if (mFindAutomatically) {
		findPresetMaps();
	}
	return *this;
}

bool PresetMapper::archive(std::string mapName, bool overwrite)
{
	bool ok = true;
	std::string fullPath = mPresetHandler->buildMapPath(mapName) + "_archive";
	if (overwrite) {
		if(File::isDirectory(fullPath)) {
			if (!Dir::removeRecursively(fullPath)) {
				std::cout << "Error removing directory: " << fullPath << " aborting preset map archiving." << std::endl;
				return false;
			}
		} else {
			if (File::remove(fullPath) != 0) {
				std::cout << "Error removing file: " << fullPath << " aborting preset map archiving." << std::endl;
				return false;
			}
		}
		if (!Dir::make(fullPath)) {
			std::cout << "Error creating preset map archive directory " << fullPath << std::endl;
			return false;
		}
	} else {
		int counter = 0;
		while (File::isDirectory(fullPath)) {
			std::string newName = mapName + "_" + std::to_string(counter++);
			fullPath = mPresetHandler->buildMapPath(newName) + "_archive";
			if (counter == 0) { // We've wrapped and run out of names...
				std::cout << "Out of names for preset map archive." << std::endl;
				return false;
			}
		}
		if (!Dir::make(fullPath)) {
			std::cout << "Error creating preset map archive directory " << fullPath << std::endl;
			return false;
		}
	}
	std::map<int, std::string> presetMap = mPresetHandler->readPresetMap(mapName);
	for(auto const &preset : presetMap) {
		std::string presetFilename = mPresetHandler->getCurrentPath() + preset.second + ".preset";
		if (!File::copy(presetFilename, fullPath)) {
			std::cout << "Error copying preset " << presetFilename << " when archiving preset map." << std::endl;
			ok = false;
		}
	}
	if (!File::copy(mPresetHandler->buildMapPath(mapName), fullPath + "default.presetMap")) {
		std::cout << "Error copying map: " << mapName << " when archiving preset map." << std::endl;
		ok = false;
	}

	return ok;
}

bool PresetMapper::load(std::string archiveName)
{
	if (! (archiveName.size() > 18 && archiveName.substr(archiveName.size() - 18) == ".presetMap_archive") ) {
		archiveName +=".presetMap_archive";
	}
	std::string mapPath = mPresetHandler->getRootPath() + archiveName;
	if (File::isDirectory(archiveName)) {
		mPresetHandler->setSubDirectory(archiveName);
		mPresetHandler->setCurrentPresetMap("default");
	} else {
		std::cout << "Error loading archive: " << archiveName << std::endl;
		return false;
	}
	return true;
}

std::vector<std::string> PresetMapper::listAvailableMaps(bool showArchives)
{
	std::vector<std::string> mapList;
	Dir mapperDir(mPresetHandler->getCurrentPath());

	// TODO it makes more sense to sort entries alphabetically
	while(mapperDir.read()) {
		const FileInfo &info = mapperDir.entry();
		if (info.type() == FileInfo::DIR && showArchives) {
			std::string name = info.name();
			if ( (name.size() > 18 && name.substr(name.size() - 18) == ".presetMap_archive")) {
				mapList.push_back(name);
			}
		} else if (info.type() == FileInfo::REG && !showArchives) {
			std::string name = info.name();
			if ( (name.size() > 4 && name.substr(name.size() - 4) == ".txt")
			     || (name.size() > 10 && name.substr(name.size() - 10) == ".presetMap")) {
				mapList.push_back(name);
			}
		}
	}
	return mapList;
}

bool PresetMapper::consumeMessage(osc::Message &m, std::string rootOSCPath)
{
	if(m.addressPattern() == rootOSCPath + "/map" && m.typeTags() == "s"){
		std::string val;
		m >> val;
		std::cout << "OSC: Recall preset map: " << val << std::endl;
		this->load(val);
		return true;
	}
	return false;
}

bool PresetMapper::restore(std::string mapName, bool overwrite, bool autoCreate)
{
	bool ok = true;
	if (mapName.size() > 18 && mapName.substr(mapName.size() - 18) == ".presetMap_archive") { // restore from archive
		std::cout << "Restoring archive " << mapName << std::endl;
		Dir mapDirectory(mPresetHandler->getCurrentPath() + mapName);
		std::string mapNewName = mapName.substr(0, mapName.size() - sizeof("_archive") + 1);
		while (mapDirectory.read()) {
			const FileInfo &entry = mapDirectory.entry();
			if (entry.type() == FileInfo::REG) {
				if (entry.name().substr(entry.name().size() - 7) == ".preset") {
					if (overwrite && File::exists(mPresetHandler->getCurrentPath() + "/" + entry.name())) {
						File::remove(mPresetHandler->getCurrentPath() + entry.name());
					}
					if (!File::copy(mPresetHandler->getCurrentPath() + mapName + "/" + entry.name(),
					                mPresetHandler->getCurrentPath() + entry.name())) {
						std::cout << "Error restoring preset " << entry.name() << " for " << mapName << std::endl;
						ok = false;
					}
				} else if (entry.name() == "default.presetMap") {

					if (overwrite && File::exists(mPresetHandler->getCurrentPath() + "/" + mapNewName)) {
						File::remove(mPresetHandler->getCurrentPath() + "/" + entry.name());
					}

					if (!File::copy(mPresetHandler->getCurrentPath() + "/" + mapName + "/default.presetMap",
					                mPresetHandler->getCurrentPath() + "/" + mapNewName)) {
						std::cout << "Error restoring preset map " << mapNewName << " for " << mapName << std::endl;
						ok = false;
					}
				} else {
					std::cout << "PresetMapper::restore() invalid file: " << entry.name() << std::endl;
				}
			}
		}
		mPresetHandler->setCurrentPresetMap(mapNewName, autoCreate);
	} else { // set preset map directly
		mPresetHandler->setCurrentPresetMap(mapName, autoCreate);
	}
	return ok;
}

void PresetMapper::findPresetMaps() {
	std::string presetsPath = mPresetHandler->getCurrentPath();

	Dir presetDir(presetsPath);
	while (presetDir.read()) {
		FileInfo entry = presetDir.entry();
		if (entry.name().size() > 4 && entry.name().substr(entry.name().size() - 4) == ".txt") {
			std::cout << "Found map: " << entry.name() << std::endl;
		}
	}
}
<|endoftext|>


<commit_before>// $Id: ParameterSection_test.C,v 1.1 2000/09/16 08:33:55 oliver Exp $
#include <BALL/CONCEPT/classTest.h>

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

#include <BALL/FORMAT/parameterSection.h>

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

START_TEST(Parameters, "$Id: ParameterSection_test.C,v 1.1 2000/09/16 08:33:55 oliver Exp $")

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

using namespace BALL;

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<commit_msg>added: test skeleton<commit_after>// $Id: ParameterSection_test.C,v 1.2 2000/09/19 15:53:02 oliver Exp $
#include <BALL/CONCEPT/classTest.h>

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

#include <BALL/FORMAT/parameterSection.h>

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

START_TEST(Parameters, "$Id: ParameterSection_test.C,v 1.2 2000/09/19 15:53:02 oliver Exp $")

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

using namespace BALL;

CHECK(ParameterSection::ParameterSection())
  //BAUSTELLE
RESULT

CHECK(ParameterSection::~ParameterSection())
  //BAUSTELLE
RESULT

CHECK(ParameterSection::destroy())
  //BAUSTELLE
RESULT

CHECK(ParameterSection::extractSection(Parameters& parameters, const String& section_name))
  //BAUSTELLE
RESULT

CHECK(ParameterSection::getValue(const String& key, const String& variable) const )
  //BAUSTELLE
RESULT

CHECK(ParameterSection::has(const String& key, const String& variable) const )
  //BAUSTELLE
RESULT

CHECK(ParameterSection::has(const String& key) const )
  //BAUSTELLE
RESULT

CHECK(ParameterSection::hasVariable(const String& variable) const )
  //BAUSTELLE
RESULT

CHECK(ParameterSection::getColumnIndex(const String& variable) const )
  //BAUSTELLE
RESULT

CHECK(ParameterSection::getNumberOfVariables() const )
  //BAUSTELLE
RESULT

CHECK(ParameterSection::getNumberOfKeys() const )
  //BAUSTELLE
RESULT

CHECK(ParameterSection::getValue(Position key_index, Position variable_index) const )
  //BAUSTELLE
RESULT

CHECK(ParameterSection::getKey(Position key_index) const )
  //BAUSTELLE
RESULT

CHECK(ParameterSection::isValid() const )
  //BAUSTELLE
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright 2015 Cloudius Systems
 */

#include <seastar/http/httpd.hh>
#include <seastar/http/handlers.hh>
#include <seastar/http/function_handlers.hh>
#include <seastar/http/file_handler.hh>
#include "demo.json.hh"
#include <seastar/http/api_docs.hh>

namespace bpo = boost::program_options;

using namespace seastar;
using namespace httpd;

class handl : public httpd::handler_base {
public:
    virtual future<std::unique_ptr<reply> > handle(const sstring& path,
            std::unique_ptr<request> req, std::unique_ptr<reply> rep) {
        rep->_content = "hello";
        rep->done("html");
        return make_ready_future<std::unique_ptr<reply>>(std::move(rep));
    }
};

void set_routes(routes& r) {
    function_handler* h1 = new function_handler([](const_req req) {
        return "hello";
    });
    function_handler* h2 = new function_handler([](std::unique_ptr<request> req) {
        return make_ready_future<json::json_return_type>("json-future");
    });
    r.add(operation_type::GET, url("/"), h1);
    r.add(operation_type::GET, url("/jf"), h2);
    r.add(operation_type::GET, url("/file").remainder("path"),
            new directory_handler("/"));
    demo_json::hello_world.set(r, [] (const_req req) {
        demo_json::my_object obj;
        obj.var1 = req.param.at("var1");
        obj.var2 = req.param.at("var2");
        demo_json::ns_hello_world::query_enum v = demo_json::ns_hello_world::str2query_enum(req.query_parameters.at("query_enum"));
        // This demonstrate enum conversion
        obj.enum_var = v;
        return obj;
    });
}

int main(int ac, char** av) {
    app_template app;
    app.add_options()("port", bpo::value<uint16_t>()->default_value(10000),
            "HTTP Server port");
    return app.run_deprecated(ac, av, [&] {
        auto&& config = app.configuration();
        uint16_t port = config["port"].as<uint16_t>();
        auto server = new http_server_control();
        auto rb = make_shared<api_registry_builder>("apps/httpd/");
        server->start().then([server] {
            return server->set_routes(set_routes);
        }).then([server, rb]{
            return server->set_routes([rb](routes& r){rb->set_api_doc(r);});
        }).then([server, rb]{
            return server->set_routes([rb](routes& r) {rb->register_function(r, "demo", "hello world application");});
        }).then([server, port] {
            return server->listen(port);
        }).then([server, port] {
            std::cout << "Seastar HTTP server listening on port " << port << " ...\n";
            engine().at_exit([server] {
                return server->stop();
            });
        });

    });
}
<commit_msg>apps/httpd: main: do not discard future<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright 2015 Cloudius Systems
 */

#include <seastar/http/httpd.hh>
#include <seastar/http/handlers.hh>
#include <seastar/http/function_handlers.hh>
#include <seastar/http/file_handler.hh>
#include "demo.json.hh"
#include <seastar/http/api_docs.hh>

namespace bpo = boost::program_options;

using namespace seastar;
using namespace httpd;

class handl : public httpd::handler_base {
public:
    virtual future<std::unique_ptr<reply> > handle(const sstring& path,
            std::unique_ptr<request> req, std::unique_ptr<reply> rep) {
        rep->_content = "hello";
        rep->done("html");
        return make_ready_future<std::unique_ptr<reply>>(std::move(rep));
    }
};

void set_routes(routes& r) {
    function_handler* h1 = new function_handler([](const_req req) {
        return "hello";
    });
    function_handler* h2 = new function_handler([](std::unique_ptr<request> req) {
        return make_ready_future<json::json_return_type>("json-future");
    });
    r.add(operation_type::GET, url("/"), h1);
    r.add(operation_type::GET, url("/jf"), h2);
    r.add(operation_type::GET, url("/file").remainder("path"),
            new directory_handler("/"));
    demo_json::hello_world.set(r, [] (const_req req) {
        demo_json::my_object obj;
        obj.var1 = req.param.at("var1");
        obj.var2 = req.param.at("var2");
        demo_json::ns_hello_world::query_enum v = demo_json::ns_hello_world::str2query_enum(req.query_parameters.at("query_enum"));
        // This demonstrate enum conversion
        obj.enum_var = v;
        return obj;
    });
}

int main(int ac, char** av) {
    app_template app;
    app.add_options()("port", bpo::value<uint16_t>()->default_value(10000),
            "HTTP Server port");
    return app.run_deprecated(ac, av, [&] {
        auto&& config = app.configuration();
        uint16_t port = config["port"].as<uint16_t>();
        auto server = new http_server_control();
        auto rb = make_shared<api_registry_builder>("apps/httpd/");
        return server->start().then([server] {
            return server->set_routes(set_routes);
        }).then([server, rb]{
            return server->set_routes([rb](routes& r){rb->set_api_doc(r);});
        }).then([server, rb]{
            return server->set_routes([rb](routes& r) {rb->register_function(r, "demo", "hello world application");});
        }).then([server, port] {
            return server->listen(port);
        }).then([server, port] {
            std::cout << "Seastar HTTP server listening on port " << port << " ...\n";
            engine().at_exit([server] {
                return server->stop();
            });
        });

    });
}
<|endoftext|>


<commit_before>/**
 * @file   MqNodeTest.cpp
 * @brief  MqNode class tester.
 * @author zer0
 * @date   2018-11-11
 */

#include <gtest/gtest.h>
#include <tester/DemoAsset.hpp>
#include <libtbag/mq/MqNode.hpp>
#include <string>

using namespace libtbag;
using namespace libtbag::mq;

TEST(MqNodeTest, Bind_Release)
{
    tttDir_Automatic_Pipe();
    auto const PIPE_PATH = std::string("pipe://") + tttDir_Pipe_Get();

    MqNode node;
    ASSERT_EQ(Err::E_SUCCESS, node.bind(PIPE_PATH));
}

//TEST(MqNodeTest, Connect_Release)
//{
//    tttDir_Automatic_Pipe();
//    auto const PIPE_PATH = std::string("pipe://") + tttDir_Pipe_Get();
//
//    MqNode node;
//    ASSERT_EQ(Err::E_SUCCESS, node.connect(PIPE_PATH));
//}

TEST(MqNodeTest, BindAndConnection_Release)
{
    tttDir_Automatic_Pipe();
    auto const PIPE_PATH = std::string("pipe://") + tttDir_Pipe_Get();

    MqNode node1;
    MqNode node2;
    ASSERT_EQ(Err::E_SUCCESS, node1.bind(PIPE_PATH));
    ASSERT_EQ(Err::E_SUCCESS, node2.connect(PIPE_PATH));
}

<commit_msg>Create MqNodeTest.BindAndConnection2 tester.<commit_after>/**
 * @file   MqNodeTest.cpp
 * @brief  MqNode class tester.
 * @author zer0
 * @date   2018-11-11
 */

#include <gtest/gtest.h>
#include <tester/DemoAsset.hpp>
#include <libtbag/mq/MqNode.hpp>
#include <libtbag/log/Log.hpp>

#include <string>

using namespace libtbag;
using namespace libtbag::mq;

TEST(MqNodeTest, Bind)
{
    libtbag::log::SeverityGuard guard;

    tttDir_Automatic_Pipe();
    auto const PIPE_PATH = std::string("pipe://") + tttDir_Pipe_Get() + "?verbose=true";

    MqNode node;
    ASSERT_EQ(Err::E_SUCCESS, node.bind(PIPE_PATH));
}

//TEST(MqNodeTest, Connect_Release)
//{
//    tttDir_Automatic_Pipe();
//    auto const PIPE_PATH = std::string("pipe://") + tttDir_Pipe_Get();
//
//    MqNode node;
//    ASSERT_EQ(Err::E_SUCCESS, node.connect(PIPE_PATH));
//}

TEST(MqNodeTest, BindAndConnection)
{
    // Client release -> Server release!

    tttDir_Automatic_Pipe();
    auto const PIPE_PATH = std::string("pipe://") + tttDir_Pipe_Get() + "?verbose=true";

    auto server = std::make_unique<MqNode>();
    auto client = std::make_unique<MqNode>();

    libtbag::log::SeverityGuard guard;
    ASSERT_EQ(Err::E_SUCCESS, server->bind(PIPE_PATH));
    ASSERT_EQ(Err::E_SUCCESS, client->connect(PIPE_PATH));

    client.reset();
    server.reset();
}

TEST(MqNodeTest, BindAndConnection2)
{
    // Server release -> Client release!

    tttDir_Automatic_Pipe();
    auto const PIPE_PATH = std::string("pipe://") + tttDir_Pipe_Get() + "?verbose=true";

    auto server = std::make_unique<MqNode>();
    auto client = std::make_unique<MqNode>();

    //libtbag::log::SeverityGuard guard;
    ASSERT_EQ(Err::E_SUCCESS, server->bind(PIPE_PATH));
    ASSERT_EQ(Err::E_SUCCESS, client->connect(PIPE_PATH));

    server.reset();
    client.reset();
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fmtline.hxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: hr $ $Date: 2006-08-14 15:23:59 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef SW_FMTLINE_HXX
#define SW_FMTLINE_HXX

#ifndef _SFXPOOLITEM_HXX //autogen
#include <svtools/poolitem.hxx>
#endif
#ifndef _HINTIDS_HXX
#include <hintids.hxx>
#endif
#ifndef _FORMAT_HXX //autogen
#include <format.hxx>
#endif
#ifndef INCLUDED_SWDLLAPI_H
#include "swdllapi.h"
#endif

class IntlWrapper;

class SW_DLLPUBLIC SwFmtLineNumber: public SfxPoolItem
{
    ULONG nStartValue   :24; //Startwert fuer den Absatz, 0 == kein Startwert
    ULONG bCountLines   :1;  //Zeilen des Absatzes sollen mitgezaehlt werden.

public:
    SwFmtLineNumber();
    ~SwFmtLineNumber();

    TYPEINFO();

    // "pure virtual Methoden" vom SfxPoolItem
    virtual int             operator==( const SfxPoolItem& ) const;
    virtual SfxPoolItem*    Clone( SfxItemPool* pPool = 0 ) const;
    virtual SfxItemPresentation GetPresentation( SfxItemPresentation ePres,
                                    SfxMapUnit eCoreMetric,
                                    SfxMapUnit ePresMetric,
                                    String &rText,
                                    const IntlWrapper*    pIntl = 0 ) const;
    virtual BOOL             QueryValue( com::sun::star::uno::Any& rVal, BYTE nMemberId = 0 ) const;
    virtual BOOL             PutValue( const com::sun::star::uno::Any& rVal, BYTE nMemberId = 0 );

    ULONG GetStartValue() const { return nStartValue; }
    BOOL  IsCount()       const { return bCountLines != 0; }

    void SetStartValue( ULONG nNew ) { nStartValue = nNew; }
    void SetCountLines( BOOL b )     { bCountLines = b;    }
};

inline const SwFmtLineNumber &SwAttrSet::GetLineNumber(BOOL bInP) const
    { return (const SwFmtLineNumber&)Get( RES_LINENUMBER,bInP); }

#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.10.738); FILE MERGED 2008/04/01 15:56:12 thb 1.10.738.3: #i85898# Stripping all external header guards 2008/04/01 12:53:30 thb 1.10.738.2: #i85898# Stripping all external header guards 2008/03/31 16:52:38 rt 1.10.738.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: fmtline.hxx,v $
 * $Revision: 1.11 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef SW_FMTLINE_HXX
#define SW_FMTLINE_HXX

#include <svtools/poolitem.hxx>
#include <hintids.hxx>
#include <format.hxx>
#include "swdllapi.h"

class IntlWrapper;

class SW_DLLPUBLIC SwFmtLineNumber: public SfxPoolItem
{
    ULONG nStartValue   :24; //Startwert fuer den Absatz, 0 == kein Startwert
    ULONG bCountLines   :1;  //Zeilen des Absatzes sollen mitgezaehlt werden.

public:
    SwFmtLineNumber();
    ~SwFmtLineNumber();

    TYPEINFO();

    // "pure virtual Methoden" vom SfxPoolItem
    virtual int             operator==( const SfxPoolItem& ) const;
    virtual SfxPoolItem*    Clone( SfxItemPool* pPool = 0 ) const;
    virtual SfxItemPresentation GetPresentation( SfxItemPresentation ePres,
                                    SfxMapUnit eCoreMetric,
                                    SfxMapUnit ePresMetric,
                                    String &rText,
                                    const IntlWrapper*    pIntl = 0 ) const;
    virtual BOOL             QueryValue( com::sun::star::uno::Any& rVal, BYTE nMemberId = 0 ) const;
    virtual BOOL             PutValue( const com::sun::star::uno::Any& rVal, BYTE nMemberId = 0 );

    ULONG GetStartValue() const { return nStartValue; }
    BOOL  IsCount()       const { return bCountLines != 0; }

    void SetStartValue( ULONG nNew ) { nStartValue = nNew; }
    void SetCountLines( BOOL b )     { bCountLines = b;    }
};

inline const SwFmtLineNumber &SwAttrSet::GetLineNumber(BOOL bInP) const
    { return (const SwFmtLineNumber&)Get( RES_LINENUMBER,bInP); }

#endif

<|endoftext|>