<commit_before>/*
 *
 * Copyright 2017 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 <stdlib.h>
#include <string.h>

#include <gtest/gtest.h>

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>

#include "src/core/lib/channel/channel_trace.h"
#include "src/core/lib/channel/channel_trace_registry.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/json/json.h"

#include "test/core/util/test_config.h"
#include "test/cpp/util/channel_trace_proto_helper.h"

// remove me
#include <grpc/support/string_util.h>
#include <stdlib.h>
#include <string.h>

namespace grpc_core {
namespace testing {
namespace {

grpc_json* GetJsonChild(grpc_json* parent, const char* key) {
  EXPECT_NE(parent, nullptr);
  for (grpc_json* child = parent->child; child != nullptr;
       child = child->next) {
    if (child->key != nullptr && strcmp(child->key, key) == 0) return child;
  }
  return nullptr;
}

void ValidateJsonArraySize(grpc_json* json, const char* key,
                           size_t expected_size) {
  grpc_json* arr = GetJsonChild(json, key);
  ASSERT_NE(arr, nullptr);
  ASSERT_EQ(arr->type, GRPC_JSON_ARRAY);
  size_t count = 0;
  for (grpc_json* child = arr->child; child != nullptr; child = child->next) {
    ++count;
  }
  ASSERT_EQ(count, expected_size);
}

void ValidateChannelTraceData(grpc_json* json,
                              size_t num_events_logged_expected,
                              size_t actual_num_events_expected) {
  ASSERT_NE(json, nullptr);
  grpc_json* num_events_logged_json = GetJsonChild(json, "numEventsLogged");
  ASSERT_NE(num_events_logged_json, nullptr);
  grpc_json* start_time = GetJsonChild(json, "creationTime");
  ASSERT_NE(start_time, nullptr);
  size_t num_events_logged =
      (size_t)strtol(num_events_logged_json->value, nullptr, 0);
  ASSERT_EQ(num_events_logged, num_events_logged_expected);
  ValidateJsonArraySize(json, "events", actual_num_events_expected);
}

void AddSimpleTrace(RefCountedPtr<ChannelTrace> tracer) {
  tracer->AddTraceEvent(ChannelTrace::Severity::Info,
                        grpc_slice_from_static_string("simple trace"));
}

// checks for the existence of all the required members of the tracer.
void ValidateChannelTrace(RefCountedPtr<ChannelTrace> tracer,
                          size_t expected_num_event_logged, size_t max_nodes) {
  if (!max_nodes) return;
  char* json_str = tracer->RenderTrace();
  grpc::testing::ValidateChannelTraceProtoJsonTranslation(json_str);
  grpc_json* json = grpc_json_parse_string(json_str);
  ValidateChannelTraceData(json, expected_num_event_logged,
                           GPR_MIN(expected_num_event_logged, max_nodes));
  grpc_json_destroy(json);
  gpr_free(json_str);
}

void ValidateTraceDataMatchedUuidLookup(RefCountedPtr<ChannelTrace> tracer) {
  intptr_t uuid = tracer->GetUuid();
  if (uuid == -1) return;  // Doesn't make sense to lookup if tracing disabled
  char* tracer_json_str = tracer->RenderTrace();
  ChannelTrace* uuid_lookup =
      grpc_channel_trace_registry_get_channel_trace(uuid);
  char* uuid_lookup_json_str = uuid_lookup->RenderTrace();
  EXPECT_EQ(strcmp(tracer_json_str, uuid_lookup_json_str), 0);
  gpr_free(tracer_json_str);
  gpr_free(uuid_lookup_json_str);
}

}  // anonymous namespace

class ChannelTracerTest : public ::testing::TestWithParam<size_t> {};

// Tests basic ChannelTrace functionality like construction, adding trace, and
// lookups by uuid.
TEST_P(ChannelTracerTest, BasicTest) {
  grpc_core::ExecCtx exec_ctx;
  RefCountedPtr<ChannelTrace> tracer = MakeRefCounted<ChannelTrace>(GetParam());
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  ValidateTraceDataMatchedUuidLookup(tracer);
  tracer->AddTraceEvent(ChannelTrace::Severity::Info,
                        grpc_slice_from_static_string("trace three"));
  tracer->AddTraceEvent(ChannelTrace::Severity::Error,
                        grpc_slice_from_static_string("trace four error"));
  ValidateChannelTrace(tracer, 4, GetParam());
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  ValidateChannelTrace(tracer, 6, GetParam());
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  ValidateChannelTrace(tracer, 10, GetParam());
  ValidateTraceDataMatchedUuidLookup(tracer);
  tracer.reset(nullptr);
}

// Tests more complex functionality, like a parent channel tracking
// subchannles. This exercises the ref/unref patterns since the parent tracer
// and this function will both hold refs to the subchannel.
TEST_P(ChannelTracerTest, ComplexTest) {
  grpc_core::ExecCtx exec_ctx;
  RefCountedPtr<ChannelTrace> tracer = MakeRefCounted<ChannelTrace>(GetParam());
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  RefCountedPtr<ChannelTrace> sc1 = MakeRefCounted<ChannelTrace>(GetParam());
  tracer->AddTraceEventReferencingSubchannel(
      ChannelTrace::Severity::Info,
      grpc_slice_from_static_string("subchannel one created"), sc1);
  ValidateChannelTrace(tracer, 3, GetParam());
  AddSimpleTrace(sc1);
  AddSimpleTrace(sc1);
  AddSimpleTrace(sc1);
  ValidateChannelTrace(sc1, 3, GetParam());
  AddSimpleTrace(sc1);
  AddSimpleTrace(sc1);
  AddSimpleTrace(sc1);
  ValidateChannelTrace(sc1, 6, GetParam());
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  ValidateChannelTrace(tracer, 5, GetParam());
  ValidateTraceDataMatchedUuidLookup(tracer);
  RefCountedPtr<ChannelTrace> sc2 = MakeRefCounted<ChannelTrace>(GetParam());
  tracer->AddTraceEventReferencingChannel(
      ChannelTrace::Severity::Info,
      grpc_slice_from_static_string("LB channel two created"), sc2);
  tracer->AddTraceEventReferencingSubchannel(
      ChannelTrace::Severity::Warning,
      grpc_slice_from_static_string("subchannel one inactive"), sc1);
  ValidateChannelTrace(tracer, 7, GetParam());
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  ValidateTraceDataMatchedUuidLookup(tracer);
  tracer.reset(nullptr);
  sc1.reset(nullptr);
  sc2.reset(nullptr);
}

// Test a case in which the parent channel has subchannels and the subchannels
// have connections. Ensures that everything lives as long as it should then
// gets deleted.
TEST_P(ChannelTracerTest, TestNesting) {
  grpc_core::ExecCtx exec_ctx;
  RefCountedPtr<ChannelTrace> tracer = MakeRefCounted<ChannelTrace>(GetParam());
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  RefCountedPtr<ChannelTrace> sc1 = MakeRefCounted<ChannelTrace>(GetParam());
  tracer->AddTraceEventReferencingChannel(
      ChannelTrace::Severity::Info,
      grpc_slice_from_static_string("subchannel one created"), sc1);
  AddSimpleTrace(sc1);
  RefCountedPtr<ChannelTrace> conn1 = MakeRefCounted<ChannelTrace>(GetParam());
  // nesting one level deeper.
  sc1->AddTraceEventReferencingSubchannel(
      ChannelTrace::Severity::Info,
      grpc_slice_from_static_string("connection one created"), conn1);
  AddSimpleTrace(conn1);
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  RefCountedPtr<ChannelTrace> sc2 = MakeRefCounted<ChannelTrace>(GetParam());
  tracer->AddTraceEventReferencingSubchannel(
      ChannelTrace::Severity::Info,
      grpc_slice_from_static_string("subchannel two created"), sc2);
  // this trace should not get added to the parents children since it is already
  // present in the tracer.
  tracer->AddTraceEventReferencingChannel(
      ChannelTrace::Severity::Warning,
      grpc_slice_from_static_string("subchannel one inactive"), sc1);
  AddSimpleTrace(tracer);
  tracer.reset(nullptr);
  sc1.reset(nullptr);
  sc2.reset(nullptr);
  conn1.reset(nullptr);
}

INSTANTIATE_TEST_CASE_P(ChannelTracerTestSweep, ChannelTracerTest,
                        ::testing::Values(0, 1, 2, 6, 10, 15));

}  // namespace testing
}  // namespace grpc_core

int main(int argc, char** argv) {
  grpc_test_init(argc, argv);
  grpc_init();
  ::testing::InitGoogleTest(&argc, argv);
  int ret = RUN_ALL_TESTS();
  grpc_shutdown();
  return ret;
}
<commit_msg>Add more validation tests to channel_trace_test<commit_after>/*
 *
 * Copyright 2017 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 <stdlib.h>
#include <string.h>

#include <gtest/gtest.h>

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>

#include "src/core/lib/channel/channel_trace.h"
#include "src/core/lib/channel/channel_trace_registry.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/json/json.h"

#include "test/core/util/test_config.h"
#include "test/cpp/util/channel_trace_proto_helper.h"

// remove me
#include <grpc/support/string_util.h>
#include <stdlib.h>
#include <string.h>

namespace grpc_core {
namespace testing {
namespace {

grpc_json* GetJsonChild(grpc_json* parent, const char* key) {
  EXPECT_NE(parent, nullptr);
  for (grpc_json* child = parent->child; child != nullptr;
       child = child->next) {
    if (child->key != nullptr && strcmp(child->key, key) == 0) return child;
  }
  return nullptr;
}

void ValidateJsonArraySize(grpc_json* json, const char* key,
                           size_t expected_size) {
  grpc_json* arr = GetJsonChild(json, key);
  ASSERT_NE(arr, nullptr);
  ASSERT_EQ(arr->type, GRPC_JSON_ARRAY);
  size_t count = 0;
  for (grpc_json* child = arr->child; child != nullptr; child = child->next) {
    ++count;
  }
  ASSERT_EQ(count, expected_size);
}

void ValidateChannelTraceData(grpc_json* json,
                              size_t num_events_logged_expected,
                              size_t actual_num_events_expected) {
  ASSERT_NE(json, nullptr);
  grpc_json* num_events_logged_json = GetJsonChild(json, "numEventsLogged");
  ASSERT_NE(num_events_logged_json, nullptr);
  grpc_json* start_time = GetJsonChild(json, "creationTime");
  ASSERT_NE(start_time, nullptr);
  size_t num_events_logged =
      (size_t)strtol(num_events_logged_json->value, nullptr, 0);
  ASSERT_EQ(num_events_logged, num_events_logged_expected);
  ValidateJsonArraySize(json, "events", actual_num_events_expected);
}

void AddSimpleTrace(RefCountedPtr<ChannelTrace> tracer) {
  tracer->AddTraceEvent(ChannelTrace::Severity::Info,
                        grpc_slice_from_static_string("simple trace"));
}

// checks for the existence of all the required members of the tracer.
void ValidateChannelTrace(RefCountedPtr<ChannelTrace> tracer,
                          size_t expected_num_event_logged, size_t max_nodes) {
  if (!max_nodes) return;
  char* json_str = tracer->RenderTrace();
  grpc::testing::ValidateChannelTraceProtoJsonTranslation(json_str);
  grpc_json* json = grpc_json_parse_string(json_str);
  ValidateChannelTraceData(json, expected_num_event_logged,
                           GPR_MIN(expected_num_event_logged, max_nodes));
  grpc_json_destroy(json);
  gpr_free(json_str);
}

void ValidateTraceDataMatchedUuidLookup(RefCountedPtr<ChannelTrace> tracer) {
  intptr_t uuid = tracer->GetUuid();
  if (uuid == -1) return;  // Doesn't make sense to lookup if tracing disabled
  char* tracer_json_str = tracer->RenderTrace();
  ChannelTrace* uuid_lookup =
      grpc_channel_trace_registry_get_channel_trace(uuid);
  char* uuid_lookup_json_str = uuid_lookup->RenderTrace();
  EXPECT_EQ(strcmp(tracer_json_str, uuid_lookup_json_str), 0);
  gpr_free(tracer_json_str);
  gpr_free(uuid_lookup_json_str);
}

}  // anonymous namespace

class ChannelTracerTest : public ::testing::TestWithParam<size_t> {};

// Tests basic ChannelTrace functionality like construction, adding trace, and
// lookups by uuid.
TEST_P(ChannelTracerTest, BasicTest) {
  grpc_core::ExecCtx exec_ctx;
  RefCountedPtr<ChannelTrace> tracer = MakeRefCounted<ChannelTrace>(GetParam());
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  ValidateTraceDataMatchedUuidLookup(tracer);
  tracer->AddTraceEvent(ChannelTrace::Severity::Info,
                        grpc_slice_from_static_string("trace three"));
  tracer->AddTraceEvent(ChannelTrace::Severity::Error,
                        grpc_slice_from_static_string("trace four error"));
  ValidateChannelTrace(tracer, 4, GetParam());
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  ValidateChannelTrace(tracer, 6, GetParam());
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  ValidateChannelTrace(tracer, 10, GetParam());
  ValidateTraceDataMatchedUuidLookup(tracer);
  tracer.reset(nullptr);
}

// Tests more complex functionality, like a parent channel tracking
// subchannles. This exercises the ref/unref patterns since the parent tracer
// and this function will both hold refs to the subchannel.
TEST_P(ChannelTracerTest, ComplexTest) {
  grpc_core::ExecCtx exec_ctx;
  RefCountedPtr<ChannelTrace> tracer = MakeRefCounted<ChannelTrace>(GetParam());
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  RefCountedPtr<ChannelTrace> sc1 = MakeRefCounted<ChannelTrace>(GetParam());
  tracer->AddTraceEventReferencingSubchannel(
      ChannelTrace::Severity::Info,
      grpc_slice_from_static_string("subchannel one created"), sc1);
  ValidateChannelTrace(tracer, 3, GetParam());
  AddSimpleTrace(sc1);
  AddSimpleTrace(sc1);
  AddSimpleTrace(sc1);
  ValidateChannelTrace(sc1, 3, GetParam());
  AddSimpleTrace(sc1);
  AddSimpleTrace(sc1);
  AddSimpleTrace(sc1);
  ValidateChannelTrace(sc1, 6, GetParam());
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  ValidateChannelTrace(tracer, 5, GetParam());
  ValidateTraceDataMatchedUuidLookup(tracer);
  RefCountedPtr<ChannelTrace> sc2 = MakeRefCounted<ChannelTrace>(GetParam());
  tracer->AddTraceEventReferencingChannel(
      ChannelTrace::Severity::Info,
      grpc_slice_from_static_string("LB channel two created"), sc2);
  tracer->AddTraceEventReferencingSubchannel(
      ChannelTrace::Severity::Warning,
      grpc_slice_from_static_string("subchannel one inactive"), sc1);
  ValidateChannelTrace(tracer, 7, GetParam());
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  ValidateTraceDataMatchedUuidLookup(tracer);
  tracer.reset(nullptr);
  sc1.reset(nullptr);
  sc2.reset(nullptr);
}

// Test a case in which the parent channel has subchannels and the subchannels
// have connections. Ensures that everything lives as long as it should then
// gets deleted.
TEST_P(ChannelTracerTest, TestNesting) {
  grpc_core::ExecCtx exec_ctx;
  RefCountedPtr<ChannelTrace> tracer = MakeRefCounted<ChannelTrace>(GetParam());
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  ValidateChannelTrace(tracer, 2, GetParam());
  RefCountedPtr<ChannelTrace> sc1 = MakeRefCounted<ChannelTrace>(GetParam());
  tracer->AddTraceEventReferencingChannel(
      ChannelTrace::Severity::Info,
      grpc_slice_from_static_string("subchannel one created"), sc1);
  ValidateChannelTrace(tracer, 3, GetParam());
  AddSimpleTrace(sc1);
  RefCountedPtr<ChannelTrace> conn1 = MakeRefCounted<ChannelTrace>(GetParam());
  // nesting one level deeper.
  sc1->AddTraceEventReferencingSubchannel(
      ChannelTrace::Severity::Info,
      grpc_slice_from_static_string("connection one created"), conn1);
  ValidateChannelTrace(tracer, 3, GetParam());
  AddSimpleTrace(conn1);
  AddSimpleTrace(tracer);
  AddSimpleTrace(tracer);
  ValidateChannelTrace(tracer, 5, GetParam());
  ValidateChannelTrace(conn1, 1, GetParam());
  RefCountedPtr<ChannelTrace> sc2 = MakeRefCounted<ChannelTrace>(GetParam());
  tracer->AddTraceEventReferencingSubchannel(
      ChannelTrace::Severity::Info,
      grpc_slice_from_static_string("subchannel two created"), sc2);
  // this trace should not get added to the parents children since it is already
  // present in the tracer.
  tracer->AddTraceEventReferencingChannel(
      ChannelTrace::Severity::Warning,
      grpc_slice_from_static_string("subchannel one inactive"), sc1);
  AddSimpleTrace(tracer);
  ValidateChannelTrace(tracer, 8, GetParam());
  tracer.reset(nullptr);
  sc1.reset(nullptr);
  sc2.reset(nullptr);
  conn1.reset(nullptr);
}

INSTANTIATE_TEST_CASE_P(ChannelTracerTestSweep, ChannelTracerTest,
                        ::testing::Values(0, 1, 2, 6, 10, 15));

}  // namespace testing
}  // namespace grpc_core

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


<commit_before>/*
 *
 * Copyright 2017 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.
 *
 */

/* Test out various metadata handling primitives */

#include <benchmark/benchmark.h>
#include <grpc/grpc.h>

#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/static_metadata.h"

#include "test/cpp/microbenchmarks/helpers.h"
#include "test/cpp/util/test_config.h"

static void BM_SliceFromStatic(benchmark::State& state) {
  TrackCounters track_counters;
  for (auto _ : state) {
    benchmark::DoNotOptimize(grpc_core::ExternallyManagedSlice("abc"));
  }
  track_counters.Finish(state);
}
BENCHMARK(BM_SliceFromStatic);

static void BM_SliceFromCopied(benchmark::State& state) {
  TrackCounters track_counters;
  for (auto _ : state) {
    grpc_slice_unref(grpc_core::UnmanagedMemorySlice("abc"));
  }
  track_counters.Finish(state);
}
BENCHMARK(BM_SliceFromCopied);

static void BM_SliceIntern(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExternallyManagedSlice slice("abc");
  for (auto _ : state) {
    grpc_slice_unref(grpc_core::ManagedMemorySlice(&slice));
  }
  track_counters.Finish(state);
}
BENCHMARK(BM_SliceIntern);

static void BM_SliceReIntern(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExternallyManagedSlice static_slice("abc");
  grpc_core::ManagedMemorySlice slice(&static_slice);
  for (auto _ : state) {
    grpc_slice_unref(grpc_core::ManagedMemorySlice(&slice));
  }
  track_counters.Finish(state);
}
BENCHMARK(BM_SliceReIntern);

static void BM_SliceInternStaticMetadata(benchmark::State& state) {
  TrackCounters track_counters;
  for (auto _ : state) {
    benchmark::DoNotOptimize(grpc_core::ManagedMemorySlice(&GRPC_MDSTR_GZIP));
  }
  track_counters.Finish(state);
}
BENCHMARK(BM_SliceInternStaticMetadata);

static void BM_SliceInternEqualToStaticMetadata(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExternallyManagedSlice slice("gzip");
  for (auto _ : state) {
    benchmark::DoNotOptimize(grpc_core::ManagedMemorySlice(&slice));
  }
  track_counters.Finish(state);
}
BENCHMARK(BM_SliceInternEqualToStaticMetadata);

static void BM_MetadataFromNonInternedSlices(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExternallyManagedSlice k("key");
  grpc_core::ExternallyManagedSlice v("value");
  grpc_core::ExecCtx exec_ctx;
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(grpc_mdelem_create(k, v, nullptr));
  }

  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromNonInternedSlices);

static void BM_MetadataFromInternedSlices(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ManagedMemorySlice k("key");
  grpc_core::ManagedMemorySlice v("value");
  grpc_core::ExecCtx exec_ctx;
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(grpc_mdelem_create(k, v, nullptr));
  }

  grpc_slice_unref(k);
  grpc_slice_unref(v);
  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromInternedSlices);

static void BM_MetadataFromInternedSlicesAlreadyInIndex(
    benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ManagedMemorySlice k("key");
  grpc_core::ManagedMemorySlice v("value");
  grpc_core::ExecCtx exec_ctx;
  grpc_mdelem seed = grpc_mdelem_create(k, v, nullptr);
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(grpc_mdelem_create(k, v, nullptr));
  }
  GRPC_MDELEM_UNREF(seed);

  grpc_slice_unref(k);
  grpc_slice_unref(v);
  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromInternedSlicesAlreadyInIndex);

static void BM_MetadataFromInternedKey(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ManagedMemorySlice k("key");
  grpc_core::ExternallyManagedSlice v("value");
  grpc_core::ExecCtx exec_ctx;
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(grpc_mdelem_create(k, v, nullptr));
  }

  grpc_slice_unref(k);
  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromInternedKey);

static void BM_MetadataFromNonInternedSlicesWithBackingStore(
    benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExternallyManagedSlice k("key");
  grpc_core::ExternallyManagedSlice v("value");
  char backing_store[sizeof(grpc_mdelem_data)];
  grpc_core::ExecCtx exec_ctx;
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(grpc_mdelem_create(
        k, v, reinterpret_cast<grpc_mdelem_data*>(backing_store)));
  }

  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromNonInternedSlicesWithBackingStore);

static void BM_MetadataFromInternedSlicesWithBackingStore(
    benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ManagedMemorySlice k("key");
  grpc_core::ManagedMemorySlice v("value");
  char backing_store[sizeof(grpc_mdelem_data)];
  grpc_core::ExecCtx exec_ctx;
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(grpc_mdelem_create(
        k, v, reinterpret_cast<grpc_mdelem_data*>(backing_store)));
  }

  grpc_slice_unref(k);
  grpc_slice_unref(v);
  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromInternedSlicesWithBackingStore);

static void BM_MetadataFromInternedKeyWithBackingStore(
    benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ManagedMemorySlice k("key");
  grpc_core::ExternallyManagedSlice v("value");
  char backing_store[sizeof(grpc_mdelem_data)];
  grpc_core::ExecCtx exec_ctx;
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(grpc_mdelem_create(
        k, v, reinterpret_cast<grpc_mdelem_data*>(backing_store)));
  }

  grpc_slice_unref(k);
  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromInternedKeyWithBackingStore);

static void BM_MetadataFromStaticMetadataStrings(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExecCtx exec_ctx;
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(
        grpc_mdelem_create(GRPC_MDSTR_STATUS, GRPC_MDSTR_200, nullptr));
  }

  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromStaticMetadataStrings);

static void BM_MetadataFromStaticMetadataStringsNotIndexed(
    benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExecCtx exec_ctx;
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(
        grpc_mdelem_create(GRPC_MDSTR_STATUS, GRPC_MDSTR_GZIP, nullptr));
  }

  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromStaticMetadataStringsNotIndexed);

static void BM_MetadataRefUnrefExternal(benchmark::State& state) {
  TrackCounters track_counters;
  char backing_store[sizeof(grpc_mdelem_data)];
  grpc_core::ExecCtx exec_ctx;
  grpc_mdelem el =
      grpc_mdelem_create(grpc_core::ExternallyManagedSlice("a"),
                         grpc_core::ExternallyManagedSlice("b"),
                         reinterpret_cast<grpc_mdelem_data*>(backing_store));
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(GRPC_MDELEM_REF(el));
  }
  GRPC_MDELEM_UNREF(el);

  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataRefUnrefExternal);

static void BM_MetadataRefUnrefInterned(benchmark::State& state) {
  TrackCounters track_counters;
  char backing_store[sizeof(grpc_mdelem_data)];
  grpc_core::ExecCtx exec_ctx;
  grpc_core::ManagedMemorySlice k("key");
  grpc_core::ManagedMemorySlice v("value");
  grpc_mdelem el = grpc_mdelem_create(
      k, v, reinterpret_cast<grpc_mdelem_data*>(backing_store));
  grpc_slice_unref(k);
  grpc_slice_unref(v);
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(GRPC_MDELEM_REF(el));
  }
  GRPC_MDELEM_UNREF(el);

  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataRefUnrefInterned);

static void BM_MetadataRefUnrefAllocated(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExecCtx exec_ctx;
  grpc_mdelem el =
      grpc_mdelem_create(grpc_core::ExternallyManagedSlice("a"),
                         grpc_core::ExternallyManagedSlice("b"), nullptr);
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(GRPC_MDELEM_REF(el));
  }
  GRPC_MDELEM_UNREF(el);

  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataRefUnrefAllocated);

static void BM_MetadataRefUnrefStatic(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExecCtx exec_ctx;
  grpc_mdelem el =
      grpc_mdelem_create(GRPC_MDSTR_STATUS, GRPC_MDSTR_200, nullptr);
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(GRPC_MDELEM_REF(el));
  }
  GRPC_MDELEM_UNREF(el);

  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataRefUnrefStatic);

// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
// and others do not. This allows us to support both modes.
namespace benchmark {
void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
}  // namespace benchmark

int main(int argc, char** argv) {
  LibraryInitializer libInit;
  ::benchmark::Initialize(&argc, argv);
  ::grpc::testing::InitTest(&argc, &argv, false);
  benchmark::RunTheBenchmarksNamespaced();
  return 0;
}
<commit_msg>Add missing grpc_slice_unref to bm_metadata<commit_after>/*
 *
 * Copyright 2017 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.
 *
 */

/* Test out various metadata handling primitives */

#include <benchmark/benchmark.h>
#include <grpc/grpc.h>

#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/static_metadata.h"

#include "test/cpp/microbenchmarks/helpers.h"
#include "test/cpp/util/test_config.h"

static void BM_SliceFromStatic(benchmark::State& state) {
  TrackCounters track_counters;
  for (auto _ : state) {
    benchmark::DoNotOptimize(grpc_core::ExternallyManagedSlice("abc"));
  }
  track_counters.Finish(state);
}
BENCHMARK(BM_SliceFromStatic);

static void BM_SliceFromCopied(benchmark::State& state) {
  TrackCounters track_counters;
  for (auto _ : state) {
    grpc_slice_unref(grpc_core::UnmanagedMemorySlice("abc"));
  }
  track_counters.Finish(state);
}
BENCHMARK(BM_SliceFromCopied);

static void BM_SliceIntern(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExternallyManagedSlice slice("abc");
  for (auto _ : state) {
    grpc_slice_unref(grpc_core::ManagedMemorySlice(&slice));
  }
  track_counters.Finish(state);
}
BENCHMARK(BM_SliceIntern);

static void BM_SliceReIntern(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExternallyManagedSlice static_slice("abc");
  grpc_core::ManagedMemorySlice slice(&static_slice);
  for (auto _ : state) {
    grpc_slice_unref(grpc_core::ManagedMemorySlice(&slice));
  }
  grpc_slice_unref(slice);
  track_counters.Finish(state);
}
BENCHMARK(BM_SliceReIntern);

static void BM_SliceInternStaticMetadata(benchmark::State& state) {
  TrackCounters track_counters;
  for (auto _ : state) {
    benchmark::DoNotOptimize(grpc_core::ManagedMemorySlice(&GRPC_MDSTR_GZIP));
  }
  track_counters.Finish(state);
}
BENCHMARK(BM_SliceInternStaticMetadata);

static void BM_SliceInternEqualToStaticMetadata(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExternallyManagedSlice slice("gzip");
  for (auto _ : state) {
    benchmark::DoNotOptimize(grpc_core::ManagedMemorySlice(&slice));
  }
  track_counters.Finish(state);
}
BENCHMARK(BM_SliceInternEqualToStaticMetadata);

static void BM_MetadataFromNonInternedSlices(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExternallyManagedSlice k("key");
  grpc_core::ExternallyManagedSlice v("value");
  grpc_core::ExecCtx exec_ctx;
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(grpc_mdelem_create(k, v, nullptr));
  }

  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromNonInternedSlices);

static void BM_MetadataFromInternedSlices(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ManagedMemorySlice k("key");
  grpc_core::ManagedMemorySlice v("value");
  grpc_core::ExecCtx exec_ctx;
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(grpc_mdelem_create(k, v, nullptr));
  }

  grpc_slice_unref(k);
  grpc_slice_unref(v);
  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromInternedSlices);

static void BM_MetadataFromInternedSlicesAlreadyInIndex(
    benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ManagedMemorySlice k("key");
  grpc_core::ManagedMemorySlice v("value");
  grpc_core::ExecCtx exec_ctx;
  grpc_mdelem seed = grpc_mdelem_create(k, v, nullptr);
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(grpc_mdelem_create(k, v, nullptr));
  }
  GRPC_MDELEM_UNREF(seed);

  grpc_slice_unref(k);
  grpc_slice_unref(v);
  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromInternedSlicesAlreadyInIndex);

static void BM_MetadataFromInternedKey(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ManagedMemorySlice k("key");
  grpc_core::ExternallyManagedSlice v("value");
  grpc_core::ExecCtx exec_ctx;
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(grpc_mdelem_create(k, v, nullptr));
  }

  grpc_slice_unref(k);
  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromInternedKey);

static void BM_MetadataFromNonInternedSlicesWithBackingStore(
    benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExternallyManagedSlice k("key");
  grpc_core::ExternallyManagedSlice v("value");
  char backing_store[sizeof(grpc_mdelem_data)];
  grpc_core::ExecCtx exec_ctx;
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(grpc_mdelem_create(
        k, v, reinterpret_cast<grpc_mdelem_data*>(backing_store)));
  }

  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromNonInternedSlicesWithBackingStore);

static void BM_MetadataFromInternedSlicesWithBackingStore(
    benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ManagedMemorySlice k("key");
  grpc_core::ManagedMemorySlice v("value");
  char backing_store[sizeof(grpc_mdelem_data)];
  grpc_core::ExecCtx exec_ctx;
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(grpc_mdelem_create(
        k, v, reinterpret_cast<grpc_mdelem_data*>(backing_store)));
  }

  grpc_slice_unref(k);
  grpc_slice_unref(v);
  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromInternedSlicesWithBackingStore);

static void BM_MetadataFromInternedKeyWithBackingStore(
    benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ManagedMemorySlice k("key");
  grpc_core::ExternallyManagedSlice v("value");
  char backing_store[sizeof(grpc_mdelem_data)];
  grpc_core::ExecCtx exec_ctx;
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(grpc_mdelem_create(
        k, v, reinterpret_cast<grpc_mdelem_data*>(backing_store)));
  }

  grpc_slice_unref(k);
  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromInternedKeyWithBackingStore);

static void BM_MetadataFromStaticMetadataStrings(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExecCtx exec_ctx;
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(
        grpc_mdelem_create(GRPC_MDSTR_STATUS, GRPC_MDSTR_200, nullptr));
  }

  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromStaticMetadataStrings);

static void BM_MetadataFromStaticMetadataStringsNotIndexed(
    benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExecCtx exec_ctx;
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(
        grpc_mdelem_create(GRPC_MDSTR_STATUS, GRPC_MDSTR_GZIP, nullptr));
  }

  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromStaticMetadataStringsNotIndexed);

static void BM_MetadataRefUnrefExternal(benchmark::State& state) {
  TrackCounters track_counters;
  char backing_store[sizeof(grpc_mdelem_data)];
  grpc_core::ExecCtx exec_ctx;
  grpc_mdelem el =
      grpc_mdelem_create(grpc_core::ExternallyManagedSlice("a"),
                         grpc_core::ExternallyManagedSlice("b"),
                         reinterpret_cast<grpc_mdelem_data*>(backing_store));
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(GRPC_MDELEM_REF(el));
  }
  GRPC_MDELEM_UNREF(el);

  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataRefUnrefExternal);

static void BM_MetadataRefUnrefInterned(benchmark::State& state) {
  TrackCounters track_counters;
  char backing_store[sizeof(grpc_mdelem_data)];
  grpc_core::ExecCtx exec_ctx;
  grpc_core::ManagedMemorySlice k("key");
  grpc_core::ManagedMemorySlice v("value");
  grpc_mdelem el = grpc_mdelem_create(
      k, v, reinterpret_cast<grpc_mdelem_data*>(backing_store));
  grpc_slice_unref(k);
  grpc_slice_unref(v);
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(GRPC_MDELEM_REF(el));
  }
  GRPC_MDELEM_UNREF(el);

  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataRefUnrefInterned);

static void BM_MetadataRefUnrefAllocated(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExecCtx exec_ctx;
  grpc_mdelem el =
      grpc_mdelem_create(grpc_core::ExternallyManagedSlice("a"),
                         grpc_core::ExternallyManagedSlice("b"), nullptr);
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(GRPC_MDELEM_REF(el));
  }
  GRPC_MDELEM_UNREF(el);

  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataRefUnrefAllocated);

static void BM_MetadataRefUnrefStatic(benchmark::State& state) {
  TrackCounters track_counters;
  grpc_core::ExecCtx exec_ctx;
  grpc_mdelem el =
      grpc_mdelem_create(GRPC_MDSTR_STATUS, GRPC_MDSTR_200, nullptr);
  for (auto _ : state) {
    GRPC_MDELEM_UNREF(GRPC_MDELEM_REF(el));
  }
  GRPC_MDELEM_UNREF(el);

  track_counters.Finish(state);
}
BENCHMARK(BM_MetadataRefUnrefStatic);

// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
// and others do not. This allows us to support both modes.
namespace benchmark {
void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
}  // namespace benchmark

int main(int argc, char** argv) {
  LibraryInitializer libInit;
  ::benchmark::Initialize(&argc, argv);
  ::grpc::testing::InitTest(&argc, &argv, false);
  benchmark::RunTheBenchmarksNamespaced();
  return 0;
}
<|endoftext|>


<commit_before><commit_msg>routing: added QoS similar to ros latch mode<commit_after><|endoftext|>


<commit_before>#include <QtTest/QtTest>
#include <QProcess>

namespace cutehmi {
namespace daemon {

class test_cutehmi_daemon:
	public QObject
{
	Q_OBJECT

	private slots:
		void initTestCase();

		void helpOption();

		void versionOption();

		void countDaemonExample();

	private:
		QString m_installRoot;
		QString m_programPath;
};

void test_cutehmi_daemon::initTestCase()
{
	QString m_installRoot = qEnvironmentVariable("CUTEHMI_INSTALL_ROOT");
	QVERIFY(!m_installRoot.isEmpty());

	m_programPath = m_installRoot + "/bin/cutehmi_daemon";
#ifndef CUTEHMI_NDEBUG
	m_programPath += "_debug";
#endif
}

void test_cutehmi_daemon::helpOption()
{
	QList<QStringList> argumentsList;
	argumentsList << QStringList({"--help"})
				  << QStringList({"--h"});

	for (auto arguments: argumentsList) {
		QProcess process;
		process.start(m_programPath, arguments);
		process.waitForFinished(1000);
		QCOMPARE(process.error(), QProcess::UnknownError);
		QVERIFY(!process.readAllStandardError().contains("Unknown option"));
		QVERIFY(!process.readAllStandardOutput().isEmpty());
		QCOMPARE(process.exitStatus(), QProcess::NormalExit);
		QCOMPARE(process.exitCode(), EXIT_SUCCESS);
	}
}

void test_cutehmi_daemon::versionOption()
{
	QList<QStringList> argumentsList;
	argumentsList << QStringList({"--version"})
				  << QStringList({"--v"});

	for (auto arguments: argumentsList) {
		QProcess process;
		process.start(m_programPath, arguments);
		process.waitForFinished(1000);
		QCOMPARE(process.error(), QProcess::UnknownError);
		QVERIFY(!process.readAllStandardError().contains("Unknown option"));
		QVERIFY(!process.readAllStandardOutput().isEmpty());
		QCOMPARE(process.exitStatus(), QProcess::NormalExit);
		QCOMPARE(process.exitCode(), EXIT_SUCCESS);
	}
}

void test_cutehmi_daemon::countDaemonExample()
{
	QProcess process;
	QStringList arguments { {"--app"}, {"--project=examples/CountDaemon/Main.qml"} };
	process.start(m_programPath, arguments);
	process.waitForFinished();

	QString stdOut = QString::fromLocal8Bit(process.readAllStandardOutput());
	QString stdErr = QString::fromLocal8Bit(process.readAllStandardError());

	QVERIFY(!stdErr.contains("Unknown option"));

	{
		QRegExp rx(".*(Project file .* does not exist).*");
		QVERIFY2(!rx.exactMatch(stdErr), rx.cap(1).toLocal8Bit().constData());
	}

	QVERIFY(stdErr.contains("I can count"));

	QCOMPARE(process.error(), QProcess::UnknownError);
	QCOMPARE(process.exitStatus(), QProcess::NormalExit);
	QCOMPARE(process.exitCode(), EXIT_SUCCESS);
}

}
}

QTEST_MAIN(cutehmi::daemon::test_cutehmi_daemon)
#include "test_cutehmi_daemon.moc"

//(c)MP: Copyright © 2019, Michal Policht. All rights reserved.
//(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
<commit_msg>Verify that process has finished.<commit_after>#include <QtTest/QtTest>
#include <QProcess>

namespace cutehmi {
namespace daemon {

class test_cutehmi_daemon:
	public QObject
{
	Q_OBJECT

	private slots:
		void initTestCase();

		void helpOption();

		void versionOption();

		void countDaemonExample();

	private:
		QString m_installRoot;
		QString m_programPath;
};

void test_cutehmi_daemon::initTestCase()
{
	QString m_installRoot = qEnvironmentVariable("CUTEHMI_INSTALL_ROOT");
	QVERIFY(!m_installRoot.isEmpty());

	m_programPath = m_installRoot + "/bin/cutehmi_daemon";
#ifndef CUTEHMI_NDEBUG
	m_programPath += "_debug";
#endif
}

void test_cutehmi_daemon::helpOption()
{
	QList<QStringList> argumentsList;
	argumentsList << QStringList({"--help"})
				  << QStringList({"--h"});

	for (auto arguments: argumentsList) {
		QProcess process;
		process.start(m_programPath, arguments);
		process.waitForFinished(1000);
		QCOMPARE(process.error(), QProcess::UnknownError);
		QVERIFY(!process.readAllStandardError().contains("Unknown option"));
		QVERIFY(!process.readAllStandardOutput().isEmpty());
		QCOMPARE(process.exitStatus(), QProcess::NormalExit);
		QCOMPARE(process.exitCode(), EXIT_SUCCESS);
	}
}

void test_cutehmi_daemon::versionOption()
{
	QList<QStringList> argumentsList;
	argumentsList << QStringList({"--version"})
				  << QStringList({"--v"});

	for (auto arguments: argumentsList) {
		QProcess process;
		process.start(m_programPath, arguments);
		process.waitForFinished(1000);
		QCOMPARE(process.error(), QProcess::UnknownError);
		QVERIFY(!process.readAllStandardError().contains("Unknown option"));
		QVERIFY(!process.readAllStandardOutput().isEmpty());
		QCOMPARE(process.exitStatus(), QProcess::NormalExit);
		QCOMPARE(process.exitCode(), EXIT_SUCCESS);
	}
}

void test_cutehmi_daemon::countDaemonExample()
{
	QProcess process;
	QStringList arguments { {"--app"}, {"--project=examples/CountDaemon/Main.qml"} };
	process.start(m_programPath, arguments);
	QVERIFY(process.waitForFinished());

	QString stdOut = QString::fromLocal8Bit(process.readAllStandardOutput());
	QString stdErr = QString::fromLocal8Bit(process.readAllStandardError());

	QVERIFY(!stdErr.contains("Unknown option"));

	{
		QRegExp rx(".*(Project file .* does not exist).*");
		QVERIFY2(!rx.exactMatch(stdErr), rx.cap(1).toLocal8Bit().constData());
	}

	QVERIFY(stdErr.contains("I can count"));

	QCOMPARE(process.error(), QProcess::UnknownError);
	QCOMPARE(process.exitStatus(), QProcess::NormalExit);
	QCOMPARE(process.exitCode(), EXIT_SUCCESS);
}

}
}

QTEST_MAIN(cutehmi::daemon::test_cutehmi_daemon)
#include "test_cutehmi_daemon.moc"

//(c)MP: Copyright © 2019, Michal Policht. All rights reserved.
//(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// packet_manager_test.cpp
//
// Identification: test/wire/packet_manager_test.cpp
//
// Copyright (c) 2016-17, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "common/harness.h"
#include "gtest/gtest.h"
#include "common/logger.h"
#include "wire/libevent_server.h"
#include <pqxx/pqxx> /* libpqxx is used to instantiate C++ client */

#define NUM_THREADS 1

namespace peloton {
namespace test {

//===--------------------------------------------------------------------===//
// Packet Manager Tests
//===--------------------------------------------------------------------===//

class PacketManagerTests : public PelotonTest {};

static void *LaunchServer(peloton::wire::LibeventServer libeventserver) {
  try {
    libeventserver.StartServer();
  } catch (peloton::ConnectionException exception) {
    LOG_INFO("[LaunchServer] exception in thread");
  }
  return NULL;
}

/**
 * Simple select query test
 */
static void *SimpleQueryTest(void *) {
  try {
    pqxx::connection C(
        "host=127.0.0.1 port=15721 user=postgres sslmode=disable");
    LOG_INFO("[SimpleQueryTest] Connected to %s", C.dbname());
    pqxx::work W(C);

    peloton::wire::LibeventSocket *conn =
        peloton::wire::LibeventServer::GetConn(
            peloton::wire::LibeventServer::recent_connfd);

    EXPECT_EQ(conn->pkt_manager.is_started, true);
    EXPECT_EQ(conn->state, peloton::wire::CONN_READ);
    // create table and insert some data
    W.exec("DROP TABLE IF EXISTS employee;");
    W.exec("CREATE TABLE employee(id INT, name VARCHAR(100));");
    W.exec("INSERT INTO employee VALUES (1, 'Han LI');");
    W.exec("INSERT INTO employee VALUES (2, 'Shaokun ZOU');");
    W.exec("INSERT INTO employee VALUES (3, 'Yilei CHU');");

    pqxx::result R = W.exec("SELECT name FROM employee where id=1;");

    EXPECT_EQ(R.size(), 1);
    LOG_INFO("[SimpleQueryTest] Found %lu employees", R.size());
    W.commit();
  } catch (const std::exception &e) {
    LOG_INFO("[SimpleQueryTest] Exception occurred");
  }

  LOG_INFO("[SimpleQueryTest] Client has closed");
  return NULL;
}

/**
 * named prepare statement without parameters
 * TODO: add prepare's parameters when parser team fix the bug
 */

static void *PrepareStatementTest(void *) {
  try {
    pqxx::connection C(
        "host=127.0.0.1 port=15721 user=postgres sslmode=disable");
    LOG_INFO("[PrepareStatementTest] Connected to %s", C.dbname());
    pqxx::work W(C);

    peloton::wire::LibeventSocket *conn =
        peloton::wire::LibeventServer::GetConn(
            peloton::wire::LibeventServer::recent_connfd);

    // create table and insert some data
    W.exec("DROP TABLE IF EXISTS employee;");
    W.exec("CREATE TABLE employee(id INT, name VARCHAR(100));");
    W.exec("INSERT INTO employee VALUES (1, 'Han LI');");
    W.exec("INSERT INTO employee VALUES (2, 'Shaokun ZOU');");
    W.exec("INSERT INTO employee VALUES (3, 'Yilei CHU');");

    // test prepare statement
    C.prepare("searchstmt","SELECT name FROM employee WHERE id=1;");
    // invocation as in variable binding
    pqxx::result R = W.prepared("searchstmt").exec();
    W.commit();

    // test prepared statement already in statement cache
//    LOG_INFO("[Prepare statement cache] %d",conn->pkt_manager.ExistCachedStatement("searchstmt"));
    EXPECT_TRUE(conn->pkt_manager.ExistCachedStatement("searchstmt"));

    LOG_INFO("Prepare statement search result:%lu",R.size());
  } catch (const std::exception &e) {
    LOG_INFO("[PrepareStatementTest] Exception occurred");
  }

  LOG_INFO("[PrepareStatementTest] Client has closed");
  return NULL;
}

/**
 * Use std::thread to initiate peloton server and pqxx client in separate
 * threads
 * Simple query test to guarantee both sides run correctly
 * Callback method to close server after client finishes
 */
TEST_F(PacketManagerTests, SimpleQueryTest) {
  peloton::PelotonInit::Initialize();
  LOG_INFO("Server initialized");
  peloton::wire::LibeventServer libeventserver;
  std::thread serverThread(LaunchServer, libeventserver);
  while (!libeventserver.is_started) {
    sleep(1);
  }

  /* server & client running correctly */
  SimpleQueryTest(NULL);

  /* TODO: monitor packet_manager's status when receiving prepare statement from
   * client */
  // PrepareStatementTest(NULL);

  libeventserver.CloseServer();
  serverThread.join();
  LOG_INFO("Thread has joined");
  peloton::PelotonInit::Shutdown();
  LOG_INFO("Peloton has shut down\n");
}

TEST_F(PacketManagerTests, PrepareStatementTest) {
  peloton::PelotonInit::Initialize();
  LOG_INFO("Server initialized");
  peloton::wire::LibeventServer libeventserver;
  std::thread serverThread(LaunchServer, libeventserver);
  while (!libeventserver.is_started) {
    sleep(1);
  }

  PrepareStatementTest(NULL);

  libeventserver.CloseServer();
  serverThread.join();
  LOG_INFO("Thread has joined");
  peloton::PelotonInit::Shutdown();
  LOG_INFO("Peloton has shut down\n");
}

}  // End test namespace
}  // End peloton namespace
<commit_msg>add rollback test<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// packet_manager_test.cpp
//
// Identification: test/wire/packet_manager_test.cpp
//
// Copyright (c) 2016-17, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "common/harness.h"
#include "gtest/gtest.h"
#include "common/logger.h"
#include "wire/libevent_server.h"
#include <pqxx/pqxx> /* libpqxx is used to instantiate C++ client */

#define NUM_THREADS 1

namespace peloton {
namespace test {

//===--------------------------------------------------------------------===//
// Packet Manager Tests
//===--------------------------------------------------------------------===//

class PacketManagerTests : public PelotonTest {};

static void *LaunchServer(peloton::wire::LibeventServer libeventserver) {
  try {
    libeventserver.StartServer();
  } catch (peloton::ConnectionException exception) {
    LOG_INFO("[LaunchServer] exception in thread");
  }
  return NULL;
}

/**
 * Simple select query test
 */
static void *SimpleQueryTest(void *) {
  try {
    pqxx::connection C(
        "host=127.0.0.1 port=15721 user=postgres sslmode=disable");
    LOG_INFO("[SimpleQueryTest] Connected to %s", C.dbname());
    pqxx::work W(C);

    peloton::wire::LibeventSocket *conn =
        peloton::wire::LibeventServer::GetConn(
            peloton::wire::LibeventServer::recent_connfd);

    EXPECT_EQ(conn->pkt_manager.is_started, true);
    EXPECT_EQ(conn->state, peloton::wire::CONN_READ);
    // create table and insert some data
    W.exec("DROP TABLE IF EXISTS employee;");
    W.exec("CREATE TABLE employee(id INT, name VARCHAR(100));");
    W.exec("INSERT INTO employee VALUES (1, 'Han LI');");
    W.exec("INSERT INTO employee VALUES (2, 'Shaokun ZOU');");
    W.exec("INSERT INTO employee VALUES (3, 'Yilei CHU');");

    pqxx::result R = W.exec("SELECT name FROM employee where id=1;");

    EXPECT_EQ(R.size(), 1);
    LOG_INFO("[SimpleQueryTest] Found %lu employees", R.size());
    W.commit();
  } catch (const std::exception &e) {
    LOG_INFO("[SimpleQueryTest] Exception occurred");
  }

  LOG_INFO("[SimpleQueryTest] Client has closed");
  return NULL;
}

/**
 * named prepare statement without parameters
 * TODO: add prepare's parameters when parser team fix the bug
 */

static void *PrepareStatementTest(void *) {
  try {
    pqxx::connection C(
        "host=127.0.0.1 port=15721 user=postgres sslmode=disable");
    LOG_INFO("[PrepareStatementTest] Connected to %s", C.dbname());
    pqxx::work W(C);

    peloton::wire::LibeventSocket *conn =
        peloton::wire::LibeventServer::GetConn(
            peloton::wire::LibeventServer::recent_connfd);

    // create table and insert some data
    W.exec("DROP TABLE IF EXISTS employee;");
    W.exec("CREATE TABLE employee(id INT, name VARCHAR(100));");
    W.exec("INSERT INTO employee VALUES (1, 'Han LI');");
    W.exec("INSERT INTO employee VALUES (2, 'Shaokun ZOU');");
    W.exec("INSERT INTO employee VALUES (3, 'Yilei CHU');");

    // test prepare statement
    C.prepare("searchstmt","SELECT name FROM employee WHERE id=1;");
    // invocation as in variable binding
    pqxx::result R = W.prepared("searchstmt").exec();
    W.commit();

    // test prepared statement already in statement cache
//    LOG_INFO("[Prepare statement cache] %d",conn->pkt_manager.ExistCachedStatement("searchstmt"));
    EXPECT_TRUE(conn->pkt_manager.ExistCachedStatement("searchstmt"));

    LOG_INFO("Prepare statement search result:%lu",R.size());
  } catch (const std::exception &e) {
    LOG_INFO("[PrepareStatementTest] Exception occurred");
  }

  LOG_INFO("[PrepareStatementTest] Client has closed");
  return NULL;
}

/**
 * rollback test
 */
static void *RollbackTest(void *) {
  try {
    pqxx::connection C(
        "host=127.0.0.1 port=15721 user=postgres sslmode=disable");
    LOG_INFO("[RollbackTest] Connected to %s", C.dbname());
    pqxx::work W(C);

    peloton::wire::LibeventSocket *conn =
        peloton::wire::LibeventServer::GetConn(
            peloton::wire::LibeventServer::recent_connfd);

    EXPECT_EQ(conn->pkt_manager.is_started, true);
    EXPECT_EQ(conn->state, peloton::wire::CONN_READ);
    // create table and insert some data
    W.exec("DROP TABLE IF EXISTS employee;");
    W.exec("CREATE TABLE employee(id INT, name VARCHAR(100));");
    w.abort();

    // W.exec("INSERT INTO employee VALUES (1, 'Han LI');");
    // W.exec("INSERT INTO employee VALUES (2, 'Shaokun ZOU');");
    // W.exec("INSERT INTO employee VALUES (3, 'Yilei CHU');");

    pqxx::result R = W.exec("SELECT name FROM employee where id=1;");

    EXPECT_EQ(R.size(), 1);
    LOG_INFO("[RollbackTest] Found %lu employees", R.size());
    W.commit();
  } catch (const std::exception &e) {
    LOG_INFO("[RollbackTest] Exception occurred");
  }

  LOG_INFO("[RollbackTest] Client has closed");
  return NULL;
}

/**
 * Use std::thread to initiate peloton server and pqxx client in separate
 * threads
 * Simple query test to guarantee both sides run correctly
 * Callback method to close server after client finishes
 */
TEST_F(PacketManagerTests, SimpleQueryTest) {
  peloton::PelotonInit::Initialize();
  LOG_INFO("Server initialized");
  peloton::wire::LibeventServer libeventserver;
  std::thread serverThread(LaunchServer, libeventserver);
  while (!libeventserver.is_started) {
    sleep(1);
  }

  /* server & client running correctly */
  SimpleQueryTest(NULL);

  /* TODO: monitor packet_manager's status when receiving prepare statement from
   * client */
  // PrepareStatementTest(NULL);

  libeventserver.CloseServer();
  serverThread.join();
  LOG_INFO("Thread has joined");
  peloton::PelotonInit::Shutdown();
  LOG_INFO("Peloton has shut down\n");
}

TEST_F(PacketManagerTests, PrepareStatementTest) {
  peloton::PelotonInit::Initialize();
  LOG_INFO("Server initialized");
  peloton::wire::LibeventServer libeventserver;
  std::thread serverThread(LaunchServer, libeventserver);
  while (!libeventserver.is_started) {
    sleep(1);
  }

  PrepareStatementTest(NULL);

  libeventserver.CloseServer();
  serverThread.join();
  LOG_INFO("Thread has joined");
  peloton::PelotonInit::Shutdown();
  LOG_INFO("Peloton has shut down\n");
}

TEST_F(PacketManagerTests, RollbackTest) {
  peloton::PelotonInit::Initialize();
  LOG_INFO("Server initialized");
  peloton::wire::LibeventServer libeventserver;
  std::thread serverThread(LaunchServer, libeventserver);
  while (!libeventserver.is_started) {
    sleep(1);
  }

  RollbackTest(NULL);

  libeventserver.CloseServer();
  serverThread.join();
  LOG_INFO("Thread has joined");
  peloton::PelotonInit::Shutdown();
  LOG_INFO("Peloton has shut down\n");
}

}  // End test namespace
}  // End peloton namespace
<|endoftext|>


<commit_before>/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#ifndef NDB_SCAN_FILTER_HPP
#define NDB_SCAN_FILTER_HPP

#include <ndb_types.h>

/**
 * @class NdbScanFilter
 * @brief A simple way to specify filters for scan operations
 *
 * @note  This filter interface is under development and may change in
 *        the future!
 *
 */
class NdbScanFilter {
public:
  /**
   * Constructor
   * @param op  The NdbOperation that the filter belongs to (is applied to).
   */
  NdbScanFilter(class NdbOperation * op);
  ~NdbScanFilter();

  /**
   *  Group operators
   */
  enum Group {
    AND  = 1,    ///< (x1 AND x2 AND x3)
    OR   = 2,    ///< (x1 OR x2 OR X3)
    NAND = 3,    ///< NOT (x1 AND x2 AND x3)
    NOR  = 4     ///< NOT (x1 OR x2 OR x3)
  };

  enum BinaryCondition
  {
    COND_LE = 0,        ///< lower bound
    COND_LT = 1,        ///< lower bound, strict
    COND_GE = 2,        ///< upper bound
    COND_GT = 3,        ///< upper bound, strict
    COND_EQ = 4,        ///< equality
    COND_NE = 5
  };

  /**
   * @name Grouping
   * @{
   */

  /**
   *  Begin of compound.
   *  return  0 if successful, -1 otherwize
   */
  int begin(Group group = AND);

  /**
   *  End of compound.
   *  return  0 if successful, -1 otherwize
   */
  int end();

  /** @} *********************************************************************/

  /**
   *  Explanation missing
   */
  int istrue();

  /**
   *  Explanation missing
   */
  int isfalse();

  /**
   * Compare column ColId with val
   */
  int cmp(BinaryCondition cond, int ColId, const void *val, Uint32 len = 0);

  /**
   * @name Integer Comparators
   * @{
   */
  /** Compare column value with integer for equal
   *  return  0 if successful, -1 otherwize
   */
  int eq(int ColId, Uint32 value) { return cmp(COND_EQ, ColId, &value, 4);}

  /** Compare column value with integer for not equal.
   *  return  0 if successful, -1 otherwize
   */
  int ne(int ColId, Uint32 value) { return cmp(COND_NE, ColId, &value, 4);}
  /** Compare column value with integer for less than.
   *  return  0 if successful, -1 otherwize
   */
  int lt(int ColId, Uint32 value) { return cmp(COND_LT, ColId, &value, 4);}
  /** Compare column value with integer for less than or equal.
   *  return  0 if successful, -1 otherwize
   */
  int le(int ColId, Uint32 value) { return cmp(COND_LE, ColId, &value, 4);}
  /** Compare column value with integer for greater than.
   *  return  0 if successful, -1 otherwize
   */
  int gt(int ColId, Uint32 value) { return cmp(COND_GT, ColId, &value, 4);}
  /** Compare column value with integer for greater than or equal.
   *  return  0 if successful, -1 otherwize
   */
  int ge(int ColId, Uint32 value) { return cmp(COND_GE, ColId, &value, 4);}

  /** Compare column value with integer for equal. 64-bit.
   *  return  0 if successful, -1 otherwize
   */
  int eq(int ColId, Uint64 value) { return cmp(COND_EQ, ColId, &value, 8);}
  /** Compare column value with integer for not equal. 64-bit.
   *  return  0 if successful, -1 otherwize
   */
  int ne(int ColId, Uint64 value) { return cmp(COND_NE, ColId, &value, 8);}
  /** Compare column value with integer for less than. 64-bit.
   *  return  0 if successful, -1 otherwize
   */
  int lt(int ColId, Uint64 value) { return cmp(COND_LT, ColId, &value, 8);}
  /** Compare column value with integer for less than or equal. 64-bit.
   *  return  0 if successful, -1 otherwize
   */
  int le(int ColId, Uint64 value) { return cmp(COND_LE, ColId, &value, 8);}
  /** Compare column value with integer for greater than. 64-bit.
   *  return  0 if successful, -1 otherwize
   */
  int gt(int ColId, Uint64 value) { return cmp(COND_GT, ColId, &value, 8);}
  /** Compare column value with integer for greater than or equal. 64-bit.
   *  return  0 if successful, -1 otherwize
   */
  int ge(int ColId, Uint64 value) { return cmp(COND_GE, ColId, &value, 8);}
  /** @} *********************************************************************/

  /** Check if column value is NULL */
  int isnull(int ColId);
  /** Check if column value is non-NULL */
  int isnotnull(int ColId);

#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
  /**
   *  Like comparison operator.
   *  return  0 if successful, -1 otherwize
   */
  int like(int ColId, const char * val, Uint32 len, bool nopad=false);
  /**
   *  Notlike comparison operator.
   *  return  0 if successful, -1 otherwize
   */
  int notlike(int ColId, const char * val, Uint32 len, bool nopad=false);
  /** @} *********************************************************************/
#endif

private:
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
  friend class NdbScanFilterImpl;
#endif
  class NdbScanFilterImpl & m_impl;
  NdbScanFilter& operator=(const NdbScanFilter&); ///< Defined not implemented
};

#endif
<commit_msg>NdbScanFilter.hpp:   added docs<commit_after>/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#ifndef NDB_SCAN_FILTER_HPP
#define NDB_SCAN_FILTER_HPP

#include <ndb_types.h>

/**
 * @class NdbScanFilter
 * @brief A simple way to specify filters for scan operations
 *
 * @note  This filter interface is under development and may change in
 *        the future!
 *
 */
class NdbScanFilter {
public:
  /**
   * Constructor
   * @param op  The NdbOperation that the filter belongs to (is applied to).
   */
  NdbScanFilter(class NdbOperation * op);
  ~NdbScanFilter();

  /**
   *  Group operators
   */
  enum Group {
    AND  = 1,    ///< (x1 AND x2 AND x3)
    OR   = 2,    ///< (x1 OR x2 OR X3)
    NAND = 3,    ///< NOT (x1 AND x2 AND x3)
    NOR  = 4     ///< NOT (x1 OR x2 OR x3)
  };

  enum BinaryCondition
  {
    COND_LE = 0,        ///< lower bound
    COND_LT = 1,        ///< lower bound, strict
    COND_GE = 2,        ///< upper bound
    COND_GT = 3,        ///< upper bound, strict
    COND_EQ = 4,        ///< equality
    COND_NE = 5         ///< not equal
  };

  /**
   * @name Grouping
   * @{
   */

  /**
   *  Begin of compound.
   *  return  0 if successful, -1 otherwize
   */
  int begin(Group group = AND);

  /**
   *  End of compound.
   *  return  0 if successful, -1 otherwize
   */
  int end();

  /** @} *********************************************************************/

  /**
   *  Explanation missing
   */
  int istrue();

  /**
   *  Explanation missing
   */
  int isfalse();

  /**
   * Compare column ColId with val
   */
  int cmp(BinaryCondition cond, int ColId, const void *val, Uint32 len = 0);

  /**
   * @name Integer Comparators
   * @{
   */
  /** Compare column value with integer for equal
   *  return  0 if successful, -1 otherwize
   */
  int eq(int ColId, Uint32 value) { return cmp(COND_EQ, ColId, &value, 4);}

  /** Compare column value with integer for not equal.
   *  return  0 if successful, -1 otherwize
   */
  int ne(int ColId, Uint32 value) { return cmp(COND_NE, ColId, &value, 4);}
  /** Compare column value with integer for less than.
   *  return  0 if successful, -1 otherwize
   */
  int lt(int ColId, Uint32 value) { return cmp(COND_LT, ColId, &value, 4);}
  /** Compare column value with integer for less than or equal.
   *  return  0 if successful, -1 otherwize
   */
  int le(int ColId, Uint32 value) { return cmp(COND_LE, ColId, &value, 4);}
  /** Compare column value with integer for greater than.
   *  return  0 if successful, -1 otherwize
   */
  int gt(int ColId, Uint32 value) { return cmp(COND_GT, ColId, &value, 4);}
  /** Compare column value with integer for greater than or equal.
   *  return  0 if successful, -1 otherwize
   */
  int ge(int ColId, Uint32 value) { return cmp(COND_GE, ColId, &value, 4);}

  /** Compare column value with integer for equal. 64-bit.
   *  return  0 if successful, -1 otherwize
   */
  int eq(int ColId, Uint64 value) { return cmp(COND_EQ, ColId, &value, 8);}
  /** Compare column value with integer for not equal. 64-bit.
   *  return  0 if successful, -1 otherwize
   */
  int ne(int ColId, Uint64 value) { return cmp(COND_NE, ColId, &value, 8);}
  /** Compare column value with integer for less than. 64-bit.
   *  return  0 if successful, -1 otherwize
   */
  int lt(int ColId, Uint64 value) { return cmp(COND_LT, ColId, &value, 8);}
  /** Compare column value with integer for less than or equal. 64-bit.
   *  return  0 if successful, -1 otherwize
   */
  int le(int ColId, Uint64 value) { return cmp(COND_LE, ColId, &value, 8);}
  /** Compare column value with integer for greater than. 64-bit.
   *  return  0 if successful, -1 otherwize
   */
  int gt(int ColId, Uint64 value) { return cmp(COND_GT, ColId, &value, 8);}
  /** Compare column value with integer for greater than or equal. 64-bit.
   *  return  0 if successful, -1 otherwize
   */
  int ge(int ColId, Uint64 value) { return cmp(COND_GE, ColId, &value, 8);}
  /** @} *********************************************************************/

  /** Check if column value is NULL */
  int isnull(int ColId);
  /** Check if column value is non-NULL */
  int isnotnull(int ColId);

#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
  /**
   *  Like comparison operator.
   *  return  0 if successful, -1 otherwize
   */
  int like(int ColId, const char * val, Uint32 len, bool nopad=false);
  /**
   *  Notlike comparison operator.
   *  return  0 if successful, -1 otherwize
   */
  int notlike(int ColId, const char * val, Uint32 len, bool nopad=false);
  /** @} *********************************************************************/
#endif

private:
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
  friend class NdbScanFilterImpl;
#endif
  class NdbScanFilterImpl & m_impl;
  NdbScanFilter& operator=(const NdbScanFilter&); ///< Defined not implemented
};

#endif
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>

#include <MultiRegions/ExpList.h>

using namespace Nektar;

int main(int argc, char *argv[])
{
    Array<OneD,NekDouble>  fce;
    Array<OneD,NekDouble>  xc0,xc1,xc2;

    if(argc != 2)
    {
        fprintf(stderr,"Usage: XmlToTecplotWireFrame  meshfile\n");
        exit(1);
    }

    LibUtilities::SessionReaderSharedPtr vSession
            = LibUtilities::SessionReader::CreateInstance(argc, argv);

    //----------------------------------------------
    // Read in mesh from input file
    string meshfile(argv[argc-1]);
    SpatialDomains::MeshGraphSharedPtr mesh  = SpatialDomains::MeshGraph::Read(vSession);
    //----------------------------------------------

    //----------------------------------------------
    // Define Expansion
    int expdim   = mesh->GetMeshDimension();

    switch(expdim)
    {
    case 1:
        ASSERTL0(false,"3D not set up");
        break;
    case 2:
        {
            NekDouble x,y,z;
            string   outname(strtok(argv[argc-1],"."));
            outname += ".dat";
            FILE *fp = fopen(outname.c_str(),"w");

            SpatialDomains::TriGeomMap trigeom = mesh->GetAllTriGeoms();
            SpatialDomains::QuadGeomMap quadgeom = mesh->GetAllQuadGeoms();

            int nverts = mesh->GetNvertices();

            fprintf(fp,"Variables = x, y\n");
            fprintf(fp,"Zone,N=%d, E=%d,DATAPACKING=POINT,ZONETYPE=FEQUADRILATERAL\n",nverts,(int)(trigeom.size()+quadgeom.size()));

            for(int i = 0; i < nverts; ++i)
            {
                mesh->GetVertex(i)->GetCoords(x,y,z);
                fprintf(fp,"%lf %lf\n",x,y);
            }

            std::map<int,SpatialDomains::TriGeomSharedPtr>::iterator triIter;
            for(triIter = trigeom.begin(); triIter != trigeom.end(); ++triIter)
            {
                fprintf(fp,"%d %d %d %d\n",(triIter->second)->GetVid(0)+1,(triIter->second)->GetVid(1)+1,(triIter->second)->GetVid(2)+1,(triIter->second)->GetVid(2)+1);
            }

            std::map<int,SpatialDomains::QuadGeomSharedPtr>::iterator quadIter;
            for(quadIter = quadgeom.begin(); quadIter != quadgeom.end(); ++quadIter)
            {
                fprintf(fp,"%d %d %d %d\n",(quadIter->second)->GetVid(0)+1,(quadIter->second)->GetVid(1)+1,(quadIter->second)->GetVid(2)+1,(quadIter->second)->GetVid(3)+1);
            }
        }
        break;
    case 3:
        ASSERTL0(false,"3D not set up");
        break;
    default:
        ASSERTL0(false,"Expansion dimension not recognised");
        break;
    }

    //-----------------------------------------------

    return 0;
}

<commit_msg>Added routine to dump 3d fields and check tet rotation<commit_after>#include <cstdio>
#include <cstdlib>

#include <MultiRegions/ExpList.h>

using namespace Nektar;

void CheckTetRotation(Array<OneD, NekDouble> &xc, Array<OneD, NekDouble> &yc,
                      Array<OneD, NekDouble> &xz,
                      std::map<int,SpatialDomains::TetGeomSharedPtr>::iterator &tetIter,
                      int id);

int main(int argc, char *argv[])
{
    Array<OneD,NekDouble>  fce;
    Array<OneD,NekDouble>  xc0,xc1,xc2;

    if(argc != 2)
    {
        fprintf(stderr,"Usage: XmlToTecplotWireFrame  meshfile\n");
        exit(1);
    }

    LibUtilities::SessionReaderSharedPtr vSession
            = LibUtilities::SessionReader::CreateInstance(argc, argv);

    //----------------------------------------------
    // Read in mesh from input file
    string meshfile(argv[argc-1]);
    SpatialDomains::MeshGraphSharedPtr mesh  = SpatialDomains::MeshGraph::Read(vSession);
    //----------------------------------------------

    //----------------------------------------------
    // Define Expansion
    int expdim   = mesh->GetMeshDimension();

    switch(expdim)
    {
    case 1:
        ASSERTL0(false,"1D not set up");
        break;
    case 2:
        {
            NekDouble x,y,z;
            string   outname(strtok(argv[argc-1],"."));
            outname += ".dat";
            FILE *fp = fopen(outname.c_str(),"w");

            SpatialDomains::TriGeomMap trigeom = mesh->GetAllTriGeoms();
            SpatialDomains::QuadGeomMap quadgeom = mesh->GetAllQuadGeoms();

            int nverts = mesh->GetNvertices();

            fprintf(fp,"Variables = x, y\n");
            fprintf(fp,"Zone,N=%d, E=%d,DATAPACKING=POINT,ZONETYPE=FEQUADRILATERAL\n",nverts,(int)(trigeom.size()+quadgeom.size()));

            for(int i = 0; i < nverts; ++i)
            {
                mesh->GetVertex(i)->GetCoords(x,y,z);
                fprintf(fp,"%lf %lf\n",x,y);
            }

            std::map<int,SpatialDomains::TriGeomSharedPtr>::iterator triIter;
            for(triIter = trigeom.begin(); triIter != trigeom.end(); ++triIter)
            {
                fprintf(fp,"%d %d %d %d\n",(triIter->second)->GetVid(0)+1,(triIter->second)->GetVid(1)+1,(triIter->second)->GetVid(2)+1,(triIter->second)->GetVid(2)+1);
            }

            std::map<int,SpatialDomains::QuadGeomSharedPtr>::iterator quadIter;
            for(quadIter = quadgeom.begin(); quadIter != quadgeom.end(); ++quadIter)
            {
                fprintf(fp,"%d %d %d %d\n",(quadIter->second)->GetVid(0)+1,(quadIter->second)->GetVid(1)+1,(quadIter->second)->GetVid(2)+1,(quadIter->second)->GetVid(3)+1);
            }
        }
        break;
    case 3:
        {
            NekDouble x,y,z;
            string   outname(strtok(argv[argc-1],"."));
            outname += ".dat";
            FILE *fp = fopen(outname.c_str(),"w");

            SpatialDomains::TetGeomMap   tetgeom   = mesh->GetAllTetGeoms();
            SpatialDomains::PyrGeomMap   pyrgeom   = mesh->GetAllPyrGeoms();
            SpatialDomains::PrismGeomMap prismgeom = mesh->GetAllPrismGeoms();
            SpatialDomains::HexGeomMap   hexgeom   = mesh->GetAllHexGeoms();

            int nverts = mesh->GetNvertices();

            fprintf(fp,"Variables = x, y, z\n");
            fprintf(fp,"Zone,N=%d, E=%d,DATAPACKING=POINT,ZONETYPE=FEBRICK\n",nverts,(int)(tetgeom.size() + pyrgeom.size() + prismgeom.size() + hexgeom.size()));

            Array<OneD, NekDouble> xc(nverts),yc(nverts),zc(nverts);

            for(int i = 0; i < nverts; ++i)
            {
                mesh->GetVertex(i)->GetCoords(x,y,z);
                fprintf(fp,"%lf %lf %lf \n",x,y,z);
                xc[i] = x;
                yc[i] = y;
                zc[i] = z;
            }

            std::map<int,SpatialDomains::TetGeomSharedPtr>::iterator tetIter;
            int cnt = 0;
            for(tetIter = tetgeom.begin(); tetIter != tetgeom.end(); ++tetIter)
            {
                // check rotation and dump
                CheckTetRotation(xc,yc,zc,tetIter,cnt++);

                fprintf(fp,"%d %d %d %d %d %d %d %d\n",(tetIter->second)->GetVid(0)+1,
                        (tetIter->second)->GetVid(1)+1,(tetIter->second)->GetVid(2)+1,
                        (tetIter->second)->GetVid(3)+1,(tetIter->second)->GetVid(3)+1,
                        (tetIter->second)->GetVid(3)+1,(tetIter->second)->GetVid(3)+1,
                        (tetIter->second)->GetVid(3)+1);
            }

            std::map<int,SpatialDomains::PyrGeomSharedPtr>::iterator pyrIter;
            for(pyrIter = pyrgeom.begin(); pyrIter != pyrgeom.end(); ++pyrIter)
            {
                fprintf(fp,"%d %d %d %d %d %d %d %d\n",(pyrIter->second)->GetVid(0)+1,
                        (pyrIter->second)->GetVid(1)+1,(pyrIter->second)->GetVid(2)+1,
                        (pyrIter->second)->GetVid(3)+1,(pyrIter->second)->GetVid(4)+1,
                        (pyrIter->second)->GetVid(4)+1,(pyrIter->second)->GetVid(4)+1,
                        (pyrIter->second)->GetVid(5)+1);
            }

            std::map<int,SpatialDomains::PrismGeomSharedPtr>::iterator prismIter;
            for(prismIter = prismgeom.begin(); prismIter != prismgeom.end(); ++prismIter)
            {
                fprintf(fp,"%d %d %d %d %d %d %d %d\n",(prismIter->second)->GetVid(0)+1,
                        (prismIter->second)->GetVid(1)+1,(prismIter->second)->GetVid(2)+1,
                        (prismIter->second)->GetVid(3)+1,(prismIter->second)->GetVid(4)+1,
                        (prismIter->second)->GetVid(4)+1,(prismIter->second)->GetVid(5)+1,
                        (prismIter->second)->GetVid(5)+1);
            }

            std::map<int,SpatialDomains::HexGeomSharedPtr>::iterator hexIter;
            for(hexIter = hexgeom.begin(); hexIter != hexgeom.end(); ++hexIter)
            {
                fprintf(fp,"%d %d %d %d %d %d %d %d\n",(hexIter->second)->GetVid(0)+1,
                        (hexIter->second)->GetVid(1)+1,(hexIter->second)->GetVid(2)+1,
                        (hexIter->second)->GetVid(3)+1,(hexIter->second)->GetVid(4)+1,
                        (hexIter->second)->GetVid(5)+1,(hexIter->second)->GetVid(6)+1,
                        (hexIter->second)->GetVid(7)+1);
            }

        }

        break;
    default:
        ASSERTL0(false,"Expansion dimension not recognised");
        break;
    }

    //-----------------------------------------------

    return 0;
}

class Ord
{
public:
    double x;
    double y;
    double z;
};

void CheckTetRotation(Array<OneD, NekDouble> &xc, Array<OneD, NekDouble> &yc, Array<OneD, NekDouble> &zc, std::map<int,SpatialDomains::TetGeomSharedPtr>::iterator &tetIter, int id)
{
    Ord       v[4];
    NekDouble abx,aby,abz;

    v[0].x = xc[(tetIter->second)->GetVid(0)];
    v[0].y = yc[(tetIter->second)->GetVid(0)];
    v[0].z = zc[(tetIter->second)->GetVid(0)];

    v[1].x = xc[(tetIter->second)->GetVid(1)];
    v[1].y = yc[(tetIter->second)->GetVid(1)];
    v[1].z = zc[(tetIter->second)->GetVid(1)];

    v[2].x = xc[(tetIter->second)->GetVid(2)];
    v[2].y = yc[(tetIter->second)->GetVid(2)];
    v[2].z = zc[(tetIter->second)->GetVid(2)];

    v[3].x = xc[(tetIter->second)->GetVid(3)];
    v[3].y = yc[(tetIter->second)->GetVid(3)];
    v[3].z = zc[(tetIter->second)->GetVid(3)];

    // cross product of edge 0 and 2
    abx = (v[1].y-v[0].y)*(v[2].z-v[0].z) -
        (v[1].z-v[0].z)*(v[2].y-v[0].y);
    aby = (v[1].z-v[0].z)*(v[2].x-v[0].x) -
        (v[1].x-v[0].x)*(v[2].z-v[0].z);
    abz = (v[1].x-v[0].x)*(v[2].y-v[0].y) -
        (v[1].y-v[0].y)*(v[2].x-v[0].x);

    // inner product of cross product with respect to edge 3 should be positive
    if(((v[3].x-v[0].x)*abx + (v[3].y-v[0].y)*aby +
        (v[3].z-v[0].z)*abz)<0.0)
    {
        cerr << "ERROR: Element " << id + 1 << "is NOT counter-clockwise\n" << endl;
    }

}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 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 <limits>

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"

namespace webrtc {
namespace {

class ByteIoTest : public ::testing::Test {
 protected:
  ByteIoTest() {}
  virtual ~ByteIoTest() {}

  enum { kAlignments = sizeof(uint64_t) - 1 };

  // Method to create a test value that is not the same when byte reversed.
  template <typename T>
  T CreateTestValue(bool negative, uint8_t num_bytes) {
    T val = 0;
    for (uint8_t i = 0; i != num_bytes; ++i) {
      val = (val << 8) + (negative ? (0xFF - i) : (i + 1));
    }
    if (negative && std::numeric_limits<T>::is_signed) {
      val |= static_cast<T>(-1) << (8 * num_bytes);
    }
    return val;
  }

  // Populate byte buffer with value, in big endian format.
  template <typename T>
  void PopulateTestData(uint8_t* data, T value, int num_bytes, bool bigendian) {
    if (bigendian) {
      for (int i = 0; i < num_bytes; ++i) {
        data[i] = (value >> ((num_bytes - i - 1) * 8)) & 0xFF;
      }
    } else {
      for (int i = 0; i < num_bytes; ++i) {
        data[i] = (value >> (i * 8)) & 0xFF;
      }
    }
  }

  // Test reading big endian numbers.
  // Template arguments: Type T, read method RM(buffer), B bytes of data.
  template <typename T, T (*RM)(const uint8_t*), int B>
  void TestRead(bool big_endian) {
    // Test both for values that are positive and negative (if signed)
    for (int neg = 0; neg < 2; ++neg) {
      bool negative = neg > 0;

      // Write test value to byte buffer, in big endian format.
      T test_value = CreateTestValue<T>(negative, B);
      uint8_t bytes[B + kAlignments];

      // Make one test for each alignment.
      for (int i = 0; i < kAlignments; ++i) {
        PopulateTestData(bytes + i, test_value, B, big_endian);

        // Check that test value is retrieved from buffer when used read method.
        EXPECT_EQ(test_value, RM(bytes + i));
      }
    }
  }

  // Test writing big endian numbers.
  // Template arguments: Type T, write method WM(buffer, value), B bytes of data
  template <typename T, void (*WM)(uint8_t*, T), int B>
  void TestWrite(bool big_endian) {
    // Test both for values that are positive and negative (if signed).
    for (int neg = 0; neg < 2; ++neg) {
      bool negative = neg > 0;

      // Write test value to byte buffer, in big endian format.
      T test_value = CreateTestValue<T>(negative, B);
      uint8_t expected_bytes[B + kAlignments];
      uint8_t bytes[B + kAlignments];

      // Make one test for each alignment.
      for (int i = 0; i < kAlignments; ++i) {
        PopulateTestData(expected_bytes + i, test_value, B, big_endian);

        // Zero initialize buffer and let WM populate it.
        memset(bytes, 0, B + kAlignments);
        WM(bytes + i, test_value);

        // Check that data produced by WM is big endian as expected.
        for (int j = 0; j < B; ++j) {
          EXPECT_EQ(expected_bytes[i + j], bytes[i + j]);
        }
      }
    }
  }
};

TEST_F(ByteIoTest, Test16UBitBigEndian) {
  TestRead<uint16_t, ByteReader<uint16_t>::ReadBigEndian,
      sizeof(uint16_t)>(true);
  TestWrite<uint16_t, ByteWriter<uint16_t>::WriteBigEndian,
    sizeof(uint16_t)>(true);
}

TEST_F(ByteIoTest, Test24UBitBigEndian) {
  TestRead<uint32_t, ByteReader<uint32_t, 3>::ReadBigEndian, 3>(true);
  TestWrite<uint32_t, ByteWriter<uint32_t, 3>::WriteBigEndian, 3>(true);
}

TEST_F(ByteIoTest, Test32UBitBigEndian) {
  TestRead<uint32_t, ByteReader<uint32_t>::ReadBigEndian,
      sizeof(uint32_t)>(true);
  TestWrite<uint32_t, ByteWriter<uint32_t>::WriteBigEndian,
      sizeof(uint32_t)>(true);
}

TEST_F(ByteIoTest, Test64UBitBigEndian) {
  TestRead<uint64_t, ByteReader<uint64_t>::ReadBigEndian,
      sizeof(uint64_t)>(true);
  TestWrite<uint64_t, ByteWriter<uint64_t>::WriteBigEndian,
      sizeof(uint64_t)>(true);
}

TEST_F(ByteIoTest, Test16SBitBigEndian) {
  TestRead<int16_t, ByteReader<int16_t>::ReadBigEndian,
      sizeof(int16_t)>(true);
  TestWrite<int16_t, ByteWriter<int16_t>::WriteBigEndian,
      sizeof(int16_t)>(true);
}

TEST_F(ByteIoTest, Test24SBitBigEndian) {
  TestRead<int32_t, ByteReader<int32_t, 3>::ReadBigEndian, 3>(true);
  TestWrite<int32_t, ByteWriter<int32_t, 3>::WriteBigEndian, 3>(true);
}

// Disabled for UBSan: https://bugs.chromium.org/p/webrtc/issues/detail?id=5490
#ifdef UNDEFINED_SANITIZER
#define MAYBE_Test32SBitBigEndian DISABLED_Test32SBitBigEndian
#else
#define MAYBE_Test32SBitBigEndian Test32SBitBigEndian
#endif
TEST_F(ByteIoTest, MAYBE_Test32SBitBigEndian) {
  TestRead<int32_t, ByteReader<int32_t>::ReadBigEndian,
      sizeof(int32_t)>(true);
  TestWrite<int32_t, ByteWriter<int32_t>::WriteBigEndian,
      sizeof(int32_t)>(true);
}

// Disabled for UBSan: https://bugs.chromium.org/p/webrtc/issues/detail?id=5490
#ifdef UNDEFINED_SANITIZER
#define MAYBE_Test64SBitBigEndian DISABLED_Test64SBitBigEndian
#else
#define MAYBE_Test64SBitBigEndian Test64SBitBigEndian
#endif
TEST_F(ByteIoTest, MAYBE_Test64SBitBigEndian) {
  TestRead<int64_t, ByteReader<int64_t>::ReadBigEndian,
      sizeof(int64_t)>(true);
  TestWrite<int64_t, ByteWriter<int64_t>::WriteBigEndian,
      sizeof(int64_t)>(true);
}

TEST_F(ByteIoTest, Test16UBitLittleEndian) {
  TestRead<uint16_t, ByteReader<uint16_t>::ReadLittleEndian,
      sizeof(uint16_t)>(false);
  TestWrite<uint16_t, ByteWriter<uint16_t>::WriteLittleEndian,
      sizeof(uint16_t)>(false);
}

TEST_F(ByteIoTest, Test24UBitLittleEndian) {
  TestRead<uint32_t, ByteReader<uint32_t, 3>::ReadLittleEndian, 3>(false);
  TestWrite<uint32_t, ByteWriter<uint32_t, 3>::WriteLittleEndian, 3>(false);
}

TEST_F(ByteIoTest, Test32UBitLittleEndian) {
  TestRead<uint32_t, ByteReader<uint32_t>::ReadLittleEndian,
      sizeof(uint32_t)>(false);
  TestWrite<uint32_t, ByteWriter<uint32_t>::WriteLittleEndian,
      sizeof(uint32_t)>(false);
}

TEST_F(ByteIoTest, Test64UBitLittleEndian) {
  TestRead<uint64_t, ByteReader<uint64_t>::ReadLittleEndian,
      sizeof(uint64_t)>(false);
  TestWrite<uint64_t, ByteWriter<uint64_t>::WriteLittleEndian,
      sizeof(uint64_t)>(false);
}

TEST_F(ByteIoTest, Test16SBitLittleEndian) {
  TestRead<int16_t, ByteReader<int16_t>::ReadLittleEndian,
      sizeof(int16_t)>(false);
  TestWrite<int16_t, ByteWriter<int16_t>::WriteLittleEndian,
      sizeof(int16_t)>(false);
}

TEST_F(ByteIoTest, Test24SBitLittleEndian) {
  TestRead<int32_t, ByteReader<int32_t, 3>::ReadLittleEndian, 3>(false);
  TestWrite<int32_t, ByteWriter<int32_t, 3>::WriteLittleEndian, 3>(false);
}

// Disabled for UBSan: https://bugs.chromium.org/p/webrtc/issues/detail?id=5490
#ifdef UNDEFINED_SANITIZER
#define MAYBE_Test32SBitLittleEndian DISABLED_Test32SBitLittleEndian
#else
#define MAYBE_Test32SBitLittleEndian Test32SBitLittleEndian
#endif
TEST_F(ByteIoTest, MAYBE_Test32SBitLittleEndian) {
  TestRead<int32_t, ByteReader<int32_t>::ReadLittleEndian,
      sizeof(int32_t)>(false);
  TestWrite<int32_t, ByteWriter<int32_t>::WriteLittleEndian,
      sizeof(int32_t)>(false);
}

// Disabled for UBSan: https://bugs.chromium.org/p/webrtc/issues/detail?id=5490
#ifdef UNDEFINED_SANITIZER
#define MAYBE_Test64SBitLittleEndian DISABLED_Test64SBitLittleEndian
#else
#define MAYBE_Test64SBitLittleEndian Test64SBitLittleEndian
#endif
TEST_F(ByteIoTest, MAYBE_Test64SBitLittleEndian) {
  TestRead<int64_t, ByteReader<int64_t>::ReadLittleEndian,
      sizeof(int64_t)>(false);
  TestWrite<int64_t, ByteWriter<int64_t>::WriteLittleEndian,
      sizeof(int64_t)>(false);
}

// Sets up a fixed byte array and converts N bytes from the array into a
// uint64_t. Verifies the value with hard-coded reference.
TEST(ByteIo, SanityCheckFixedByteArrayUnsignedReadBigEndian) {
  uint8_t data[8] = {0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88};
  uint64_t value = ByteReader<uint64_t, 2>::ReadBigEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xFFEE), value);
  value = ByteReader<uint64_t, 3>::ReadBigEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDD), value);
  value = ByteReader<uint64_t, 4>::ReadBigEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDDCC), value);
  value = ByteReader<uint64_t, 5>::ReadBigEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDDCCBB), value);
  value = ByteReader<uint64_t, 6>::ReadBigEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDDCCBBAA), value);
  value = ByteReader<uint64_t, 7>::ReadBigEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDDCCBBAA99), value);
  value = ByteReader<uint64_t, 8>::ReadBigEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDDCCBBAA9988), value);
}

// Same as above, but for little-endian reading.
TEST(ByteIo, SanityCheckFixedByteArrayUnsignedReadLittleEndian) {
  uint8_t data[8] = {0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88};
  uint64_t value = ByteReader<uint64_t, 2>::ReadLittleEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xEEFF), value);
  value = ByteReader<uint64_t, 3>::ReadLittleEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xDDEEFF), value);
  value = ByteReader<uint64_t, 4>::ReadLittleEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xCCDDEEFF), value);
  value = ByteReader<uint64_t, 5>::ReadLittleEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xBBCCDDEEFF), value);
  value = ByteReader<uint64_t, 6>::ReadLittleEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xAABBCCDDEEFF), value);
  value = ByteReader<uint64_t, 7>::ReadLittleEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0x99AABBCCDDEEFF), value);
  value = ByteReader<uint64_t, 8>::ReadLittleEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0x8899AABBCCDDEEFF), value);
}
}  // namespace
}  // namespace webrtc
<commit_msg>Fix ubsan warning in byteio_unittest<commit_after>/*
 *  Copyright (c) 2012 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 <limits>

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"

namespace webrtc {
namespace {

class ByteIoTest : public ::testing::Test {
 protected:
  ByteIoTest() {}
  virtual ~ByteIoTest() {}

  enum { kAlignments = sizeof(uint64_t) - 1 };

  // Method to create a test value that is not the same when byte reversed.
  template <typename T>
  T CreateTestValue(bool negative, uint8_t num_bytes) {
    // Examples of output:
    // T = int32_t, negative = false, num_bytes = 4: 0x00010203
    // T = int32_t, negative = true, num_bytes = 4: 0xFFFEFDFC
    // T = int32_t, negative = false, num_bytes = 3: 0x000102
    // * T = int32_t, negative = true, num_bytes = 3: 0xFFFEFD

    T val = 0;
    for (uint8_t i = 0; i != num_bytes; ++i) {
      val = (val << 8) + (negative ? (0xFF - i) : (i + 1));
    }

    // This loop will create a sign extend mask if num_bytes if necessary.
    // For the last example (marked * above), the number needs to be sign
    // extended to be a valid int32_t. The sign extend mask is 0xFF000000.
    // Comments for each step with this example below.
    if (std::numeric_limits<T>::is_signed && negative &&
        num_bytes < sizeof(T)) {
      // Start with mask = 0xFFFFFFFF.
      T mask = static_cast<T>(-1);
      // Create a temporary for the lowest byte (0x000000FF).
      const T neg_byte = static_cast<T>(0xFF);
      for (int i = 0; i < num_bytes; ++i) {
        // And the inverse of the temporary and the mask:
        // 0xFFFFFFFF & 0xFFFFFF00 = 0xFFFFFF00.
        // 0xFFFFFF00 & 0xFFFF00FF = 0xFFFF0000.
        // 0xFFFF0000 & 0xFF00FFFF = 0xFF000000.
        mask &= ~(neg_byte << (i * 8));
      }
      // Add the sign extension mask to the actual value.
      val |= mask;
    }
    return val;
  }

  // Populate byte buffer with value, in big endian format.
  template <typename T>
  void PopulateTestData(uint8_t* data, T value, int num_bytes, bool bigendian) {
    if (bigendian) {
      for (int i = 0; i < num_bytes; ++i) {
        data[i] = (value >> ((num_bytes - i - 1) * 8)) & 0xFF;
      }
    } else {
      for (int i = 0; i < num_bytes; ++i) {
        data[i] = (value >> (i * 8)) & 0xFF;
      }
    }
  }

  // Test reading big endian numbers.
  // Template arguments: Type T, read method RM(buffer), B bytes of data.
  template <typename T, T (*RM)(const uint8_t*), int B>
  void TestRead(bool big_endian) {
    // Test both for values that are positive and negative (if signed)
    for (int neg = 0; neg < 2; ++neg) {
      bool negative = neg > 0;

      // Write test value to byte buffer, in big endian format.
      T test_value = CreateTestValue<T>(negative, B);
      uint8_t bytes[B + kAlignments];

      // Make one test for each alignment.
      for (int i = 0; i < kAlignments; ++i) {
        PopulateTestData(bytes + i, test_value, B, big_endian);

        // Check that test value is retrieved from buffer when used read method.
        EXPECT_EQ(test_value, RM(bytes + i));
      }
    }
  }

  // Test writing big endian numbers.
  // Template arguments: Type T, write method WM(buffer, value), B bytes of data
  template <typename T, void (*WM)(uint8_t*, T), int B>
  void TestWrite(bool big_endian) {
    // Test both for values that are positive and negative (if signed).
    for (int neg = 0; neg < 2; ++neg) {
      bool negative = neg > 0;

      // Write test value to byte buffer, in big endian format.
      T test_value = CreateTestValue<T>(negative, B);
      uint8_t expected_bytes[B + kAlignments];
      uint8_t bytes[B + kAlignments];

      // Make one test for each alignment.
      for (int i = 0; i < kAlignments; ++i) {
        PopulateTestData(expected_bytes + i, test_value, B, big_endian);

        // Zero initialize buffer and let WM populate it.
        memset(bytes, 0, B + kAlignments);
        WM(bytes + i, test_value);

        // Check that data produced by WM is big endian as expected.
        for (int j = 0; j < B; ++j) {
          EXPECT_EQ(expected_bytes[i + j], bytes[i + j]);
        }
      }
    }
  }
};

TEST_F(ByteIoTest, Test16UBitBigEndian) {
  TestRead<uint16_t, ByteReader<uint16_t>::ReadBigEndian,
      sizeof(uint16_t)>(true);
  TestWrite<uint16_t, ByteWriter<uint16_t>::WriteBigEndian,
    sizeof(uint16_t)>(true);
}

TEST_F(ByteIoTest, Test24UBitBigEndian) {
  TestRead<uint32_t, ByteReader<uint32_t, 3>::ReadBigEndian, 3>(true);
  TestWrite<uint32_t, ByteWriter<uint32_t, 3>::WriteBigEndian, 3>(true);
}

TEST_F(ByteIoTest, Test32UBitBigEndian) {
  TestRead<uint32_t, ByteReader<uint32_t>::ReadBigEndian,
      sizeof(uint32_t)>(true);
  TestWrite<uint32_t, ByteWriter<uint32_t>::WriteBigEndian,
      sizeof(uint32_t)>(true);
}

TEST_F(ByteIoTest, Test64UBitBigEndian) {
  TestRead<uint64_t, ByteReader<uint64_t>::ReadBigEndian,
      sizeof(uint64_t)>(true);
  TestWrite<uint64_t, ByteWriter<uint64_t>::WriteBigEndian,
      sizeof(uint64_t)>(true);
}

TEST_F(ByteIoTest, Test16SBitBigEndian) {
  TestRead<int16_t, ByteReader<int16_t>::ReadBigEndian,
      sizeof(int16_t)>(true);
  TestWrite<int16_t, ByteWriter<int16_t>::WriteBigEndian,
      sizeof(int16_t)>(true);
}

TEST_F(ByteIoTest, Test24SBitBigEndian) {
  TestRead<int32_t, ByteReader<int32_t, 3>::ReadBigEndian, 3>(true);
  TestWrite<int32_t, ByteWriter<int32_t, 3>::WriteBigEndian, 3>(true);
}

TEST_F(ByteIoTest, Test32SBitBigEndian) {
  TestRead<int32_t, ByteReader<int32_t>::ReadBigEndian,
      sizeof(int32_t)>(true);
  TestWrite<int32_t, ByteWriter<int32_t>::WriteBigEndian,
      sizeof(int32_t)>(true);
}

TEST_F(ByteIoTest, Test64SBitBigEndian) {
  TestRead<int64_t, ByteReader<int64_t>::ReadBigEndian,
      sizeof(int64_t)>(true);
  TestWrite<int64_t, ByteWriter<int64_t>::WriteBigEndian,
      sizeof(int64_t)>(true);
}

TEST_F(ByteIoTest, Test16UBitLittleEndian) {
  TestRead<uint16_t, ByteReader<uint16_t>::ReadLittleEndian,
      sizeof(uint16_t)>(false);
  TestWrite<uint16_t, ByteWriter<uint16_t>::WriteLittleEndian,
      sizeof(uint16_t)>(false);
}

TEST_F(ByteIoTest, Test24UBitLittleEndian) {
  TestRead<uint32_t, ByteReader<uint32_t, 3>::ReadLittleEndian, 3>(false);
  TestWrite<uint32_t, ByteWriter<uint32_t, 3>::WriteLittleEndian, 3>(false);
}

TEST_F(ByteIoTest, Test32UBitLittleEndian) {
  TestRead<uint32_t, ByteReader<uint32_t>::ReadLittleEndian,
      sizeof(uint32_t)>(false);
  TestWrite<uint32_t, ByteWriter<uint32_t>::WriteLittleEndian,
      sizeof(uint32_t)>(false);
}

TEST_F(ByteIoTest, Test64UBitLittleEndian) {
  TestRead<uint64_t, ByteReader<uint64_t>::ReadLittleEndian,
      sizeof(uint64_t)>(false);
  TestWrite<uint64_t, ByteWriter<uint64_t>::WriteLittleEndian,
      sizeof(uint64_t)>(false);
}

TEST_F(ByteIoTest, Test16SBitLittleEndian) {
  TestRead<int16_t, ByteReader<int16_t>::ReadLittleEndian,
      sizeof(int16_t)>(false);
  TestWrite<int16_t, ByteWriter<int16_t>::WriteLittleEndian,
      sizeof(int16_t)>(false);
}

TEST_F(ByteIoTest, Test24SBitLittleEndian) {
  TestRead<int32_t, ByteReader<int32_t, 3>::ReadLittleEndian, 3>(false);
  TestWrite<int32_t, ByteWriter<int32_t, 3>::WriteLittleEndian, 3>(false);
}

TEST_F(ByteIoTest, Test32SBitLittleEndian) {
  TestRead<int32_t, ByteReader<int32_t>::ReadLittleEndian,
      sizeof(int32_t)>(false);
  TestWrite<int32_t, ByteWriter<int32_t>::WriteLittleEndian,
      sizeof(int32_t)>(false);
}

TEST_F(ByteIoTest, Test64SBitLittleEndian) {
  TestRead<int64_t, ByteReader<int64_t>::ReadLittleEndian,
      sizeof(int64_t)>(false);
  TestWrite<int64_t, ByteWriter<int64_t>::WriteLittleEndian,
      sizeof(int64_t)>(false);
}

// Sets up a fixed byte array and converts N bytes from the array into a
// uint64_t. Verifies the value with hard-coded reference.
TEST(ByteIo, SanityCheckFixedByteArrayUnsignedReadBigEndian) {
  uint8_t data[8] = {0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88};
  uint64_t value = ByteReader<uint64_t, 2>::ReadBigEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xFFEE), value);
  value = ByteReader<uint64_t, 3>::ReadBigEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDD), value);
  value = ByteReader<uint64_t, 4>::ReadBigEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDDCC), value);
  value = ByteReader<uint64_t, 5>::ReadBigEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDDCCBB), value);
  value = ByteReader<uint64_t, 6>::ReadBigEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDDCCBBAA), value);
  value = ByteReader<uint64_t, 7>::ReadBigEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDDCCBBAA99), value);
  value = ByteReader<uint64_t, 8>::ReadBigEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDDCCBBAA9988), value);
}

// Same as above, but for little-endian reading.
TEST(ByteIo, SanityCheckFixedByteArrayUnsignedReadLittleEndian) {
  uint8_t data[8] = {0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88};
  uint64_t value = ByteReader<uint64_t, 2>::ReadLittleEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xEEFF), value);
  value = ByteReader<uint64_t, 3>::ReadLittleEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xDDEEFF), value);
  value = ByteReader<uint64_t, 4>::ReadLittleEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xCCDDEEFF), value);
  value = ByteReader<uint64_t, 5>::ReadLittleEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xBBCCDDEEFF), value);
  value = ByteReader<uint64_t, 6>::ReadLittleEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0xAABBCCDDEEFF), value);
  value = ByteReader<uint64_t, 7>::ReadLittleEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0x99AABBCCDDEEFF), value);
  value = ByteReader<uint64_t, 8>::ReadLittleEndian(data);
  EXPECT_EQ(static_cast<uint64_t>(0x8899AABBCCDDEEFF), value);
}
}  // namespace
}  // namespace webrtc
<|endoftext|>