Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit f623828

Browse files
committed
Add tests for SharedDictionaryManager
1 parent 72734da commit f623828

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-0
lines changed

test/GitHub.UI.UnitTests/GitHub.UI.UnitTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
<Reference Include="WindowsBase" />
4949
</ItemGroup>
5050
<ItemGroup>
51+
<Compile Include="SharedDictionaryManagerTests.cs" />
5152
<Compile Include="LoadingResourceDictionaryTests.cs" />
5253
<Compile Include="Properties\AssemblyInfo.cs" />
5354
</ItemGroup>
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
using System;
2+
using System.IO;
3+
using System.Windows;
4+
using NUnit.Framework;
5+
using GitHub.UI.Helpers;
6+
7+
namespace GitHub.UI.Tests
8+
{
9+
public class SharedDictionaryManagerTests
10+
{
11+
public class TheSourceProperty
12+
{
13+
[TestCase("pack://application:,,,/GitHub.UI;component/SharedDictionary.xaml")]
14+
[TestCase("pack://application:,,,/GitHub.VisualStudio.UI;component/SharedDictionary.xaml")]
15+
[RequiresThread(System.Threading.ApartmentState.STA)]
16+
public void SetSourceOnDifferentInstances_ExpectTheSameObjects(params string[] urls)
17+
{
18+
var setup = new AppDomainSetup { ApplicationBase = "NOTHING_HERE" };
19+
using (var context = new AppDomainContext(setup))
20+
{
21+
var remote = context.CreateInstance<SharedDictionaryManagerContext>();
22+
string expectDump = remote.DumpMergedDictionariesSharedDictionaryManager(urls);
23+
24+
var dump = remote.DumpMergedDictionariesSharedDictionaryManager(urls);
25+
26+
Assert.That(dump, Is.EqualTo(expectDump));
27+
}
28+
}
29+
30+
// This is why we need `SharedDictionaryManager`.
31+
[TestCase("pack://application:,,,/GitHub.UI;component/SharedDictionary.xaml")]
32+
[TestCase("pack://application:,,,/GitHub.VisualStudio.UI;component/SharedDictionary.xaml")]
33+
[RequiresThread(System.Threading.ApartmentState.STA)]
34+
public void SetResourceDictionarySourceOnDifferentInstances_ExpectDifferentObjects(params string[] urls)
35+
{
36+
var setup = new AppDomainSetup { ApplicationBase = "NOTHING_HERE" };
37+
using (var context = new AppDomainContext(setup))
38+
{
39+
var remote = context.CreateInstance<SharedDictionaryManagerContext>();
40+
string expectDump = remote.DumpMergedDictionariesLoadingResourceDictionary(urls);
41+
42+
var dump = remote.DumpMergedDictionariesLoadingResourceDictionary(urls);
43+
44+
Assert.That(dump, Is.Not.EqualTo(expectDump));
45+
}
46+
}
47+
48+
class SharedDictionaryManagerContext : MarshalByRefObject
49+
{
50+
internal string DumpMergedDictionariesLoadingResourceDictionary(params string[] urls)
51+
{
52+
var target = new LoadingResourceDictionary();
53+
return DumpMergedDictionaries(target, urls);
54+
}
55+
56+
internal string DumpMergedDictionariesSharedDictionaryManager(params string[] urls)
57+
{
58+
var target = new SharedDictionaryManager();
59+
return DumpMergedDictionaries(target, urls);
60+
}
61+
62+
string DumpMergedDictionaries(ResourceDictionary target, params string[] urls)
63+
{
64+
foreach(var url in urls)
65+
{
66+
SetProperty(target, "Source", ToPackUri(url));
67+
}
68+
69+
return DumpResourceDictionary(target);
70+
}
71+
72+
static void SetProperty(object target, string name, object value)
73+
{
74+
var prop = target.GetType().GetProperty(name);
75+
prop.SetValue(target, value);
76+
}
77+
}
78+
}
79+
80+
public class TheResourceDictionarySourceProperty
81+
{
82+
[Description("This shows why LoadingResourceDictionary is necessary")]
83+
[TestCase("pack://application:,,,/GitHub.UI;component/SharedDictionary.xaml")]
84+
[TestCase("pack://application:,,,/GitHub.VisualStudio.UI;component/SharedDictionary.xaml")]
85+
public void SetInLoadFromContext(string url)
86+
{
87+
var setup = new AppDomainSetup { ApplicationBase = "NOTHING_HERE" };
88+
using (var context = new AppDomainContext(setup))
89+
{
90+
var remote = context.CreateInstance<ResourceDictionaryContext>();
91+
92+
Assert.Throws<FileNotFoundException>(() => remote.CountMergedDictionaries(url));
93+
}
94+
}
95+
96+
class ResourceDictionaryContext : MarshalByRefObject
97+
{
98+
internal int CountMergedDictionaries(string url)
99+
{
100+
var target = new ResourceDictionary();
101+
var packUri = ToPackUri(url);
102+
103+
target.Source = packUri;
104+
105+
return target.MergedDictionaries.Count;
106+
}
107+
}
108+
}
109+
110+
static Uri ToPackUri(string url)
111+
{
112+
if (!UriParser.IsKnownScheme("pack"))
113+
{
114+
// Register the pack scheme.
115+
new Application();
116+
}
117+
118+
return new Uri(url);
119+
}
120+
121+
class AppDomainContext : IDisposable
122+
{
123+
AppDomain domain;
124+
125+
public AppDomainContext(AppDomainSetup setup)
126+
{
127+
var friendlyName = GetType().FullName;
128+
domain = AppDomain.CreateDomain(friendlyName, null, setup);
129+
}
130+
131+
public T CreateInstance<T>()
132+
{
133+
return (T)domain.CreateInstanceFromAndUnwrap(typeof(T).Assembly.CodeBase, typeof(T).FullName);
134+
}
135+
136+
public void Dispose()
137+
{
138+
AppDomain.Unload(domain);
139+
}
140+
}
141+
142+
static string DumpResourceDictionary(ResourceDictionary rd, string indent = "")
143+
{
144+
var writer = new StringWriter();
145+
DumpResourceDictionary(writer, rd);
146+
return writer.ToString();
147+
}
148+
149+
static void DumpResourceDictionary(TextWriter writer, ResourceDictionary rd, string indent = "")
150+
{
151+
var source = rd.Source;
152+
if(source != null)
153+
{
154+
writer.WriteLine(indent + source + " (" + rd.GetType().FullName + ") # " + rd.GetHashCode());
155+
foreach (var child in rd.MergedDictionaries)
156+
{
157+
DumpResourceDictionary(writer, child, indent + " ");
158+
}
159+
}
160+
else
161+
{
162+
// ignore our empty nodes
163+
foreach (var child in rd.MergedDictionaries)
164+
{
165+
DumpResourceDictionary(writer, child, indent);
166+
}
167+
}
168+
}
169+
}
170+
}

0 commit comments

Comments
 (0)