Verified Commit 7f0cb46b authored by Yorick Peterse's avatar Yorick Peterse 🌴

Reorganise and test std::time

std::time is now broken up into two modules:

1. std::time, which provides time related types.
2. std::time::duration, which provides the Duration type.

This separation allows for the use of module methods to construct a
Duration using different time units, instead of using methods defined on
Duration itself. This means that instead of this:

    import std::time::Duration

    Duration.from_seconds(5)

You now write this:

    import std::time::duration

    duration.from_seconds(5)

== Renaming MonotonicTime to Instant

MonotonicTime has been renamed to "Instant", which is a bit shorter and
much easier to type. A new method has been added as well: "elapsed".
This method can be used to measure the time that has elapsed since the
Instant was created.

== Adding and subtracting SystemTime and Instant

The methods + and - for SystemTime and Instant no longer accept a
ToFloat, instead they require a Duration. Accepting a ToFloat would
allow you to add a SystemTime to another SystemTime, or add an Instant
to an Instant. Neither make sense, so instead we now require the use of
a Duration. This means that instead of this:

    import std::time

    time.now + 5

You now have to write this:

    import std::time
    import std::time::duration

    time.now + duration.from_seconds(5)

== Tests

Finally, both std::time and std::time::duration have tests. These tests
uncovered a few bugs in the implementation of SystemTime, which have
been resolved.
parent f9c07ef6
Pipeline #41277834 passed with stages
in 15 minutes and 11 seconds
......@@ -3,7 +3,7 @@
#! The `Formatter` trait is used by a `Runner` to display test results as they
#! finish, and to display a summary once all tests have been executed.
import std::test::test::Test
import std::time::Duration
import std::time::duration::Duration
## A type for formatting the results of tests.
trait Formatter {
......
......@@ -10,7 +10,7 @@ import std::string_buffer::StringBuffer
import std::test::error::TestFailure
import std::test::formatter::Formatter
import std::test::test::Test
import std::time::Duration
import std::time::duration::Duration
## The minimum amount of time (in seconds) the test suite should run, before
## displaying the execution time in seconds.
......
......@@ -21,7 +21,8 @@ import std::process::(self, Receiver, Sender)
import std::test::config::Configuration
import std::test::formatter::Formatter
import std::test::test::Test
import std::time::(self, Duration)
import std::time
import std::time::duration
import std::vm
## The exit status to use if one or more tests failed to run.
......@@ -119,7 +120,7 @@ object RunTests impl Command {
## Once this method has been called, no new tests can be registered.
def run(state: RunnerState) {
let mut pending = 0
let start_time = time.monotonic
let start_time = time.instant
let last_index = state.tests.length - 1
let executed = []
let failed = []
......@@ -152,7 +153,7 @@ object RunTests impl Command {
}
}
let duration = Duration.from_seconds((time.monotonic - start_time).to_float)
let duration = start_time.elapsed
failed.empty?.if_false {
state.formatter.failures(failed)
......
This diff is collapsed.
#! Types for measuring the duration between two points in time.
import std::conversion::(ToFloat, ToInteger)
import std::operators::(Add, Subtract)
import std::operators::(Smaller, Greater, GreaterOrEqual, SmallerOrEqual, Equal)
import std::time::constants::*
## A span of time measured in seconds.
##
## A `Duration` can be used to measure the span of time without having to worry
## about casting the time to different scales yourself. A `Duration` can be
## created using various scales such as seconds and milliseconds.
object Duration impl
ToInteger,
ToFloat,
Add!(Self),
Subtract!(Self),
Smaller,
Greater,
SmallerOrEqual,
GreaterOrEqual {
def init(seconds: Float) {
let @seconds = seconds
}
## Returns the duration in seconds.
##
## # Examples
##
## Getting the seconds in a `Duration`:
##
## import std::time::duration
##
## duration.from_seconds(5).as_seconds # => 5.0
def as_seconds -> Float {
@seconds
}
## Returns the duration in milliseconds.
##
## # Examples
##
## Getting the milliseconds in a `Duration`:
##
## import std::time::duration
##
## duration.from_seconds(5).as_milliseconds # => 5000.0
def as_milliseconds -> Float {
@seconds * MILLISEC_TO_SEC
}
## Returns the duration in microseconds.
##
## # Examples
##
## Getting the microseconds in a `Duration`:
##
## import std::time::duration
##
## duration.from_seconds(5).as_microseconds # => 5000000.0
def as_microseconds -> Float {
@seconds * MICROSEC_TO_SEC
}
## Returns the duration in nanoseconds.
##
## # Examples
##
## Getting the nanoseconds in a `Duration`:
##
## import std::time::duration
##
## duration.from_seconds(5).as_nanoseconds # => 5000000000.0
def as_nanoseconds -> Float {
@seconds * NANOSEC_TO_SEC
}
## Returns the number of seconds in the `Duration`.
def to_integer -> Integer {
@seconds.to_integer
}
## Returns the number of seconds in the `Duration`.
def to_float -> Float {
@seconds
}
## Adds two `Duration` objects together.
##
## # Examples
##
## Adding two `Duration` objects:
##
## import std::time::duration
##
## let sum = duration.from_seconds(5) + duration.from_seconds(2)
##
## sum.as_seconds # => 7.0
def +(other: Self) -> Self {
Duration.new(@seconds + other.as_seconds)
}
## Subtracts the given `Duration` from `self`.
##
## # Examples
##
## Subtracting a `Duration` from another `Duration`
##
## import std::time::duration
##
## let diff = duration.from_seconds(5) - duration.from_seconds(2)
##
## diff.as_seconds # => 3.0
def -(other: Self) -> Self {
Duration.new(@seconds - other.as_seconds)
}
## Returns `True` if `self` is smaller than the given `Duration`.
##
## # Examples
##
## Comparing two `Duration` objects:
##
## import std::time::duration
##
## duration.from_seconds(5) < duration.from_seconds(10) # => True
def <(other: Self) -> Boolean {
@seconds < other.as_seconds
}
## Returns `True` if `self` is greater than the given `Duration`.
##
## # Examples
##
## Comparing two `Duration` objects:
##
## import std::time::duration
##
## duration.from_seconds(5) > duration.from_seconds(10) # => False
def >(other: Self) -> Boolean {
@seconds > other.as_seconds
}
## Returns `True` if `self` is smaller than or equal to the given `Duration`.
##
## # Examples
##
## Comparing two `Duration` objects:
##
## import std::time::duration
##
## duration.from_seconds(5) <= duration.from_seconds(10) # => True
## duration.from_seconds(5) <= duration.from_seconds(5) # => True
def <=(other: Self) -> Boolean {
@seconds <= other.as_seconds
}
## Returns `True` if `self` is greater than or equal to the given `Duration`.
##
## # Examples
##
## Comparing two `Duration` objects:
##
## import std::time::duration
##
## duration.from_seconds(5) >= duration.from_seconds(10) # => False
## duration.from_seconds(5) >= duration.from_seconds(5) # => True
def >=(other: Self) -> Boolean {
@seconds >= other.as_seconds
}
}
## Creates a new `Duration` from the given number of seconds.
##
## # Examples
##
## Creating a `Duration` using an `Integer`:
##
## import std::time::duration
##
## duration.from_seconds(10)
##
## Creating a `Duration` using a `Float`:
##
## import std::time::duration
##
## duration.from_seconds(10.5)
def from_seconds(seconds: ToFloat) -> Duration {
Duration.new(seconds.to_float)
}
## Creates a new `Duration` from the given number of milliseconds.
##
## # Examples
##
## Creating a `Duration` using an `Integer`:
##
## import std::time::duration
##
## duration.from_milliseconds(10)
##
## Creating a `Duration` using a `Float`:
##
## import std::time::duration
##
## duration.from_milliseconds(10.5)
def from_milliseconds(milliseconds: ToFloat) -> Duration {
Duration.new(milliseconds.to_float / MILLISEC_TO_SEC)
}
## Creates a new `Duration` from the given number of nanoseconds.
##
## # Examples
##
## Creating a `Duration` using an `Integer`:
##
## import std::time::duration
##
## duration.from_nanoseconds(10)
##
## Creating a `Duration` using a `Float`:
##
## import std::time::duration
##
## duration.from_nanoseconds(10.5)
def from_nanoseconds(nanoseconds: ToFloat) -> Duration {
Duration.new(nanoseconds.to_float / NANOSEC_TO_SEC)
}
......@@ -32,6 +32,8 @@ import test::std::test_process
import test::std::test_range
import test::std::test_string
import test::std::test_string_buffer
import test::std::test_time
import test::std::test_trait
import test::std::time::test_duration
test.run
import std::process::(self, Receiver, Sender)
import std::test
import std::test::assert
import std::time::MonotonicTime
import std::time::Instant
test.group('std::process::Sender.send') do (g) {
g.test('Sending a message to a process') {
......@@ -108,12 +108,12 @@ test.group('std::process.suspend') do (g) {
}
g.test('Suspending a process for a minimum amount of time') {
let start = MonotonicTime.new
let start = Instant.new
let wait = 0.01
process.suspend(wait)
let duration = (MonotonicTime.new - start).to_float
let duration = start.elapsed.to_float
assert.true(duration >= wait)
}
......
This diff is collapsed.
import std::test
import std::test::assert
import std::time::duration
import std::time::duration::Duration
test.group('std::time::duration::Duration.as_seconds') do (g) {
g.test('Converting a Duration to seconds') {
assert.equal(Duration.new(1.2).as_seconds, 1.2)
}
}
test.group('std::time::duration::Duration.as_milliseconds') do (g) {
g.test('Converting a Duration to milliseconds') {
assert.equal(Duration.new(1.2).as_milliseconds, 1200.0)
}
}
test.group('std::time::duration::Duration.as_microseconds') do (g) {
g.test('Converting a Duration to microseconds') {
assert.equal(Duration.new(1.2).as_microseconds, 1_200_000.0)
}
}
test.group('std::time::duration::Duration.as_nanoseconds') do (g) {
g.test('Converting a Duration to nanoseconds') {
assert.equal(Duration.new(1.2).as_nanoseconds, 1_200_000_000.0)
}
}
test.group('std::time::duration::Duration.to_integer') do (g) {
g.test('Converting a Duration to an Integer') {
assert.equal(Duration.new(1.2).to_integer, 1)
}
}
test.group('std::time::duration::Duration.to_float') do (g) {
g.test('Converting a Duration to a Float') {
assert.equal(Duration.new(1.2).to_float, 1.2)
}
}
test.group('std::time::duration::Duration.+') do (g) {
g.test('Adding two Durations together') {
let duration = Duration.new(1.0) + Duration.new(2.0)
assert.equal(duration.as_seconds, 3.0)
}
}
test.group('std::time::duration::Duration.-') do (g) {
g.test('Subtracting a Duration from another Duration') {
let duration = Duration.new(2.0) - Duration.new(0.5)
assert.equal(duration.as_seconds, 1.5)
}
}
test.group('std::time::duration::Duration.<') do (g) {
g.test('Checking if on Duration is shorter than another Duration') {
assert.true(Duration.new(1.0) < Duration.new(2.0))
assert.false(Duration.new(2.0) < Duration.new(1.0))
}
}
test.group('std::time::duration::Duration.>') do (g) {
g.test('Checking if on Duration is longer than another Duration') {
assert.true(Duration.new(2.0) > Duration.new(1.0))
assert.false(Duration.new(1.0) > Duration.new(2.0))
}
}
test.group('std::time::duration::Duration.<=') do (g) {
g.test('Checking if on Duration is shorter than or equal to another Duration') {
assert.true(Duration.new(1.0) <= Duration.new(2.0))
assert.true(Duration.new(1.0) <= Duration.new(1.0))
assert.false(Duration.new(2.0) <= Duration.new(1.0))
}
}
test.group('std::time::duration::Duration.>=') do (g) {
g.test('Checking if on Duration is longer than or equal to another Duration') {
assert.true(Duration.new(2.0) >= Duration.new(1.0))
assert.true(Duration.new(2.0) >= Duration.new(2.0))
assert.false(Duration.new(1.0) >= Duration.new(2.0))
}
}
test.group('std::time::duration.from_seconds') do (g) {
g.test('Creating a Duration using seconds as the unit of time') {
assert.equal(duration.from_seconds(5.0).as_seconds, 5.0)
}
}
test.group('std::time::duration.from_milliseconds') do (g) {
g.test('Creating a Duration using milliseconds as the unit of time') {
assert.equal(duration.from_milliseconds(500).as_seconds, 0.5)
}
}
test.group('std::time::duration.from_nanoseconds') do (g) {
g.test('Creating a Duration using nanoseconds as the unit of time') {
assert.equal(duration.from_nanoseconds(5_00_000_000).as_seconds, 0.5)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment