From fb67fe839e742e65f024472c36c0976b3317d95c Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 26 Nov 2020 21:04:42 +0800 Subject: refactor: ... --- .../Services/TimelinePostServiceTest.cs | 200 +++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 BackEnd/Timeline.Tests/Services/TimelinePostServiceTest.cs (limited to 'BackEnd/Timeline.Tests/Services/TimelinePostServiceTest.cs') diff --git a/BackEnd/Timeline.Tests/Services/TimelinePostServiceTest.cs b/BackEnd/Timeline.Tests/Services/TimelinePostServiceTest.cs new file mode 100644 index 00000000..97512be5 --- /dev/null +++ b/BackEnd/Timeline.Tests/Services/TimelinePostServiceTest.cs @@ -0,0 +1,200 @@ +using FluentAssertions; +using Microsoft.Extensions.Logging.Abstractions; +using System; +using System.Linq; +using System.Threading.Tasks; +using Timeline.Models; +using Timeline.Services; +using Timeline.Tests.Helpers; +using Xunit; + +namespace Timeline.Tests.Services +{ + public class TimelinePostServiceTest : DatabaseBasedTest + { + private readonly PasswordService _passwordService = new PasswordService(); + + private readonly ETagGenerator _eTagGenerator = new ETagGenerator(); + + private readonly ImageValidator _imageValidator = new ImageValidator(); + + private readonly TestClock _clock = new TestClock(); + + private DataManager _dataManager = default!; + + private UserPermissionService _userPermissionService = default!; + + private UserService _userService = default!; + + private TimelineService _timelineService = default!; + + private TimelinePostService _timelinePostService = default!; + + private UserDeleteService _userDeleteService = default!; + + protected override void OnDatabaseCreated() + { + _dataManager = new DataManager(Database, _eTagGenerator); + _userPermissionService = new UserPermissionService(Database); + _userService = new UserService(NullLogger.Instance, Database, _passwordService, _clock, _userPermissionService); + _timelineService = new TimelineService(Database, _userService, _clock); + _timelinePostService = new TimelinePostService(NullLogger.Instance, Database, _timelineService, _userService, _dataManager, _imageValidator, _clock); + _userDeleteService = new UserDeleteService(NullLogger.Instance, Database, _timelinePostService); + } + + protected override void BeforeDatabaseDestroy() + { + _eTagGenerator.Dispose(); + } + + [Theory] + [InlineData("@user")] + [InlineData("tl")] + public async Task GetPosts_ModifiedSince(string timelineName) + { + _clock.ForwardCurrentTime(); + + var userId = await _userService.GetUserIdByUsername("user"); + + var _ = TimelineHelper.ExtractTimelineName(timelineName, out var isPersonal); + if (!isPersonal) + await _timelineService.CreateTimeline(timelineName, userId); + + var postContentList = new string[] { "a", "b", "c", "d" }; + + DateTime testPoint = new DateTime(); + + foreach (var (content, index) in postContentList.Select((v, i) => (v, i))) + { + var t = _clock.ForwardCurrentTime(); + if (index == 1) + testPoint = t; + await _timelinePostService.CreateTextPost(timelineName, userId, content, null); + } + + var posts = await _timelinePostService.GetPosts(timelineName, testPoint); + posts.Should().HaveCount(3) + .And.Subject.Select(p => ((TextTimelinePostContent)p.Content!).Text).Should().Equal(postContentList.Skip(1)); + } + + [Theory] + [InlineData("@user")] + [InlineData("tl")] + public async Task GetPosts_IncludeDeleted(string timelineName) + { + var userId = await _userService.GetUserIdByUsername("user"); + + var _ = TimelineHelper.ExtractTimelineName(timelineName, out var isPersonal); + if (!isPersonal) + await _timelineService.CreateTimeline(timelineName, userId); + + var postContentList = new string[] { "a", "b", "c", "d" }; + + foreach (var content in postContentList) + { + await _timelinePostService.CreateTextPost(timelineName, userId, content, null); + } + + var posts = await _timelinePostService.GetPosts(timelineName); + posts.Should().HaveCount(4); + posts.Select(p => p.Deleted).Should().Equal(Enumerable.Repeat(false, posts.Count)); + posts.Select(p => ((TextTimelinePostContent)p.Content!).Text).Should().Equal(postContentList); + + foreach (var id in new long[] { posts[0].Id, posts[2].Id }) + { + await _timelinePostService.DeletePost(timelineName, id); + } + + posts = await _timelinePostService.GetPosts(timelineName); + posts.Should().HaveCount(2); + posts.Select(p => p.Deleted).Should().Equal(Enumerable.Repeat(false, posts.Count)); + posts.Select(p => ((TextTimelinePostContent)p.Content!).Text).Should().Equal(new string[] { "b", "d" }); + + posts = await _timelinePostService.GetPosts(timelineName, includeDeleted: true); + posts.Should().HaveCount(4); + posts.Select(p => p.Deleted).Should().Equal(new bool[] { true, false, true, false }); + posts.Where(p => !p.Deleted).Select(p => ((TextTimelinePostContent)p.Content!).Text).Should().Equal(new string[] { "b", "d" }); + } + + [Theory] + [InlineData("@admin")] + [InlineData("tl")] + public async Task GetPosts_ModifiedSince_UsernameChange(string timelineName) + { + var time1 = _clock.ForwardCurrentTime(); + + var userId = await _userService.GetUserIdByUsername("user"); + + var _ = TimelineHelper.ExtractTimelineName(timelineName, out var isPersonal); + if (!isPersonal) + await _timelineService.CreateTimeline(timelineName, userId); + + var postContentList = new string[] { "a", "b", "c", "d" }; + + foreach (var (content, index) in postContentList.Select((v, i) => (v, i))) + { + await _timelinePostService.CreateTextPost(timelineName, userId, content, null); + } + + var time2 = _clock.ForwardCurrentTime(); + + { + var posts = await _timelinePostService.GetPosts(timelineName, time2); + posts.Should().HaveCount(0); + } + + { + await _userService.ModifyUser(userId, new ModifyUserParams { Nickname = "haha" }); + var posts = await _timelinePostService.GetPosts(timelineName, time2); + posts.Should().HaveCount(0); + } + + { + await _userService.ModifyUser(userId, new ModifyUserParams { Username = "haha" }); + var posts = await _timelinePostService.GetPosts(timelineName, time2); + posts.Should().HaveCount(4); + } + } + + [Theory] + [InlineData("@admin")] + [InlineData("tl")] + public async Task GetPosts_ModifiedSince_UserDelete(string timelineName) + { + var time1 = _clock.ForwardCurrentTime(); + + var userId = await _userService.GetUserIdByUsername("user"); + var adminId = await _userService.GetUserIdByUsername("admin"); + + var _ = TimelineHelper.ExtractTimelineName(timelineName, out var isPersonal); + if (!isPersonal) + await _timelineService.CreateTimeline(timelineName, adminId); + + var postContentList = new string[] { "a", "b", "c", "d" }; + + foreach (var (content, index) in postContentList.Select((v, i) => (v, i))) + { + await _timelinePostService.CreateTextPost(timelineName, userId, content, null); + } + + var time2 = _clock.ForwardCurrentTime(); + + { + var posts = await _timelinePostService.GetPosts(timelineName, time2); + posts.Should().HaveCount(0); + } + + await _userDeleteService.DeleteUser("user"); + + { + var posts = await _timelinePostService.GetPosts(timelineName, time2); + posts.Should().HaveCount(0); + } + + { + var posts = await _timelinePostService.GetPosts(timelineName, time2, true); + posts.Should().HaveCount(4); + } + } + } +} -- cgit v1.2.3 From 5e4cdbbfa75ce021dfbfd8e1f2d38370a702285e Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 27 Nov 2020 01:26:23 +0800 Subject: ... --- BackEnd/Timeline.Tests/Helpers/TestDatabase.cs | 2 +- .../Services/HighlightTimelineServiceTest.cs | 35 ++++++++++++++++++---- .../Services/TimelinePostServiceTest.cs | 2 +- .../Timeline.Tests/Services/TimelineServiceTest.cs | 2 +- .../Timeline/Entities/HighlightTimelineEntity.cs | 8 +++-- BackEnd/Timeline/Models/TimelineInfo.cs | 4 +-- BackEnd/Timeline/Models/UserInfo.cs | 2 +- .../Timeline/Services/HighlightTimelineService.cs | 6 ++-- BackEnd/Timeline/Services/UserPermissionService.cs | 33 ++++++++++++++++++-- BackEnd/Timeline/Services/UserService.cs | 6 ++-- 10 files changed, 79 insertions(+), 21 deletions(-) (limited to 'BackEnd/Timeline.Tests/Services/TimelinePostServiceTest.cs') diff --git a/BackEnd/Timeline.Tests/Helpers/TestDatabase.cs b/BackEnd/Timeline.Tests/Helpers/TestDatabase.cs index 74db74aa..a71c2208 100644 --- a/BackEnd/Timeline.Tests/Helpers/TestDatabase.cs +++ b/BackEnd/Timeline.Tests/Helpers/TestDatabase.cs @@ -35,7 +35,7 @@ namespace Timeline.Tests.Helpers if (_createUser) { var passwordService = new PasswordService(); - var userService = new UserService(NullLogger.Instance, context, passwordService, new Clock(), new UserPermissionService(context)); + var userService = new UserService(NullLogger.Instance, context, passwordService, new UserPermissionService(context), new Clock()); var admin = await userService.CreateUser("admin", "adminpw"); await userService.ModifyUser(admin.Id, new ModifyUserParams() { Nickname = "administrator" }); diff --git a/BackEnd/Timeline.Tests/Services/HighlightTimelineServiceTest.cs b/BackEnd/Timeline.Tests/Services/HighlightTimelineServiceTest.cs index a4cd983d..8ba26613 100644 --- a/BackEnd/Timeline.Tests/Services/HighlightTimelineServiceTest.cs +++ b/BackEnd/Timeline.Tests/Services/HighlightTimelineServiceTest.cs @@ -1,18 +1,43 @@ -using Timeline.Services; +using FluentAssertions; +using Microsoft.Extensions.Logging.Abstractions; +using System.Threading.Tasks; +using Timeline.Services; +using Timeline.Tests.Helpers; +using Xunit; namespace Timeline.Tests.Services { public class HighlightTimelineServiceTest : DatabaseBasedTest { - private UserService _userService; - private TimelineService _timelineService; + private readonly TestClock _clock = new TestClock(); + private UserService _userService = default!; + private TimelineService _timelineService = default!; - private HighlightTimelineService _service; + private HighlightTimelineService _service = default!; protected override void OnDatabaseCreated() { - + _userService = new UserService(NullLogger.Instance, Database, new PasswordService(), new UserPermissionService(Database), _clock); + _timelineService = new TimelineService(Database, _userService, _clock); + _service = new HighlightTimelineService(Database, _userService, _timelineService, _clock); } + [Fact] + public async Task Should_Work() + { + { + var ht = await _service.GetHighlightTimelines(); + ht.Should().BeEmpty(); + } + + var userId = await _userService.GetUserIdByUsername("user"); + await _timelineService.CreateTimeline("tl", userId); + await _service.AddHighlightTimeline("tl", userId); + + { + var ht = await _service.GetHighlightTimelines(); + ht.Should().HaveCount(1).And.BeEquivalentTo(await _timelineService.GetTimeline("tl")); + } + } } } diff --git a/BackEnd/Timeline.Tests/Services/TimelinePostServiceTest.cs b/BackEnd/Timeline.Tests/Services/TimelinePostServiceTest.cs index 97512be5..7771ae0b 100644 --- a/BackEnd/Timeline.Tests/Services/TimelinePostServiceTest.cs +++ b/BackEnd/Timeline.Tests/Services/TimelinePostServiceTest.cs @@ -36,7 +36,7 @@ namespace Timeline.Tests.Services { _dataManager = new DataManager(Database, _eTagGenerator); _userPermissionService = new UserPermissionService(Database); - _userService = new UserService(NullLogger.Instance, Database, _passwordService, _clock, _userPermissionService); + _userService = new UserService(NullLogger.Instance, Database, _passwordService, _userPermissionService, _clock); _timelineService = new TimelineService(Database, _userService, _clock); _timelinePostService = new TimelinePostService(NullLogger.Instance, Database, _timelineService, _userService, _dataManager, _imageValidator, _clock); _userDeleteService = new UserDeleteService(NullLogger.Instance, Database, _timelinePostService); diff --git a/BackEnd/Timeline.Tests/Services/TimelineServiceTest.cs b/BackEnd/Timeline.Tests/Services/TimelineServiceTest.cs index 98f03066..70f54ede 100644 --- a/BackEnd/Timeline.Tests/Services/TimelineServiceTest.cs +++ b/BackEnd/Timeline.Tests/Services/TimelineServiceTest.cs @@ -26,7 +26,7 @@ namespace Timeline.Tests.Services protected override void OnDatabaseCreated() { _userPermissionService = new UserPermissionService(Database); - _userService = new UserService(NullLogger.Instance, Database, _passwordService, _clock, _userPermissionService); + _userService = new UserService(NullLogger.Instance, Database, _passwordService, _userPermissionService, _clock); _timelineService = new TimelineService(Database, _userService, _clock); } diff --git a/BackEnd/Timeline/Entities/HighlightTimelineEntity.cs b/BackEnd/Timeline/Entities/HighlightTimelineEntity.cs index 0a38c8a6..3378a175 100644 --- a/BackEnd/Timeline/Entities/HighlightTimelineEntity.cs +++ b/BackEnd/Timeline/Entities/HighlightTimelineEntity.cs @@ -1,10 +1,11 @@ -using System.ComponentModel.DataAnnotations; +using System; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Timeline.Entities { [Table("highlight_timelines")] - public record HighlightTimelineEntity + public class HighlightTimelineEntity { [Key, Column("id"), DatabaseGenerated(DatabaseGeneratedOption.Identity)] public long Id { get; set; } @@ -20,5 +21,8 @@ namespace Timeline.Entities [ForeignKey(nameof(OperatorId))] public UserEntity? Operator { get; set; } + + [Column("add_time")] + public DateTime AddTime { get; set; } } } diff --git a/BackEnd/Timeline/Models/TimelineInfo.cs b/BackEnd/Timeline/Models/TimelineInfo.cs index 440f6b81..649af274 100644 --- a/BackEnd/Timeline/Models/TimelineInfo.cs +++ b/BackEnd/Timeline/Models/TimelineInfo.cs @@ -50,7 +50,7 @@ namespace Timeline.Models public string DataTag { get; set; } } - public record TimelinePostInfo + public class TimelinePostInfo { public TimelinePostInfo() { @@ -76,7 +76,7 @@ namespace Timeline.Models public string TimelineName { get; set; } = default!; } - public record TimelineInfo + public class TimelineInfo { public TimelineInfo() { diff --git a/BackEnd/Timeline/Models/UserInfo.cs b/BackEnd/Timeline/Models/UserInfo.cs index 058cc590..e8d57def 100644 --- a/BackEnd/Timeline/Models/UserInfo.cs +++ b/BackEnd/Timeline/Models/UserInfo.cs @@ -3,7 +3,7 @@ using Timeline.Services; namespace Timeline.Models { - public record UserInfo + public class UserInfo { public UserInfo() { diff --git a/BackEnd/Timeline/Services/HighlightTimelineService.cs b/BackEnd/Timeline/Services/HighlightTimelineService.cs index 619bc33e..0f4e5488 100644 --- a/BackEnd/Timeline/Services/HighlightTimelineService.cs +++ b/BackEnd/Timeline/Services/HighlightTimelineService.cs @@ -46,12 +46,14 @@ namespace Timeline.Services private readonly DatabaseContext _database; private readonly IBasicUserService _userService; private readonly ITimelineService _timelineService; + private readonly IClock _clock; - public HighlightTimelineService(DatabaseContext database, IBasicUserService userService, ITimelineService timelineService) + public HighlightTimelineService(DatabaseContext database, IBasicUserService userService, ITimelineService timelineService, IClock clock) { _database = database; _userService = userService; _timelineService = timelineService; + _clock = clock; } public async Task AddHighlightTimeline(string timelineName, long? operatorId) @@ -70,7 +72,7 @@ namespace Timeline.Services if (alreadyIs) return; - _database.HighlightTimelines.Add(new HighlightTimelineEntity { TimelineId = timelineId, OperatorId = operatorId }); + _database.HighlightTimelines.Add(new HighlightTimelineEntity { TimelineId = timelineId, OperatorId = operatorId, AddTime = _clock.GetCurrentTime() }); await _database.SaveChangesAsync(); } diff --git a/BackEnd/Timeline/Services/UserPermissionService.cs b/BackEnd/Timeline/Services/UserPermissionService.cs index 9683000a..bd7cd6aa 100644 --- a/BackEnd/Timeline/Services/UserPermissionService.cs +++ b/BackEnd/Timeline/Services/UserPermissionService.cs @@ -28,7 +28,7 @@ namespace Timeline.Services /// /// Represents a user's permissions. /// - public class UserPermissions : IEnumerable + public class UserPermissions : IEnumerable, IEquatable { public static UserPermissions AllPermissions { get; } = new UserPermissions(Enum.GetValues()); @@ -49,10 +49,10 @@ namespace Timeline.Services public UserPermissions(IEnumerable permissions) { if (permissions == null) throw new ArgumentNullException(nameof(permissions)); - _permissions = new HashSet(permissions); + _permissions = new SortedSet(permissions); } - private readonly HashSet _permissions = new(); + private readonly SortedSet _permissions = new(); /// /// Check if a permission is contained in the list. @@ -108,6 +108,33 @@ namespace Timeline.Services { return ((IEnumerable)_permissions).GetEnumerator(); } + + public bool Equals(UserPermissions? other) + { + if (other == null) + return false; + + return _permissions.SequenceEqual(other._permissions); + } + + public override bool Equals(object? obj) + { + return Equals(obj as UserPermissions); + } + + public override int GetHashCode() + { + int result = 0; + foreach (var permission in Enum.GetValues()) + { + if (_permissions.Contains(permission)) + { + result += 1; + } + result <<= 1; + } + return result; + } } public interface IUserPermissionService diff --git a/BackEnd/Timeline/Services/UserService.cs b/BackEnd/Timeline/Services/UserService.cs index 96068e44..c99e86b0 100644 --- a/BackEnd/Timeline/Services/UserService.cs +++ b/BackEnd/Timeline/Services/UserService.cs @@ -17,7 +17,7 @@ namespace Timeline.Services /// /// Null means not change. /// - public record ModifyUserParams + public class ModifyUserParams { public string? Username { get; set; } public string? Password { get; set; } @@ -78,13 +78,13 @@ namespace Timeline.Services private readonly UsernameValidator _usernameValidator = new UsernameValidator(); private readonly NicknameValidator _nicknameValidator = new NicknameValidator(); - public UserService(ILogger logger, DatabaseContext databaseContext, IPasswordService passwordService, IClock clock, IUserPermissionService userPermissionService) : base(databaseContext) + public UserService(ILogger logger, DatabaseContext databaseContext, IPasswordService passwordService, IUserPermissionService userPermissionService, IClock clock) : base(databaseContext) { _logger = logger; - _clock = clock; _databaseContext = databaseContext; _passwordService = passwordService; _userPermissionService = userPermissionService; + _clock = clock; } private void CheckUsernameFormat(string username, string? paramName) -- cgit v1.2.3