Home | History | Annotate | Download | only in base
      1 /*
      2  * libjingle
      3  * Copyright 2003-2008, Google Inc.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *  1. Redistributions of source code must retain the above copyright notice,
      9  *     this list of conditions and the following disclaimer.
     10  *  2. Redistributions in binary form must reproduce the above copyright notice,
     11  *     this list of conditions and the following disclaimer in the documentation
     12  *     and/or other materials provided with the distribution.
     13  *  3. The name of the author may not be used to endorse or promote products
     14  *     derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 // Unittest for registry access API
     29 
     30 #include "talk/base/gunit.h"
     31 #include "talk/base/common.h"
     32 #include "talk/base/win32regkey.h"
     33 
     34 namespace talk_base {
     35 
     36 #ifndef EXPECT_SUCCEEDED
     37 #define EXPECT_SUCCEEDED(x)  EXPECT_TRUE(SUCCEEDED(x))
     38 #endif
     39 
     40 #ifndef EXPECT_FAILED
     41 #define EXPECT_FAILED(x)  EXPECT_TRUE(FAILED(x))
     42 #endif
     43 
     44 #define kBaseKey           L"Software\\Google\\__TEST"
     45 #define kSubkeyName        L"subkey_test"
     46 
     47 const wchar_t kRkey1[] = kBaseKey;
     48 const wchar_t kRkey1SubkeyName[] = kSubkeyName;
     49 const wchar_t kRkey1Subkey[] = kBaseKey L"\\" kSubkeyName;
     50 const wchar_t kFullRkey1[] = L"HKCU\\" kBaseKey;
     51 const wchar_t kFullRkey1Subkey[] = L"HKCU\\" kBaseKey L"\\" kSubkeyName;
     52 
     53 const wchar_t kValNameInt[] = L"Int32 Value";
     54 const DWORD kIntVal = 20;
     55 const DWORD kIntVal2 = 30;
     56 
     57 const wchar_t kValNameInt64[] = L"Int64 Value";
     58 const DWORD64 kIntVal64 = 119600064000000000uI64;
     59 
     60 const wchar_t kValNameFloat[] = L"Float Value";
     61 const float kFloatVal = 12.3456789f;
     62 
     63 const wchar_t kValNameDouble[] = L"Double Value";
     64 const double kDoubleVal = 98.7654321;
     65 
     66 const wchar_t kValNameStr[] = L"Str Value";
     67 const wchar_t kStrVal[] = L"Some string data 1";
     68 const wchar_t kStrVal2[] = L"Some string data 2";
     69 
     70 const wchar_t kValNameBinary[] = L"Binary Value";
     71 const char kBinaryVal[] = "Some binary data abcdefghi 1";
     72 const char kBinaryVal2[] = "Some binary data abcdefghi 2";
     73 
     74 const wchar_t kValNameMultiStr[] = L"MultiStr Value";
     75 const wchar_t kMultiSZ[] = L"abc\0def\0P12345\0";
     76 const wchar_t kEmptyMultiSZ[] = L"";
     77 const wchar_t kInvalidMultiSZ[] = {L'6', L'7', L'8'};
     78 
     79 // friend function of RegKey
     80 void RegKeyHelperFunctionsTest() {
     81   // Try out some dud values
     82   std::wstring temp_key = L"";
     83   EXPECT_TRUE(RegKey::GetRootKeyInfo(&temp_key) == NULL);
     84   EXPECT_STREQ(temp_key.c_str(), L"");
     85 
     86   temp_key = L"a";
     87   EXPECT_TRUE(RegKey::GetRootKeyInfo(&temp_key) == NULL);
     88   EXPECT_STREQ(temp_key.c_str(), L"");
     89 
     90   // The basics
     91   temp_key = L"HKLM\\a";
     92   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_LOCAL_MACHINE);
     93   EXPECT_STREQ(temp_key.c_str(), L"a");
     94 
     95   temp_key = L"HKEY_LOCAL_MACHINE\\a";
     96   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_LOCAL_MACHINE);
     97   EXPECT_STREQ(temp_key.c_str(), L"a");
     98 
     99   temp_key = L"HKCU\\a";
    100   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CURRENT_USER);
    101   EXPECT_STREQ(temp_key.c_str(), L"a");
    102 
    103   temp_key = L"HKEY_CURRENT_USER\\a";
    104   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CURRENT_USER);
    105   EXPECT_STREQ(temp_key.c_str(), L"a");
    106 
    107   temp_key = L"HKU\\a";
    108   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_USERS);
    109   EXPECT_STREQ(temp_key.c_str(), L"a");
    110 
    111   temp_key = L"HKEY_USERS\\a";
    112   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_USERS);
    113   EXPECT_STREQ(temp_key.c_str(), L"a");
    114 
    115   temp_key = L"HKCR\\a";
    116   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CLASSES_ROOT);
    117   EXPECT_STREQ(temp_key.c_str(), L"a");
    118 
    119   temp_key = L"HKEY_CLASSES_ROOT\\a";
    120   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CLASSES_ROOT);
    121   EXPECT_STREQ(temp_key.c_str(), L"a");
    122 
    123   // Make sure it is case insensitive
    124   temp_key = L"hkcr\\a";
    125   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CLASSES_ROOT);
    126   EXPECT_STREQ(temp_key.c_str(), L"a");
    127 
    128   temp_key = L"hkey_CLASSES_ROOT\\a";
    129   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CLASSES_ROOT);
    130   EXPECT_STREQ(temp_key.c_str(), L"a");
    131 
    132   //
    133   // Test RegKey::GetParentKeyInfo
    134   //
    135 
    136   // dud cases
    137   temp_key = L"";
    138   EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L"");
    139   EXPECT_STREQ(temp_key.c_str(), L"");
    140 
    141   temp_key = L"a";
    142   EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L"");
    143   EXPECT_STREQ(temp_key.c_str(), L"a");
    144 
    145   temp_key = L"a\\b";
    146   EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L"a");
    147   EXPECT_STREQ(temp_key.c_str(), L"b");
    148 
    149   temp_key = L"\\b";
    150   EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L"");
    151   EXPECT_STREQ(temp_key.c_str(), L"b");
    152 
    153   // Some regular cases
    154   temp_key = L"HKEY_CLASSES_ROOT\\moon";
    155   EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(),
    156                L"HKEY_CLASSES_ROOT");
    157   EXPECT_STREQ(temp_key.c_str(), L"moon");
    158 
    159   temp_key = L"HKEY_CLASSES_ROOT\\moon\\doggy";
    160   EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(),
    161                L"HKEY_CLASSES_ROOT\\moon");
    162   EXPECT_STREQ(temp_key.c_str(), L"doggy");
    163 
    164   //
    165   // Test MultiSZBytesToStringArray
    166   //
    167 
    168   std::vector<std::wstring> result;
    169   EXPECT_SUCCEEDED(RegKey::MultiSZBytesToStringArray(
    170       reinterpret_cast<const uint8*>(kMultiSZ), sizeof(kMultiSZ), &result));
    171   EXPECT_EQ(result.size(), 3);
    172   EXPECT_STREQ(result[0].c_str(), L"abc");
    173   EXPECT_STREQ(result[1].c_str(), L"def");
    174   EXPECT_STREQ(result[2].c_str(), L"P12345");
    175 
    176   EXPECT_SUCCEEDED(RegKey::MultiSZBytesToStringArray(
    177       reinterpret_cast<const uint8*>(kEmptyMultiSZ),
    178       sizeof(kEmptyMultiSZ), &result));
    179   EXPECT_EQ(result.size(), 0);
    180   EXPECT_FALSE(SUCCEEDED(RegKey::MultiSZBytesToStringArray(
    181       reinterpret_cast<const uint8*>(kInvalidMultiSZ),
    182       sizeof(kInvalidMultiSZ), &result)));
    183 }
    184 
    185 TEST(RegKeyTest, RegKeyHelperFunctionsTest) {
    186   RegKeyHelperFunctionsTest();
    187 }
    188 
    189 TEST(RegKeyTest, RegKeyNonStaticFunctionsTest) {
    190   DWORD int_val = 0;
    191   DWORD64 int64_val = 0;
    192   wchar_t* str_val = NULL;
    193   uint8* binary_val = NULL;
    194   DWORD uint8_count = 0;
    195 
    196   // Just in case...
    197   // make sure the no test key residue is left from previous aborted runs
    198   RegKey::DeleteKey(kFullRkey1);
    199 
    200   // initial state
    201   RegKey r_key;
    202   EXPECT_TRUE(r_key.key() == NULL);
    203 
    204   // create a reg key
    205   EXPECT_SUCCEEDED(r_key.Create(HKEY_CURRENT_USER, kRkey1));
    206 
    207   // do the create twice - it should return the already created one
    208   EXPECT_SUCCEEDED(r_key.Create(HKEY_CURRENT_USER, kRkey1));
    209 
    210   // now do an open - should work just fine
    211   EXPECT_SUCCEEDED(r_key.Open(HKEY_CURRENT_USER, kRkey1));
    212 
    213   // get an in-existent value
    214   EXPECT_EQ(r_key.GetValue(kValNameInt, &int_val),
    215             HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
    216 
    217   // set and get some values
    218 
    219   // set an INT 32
    220   EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt, kIntVal));
    221 
    222   // check that the value exists
    223   EXPECT_TRUE(r_key.HasValue(kValNameInt));
    224 
    225   // read it back
    226   EXPECT_SUCCEEDED(r_key.GetValue(kValNameInt, &int_val));
    227   EXPECT_EQ(int_val, kIntVal);
    228 
    229   // set it again!
    230   EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt, kIntVal2));
    231 
    232   // read it again
    233   EXPECT_SUCCEEDED(r_key.GetValue(kValNameInt, &int_val));
    234   EXPECT_EQ(int_val, kIntVal2);
    235 
    236   // delete the value
    237   EXPECT_SUCCEEDED(r_key.DeleteValue(kValNameInt));
    238 
    239   // check that the value is gone
    240   EXPECT_FALSE(r_key.HasValue(kValNameInt));
    241 
    242   // set an INT 64
    243   EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt64, kIntVal64));
    244 
    245   // check that the value exists
    246   EXPECT_TRUE(r_key.HasValue(kValNameInt64));
    247 
    248   // read it back
    249   EXPECT_SUCCEEDED(r_key.GetValue(kValNameInt64, &int64_val));
    250   EXPECT_EQ(int64_val, kIntVal64);
    251 
    252   // delete the value
    253   EXPECT_SUCCEEDED(r_key.DeleteValue(kValNameInt64));
    254 
    255   // check that the value is gone
    256   EXPECT_FALSE(r_key.HasValue(kValNameInt64));
    257 
    258   // set a string
    259   EXPECT_SUCCEEDED(r_key.SetValue(kValNameStr, kStrVal));
    260 
    261   // check that the value exists
    262   EXPECT_TRUE(r_key.HasValue(kValNameStr));
    263 
    264   // read it back
    265   EXPECT_SUCCEEDED(r_key.GetValue(kValNameStr, &str_val));
    266   EXPECT_TRUE(lstrcmp(str_val, kStrVal) == 0);
    267   delete[] str_val;
    268 
    269   // set it again
    270   EXPECT_SUCCEEDED(r_key.SetValue(kValNameStr, kStrVal2));
    271 
    272   // read it again
    273   EXPECT_SUCCEEDED(r_key.GetValue(kValNameStr, &str_val));
    274   EXPECT_TRUE(lstrcmp(str_val, kStrVal2) == 0);
    275   delete[] str_val;
    276 
    277   // delete the value
    278   EXPECT_SUCCEEDED(r_key.DeleteValue(kValNameStr));
    279 
    280   // check that the value is gone
    281   EXPECT_FALSE(r_key.HasValue(kValNameInt));
    282 
    283   // set a binary value
    284   EXPECT_SUCCEEDED(r_key.SetValue(kValNameBinary,
    285       reinterpret_cast<const uint8*>(kBinaryVal), sizeof(kBinaryVal) - 1));
    286 
    287   // check that the value exists
    288   EXPECT_TRUE(r_key.HasValue(kValNameBinary));
    289 
    290   // read it back
    291   EXPECT_SUCCEEDED(r_key.GetValue(kValNameBinary, &binary_val, &uint8_count));
    292   EXPECT_TRUE(memcmp(binary_val, kBinaryVal, sizeof(kBinaryVal) - 1) == 0);
    293   delete[] binary_val;
    294 
    295   // set it again
    296   EXPECT_SUCCEEDED(r_key.SetValue(kValNameBinary,
    297       reinterpret_cast<const uint8*>(kBinaryVal2), sizeof(kBinaryVal) - 1));
    298 
    299   // read it again
    300   EXPECT_SUCCEEDED(r_key.GetValue(kValNameBinary, &binary_val, &uint8_count));
    301   EXPECT_TRUE(memcmp(binary_val, kBinaryVal2, sizeof(kBinaryVal2) - 1) == 0);
    302   delete[] binary_val;
    303 
    304   // delete the value
    305   EXPECT_SUCCEEDED(r_key.DeleteValue(kValNameBinary));
    306 
    307   // check that the value is gone
    308   EXPECT_FALSE(r_key.HasValue(kValNameBinary));
    309 
    310   // set some values and check the total count
    311 
    312   // set an INT 32
    313   EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt, kIntVal));
    314 
    315   // set an INT 64
    316   EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt64, kIntVal64));
    317 
    318   // set a string
    319   EXPECT_SUCCEEDED(r_key.SetValue(kValNameStr, kStrVal));
    320 
    321   // set a binary value
    322   EXPECT_SUCCEEDED(r_key.SetValue(kValNameBinary,
    323       reinterpret_cast<const uint8*>(kBinaryVal), sizeof(kBinaryVal) - 1));
    324 
    325   // get the value count
    326   uint32 value_count = r_key.GetValueCount();
    327   EXPECT_EQ(value_count, 4);
    328 
    329   // check the value names
    330   std::wstring value_name;
    331   DWORD type = 0;
    332 
    333   EXPECT_SUCCEEDED(r_key.GetValueNameAt(0, &value_name, &type));
    334   EXPECT_STREQ(value_name.c_str(), kValNameInt);
    335   EXPECT_EQ(type, REG_DWORD);
    336 
    337   EXPECT_SUCCEEDED(r_key.GetValueNameAt(1, &value_name, &type));
    338   EXPECT_STREQ(value_name.c_str(), kValNameInt64);
    339   EXPECT_EQ(type, REG_QWORD);
    340 
    341   EXPECT_SUCCEEDED(r_key.GetValueNameAt(2, &value_name, &type));
    342   EXPECT_STREQ(value_name.c_str(), kValNameStr);
    343   EXPECT_EQ(type, REG_SZ);
    344 
    345   EXPECT_SUCCEEDED(r_key.GetValueNameAt(3, &value_name, &type));
    346   EXPECT_STREQ(value_name.c_str(), kValNameBinary);
    347   EXPECT_EQ(type, REG_BINARY);
    348 
    349   // check that there are no more values
    350   EXPECT_FAILED(r_key.GetValueNameAt(4, &value_name, &type));
    351 
    352   uint32 subkey_count = r_key.GetSubkeyCount();
    353   EXPECT_EQ(subkey_count, 0);
    354 
    355   // now create a subkey and make sure we can get the name
    356   RegKey temp_key;
    357   EXPECT_SUCCEEDED(temp_key.Create(HKEY_CURRENT_USER, kRkey1Subkey));
    358 
    359   // check the subkey exists
    360   EXPECT_TRUE(r_key.HasSubkey(kRkey1SubkeyName));
    361 
    362   // check the name
    363   EXPECT_EQ(r_key.GetSubkeyCount(), 1);
    364 
    365   std::wstring subkey_name;
    366   EXPECT_SUCCEEDED(r_key.GetSubkeyNameAt(0, &subkey_name));
    367   EXPECT_STREQ(subkey_name.c_str(), kRkey1SubkeyName);
    368 
    369   // delete the key
    370   EXPECT_SUCCEEDED(r_key.DeleteSubKey(kRkey1));
    371 
    372   // close this key
    373   EXPECT_SUCCEEDED(r_key.Close());
    374 
    375   // whack the whole key
    376   EXPECT_SUCCEEDED(RegKey::DeleteKey(kFullRkey1));
    377 }
    378 
    379 TEST(RegKeyTest, RegKeyStaticFunctionsTest) {
    380   DWORD int_val = 0;
    381   DWORD64 int64_val = 0;
    382   float float_val = 0;
    383   double double_val = 0;
    384   wchar_t* str_val = NULL;
    385   std::wstring wstr_val;
    386   uint8* binary_val = NULL;
    387   DWORD uint8_count = 0;
    388 
    389   // Just in case...
    390   // make sure the no test key residue is left from previous aborted runs
    391   RegKey::DeleteKey(kFullRkey1);
    392 
    393   // get an in-existent value from an un-existent key
    394   EXPECT_EQ(RegKey::GetValue(kFullRkey1, kValNameInt, &int_val),
    395             HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
    396 
    397   // set int32
    398   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameInt, kIntVal));
    399 
    400   // check that the value exists
    401   EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameInt));
    402 
    403   // get an in-existent value from an existent key
    404   EXPECT_EQ(RegKey::GetValue(kFullRkey1, L"bogus", &int_val),
    405             HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
    406 
    407   // read it back
    408   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameInt, &int_val));
    409   EXPECT_EQ(int_val, kIntVal);
    410 
    411   // delete the value
    412   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameInt));
    413 
    414   // check that the value is gone
    415   EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameInt));
    416 
    417   // set int64
    418   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameInt64, kIntVal64));
    419 
    420   // check that the value exists
    421   EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameInt64));
    422 
    423   // read it back
    424   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameInt64, &int64_val));
    425   EXPECT_EQ(int64_val, kIntVal64);
    426 
    427   // delete the value
    428   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameInt64));
    429 
    430   // check that the value is gone
    431   EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameInt64));
    432 
    433   // set float
    434   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameFloat, kFloatVal));
    435 
    436   // check that the value exists
    437   EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameFloat));
    438 
    439   // read it back
    440   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameFloat, &float_val));
    441   EXPECT_EQ(float_val, kFloatVal);
    442 
    443   // delete the value
    444   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameFloat));
    445 
    446   // check that the value is gone
    447   EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameFloat));
    448   EXPECT_FAILED(RegKey::GetValue(kFullRkey1, kValNameFloat, &float_val));
    449 
    450   // set double
    451   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameDouble, kDoubleVal));
    452 
    453   // check that the value exists
    454   EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameDouble));
    455 
    456   // read it back
    457   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameDouble, &double_val));
    458   EXPECT_EQ(double_val, kDoubleVal);
    459 
    460   // delete the value
    461   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameDouble));
    462 
    463   // check that the value is gone
    464   EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameDouble));
    465   EXPECT_FAILED(RegKey::GetValue(kFullRkey1, kValNameDouble, &double_val));
    466 
    467   // set string
    468   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameStr, kStrVal));
    469 
    470   // check that the value exists
    471   EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameStr));
    472 
    473   // read it back
    474   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameStr, &str_val));
    475   EXPECT_TRUE(lstrcmp(str_val, kStrVal) == 0);
    476   delete[] str_val;
    477 
    478   // read it back in std::wstring
    479   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameStr, &wstr_val));
    480   EXPECT_STREQ(wstr_val.c_str(), kStrVal);
    481 
    482   // get an in-existent value from an existent key
    483   EXPECT_EQ(RegKey::GetValue(kFullRkey1, L"bogus", &str_val),
    484             HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
    485 
    486   // delete the value
    487   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameStr));
    488 
    489   // check that the value is gone
    490   EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameStr));
    491 
    492   // set binary
    493   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameBinary,
    494       reinterpret_cast<const uint8*>(kBinaryVal), sizeof(kBinaryVal)-1));
    495 
    496   // check that the value exists
    497   EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameBinary));
    498 
    499   // read it back
    500   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameBinary,
    501       &binary_val, &uint8_count));
    502   EXPECT_TRUE(memcmp(binary_val, kBinaryVal, sizeof(kBinaryVal)-1) == 0);
    503   delete[] binary_val;
    504 
    505   // delete the value
    506   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameBinary));
    507 
    508   // check that the value is gone
    509   EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameBinary));
    510 
    511   // special case - set a binary value with length 0
    512   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameBinary,
    513       reinterpret_cast<const uint8*>(kBinaryVal), 0));
    514 
    515   // check that the value exists
    516   EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameBinary));
    517 
    518   // read it back
    519   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameBinary,
    520       &binary_val, &uint8_count));
    521   EXPECT_EQ(uint8_count, 0);
    522   EXPECT_TRUE(binary_val == NULL);
    523   delete[] binary_val;
    524 
    525   // delete the value
    526   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameBinary));
    527 
    528   // check that the value is gone
    529   EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameBinary));
    530 
    531   // special case - set a NULL binary value
    532   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameBinary, NULL, 100));
    533 
    534   // check that the value exists
    535   EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameBinary));
    536 
    537   // read it back
    538   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameBinary,
    539                                     &binary_val, &uint8_count));
    540   EXPECT_EQ(uint8_count, 0);
    541   EXPECT_TRUE(binary_val == NULL);
    542   delete[] binary_val;
    543 
    544   // delete the value
    545   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameBinary));
    546 
    547   // check that the value is gone
    548   EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameBinary));
    549 
    550   // test read/write REG_MULTI_SZ value
    551   std::vector<std::wstring> result;
    552   EXPECT_SUCCEEDED(RegKey::SetValueMultiSZ(kFullRkey1, kValNameMultiStr,
    553       reinterpret_cast<const uint8*>(kMultiSZ), sizeof(kMultiSZ)));
    554   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameMultiStr, &result));
    555   EXPECT_EQ(result.size(), 3);
    556   EXPECT_STREQ(result[0].c_str(), L"abc");
    557   EXPECT_STREQ(result[1].c_str(), L"def");
    558   EXPECT_STREQ(result[2].c_str(), L"P12345");
    559   EXPECT_SUCCEEDED(RegKey::SetValueMultiSZ(kFullRkey1, kValNameMultiStr,
    560       reinterpret_cast<const uint8*>(kEmptyMultiSZ), sizeof(kEmptyMultiSZ)));
    561   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameMultiStr, &result));
    562   EXPECT_EQ(result.size(), 0);
    563   // writing REG_MULTI_SZ value will automatically add ending null characters
    564   EXPECT_SUCCEEDED(RegKey::SetValueMultiSZ(kFullRkey1, kValNameMultiStr,
    565       reinterpret_cast<const uint8*>(kInvalidMultiSZ), sizeof(kInvalidMultiSZ)));
    566   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameMultiStr, &result));
    567   EXPECT_EQ(result.size(), 1);
    568   EXPECT_STREQ(result[0].c_str(), L"678");
    569 
    570   // Run the following test only in dev machine
    571   // This is because the build machine might not have admin privilege
    572 #ifdef IS_PRIVATE_BUILD
    573   // get a temp file name
    574   wchar_t temp_path[MAX_PATH] = {0};
    575   EXPECT_LT(::GetTempPath(ARRAY_SIZE(temp_path), temp_path),
    576             static_cast<DWORD>(ARRAY_SIZE(temp_path)));
    577   wchar_t temp_file[MAX_PATH] = {0};
    578   EXPECT_NE(::GetTempFileName(temp_path, L"rkut_",
    579                               ::GetTickCount(), temp_file), 0);
    580 
    581   // test save
    582   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1Subkey, kValNameInt, kIntVal));
    583   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1Subkey, kValNameInt64, kIntVal64));
    584   EXPECT_SUCCEEDED(RegKey::Save(kFullRkey1Subkey, temp_file));
    585   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1Subkey, kValNameInt));
    586   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1Subkey, kValNameInt64));
    587 
    588   // test restore
    589   EXPECT_SUCCEEDED(RegKey::Restore(kFullRkey1Subkey, temp_file));
    590   int_val = 0;
    591   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1Subkey, kValNameInt, &int_val));
    592   EXPECT_EQ(int_val, kIntVal);
    593   int64_val = 0;
    594   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1Subkey,
    595                                     kValNameInt64,
    596                                     &int64_val));
    597   EXPECT_EQ(int64_val, kIntVal64);
    598 
    599   // delete the temp file
    600   EXPECT_EQ(TRUE, ::DeleteFile(temp_file));
    601 #endif
    602 
    603   // whack the whole key
    604   EXPECT_SUCCEEDED(RegKey::DeleteKey(kFullRkey1));
    605 }
    606 
    607 }  // namespace talk_base
    608