/* * Copyright 2003 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. */ // Unittest for registry access API #include "webrtc/base/gunit.h" #include "webrtc/base/common.h" #include "webrtc/base/win32regkey.h" namespace rtc { #ifndef EXPECT_SUCCEEDED #define EXPECT_SUCCEEDED(x) EXPECT_TRUE(SUCCEEDED(x)) #endif #ifndef EXPECT_FAILED #define EXPECT_FAILED(x) EXPECT_TRUE(FAILED(x)) #endif #define kBaseKey L"Software\\Google\\__TEST" #define kSubkeyName L"subkey_test" const wchar_t kRkey1[] = kBaseKey; const wchar_t kRkey1SubkeyName[] = kSubkeyName; const wchar_t kRkey1Subkey[] = kBaseKey L"\\" kSubkeyName; const wchar_t kFullRkey1[] = L"HKCU\\" kBaseKey; const wchar_t kFullRkey1Subkey[] = L"HKCU\\" kBaseKey L"\\" kSubkeyName; const wchar_t kValNameInt[] = L"Int32 Value"; const DWORD kIntVal = 20; const DWORD kIntVal2 = 30; const wchar_t kValNameInt64[] = L"Int64 Value"; const DWORD64 kIntVal64 = 119600064000000000uI64; const wchar_t kValNameFloat[] = L"Float Value"; const float kFloatVal = 12.3456789f; const wchar_t kValNameDouble[] = L"Double Value"; const double kDoubleVal = 98.7654321; const wchar_t kValNameStr[] = L"Str Value"; const wchar_t kStrVal[] = L"Some string data 1"; const wchar_t kStrVal2[] = L"Some string data 2"; const wchar_t kValNameBinary[] = L"Binary Value"; const char kBinaryVal[] = "Some binary data abcdefghi 1"; const char kBinaryVal2[] = "Some binary data abcdefghi 2"; const wchar_t kValNameMultiStr[] = L"MultiStr Value"; const wchar_t kMultiSZ[] = L"abc\0def\0P12345\0"; const wchar_t kEmptyMultiSZ[] = L""; const wchar_t kInvalidMultiSZ[] = {L'6', L'7', L'8'}; // friend function of RegKey void RegKeyHelperFunctionsTest() { // Try out some dud values std::wstring temp_key = L""; EXPECT_TRUE(RegKey::GetRootKeyInfo(&temp_key) == NULL); EXPECT_STREQ(temp_key.c_str(), L""); temp_key = L"a"; EXPECT_TRUE(RegKey::GetRootKeyInfo(&temp_key) == NULL); EXPECT_STREQ(temp_key.c_str(), L""); // The basics temp_key = L"HKLM\\a"; EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_LOCAL_MACHINE); EXPECT_STREQ(temp_key.c_str(), L"a"); temp_key = L"HKEY_LOCAL_MACHINE\\a"; EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_LOCAL_MACHINE); EXPECT_STREQ(temp_key.c_str(), L"a"); temp_key = L"HKCU\\a"; EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CURRENT_USER); EXPECT_STREQ(temp_key.c_str(), L"a"); temp_key = L"HKEY_CURRENT_USER\\a"; EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CURRENT_USER); EXPECT_STREQ(temp_key.c_str(), L"a"); temp_key = L"HKU\\a"; EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_USERS); EXPECT_STREQ(temp_key.c_str(), L"a"); temp_key = L"HKEY_USERS\\a"; EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_USERS); EXPECT_STREQ(temp_key.c_str(), L"a"); temp_key = L"HKCR\\a"; EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CLASSES_ROOT); EXPECT_STREQ(temp_key.c_str(), L"a"); temp_key = L"HKEY_CLASSES_ROOT\\a"; EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CLASSES_ROOT); EXPECT_STREQ(temp_key.c_str(), L"a"); // Make sure it is case insensitive temp_key = L"hkcr\\a"; EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CLASSES_ROOT); EXPECT_STREQ(temp_key.c_str(), L"a"); temp_key = L"hkey_CLASSES_ROOT\\a"; EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CLASSES_ROOT); EXPECT_STREQ(temp_key.c_str(), L"a"); // // Test RegKey::GetParentKeyInfo // // dud cases temp_key = L""; EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L""); EXPECT_STREQ(temp_key.c_str(), L""); temp_key = L"a"; EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L""); EXPECT_STREQ(temp_key.c_str(), L"a"); temp_key = L"a\\b"; EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L"a"); EXPECT_STREQ(temp_key.c_str(), L"b"); temp_key = L"\\b"; EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L""); EXPECT_STREQ(temp_key.c_str(), L"b"); // Some regular cases temp_key = L"HKEY_CLASSES_ROOT\\moon"; EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L"HKEY_CLASSES_ROOT"); EXPECT_STREQ(temp_key.c_str(), L"moon"); temp_key = L"HKEY_CLASSES_ROOT\\moon\\doggy"; EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L"HKEY_CLASSES_ROOT\\moon"); EXPECT_STREQ(temp_key.c_str(), L"doggy"); // // Test MultiSZBytesToStringArray // std::vector result; EXPECT_SUCCEEDED(RegKey::MultiSZBytesToStringArray( reinterpret_cast(kMultiSZ), sizeof(kMultiSZ), &result)); EXPECT_EQ(result.size(), 3); EXPECT_STREQ(result[0].c_str(), L"abc"); EXPECT_STREQ(result[1].c_str(), L"def"); EXPECT_STREQ(result[2].c_str(), L"P12345"); EXPECT_SUCCEEDED(RegKey::MultiSZBytesToStringArray( reinterpret_cast(kEmptyMultiSZ), sizeof(kEmptyMultiSZ), &result)); EXPECT_EQ(result.size(), 0); EXPECT_FALSE(SUCCEEDED(RegKey::MultiSZBytesToStringArray( reinterpret_cast(kInvalidMultiSZ), sizeof(kInvalidMultiSZ), &result))); } TEST(RegKeyTest, RegKeyHelperFunctionsTest) { RegKeyHelperFunctionsTest(); } void RegKeyNonStaticFunctionsTest() { DWORD int_val = 0; DWORD64 int64_val = 0; wchar_t* str_val = NULL; uint8_t* binary_val = NULL; DWORD uint8_count = 0; // Just in case... // make sure the no test key residue is left from previous aborted runs RegKey::DeleteKey(kFullRkey1); // initial state RegKey r_key; EXPECT_TRUE(r_key.key() == NULL); // create a reg key EXPECT_SUCCEEDED(r_key.Create(HKEY_CURRENT_USER, kRkey1)); // do the create twice - it should return the already created one EXPECT_SUCCEEDED(r_key.Create(HKEY_CURRENT_USER, kRkey1)); // now do an open - should work just fine EXPECT_SUCCEEDED(r_key.Open(HKEY_CURRENT_USER, kRkey1)); // get an in-existent value EXPECT_EQ(r_key.GetValue(kValNameInt, &int_val), HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); // set and get some values // set an INT 32 EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt, kIntVal)); // check that the value exists EXPECT_TRUE(r_key.HasValue(kValNameInt)); // read it back EXPECT_SUCCEEDED(r_key.GetValue(kValNameInt, &int_val)); EXPECT_EQ(int_val, kIntVal); // set it again! EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt, kIntVal2)); // read it again EXPECT_SUCCEEDED(r_key.GetValue(kValNameInt, &int_val)); EXPECT_EQ(int_val, kIntVal2); // delete the value EXPECT_SUCCEEDED(r_key.DeleteValue(kValNameInt)); // check that the value is gone EXPECT_FALSE(r_key.HasValue(kValNameInt)); // set an INT 64 EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt64, kIntVal64)); // check that the value exists EXPECT_TRUE(r_key.HasValue(kValNameInt64)); // read it back EXPECT_SUCCEEDED(r_key.GetValue(kValNameInt64, &int64_val)); EXPECT_EQ(int64_val, kIntVal64); // delete the value EXPECT_SUCCEEDED(r_key.DeleteValue(kValNameInt64)); // check that the value is gone EXPECT_FALSE(r_key.HasValue(kValNameInt64)); // set a string EXPECT_SUCCEEDED(r_key.SetValue(kValNameStr, kStrVal)); // check that the value exists EXPECT_TRUE(r_key.HasValue(kValNameStr)); // read it back EXPECT_SUCCEEDED(r_key.GetValue(kValNameStr, &str_val)); EXPECT_TRUE(lstrcmp(str_val, kStrVal) == 0); delete[] str_val; // set it again EXPECT_SUCCEEDED(r_key.SetValue(kValNameStr, kStrVal2)); // read it again EXPECT_SUCCEEDED(r_key.GetValue(kValNameStr, &str_val)); EXPECT_TRUE(lstrcmp(str_val, kStrVal2) == 0); delete[] str_val; // delete the value EXPECT_SUCCEEDED(r_key.DeleteValue(kValNameStr)); // check that the value is gone EXPECT_FALSE(r_key.HasValue(kValNameInt)); // set a binary value EXPECT_SUCCEEDED(r_key.SetValue(kValNameBinary, reinterpret_cast(kBinaryVal), sizeof(kBinaryVal) - 1)); // check that the value exists EXPECT_TRUE(r_key.HasValue(kValNameBinary)); // read it back EXPECT_SUCCEEDED(r_key.GetValue(kValNameBinary, &binary_val, &uint8_count)); EXPECT_TRUE(memcmp(binary_val, kBinaryVal, sizeof(kBinaryVal) - 1) == 0); delete[] binary_val; // set it again EXPECT_SUCCEEDED(r_key.SetValue(kValNameBinary, reinterpret_cast(kBinaryVal2), sizeof(kBinaryVal) - 1)); // read it again EXPECT_SUCCEEDED(r_key.GetValue(kValNameBinary, &binary_val, &uint8_count)); EXPECT_TRUE(memcmp(binary_val, kBinaryVal2, sizeof(kBinaryVal2) - 1) == 0); delete[] binary_val; // delete the value EXPECT_SUCCEEDED(r_key.DeleteValue(kValNameBinary)); // check that the value is gone EXPECT_FALSE(r_key.HasValue(kValNameBinary)); // set some values and check the total count // set an INT 32 EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt, kIntVal)); // set an INT 64 EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt64, kIntVal64)); // set a string EXPECT_SUCCEEDED(r_key.SetValue(kValNameStr, kStrVal)); // set a binary value EXPECT_SUCCEEDED(r_key.SetValue(kValNameBinary, reinterpret_cast(kBinaryVal), sizeof(kBinaryVal) - 1)); // get the value count uint32_t value_count = r_key.GetValueCount(); EXPECT_EQ(value_count, 4); // check the value names std::wstring value_name; DWORD type = 0; EXPECT_SUCCEEDED(r_key.GetValueNameAt(0, &value_name, &type)); EXPECT_STREQ(value_name.c_str(), kValNameInt); EXPECT_EQ(type, REG_DWORD); EXPECT_SUCCEEDED(r_key.GetValueNameAt(1, &value_name, &type)); EXPECT_STREQ(value_name.c_str(), kValNameInt64); EXPECT_EQ(type, REG_QWORD); EXPECT_SUCCEEDED(r_key.GetValueNameAt(2, &value_name, &type)); EXPECT_STREQ(value_name.c_str(), kValNameStr); EXPECT_EQ(type, REG_SZ); EXPECT_SUCCEEDED(r_key.GetValueNameAt(3, &value_name, &type)); EXPECT_STREQ(value_name.c_str(), kValNameBinary); EXPECT_EQ(type, REG_BINARY); // check that there are no more values EXPECT_FAILED(r_key.GetValueNameAt(4, &value_name, &type)); uint32_t subkey_count = r_key.GetSubkeyCount(); EXPECT_EQ(subkey_count, 0); // now create a subkey and make sure we can get the name RegKey temp_key; EXPECT_SUCCEEDED(temp_key.Create(HKEY_CURRENT_USER, kRkey1Subkey)); // check the subkey exists EXPECT_TRUE(r_key.HasSubkey(kRkey1SubkeyName)); // check the name EXPECT_EQ(r_key.GetSubkeyCount(), 1); std::wstring subkey_name; EXPECT_SUCCEEDED(r_key.GetSubkeyNameAt(0, &subkey_name)); EXPECT_STREQ(subkey_name.c_str(), kRkey1SubkeyName); // delete the key EXPECT_SUCCEEDED(r_key.DeleteSubKey(kRkey1)); // close this key EXPECT_SUCCEEDED(r_key.Close()); // whack the whole key EXPECT_SUCCEEDED(RegKey::DeleteKey(kFullRkey1)); } void RegKeyStaticFunctionsTest() { DWORD int_val = 0; DWORD64 int64_val = 0; float float_val = 0; double double_val = 0; wchar_t* str_val = NULL; std::wstring wstr_val; uint8_t* binary_val = NULL; DWORD uint8_count = 0; // Just in case... // make sure the no test key residue is left from previous aborted runs RegKey::DeleteKey(kFullRkey1); // get an in-existent value from an un-existent key EXPECT_EQ(RegKey::GetValue(kFullRkey1, kValNameInt, &int_val), HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); // set int32_t EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameInt, kIntVal)); // check that the value exists EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameInt)); // get an in-existent value from an existent key EXPECT_EQ(RegKey::GetValue(kFullRkey1, L"bogus", &int_val), HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); // read it back EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameInt, &int_val)); EXPECT_EQ(int_val, kIntVal); // delete the value EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameInt)); // check that the value is gone EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameInt)); // set int64_t EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameInt64, kIntVal64)); // check that the value exists EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameInt64)); // read it back EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameInt64, &int64_val)); EXPECT_EQ(int64_val, kIntVal64); // delete the value EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameInt64)); // check that the value is gone EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameInt64)); // set float EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameFloat, kFloatVal)); // check that the value exists EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameFloat)); // read it back EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameFloat, &float_val)); EXPECT_EQ(float_val, kFloatVal); // delete the value EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameFloat)); // check that the value is gone EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameFloat)); EXPECT_FAILED(RegKey::GetValue(kFullRkey1, kValNameFloat, &float_val)); // set double EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameDouble, kDoubleVal)); // check that the value exists EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameDouble)); // read it back EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameDouble, &double_val)); EXPECT_EQ(double_val, kDoubleVal); // delete the value EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameDouble)); // check that the value is gone EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameDouble)); EXPECT_FAILED(RegKey::GetValue(kFullRkey1, kValNameDouble, &double_val)); // set string EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameStr, kStrVal)); // check that the value exists EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameStr)); // read it back EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameStr, &str_val)); EXPECT_TRUE(lstrcmp(str_val, kStrVal) == 0); delete[] str_val; // read it back in std::wstring EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameStr, &wstr_val)); EXPECT_STREQ(wstr_val.c_str(), kStrVal); // get an in-existent value from an existent key EXPECT_EQ(RegKey::GetValue(kFullRkey1, L"bogus", &str_val), HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); // delete the value EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameStr)); // check that the value is gone EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameStr)); // set binary EXPECT_SUCCEEDED(RegKey::SetValue( kFullRkey1, kValNameBinary, reinterpret_cast(kBinaryVal), sizeof(kBinaryVal) - 1)); // check that the value exists EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameBinary)); // read it back EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameBinary, &binary_val, &uint8_count)); EXPECT_TRUE(memcmp(binary_val, kBinaryVal, sizeof(kBinaryVal)-1) == 0); delete[] binary_val; // delete the value EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameBinary)); // check that the value is gone EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameBinary)); // special case - set a binary value with length 0 EXPECT_SUCCEEDED( RegKey::SetValue(kFullRkey1, kValNameBinary, reinterpret_cast(kBinaryVal), 0)); // check that the value exists EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameBinary)); // read it back EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameBinary, &binary_val, &uint8_count)); EXPECT_EQ(uint8_count, 0); EXPECT_TRUE(binary_val == NULL); delete[] binary_val; // delete the value EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameBinary)); // check that the value is gone EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameBinary)); // special case - set a NULL binary value EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameBinary, NULL, 100)); // check that the value exists EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameBinary)); // read it back EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameBinary, &binary_val, &uint8_count)); EXPECT_EQ(uint8_count, 0); EXPECT_TRUE(binary_val == NULL); delete[] binary_val; // delete the value EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameBinary)); // check that the value is gone EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameBinary)); // test read/write REG_MULTI_SZ value std::vector result; EXPECT_SUCCEEDED(RegKey::SetValueMultiSZ( kFullRkey1, kValNameMultiStr, reinterpret_cast(kMultiSZ), sizeof(kMultiSZ))); EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameMultiStr, &result)); EXPECT_EQ(result.size(), 3); EXPECT_STREQ(result[0].c_str(), L"abc"); EXPECT_STREQ(result[1].c_str(), L"def"); EXPECT_STREQ(result[2].c_str(), L"P12345"); EXPECT_SUCCEEDED(RegKey::SetValueMultiSZ( kFullRkey1, kValNameMultiStr, reinterpret_cast(kEmptyMultiSZ), sizeof(kEmptyMultiSZ))); EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameMultiStr, &result)); EXPECT_EQ(result.size(), 0); // writing REG_MULTI_SZ value will automatically add ending null characters EXPECT_SUCCEEDED( RegKey::SetValueMultiSZ(kFullRkey1, kValNameMultiStr, reinterpret_cast(kInvalidMultiSZ), sizeof(kInvalidMultiSZ))); EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameMultiStr, &result)); EXPECT_EQ(result.size(), 1); EXPECT_STREQ(result[0].c_str(), L"678"); // Run the following test only in dev machine // This is because the build machine might not have admin privilege #ifdef IS_PRIVATE_BUILD // get a temp file name wchar_t temp_path[MAX_PATH] = {0}; EXPECT_LT(::GetTempPath(ARRAY_SIZE(temp_path), temp_path), static_cast(ARRAY_SIZE(temp_path))); wchar_t temp_file[MAX_PATH] = {0}; EXPECT_NE(::GetTempFileName(temp_path, L"rkut_", ::GetTickCount(), temp_file), 0); // test save EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1Subkey, kValNameInt, kIntVal)); EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1Subkey, kValNameInt64, kIntVal64)); EXPECT_SUCCEEDED(RegKey::Save(kFullRkey1Subkey, temp_file)); EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1Subkey, kValNameInt)); EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1Subkey, kValNameInt64)); // test restore EXPECT_SUCCEEDED(RegKey::Restore(kFullRkey1Subkey, temp_file)); int_val = 0; EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1Subkey, kValNameInt, &int_val)); EXPECT_EQ(int_val, kIntVal); int64_val = 0; EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1Subkey, kValNameInt64, &int64_val)); EXPECT_EQ(int64_val, kIntVal64); // delete the temp file EXPECT_EQ(TRUE, ::DeleteFile(temp_file)); #endif // whack the whole key EXPECT_SUCCEEDED(RegKey::DeleteKey(kFullRkey1)); } // Run both tests under the same test target. Because they access (read and // write) the same registry keys they can't run in parallel with eachother. TEST(RegKeyTest, RegKeyFunctionsTest) { RegKeyNonStaticFunctionsTest(); RegKeyStaticFunctionsTest(); } } // namespace rtc