Skip to content

Commit a954506

Browse files
Impoved code coverage.
1 parent a011125 commit a954506

25 files changed

Lines changed: 471 additions & 240 deletions

source/CollectionWrapper.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
using System.Collections.Generic;
2+
using System.Diagnostics.CodeAnalysis;
23
using System.Runtime.CompilerServices;
34

45
namespace Open.Collections;
56

67
public class CollectionWrapper<T, TCollection> : ReadOnlyCollectionWrapper<T, TCollection>, ICollection<T>
78
where TCollection : class, ICollection<T>
89
{
9-
public CollectionWrapper(TCollection source, bool owner = false)
10+
[ExcludeFromCodeCoverage]
11+
public CollectionWrapper(TCollection source, bool owner = false)
1012
: base(source, owner)
1113
{
1214
}
@@ -17,22 +19,26 @@ public CollectionWrapper(TCollection source, bool owner = false)
1719
/// The underlying object used for synchronization.
1820
/// This is exposed to allow for more complex synchronization operations.
1921
/// </summary>
22+
[ExcludeFromCodeCoverage]
2023
public object SyncRoot => Sync;
2124

2225
#region Implementation of ICollection<T>
2326

27+
[ExcludeFromCodeCoverage]
2428
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2529
protected virtual void AddInternal(T item)
2630
=> InternalSource.Add(item);
2731

2832
/// <inheritdoc />
33+
[ExcludeFromCodeCoverage]
2934
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3035
public virtual void Add(T item) => AddInternal(item);
3136

3237
/// <summary>Adds more than one item.</summary>
3338
/// <param name="item1">First item to add.</param>
3439
/// <param name="item2">Additional item to add.</param>
3540
/// <param name="items">Extended param items to add.</param>
41+
[ExcludeFromCodeCoverage]
3642
public virtual void AddThese(T item1, T item2, params T[] items)
3743
{
3844
AddInternal(item1);
@@ -47,6 +53,7 @@ public virtual void AddThese(T item1, T item2, params T[] items)
4753
/// An enumerable is potentially slow as it may be yielding to a process.
4854
/// </summary>
4955
/// <param name="items">The items to add.</param>
56+
[ExcludeFromCodeCoverage]
5057
[MethodImpl(MethodImplOptions.AggressiveInlining)]
5158
public virtual void AddRange(IEnumerable<T> items)
5259
{
@@ -55,17 +62,20 @@ public virtual void AddRange(IEnumerable<T> items)
5562
}
5663

5764
/// <inheritdoc />
65+
[ExcludeFromCodeCoverage]
5866
[MethodImpl(MethodImplOptions.AggressiveInlining)]
5967
public virtual void Clear()
6068
=> InternalSource.Clear();
6169

6270
/// <inheritdoc />
71+
[ExcludeFromCodeCoverage]
6372
[MethodImpl(MethodImplOptions.AggressiveInlining)]
6473
public virtual bool Remove(T item)
6574
=> InternalSource.Remove(item);
6675

67-
/// <inheritdoc />
68-
public override bool IsReadOnly
76+
/// <inheritdoc />
77+
[ExcludeFromCodeCoverage]
78+
public override bool IsReadOnly
6979
=> InternalSource.IsReadOnly;
7080
#endregion
7181
}

source/Extensions.Generic.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public static void Register<T>(this ICollection<T> target, T value)
3838
target.Add(value);
3939
}
4040

41-
public static void Add<T>(this ICollection<T> target, IEnumerable<T> values)
41+
public static void AddRange<T>(this ICollection<T> target, IEnumerable<T> values)
4242
{
4343
if (target is null) throw new ArgumentNullException(nameof(target));
4444
Contract.EndContractBlock();
@@ -50,11 +50,11 @@ public static void Add<T>(this ICollection<T> target, IEnumerable<T> values)
5050
target.Add(value);
5151
}
5252

53-
public static void Add<T>(this ICollection<T> target, T a, T b, params T[] more)
53+
public static void AddThese<T>(this ICollection<T> target, T a, T b, params T[] more)
5454
{
5555
target.Add(a);
5656
target.Add(b);
57-
target.Add(more);
57+
target.AddRange(more);
5858
}
5959

6060
public static int Remove<T>(this ICollection<T> target, IEnumerable<T> values)

source/Extensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ public static void ForEach<T>(this IEnumerable<T> target, Action<T> closure, boo
203203
closure(t);
204204
}
205205

206-
public static void ForEach<T>(this IEnumerable<T> target, CancellationToken token, Action<T> closure)
206+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1068:CancellationToken parameters must come last", Justification = "Allows for simpler implementation. Other methods cover non-cancellable case.")]
207+
public static void ForEach<T>(this IEnumerable<T> target, CancellationToken token, Action<T> closure)
207208
{
208209
if (target is null) throw new ArgumentNullException(nameof(target));
209210
if (closure is null) throw new ArgumentNullException(nameof(closure));

source/ReadOnlyCollectionWrapper.cs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System;
33
using System.Collections;
44
using System.Collections.Generic;
5+
using System.Diagnostics.CodeAnalysis;
56
using System.Runtime.CompilerServices;
67

78
namespace Open.Collections;
@@ -21,51 +22,60 @@ public class ReadOnlyCollectionWrapper<T, TCollection> : DisposableBase, IReadOn
2122
/// And will throw <see cref="NotSupportedException"/> to prevent direct access to the source when .ExtractAndDispose() is called.
2223
/// </param>
2324
/// <exception cref="ArgumentNullException">If the <paramref name="source"/> is <see langword="null"/>.</exception>
24-
public ReadOnlyCollectionWrapper(TCollection source, bool owner = false)
25+
[ExcludeFromCodeCoverage]
26+
public ReadOnlyCollectionWrapper(TCollection source, bool owner = false)
2527
{
2628
InternalSource = source ?? throw new ArgumentNullException(nameof(source));
2729
SourceOwned = owner;
2830
}
2931

3032
#region Implementation of IReadOnlyCollection<T>
3133
/// <inheritdoc cref="ICollection&lt;T&gt;.Contains(T)" />
34+
[ExcludeFromCodeCoverage]
3235
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3336
public virtual bool Contains(T item)
3437
=> InternalSource.Contains(item);
3538

36-
/// <inheritdoc />
37-
public virtual int Count
39+
/// <inheritdoc />
40+
[ExcludeFromCodeCoverage]
41+
public virtual int Count
3842
=> InternalSource.Count;
3943

40-
/// <inheritdoc cref="ICollection&lt;T&gt;.IsReadOnly" />
41-
public virtual bool IsReadOnly
44+
/// <inheritdoc cref="ICollection&lt;T&gt;.IsReadOnly" />
45+
[ExcludeFromCodeCoverage]
46+
public virtual bool IsReadOnly
4247
=> true;
4348

44-
/// <summary>
45-
/// To ensure expected behavior, this returns an enumerator from the underlying collection. Exceptions can be thrown if the collection content changes.
46-
/// </summary>
47-
/// <returns>An enumerator from the underlying collection.</returns>
48-
public virtual IEnumerator<T> GetEnumerator() => InternalSource.GetEnumerator();
49+
/// <summary>
50+
/// To ensure expected behavior, this returns an enumerator from the underlying collection. Exceptions can be thrown if the collection content changes.
51+
/// </summary>
52+
/// <returns>An enumerator from the underlying collection.</returns>
53+
[ExcludeFromCodeCoverage]
54+
public virtual IEnumerator<T> GetEnumerator() => InternalSource.GetEnumerator();
4955

50-
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
56+
[ExcludeFromCodeCoverage]
57+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
5158

5259
/// <inheritdoc cref="ICollection&lt;T&gt;.CopyTo(T[], int)" />
60+
[ExcludeFromCodeCoverage]
5361
[MethodImpl(MethodImplOptions.AggressiveInlining)]
5462
public virtual void CopyTo(T[] array, int arrayIndex)
5563
=> InternalSource.CopyTo(array, arrayIndex);
5664
#endregion
5765

5866
/// <inheritdoc cref="Extensions.CopyToSpan{T}(IEnumerable{T}, Span{T})"/>
67+
[ExcludeFromCodeCoverage]
5968
[MethodImpl(MethodImplOptions.AggressiveInlining)]
6069
public virtual Span<T> CopyTo(Span<T> span)
6170
=> InternalSource.CopyToSpan(span);
6271

6372
/// <inheritdoc cref="ISynchronizedCollection&lt;T&gt;.Export(ICollection{T})" />
6473
[MethodImpl(MethodImplOptions.AggressiveInlining)]
6574
public virtual void Export(ICollection<T> to)
66-
=> to.Add(InternalSource);
75+
=> to.AddRange(InternalSource);
6776

6877
#region Dispose
78+
[ExcludeFromCodeCoverage]
6979
protected override void OnDispose()
7080
{
7181
var source = Nullify(ref InternalSource);
@@ -86,5 +96,4 @@ public TCollection ExtractAndDispose()
8696
}
8797
}
8898
#endregion
89-
9099
}

source/Synchronized/LockSynchronizedCollectionWrapper.cs

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Collections.Immutable;
4+
using System.Diagnostics.CodeAnalysis;
45
using System.Linq;
56

67
namespace Open.Collections.Synchronized;
@@ -66,18 +67,20 @@ public override bool Remove(T item)
6667
lock (Sync) return base.Remove(item);
6768
}
6869

69-
#endregion
70+
#endregion
7071

71-
/// <inheritdoc />
72-
public T[] Snapshot()
72+
/// <inheritdoc />
73+
[ExcludeFromCodeCoverage]
74+
public T[] Snapshot()
7375
{
7476
lock (Sync) return this.ToArray();
7577
}
7678

77-
/// <inheritdoc cref="CollectionWrapper&lt;T, TCollection&gt;" />
78-
public override void Export(ICollection<T> to)
79+
/// <inheritdoc cref="CollectionWrapper&lt;T, TCollection&gt;" />
80+
[ExcludeFromCodeCoverage]
81+
public override void Export(ICollection<T> to)
7982
{
80-
lock (Sync) to.Add(this);
83+
lock (Sync) to.AddRange(this);
8184
}
8285

8386
/// <summary>
@@ -103,33 +106,37 @@ public void ForEach(Action<T> action, bool useSnapshot = true)
103106
}
104107
}
105108

106-
/// <inheritdoc />
107-
public override void CopyTo(T[] array, int arrayIndex)
109+
/// <inheritdoc />
110+
[ExcludeFromCodeCoverage]
111+
public override void CopyTo(T[] array, int arrayIndex)
108112
{
109113
lock (Sync) base.CopyTo(array, arrayIndex);
110114
}
111115

112-
/// <summary>
113-
/// Copies the results to the provided span up to its length or until the end of the results.
114-
/// </summary>
115-
/// <returns>
116-
/// A span representing the results.
117-
/// If the count was less than the target length, a new span representing the results.
118-
/// Otherwise the target is returned.
119-
/// </returns>
120-
public override Span<T> CopyTo(Span<T> span)
116+
/// <summary>
117+
/// Copies the results to the provided span up to its length or until the end of the results.
118+
/// </summary>
119+
/// <returns>
120+
/// A span representing the results.
121+
/// If the count was less than the target length, a new span representing the results.
122+
/// Otherwise the target is returned.
123+
/// </returns>
124+
[ExcludeFromCodeCoverage]
125+
public override Span<T> CopyTo(Span<T> span)
121126
{
122127
lock (Sync) return base.CopyTo(span);
123128
}
124129

125-
/// <inheritdoc />
126-
public void Modify(Action<TCollection> action)
130+
/// <inheritdoc />
131+
[ExcludeFromCodeCoverage]
132+
public void Modify(Action<TCollection> action)
127133
{
128134
lock (Sync) action(InternalSource);
129135
}
130136

131-
/// <inheritdoc />
132-
public void Modify(Func<bool> condition, Action<TCollection> action)
137+
/// <inheritdoc />
138+
[ExcludeFromCodeCoverage]
139+
public void Modify(Func<bool> condition, Action<TCollection> action)
133140
{
134141
if (!condition()) return;
135142
lock (Sync)
@@ -139,8 +146,9 @@ public void Modify(Func<bool> condition, Action<TCollection> action)
139146
}
140147
}
141148

142-
/// <inheritdoc />
143-
public TResult Modify<TResult>(Func<TCollection, TResult> action)
149+
/// <inheritdoc />
150+
[ExcludeFromCodeCoverage]
151+
public TResult Modify<TResult>(Func<TCollection, TResult> action)
144152
{
145153
lock (Sync) return action(InternalSource);
146154
}

source/Synchronized/LockSynchronizedDictionaryWrapper.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Generic;
2+
using System.Diagnostics.CodeAnalysis;
23
using System.Runtime.CompilerServices;
34

45
namespace Open.Collections.Synchronized;
@@ -11,41 +12,48 @@ public class LockSynchronizedDictionaryWrapper<TKey, TValue>
1112
public LockSynchronizedDictionaryWrapper(IDictionary<TKey, TValue> dictionary) : base(dictionary) { }
1213

1314
/// <inheritdoc />
15+
[ExcludeFromCodeCoverage]
1416
public virtual TValue this[TKey key]
1517
{
1618
get => InternalSource[key];
1719
set => InternalSource[key] = value;
1820
}
1921

2022
/// <inheritdoc />
23+
[ExcludeFromCodeCoverage]
2124
public virtual ICollection<TKey> Keys
2225
=> InternalSource.Keys;
2326

2427
/// <inheritdoc />
28+
[ExcludeFromCodeCoverage]
2529
public virtual ICollection<TValue> Values
2630
=> InternalSource.Values;
2731

28-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2932
/// <inheritdoc />
33+
[ExcludeFromCodeCoverage]
34+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3035
public virtual void Add(TKey key, TValue value)
3136
{
3237
lock(Sync) InternalSource.Add(key, value);
3338
}
3439

35-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3640
/// <inheritdoc />
41+
[ExcludeFromCodeCoverage]
42+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3743
public bool ContainsKey(TKey key)
3844
=> InternalSource.ContainsKey(key);
3945

40-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
4146
/// <inheritdoc />
47+
[ExcludeFromCodeCoverage]
48+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
4249
public virtual bool Remove(TKey key)
4350
{
4451
lock (Sync) return InternalSource.Remove(key);
4552
}
4653

47-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
4854
/// <inheritdoc />
55+
[ExcludeFromCodeCoverage]
56+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
4957
public bool TryGetValue(TKey key, out TValue value)
5058
=> InternalSource.TryGetValue(key, out value);
5159
}

0 commit comments

Comments
 (0)