1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using Xunit;
namespace Microsoft.Win32.RegistryTests
{
public abstract class RegistryTestsBase : IDisposable
{
protected string TestRegistryKeyName { get; private set; }
protected RegistryKey TestRegistryKey { get; private set; }
protected RegistryTestsBase()
{
// Create a unique name for this test class
TestRegistryKeyName = CreateUniqueKeyName();
// Cleanup the key in case a previous run of this test crashed and left
// the key behind. The key name is specific enough to corefx that we don't
// need to worry about it being a real key on the user's system used
// for another purpose.
RemoveKeyIfExists(TestRegistryKeyName);
// Then create the key.
TestRegistryKey = Registry.CurrentUser.CreateSubKey(TestRegistryKeyName);
Assert.NotNull(TestRegistryKey);
}
public void Dispose()
{
TestRegistryKey.Dispose();
RemoveKeyIfExists(TestRegistryKeyName);
}
private static void RemoveKeyIfExists(string keyName)
{
RegistryKey rk = Registry.CurrentUser;
if (rk.OpenSubKey(keyName) != null)
{
rk.DeleteSubKeyTree(keyName);
Assert.Null(rk.OpenSubKey(keyName));
}
}
private string CreateUniqueKeyName()
{
// Create a name to use for this class of tests. The name includes:
// - A "corefxtest" prefix to help make it clear to anyone looking at the registry
// that these keys are test-only and can be deleted, in case the tests crash and
// we end up leaving some keys behind.
// - The name of this test class, so as to avoid problems with tests on different test
// classes running concurrently
return "corefxtest_" + GetType().Name;
}
public static readonly object[][] TestRegistrySubKeyNames =
{
new object[] { @"Foo", @"Foo" },
new object[] { @"Foo\Bar", @"Foo\Bar" },
// Multiple/trailing slashes should be removed.
new object[] { @"Foo", @"Foo\" },
new object[] { @"Foo", @"Foo\\" },
new object[] { @"Foo", @"Foo\\\" },
new object[] { @"Foo", @"Foo\\\\" },
new object[] { @"Foo\Bar", @"Foo\\Bar" },
new object[] { @"Foo\Bar", @"Foo\\\Bar" },
new object[] { @"Foo\Bar", @"Foo\\\\Bar" },
new object[] { @"Foo\Bar", @"Foo\Bar\" },
new object[] { @"Foo\Bar", @"Foo\Bar\\" },
new object[] { @"Foo\Bar", @"Foo\Bar\\\" },
new object[] { @"Foo\Bar", @"Foo\\Bar\" },
new object[] { @"Foo\Bar", @"Foo\\Bar\\" },
new object[] { @"Foo\Bar", @"Foo\\Bar\\\" },
new object[] { @"Foo\Bar", @"Foo\\\Bar\\\" },
new object[] { @"Foo\Bar", @"Foo\\\\Bar\\\\" },
// The name fix-up implementation uses a mark-and-sweep approach.
// If there are multiple slashes, any extra slash chars will be
// replaced with a marker char ('\uffff'), and then all '\uffff'
// chars will be removed, including any pre-existing '\uffff' chars.
InsertMarkerChar(@"Foo", @"{0}Foo\\"),
InsertMarkerChar(@"Foo", @"Foo{0}\\"),
InsertMarkerChar(@"Foo", @"Foo\\{0}"),
InsertMarkerChar(@"Foo", @"Fo{0}o\\"),
InsertMarkerChar(@"Foo", @"{0}Fo{0}o{0}\\{0}"),
InsertMarkerChar(@"Foo", @"{0}Foo\\\"),
InsertMarkerChar(@"Foo", @"Foo{0}\\\"),
InsertMarkerChar(@"Foo", @"Foo\\\{0}"),
InsertMarkerChar(@"Foo", @"Fo{0}o\\\"),
InsertMarkerChar(@"Foo", @"{0}Fo{0}o{0}\\\{0}"),
InsertMarkerChar(@"Foo\Bar", @"{0}Foo\\Bar"),
InsertMarkerChar(@"Foo\Bar", @"Foo{0}\\Bar"),
InsertMarkerChar(@"Foo\Bar", @"Foo\\{0}Bar"),
InsertMarkerChar(@"Foo\Bar", @"Foo\\Bar{0}"),
InsertMarkerChar(@"Foo\Bar", @"Fo{0}o\\Bar"),
InsertMarkerChar(@"Foo\Bar", @"Foo\\B{0}ar"),
InsertMarkerChar(@"Foo\Bar", @"Fo{0}o\\B{0}ar"),
InsertMarkerChar(@"Foo\Bar", @"{0}Fo{0}o{0}\\{0}B{0}ar{0}"),
InsertMarkerChar(@"Foo\Bar", @"{0}Foo\\\Bar"),
InsertMarkerChar(@"Foo\Bar", @"Foo{0}\\\Bar"),
InsertMarkerChar(@"Foo\Bar", @"Foo\\\{0}Bar"),
InsertMarkerChar(@"Foo\Bar", @"Foo\\\Bar{0}"),
InsertMarkerChar(@"Foo\Bar", @"Fo{0}o\\\Bar"),
InsertMarkerChar(@"Foo\Bar", @"Foo\\\B{0}ar"),
InsertMarkerChar(@"Foo\Bar", @"Fo{0}o\\\B{0}ar"),
InsertMarkerChar(@"Foo\Bar", @"{0}Fo{0}o{0}\\\{0}B{0}ar{0}"),
InsertMarkerChar(@"Foo\Bar", @"{0}Foo\Bar\\"),
InsertMarkerChar(@"Foo\Bar", @"Foo{0}\Bar\\"),
InsertMarkerChar(@"Foo\Bar", @"Foo\{0}Bar\\"),
InsertMarkerChar(@"Foo\Bar", @"Foo\Bar{0}\\"),
InsertMarkerChar(@"Foo\Bar", @"Foo\Bar\\{0}"),
InsertMarkerChar(@"Foo\Bar", @"Fo{0}o\B{0}ar\\"),
InsertMarkerChar(@"Foo\Bar", @"{0}Fo{0}o{0}\{0}B{0}ar{0}\\{0}"),
// If there aren't multiple slashes, any '\uffff' chars should remain.
InsertMarkerChar(@"{0}Foo"),
InsertMarkerChar(@"Foo{0}"),
InsertMarkerChar(@"Fo{0}o"),
InsertMarkerChar(@"{0}Fo{0}o{0}"),
InsertMarkerChar(@"{0}Foo\"),
InsertMarkerChar(@"Foo{0}\"),
InsertMarkerChar(@"Fo{0}o\"),
InsertMarkerChar(@"{0}Fo{0}o{0}\"),
InsertMarkerChar(@"{0}Foo\Bar"),
InsertMarkerChar(@"Foo{0}\Bar"),
InsertMarkerChar(@"Foo\{0}Bar"),
InsertMarkerChar(@"Foo\Bar{0}"),
InsertMarkerChar(@"Fo{0}o\Bar"),
InsertMarkerChar(@"Foo\B{0}ar"),
InsertMarkerChar(@"Fo{0}o\B{0}ar"),
InsertMarkerChar(@"{0}Fo{0}o{0}\{0}B{0}ar{0}"),
InsertMarkerChar(@"{0}Foo\Bar\"),
InsertMarkerChar(@"Foo{0}\Bar\"),
InsertMarkerChar(@"Foo\{0}Bar\"),
InsertMarkerChar(@"Foo\Bar{0}\"),
InsertMarkerChar(@"Fo{0}o\Bar\"),
InsertMarkerChar(@"Foo\B{0}ar\"),
InsertMarkerChar(@"Fo{0}o\B{0}ar\"),
InsertMarkerChar(@"{0}Fo{0}o{0}\{0}B{0}ar{0}\"),
};
private const char MarkerChar = '\uffff';
private static object[] InsertMarkerChar(string expected, string format)
{
string result = string.Format(format, MarkerChar);
return new object[] { expected, result };
}
private static object[] InsertMarkerChar(string format)
{
string result = string.Format(format, MarkerChar);
string expected = result.TrimEnd('\\');
return new object[] { expected, result };
}
protected void CreateTestRegistrySubKey(string expected)
{
Assert.Equal(0, TestRegistryKey.SubKeyCount);
using (RegistryKey key = TestRegistryKey.CreateSubKey(expected))
{
Assert.NotNull(key);
Assert.Equal(1, TestRegistryKey.SubKeyCount);
Assert.Equal(TestRegistryKey.Name + @"\" + expected, key.Name);
}
}
}
}
|