1 #region Copyright notice and license
2 // Protocol Buffers - Google's data interchange format
3 // Copyright 2015 Google Inc.  All rights reserved.
4 // https://developers.google.com/protocol-buffers/
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
8 // met:
9 //
10 //     * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 //     * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following disclaimer
14 // in the documentation and/or other materials provided with the
15 // distribution.
16 //     * Neither the name of Google Inc. nor the names of its
17 // contributors may be used to endorse or promote products derived from
18 // this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #endregion
32 
33 using NUnit.Framework;
34 using System;
35 
36 namespace Google.Protobuf.WellKnownTypes
37 {
38     public class DurationTest
39     {
40         [Test]
ToTimeSpan()41         public void ToTimeSpan()
42         {
43             Assert.AreEqual(TimeSpan.FromSeconds(1), new Duration { Seconds = 1 }.ToTimeSpan());
44             Assert.AreEqual(TimeSpan.FromSeconds(-1), new Duration { Seconds = -1 }.ToTimeSpan());
45             Assert.AreEqual(TimeSpan.FromMilliseconds(1), new Duration { Nanos = 1000000 }.ToTimeSpan());
46             Assert.AreEqual(TimeSpan.FromMilliseconds(-1), new Duration { Nanos = -1000000 }.ToTimeSpan());
47             Assert.AreEqual(TimeSpan.FromTicks(1), new Duration { Nanos = 100 }.ToTimeSpan());
48             Assert.AreEqual(TimeSpan.FromTicks(-1), new Duration { Nanos = -100 }.ToTimeSpan());
49 
50             // Rounding is towards 0
51             Assert.AreEqual(TimeSpan.FromTicks(2), new Duration { Nanos = 250 }.ToTimeSpan());
52             Assert.AreEqual(TimeSpan.FromTicks(-2), new Duration { Nanos = -250 }.ToTimeSpan());
53         }
54 
55         [Test]
Addition()56         public void Addition()
57         {
58             Assert.AreEqual(new Duration { Seconds = 2, Nanos = 100000000 },
59                 new Duration { Seconds = 1, Nanos = 600000000 } + new Duration { Nanos = 500000000 });
60             Assert.AreEqual(new Duration { Seconds = -2, Nanos = -100000000 },
61                 new Duration { Seconds = -1, Nanos = -600000000 } + new Duration { Nanos = -500000000 });
62             Assert.AreEqual(new Duration { Seconds = 1, Nanos = 100000000 },
63                 new Duration { Seconds = 1, Nanos = 600000000 } + new Duration { Nanos = -500000000 });
64 
65             // Non-normalized durations, or non-normalized intermediate results
66             Assert.AreEqual(new Duration { Seconds = 1 },
67                 new Duration { Seconds = 1, Nanos = -500000000 } + new Duration { Nanos = 500000000 });
68 
69             Assert.AreEqual(new Duration { Nanos = -900000000 },
70                 new Duration { Seconds = -1, Nanos = -100000000 } + new Duration { Nanos = 200000000 });
71             Assert.AreEqual(new Duration { Nanos = 900000000 },
72                 new Duration { Seconds = 1, Nanos = 100000000 } + new Duration { Nanos = -200000000 });
73         }
74 
75         [Test]
Subtraction()76         public void Subtraction()
77         {
78             Assert.AreEqual(new Duration { Seconds = 1, Nanos = 100000000 },
79                 new Duration { Seconds = 1, Nanos = 600000000 } - new Duration { Nanos = 500000000 });
80             Assert.AreEqual(new Duration { Seconds = -1, Nanos = -100000000 },
81                 new Duration { Seconds = -1, Nanos = -600000000 } - new Duration { Nanos = -500000000 });
82             Assert.AreEqual(new Duration { Seconds = 2, Nanos = 100000000 },
83                 new Duration { Seconds = 1, Nanos = 600000000 } - new Duration { Nanos = -500000000 });
84 
85             // Non-normalized durations
86             Assert.AreEqual(new Duration(),
87                 new Duration { Seconds = 1, Nanos = -500000000 } - new Duration { Nanos = 500000000 });
88             Assert.AreEqual(new Duration { Seconds = 1 },
89                 new Duration { Nanos = 2000000000 } - new Duration { Nanos = 1000000000 });
90         }
91 
92         [Test]
FromTimeSpan()93         public void FromTimeSpan()
94         {
95             Assert.AreEqual(new Duration { Seconds = 1 }, Duration.FromTimeSpan(TimeSpan.FromSeconds(1)));
96             Assert.AreEqual(new Duration { Nanos = Duration.NanosecondsPerTick }, Duration.FromTimeSpan(TimeSpan.FromTicks(1)));
97         }
98 
99         [Test]
100         [TestCase(0, Duration.MaxNanoseconds + 1)]
101         [TestCase(0, Duration.MinNanoseconds - 1)]
102         [TestCase(Duration.MinSeconds - 1, 0)]
103         [TestCase(Duration.MaxSeconds + 1, 0)]
104         [TestCase(1, -1)]
105         [TestCase(-1, 1)]
ToTimeSpan_Invalid(long seconds, int nanoseconds)106         public void ToTimeSpan_Invalid(long seconds, int nanoseconds)
107         {
108             var duration = new Duration { Seconds = seconds, Nanos = nanoseconds };
109             Assert.Throws<InvalidOperationException>(() => duration.ToTimeSpan());
110         }
111 
112         [Test]
113         [TestCase(0, Duration.MaxNanoseconds)]
114         [TestCase(0, Duration.MinNanoseconds)]
115         [TestCase(Duration.MinSeconds, Duration.MinNanoseconds)]
116         [TestCase(Duration.MaxSeconds, Duration.MaxNanoseconds)]
ToTimeSpan_Valid(long seconds, int nanoseconds)117         public void ToTimeSpan_Valid(long seconds, int nanoseconds)
118         {
119             // Only testing that these values don't throw, unlike their similar tests in ToTimeSpan_Invalid
120             var duration = new Duration { Seconds = seconds, Nanos = nanoseconds };
121             duration.ToTimeSpan();
122         }
123 
124         [Test]
ToString_NonNormalized()125         public void ToString_NonNormalized()
126         {
127             // Just a single example should be sufficient...
128             var duration = new Duration { Seconds = 1, Nanos = -1 };
129             Assert.AreEqual("{ \"@warning\": \"Invalid Duration\", \"seconds\": \"1\", \"nanos\": -1 }", duration.ToString());
130         }
131     }
132 }
133