habitat-cpp-connector/tests/test_rfc3339.py

277 wiersze
11 KiB
Python

# Copyright 2012 (C) Adam Greig, Daniel Richman
#
# This file is part of habitat.
#
# habitat is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# habitat is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with habitat. If not, see <http://www.gnu.org/licenses/>.
import os
import time
import subprocess
import json
from nose import SkipTest
# Identical to habitat's rfc3339 tests, except with a class that proxies
# calls to an executable and without the float tests.
class ProxyFunction(object):
def __init__(self, process, name):
self.p = process
self.name = name
def __call__(self, *args):
args = [self.name] + list(args)
self.p.stdin.write(json.dumps(args))
self.p.stdin.write("\n")
return json.loads(self.p.stdout.readline())
class ProxyFunctionModule(object):
# i.e., a module that contains functions only
def __init__(self, command, environ=None):
self.closed = False
self.p = subprocess.Popen(command, env=environ,
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
for n in ["validate_rfc3339", "rfc3339_to_timestamp",
"timestamp_to_rfc3339_utcoffset",
"timestamp_to_rfc3339_localoffset",
"now_to_rfc3339_utcoffset",
"now_to_rfc3339_localoffset"]:
setattr(self, n, ProxyFunction(self.p, n))
def close(self, quiet=False):
self.p.stdin.close()
ret = self.p.wait()
if not quiet:
assert ret == 0
def __del__(self):
if not self.closed:
self.close(True)
class TestValidateRFC3339(object):
def setup(self):
self.mod = ProxyFunctionModule("tests/rfc3339")
self.validate = self.mod.validate_rfc3339
def teardown(self):
self.mod.close()
def test_rejects_bad_format(self):
assert self.validate("asdf") == False
assert self.validate("24822") == False
assert self.validate("123-345-124T123:453:213") == False
assert self.validate("99-09-12T12:42:21Z") == False
assert self.validate("99-09-12T12:42:21+00:") == False
assert self.validate("99-09-12T12:42:21+00:00") == False
assert self.validate("2012-09-12T21:-1:21") == False
def test_rejects_no_offset(self):
assert self.validate("2012-09-12T12:42:21") == False
def test_rejects_out_of_range(self):
assert self.validate("2012-00-12T12:42:21Z") == False
assert self.validate("2012-13-12T12:42:21Z") == False
assert self.validate("2012-09-00T12:42:21Z") == False
assert self.validate("2012-09-31T12:42:21Z") == False # Sep
assert self.validate("2012-08-31T12:42:21Z") == True # Aug
assert self.validate("2012-08-32T12:42:21Z") == False
assert self.validate("2012-09-12T24:00:00Z") == False
assert self.validate("2012-09-12T12:60:21Z") == False
assert self.validate("2012-09-12T12:42:99Z") == False
assert self.validate("2012-09-12T12:42:21+24:00") == False
assert self.validate("2012-09-12T12:42:21-24:00") == False
assert self.validate("2012-09-12T12:42:21+02:60") == False
def test_rejects_leap_seconds(self):
# with regret :-(
assert self.validate("2012-06-30T23:59:60Z") == False
assert self.validate("2012-03-21T09:21:60Z") == False
def test_handles_leapyear(self):
assert self.validate("2012-02-29T12:42:21Z") == True
assert self.validate("2012-02-30T12:42:21Z") == False
assert self.validate("2000-02-29T12:42:21Z") == True
assert self.validate("2000-02-30T12:42:21Z") == False
assert self.validate("2100-02-28T12:42:21Z") == True
assert self.validate("2100-02-29T12:42:21Z") == False
assert self.validate("2011-02-28T12:42:21Z") == True
assert self.validate("2011-02-29T12:42:21Z") == False
def test_accepts_good(self):
assert self.validate("1994-03-14T17:00:00Z") == True
assert self.validate("2011-06-23T17:12:00+05:21") == True
assert self.validate("1992-03-14T17:04:00-01:42") == True
class TestRFC3339toTimestamp(object):
def setup(self):
self.mod = ProxyFunctionModule("tests/rfc3339")
self.func = self.mod.rfc3339_to_timestamp
def teardown(self):
self.mod.close()
def test_simple_cases(self):
assert self.func("1996-12-19T16:39:57-08:00") == 851042397
assert self.func("2012-08-08T21:30:36+01:00") == 1344457836
assert self.func("1994-03-14T17:00:00Z") == 763664400
assert self.func("1970-01-01T00:00:00Z") == 0
assert self.func("1970-01-01T01:20:34Z") == 4834
assert self.func("1969-12-31T23:59:59Z") == -1
assert self.func("1969-12-31T22:51:12Z") == -4128
def test_y2038(self):
assert self.func("2100-01-01T00:00:00Z") == 4102444800
assert self.func("1900-01-01T00:00:00Z") == -2208988800
def test_leap_year(self):
assert self.func("2012-02-29T12:42:21Z") == 1330519341
assert self.func("2000-02-29T23:59:59Z") == 951868799
assert self.func("2011-02-28T04:02:12Z") == 1298865732
assert self.func("2100-02-28T00:00:00Z") == 4107456000
assert self.func("1900-02-28T00:00:00Z") == -2203977600
def test_dst_transition(self):
assert self.func("2012-03-25T00:59:59+00:00") == 1332637199
assert self.func("2012-03-25T02:00:00+01:00") == 1332637200
assert self.func("2012-10-28T01:00:00+01:00") == 1351382400
assert self.func("2012-10-28T01:00:00+00:00") == 1351386000
def test_wacky_offset(self):
assert self.func("1996-12-19T16:39:57-02:52") == 851042397 - 18480
assert self.func("2012-08-08T21:30:36+23:11") == 1344457836 - 79860
def test_float(self):
assert self.func("1996-12-19T16:39:57.1234-08:00") == 851042397
assert self.func("1996-12-20T00:39:57.004Z") == 851042397
class TestTimestampToRFC3339UTCOffset(object):
def setup(self):
self.mod = ProxyFunctionModule("tests/rfc3339")
self.func = self.mod.timestamp_to_rfc3339_utcoffset
def teardown(self):
self.mod.close()
def test_simple_cases(self):
assert self.func(851042397) == "1996-12-20T00:39:57Z"
assert self.func(1344457836) == "2012-08-08T20:30:36Z"
assert self.func(763664400) == "1994-03-14T17:00:00Z"
assert self.func(0) == "1970-01-01T00:00:00Z"
assert self.func(4834) == "1970-01-01T01:20:34Z"
assert self.func(-1) == "1969-12-31T23:59:59Z"
assert self.func(-4128) == "1969-12-31T22:51:12Z"
def test_y2038(self):
try:
assert self.func(4102444800) == "2100-01-01T00:00:00Z"
assert self.func(-2208988800) == "1900-01-01T00:00:00Z"
except ValueError as e:
if str(e) == "timestamp out of range for platform time_t":
raise SkipTest("Can't run this test on 32 bit")
else:
raise
def test_leap_year(self):
assert self.func(1330519341) == "2012-02-29T12:42:21Z"
assert self.func(951868799) == "2000-02-29T23:59:59Z"
assert self.func(1298865732) == "2011-02-28T04:02:12Z"
try:
assert self.func(4107456000) == "2100-02-28T00:00:00Z"
assert self.func(-2203977600) == "1900-02-28T00:00:00Z"
except ValueError as e:
if str(e) == "timestamp out of range for platform time_t":
raise SkipTest("Can't run this test on 32 bit")
else:
raise
def test_now(self):
s = self.mod.now_to_rfc3339_utcoffset()
assert s[-1] == "Z"
assert len(s) == 20
d = int(time.time()) - self.mod.rfc3339_to_timestamp(s)
assert d == 0 or d == 1
class TestTimestampToRFC3339LocalOffsetLondon(object):
def setup(self):
environ = os.environ.copy()
environ["TZ"] = "Europe/London"
self.mod = ProxyFunctionModule("tests/rfc3339", environ=environ)
self.func = self.mod.timestamp_to_rfc3339_localoffset
def teardown(self):
self.mod.close()
def test_simple_cases(self):
assert self.func(851042397) == "1996-12-20T00:39:57+00:00"
assert self.func(1344457836) == "2012-08-08T21:30:36+01:00"
assert self.func(763664400) == "1994-03-14T17:00:00+00:00"
assert self.func(1340280000) == "2012-06-21T13:00:00+01:00"
assert self.func(1234) == "1970-01-01T01:20:34+01:00"
assert self.func(-7728) == "1969-12-31T22:51:12+01:00"
def test_dst_transition(self):
assert self.func(1332637199) == "2012-03-25T00:59:59+00:00"
assert self.func(1332637200) == "2012-03-25T02:00:00+01:00"
assert self.func(1351382400) == "2012-10-28T01:00:00+01:00"
assert self.func(1351386000) == "2012-10-28T01:00:00+00:00"
def test_now(self):
s = self.mod.now_to_rfc3339_localoffset()
w = self.mod.rfc3339_to_timestamp(s)
assert s[-6:] == ["+00:00", "+01:00"][time.localtime(w).tm_isdst]
d = int(time.time()) - w
assert d == 0 or d == 1
class TestTimestampToRFC3339LocalOffsetNewYork(object):
def setup(self):
environ = os.environ.copy()
environ["TZ"] = "America/New_York"
self.mod = ProxyFunctionModule("tests/rfc3339", environ=environ)
self.func = self.mod.timestamp_to_rfc3339_localoffset
def teardown(self):
self.mod.close()
def test_simple_cases(self):
assert self.func(851042397) == "1996-12-19T19:39:57-05:00"
assert self.func(1344457836) == "2012-08-08T16:30:36-04:00"
assert self.func(761245200) == "1994-02-14T12:00:00-05:00"
assert self.func(1340280000) == "2012-06-21T08:00:00-04:00"
assert self.func(19234) == "1970-01-01T00:20:34-05:00"
assert self.func(-4128) == "1969-12-31T17:51:12-05:00"
def test_dst_transition(self):
assert self.func(1331449199) == "2012-03-11T01:59:59-05:00"
assert self.func(1331449200) == "2012-03-11T03:00:00-04:00"
assert self.func(1352005200) == "2012-11-04T01:00:00-04:00"
assert self.func(1352008800) == "2012-11-04T01:00:00-05:00"
def test_now(self):
s = self.mod.now_to_rfc3339_localoffset()
w = self.mod.rfc3339_to_timestamp(s)
assert s[-6:] == ["-05:00", "-04:00"][time.localtime(w).tm_isdst]
d = int(time.time()) - w
assert d == 0 or d == 1