• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zorbathut / dec / 11670896818

04 Nov 2024 07:02PM UTC coverage: 90.556%. Remained the same
11670896818

push

github

zorbathut
Removed redundant namespaces

4564 of 5040 relevant lines covered (90.56%)

191694.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.16
/src/WriterValidation.cs
1
using System;
2
using System.Collections;
3
using System.Collections.Generic;
4
using System.Text;
5

6
namespace Dec
7
{
8
    internal abstract class WriterValidation
9
    {
10
        private StringBuilder sb = new StringBuilder();
2,345✔
11

12
        internal Dictionary<object, string> referenceLookup = new Dictionary<object, string>();
2,345✔
13
        private WriterUtil.PendingWriteCoordinator pendingWriteCoordinator = new WriterUtil.PendingWriteCoordinator();
2,345✔
14

15
        public abstract bool AllowReflection { get; }
16
        public Recorder.IUserSettings UserSettings { get; }
8,785✔
17

18
        public WriterValidation(Recorder.IUserSettings userSettings)
2,345✔
19
        {
2,345✔
20
            UserSettings = userSettings;
2,345✔
21
        }
2,345✔
22

23
        public void AppendLine(string line)
24
        {
167,935✔
25
            sb.AppendLine(line);
167,935✔
26
        }
167,935✔
27

28
        public void RegisterPendingWrite(Action action)
29
        {
4,065✔
30
            pendingWriteCoordinator.RegisterPendingWrite(action);
4,065✔
31
        }
4,065✔
32

33
        public string Finish()
34
        {
2,345✔
35
            pendingWriteCoordinator.DequeuePendingWrites();
2,345✔
36

37
            return sb.ToString();
2,345✔
38
        }
2,345✔
39
    }
40

41
    internal class WriterValidationCompose : WriterValidation
42
    {
43
        public override bool AllowReflection { get => true; }
18,380✔
44

45
        public WriterValidationCompose(Recorder.IUserSettings userSettings) : base(userSettings)
1,870✔
46
        {
1,870✔
47
        }
1,870✔
48

49
        public WriterNode StartDec(Type type, string decName)
50
        {
7,235✔
51
            return new WriterNodeValidation(this, $"Dec.Database<{type.ComposeCSFormatted()}>.Get(\"{decName}\")");
7,235✔
52
        }
7,235✔
53
    }
54

55
    internal class WriterValidationRecord : WriterValidation
56
    {
57
        public override bool AllowReflection { get => false; }
×
58

59
        public WriterValidationRecord(Recorder.IUserSettings userSettings) : base(userSettings)
475✔
60
        {
475✔
61
        }
475✔
62

63
        public WriterNode StartData()
64
        {
475✔
65
            return new WriterNodeValidation(this, $"input");
475✔
66
        }
475✔
67
    }
68

69
    // This is used for things that can be expressed as an easy inline string, which is used as part of the Dictionary-handling code.
70
    internal abstract class WriterNodeCS : WriterNode
71
    {
72
        public WriterNodeCS() : base(new Recorder.Context())
150,215✔
73
        {
150,215✔
74
        }
150,215✔
75

76
        public abstract void WriteToken(string token);
77

78
        public override void WritePrimitive(object value)
79
        {
76,975✔
80
            if (value.GetType() == typeof(bool))
76,975✔
81
            {
11,245✔
82
                WriteToken(value.ToString().ToLower());
11,245✔
83
            }
11,245✔
84
            else if (value.GetType() == typeof(float))
65,730✔
85
            {
8,580✔
86
                var val = (float)value;
8,580✔
87
                if (float.IsNaN(val))
8,580✔
88
                {
15✔
89
                    WriteToken("float.NaN");
15✔
90
                }
15✔
91
                else if (float.IsPositiveInfinity(val))
8,565✔
92
                {
15✔
93
                    WriteToken("float.PositiveInfinity");
15✔
94
                }
15✔
95
                else if (float.IsNegativeInfinity(val))
8,550✔
96
                {
15✔
97
                    WriteToken("float.NegativeInfinity");
15✔
98
                }
15✔
99
                else
100
                {
8,535✔
101
                    WriteToken(((float)value).ToString("G17") + 'f');
8,535✔
102
                }
8,535✔
103
            }
8,580✔
104
            else if (value.GetType() == typeof(double))
57,150✔
105
            {
905✔
106
                var val = (double)value;
905✔
107
                if (double.IsNaN(val))
905✔
108
                {
685✔
109
                    WriteToken("double.NaN");
685✔
110
                }
685✔
111
                else if (double.IsPositiveInfinity(val))
220✔
112
                {
15✔
113
                    WriteToken("double.PositiveInfinity");
15✔
114
                }
15✔
115
                else if (double.IsNegativeInfinity(val))
205✔
116
                {
15✔
117
                    WriteToken("double.NegativeInfinity");
15✔
118
                }
15✔
119
                else
120
                {
190✔
121
                    WriteToken(((double)value).ToString("G17") + 'd');
190✔
122
                }
190✔
123
            }
905✔
124
            else
125
            {
56,245✔
126
                WriteToken(value.ToString());
56,245✔
127
            }
56,245✔
128
        }
76,975✔
129

130
        public override void WriteEnum(object value)
131
        {
65✔
132
            WriteToken($"{value.GetType().ComposeCSFormatted()}.{value}");
65✔
133
        }
65✔
134

135
        public override void WriteString(string value)
136
        {
9,035✔
137
            WriteToken($"\"{value}\"");
9,035✔
138
        }
9,035✔
139

140
        public override void WriteType(Type value)
141
        {
65✔
142
            WriteToken($"typeof({value.ComposeCSFormatted()})");
65✔
143
        }
65✔
144

145
        public override void WriteDec(Dec value)
146
        {
12,520✔
147
            if (value != null)
12,520✔
148
            {
1,245✔
149
                WriteToken($"Dec.Database<{value.GetType().ComposeCSFormatted()}>.Get(\"{value.DecName}\")");
1,245✔
150
            }
1,245✔
151
            else
152
            {
11,275✔
153
                WriteExplicitNull();
11,275✔
154
            }
11,275✔
155
        }
12,520✔
156
    }
157

158
    internal sealed class WriterNodeValidation : WriterNodeCS
159
    {
160
        private WriterValidation writer;
161
        private string accessor;
162

163
        public override bool AllowReflection { get => writer.AllowReflection; }
18,380✔
164
        public override Recorder.IUserSettings UserSettings { get => writer.UserSettings; }
8,785✔
165

166
        public WriterNodeValidation(WriterValidation writer, string accessor)
141,430✔
167
        {
141,430✔
168
            this.writer = writer;
141,430✔
169
            this.accessor = accessor;
141,430✔
170
        }
141,430✔
171

172
        public override WriterNode CreateRecorderChild(string label, Recorder.Context context)
173
        {
7,765✔
174
            return new WriterNodeValidation(writer, $"{accessor}.{label}");
7,765✔
175
        }
7,765✔
176

177
        public override WriterNode CreateReflectionChild(System.Reflection.FieldInfo field, Recorder.Context context)
178
        {
98,565✔
179
            if (field.IsPublic)
98,565✔
180
            {
98,545✔
181
                return new WriterNodeValidation(writer, $"{accessor}.{field.Name}");
98,545✔
182
            }
183
            else
184
            {
20✔
185
                return new WriterNodeValidation(writer, $"(({field.FieldType.ComposeCSFormatted()})typeof({field.DeclaringType.ComposeCSFormatted()}).GetField(\"{field.Name}\", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue({accessor}))");
20✔
186
            }
187
        }
98,565✔
188

189
        private void WriteIsEqual(string value)
190
        {
78,600✔
191
            writer.AppendLine($"Assert.AreEqual({value}, {accessor});");
78,600✔
192
        }
78,600✔
193

194
        public override void WriteToken(string token)
195
        {
78,600✔
196
            WriteIsEqual(token);
78,600✔
197
        }
78,600✔
198

199
        public override void TagClass(Type type)
200
        {
215✔
201
            FlagAsClass();
215✔
202

203
            if (type == typeof(Type))
215✔
204
            {
5✔
205
                // Special case: Sometimes we convert System.RuntimeType to System.Type, because System.RuntimeType is a compatible C# implementation detail that we don't want to preserve.
206
                // We handle that conversion here as well.
207
                writer.AppendLine($"Assert.IsTrue({accessor} is System.Type);");
5✔
208
            }
5✔
209
            else if (typeof(Dec).IsAssignableFrom(type))
210✔
210
            {
10✔
211
                // Decs are a little weird; sometimes we specify the root of a dec hierarchy with full expectation that it'll grab a child in that hierarchy.
212
                writer.AppendLine($"Assert.IsTrue(typeof({type.ComposeCSFormatted()}).IsAssignableFrom({accessor}.GetType()));");
10✔
213
            }
10✔
214
            else
215
            {
200✔
216
                writer.AppendLine($"Assert.AreEqual(typeof({type.ComposeCSFormatted()}), {accessor}.GetType());");
200✔
217
            }
200✔
218

219
            accessor = $"(({type.ComposeCSFormatted()}){accessor})";
215✔
220
        }
215✔
221

222
        public override void WriteExplicitNull()
223
        {
28,015✔
224
            writer.AppendLine($"Assert.IsNull({accessor});");
28,015✔
225
        }
28,015✔
226

227
        public override bool WriteReference(object value)
228
        {
25,290✔
229
            // We're just going to ignore whether a reference is "allowed" here; this is not the place for metavalidation.
230

231
            if (writer.referenceLookup.ContainsKey(value))
25,290✔
232
            {
105✔
233
                writer.AppendLine($"Assert.AreSame({writer.referenceLookup[value]}, {accessor});");
105✔
234
                return true;
105✔
235
            }
236
            else
237
            {
25,185✔
238
                writer.referenceLookup[value] = accessor;
25,185✔
239
                return false;
25,185✔
240
            }
241
        }
25,290✔
242

243
        public override void WriteRecord(IRecordable value)
244
        {
4,065✔
245
            // For performance's sake we shouldn't always be doing this.
246
            // But the validation layer is already incredibly slow and none of this is relevant in terms of performance anyway.
247
            // So, whatever.
248
            writer.RegisterPendingWrite(() => value.Record(new RecorderWriter(this)));
8,130✔
249
        }
4,065✔
250

251
        public override void WriteArray(Array value)
252
        {
150✔
253
            Type referencedType = value.GetType().GetElementType();
150✔
254

255
            // Maybe this should just be a giant AreEqual with a dynamically allocated array?
256
            writer.AppendLine($"Assert.AreEqual({accessor}.Length, {value.Length});");
150✔
257
            writer.AppendLine($"if ({accessor}.Length == {value.Length}) {{");
150✔
258

259
            for (int i = 0; i < value.Length; ++i)
1,630✔
260
            {
665✔
261
                Serialization.ComposeElement(new WriterNodeValidation(writer, $"{accessor}[{i}]"), value.GetValue(i), referencedType);
665✔
262
            }
665✔
263

264
            writer.AppendLine($"}}");
150✔
265
        }
150✔
266

267
        public override void WriteList(IList value)
268
        {
7,805✔
269
            Type referencedType = value.GetType().GetGenericArguments()[0];
7,805✔
270

271
            // Maybe this should just be a giant AreEqual with a dynamically allocated list?
272
            writer.AppendLine($"Assert.AreEqual({accessor}.Count, {value.Count});");
7,805✔
273
            writer.AppendLine($"if ({accessor}.Count == {value.Count}) {{");
7,805✔
274

275
            for (int i = 0; i < value.Count; ++i)
51,810✔
276
            {
18,100✔
277
                Serialization.ComposeElement(new WriterNodeValidation(writer, $"{accessor}[{i}]"), value[i], referencedType);
18,100✔
278
            }
18,100✔
279

280
            writer.AppendLine($"}}");
7,805✔
281
        }
7,805✔
282

283
        public override void WriteDictionary(IDictionary value)
284
        {
3,915✔
285
            Type keyType = value.GetType().GetGenericArguments()[0];
3,915✔
286
            Type valueType = value.GetType().GetGenericArguments()[1];
3,915✔
287

288
            writer.AppendLine($"Assert.AreEqual({accessor}.Count, {value.Count});");
3,915✔
289

290
            IDictionaryEnumerator iterator = value.GetEnumerator();
3,915✔
291
            while (iterator.MoveNext())
11,960✔
292
            {
8,045✔
293
                var keyNode = new WriterNodeStringize(UserSettings);
8,045✔
294
                Serialization.ComposeElement(keyNode, iterator.Key, keyType);
8,045✔
295

296
                writer.AppendLine($"if ({accessor}.ContainsKey({keyNode.SerializedString})) {{");
8,045✔
297
                Serialization.ComposeElement(new WriterNodeValidation(writer, $"{accessor}[{keyNode.SerializedString}]"), iterator.Value, valueType);
8,045✔
298
                writer.AppendLine($"}} else {{");
8,045✔
299
                writer.AppendLine($"Assert.IsTrue({accessor}.ContainsKey({keyNode.SerializedString}));");   // this is unnecessary - it could just be .Fail() - but this gives you a *much* better error message
8,045✔
300
                writer.AppendLine($"}}");
8,045✔
301
            }
8,045✔
302
        }
3,915✔
303

304
        public override void WriteHashSet(IEnumerable value)
305
        {
200✔
306
            Type keyType = value.GetType().GetGenericArguments()[0];
200✔
307

308
            int count = 0;
200✔
309
            IEnumerator iterator = value.GetEnumerator();
200✔
310
            while (iterator.MoveNext())
940✔
311
            {
740✔
312
                var keyNode = new WriterNodeStringize(UserSettings);
740✔
313
                Serialization.ComposeElement(keyNode, iterator.Current, keyType);
740✔
314

315
                // You might think "Assert.Contains" would do what we want, but it doesn't - it requires an ICollection and HashSet isn't an ICollection.
316
                writer.AppendLine($"Assert.IsTrue({accessor}.Contains({keyNode.SerializedString}));");
740✔
317

318
                ++count;
740✔
319
            }
740✔
320

321
            writer.AppendLine($"Assert.AreEqual({accessor}.Count, {count});");
200✔
322
        }
200✔
323

324
        public override void WriteQueue(IEnumerable value)
325
        {
10✔
326
            Type referencedType = value.GetType().GetGenericArguments()[0];
10✔
327

328
            var count = (int)value.GetType().GetProperty("Count").GetValue(value);
10✔
329

330
            // Maybe this should just be a giant AreEqual with a dynamically allocated list?
331
            writer.AppendLine($"Assert.AreEqual({accessor}.Count, {count});");
10✔
332
            writer.AppendLine($"if ({accessor}.Count == {count}) {{");
10✔
333

334
            // this is just easier
335
            writer.AppendLine($"var tempArray = new {referencedType.ComposeCSFormatted()}[{count}];");
10✔
336
            writer.AppendLine($"{accessor}.CopyTo(tempArray, 0);");
10✔
337

338
            // and meanwhile . . .
339
            var array = value.GetType().GetMethod("ToArray").Invoke(value, new object[] { }) as Array;
10✔
340

341
            for (int i = 0; i < count; ++i)
90✔
342
            {
35✔
343
                Serialization.ComposeElement(new WriterNodeValidation(writer, $"tempArray[{i}]"), array.GetValue(i), referencedType);
35✔
344
            }
35✔
345

346
            writer.AppendLine($"}}");
10✔
347
        }
10✔
348

349
        public override void WriteStack(IEnumerable value)
350
        {
10✔
351
            Type referencedType = value.GetType().GetGenericArguments()[0];
10✔
352

353
            var count = (int)value.GetType().GetProperty("Count").GetValue(value);
10✔
354

355
            // Maybe this should just be a giant AreEqual with a dynamically allocated list?
356
            writer.AppendLine($"Assert.AreEqual({accessor}.Count, {count});");
10✔
357
            writer.AppendLine($"if ({accessor}.Count == {count}) {{");
10✔
358

359
            // this is just easier
360
            writer.AppendLine($"var tempArray = new {referencedType.ComposeCSFormatted()}[{count}];");
10✔
361
            writer.AppendLine($"{accessor}.CopyTo(tempArray, 0);");
10✔
362

363
            // and meanwhile . . .
364
            var array = value.GetType().GetMethod("ToArray").Invoke(value, new object[] { }) as Array;
10✔
365

366
            for (int i = 0; i < count; ++i)
90✔
367
            {
35✔
368
                Serialization.ComposeElement(new WriterNodeValidation(writer, $"tempArray[{i}]"), array.GetValue(i), referencedType);
35✔
369
            }
35✔
370

371
            writer.AppendLine($"}}");
10✔
372
        }
10✔
373

374
        public override void WriteTuple(object value, System.Runtime.CompilerServices.TupleElementNamesAttribute names)
375
        {
65✔
376
            var args = value.GetType().GenericTypeArguments;
65✔
377
            var length = args.Length;
65✔
378

379
            var nameArray = names?.TransformNames ?? UtilMisc.DefaultTupleNames;
65✔
380

381
            for (int i = 0; i < length; ++i)
540✔
382
            {
205✔
383
                var propertyName = nameArray[i];
205✔
384
                Serialization.ComposeElement(new WriterNodeValidation(writer, $"{accessor}.{propertyName}"), value.GetType().GetProperty(UtilMisc.DefaultTupleNames[i]).GetValue(value), args[i]);
205✔
385
            }
205✔
386
        }
65✔
387

388
        public override void WriteValueTuple(object value, System.Runtime.CompilerServices.TupleElementNamesAttribute names)
389
        {
115✔
390
            var args = value.GetType().GenericTypeArguments;
115✔
391
            var length = args.Length;
115✔
392

393
            var nameArray = names?.TransformNames ?? UtilMisc.DefaultTupleNames;
115✔
394

395
            for (int i = 0; i < length; ++i)
840✔
396
            {
305✔
397
                var propertyName = nameArray[i];
305✔
398
                Serialization.ComposeElement(new WriterNodeValidation(writer, $"{accessor}.{propertyName}"), value.GetType().GetField(UtilMisc.DefaultTupleNames[i]).GetValue(value), args[i]);
305✔
399
            }
305✔
400
        }
115✔
401

402
        public override void WriteConvertible(Converter converter, object value)
403
        {
×
404
            // this isn't really a thing I can implement because the entire point of this is to compare the output to known values
405
            // and if we're going through Converter, we don't know what the underlying known values will be
406
            throw new NotImplementedException();
×
407
        }
408
    }
409

410
    // This is used solely for dict keys, because we want to get a reasonably-stringized version of this without having to jump through hideous hoops.
411
    internal sealed class WriterNodeStringize : WriterNodeCS
412
    {
413
        public override bool AllowReflection { get => false; }
×
414
        public override Recorder.IUserSettings UserSettings { get; }
×
415

416
        public string SerializedString { get; private set; }
42,445✔
417

418
        public WriterNodeStringize(Recorder.IUserSettings userSettings)
8,785✔
419
        {
8,785✔
420
            UserSettings = userSettings;
8,785✔
421
        }
8,785✔
422

423
        public override void WriteToken(string token)
424
        {
8,785✔
425
            if (SerializedString != null)
8,785✔
426
            {
×
427
                Dbg.Err("String is already set!");
×
428
            }
×
429

430
            SerializedString = token;
8,785✔
431
        }
8,785✔
432

433
        public override WriterNode CreateRecorderChild(string label, Recorder.Context context)
434
        {
×
435
            throw new NotImplementedException();
×
436
        }
437

438
        public override WriterNode CreateReflectionChild(System.Reflection.FieldInfo field, Recorder.Context context)
439
        {
×
440
            throw new NotImplementedException();
×
441
        }
442

443
        public override void TagClass(Type type)
444
        {
×
445
            throw new NotImplementedException();
×
446
        }
447

448
        public override void WriteExplicitNull()
449
        {
×
450
            throw new NotImplementedException();
×
451
        }
452

453
        public override bool WriteReference(object value)
454
        {
×
455
            throw new NotImplementedException();
×
456
        }
457

458
        public override void WriteRecord(IRecordable value)
459
        {
×
460
            throw new NotImplementedException();
×
461
        }
462

463
        public override void WriteArray(Array value)
464
        {
×
465
            throw new NotImplementedException();
×
466
        }
467

468
        public override void WriteList(IList value)
469
        {
×
470
            throw new NotImplementedException();
×
471
        }
472

473
        public override void WriteDictionary(IDictionary value)
474
        {
×
475
            throw new NotImplementedException();
×
476
        }
477

478
        public override void WriteHashSet(IEnumerable value)
479
        {
×
480
            throw new NotImplementedException();
×
481
        }
482

483
        public override void WriteStack(IEnumerable value)
484
        {
×
485
            throw new NotImplementedException();
×
486
        }
487

488
        public override void WriteQueue(IEnumerable value)
489
        {
×
490
            throw new NotImplementedException();
×
491
        }
492

493
        public override void WriteTuple(object value, System.Runtime.CompilerServices.TupleElementNamesAttribute names)
494
        {
×
495
            throw new NotImplementedException();
×
496
        }
497

498
        public override void WriteValueTuple(object value, System.Runtime.CompilerServices.TupleElementNamesAttribute names)
499
        {
×
500
            throw new NotImplementedException();
×
501
        }
502

503
        public override void WriteConvertible(Converter converter, object value)
504
        {
×
505
            throw new NotImplementedException();
×
506
        }
507
    }
508
}
509

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc