registry_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. // Copyright 2015 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // +build windows
  5. package registry_test
  6. import (
  7. "bytes"
  8. "crypto/rand"
  9. "os"
  10. "syscall"
  11. "testing"
  12. "time"
  13. "golang.org/x/sys/windows/registry"
  14. )
  15. func randKeyName(prefix string) string {
  16. const numbers = "0123456789"
  17. buf := make([]byte, 10)
  18. rand.Read(buf)
  19. for i, b := range buf {
  20. buf[i] = numbers[b%byte(len(numbers))]
  21. }
  22. return prefix + string(buf)
  23. }
  24. func TestReadSubKeyNames(t *testing.T) {
  25. k, err := registry.OpenKey(registry.CLASSES_ROOT, "TypeLib", registry.ENUMERATE_SUB_KEYS|registry.QUERY_VALUE)
  26. if err != nil {
  27. t.Fatal(err)
  28. }
  29. defer k.Close()
  30. names, err := k.ReadSubKeyNames(-1)
  31. if err != nil {
  32. t.Fatal(err)
  33. }
  34. var foundStdOle bool
  35. for _, name := range names {
  36. // Every PC has "stdole 2.0 OLE Automation" library installed.
  37. if name == "{00020430-0000-0000-C000-000000000046}" {
  38. foundStdOle = true
  39. }
  40. }
  41. if !foundStdOle {
  42. t.Fatal("could not find stdole 2.0 OLE Automation")
  43. }
  44. }
  45. func TestCreateOpenDeleteKey(t *testing.T) {
  46. k, err := registry.OpenKey(registry.CURRENT_USER, "Software", registry.QUERY_VALUE)
  47. if err != nil {
  48. t.Fatal(err)
  49. }
  50. defer k.Close()
  51. testKName := randKeyName("TestCreateOpenDeleteKey_")
  52. testK, exist, err := registry.CreateKey(k, testKName, registry.CREATE_SUB_KEY)
  53. if err != nil {
  54. t.Fatal(err)
  55. }
  56. defer testK.Close()
  57. if exist {
  58. t.Fatalf("key %q already exists", testKName)
  59. }
  60. testKAgain, exist, err := registry.CreateKey(k, testKName, registry.CREATE_SUB_KEY)
  61. if err != nil {
  62. t.Fatal(err)
  63. }
  64. defer testKAgain.Close()
  65. if !exist {
  66. t.Fatalf("key %q should already exist", testKName)
  67. }
  68. testKOpened, err := registry.OpenKey(k, testKName, registry.ENUMERATE_SUB_KEYS)
  69. if err != nil {
  70. t.Fatal(err)
  71. }
  72. defer testKOpened.Close()
  73. err = registry.DeleteKey(k, testKName)
  74. if err != nil {
  75. t.Fatal(err)
  76. }
  77. testKOpenedAgain, err := registry.OpenKey(k, testKName, registry.ENUMERATE_SUB_KEYS)
  78. if err == nil {
  79. defer testKOpenedAgain.Close()
  80. t.Fatalf("key %q should already been deleted", testKName)
  81. }
  82. if err != registry.ErrNotExist {
  83. t.Fatalf(`unexpected error ("not exist" expected): %v`, err)
  84. }
  85. }
  86. func equalStringSlice(a, b []string) bool {
  87. if len(a) != len(b) {
  88. return false
  89. }
  90. if a == nil {
  91. return true
  92. }
  93. for i := range a {
  94. if a[i] != b[i] {
  95. return false
  96. }
  97. }
  98. return true
  99. }
  100. type ValueTest struct {
  101. Type uint32
  102. Name string
  103. Value interface{}
  104. WillFail bool
  105. }
  106. var ValueTests = []ValueTest{
  107. {Type: registry.SZ, Name: "String1", Value: ""},
  108. {Type: registry.SZ, Name: "String2", Value: "\000", WillFail: true},
  109. {Type: registry.SZ, Name: "String3", Value: "Hello World"},
  110. {Type: registry.SZ, Name: "String4", Value: "Hello World\000", WillFail: true},
  111. {Type: registry.EXPAND_SZ, Name: "ExpString1", Value: ""},
  112. {Type: registry.EXPAND_SZ, Name: "ExpString2", Value: "\000", WillFail: true},
  113. {Type: registry.EXPAND_SZ, Name: "ExpString3", Value: "Hello World"},
  114. {Type: registry.EXPAND_SZ, Name: "ExpString4", Value: "Hello\000World", WillFail: true},
  115. {Type: registry.EXPAND_SZ, Name: "ExpString5", Value: "%PATH%"},
  116. {Type: registry.EXPAND_SZ, Name: "ExpString6", Value: "%NO_SUCH_VARIABLE%"},
  117. {Type: registry.EXPAND_SZ, Name: "ExpString7", Value: "%PATH%;."},
  118. {Type: registry.BINARY, Name: "Binary1", Value: []byte{}},
  119. {Type: registry.BINARY, Name: "Binary2", Value: []byte{1, 2, 3}},
  120. {Type: registry.BINARY, Name: "Binary3", Value: []byte{3, 2, 1, 0, 1, 2, 3}},
  121. {Type: registry.DWORD, Name: "Dword1", Value: uint64(0)},
  122. {Type: registry.DWORD, Name: "Dword2", Value: uint64(1)},
  123. {Type: registry.DWORD, Name: "Dword3", Value: uint64(0xff)},
  124. {Type: registry.DWORD, Name: "Dword4", Value: uint64(0xffff)},
  125. {Type: registry.QWORD, Name: "Qword1", Value: uint64(0)},
  126. {Type: registry.QWORD, Name: "Qword2", Value: uint64(1)},
  127. {Type: registry.QWORD, Name: "Qword3", Value: uint64(0xff)},
  128. {Type: registry.QWORD, Name: "Qword4", Value: uint64(0xffff)},
  129. {Type: registry.QWORD, Name: "Qword5", Value: uint64(0xffffff)},
  130. {Type: registry.QWORD, Name: "Qword6", Value: uint64(0xffffffff)},
  131. {Type: registry.MULTI_SZ, Name: "MultiString1", Value: []string{"a", "b", "c"}},
  132. {Type: registry.MULTI_SZ, Name: "MultiString2", Value: []string{"abc", "", "cba"}},
  133. {Type: registry.MULTI_SZ, Name: "MultiString3", Value: []string{""}},
  134. {Type: registry.MULTI_SZ, Name: "MultiString4", Value: []string{"abcdef"}},
  135. {Type: registry.MULTI_SZ, Name: "MultiString5", Value: []string{"\000"}, WillFail: true},
  136. {Type: registry.MULTI_SZ, Name: "MultiString6", Value: []string{"a\000b"}, WillFail: true},
  137. {Type: registry.MULTI_SZ, Name: "MultiString7", Value: []string{"ab", "\000", "cd"}, WillFail: true},
  138. {Type: registry.MULTI_SZ, Name: "MultiString8", Value: []string{"\000", "cd"}, WillFail: true},
  139. {Type: registry.MULTI_SZ, Name: "MultiString9", Value: []string{"ab", "\000"}, WillFail: true},
  140. }
  141. func setValues(t *testing.T, k registry.Key) {
  142. for _, test := range ValueTests {
  143. var err error
  144. switch test.Type {
  145. case registry.SZ:
  146. err = k.SetStringValue(test.Name, test.Value.(string))
  147. case registry.EXPAND_SZ:
  148. err = k.SetExpandStringValue(test.Name, test.Value.(string))
  149. case registry.MULTI_SZ:
  150. err = k.SetStringsValue(test.Name, test.Value.([]string))
  151. case registry.BINARY:
  152. err = k.SetBinaryValue(test.Name, test.Value.([]byte))
  153. case registry.DWORD:
  154. err = k.SetDWordValue(test.Name, uint32(test.Value.(uint64)))
  155. case registry.QWORD:
  156. err = k.SetQWordValue(test.Name, test.Value.(uint64))
  157. default:
  158. t.Fatalf("unsupported type %d for %s value", test.Type, test.Name)
  159. }
  160. if test.WillFail {
  161. if err == nil {
  162. t.Fatalf("setting %s value %q should fail, but succeeded", test.Name, test.Value)
  163. }
  164. } else {
  165. if err != nil {
  166. t.Fatal(err)
  167. }
  168. }
  169. }
  170. }
  171. func enumerateValues(t *testing.T, k registry.Key) {
  172. names, err := k.ReadValueNames(-1)
  173. if err != nil {
  174. t.Error(err)
  175. return
  176. }
  177. haveNames := make(map[string]bool)
  178. for _, n := range names {
  179. haveNames[n] = false
  180. }
  181. for _, test := range ValueTests {
  182. wantFound := !test.WillFail
  183. _, haveFound := haveNames[test.Name]
  184. if wantFound && !haveFound {
  185. t.Errorf("value %s is not found while enumerating", test.Name)
  186. }
  187. if haveFound && !wantFound {
  188. t.Errorf("value %s is found while enumerating, but expected to fail", test.Name)
  189. }
  190. if haveFound {
  191. delete(haveNames, test.Name)
  192. }
  193. }
  194. for n, v := range haveNames {
  195. t.Errorf("value %s (%v) is found while enumerating, but has not been cretaed", n, v)
  196. }
  197. }
  198. func testErrNotExist(t *testing.T, name string, err error) {
  199. if err == nil {
  200. t.Errorf("%s value should not exist", name)
  201. return
  202. }
  203. if err != registry.ErrNotExist {
  204. t.Errorf("reading %s value should return 'not exist' error, but got: %s", name, err)
  205. return
  206. }
  207. }
  208. func testErrUnexpectedType(t *testing.T, test ValueTest, gottype uint32, err error) {
  209. if err == nil {
  210. t.Errorf("GetXValue(%q) should not succeed", test.Name)
  211. return
  212. }
  213. if err != registry.ErrUnexpectedType {
  214. t.Errorf("reading %s value should return 'unexpected key value type' error, but got: %s", test.Name, err)
  215. return
  216. }
  217. if gottype != test.Type {
  218. t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype)
  219. return
  220. }
  221. }
  222. func testGetStringValue(t *testing.T, k registry.Key, test ValueTest) {
  223. got, gottype, err := k.GetStringValue(test.Name)
  224. if err != nil {
  225. t.Errorf("GetStringValue(%s) failed: %v", test.Name, err)
  226. return
  227. }
  228. if got != test.Value {
  229. t.Errorf("want %s value %q, got %q", test.Name, test.Value, got)
  230. return
  231. }
  232. if gottype != test.Type {
  233. t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype)
  234. return
  235. }
  236. if gottype == registry.EXPAND_SZ {
  237. _, err = registry.ExpandString(got)
  238. if err != nil {
  239. t.Errorf("ExpandString(%s) failed: %v", got, err)
  240. return
  241. }
  242. }
  243. }
  244. func testGetIntegerValue(t *testing.T, k registry.Key, test ValueTest) {
  245. got, gottype, err := k.GetIntegerValue(test.Name)
  246. if err != nil {
  247. t.Errorf("GetIntegerValue(%s) failed: %v", test.Name, err)
  248. return
  249. }
  250. if got != test.Value.(uint64) {
  251. t.Errorf("want %s value %v, got %v", test.Name, test.Value, got)
  252. return
  253. }
  254. if gottype != test.Type {
  255. t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype)
  256. return
  257. }
  258. }
  259. func testGetBinaryValue(t *testing.T, k registry.Key, test ValueTest) {
  260. got, gottype, err := k.GetBinaryValue(test.Name)
  261. if err != nil {
  262. t.Errorf("GetBinaryValue(%s) failed: %v", test.Name, err)
  263. return
  264. }
  265. if !bytes.Equal(got, test.Value.([]byte)) {
  266. t.Errorf("want %s value %v, got %v", test.Name, test.Value, got)
  267. return
  268. }
  269. if gottype != test.Type {
  270. t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype)
  271. return
  272. }
  273. }
  274. func testGetStringsValue(t *testing.T, k registry.Key, test ValueTest) {
  275. got, gottype, err := k.GetStringsValue(test.Name)
  276. if err != nil {
  277. t.Errorf("GetStringsValue(%s) failed: %v", test.Name, err)
  278. return
  279. }
  280. if !equalStringSlice(got, test.Value.([]string)) {
  281. t.Errorf("want %s value %#v, got %#v", test.Name, test.Value, got)
  282. return
  283. }
  284. if gottype != test.Type {
  285. t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype)
  286. return
  287. }
  288. }
  289. func testGetValue(t *testing.T, k registry.Key, test ValueTest, size int) {
  290. if size <= 0 {
  291. return
  292. }
  293. // read data with no buffer
  294. gotsize, gottype, err := k.GetValue(test.Name, nil)
  295. if err != nil {
  296. t.Errorf("GetValue(%s, [%d]byte) failed: %v", test.Name, size, err)
  297. return
  298. }
  299. if gotsize != size {
  300. t.Errorf("want %s value size of %d, got %v", test.Name, size, gotsize)
  301. return
  302. }
  303. if gottype != test.Type {
  304. t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype)
  305. return
  306. }
  307. // read data with short buffer
  308. gotsize, gottype, err = k.GetValue(test.Name, make([]byte, size-1))
  309. if err == nil {
  310. t.Errorf("GetValue(%s, [%d]byte) should fail, but suceeded", test.Name, size-1)
  311. return
  312. }
  313. if err != registry.ErrShortBuffer {
  314. t.Errorf("reading %s value should return 'short buffer' error, but got: %s", test.Name, err)
  315. return
  316. }
  317. if gotsize != size {
  318. t.Errorf("want %s value size of %d, got %v", test.Name, size, gotsize)
  319. return
  320. }
  321. if gottype != test.Type {
  322. t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype)
  323. return
  324. }
  325. // read full data
  326. gotsize, gottype, err = k.GetValue(test.Name, make([]byte, size))
  327. if err != nil {
  328. t.Errorf("GetValue(%s, [%d]byte) failed: %v", test.Name, size, err)
  329. return
  330. }
  331. if gotsize != size {
  332. t.Errorf("want %s value size of %d, got %v", test.Name, size, gotsize)
  333. return
  334. }
  335. if gottype != test.Type {
  336. t.Errorf("want %s value type %v, got %v", test.Name, test.Type, gottype)
  337. return
  338. }
  339. // check GetValue returns ErrNotExist as required
  340. _, _, err = k.GetValue(test.Name+"_not_there", make([]byte, size))
  341. if err == nil {
  342. t.Errorf("GetValue(%q) should not succeed", test.Name)
  343. return
  344. }
  345. if err != registry.ErrNotExist {
  346. t.Errorf("GetValue(%q) should return 'not exist' error, but got: %s", test.Name, err)
  347. return
  348. }
  349. }
  350. func testValues(t *testing.T, k registry.Key) {
  351. for _, test := range ValueTests {
  352. switch test.Type {
  353. case registry.SZ, registry.EXPAND_SZ:
  354. if test.WillFail {
  355. _, _, err := k.GetStringValue(test.Name)
  356. testErrNotExist(t, test.Name, err)
  357. } else {
  358. testGetStringValue(t, k, test)
  359. _, gottype, err := k.GetIntegerValue(test.Name)
  360. testErrUnexpectedType(t, test, gottype, err)
  361. // Size of utf16 string in bytes is not perfect,
  362. // but correct for current test values.
  363. // Size also includes terminating 0.
  364. testGetValue(t, k, test, (len(test.Value.(string))+1)*2)
  365. }
  366. _, _, err := k.GetStringValue(test.Name + "_string_not_created")
  367. testErrNotExist(t, test.Name+"_string_not_created", err)
  368. case registry.DWORD, registry.QWORD:
  369. testGetIntegerValue(t, k, test)
  370. _, gottype, err := k.GetBinaryValue(test.Name)
  371. testErrUnexpectedType(t, test, gottype, err)
  372. _, _, err = k.GetIntegerValue(test.Name + "_int_not_created")
  373. testErrNotExist(t, test.Name+"_int_not_created", err)
  374. size := 8
  375. if test.Type == registry.DWORD {
  376. size = 4
  377. }
  378. testGetValue(t, k, test, size)
  379. case registry.BINARY:
  380. testGetBinaryValue(t, k, test)
  381. _, gottype, err := k.GetStringsValue(test.Name)
  382. testErrUnexpectedType(t, test, gottype, err)
  383. _, _, err = k.GetBinaryValue(test.Name + "_byte_not_created")
  384. testErrNotExist(t, test.Name+"_byte_not_created", err)
  385. testGetValue(t, k, test, len(test.Value.([]byte)))
  386. case registry.MULTI_SZ:
  387. if test.WillFail {
  388. _, _, err := k.GetStringsValue(test.Name)
  389. testErrNotExist(t, test.Name, err)
  390. } else {
  391. testGetStringsValue(t, k, test)
  392. _, gottype, err := k.GetStringValue(test.Name)
  393. testErrUnexpectedType(t, test, gottype, err)
  394. size := 0
  395. for _, s := range test.Value.([]string) {
  396. size += len(s) + 1 // nil terminated
  397. }
  398. size += 1 // extra nil at the end
  399. size *= 2 // count bytes, not uint16
  400. testGetValue(t, k, test, size)
  401. }
  402. _, _, err := k.GetStringsValue(test.Name + "_strings_not_created")
  403. testErrNotExist(t, test.Name+"_strings_not_created", err)
  404. default:
  405. t.Errorf("unsupported type %d for %s value", test.Type, test.Name)
  406. continue
  407. }
  408. }
  409. }
  410. func testStat(t *testing.T, k registry.Key) {
  411. subk, _, err := registry.CreateKey(k, "subkey", registry.CREATE_SUB_KEY)
  412. if err != nil {
  413. t.Error(err)
  414. return
  415. }
  416. defer subk.Close()
  417. defer registry.DeleteKey(k, "subkey")
  418. ki, err := k.Stat()
  419. if err != nil {
  420. t.Error(err)
  421. return
  422. }
  423. if ki.SubKeyCount != 1 {
  424. t.Error("key must have 1 subkey")
  425. }
  426. if ki.MaxSubKeyLen != 6 {
  427. t.Error("key max subkey name length must be 6")
  428. }
  429. if ki.ValueCount != 24 {
  430. t.Errorf("key must have 24 values, but is %d", ki.ValueCount)
  431. }
  432. if ki.MaxValueNameLen != 12 {
  433. t.Errorf("key max value name length must be 10, but is %d", ki.MaxValueNameLen)
  434. }
  435. if ki.MaxValueLen != 38 {
  436. t.Errorf("key max value length must be 38, but is %d", ki.MaxValueLen)
  437. }
  438. if mt, ct := ki.ModTime(), time.Now(); ct.Sub(mt) > 100*time.Millisecond {
  439. t.Errorf("key mod time is not close to current time: mtime=%v current=%v delta=%v", mt, ct, ct.Sub(mt))
  440. }
  441. }
  442. func deleteValues(t *testing.T, k registry.Key) {
  443. for _, test := range ValueTests {
  444. if test.WillFail {
  445. continue
  446. }
  447. err := k.DeleteValue(test.Name)
  448. if err != nil {
  449. t.Error(err)
  450. continue
  451. }
  452. }
  453. names, err := k.ReadValueNames(-1)
  454. if err != nil {
  455. t.Error(err)
  456. return
  457. }
  458. if len(names) != 0 {
  459. t.Errorf("some values remain after deletion: %v", names)
  460. }
  461. }
  462. func TestValues(t *testing.T) {
  463. softwareK, err := registry.OpenKey(registry.CURRENT_USER, "Software", registry.QUERY_VALUE)
  464. if err != nil {
  465. t.Fatal(err)
  466. }
  467. defer softwareK.Close()
  468. testKName := randKeyName("TestValues_")
  469. k, exist, err := registry.CreateKey(softwareK, testKName, registry.CREATE_SUB_KEY|registry.QUERY_VALUE|registry.SET_VALUE)
  470. if err != nil {
  471. t.Fatal(err)
  472. }
  473. defer k.Close()
  474. if exist {
  475. t.Fatalf("key %q already exists", testKName)
  476. }
  477. defer registry.DeleteKey(softwareK, testKName)
  478. setValues(t, k)
  479. enumerateValues(t, k)
  480. testValues(t, k)
  481. testStat(t, k)
  482. deleteValues(t, k)
  483. }
  484. func walkKey(t *testing.T, k registry.Key, kname string) {
  485. names, err := k.ReadValueNames(-1)
  486. if err != nil {
  487. t.Fatalf("reading value names of %s failed: %v", kname, err)
  488. }
  489. for _, name := range names {
  490. _, valtype, err := k.GetValue(name, nil)
  491. if err != nil {
  492. t.Fatalf("reading value type of %s of %s failed: %v", name, kname, err)
  493. }
  494. switch valtype {
  495. case registry.NONE:
  496. case registry.SZ:
  497. _, _, err := k.GetStringValue(name)
  498. if err != nil {
  499. t.Error(err)
  500. }
  501. case registry.EXPAND_SZ:
  502. s, _, err := k.GetStringValue(name)
  503. if err != nil {
  504. t.Error(err)
  505. }
  506. _, err = registry.ExpandString(s)
  507. if err != nil {
  508. t.Error(err)
  509. }
  510. case registry.DWORD, registry.QWORD:
  511. _, _, err := k.GetIntegerValue(name)
  512. if err != nil {
  513. t.Error(err)
  514. }
  515. case registry.BINARY:
  516. _, _, err := k.GetBinaryValue(name)
  517. if err != nil {
  518. t.Error(err)
  519. }
  520. case registry.MULTI_SZ:
  521. _, _, err := k.GetStringsValue(name)
  522. if err != nil {
  523. t.Error(err)
  524. }
  525. case registry.FULL_RESOURCE_DESCRIPTOR, registry.RESOURCE_LIST, registry.RESOURCE_REQUIREMENTS_LIST:
  526. // TODO: not implemented
  527. default:
  528. t.Fatalf("value type %d of %s of %s failed: %v", valtype, name, kname, err)
  529. }
  530. }
  531. names, err = k.ReadSubKeyNames(-1)
  532. if err != nil {
  533. t.Fatalf("reading sub-keys of %s failed: %v", kname, err)
  534. }
  535. for _, name := range names {
  536. func() {
  537. subk, err := registry.OpenKey(k, name, registry.ENUMERATE_SUB_KEYS|registry.QUERY_VALUE)
  538. if err != nil {
  539. if err == syscall.ERROR_ACCESS_DENIED {
  540. // ignore error, if we are not allowed to access this key
  541. return
  542. }
  543. t.Fatalf("opening sub-keys %s of %s failed: %v", name, kname, err)
  544. }
  545. defer subk.Close()
  546. walkKey(t, subk, kname+`\`+name)
  547. }()
  548. }
  549. }
  550. func TestWalkFullRegistry(t *testing.T) {
  551. if testing.Short() {
  552. t.Skip("skipping long running test in short mode")
  553. }
  554. walkKey(t, registry.CLASSES_ROOT, "CLASSES_ROOT")
  555. walkKey(t, registry.CURRENT_USER, "CURRENT_USER")
  556. walkKey(t, registry.LOCAL_MACHINE, "LOCAL_MACHINE")
  557. walkKey(t, registry.USERS, "USERS")
  558. walkKey(t, registry.CURRENT_CONFIG, "CURRENT_CONFIG")
  559. }
  560. func TestExpandString(t *testing.T) {
  561. got, err := registry.ExpandString("%PATH%")
  562. if err != nil {
  563. t.Fatal(err)
  564. }
  565. want := os.Getenv("PATH")
  566. if got != want {
  567. t.Errorf("want %q string expanded, got %q", want, got)
  568. }
  569. }