blob: 7b1ee5267c17905643ba7f499ae3813dcd44aaca [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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 <string>
#include "common/thread-debug-info.h"
#include "testutil/gtest-util.h"
#include "util/container-util.h"
#include "util/thread.h"
#include "common/names.h"
namespace impala {
TEST(ThreadDebugInfo, Ids) {
// This test checks if SetInstanceId() stores the
// string representation of a TUniqueId correctly.
ThreadDebugInfo thread_debug_info;
TUniqueId instance_id;
instance_id.hi = 123;
instance_id.lo = 456;
thread_debug_info.SetInstanceId(instance_id);
string instance_id_str = PrintId(instance_id);
EXPECT_EQ(instance_id, thread_debug_info.GetInstanceId());
EXPECT_EQ(instance_id_str, PrintId(thread_debug_info.GetInstanceId()));
TUniqueId query_id;
query_id.hi = 1234;
query_id.lo = 4567;
thread_debug_info.SetQueryId(query_id);
string query_id_str = PrintId(query_id);
EXPECT_EQ(query_id, thread_debug_info.GetQueryId());
EXPECT_EQ(query_id_str, PrintId(thread_debug_info.GetQueryId()));
}
TEST(ThreadDebugInfo, ThreadName) {
// Checks if we can store the thread name.
// If thread name is too long, the prefix of the thread name is stored.
ThreadDebugInfo thread_debug_info;
string thread_name = "thread-1";
thread_debug_info.SetThreadName(thread_name);
EXPECT_EQ(thread_name, thread_debug_info.GetThreadName());
string a_255(255, 'a');
string b_255(255, 'b');
string a_b = a_255 + b_255;
thread_debug_info.SetThreadName(a_b);
string stored_name = thread_debug_info.GetThreadName();
// Let's check if we stored the corrects parts of thread name
string expected = a_255.substr(0, 244) + "..." + b_255.substr(0, 8);
EXPECT_EQ(expected, stored_name);
}
TEST(ThreadDebugInfo, Global) {
// Checks if the constructor of the local ThreadDebugInfo object set the
// global pointer to itself.
ThreadDebugInfo thread_debug_info;
ThreadDebugInfo* global_thread_debug_info = GetThreadDebugInfo();
EXPECT_EQ(&thread_debug_info, global_thread_debug_info);
}
TEST(ThreadDebugInfo, ThreadCreateRelationships) {
// Checks if child thread extracts debug info from parent automatically.
// Child's thread name is given in Thread::Create
// Child's instance_id_ should be the same as parent's instance_id_
// Child should store a copy of its parent's thread name.
// Child should store its parent's system thread id.
string parent_name = "Parent";
string child_name = "Child";
ThreadDebugInfo parent_tdi;
parent_tdi.SetThreadName(parent_name);
TUniqueId instance_id;
instance_id.hi = 123;
instance_id.lo = 456;
parent_tdi.SetInstanceId(instance_id);
TUniqueId query_id;
query_id.hi = 123;
query_id.lo = 456;
parent_tdi.SetQueryId(query_id);
std::unique_ptr<Thread> child_thread;
auto f = [instance_id, query_id, child_name, parent_name, &parent_tdi]() {
// In child's thread the global ThreadDebugInfo object points to the child's own
// ThreadDebugInfo object which was automatically created in Thread::SuperviseThread
ThreadDebugInfo* child_tdi = GetThreadDebugInfo();
EXPECT_EQ(child_name, child_tdi->GetThreadName());
EXPECT_EQ(instance_id, child_tdi->GetInstanceId());
EXPECT_EQ(query_id, child_tdi->GetQueryId());
EXPECT_EQ(parent_name, child_tdi->GetParentThreadName());
EXPECT_EQ(parent_tdi.GetSystemThreadId(), child_tdi->GetParentSystemThreadId());
};
ASSERT_OK(Thread::Create("Test", child_name, f, &child_thread));
child_thread->Join();
}
TEST(ThreadDebugInfo, Scoping) {
TUniqueId id;
id.hi = 123;
id.lo = 456;
TUniqueId id2;
id.hi = 234;
id.lo = 345;
ThreadDebugInfo tdi;
ASSERT_EQ(ThreadDebugInfo::ZERO_THREAD_ID, tdi.GetQueryId());
ASSERT_EQ(ThreadDebugInfo::ZERO_THREAD_ID, tdi.GetInstanceId());
{
ScopedThreadContext s(&tdi, id);
ASSERT_EQ(id, tdi.GetQueryId());
ASSERT_EQ(ThreadDebugInfo::ZERO_THREAD_ID, tdi.GetInstanceId());
}
ASSERT_EQ(ThreadDebugInfo::ZERO_THREAD_ID, tdi.GetQueryId());
ASSERT_EQ(ThreadDebugInfo::ZERO_THREAD_ID, tdi.GetInstanceId());
{
ScopedThreadContext s(&tdi, id, id2);
ASSERT_EQ(id, tdi.GetQueryId());
ASSERT_EQ(id2, tdi.GetInstanceId());
}
ASSERT_EQ(ThreadDebugInfo::ZERO_THREAD_ID, tdi.GetQueryId());
ASSERT_EQ(ThreadDebugInfo::ZERO_THREAD_ID, tdi.GetInstanceId());
}
}