Skip to content

Commit bcd6d25

Browse files
Merge branch 'main' into release
2 parents e96130d + 7a6aa9f commit bcd6d25

13 files changed

+617
-17
lines changed

Directory.Build.props

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
<NeutralLanguage>en</NeutralLanguage>
99
<Copyright>Copyright © ONIXLabs 2020</Copyright>
1010
<RepositoryUrl>https://github.com/onix-labs/onixlabs-dotnet</RepositoryUrl>
11-
<Version>11.2.0</Version>
12-
<PackageVersion>11.2.0</PackageVersion>
13-
<AssemblyVersion>11.2.0</AssemblyVersion>
11+
<Version>11.3.0</Version>
12+
<PackageVersion>11.3.0</PackageVersion>
13+
<AssemblyVersion>11.3.0</AssemblyVersion>
1414
</PropertyGroup>
1515
</Project>
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2020 ONIXLabs
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
namespace OnixLabs.Core.UnitTests.Data;
16+
17+
public sealed record Location(string City, string Country)
18+
{
19+
public static readonly Location London = new("London", "England");
20+
public static readonly Location Paris = new("Paris", "France");
21+
public static readonly Location Lisbon = new("Lisbon", "Postugal");
22+
public static readonly Location Berlin = new("Berlin", "Germany");
23+
public static readonly Location Brussels = new("Brussels", "Belgium");
24+
}
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2020 ONIXLabs
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using System.Collections.Generic;
16+
17+
namespace OnixLabs.Core.UnitTests.Data;
18+
19+
public sealed record Person(string Name, int Age, IEnumerable<Location> Locations)
20+
{
21+
public static readonly Person Alice = new("Alice", 12, [Location.London, Location.Paris]);
22+
public static readonly Person Bob = new("Bob", 23, [Location.Lisbon, Location.London]);
23+
public static readonly Person Charlie = new("Charlie", 34, [Location.Berlin, Location.Brussels]);
24+
25+
public static readonly IEnumerable<Person> People = [Alice, Bob, Charlie];
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2020 ONIXLabs
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using System;
16+
using System.Linq;
17+
using System.Linq.Expressions;
18+
19+
namespace OnixLabs.Core.UnitTests.Data;
20+
21+
public class PersonSpecification(Expression<Func<Person, bool>> expression) :
22+
CriteriaSpecification<Person>(expression);
23+
24+
public sealed class PersonNameEqualsSpecification(string name) :
25+
PersonSpecification(person => person.Name == name);
26+
27+
public sealed class PersonNameStartsWithSpecification(string name) :
28+
PersonSpecification(person => person.Name.StartsWith(name));
29+
30+
public sealed class PersonOlderThanSpecification(int age) :
31+
PersonSpecification(person => person.Age > age);
32+
33+
public sealed class PersonHasLocationSpecification(Location location) :
34+
PersonSpecification(person => person.Locations.Contains(location));
35+
36+
public sealed class PersonHasLocationCitySpecification(string city) :
37+
PersonSpecification(person => person.Locations.Any(location => location.City == city));

OnixLabs.Core.UnitTests/OptionalTests.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ public void OptionalNoneGetValueOrDefaultShouldProduceExpectedResult()
336336

337337
// Then
338338
Assert.Equal(0, actualNumber);
339-
Assert.Equal(null, actualText);
339+
Assert.Null(actualText);
340340
}
341341

342342
[Fact(DisplayName = "Optional Some.GetValueOrDefault with default value should produce the expected result.")]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// Copyright 2020 ONIXLabs
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using System.Collections.Generic;
16+
using System.Linq;
17+
using OnixLabs.Core.Linq;
18+
using OnixLabs.Core.UnitTests.Data;
19+
using Xunit;
20+
21+
namespace OnixLabs.Core.UnitTests;
22+
23+
public sealed class SpecificationTests
24+
{
25+
[Fact(DisplayName = "PersonNameEqualsSpecification should return the expected result")]
26+
public void PersonNameEqualsSpecificationShouldReturnExpectedResult()
27+
{
28+
// Given
29+
PersonNameEqualsSpecification specification = new("Alice");
30+
31+
// When
32+
IEnumerable<Person> result = Person.People.Where(specification).ToList();
33+
34+
// Then
35+
Assert.Single(result);
36+
Assert.Contains(Person.Alice, result);
37+
}
38+
39+
[Fact(DisplayName = "PersonNameStartsWithSpecification should return the expected result")]
40+
public void PersonNameStartsWithSpecificationShouldReturnExpectedResult()
41+
{
42+
// Given
43+
PersonNameStartsWithSpecification specification = new("A");
44+
45+
// When
46+
IEnumerable<Person> result = Person.People.Where(specification).ToList();
47+
48+
// Then
49+
Assert.Single(result);
50+
Assert.Contains(Person.Alice, result);
51+
}
52+
53+
[Fact(DisplayName = "PersonOlderThanSpecification should return the expected result")]
54+
public void PersonOlderThanSpecificationShouldReturnExpectedResult()
55+
{
56+
// Given
57+
PersonOlderThanSpecification specification = new(20);
58+
59+
// When
60+
IEnumerable<Person> result = Person.People.Where(specification).ToList();
61+
62+
// Then
63+
Assert.Equal(2, IEnumerableExtensions.Count(result));
64+
Assert.Contains(Person.Bob, result);
65+
Assert.Contains(Person.Charlie, result);
66+
}
67+
68+
[Fact(DisplayName = "PersonHasLocationSpecification should return the expected result")]
69+
public void PersonHasLocationSpecificationShouldReturnExpectedResult()
70+
{
71+
// Given
72+
PersonHasLocationSpecification specification = new(Location.London);
73+
74+
// When
75+
IEnumerable<Person> result = Person.People.Where(specification).ToList();
76+
77+
// Then
78+
Assert.Equal(2, IEnumerableExtensions.Count(result));
79+
Assert.Contains(Person.Alice, result);
80+
Assert.Contains(Person.Bob, result);
81+
}
82+
83+
[Fact(DisplayName = "PersonHasLocationCitySpecification should return the expected result")]
84+
public void PersonHasLocationCitySpecificationShouldReturnExpectedResult()
85+
{
86+
// Given
87+
PersonHasLocationCitySpecification specification = new(Location.London.City);
88+
89+
// When
90+
IEnumerable<Person> result = Person.People.Where(specification).ToList();
91+
92+
// Then
93+
Assert.Equal(2, IEnumerableExtensions.Count(result));
94+
Assert.Contains(Person.Alice, result);
95+
Assert.Contains(Person.Bob, result);
96+
}
97+
98+
[Fact(DisplayName = "PersonSpecification.And should return the expected result")]
99+
public void PersonSpecificationAndShouldReturnExpectedResult()
100+
{
101+
// Given
102+
Specification<Person> specification = PersonSpecification.And(
103+
new PersonOlderThanSpecification(20),
104+
new PersonHasLocationCitySpecification("London")
105+
);
106+
107+
// When
108+
IEnumerable<Person> result = Person.People.Where(specification).ToList();
109+
110+
// Then
111+
Assert.Single(result);
112+
Assert.Contains(Person.Bob, result);
113+
}
114+
115+
[Fact(DisplayName = "PersonSpecification.And should return true for an empty collection")]
116+
public void PersonSpecificationAndShouldReturnTrueForEmptyCollection()
117+
{
118+
// Given
119+
Specification<Person> specification = PersonSpecification.And();
120+
121+
// When
122+
bool result = specification.IsSatisfiedBy(Person.Alice);
123+
124+
// Then
125+
Assert.True(result);
126+
}
127+
128+
[Fact(DisplayName = "PersonSpecification.Or should return the expected result")]
129+
public void PersonSpecificationOrShouldReturnExpectedResult()
130+
{
131+
// Given
132+
Specification<Person> specification = PersonSpecification.Or(
133+
new PersonNameStartsWithSpecification("A"),
134+
new PersonHasLocationCitySpecification("Lisbon")
135+
);
136+
137+
// When
138+
IEnumerable<Person> result = Person.People.Where(specification).ToList();
139+
140+
// Then
141+
Assert.Equal(2, result.Count());
142+
Assert.Contains(Person.Alice, result);
143+
Assert.Contains(Person.Bob, result);
144+
}
145+
146+
[Fact(DisplayName = "PersonSpecification.Or should return false for an empty collection")]
147+
public void PersonSpecificationOrShouldReturnFalseForEmptyCollection()
148+
{
149+
// Given
150+
Specification<Person> specification = PersonSpecification.Or();
151+
152+
// When
153+
bool result = specification.IsSatisfiedBy(Person.Alice);
154+
155+
// Then
156+
Assert.False(result);
157+
}
158+
159+
[Fact(DisplayName = "PersonSpecification.Not should return the expected result")]
160+
public void PersonSpecificationNotShouldReturnExpectedResult()
161+
{
162+
// Given
163+
Specification<Person> specification = PersonSpecification.Or(
164+
new PersonNameStartsWithSpecification("A"),
165+
new PersonHasLocationCitySpecification("Lisbon")
166+
);
167+
168+
// When
169+
IEnumerable<Person> result = Person.People.WhereNot(specification).ToList();
170+
171+
// Then
172+
Assert.Single(result);
173+
Assert.Contains(Person.Charlie, result);
174+
}
175+
}

OnixLabs.Core/Extensions.DateTime.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2020-2024 ONIXLabs
1+
// Copyright 2020 ONIXLabs
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.

OnixLabs.Core/IBinaryConvertible.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
using System;
16+
1517
namespace OnixLabs.Core;
1618

1719
/// <summary>
18-
/// Defines a type that is convertible to an instance of <see cref="T:Byte[]"/>.
20+
/// Defines a type that is convertible to a <see cref="ReadOnlySpan{T}"/>, or <see cref="ReadOnlyMemory{T}"/>.
1921
/// </summary>
2022
public interface IBinaryConvertible : ISpanBinaryConvertible, IMemoryBinaryConvertible;

OnixLabs.Core/IMemoryBinaryConvertible.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2020-2024 ONIXLabs
1+
// Copyright 2020 ONIXLabs
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.

0 commit comments

Comments
 (0)