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

Commit 5ad4d53

Browse files
authored
Merge branch 'master' into grokys/maintainer-workflow
2 parents 4711503 + 6f99a4c commit 5ad4d53

File tree

7 files changed

+211
-38
lines changed

7 files changed

+211
-38
lines changed

src/GitHub.App/Models/Account.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ namespace GitHub.Models
1414
public class Account : ReactiveObject, IAccount
1515
{
1616
BitmapSource avatar;
17+
IObservable<BitmapSource> bitmapSource;
18+
IDisposable bitmapSourceSubscription;
1719

1820
public Account(
1921
string login,
@@ -30,8 +32,10 @@ public Account(
3032
PrivateReposInPlan = privateRepositoryInPlanCount;
3133
IsOnFreePlan = privateRepositoryInPlanCount == 0;
3234
HasMaximumPrivateRepositories = OwnedPrivateRepos >= PrivateReposInPlan;
35+
this.bitmapSource = bitmapSource;
3336

34-
bitmapSource.ObserveOn(RxApp.MainThreadScheduler)
37+
bitmapSourceSubscription = bitmapSource
38+
.ObserveOn(RxApp.MainThreadScheduler)
3539
.Subscribe(x => Avatar = x);
3640
}
3741

@@ -87,6 +91,16 @@ public void CopyFrom(IAccount other)
8791
IsOnFreePlan = other.IsOnFreePlan;
8892
HasMaximumPrivateRepositories = other.HasMaximumPrivateRepositories;
8993
Avatar = other.Avatar;
94+
95+
var otherAccount = other as Account;
96+
if (otherAccount != null)
97+
{
98+
bitmapSourceSubscription.Dispose();
99+
100+
bitmapSourceSubscription = otherAccount.bitmapSource
101+
.ObserveOn(RxApp.MainThreadScheduler)
102+
.Subscribe(x => Avatar = x);
103+
}
90104
}
91105

92106
public override bool Equals([AllowNull]object obj)

src/GitHub.Exports/Primitives/HostAddress.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,16 @@ public static bool IsGitHubDotComUri(Uri hostUri)
7878
|| hostUri.IsSameHost(gistUri);
7979
}
8080

81+
public static bool operator ==(HostAddress a, HostAddress b)
82+
{
83+
return object.ReferenceEquals(a, null) ? object.ReferenceEquals(b, null) : a.Equals(b);
84+
}
85+
86+
public static bool operator !=(HostAddress a, HostAddress b)
87+
{
88+
return !(a == b);
89+
}
90+
8191
public bool IsGitHubDotCom()
8292
{
8393
return IsGitHubDotComUri(ApiUri);

src/TrackingCollectionTests/TrackingCollectionTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ public void OrderByDoesntMatchOriginalOrderTimings()
378378
var total = 1000;
379379

380380
var list1 = new List<Thing>(Enumerable.Range(1, total).Select(i => GetThing(i, i, i, "Run 1")).ToList());
381-
var list2 = new List<Thing>(Enumerable.Range(1, total).Select(i => GetThing(i, i, i, "Run 2")).ToList());
381+
var list2 = new List<Thing>(Enumerable.Range(1, total).Select(i => GetThing(i, i, i + 1, "Run 2")).ToList());
382382

383383
ITrackingCollection<Thing> col = new TrackingCollection<Thing>(
384384
list1.ToObservable(),
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
using System;
2+
using System.IO;
3+
using System.Linq;
4+
using System.Reactive.Linq;
5+
using System.Reactive.Subjects;
6+
using System.Threading;
7+
using System.Windows.Media.Imaging;
8+
using GitHub.Collections;
9+
using GitHub.Models;
10+
using GitHub.Services;
11+
using ReactiveUI;
12+
using Xunit;
13+
14+
namespace UnitTests.GitHub.App.Models
15+
{
16+
public class AccountModelTests : TestBaseClass
17+
{
18+
[Fact]
19+
public void CopyFromDoesNotLoseAvatar()
20+
{
21+
var userImage = AvatarProvider.CreateBitmapImage("pack://application:,,,/GitHub.App;component/Images/default_user_avatar.png");
22+
var orgImage = AvatarProvider.CreateBitmapImage("pack://application:,,,/GitHub.App;component/Images/default_org_avatar.png");
23+
24+
var initialBitmapImageSubject = new Subject<BitmapImage>();
25+
26+
var collectionEvent = new ManualResetEvent(false);
27+
var avatarPropertyEvent = new ManualResetEvent(false);
28+
29+
//Creating an initial account with an observable that returns immediately
30+
const string login = "foo";
31+
const int initialOwnedPrivateRepositoryCount = 1;
32+
33+
var initialAccount = new Account(login, true, false, initialOwnedPrivateRepositoryCount, 0, initialBitmapImageSubject);
34+
35+
//Creating the test collection
36+
var col = new TrackingCollection<IAccount>(Observable.Empty<IAccount>(), OrderedComparer<IAccount>.OrderByDescending(x => x.Login).Compare);
37+
col.Subscribe(account =>
38+
{
39+
collectionEvent.Set();
40+
}, () => { });
41+
42+
//Adding that account to the TrackingCollection
43+
col.AddItem(initialAccount);
44+
45+
//Waiting for the collection add the item
46+
collectionEvent.WaitOne();
47+
collectionEvent.Reset();
48+
49+
//Checking some initial properties
50+
Assert.Equal(login, col[0].Login);
51+
Assert.Equal(initialOwnedPrivateRepositoryCount, col[0].OwnedPrivateRepos);
52+
53+
//Demonstrating that the avatar is not yet present
54+
Assert.Null(col[0].Avatar);
55+
56+
//Adding a listener to check for the changing of the Avatar property
57+
initialAccount.Changed.Subscribe(args =>
58+
{
59+
if (args.PropertyName == "Avatar")
60+
{
61+
avatarPropertyEvent.Set();
62+
}
63+
});
64+
65+
//Providing the first avatar
66+
initialBitmapImageSubject.OnNext(userImage);
67+
initialBitmapImageSubject.OnCompleted();
68+
69+
//Waiting for the avatar to be added
70+
avatarPropertyEvent.WaitOne();
71+
avatarPropertyEvent.Reset();
72+
73+
//Demonstrating that the avatar is present
74+
Assert.NotNull(col[0].Avatar);
75+
Assert.True(BitmapSourcesAreEqual(col[0].Avatar, userImage));
76+
Assert.False(BitmapSourcesAreEqual(col[0].Avatar, orgImage));
77+
78+
//Creating an account update
79+
const int updatedOwnedPrivateRepositoryCount = 2;
80+
var updatedBitmapImageSubject = new Subject<BitmapImage>();
81+
var updatedAccount = new Account(login, true, false, updatedOwnedPrivateRepositoryCount, 0, updatedBitmapImageSubject);
82+
83+
//Updating the account in the collection
84+
col.AddItem(updatedAccount);
85+
86+
//Waiting for the collection to process the update
87+
collectionEvent.WaitOne();
88+
collectionEvent.Reset();
89+
90+
//Providing the second avatar
91+
updatedBitmapImageSubject.OnNext(orgImage);
92+
updatedBitmapImageSubject.OnCompleted();
93+
94+
//Waiting for the delayed bitmap image observable
95+
avatarPropertyEvent.WaitOne();
96+
avatarPropertyEvent.Reset();
97+
98+
//Login is the id, so that should be the same
99+
Assert.Equal(login, col[0].Login);
100+
101+
//CopyFrom() should have updated this field
102+
Assert.Equal(updatedOwnedPrivateRepositoryCount, col[0].OwnedPrivateRepos);
103+
104+
//CopyFrom() should not cause a race condition here
105+
Assert.NotNull(col[0].Avatar);
106+
Assert.True(BitmapSourcesAreEqual(col[0].Avatar, orgImage));
107+
Assert.False(BitmapSourcesAreEqual(col[0].Avatar, userImage));
108+
}
109+
110+
public static bool BitmapSourcesAreEqual(BitmapSource image1, BitmapSource image2)
111+
{
112+
if (image1 == null || image2 == null)
113+
{
114+
return false;
115+
}
116+
117+
return BitmapSourceToBytes(image1).SequenceEqual(BitmapSourceToBytes(image2));
118+
}
119+
120+
public static byte[] BitmapSourceToBytes(BitmapSource image)
121+
{
122+
byte[] data = new byte[] { };
123+
if (image != null)
124+
{
125+
try
126+
{
127+
var encoder = new BmpBitmapEncoder();
128+
encoder.Frames.Add(BitmapFrame.Create(image));
129+
using (MemoryStream ms = new MemoryStream())
130+
{
131+
encoder.Save(ms);
132+
data = ms.ToArray();
133+
}
134+
return data;
135+
}
136+
catch (Exception ex)
137+
{
138+
}
139+
}
140+
141+
return data;
142+
}
143+
}
144+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System;
2+
using GitHub.Primitives;
3+
using Xunit;
4+
5+
namespace UnitTests.GitHub.Exports
6+
{
7+
public class HostAddressTests
8+
{
9+
[Fact]
10+
public void ShouldBeEqualIfAddressesMatch()
11+
{
12+
var address1 = HostAddress.Create("foo.com");
13+
var address2 = HostAddress.Create("foo.com");
14+
var null1 = default(HostAddress);
15+
var null2 = default(HostAddress);
16+
17+
Assert.True(address1.Equals(address2));
18+
Assert.True(address1 == address2);
19+
Assert.False(address1 != address2);
20+
Assert.True(null1 == null2);
21+
}
22+
23+
[Fact]
24+
public void ShouldBeNotEqualIfAddressesDontMatch()
25+
{
26+
var address1 = HostAddress.Create("foo.com");
27+
var address2 = HostAddress.Create("bar.com");
28+
var null1 = default(HostAddress);
29+
30+
Assert.False(address1.Equals(address2));
31+
Assert.False(address1 == address2);
32+
Assert.True(address1 != address2);
33+
Assert.False(null1 == address1);
34+
Assert.False(address1 == null1);
35+
Assert.True(null1 != address1);
36+
Assert.True(address1 != null1);
37+
}
38+
}
39+
}

src/UnitTests/GitHubPackageTests.cs

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/UnitTests/UnitTests.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@
160160
<Compile Include="GitHub.App\Caches\CredentialCacheTests.cs" />
161161
<Compile Include="GitHub.App\Caches\ImageCacheTests.cs" />
162162
<Compile Include="GitHub.App\Controllers\UIProviderTests.cs" />
163+
<Compile Include="GitHub.App\Models\AccountModelTests.cs" />
163164
<Compile Include="GitHub.App\Models\ModelServiceTests.cs" />
164165
<Compile Include="GitHub.App\Controllers\UIControllerTests.cs" />
165166
<Compile Include="GitHub.App\Models\PullRequestModelTests.cs" />
@@ -182,6 +183,7 @@
182183
<Compile Include="GitHub.Exports.Reactive\Caches\AccountCacheItemTests.cs" />
183184
<Compile Include="GitHub.Exports\GitServiceTests.cs" />
184185
<None Include="GitHub.Exports\VSServicesTests.cs" />
186+
<Compile Include="GitHub.Exports\HostAddressTests.cs" />
185187
<Compile Include="GitHub.Exports\LocalRepositoryModelTests.cs" />
186188
<Compile Include="GitHub.Extensions\GuardTests.cs" />
187189
<Compile Include="GitHub.Extensions\UriExtensionTests.cs" />
@@ -192,7 +194,6 @@
192194
<Compile Include="GitHub.VisualStudio\Services\RepositoryPublishServiceTests.cs" />
193195
<Compile Include="GitHub.VisualStudio\TeamExplorer\Home\GraphsNavigationItemTests.cs" />
194196
<Compile Include="GitHub.VisualStudio\UI\Views\GitHubPaneViewModelTests.cs" />
195-
<Compile Include="GitHubPackageTests.cs" />
196197
<Compile Include="Helpers\CommandTestHelpers.cs" />
197198
<Compile Include="Helpers\LazySubstitute.cs" />
198199
<Compile Include="Helpers\ReactiveTestHelper.cs" />

0 commit comments

Comments
 (0)