github.com/huandu/go@v0.0.0-20151114150818-04e615e41150/src/internal/syscall/windows/registry/registry_test.go (about)

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