├── .appveyor.yml
├── .gitignore
├── .travis.yml
├── CREDITS
├── EXPERIMENTAL
├── LICENSE
├── README.md
├── circle.yml
├── config.m4
├── config.w32
├── package.xml
├── php-timecop.spec
├── php_timecop.h
├── stubs
└── Timecop.php
├── tc_timeval.c
├── tc_timeval.h
├── tests
├── core_001.phpt
├── core_002.phpt
├── core_003.phpt
├── core_004.phpt
├── core_005.phpt
├── core_006.phpt
├── core_007.phpt
├── core_008.phpt
├── core_009.phpt
├── core_010.phpt
├── core_011.phpt
├── core_012.phpt
├── core_013.phpt
├── date_001.phpt
├── date_002.phpt
├── date_003.phpt
├── date_004.phpt
├── date_005.phpt
├── date_006.phpt
├── date_007.phpt
├── date_008.phpt
├── date_override_001.phpt
├── date_override_002.phpt
├── date_override_003.phpt
├── date_override_006.phpt
├── date_override_007.phpt
├── date_override_008.phpt
├── func_001.phpt
├── func_002.phpt
├── func_003.phpt
├── func_004.phpt
├── func_005.phpt
├── func_006.phpt
├── func_007.phpt
├── func_008.phpt
├── func_009.phpt
├── func_010.phpt
├── func_011.phpt
├── func_012.phpt
├── func_013.phpt
├── func_014.phpt
├── func_override_001.phpt
├── func_override_002.phpt
├── func_override_003.phpt
├── func_override_004.phpt
├── func_override_005.phpt
├── func_override_006.phpt
├── func_override_007.phpt
├── func_override_008.phpt
├── func_override_009.phpt
├── func_override_010.phpt
├── func_override_011.phpt
├── func_override_012.phpt
├── func_override_013.phpt
├── func_override_014.phpt
├── immutable_001.phpt
├── immutable_002.phpt
├── immutable_003.phpt
├── immutable_004.phpt
├── immutable_005.phpt
├── immutable_006.phpt
├── immutable_007.phpt
├── immutable_008.phpt
├── immutable_override_001.phpt
├── immutable_override_006.phpt
├── immutable_override_007.phpt
├── immutable_override_008.phpt
├── issue_009.phpt
├── issue_010.phpt
├── issue_013.phpt
├── issue_014.phpt
└── tests-skipcheck.inc.php
├── timecop.php
├── timecop_php5.c
├── timecop_php7.c
└── wercker.yml
/.appveyor.yml:
--------------------------------------------------------------------------------
1 | version: '{branch}.{build}'
2 |
3 | environment:
4 | PROJECT_NAME: php-timecop
5 | REPORT_EXIT_STATUS: 1
6 | NO_INTERACTION: 1
7 | PHP_SDK_DIR: 'C:\projects\php-sdk'
8 | matrix:
9 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
10 | PHP_PACKAGE_URL: 'https://secure.php.net/distributions/php-5.4.45.tar.bz2'
11 | PHP_SDK_TOOLS_URL: 'http://windows.php.net/downloads/php-sdk/php-sdk-binary-tools-20110915.zip'
12 | PHP_SDK_DEPS_URL: 'http://windows.php.net/downloads/php-sdk/archives/deps-5.4-vc9-x86_2015-05.7z'
13 | VCVARS32_PATH: 'C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat'
14 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
15 | PHP_PACKAGE_URL: 'https://secure.php.net/distributions/php-5.6.29.tar.bz2'
16 | PHP_SDK_TOOLS_URL: 'http://windows.php.net/downloads/php-sdk/php-sdk-binary-tools-20110915.zip'
17 | PHP_SDK_DEPS_URL: 'http://windows.php.net/downloads/php-sdk/archives/deps-5.6-vc11-x86.7z'
18 | VCVARS32_PATH: 'C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\vcvars32.bat'
19 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
20 | PHP_PACKAGE_URL: 'https://secure.php.net/distributions/php-7.1.7.tar.bz2'
21 | PHP_SDK_TOOLS_URL: 'http://windows.php.net/downloads/php-sdk/php-sdk-binary-tools-20110915.zip'
22 | PHP_SDK_DEPS_URL: 'http://windows.php.net/downloads/php-sdk/archives/deps-7.1-vc14-x86.7z'
23 | VCVARS32_PATH: 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\vcvars32.bat'
24 | # - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
25 | # PHP_PACKAGE_URL: 'https://downloads.php.net/~pollita/php-7.2.0beta1.tar.bz2'
26 | # PHP_SDK_TOOLS_URL: 'https://github.com/OSTC/php-sdk-binary-tools/archive/php-sdk-2.0.7.zip'
27 | # PHP_SDK_DEPS_URL: 'http://windows.php.net/downloads/php-sdk/deps-master-vc15-x86.7z'
28 | # VCVARS32_PATH: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat'
29 |
30 | install:
31 | - cmd: >-
32 | set PROJECT_DIR=C:\projects\%PROJECT_NAME%
33 |
34 | set TEST_PHP_EXECUTABLE=%PROJECT_DIR%\bin\php.exe
35 |
36 | for /f %%F in ("%PHP_PACKAGE_URL%") do set PHP_PACKAGE_FILENAME=%%~nxF
37 |
38 | set PHP_SRC_DIR=C:\projects\%PHP_PACKAGE_FILENAME:.tar.bz2=%
39 |
40 | for /f %%F in ("%PHP_SDK_TOOLS_URL%") do set PHP_SDK_TOOLS_FILENAME=%%~nxF
41 |
42 | set PHP_SDK_TOOLS_SUBDIR=php-sdk-binary-tools-%PHP_SDK_TOOLS_FILENAME:.zip=%
43 |
44 | for /f %%F in ("%PHP_SDK_DEPS_URL%") do set PHP_SDK_DEPS_FILENAME=%%~nxF
45 |
46 | set TEST_PHP_EXECUTABLE=%PROJECT_DIR%\bin\php.exe
47 |
48 | choco feature enable -n=allowGlobalConfirmation
49 |
50 | cinst wget
51 |
52 | mkdir %PROJECT_DIR%\bin
53 |
54 | build_script:
55 | - cmd: >-
56 | echo %APPVEYOR_BUILD_WORKER_IMAGE%
57 |
58 | echo %PROJECT_DIR%
59 |
60 | echo %TEST_PHP_EXECUTABLE%
61 |
62 | "%VCVARS32_PATH%"
63 |
64 | wget --no-check-certificate %PHP_PACKAGE_URL%
65 |
66 | 7z x -so %PHP_PACKAGE_FILENAME% | 7z x -si -ttar -oC:\projects\
67 |
68 | wget --no-check-certificate %PHP_SDK_TOOLS_URL%
69 |
70 | 7z x -y %PHP_SDK_TOOLS_FILENAME% -o%PHP_SDK_DIR%
71 |
72 | if exist %PHP_SDK_DIR%\%PHP_SDK_TOOLS_SUBDIR% ( cd %PHP_SDK_DIR%\%PHP_SDK_TOOLS_SUBDIR% ) else ( cd %PHP_SDK_DIR% )
73 |
74 | dir
75 |
76 | bin\phpsdk_setvars.bat
77 |
78 | mkdir %PHP_SRC_DIR%\ext\%PROJECT_NAME%
79 |
80 | xcopy %PROJECT_DIR% %PHP_SRC_DIR%\ext\%PROJECT_NAME% /s /e /y
81 |
82 | wget --no-check-certificate %PHP_SDK_DEPS_URL%
83 |
84 | 7z x -y %PHP_SDK_DEPS_FILENAME% -o%PHP_SRC_DIR%
85 |
86 | cd %PHP_SRC_DIR%
87 |
88 | buildconf.bat
89 |
90 | rem "Build failed with '--enable-zip' on PHP 7.2.0 beta1"
91 |
92 | configure.bat --disable-all --enable-phar --enable-json --enable-hash --enable-ctype --enable-filter --enable-tokenizer --with-iconv --with-openssl --with-dom --with-libxml --enable-zip --enable-timecop=shared --enable-cli --enable-zts --with-config-file-scan-dir=%PROJECT_DIR%\bin\modules.d --with-prefix=%PROJECT_DIR%\bin --with-php-build=deps
93 |
94 | nmake
95 |
96 | nmake install
97 |
98 | copy php.ini-development %PROJECT_DIR%\bin\php.ini
99 |
100 | mkdir %PROJECT_DIR%\bin\modules.d
101 |
102 | echo extension=php_timecop.dll >> %PROJECT_DIR%\bin\modules.d\php.ini
103 |
104 | test_script:
105 | - cmd: >-
106 | echo %PROJECT_DIR%
107 |
108 | echo %TEST_PHP_EXECUTABLE%
109 |
110 | cd %PROJECT_DIR%
111 |
112 | if exist bin dir bin
113 |
114 | if exist bin\ext dir bin\ext
115 |
116 | if exist bin\modules.d dir bin\modules.d
117 |
118 | "%TEST_PHP_EXECUTABLE%" %PHP_SRC_DIR%\run-tests.php --show-diff
119 |
120 | exit /b %errorlevel%
121 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore automatically created files in building PHP extensions
2 | .deps
3 | .libs
4 | Makefile
5 | Makefile.fragments
6 | Makefile.global
7 | Makefile.objects
8 | acinclude.m4
9 | aclocal.m4
10 | autom4te.cache
11 | build
12 | config.guess
13 | config.h
14 | config.h.in
15 | config.log
16 | config.nice
17 | config.status
18 | config.sub
19 | configure
20 | configure.in
21 | install-sh
22 | libtool
23 | ltmain.sh
24 | ltmain.sh.backup
25 | missing
26 | mkinstalldirs
27 | modules
28 | run-tests.php
29 |
30 | # Ignore generated tarball
31 | timecop-*.tgz
32 |
33 | # Ignore test-related temporary files
34 | tmp-php.ini
35 | tests/*.diff
36 | tests/*.exp
37 | tests/*.log
38 | tests/*.php
39 | tests/*.sh
40 | tests/*.out
41 |
42 | # Ignore C-related temporary files
43 | *.o
44 | *.lo
45 | *.la
46 |
47 | # Ignore other temporary files
48 | #*#
49 | .*.rej
50 | *.rej
51 | .*~
52 | *~
53 | .#*
54 | .DS_Store
55 | Thumbs.db
56 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: php
3 | dist: xenial
4 |
5 | matrix:
6 | include:
7 | - dist: trusty
8 | php: 5.4
9 | - dist: trusty
10 | php: 5.5
11 | allow_failures:
12 | - php: master
13 |
14 | branches:
15 | except:
16 | - gh-pages
17 | - /^circleci-.*$/
18 | - /^wercker-.*$/
19 |
20 | php:
21 | - 5.6
22 | - 7.0
23 | - 7.1
24 | - 7.2
25 | - 7.3
26 | - master
27 |
28 | before_script:
29 | - phpize && ./configure && make
30 |
31 | script:
32 | - make test REPORT_EXIT_STATUS=1 NO_INTERACTION=1 TESTS="--show-all" | tee tests-output.txt && if grep -q 'TEST SUMMARY$' tests-output.txt ; then exit 1 ; fi
33 |
--------------------------------------------------------------------------------
/CREDITS:
--------------------------------------------------------------------------------
1 | timecop
2 |
--------------------------------------------------------------------------------
/EXPERIMENTAL:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hnw/php-timecop/3efe135ba5c34f22f2c08a7874e922b8173ccbb1/EXPERIMENTAL
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2012-2017 Yoshio HANAWA
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # php-timecop [](https://travis-ci.org/hnw/php-timecop) [](https://circleci.com/gh/hnw/php-timecop) [](https://app.wercker.com/project/bykey/bb9856dda9b2ced0bbfa44d50d7fc034)[](https://ci.appveyor.com/project/hnw/php-timecop/branch/master)
2 |
3 | ## DESCRIPTION
4 |
5 | A PHP extension providing "time travel" and "time freezing" capabilities, inspired by [ruby timecop gem](https://github.com/travisjeffery/timecop).
6 |
7 | ## INSTALL (with package manager)
8 |
9 | If you are using macOS, you can install php-timecop with [Homebrew](https://brew.sh/) .
10 |
11 | ```
12 | brew install homebrew/php/php71-timecop
13 | ```
14 |
15 | In Fedora, you can install php-timecop from official repository as php-pecl-timecop
16 | ```
17 | sudo dnf install php-pecl-timecop
18 | ```
19 |
20 | In RHEL/CentOS, you can install php-timecop from [Remi's RPM repository](https://rpms.remirepo.net/).
21 |
22 | ```
23 | sudo yum install http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
24 | sudo yum install yum-utils
25 | sudo yum-config-manager --enable remi-php71
26 | sudo yum install php-pecl-timecop
27 | ```
28 |
29 | Otherwise, you can use pecl command to install php-timecop.
30 |
31 | ```
32 | pecl install timecop-beta
33 | ```
34 |
35 | ## INSTALL (with phpize)
36 |
37 | ```
38 | git clone https://github.com/hnw/php-timecop.git
39 | cd php-timecop
40 | phpize
41 | ./configure
42 | make
43 | make install
44 | ```
45 |
46 | After install, add these lines to your `php.ini` .
47 |
48 | ```ini
49 | extension=timecop.so
50 | ```
51 |
52 | ## INSTALL (on Windows, experimental)
53 |
54 | You can download the extension DLL from [PECL :: Package :: timecop](https://pecl.php.net/package/timecop)
55 |
56 | To install the extension, extract zip and copy `php_timecop.dll` to the extension directory.
57 |
58 | After install, add these lines to your `php.ini` .
59 |
60 | ```ini
61 | extension=php_timecop.dll
62 | ```
63 |
64 | ## SYSTEM REQUIREMENTS
65 |
66 | - OS: Windows(experimental), Linux, macOS
67 | - PHP: 5.3.1 - 7.2.x (might work on 5.2.x and 5.3.0, but not tested enough)
68 | - SAPI: Apache, CLI
69 | - Other SAPIs are not tested, but there is no SAPI-dependent code.
70 | - non-ZTS(recommended), ZTS
71 |
72 | ## FEATURES
73 |
74 | - Freeze time to a specific point.
75 | - Travel back to a specific point in time, but allow time to continue moving forward from there.
76 | - Scale time by a given scaling factor that will cause time to move at an accelerated pace.
77 | - Override the following PHP stock functions and methods, which supports freezing or traveling time.
78 | - `time()`
79 | - `mktime()`
80 | - `gmmktime()`
81 | - `date()`
82 | - `gmdate()`
83 | - `idate()`
84 | - `getdate()`
85 | - `localtime()`
86 | - `strtotime()`
87 | - `strftime()`
88 | - `gmstrftime()`
89 | - `microtime()`
90 | - `gettimeofday()`
91 | - `unixtojd()`
92 | - `DateTime::_construct()`
93 | - `DateTime::createFromFormat()` (PHP >= 5.3.0)
94 | - `DateTimeImmutable::_construct()` (PHP >= 5.5.0)
95 | - `DateTimeImmutable::createFromFormat()` (PHP >= 5.5.0)
96 | - `date_create()`
97 | - `date_create_from_format()` (PHP >= 5.3.0)
98 | - `date_create_immutable()` (PHP >= 5.5.0)
99 | - `date_create_immutable_from_format()` (PHP >= 5.5.0)
100 | - Rewrite value of the following global variables when the time has been moved.
101 | - `$_SERVER['REQUEST_TIME']`
102 |
103 | ## USAGE
104 |
105 | ```php
106 | format("c")); // string(25) "2017-01-01T00:00:05+00:00"
141 | ```
142 |
143 | ## CHANGELOG
144 |
145 | ### version 1.2.10(beta), 2017/11/23
146 |
147 | - Fix "double free" bug on PHP 7.2.0 ([#32](https://github.com/hnw/php-timecop/issues/32))
148 |
149 | ### version 1.2.8(beta), 2017/7/7
150 |
151 | - Publish on PECL
152 | - Support Windows (experimental)
153 |
154 | ### version 1.2.6(beta), 2017/7/4
155 |
156 | - Bug fixed: Calling timecop_freeze() on a fast machine sometimes fails to stop the microsecond part of current time.
157 | - Support PHP 7.2.0+
158 |
159 | ### version 1.2.4(beta), 2017/6/8
160 |
161 | - Fix [#18](https://github.com/hnw/php-timecop/issues/18) (Fix date_create_from_format when using `|` char)
162 | - Fix `timecop_date_create()`: The previous version of `timecop_date_create("@[unix timestamp]")` returns +1 hour time on PHP 5.3.9 - 5.4.7 only during the DST.
163 |
164 | ### version 1.2.3(beta), 2017/1/8
165 | - Fix `timecop_date_create_from_format()`: support time travelling
166 | - Now portions of the generated time not provided in `format` will be set to the travelled time
167 | - The previous version is completely same behavior as `date_create_from_format()`.
168 | - Remove `TimecopDateTime::getTimestamp()`, `TimecopDateTime::setTimestamp()` on PHP 5.2.x
169 |
170 | ### version 1.2.2(alpha), 2017/1/4
171 | - Implement `TimecopDateTimeImmutable` class and `timecop_date_create_immutable()`, `timecop_date_create_immutable_from_format()` functions.
172 | - Now `timecop_date_create_from_format()` returns `DateTime` instance
173 |
174 | ### version 1.2.0(alpha), 2016/12/30
175 | - Big internal change (without BC break): handle microseconds accurately in time traveling.
176 | - Now `timecop_freeze()` and `timecop_travel()` accepts either `DateTimeInterface` or `int`.
177 | - With `DateTimeInterface` argument, freezed/traveled time would have fraction of second.
178 | - Implement `timecop_scale()`: Make time go faster.
179 | - Implement `Timecop::***()` as alias of `timecop_***()`. (For `freeze`, `travel`, `return`, `scale`)
180 |
181 | ### version 1.1.3, 2016/12/27
182 | - Fix crash when non-object passed as 2nd argument of TimecopDateTime::__construct() (Fix [#9](https://github.com/hnw/php-timecop/issues/9))'
183 | - Add CI environment (CentOS, Ubuntu 32-bit, PHP 7.1)
184 |
185 | ### version 1.1.2(alpha), 2016/04/23
186 | - Fix for stock PHP on Ubuntu
187 |
188 | ### version 1.1.0(alpha), 2016/04/18
189 | - Support PHP 7.0.x
190 | - Now `new DateTime()` always returns `DateTime` instance
191 | - The previous version returns `TimecopDateTime` instance when `timecop.func_override=1`.
192 | - Implement `timecop_gettimeofday()` and `timecop_microtime()`
193 |
194 | ### version 1.0.6, 2016/04/15
195 | - Fix #10 (Timecop segfaults when set_error_handler throws an exception)
196 |
197 | ### version 1.0.5, 2013/11/26
198 | - Fix `TimecopDateTime::createFromFormat()` to reutrn `TimecopDateTime` instance on PHP >= 5.3.4
199 | - The previous version returns `DateTime` instance
200 | - Implement identical function `timecop_date_create_from_format()`
201 | - BUG: not supporting "relative formats" for this method currently.
202 | - Fix behavior of `TimecopDateTime::_construct()` when its 2nd argument is specified.
203 |
204 | ### version 1.0.4, 2013/03/11
205 | - Fix SIGSEGV in `TimecopDateTime::__construct()` called with NULL as 1st argument
206 |
207 | ### version 1.0.3, 2013/03/09
208 |
209 | - Fix the time traveling implementation for `TimecopDateTime::__construct()`
210 | - Fix `timecop_date_create()` to return `TimecopDateTime` instance
211 | - The previous version returns `DateTime` instance
212 | - Add `TimecopDateTime::getTimestamp()`, `TimecopDateTime::setTimestamp()` only for PHP 5.2.x
213 |
214 | ### version 1.0.2, 2013/03/06
215 |
216 | - Implement `timecop_date_create()`
217 |
218 | ### Version 1.0.1, 2013/03/04
219 |
220 | - Implement time traveling feature for `TimecopDateTime::__construct()` with 1 or 2 arguments
221 | - The previous version works correctly only for no arguments calling: "new TimecopDateTime()"
222 |
223 | ### version 1.0.0, 2012/11/21
224 |
225 | - Fix memory leak
226 |
227 | ### version 0.0.1, 2012/06/19
228 |
229 | - Initial Release
230 |
231 | ## LICENSE
232 | #
233 | The MIT License
234 |
235 | Copyright (c) 2012-2017 Yoshio HANAWA
236 |
237 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
238 |
239 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
240 |
241 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
242 |
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
1 | general:
2 | branches:
3 | ignore:
4 | - gh-pages
5 | - /^travisci-.*$/
6 | - /^wercker-.*$/
7 |
8 | dependencies:
9 | pre:
10 | - case $CIRCLE_NODE_INDEX in 0) sudo apt-get update; sudo apt-get install php5-dev; phpenv global system ;; 1) phpenv global 5.6.22 ;; 2) phpenv global 7.0.11 ;; 3) phpenv global 7.1.9 ;; esac
11 | - phpenv versions
12 | - phpize && ./configure && make
13 |
14 | test:
15 | override:
16 | - make test REPORT_EXIT_STATUS=1 NO_INTERACTION=1 TESTS="--show-all" | tee tests-output.txt && if grep -q 'TEST SUMMARY$' tests-output.txt ; then exit 1 ; fi:
17 | parallel: true
18 |
--------------------------------------------------------------------------------
/config.m4:
--------------------------------------------------------------------------------
1 | dnl $Id$
2 | dnl config.m4 for extension timecop
3 |
4 | dnl Comments in this file start with the string 'dnl'.
5 | dnl Remove where necessary. This file will not work
6 | dnl without editing.
7 |
8 | dnl If your extension references something external, use with:
9 |
10 | dnl PHP_ARG_WITH(timecop, for timecop support,
11 | dnl Make sure that the comment is aligned:
12 | dnl [ --with-timecop Include timecop support])
13 |
14 | dnl Otherwise use enable:
15 |
16 | PHP_ARG_ENABLE(timecop, whether to enable timecop support,
17 | [ --enable-timecop Enable timecop support])
18 |
19 | if test "$PHP_TIMECOP" != "no"; then
20 |
21 | dnl Check PHP version:
22 | AC_MSG_CHECKING(PHP version)
23 | if test ! -z "$phpincludedir"; then
24 | PHP_VERSION=`grep 'PHP_VERSION ' $phpincludedir/main/php_version.h | sed -e 's/.*"\([[0-9]]*\.[[0-9]]*\.[[0-9]]*.*\)".*/\1/g' 2>/dev/null`
25 | elif test ! -z "$PHP_CONFIG"; then
26 | PHP_VERSION=`$PHP_CONFIG --version 2>/dev/null`
27 | fi
28 |
29 | if test x"$PHP_VERSION" = "x"; then
30 | AC_MSG_WARN([not found])
31 | else
32 | PHP_MAJOR_VERSION=`echo $PHP_VERSION | sed -e 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/g' 2>/dev/null`
33 | PHP_MINOR_VERSION=`echo $PHP_VERSION | sed -e 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/g' 2>/dev/null`
34 | PHP_RELEASE_VERSION=`echo $PHP_VERSION | sed -e 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/g' 2>/dev/null`
35 | AC_MSG_RESULT([$PHP_VERSION])
36 | fi
37 |
38 | if test "$PHP_MAJOR_VERSION" -eq 5; then
39 | PHP_NEW_EXTENSION(timecop, timecop_php5.c tc_timeval.c, $ext_shared)
40 | else
41 | PHP_NEW_EXTENSION(timecop, timecop_php7.c tc_timeval.c, $ext_shared)
42 | fi
43 | fi
44 |
--------------------------------------------------------------------------------
/config.w32:
--------------------------------------------------------------------------------
1 | // $Id$
2 | // vim:ft=javascript
3 |
4 | ARG_ENABLE("timecop", "enable timecop support", "no");
5 |
6 | if (PHP_TIMECOP != "no") {
7 | if (PHP_VERSION <= 5) {
8 | EXTENSION("timecop", "timecop_php5.c tc_timeval.c");
9 | } else {
10 | EXTENSION("timecop", "timecop_php7.c tc_timeval.c");
11 | }
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | timecop
4 | pecl.php.net
5 |
6 | A PHP extension providing "time travel" capabilities.
7 |
8 |
9 | A PHP extension providing "time travel" and "time freezing" capabilities, inspired by ruby timecop gem.
10 |
11 |
12 | Yoshio HANAWA
13 | hnw
14 | y@hnw.jp
15 | yes
16 |
17 | 2017-11-23
18 |
19 | 1.2.10
20 | 1.2.10
21 |
22 |
23 | beta
24 | beta
25 |
26 | MIT License
27 | Fix "double free" bug on PHP 7.2.0
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 | 5.3.1
122 |
123 |
124 | 1.4.8
125 |
126 |
127 |
128 | timecop
129 |
130 |
131 |
--------------------------------------------------------------------------------
/php-timecop.spec:
--------------------------------------------------------------------------------
1 | %define __ext_name timecop
2 | Name: php-%{__ext_name}
3 | Version: 1.2.7
4 | Release: 1%{?dist}
5 | Summary: php-timecop module
6 |
7 | Group: Development/Languages
8 | License: MIT
9 | URL: https://github.com/hnw/php-timecop
10 | Source0: https://github.com/hnw/php-timecop/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz
11 | BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
12 |
13 | BuildRequires: php, php-devel
14 | Requires: php
15 | Requires: php(api) = %{php_core_api}
16 |
17 | %description
18 | A PHP extension providing "time travel" and "time freezing" capabilities,
19 | inspired by ruby timecop gem(https://github.com/travisjeffery/timecop).
20 |
21 | %prep
22 | %setup -q
23 | cat > %{__ext_name}.ini << 'EOF'
24 | ; Enable %{__ext_name} extension module
25 | extension = %{__ext_name}.so
26 |
27 | EOF
28 |
29 | %build
30 | phpize
31 | %configure
32 | make %{?_smp_mflags}
33 | make test REPORT_EXIT_STATUS=1 NO_INTERACTION=1 TESTS="--show-all" | tee tests-output.txt && if grep -q 'TEST SUMMARY$' tests-output.txt ; then exit 1 ; fi
34 |
35 | %install
36 | rm -rf %{buildroot}
37 | make install INSTALL_ROOT=%{buildroot}
38 | install -D -m 644 %{__ext_name}.ini %{buildroot}%{_sysconfdir}/php.d/%{__ext_name}.ini
39 |
40 |
41 | %clean
42 | rm -rf %{buildroot}
43 |
44 |
45 | %files
46 | %defattr(-,root,root,-)
47 | %config(noreplace) %{_sysconfdir}/php.d/%{__ext_name}.ini
48 | %{php_extdir}/%{__ext_name}.so
49 |
50 |
51 |
52 |
53 | %changelog
54 | * Wed Jun 11 2014 withgod
55 | - created
56 |
--------------------------------------------------------------------------------
/php_timecop.h:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2012-2017 Yoshio HANAWA
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 |
25 | #ifndef PHP_TIMECOP_H
26 | #define PHP_TIMECOP_H
27 |
28 | #define PHP_TIMECOP_VERSION "1.2.10"
29 |
30 | extern zend_module_entry timecop_module_entry;
31 | #define phpext_timecop_ptr &timecop_module_entry
32 |
33 | #ifdef PHP_WIN32
34 | # define PHP_TIMECOP_API __declspec(dllexport)
35 | #elif defined(__GNUC__) && __GNUC__ >= 4
36 | # define PHP_TIMECOP_API __attribute__ ((visibility("default")))
37 | #else
38 | # define PHP_TIMECOP_API
39 | #endif
40 |
41 | #ifdef ZTS
42 | #include "TSRM.h"
43 | #endif
44 |
45 | #ifndef PHP_WIN32
46 | #include
47 | #else
48 | #include "win32/time.h"
49 | #endif
50 |
51 | #include "Zend/zend_interfaces.h"
52 | #include "tc_timeval.h"
53 |
54 | PHP_MINIT_FUNCTION(timecop);
55 | PHP_MSHUTDOWN_FUNCTION(timecop);
56 | PHP_RINIT_FUNCTION(timecop);
57 | PHP_RSHUTDOWN_FUNCTION(timecop);
58 | PHP_MINFO_FUNCTION(timecop);
59 |
60 | PHP_FUNCTION(timecop_freeze);
61 | PHP_FUNCTION(timecop_travel);
62 | PHP_FUNCTION(timecop_scale);
63 | PHP_FUNCTION(timecop_return);
64 | PHP_FUNCTION(timecop_time);
65 | PHP_FUNCTION(timecop_mktime);
66 | PHP_FUNCTION(timecop_gmmktime);
67 | PHP_FUNCTION(timecop_date);
68 | PHP_FUNCTION(timecop_gmdate);
69 | PHP_FUNCTION(timecop_idate);
70 | PHP_FUNCTION(timecop_getdate);
71 | PHP_FUNCTION(timecop_localtime);
72 | PHP_FUNCTION(timecop_strtotime);
73 | PHP_FUNCTION(timecop_strftime);
74 | PHP_FUNCTION(timecop_gmstrftime);
75 | #ifdef HAVE_GETTIMEOFDAY
76 | PHP_FUNCTION(timecop_microtime);
77 | PHP_FUNCTION(timecop_gettimeofday);
78 | #endif
79 | PHP_FUNCTION(timecop_unixtojd);
80 | PHP_FUNCTION(timecop_date_create);
81 | PHP_FUNCTION(timecop_date_create_from_format);
82 | #if PHP_VERSION_ID >= 50500
83 | PHP_FUNCTION(timecop_date_create_immutable);
84 | PHP_FUNCTION(timecop_date_create_immutable_from_format);
85 | #endif
86 | #if !defined(PHP_VERSION_ID) || PHP_VERSION_ID < 50300
87 | PHP_FUNCTION(date_timestamp_set);
88 | PHP_FUNCTION(date_timestamp_get);
89 | #endif
90 |
91 | PHP_METHOD(TimecopDateTime, __construct);
92 | PHP_METHOD(TimecopOrigDateTime, __construct);
93 |
94 | #if PHP_VERSION_ID >= 50500
95 | PHP_METHOD(TimecopDateTimeImmutable, __construct);
96 | PHP_METHOD(TimecopOrigDateTimeImmutable, __construct);
97 | #endif
98 |
99 | PHP_METHOD(Timecop, freeze);
100 | PHP_METHOD(Timecop, travel);
101 |
102 | typedef enum timecop_mode_t {
103 | TIMECOP_MODE_REALTIME,
104 | TIMECOP_MODE_FREEZE,
105 | TIMECOP_MODE_TRAVEL
106 | } timecop_mode_t;
107 |
108 | ZEND_BEGIN_MODULE_GLOBALS(timecop)
109 | long func_override;
110 | long sync_request_time;
111 | #if PHP_VERSION_ID >= 70000
112 | zval orig_request_time;
113 | #else
114 | zval *orig_request_time;
115 | #endif
116 | timecop_mode_t timecop_mode;
117 | tc_timeval freezed_time;
118 | tc_timeval travel_origin;
119 | tc_timeval travel_offset;
120 | #if PHP_VERSION_ID >= 70000
121 | zend_long scaling_factor;
122 | #else
123 | long scaling_factor;
124 | #endif
125 | zend_class_entry *ce_DateTimeZone;
126 | zend_class_entry *ce_DateTimeInterface;
127 | zend_class_entry *ce_DateTime;
128 | zend_class_entry *ce_TimecopDateTime;
129 | zend_class_entry *ce_DateTimeImmutable;
130 | zend_class_entry *ce_TimecopDateTimeImmutable;
131 | ZEND_END_MODULE_GLOBALS(timecop)
132 |
133 | #if ZEND_DEBUG
134 | # define TIMECOP_ASSERT(c) assert(c)
135 | #else
136 | # define TIMECOP_ASSERT(c)
137 | #endif /* ZEND_DEBUG */
138 |
139 | #define SAVE_FUNC_PREFIX "timecop_orig_"
140 | #define OVRD_FUNC_PREFIX "timecop_"
141 |
142 | #define OVRD_CLASS_PREFIX "timecop"
143 |
144 | #define ORIG_FUNC_NAME(fname) \
145 | (TIMECOP_G(func_override) ? (SAVE_FUNC_PREFIX fname) : fname)
146 |
147 | #define TIMECOP_OFE(fname) {fname, OVRD_FUNC_PREFIX fname, SAVE_FUNC_PREFIX fname}
148 | #define TIMECOP_OCE(cname, mname) \
149 | {cname, mname, OVRD_CLASS_PREFIX cname, SAVE_FUNC_PREFIX mname}
150 |
151 | /*
152 | * Trick for guarding the multi-referenced internal function from function destructor on PHP 7.2.0+
153 | * See: https://github.com/hnw/php-timecop/issues/29#issuecomment-332171527
154 | */
155 | #define GUARD_FUNCTION_ARG_INFO_BEGIN(zend_func) { \
156 | zend_arg_info *orig_arg_info; \
157 | zend_function *zf = zend_func; \
158 | if (zf->type == ZEND_INTERNAL_FUNCTION) { \
159 | orig_arg_info = zf->common.arg_info; \
160 | zf->common.arg_info = NULL; \
161 | }
162 |
163 | #define GUARD_FUNCTION_ARG_INFO_END() \
164 | if (zf->type == ZEND_INTERNAL_FUNCTION) { \
165 | zf->common.arg_info = orig_arg_info; \
166 | } \
167 | }
168 |
169 | struct timecop_override_func_entry {
170 | char *orig_func;
171 | char *ovrd_func;
172 | char *save_func;
173 | };
174 |
175 | struct timecop_override_class_entry {
176 | char *orig_class;
177 | char *orig_method;
178 | char *ovrd_class;
179 | char *save_method;
180 | };
181 |
182 | #define call_php_method_with_0_params(obj, ce, method_name, retval) \
183 | _call_php_method_with_0_params(obj, ce, method_name, retval TSRMLS_CC)
184 |
185 | #define call_php_method_with_1_params(obj, ce, method_name, retval, arg1) \
186 | _call_php_method_with_1_params(obj, ce, method_name, retval, arg1 TSRMLS_CC)
187 |
188 | #define call_php_method_with_2_params(obj, ce, method_name, retval, arg1, arg2) \
189 | _call_php_method_with_2_params(obj, ce, method_name, retval, arg1, arg2 TSRMLS_CC)
190 |
191 | #define call_php_function_with_0_params(function_name, retval) \
192 | _call_php_function_with_0_params(function_name, retval TSRMLS_CC)
193 |
194 | #define call_php_function_with_1_params(function_name, retval, arg1) \
195 | _call_php_function_with_1_params(function_name, retval, arg1 TSRMLS_CC)
196 |
197 | #define call_php_function_with_2_params(function_name, retval, arg1, arg2) \
198 | _call_php_function_with_2_params(function_name, retval, arg1, arg2 TSRMLS_CC)
199 |
200 | #define call_php_function_with_3_params(function_name, retval, arg1, arg2, arg3) \
201 | _call_php_function_with_3_params(function_name, retval, arg1, arg2, arg3 TSRMLS_CC)
202 |
203 | #define call_php_function_with_params(function_name, retval, param_count, params) \
204 | _call_php_function_with_params(function_name, retval, param_count, params TSRMLS_CC)
205 |
206 | /* In every utility function you add that needs to use variables
207 | in php_timecop_globals, call TSRMLS_FETCH(); after declaring other
208 | variables used by that function, or better yet, pass in TSRMLS_CC
209 | after the last function argument and declare your utility function
210 | with TSRMLS_DC after the last declared argument. Always refer to
211 | the globals in your function as TIMECOP_G(variable). You are
212 | encouraged to rename these macros something shorter, see
213 | examples in any other php module directory.
214 | */
215 |
216 | #if PHP_VERSION_ID >= 70000
217 | # define TIMECOP_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(timecop, v)
218 | # if defined(ZTS) && defined(COMPILE_DL_TIMECOP)
219 | ZEND_TSRMLS_CACHE_EXTERN();
220 | # endif
221 | #else
222 | # ifdef ZTS
223 | # define TIMECOP_G(v) TSRMG(timecop_globals_id, zend_timecop_globals *, v)
224 | # else
225 | # define TIMECOP_G(v) (timecop_globals.v)
226 | # endif
227 | #endif
228 |
229 | #endif /* PHP_TIMECOP_H */
230 |
231 | /*
232 | * Local variables:
233 | * tab-width: 4
234 | * c-basic-offset: 4
235 | * End:
236 | * vim600: noet sw=4 ts=4 fdm=marker
237 | * vim<600: noet sw=4 ts=4
238 | */
239 |
--------------------------------------------------------------------------------
/stubs/Timecop.php:
--------------------------------------------------------------------------------
1 | = 7
30 | zend_long sec, usec;
31 | #else
32 | long sec, usec;
33 | #endif
34 | usec = arg1->usec + arg2->usec;
35 | sec = arg1->sec + arg2->sec;
36 | if (usec < 0) {
37 | sec -= ((-usec) / USEC_PER_SEC + 1);
38 | usec = USEC_PER_SEC - ((-usec) % USEC_PER_SEC);
39 | if (usec == USEC_PER_SEC) {
40 | sec++;
41 | usec = 0;
42 | }
43 | } else if (usec >= USEC_PER_SEC) {
44 | sec += usec / USEC_PER_SEC;
45 | usec = usec % USEC_PER_SEC;
46 | }
47 | ret->sec = sec;
48 | ret->usec = usec;
49 |
50 | return 0;
51 | }
52 | int tc_timeval_sub(tc_timeval *ret, const tc_timeval *arg1, const tc_timeval *arg2)
53 | {
54 | #if PHP_MAJOR_VERSION >= 7
55 | zend_long sec, usec;
56 | #else
57 | long sec, usec;
58 | #endif
59 | usec = arg1->usec - arg2->usec;
60 | sec = arg1->sec - arg2->sec;
61 | if (usec < 0) {
62 | sec -= ((-usec) / USEC_PER_SEC + 1);
63 | usec = USEC_PER_SEC - ((-usec) % USEC_PER_SEC);
64 | if (usec == USEC_PER_SEC) {
65 | sec++;
66 | usec = 0;
67 | }
68 | } else if (usec >= USEC_PER_SEC) {
69 | sec += usec / USEC_PER_SEC;
70 | usec = usec % USEC_PER_SEC;
71 | }
72 | ret->sec = sec;
73 | ret->usec = usec;
74 |
75 | return 0;
76 | }
77 |
78 | #if PHP_MAJOR_VERSION >= 7
79 | int tc_timeval_mul(tc_timeval *ret, const tc_timeval *arg1, const zend_long arg2)
80 | #else
81 | int tc_timeval_mul(tc_timeval *ret, const tc_timeval *arg1, const long arg2)
82 | #endif
83 | {
84 | #if PHP_MAJOR_VERSION >= 7
85 | zend_long sec, usec;
86 | #else
87 | long sec, usec;
88 | #endif
89 | usec = arg1->usec * arg2;
90 | sec = arg1->sec * arg2;
91 | if (usec < 0) {
92 | sec -= ((-usec) / USEC_PER_SEC + 1);
93 | usec = USEC_PER_SEC - ((-usec) % USEC_PER_SEC);
94 | if (usec == USEC_PER_SEC) {
95 | sec++;
96 | usec = 0;
97 | }
98 | } else if (usec >= USEC_PER_SEC) {
99 | sec += usec / USEC_PER_SEC;
100 | usec = usec % USEC_PER_SEC;
101 | }
102 | ret->sec = sec;
103 | ret->usec = usec;
104 |
105 | return 0;
106 | }
107 |
108 | /*
109 | * Local variables:
110 | * tab-width: 4
111 | * c-basic-offset: 4
112 | * End:
113 | * vim600: noet sw=4 ts=4 fdm=marker
114 | * vim<600: noet sw=4 ts=4
115 | */
116 |
--------------------------------------------------------------------------------
/tc_timeval.h:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2012-2017 Yoshio HANAWA
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 |
25 | #ifndef TC_TIMEVAL_H
26 | #define TC_TIMEVAL_H
27 |
28 | #ifndef USEC_PER_SEC
29 | # define USEC_PER_SEC 1000000
30 | #endif
31 |
32 | typedef struct _tc_timeval {
33 | #if PHP_MAJOR_VERSION >= 7
34 | zend_long sec;
35 | zend_long usec;
36 | #else
37 | long sec;
38 | long usec;
39 | #endif
40 | } tc_timeval;
41 |
42 |
43 | int tc_timeval_add(tc_timeval *ret, const tc_timeval *arg1, const tc_timeval *arg2);
44 | int tc_timeval_sub(tc_timeval *ret, const tc_timeval *arg1, const tc_timeval *arg2);
45 | #if PHP_MAJOR_VERSION >= 7
46 | int tc_timeval_mul(tc_timeval *ret, const tc_timeval *arg1, const zend_long arg2);
47 | #else
48 | int tc_timeval_mul(tc_timeval *ret, const tc_timeval *arg1, const long arg2);
49 | #endif
50 |
51 | #endif /* TC_TIMEVAL_H */
52 |
53 | /*
54 | * Local variables:
55 | * tab-width: 4
56 | * c-basic-offset: 4
57 | * End:
58 | * vim600: noet sw=4 ts=4 fdm=marker
59 | * vim<600: noet sw=4 ts=4
60 | */
61 |
--------------------------------------------------------------------------------
/tests/core_001.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for timecop_freeze()
3 | --SKIPIF--
4 | setTimeZone(new DateTimeZone("America/Los_Angeles"));
35 | }
36 |
37 | timecop_freeze(1);
38 | $dt7 =new TimecopDateTime();
39 |
40 | var_dump($dt2->format("Y-m-d H:i:s.uP"));
41 | var_dump($dt4->format("Y-m-d H:i:s.uP"));
42 | var_dump($dt6->format("Y-m-d H:i:s.uP"));
43 | var_dump($dt1 == $dt2);
44 | var_dump($dt3 == $dt4);
45 | var_dump($dt5 == $dt6);
46 | var_dump($dt7->format("Y-m-d H:i:s.uP"));
47 | --EXPECT--
48 | string(32) "1969-12-31 16:00:00.000000-08:00"
49 | string(32) "1970-01-01 01:00:00.000000-08:00"
50 | string(32) "2039-12-31 16:00:00.000000-08:00"
51 | bool(true)
52 | bool(true)
53 | bool(true)
54 | string(32) "1969-12-31 16:00:01.000000-08:00"
55 |
--------------------------------------------------------------------------------
/tests/core_002.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for timecop_travel()
3 | --SKIPIF--
4 | modify("+1second");
38 | $dt6->setTimeZone(new DateTimeZone("America/Los_Angeles"));
39 | }
40 |
41 | timecop_travel(1);
42 | sleep(1);
43 | $dt7 =new TimecopDateTime();
44 |
45 | var_dump($dt2->format("Y-m-d H:i:s"));
46 | var_dump($dt4->format("Y-m-d H:i:s"));
47 | var_dump($dt6->format("Y-m-d H:i:s"));
48 | var_dump($dt1 < $dt2);
49 | var_dump($dt3 < $dt4);
50 | var_dump($dt5 < $dt6);
51 | var_dump($dt7->format("Y-m-d H:i:s"));
52 | --EXPECT--
53 | string(19) "1969-12-31 16:00:01"
54 | string(19) "1970-01-01 01:00:01"
55 | string(19) "2039-12-31 16:00:01"
56 | bool(true)
57 | bool(true)
58 | bool(true)
59 | string(19) "1969-12-31 16:00:02"
60 |
--------------------------------------------------------------------------------
/tests/core_003.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for timecop_scale()
3 | --SKIPIF--
4 | format("Y-m-d H:i:s"));
25 | var_dump($dt3->format("Y-m-d H:i:s"));
26 | --EXPECT--
27 | string(19) "1969-12-31 16:00:02"
28 | string(19) "1969-12-31 16:00:04"
29 |
--------------------------------------------------------------------------------
/tests/core_004.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for timecop_return()
3 | --SKIPIF--
4 | $dt3);
22 | --EXPECT--
23 | bool(false)
24 | bool(false)
25 | bool(true)
26 |
--------------------------------------------------------------------------------
/tests/core_005.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Test for Timecop::freeze()
3 | --SKIPIF--
4 | setTimeZone(new DateTimeZone("Pacific/Honolulu"));
36 | }
37 |
38 | Timecop::freeze(7);
39 | $dt7 =new TimecopDateTime();
40 |
41 | var_dump($dt2->format("Y-m-d H:i:s.u"));
42 | var_dump($dt4->format("Y-m-d H:i:s.u"));
43 | var_dump($dt6->format("Y-m-d H:i:s.u"));
44 | var_dump($dt1 == $dt2);
45 | var_dump($dt3 == $dt4);
46 | var_dump($dt5 == $dt6);
47 | var_dump($dt7->format("Y-m-d H:i:s.u"));
48 | --EXPECT--
49 | string(26) "1969-12-31 14:00:00.000000"
50 | string(26) "1970-01-01 01:00:00.000000"
51 | string(26) "2039-12-31 14:00:05.000000"
52 | bool(true)
53 | bool(true)
54 | bool(true)
55 | string(26) "1969-12-31 14:00:07.000000"
56 |
--------------------------------------------------------------------------------
/tests/core_006.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for Timecop::travel()
3 | --SKIPIF--
4 | modify("+1second");
37 | $dt6->setTimeZone(new DateTimeZone("America/Los_Angeles"));
38 | }
39 |
40 | Timecop::travel(1);
41 | sleep(1);
42 | $dt7 =new TimecopDateTime();
43 |
44 | var_dump($dt2->format("Y-m-d H:i:s"));
45 | var_dump($dt4->format("Y-m-d H:i:s"));
46 | var_dump($dt6->format("Y-m-d H:i:s"));
47 | var_dump($dt1 < $dt2);
48 | var_dump($dt3 < $dt4);
49 | var_dump($dt5 < $dt6);
50 | var_dump($dt7->format("Y-m-d H:i:s"));
51 | --EXPECT--
52 | string(19) "1969-12-31 16:00:01"
53 | string(19) "1970-01-01 01:00:01"
54 | string(19) "2039-12-31 16:00:01"
55 | bool(true)
56 | bool(true)
57 | bool(true)
58 | string(19) "1969-12-31 16:00:02"
59 |
--------------------------------------------------------------------------------
/tests/core_007.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for Timecop::scale()
3 | --SKIPIF--
4 | format("Y-m-d H:i:s"));
24 | var_dump($dt3->format("Y-m-d H:i:s"));
25 | --EXPECT--
26 | string(19) "1969-12-31 16:00:02"
27 | string(19) "1969-12-31 16:00:04"
28 |
--------------------------------------------------------------------------------
/tests/core_008.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for Timecop::return()
3 | --SKIPIF--
4 | $dt3);
21 | --EXPECT--
22 | bool(false)
23 | bool(false)
24 | bool(true)
25 |
--------------------------------------------------------------------------------
/tests/core_009.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Test for date_timestamp_get() on PHP 5.2
3 | --SKIPIF--
4 | = 0) {
6 | die("skip this test is for PHP 5.2.x");
7 | }
8 | $required_class = array("timecopdatetime");
9 | include(__DIR__."/tests-skipcheck.inc.php");
10 | --INI--
11 | date.timezone=America/Los_Angeles
12 | --FILE--
13 | = 0) {
6 | die("skip this test is for PHP 5.2.x");
7 | }
8 | $required_class = array("timecopdatetime");
9 | include(__DIR__."/tests-skipcheck.inc.php");
10 | --INI--
11 | date.timezone=America/Los_Angeles
12 | --FILE--
13 | format("U"));
17 | --EXPECT--
18 | string(4) "2000"
19 |
--------------------------------------------------------------------------------
/tests/core_011.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Test for $_SERVER['REQUEST_TIME'] when timecop.sync_request_time=1
3 | --SKIPIF--
4 | enabled
17 | Version => \d+\.\d+\.\d+
18 |
19 | Directive => Local Value => Master Value
20 | timecop\.func_override => 1 => 1
21 | timecop\.sync_request_time => 1 => 1
22 | .*
23 |
--------------------------------------------------------------------------------
/tests/date_001.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Test for DateTime/TimecopDateTime/TimecopOrigDateTime inheritance
3 | --SKIPIF--
4 | = 0) {
30 | var_dump($dt1 instanceof DateTimeInterface);
31 | var_dump($dt2 instanceof DateTimeInterface);
32 | var_dump($dt3 instanceof DateTimeInterface);
33 | } else {
34 | // force pass if PHP < 5.5.0
35 | var_dump(true);
36 | var_dump(true);
37 | var_dump(true);
38 | }
39 | echo "===\n";
40 | var_dump($dt1->format("c") === $freezed_time);
41 | var_dump($dt2->format("c") === $freezed_time);
42 | var_dump($dt3->format("c") === $freezed_time);
43 | --EXPECT--
44 | string(8) "DateTime"
45 | string(15) "TimecopDateTime"
46 | string(19) "TimecopOrigDateTime"
47 | bool(true)
48 | bool(true)
49 | bool(false)
50 | bool(false)
51 | bool(false)
52 | bool(false)
53 | ===
54 | bool(true)
55 | bool(true)
56 | bool(true)
57 | ===
58 | bool(false)
59 | bool(true)
60 | bool(false)
61 |
--------------------------------------------------------------------------------
/tests/date_002.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Test for TimecopDateTime::__construct
3 | --SKIPIF--
4 | getmessage() !== $e2->getmessage()) {
44 | printf("Exception message is differ for str=%s: %s !== %s\n",
45 | $str, $e1->getmessage(), $e2->getmessage());
46 | }
47 | }
48 | if ($dt1 && $dt2) {
49 | if ($dt1->format("c") !== $dt2->format("c")) {
50 | printf("TimecopDatetime::format is differ from Datetime::format for str=%s: %s !== %s\n",
51 | $str, $dt1->format("c"), $dt2->format("c"));
52 | }
53 | if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
54 | if ($dt1->format("U") != $dt2->getTimestamp()) {
55 | printf("TimecopDatetime::getTimestamp is differ from Datetime::getTimestamp for str=%s: %s !== %s\n",
56 | $str, $dt1->format("U"), $dt2->getTimestamp());
57 | }
58 | }
59 | }
60 | }
61 | --EXPECT--
62 |
--------------------------------------------------------------------------------
/tests/date_003.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Test for serialize/unserialize TimecopDateTime instance
3 | --SKIPIF--
4 | format("c"));
17 | var_dump($dt2->format("c"));
18 | --EXPECT--
19 | string(25) "2012-01-01T12:00:00+00:00"
20 | string(25) "2012-01-01T12:00:00+00:00"
21 |
--------------------------------------------------------------------------------
/tests/date_004.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for compareing TimecopDateTime instance
3 | --SKIPIF--
4 | format("c"));
15 | --EXPECT--
16 | string(25) "2012-01-01T12:00:00+00:00"
17 |
--------------------------------------------------------------------------------
/tests/date_006.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Test for timecop_date_create
3 | --SKIPIF--
4 | format("c"));
46 | }
47 |
48 | --EXPECT--
49 | string(8) "DateTime"
50 | string(25) "2012-02-29T01:23:45-08:00"
51 | string(25) "2012-02-29T01:23:45-08:00"
52 | string(25) "2012-02-29T01:23:45-08:00"
53 | string(25) "2012-03-31T12:34:56-07:00"
54 | string(25) "2012-03-03T01:23:45-08:00"
55 | string(25) "1970-01-01T19:00:00-05:00"
56 | string(25) "1970-01-02T00:00:00+00:00"
57 | string(25) "2012-02-29T18:23:45+09:00"
58 |
--------------------------------------------------------------------------------
/tests/date_007.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Test for timecop_date_create_from_format()
3 | --SKIPIF--
4 | format("Y-m-d H:i:s.uP"));
32 | foreach ($tests_args as $args) {
33 | timecop_freeze($dt0);
34 | $dt1 = call_user_func_array("timecop_date_create_from_format", $args);
35 | var_dump($dt1->format("Y-m-d H:i:s.uP"));
36 | while (true) {
37 | /* test for equality between timecop_date_create_from_format() and date_create_from_format() */
38 | $start_time = time();
39 | timecop_freeze(new DateTime());
40 | $dt2 = call_user_func_array("timecop_date_create_from_format", $args);
41 | $dt3 = call_user_func_array("date_create_from_format", $args);
42 | if ($start_time === time()) {
43 | if ($dt2 && $dt3 && ($dt2->format("c") !== $dt3->format("c"))) {
44 | printf("timecop_date_create_from_format('%s', '%s') is differ from date_create_from_format() : %s !== %s\n",
45 | $args[0], $args[1], $dt2->format("c"), $dt3->format("c"));
46 | }
47 | break;
48 | }
49 | }
50 | }
51 | --EXPECTREGEX--
52 | string\(8\) "DateTime"
53 | string\(32\) "2010-01-02 03:04:05\.678000-08:00"
54 | string\(32\) "2010-01-02 03:04:05\.(000|678)000-08:00"
55 | string\(32\) "2010-01-02 03:04:05\.(\1)000-08:00"
56 | string\(32\) "1990-01-02 03:04:05\.000000-08:00"
57 | string\(32\) "2010-09-02 03:04:05\.000000-07:00"
58 | string\(32\) "2010-12-24 03:04:05\.000000-08:00"
59 | string\(32\) "2010-01-02 05:00:00\.000000\+09:00"
60 | string\(32\) "2010-01-02 00:00:59\.000000-08:00"
61 | string\(32\) "2010-01-02 (00:00:00|03:04:05)\.654321-08:00"
62 | string\(32\) "2012-03-31 12:34:56\.000000-07:00"
63 | string\(32\) "1970-01-01 12:34:56\.000000-08:00"
64 | string\(32\) "1970-01-01 19:00:00\.000000-05:00"
65 | string\(32\) "1970-01-02 00:00:00\.000000\+00:00"
66 | string\(32\) "2012-04-01 00:00:00\.000000\+09:00"
67 |
--------------------------------------------------------------------------------
/tests/date_008.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Test for TimecopDateTime::createFromFormat()
3 | --SKIPIF--
4 | format("Y-m-d H:i:s.uP"));
33 | foreach ($tests_args as $args) {
34 | timecop_freeze($dt0);
35 | $dt1 = call_user_func_array(array("TimecopDateTime","createFromFormat"), $args);
36 | var_dump($dt1->format("Y-m-d H:i:s.uP"));
37 | while (true) {
38 | /* test for equality between timecop_date_create_from_format() and date_create_from_format() */
39 | $start_time = time();
40 | timecop_freeze(new DateTime());
41 | $dt2 = call_user_func_array(array("TimecopDateTime","createFromFormat"), $args);
42 | $dt3 = call_user_func_array(array("DateTime","createFromFormat"), $args);
43 | if ($start_time === time()) {
44 | if ($dt2 && $dt3 && ($dt2->format("c") !== $dt3->format("c"))) {
45 | printf("TimecopDateTime::createFromFormat('%s', '%s') is differ from DateTime::createFromFormat() : %s !== %s\n",
46 | $args[0], $args[1], $dt2->format("c"), $dt3->format("c"));
47 | }
48 | break;
49 | }
50 | }
51 | }
52 | --EXPECTREGEX--
53 | string\(8\) "DateTime"
54 | string\(32\) "2010-01-02 03:04:05\.678000-08:00"
55 | string\(32\) "2010-01-02 03:04:05\.(000|678)000-08:00"
56 | string\(32\) "2010-01-02 03:04:05\.(\1)000-08:00"
57 | string\(32\) "1990-01-02 03:04:05\.000000-08:00"
58 | string\(32\) "2010-09-02 03:04:05\.000000-07:00"
59 | string\(32\) "2010-12-24 03:04:05\.000000-08:00"
60 | string\(32\) "2010-01-02 05:00:00\.000000\+09:00"
61 | string\(32\) "2010-01-02 00:00:59\.000000-08:00"
62 | string\(32\) "2010-01-02 (00:00:00|03:04:05)\.654321-08:00"
63 | string\(32\) "2012-03-31 12:34:56\.000000-07:00"
64 | string\(32\) "1970-01-01 12:34:56\.000000-08:00"
65 | string\(32\) "1970-01-01 19:00:00\.000000-05:00"
66 | string\(32\) "1970-01-02 00:00:00\.000000\+00:00"
67 | string\(32\) "2012-04-01 00:00:00\.000000\+09:00"
68 |
--------------------------------------------------------------------------------
/tests/date_override_001.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Test for DateTime/TimecopDateTime/TimecopOrigDateTime inheritance when function override is enabled
3 | --SKIPIF--
4 | = 0) {
30 | var_dump($dt1 instanceof DateTimeInterface);
31 | var_dump($dt2 instanceof DateTimeInterface);
32 | var_dump($dt3 instanceof DateTimeInterface);
33 | } else {
34 | // force pass if PHP < 5.5.0
35 | var_dump(true);
36 | var_dump(true);
37 | var_dump(true);
38 | }
39 | echo "===\n";
40 | var_dump($dt1->format("c") === $freezed_time);
41 | var_dump($dt2->format("c") === $freezed_time);
42 | var_dump($dt3->format("c") === $freezed_time);
43 | --EXPECT--
44 | string(8) "DateTime"
45 | string(15) "TimecopDateTime"
46 | string(19) "TimecopOrigDateTime"
47 | bool(true)
48 | bool(true)
49 | bool(false)
50 | bool(false)
51 | bool(false)
52 | bool(false)
53 | ===
54 | bool(true)
55 | bool(true)
56 | bool(true)
57 | ===
58 | bool(true)
59 | bool(true)
60 | bool(false)
61 |
--------------------------------------------------------------------------------
/tests/date_override_002.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Method overrideing test for DateTime::__construct
3 | --SKIPIF--
4 | format("c"));
64 | }
65 |
66 | --EXPECT--
67 | string(8) "DateTime"
68 | string(25) "2012-02-29T01:23:45-08:00"
69 | string(25) "2012-02-29T01:23:45-08:00"
70 | string(25) "2012-02-29T01:23:45-08:00"
71 | string(25) "2012-02-29T01:23:45-08:00"
72 | string(25) "2012-03-31T00:00:00-07:00"
73 | string(25) "2013-03-01T00:00:00-08:00"
74 | string(25) "2013-03-31T00:00:00-07:00"
75 | string(25) "2013-03-31T12:34:56-07:00"
76 | string(25) "2012-02-29T12:34:56-08:00"
77 | string(25) "2012-02-29T12:34:00-08:00"
78 | string(25) "2012-03-03T01:23:45-08:00"
79 | string(25) "1970-01-01T19:00:00-05:00"
80 | string(25) "1970-01-02T00:00:00+00:00"
81 | string(25) "2012-02-29T18:23:45+09:00"
82 |
--------------------------------------------------------------------------------
/tests/date_override_003.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Test for serialize/unserialize overridden DateTime instance
3 | --SKIPIF--
4 | format("c"));
16 | var_dump($dt2->format("c"));
17 | --EXPECT--
18 | string(25) "2012-01-01T12:00:00+00:00"
19 | string(25) "2012-01-01T12:00:00+00:00"
20 |
--------------------------------------------------------------------------------
/tests/date_override_006.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Function overrideing test for date_create
3 | --SKIPIF--
4 | format("c"));
46 | }
47 |
48 | --EXPECT--
49 | string(8) "DateTime"
50 | string(25) "2012-02-29T01:23:45-08:00"
51 | string(25) "2012-02-29T01:23:45-08:00"
52 | string(25) "2012-02-29T01:23:45-08:00"
53 | string(25) "2012-03-31T12:34:56-07:00"
54 | string(25) "2012-03-03T01:23:45-08:00"
55 | string(25) "1970-01-01T19:00:00-05:00"
56 | string(25) "1970-01-02T00:00:00+00:00"
57 | string(25) "2012-02-29T18:23:45+09:00"
58 |
--------------------------------------------------------------------------------
/tests/date_override_007.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Function overrideing test for date_create_from_format()
3 | --SKIPIF--
4 | format("Y-m-d H:i:s.uP"));
34 | foreach ($tests_args as $args) {
35 | timecop_freeze($dt0);
36 | $dt1 = call_user_func_array("date_create_from_format", $args);
37 | var_dump($dt1->format("Y-m-d H:i:s.uP"));
38 | while (true) {
39 | /* test for equality between timecop_date_create_from_format() and date_create_from_format() */
40 | $start_time = time();
41 | timecop_freeze(new TimecopOrigDateTime());
42 | $dt2 = call_user_func_array("date_create_from_format", $args);
43 | $dt3 = call_user_func_array("timecop_orig_date_create_from_format", $args);
44 | if ($start_time === time()) {
45 | if ($dt2 && $dt3 && ($dt2->format("c") !== $dt3->format("c"))) {
46 | printf("date_create_from_format('%s', '%s') is differ from timecop_orig_date_create_from_format() : %s !== %s\n",
47 | $args[0], $args[1], $dt2->format("c"), $dt3->format("c"));
48 | }
49 | break;
50 | }
51 | }
52 | }
53 | --EXPECTREGEX--
54 | string\(8\) "DateTime"
55 | string\(32\) "2010-01-02 03:04:05\.678000-08:00"
56 | string\(32\) "2010-01-02 03:04:05\.(000|678)000-08:00"
57 | string\(32\) "2010-01-02 03:04:05\.(\1)000-08:00"
58 | string\(32\) "1990-01-02 03:04:05\.000000-08:00"
59 | string\(32\) "2010-09-02 03:04:05\.000000-07:00"
60 | string\(32\) "2010-12-24 03:04:05\.000000-08:00"
61 | string\(32\) "2010-01-02 05:00:00\.000000\+09:00"
62 | string\(32\) "2010-01-02 00:00:59\.000000-08:00"
63 | string\(32\) "2010-01-02 (00:00:00|03:04:05)\.654321-08:00"
64 | string\(32\) "2012-03-31 12:34:56\.000000-07:00"
65 | string\(32\) "1970-01-01 12:34:56\.000000-08:00"
66 | string\(32\) "1970-01-01 19:00:00\.000000-05:00"
67 | string\(32\) "1970-01-02 00:00:00\.000000\+00:00"
68 | string\(32\) "2012-04-01 00:00:00\.000000\+09:00"
69 | string\(32\) "1970-03-31 00:00:00\.000000\-08:00"
70 |
--------------------------------------------------------------------------------
/tests/date_override_008.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Method overrideing test for DateTime::createFromFormat()
3 | --SKIPIF--
4 | format("Y-m-d H:i:s.uP"));
35 | foreach ($tests_args as $args) {
36 | timecop_freeze($dt0);
37 | $dt1 = call_user_func_array(array("DateTime","createFromFormat"), $args);
38 | var_dump($dt1->format("Y-m-d H:i:s.uP"));
39 | while (true) {
40 | /* test for equality between timecop_date_create_from_format() and date_create_from_format() */
41 | $start_time = time();
42 | timecop_freeze(new TimecopOrigDateTime());
43 | $dt2 = call_user_func_array(array("DateTime","createFromFormat"), $args);
44 | $dt3 = call_user_func_array(array("TimecopOrigDateTime","createFromFormat"), $args);
45 | if ($start_time === time()) {
46 | if ($dt2 && $dt3 && ($dt2->format("c") !== $dt3->format("c"))) {
47 | printf("DateTime::createFromFormat('%s', '%s') is differ from TimecopOrigDateTime::createFromFormat() : %s !== %s\n",
48 | $args[0], $args[1], $dt2->format("c"), $dt3->format("c"));
49 | }
50 | break;
51 | }
52 | }
53 | }
54 | --EXPECTREGEX--
55 | string\(8\) "DateTime"
56 | string\(32\) "2010-01-02 03:04:05\.678000-08:00"
57 | string\(32\) "2010-01-02 03:04:05\.(000|678)000-08:00"
58 | string\(32\) "2010-01-02 03:04:05\.(\1)000-08:00"
59 | string\(32\) "1990-01-02 03:04:05\.000000-08:00"
60 | string\(32\) "2010-09-02 03:04:05\.000000-07:00"
61 | string\(32\) "2010-12-24 03:04:05\.000000-08:00"
62 | string\(32\) "2010-01-02 05:00:00\.000000\+09:00"
63 | string\(32\) "2010-01-02 00:00:59\.000000-08:00"
64 | string\(32\) "2010-01-02 (00:00:00|03:04:05)\.654321-08:00"
65 | string\(32\) "2012-03-31 12:34:56\.000000-07:00"
66 | string\(32\) "1970-01-01 12:34:56\.000000-08:00"
67 | string\(32\) "1970-01-01 19:00:00\.000000-05:00"
68 | string\(32\) "1970-01-02 00:00:00\.000000\+00:00"
69 | string\(32\) "2012-04-01 00:00:00\.000000\+09:00"
70 | string\(32\) "1970-03-31 00:00:00\.000000\-08:00"
71 |
--------------------------------------------------------------------------------
/tests/func_001.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Test for timecop_time
3 | --SKIPIF--
4 | = 0) {
31 | var_dump($dt1 instanceof DateTimeInterface);
32 | var_dump($dt2 instanceof DateTimeInterface);
33 | var_dump($dt3 instanceof DateTimeInterface);
34 | } else {
35 | // force pass if PHP < 5.5.0
36 | var_dump(true);
37 | var_dump(true);
38 | var_dump(true);
39 | }
40 | echo "===\n";
41 | var_dump($dt1->format("c") === $dt0->format("c"));
42 | var_dump($dt2->format("c") === $dt0->format("c"));
43 | var_dump($dt3->format("c") === $dt0->format("c"));
44 | --EXPECT--
45 | string(17) "DateTimeImmutable"
46 | string(24) "TimecopDateTimeImmutable"
47 | string(28) "TimecopOrigDateTimeImmutable"
48 | bool(true)
49 | bool(true)
50 | bool(false)
51 | bool(false)
52 | bool(false)
53 | bool(false)
54 | ===
55 | bool(true)
56 | bool(true)
57 | bool(true)
58 | ===
59 | bool(false)
60 | bool(true)
61 | bool(false)
62 |
--------------------------------------------------------------------------------
/tests/immutable_002.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for TimecopDateTimeImmutable::__construct
3 | --SKIPIF--
4 | getmessage() !== $e2->getmessage()) {
44 | printf("Exception message is differ for str=%s: %s !== %s\n",
45 | $str, $e1->getmessage(), $e2->getmessage());
46 | }
47 | }
48 | if ($dt1 && $dt2) {
49 | if ($dt1->format("c") !== $dt2->format("c")) {
50 | printf("TimecopDatetimeImmutable::format is differ from DatetimeImmutable::format for str=%s: %s !== %s\n",
51 | $str, $dt1->format("c"), $dt2->format("c"));
52 | }
53 | if ($dt1->format("U") != $dt2->format("U")) {
54 | printf("TimecopDatetimeImmutable::getTimestamp is differ from DatetimeImmutable::getTimestamp for str=%s: %s !== %s\n",
55 | $str, $dt1->format("U"), $dt2->formmat("U"));
56 | }
57 | }
58 | }
59 | --EXPECT--
60 |
--------------------------------------------------------------------------------
/tests/immutable_003.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for serialize/unserialize TimecopDateTimeImmutable instance
3 | --SKIPIF--
4 | format("c"));
16 | var_dump($dt2->format("c"));
17 | --EXPECT--
18 | string(25) "2012-01-01T12:00:00+00:00"
19 | string(25) "2012-01-01T12:00:00+00:00"
20 |
--------------------------------------------------------------------------------
/tests/immutable_004.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for compareing TimecopDateTimeImmutable instance
3 | --SKIPIF--
4 | format("c"));
16 | --EXPECT--
17 | string(25) "2012-01-01T12:00:00+00:00"
18 |
--------------------------------------------------------------------------------
/tests/immutable_006.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for timecop_date_create_immutable
3 | --SKIPIF--
4 | format("c"));
47 | }
48 |
49 | --EXPECT--
50 | string(17) "DateTimeImmutable"
51 | string(25) "2012-02-29T01:23:45-08:00"
52 | string(25) "2012-02-29T01:23:45-08:00"
53 | string(25) "2012-02-29T01:23:45-08:00"
54 | string(25) "2012-03-31T12:34:56-07:00"
55 | string(25) "2012-03-03T01:23:45-08:00"
56 | string(25) "1970-01-01T19:00:00-05:00"
57 | string(25) "1970-01-02T00:00:00+00:00"
58 | string(25) "2012-02-29T18:23:45+09:00"
59 |
--------------------------------------------------------------------------------
/tests/immutable_007.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for timecop_date_create_immutable_from_format()
3 | --SKIPIF--
4 | format("Y-m-d H:i:s.uP"));
32 | foreach ($tests_args as $args) {
33 | timecop_freeze($dt0);
34 | $dt1 = call_user_func_array("timecop_date_create_immutable_from_format", $args);
35 | var_dump($dt1->format("Y-m-d H:i:s.uP"));
36 | while (true) {
37 | /* test for equality between timecop_date_create_immutable_from_format() and date_create_immutale_from_format() */
38 | $start_time = time();
39 | timecop_freeze(new DateTime());
40 | $dt2 = call_user_func_array("timecop_date_create_immutable_from_format", $args);
41 | $dt3 = call_user_func_array("date_create_immutable_from_format", $args);
42 | if ($start_time === time()) {
43 | if ($dt2 && $dt3 && ($dt2->format("c") !== $dt3->format("c"))) {
44 | printf("timecop_date_create_immutable_from_format('%s', '%s') is differ from date_create_immutable_from_format() : %s !== %s\n",
45 | $args[0], $args[1], $dt2->format("c"), $dt3->format("c"));
46 | }
47 | break;
48 | }
49 | }
50 | }
51 | --EXPECTREGEX--
52 | string\(17\) "DateTimeImmutable"
53 | string\(32\) "2010-01-02 03:04:05\.678000-08:00"
54 | string\(32\) "2010-01-02 03:04:05\.(000|678)000-08:00"
55 | string\(32\) "2010-01-02 03:04:05\.(\1)000-08:00"
56 | string\(32\) "1990-01-02 03:04:05\.000000-08:00"
57 | string\(32\) "2010-09-02 03:04:05\.000000-07:00"
58 | string\(32\) "2010-12-24 03:04:05\.000000-08:00"
59 | string\(32\) "2010-01-02 05:00:00\.000000\+09:00"
60 | string\(32\) "2010-01-02 00:00:59\.000000-08:00"
61 | string\(32\) "2010-01-02 (00:00:00|03:04:05)\.654321-08:00"
62 | string\(32\) "2012-03-31 12:34:56\.000000-07:00"
63 | string\(32\) "1970-01-01 12:34:56\.000000-08:00"
64 | string\(32\) "1970-01-01 19:00:00\.000000-05:00"
65 | string\(32\) "1970-01-02 00:00:00\.000000\+00:00"
66 | string\(32\) "2012-04-01 00:00:00\.000000\+09:00"
67 |
--------------------------------------------------------------------------------
/tests/immutable_008.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Test for TimecopDateTimeImmutable::createFromFormat()
3 | --SKIPIF--
4 | format("Y-m-d H:i:s.uP"));
33 | foreach ($tests_args as $args) {
34 | timecop_freeze($dt0);
35 | $dt1 = call_user_func_array(array("TimecopDateTimeImmutable","createFromFormat"), $args);
36 | var_dump($dt1->format("Y-m-d H:i:s.uP"));
37 | while (true) {
38 | /* test for equality between timecop_date_create_from_format() and date_create_from_format() */
39 | $start_time = time();
40 | timecop_freeze(new DateTime());
41 | $dt2 = call_user_func_array(array("TimecopDateTimeImmutable","createFromFormat"), $args);
42 | $dt3 = call_user_func_array(array("DateTimeImmutable","createFromFormat"), $args);
43 | if ($start_time === time()) {
44 | if ($dt2 && $dt3 && ($dt2->format("c") !== $dt3->format("c"))) {
45 | printf("TimecopDateTimeImmutable::createFromFormat('%s', '%s') is differ from DateTimeImmutable::createFromFormat() : %s !== %s\n",
46 | $args[0], $args[1], $dt2->format("c"), $dt3->format("c"));
47 | }
48 | break;
49 | }
50 | }
51 | }
52 | --EXPECTREGEX--
53 | string\(17\) "DateTimeImmutable"
54 | string\(32\) "2010-01-02 03:04:05\.678000-08:00"
55 | string\(32\) "2010-01-02 03:04:05\.(000|678)000-08:00"
56 | string\(32\) "2010-01-02 03:04:05\.(\1)000-08:00"
57 | string\(32\) "1990-01-02 03:04:05\.000000-08:00"
58 | string\(32\) "2010-09-02 03:04:05\.000000-07:00"
59 | string\(32\) "2010-12-24 03:04:05\.000000-08:00"
60 | string\(32\) "2010-01-02 05:00:00\.000000\+09:00"
61 | string\(32\) "2010-01-02 00:00:59\.000000-08:00"
62 | string\(32\) "2010-01-02 (00:00:00|03:04:05)\.654321-08:00"
63 | string\(32\) "2012-03-31 12:34:56\.000000-07:00"
64 | string\(32\) "1970-01-01 12:34:56\.000000-08:00"
65 | string\(32\) "1970-01-01 19:00:00\.000000-05:00"
66 | string\(32\) "1970-01-02 00:00:00\.000000\+00:00"
67 | string\(32\) "2012-04-01 00:00:00\.000000\+09:00"
68 |
--------------------------------------------------------------------------------
/tests/immutable_override_001.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Test for DateTimeImmutable/TimecopDateTimeImmutable/TimecopOrigDateTimeImmutable inheritance when function override is enabled
3 | --SKIPIF--
4 | = 0) {
31 | var_dump($dt1 instanceof DateTimeInterface);
32 | var_dump($dt2 instanceof DateTimeInterface);
33 | var_dump($dt3 instanceof DateTimeInterface);
34 | } else {
35 | // force pass if PHP < 5.5.0
36 | var_dump(true);
37 | var_dump(true);
38 | var_dump(true);
39 | }
40 | echo "===\n";
41 | var_dump($dt1->format("c") === $dt0->format("c"));
42 | var_dump($dt2->format("c") === $dt0->format("c"));
43 | var_dump($dt3->format("c") === $dt0->format("c"));
44 | --EXPECT--
45 | string(17) "DateTimeImmutable"
46 | string(24) "TimecopDateTimeImmutable"
47 | string(28) "TimecopOrigDateTimeImmutable"
48 | bool(true)
49 | bool(true)
50 | bool(false)
51 | bool(false)
52 | bool(false)
53 | bool(false)
54 | ===
55 | bool(true)
56 | bool(true)
57 | bool(true)
58 | ===
59 | bool(true)
60 | bool(true)
61 | bool(false)
62 |
--------------------------------------------------------------------------------
/tests/immutable_override_006.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Function overrideing test for date_create_immutable
3 | --SKIPIF--
4 | format("c"));
47 | }
48 |
49 | --EXPECT--
50 | string(17) "DateTimeImmutable"
51 | string(25) "2012-02-29T01:23:45-08:00"
52 | string(25) "2012-02-29T01:23:45-08:00"
53 | string(25) "2012-02-29T01:23:45-08:00"
54 | string(25) "2012-03-31T12:34:56-07:00"
55 | string(25) "2012-03-03T01:23:45-08:00"
56 | string(25) "1970-01-01T19:00:00-05:00"
57 | string(25) "1970-01-02T00:00:00+00:00"
58 | string(25) "2012-02-29T18:23:45+09:00"
59 |
--------------------------------------------------------------------------------
/tests/immutable_override_007.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Function overrideing test for date_create_immutable_from_format()
3 | --SKIPIF--
4 | format("Y-m-d H:i:s.uP"));
34 | foreach ($tests_args as $args) {
35 | timecop_freeze($dt0);
36 | $dt1 = call_user_func_array("date_create_immutable_from_format", $args);
37 | var_dump($dt1->format("Y-m-d H:i:s.uP"));
38 | while (true) {
39 | /* test for equality between timecop_date_create_from_format() and date_create_from_format() */
40 | $start_time = time();
41 | timecop_freeze(new TimecopOrigDateTime());
42 | $dt2 = call_user_func_array("date_create_immutable_from_format", $args);
43 | $dt3 = call_user_func_array("timecop_orig_date_create_immutable_from_format", $args);
44 | if ($start_time === time()) {
45 | if ($dt2 && $dt3 && ($dt2->format("c") !== $dt3->format("c"))) {
46 | printf("date_create_immutable_from_format('%s', '%s') is differ from timecop_orig_date_create_immutable_from_format() : %s !== %s\n",
47 | $args[0], $args[1], $dt2->format("c"), $dt3->format("c"));
48 | }
49 | break;
50 | }
51 | }
52 | }
53 | --EXPECTREGEX--
54 | string\(17\) "DateTimeImmutable"
55 | string\(32\) "2010-01-02 03:04:05\.678000-08:00"
56 | string\(32\) "2010-01-02 03:04:05\.(000|678)000-08:00"
57 | string\(32\) "2010-01-02 03:04:05\.(\1)000-08:00"
58 | string\(32\) "1990-01-02 03:04:05\.000000-08:00"
59 | string\(32\) "2010-09-02 03:04:05\.000000-07:00"
60 | string\(32\) "2010-12-24 03:04:05\.000000-08:00"
61 | string\(32\) "2010-01-02 05:00:00\.000000\+09:00"
62 | string\(32\) "2010-01-02 00:00:59\.000000-08:00"
63 | string\(32\) "2010-01-02 (00:00:00|03:04:05)\.654321-08:00"
64 | string\(32\) "2012-03-31 12:34:56\.000000-07:00"
65 | string\(32\) "1970-01-01 12:34:56\.000000-08:00"
66 | string\(32\) "1970-01-01 19:00:00\.000000-05:00"
67 | string\(32\) "1970-01-02 00:00:00\.000000\+00:00"
68 | string\(32\) "2012-04-01 00:00:00\.000000\+09:00"
69 | string\(32\) "1970-03-31 00:00:00\.000000\-08:00"
70 |
--------------------------------------------------------------------------------
/tests/immutable_override_008.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Method overrideing test for DateTimeImmutable::createFromFormat()
3 | --SKIPIF--
4 | format("Y-m-d H:i:s.uP"));
35 | foreach ($tests_args as $args) {
36 | timecop_freeze($dt0);
37 | $dt1 = call_user_func_array(array("DateTimeImmutable","createFromFormat"), $args);
38 | if (!$dt1 instanceof DateTimeImmutable) {
39 | // TODO: output an appropriate message
40 | echo get_class($dt1), "\n";
41 | }
42 |
43 | var_dump($dt1->format("Y-m-d H:i:s.uP"));
44 | while (true) {
45 | /* test for equality between timecop_date_create_from_format() and date_create_from_format() */
46 | $start_time = time();
47 | timecop_freeze(new TimecopOrigDateTime());
48 | $dt2 = call_user_func_array(array("DateTimeImmutable","createFromFormat"), $args);
49 | $dt3 = call_user_func_array(array("TimecopOrigDateTimeImmutable","createFromFormat"), $args);
50 | if ($start_time === time()) {
51 | if ($dt2 && $dt3 && ($dt2->format("c") !== $dt3->format("c"))) {
52 | printf("DateTimeImmutable::createFromFormat('%s', '%s') is differ from TimecopOrigDateTimeImmutable::createFromFormat() : %s !== %s\n",
53 | $args[0], $args[1], $dt2->format("c"), $dt3->format("c"));
54 | }
55 | break;
56 | }
57 | }
58 | }
59 | --EXPECTREGEX--
60 | string\(17\) "DateTimeImmutable"
61 | string\(32\) "2010-01-02 03:04:05\.678000-08:00"
62 | string\(32\) "2010-01-02 03:04:05\.(000|678)000-08:00"
63 | string\(32\) "2010-01-02 03:04:05\.(\1)000-08:00"
64 | string\(32\) "1990-01-02 03:04:05\.000000-08:00"
65 | string\(32\) "2010-09-02 03:04:05\.000000-07:00"
66 | string\(32\) "2010-12-24 03:04:05\.000000-08:00"
67 | string\(32\) "2010-01-02 05:00:00\.000000\+09:00"
68 | string\(32\) "2010-01-02 00:00:59\.000000-08:00"
69 | string\(32\) "2010-01-02 (00:00:00|03:04:05)\.654321-08:00"
70 | string\(32\) "2012-03-31 12:34:56\.000000-07:00"
71 | string\(32\) "1970-01-01 12:34:56\.000000-08:00"
72 | string\(32\) "1970-01-01 19:00:00\.000000-05:00"
73 | string\(32\) "1970-01-02 00:00:00\.000000\+00:00"
74 | string\(32\) "2012-04-01 00:00:00\.000000\+09:00"
75 | string\(32\) "1970-03-31 00:00:00\.000000\-08:00"
76 |
--------------------------------------------------------------------------------
/tests/issue_009.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for issue #9 (Issue with using timecop constructor)
3 | --SKIPIF--
4 | setTime(0, 0, 0);
20 | }
21 |
22 | public function __toString() {
23 | return $this->format('Y-m-d');
24 | }
25 | }
26 | timecop_freeze(strtotime("2010-01-01"));
27 | $dt1 = new Date();
28 | echo $dt1, "\n";
29 | $dt2 = new Date("2020-12-31");
30 | echo $dt2, "\n";
31 | $dt3 = new Date("2030-06-15", new \DateTimeZone("UTC"));
32 | echo $dt3, "\n";
33 | --EXPECT--
34 | 2010-01-01
35 | 2020-12-31
36 | 2030-06-15
37 |
--------------------------------------------------------------------------------
/tests/issue_010.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for issue #10 (Timecop segfaults when set_error_handler throws an exception)
3 | --SKIPIF--
4 | format("c"));
13 | --EXPECT--
14 | string(25) "2044-06-18T00:00:00+00:00"
15 |
--------------------------------------------------------------------------------
/tests/issue_014.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Check for issue #14 (All PHPUnit assertions involving DateTime comparison fail with PHP 7.1)
3 | --SKIPIF--
4 | voidDate = new \DateTime();
19 | }
20 | public function getvoidDate()
21 | {
22 | return $this->voidDate;
23 | }
24 | }
25 | function test_invoice_void()
26 | {
27 | $now = new \DateTime();
28 | timecop_freeze($now);
29 |
30 | $invoice = new CustomerInvoice();
31 | $invoice->void();
32 |
33 | var_dump($now == $invoice->getVoidDate());
34 | }
35 | test_invoice_void();
36 | --EXPECT--
37 | bool(true)
38 |
--------------------------------------------------------------------------------
/tests/tests-skipcheck.inc.php:
--------------------------------------------------------------------------------
1 | ";
3 |
4 | if(!extension_loaded('timecop')) {
5 | dl('timecop.' . PHP_SHLIB_SUFFIX);
6 | }
7 | $module = 'timecop';
8 | $functions = get_extension_funcs($module);
9 | echo "Functions available in the test extension:$br\n";
10 | foreach($functions as $func) {
11 | echo $func."$br\n";
12 | }
13 | echo "$br\n";
14 | $function = 'timecop_time';
15 | if (extension_loaded($module)) {
16 | echo timecop_time()."$br\n";
17 | $_SERVER['REQUEST_TIME'] = PHP_INT_MAX;
18 | echo timecop_time()."$br\n";
19 | } else {
20 | echo "Module $module is not compiled into PHP";
21 | }
22 |
23 | ?>
24 |
--------------------------------------------------------------------------------
/timecop_php7.c:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2012-2017 Yoshio HANAWA
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 |
25 | #ifdef HAVE_CONFIG_H
26 | #include "config.h"
27 | #endif
28 |
29 | #include "php.h"
30 | #include "php_ini.h"
31 | #include "ext/standard/info.h"
32 |
33 | #include "php_timecop.h"
34 |
35 | #ifdef ZFS
36 | #include "TSRM.h"
37 | #endif
38 |
39 | ZEND_DECLARE_MODULE_GLOBALS(timecop)
40 |
41 | static void timecop_globals_ctor(zend_timecop_globals *globals) {
42 | /* Initialize your global struct */
43 | globals->func_override = 1;
44 | globals->sync_request_time = 1;
45 | ZVAL_NULL(&globals->orig_request_time);
46 | globals->timecop_mode = TIMECOP_MODE_REALTIME;
47 | globals->freezed_time.sec = 0;
48 | globals->freezed_time.usec = 0;
49 | globals->travel_origin.sec = 0;
50 | globals->travel_origin.usec = 0;
51 | globals->travel_offset.sec = 0;
52 | globals->travel_offset.usec = 0;
53 | globals->scaling_factor = 1;
54 | globals->ce_DateTimeZone = NULL;
55 | globals->ce_DateTimeInterface = NULL;
56 | globals->ce_DateTime = NULL;
57 | globals->ce_TimecopDateTime = NULL;
58 | globals->ce_DateTimeImmutable = NULL;
59 | globals->ce_TimecopDateTimeImmutable = NULL;
60 | }
61 |
62 | static const struct timecop_override_func_entry timecop_override_func_table[] = {
63 | TIMECOP_OFE("time"),
64 | TIMECOP_OFE("mktime"),
65 | TIMECOP_OFE("gmmktime"),
66 | TIMECOP_OFE("date"),
67 | TIMECOP_OFE("gmdate"),
68 | TIMECOP_OFE("idate"),
69 | TIMECOP_OFE("getdate"),
70 | TIMECOP_OFE("localtime"),
71 | TIMECOP_OFE("strtotime"),
72 | TIMECOP_OFE("strftime"),
73 | TIMECOP_OFE("gmstrftime"),
74 | #ifdef HAVE_GETTIMEOFDAY
75 | TIMECOP_OFE("microtime"),
76 | TIMECOP_OFE("gettimeofday"),
77 | #endif
78 | TIMECOP_OFE("unixtojd"),
79 | TIMECOP_OFE("date_create"),
80 | TIMECOP_OFE("date_create_from_format"),
81 | TIMECOP_OFE("date_create_immutable"),
82 | TIMECOP_OFE("date_create_immutable_from_format"),
83 | {NULL, NULL, NULL}
84 | };
85 |
86 | static const struct timecop_override_class_entry timecop_override_class_table[] = {
87 | TIMECOP_OCE("datetime", "__construct"),
88 | TIMECOP_OCE("datetime", "createfromformat"),
89 | TIMECOP_OCE("datetimeimmutable", "__construct"),
90 | TIMECOP_OCE("datetimeimmutable", "createfromformat"),
91 | {NULL, NULL, NULL, NULL}
92 | };
93 |
94 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_freeze, 0, 0, 1)
95 | ZEND_ARG_INFO(0, timestamp)
96 | ZEND_END_ARG_INFO()
97 |
98 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_travel, 0, 0, 1)
99 | ZEND_ARG_INFO(0, timestamp)
100 | ZEND_END_ARG_INFO()
101 |
102 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_scale, 0, 0, 1)
103 | ZEND_ARG_INFO(0, scale)
104 | ZEND_END_ARG_INFO()
105 |
106 | ZEND_BEGIN_ARG_INFO(arginfo_timecop_return, 0)
107 | ZEND_END_ARG_INFO()
108 |
109 | ZEND_BEGIN_ARG_INFO(arginfo_timecop_time, 0)
110 | ZEND_END_ARG_INFO()
111 |
112 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_mktime, 0, 0, 0)
113 | ZEND_ARG_INFO(0, hour)
114 | ZEND_ARG_INFO(0, min)
115 | ZEND_ARG_INFO(0, sec)
116 | ZEND_ARG_INFO(0, mon)
117 | ZEND_ARG_INFO(0, day)
118 | ZEND_ARG_INFO(0, year)
119 | ZEND_END_ARG_INFO()
120 |
121 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_gmmktime, 0, 0, 0)
122 | ZEND_ARG_INFO(0, hour)
123 | ZEND_ARG_INFO(0, min)
124 | ZEND_ARG_INFO(0, sec)
125 | ZEND_ARG_INFO(0, mon)
126 | ZEND_ARG_INFO(0, day)
127 | ZEND_ARG_INFO(0, year)
128 | ZEND_END_ARG_INFO()
129 |
130 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_date, 0, 0, 1)
131 | ZEND_ARG_INFO(0, format)
132 | ZEND_ARG_INFO(0, timestamp)
133 | ZEND_END_ARG_INFO()
134 |
135 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_gmdate, 0, 0, 1)
136 | ZEND_ARG_INFO(0, format)
137 | ZEND_ARG_INFO(0, timestamp)
138 | ZEND_END_ARG_INFO()
139 |
140 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_idate, 0, 0, 1)
141 | ZEND_ARG_INFO(0, format)
142 | ZEND_ARG_INFO(0, timestamp)
143 | ZEND_END_ARG_INFO()
144 |
145 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_getdate, 0, 0, 0)
146 | ZEND_ARG_INFO(0, timestamp)
147 | ZEND_END_ARG_INFO()
148 |
149 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_localtime, 0, 0, 0)
150 | ZEND_ARG_INFO(0, timestamp)
151 | ZEND_ARG_INFO(0, associative_array)
152 | ZEND_END_ARG_INFO()
153 |
154 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_strtotime, 0, 0, 1)
155 | ZEND_ARG_INFO(0, time)
156 | ZEND_ARG_INFO(0, now)
157 | ZEND_END_ARG_INFO()
158 |
159 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_strftime, 0, 0, 1)
160 | ZEND_ARG_INFO(0, format)
161 | ZEND_ARG_INFO(0, timestamp)
162 | ZEND_END_ARG_INFO()
163 |
164 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_gmstrftime, 0, 0, 1)
165 | ZEND_ARG_INFO(0, format)
166 | ZEND_ARG_INFO(0, timestamp)
167 | ZEND_END_ARG_INFO()
168 |
169 | #ifdef HAVE_GETTIMEOFDAY
170 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_microtime, 0, 0, 0)
171 | ZEND_ARG_INFO(0, get_as_float)
172 | ZEND_END_ARG_INFO()
173 |
174 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_gettimeofday, 0, 0, 0)
175 | ZEND_ARG_INFO(0, get_as_float)
176 | ZEND_END_ARG_INFO()
177 | #endif
178 |
179 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_unixtojd, 0, 0, 0)
180 | ZEND_ARG_INFO(0, timestamp)
181 | ZEND_END_ARG_INFO()
182 |
183 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_date_create, 0, 0, 0)
184 | ZEND_ARG_INFO(0, time)
185 | ZEND_ARG_INFO(0, object)
186 | ZEND_END_ARG_INFO()
187 |
188 | ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_date_create_from_format, 0, 0, 2)
189 | ZEND_ARG_INFO(0, format)
190 | ZEND_ARG_INFO(0, time)
191 | #if PHP_VERSION_ID >= 70200
192 | ZEND_ARG_OBJ_INFO(0, object, DateTimeZone, 1)
193 | #else
194 | ZEND_ARG_INFO(0, object)
195 | #endif
196 | ZEND_END_ARG_INFO()
197 |
198 | /* {{{ timecop_functions[] */
199 | const zend_function_entry timecop_functions[] = {
200 | PHP_FE(timecop_freeze, arginfo_timecop_freeze)
201 | PHP_FE(timecop_travel, arginfo_timecop_travel)
202 | PHP_FE(timecop_scale, arginfo_timecop_scale)
203 | PHP_FE(timecop_return, arginfo_timecop_return)
204 | PHP_FE(timecop_time, arginfo_timecop_time)
205 | PHP_FE(timecop_mktime, arginfo_timecop_mktime)
206 | PHP_FE(timecop_gmmktime, arginfo_timecop_gmmktime)
207 | PHP_FE(timecop_date, arginfo_timecop_date)
208 | PHP_FE(timecop_gmdate, arginfo_timecop_gmdate)
209 | PHP_FE(timecop_idate, arginfo_timecop_idate)
210 | PHP_FE(timecop_getdate, arginfo_timecop_getdate)
211 | PHP_FE(timecop_localtime, arginfo_timecop_localtime)
212 | PHP_FE(timecop_strtotime, arginfo_timecop_strtotime)
213 | PHP_FE(timecop_strftime, arginfo_timecop_strftime)
214 | PHP_FE(timecop_gmstrftime, arginfo_timecop_gmstrftime)
215 | #ifdef HAVE_GETTIMEOFDAY
216 | PHP_FE(timecop_microtime, arginfo_timecop_microtime)
217 | PHP_FE(timecop_gettimeofday, arginfo_timecop_gettimeofday)
218 | #endif
219 | PHP_FE(timecop_unixtojd, arginfo_timecop_unixtojd)
220 | PHP_FE(timecop_date_create, arginfo_timecop_date_create)
221 | PHP_FE(timecop_date_create_from_format, arginfo_timecop_date_create_from_format)
222 | PHP_FE(timecop_date_create_immutable, arginfo_timecop_date_create)
223 | PHP_FE(timecop_date_create_immutable_from_format, arginfo_timecop_date_create_from_format)
224 | {NULL, NULL, NULL}
225 | };
226 | /* }}} */
227 |
228 | /* declare method parameters, */
229 |
230 | /* each method can have its own parameters and visibility */
231 | static zend_function_entry timecop_funcs_timecop[] = {
232 | PHP_ME_MAPPING(freeze, timecop_freeze, arginfo_timecop_travel, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
233 | PHP_ME_MAPPING(travel, timecop_travel, arginfo_timecop_travel, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
234 | PHP_ME_MAPPING(scale, timecop_scale, arginfo_timecop_scale, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
235 | PHP_ME_MAPPING(return, timecop_return, arginfo_timecop_return, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
236 | {NULL, NULL, NULL}
237 | };
238 |
239 | static zend_function_entry timecop_funcs_date[] = {
240 | PHP_ME(TimecopDateTime, __construct, arginfo_timecop_date_create,
241 | ZEND_ACC_CTOR | ZEND_ACC_PUBLIC)
242 | PHP_ME_MAPPING(createFromFormat, timecop_date_create_from_format, arginfo_timecop_date_create_from_format,
243 | ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
244 | {NULL, NULL, NULL}
245 | };
246 |
247 | static zend_function_entry timecop_funcs_orig_date[] = {
248 | PHP_ME(TimecopOrigDateTime, __construct, arginfo_timecop_date_create,
249 | ZEND_ACC_CTOR | ZEND_ACC_PUBLIC)
250 | {NULL, NULL, NULL}
251 | };
252 |
253 | static zend_function_entry timecop_funcs_immutable[] = {
254 | PHP_ME(TimecopDateTimeImmutable, __construct, arginfo_timecop_date_create,
255 | ZEND_ACC_CTOR | ZEND_ACC_PUBLIC)
256 | PHP_ME_MAPPING(createFromFormat, timecop_date_create_immutable_from_format, arginfo_timecop_date_create_from_format,
257 | ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
258 | {NULL, NULL, NULL}
259 | };
260 |
261 | static zend_function_entry timecop_funcs_orig_immutable[] = {
262 | PHP_ME(TimecopOrigDateTimeImmutable, __construct, arginfo_timecop_date_create,
263 | ZEND_ACC_CTOR | ZEND_ACC_PUBLIC)
264 | {NULL, NULL, NULL}
265 | };
266 |
267 | #define MKTIME_NUM_ARGS 6
268 |
269 | #define TIMECOP_CALL_FUNCTION(func_name, index_to_fill_timestamp) \
270 | _timecop_call_function(INTERNAL_FUNCTION_PARAM_PASSTHRU, ORIG_FUNC_NAME(func_name), index_to_fill_timestamp);
271 |
272 | #define TIMECOP_CALL_MKTIME(mktime_func_name, date_func_name) \
273 | _timecop_call_mktime(INTERNAL_FUNCTION_PARAM_PASSTHRU, ORIG_FUNC_NAME(mktime_func_name), ORIG_FUNC_NAME(date_func_name));
274 |
275 | static void timecop_globals_ctor(zend_timecop_globals *globals);
276 |
277 | static int register_timecop_classes();
278 | static int timecop_func_override();
279 | static int timecop_class_override();
280 | static int timecop_func_override_clear();
281 | static int timecop_class_override_clear();
282 |
283 | static int update_request_time(zend_long unixtime);
284 | static int restore_request_time();
285 |
286 | static int fill_mktime_params(zval *fill_params, const char *date_function_name, int from);
287 | static int get_formatted_mock_time(zval *time, zval *timezone_obj, zval *retval_time, zval *retval_timezone);
288 | static long get_mock_fraction(zval *time, zval *timezone_obj);
289 |
290 | static void _timecop_call_function(INTERNAL_FUNCTION_PARAMETERS, const char *function_name, int index_to_fill_timestamp);
291 | static void _timecop_call_mktime(INTERNAL_FUNCTION_PARAMETERS, const char *mktime_function_name, const char *date_function_name);
292 |
293 | static int get_mock_timeval(tc_timeval *fixed, const tc_timeval *now);
294 | static inline zend_long mock_timestamp();
295 |
296 | static int get_timeval_from_datetime(tc_timeval *tp, zval *dt);
297 | static int get_current_time(tc_timeval *now);
298 |
299 | static void _timecop_orig_datetime_constructor(INTERNAL_FUNCTION_PARAMETERS, int immutable);
300 | static inline void _timecop_date_create(INTERNAL_FUNCTION_PARAMETERS, int immutable);
301 | static inline void _timecop_datetime_constructor(INTERNAL_FUNCTION_PARAMETERS, int immutable);
302 | static void _timecop_datetime_constructor_ex(INTERNAL_FUNCTION_PARAMETERS, zval *obj, int immutable);
303 |
304 | static inline zval* _call_php_method_with_0_params(zval *object_pp, zend_class_entry *obj_ce, const char *method_name, zval *retval_ptr);
305 | static inline zval* _call_php_method_with_1_params(zval *object_pp, zend_class_entry *obj_ce, const char *method_name, zval *retval_ptr, zval *arg1);
306 | static inline zval* _call_php_method_with_2_params(zval *object_pp, zend_class_entry *obj_ce, const char *method_name, zval *retval_ptr, zval *arg1, zval *arg2);
307 | static inline zval* _call_php_method(zval *object_pp, zend_class_entry *obj_ce, const char *method_name, zval *retval_ptr, int param_count, zval* arg1, zval* arg2);
308 | static inline void _call_php_function_with_0_params(const char *function_name, zval *retval_ptr);
309 | static inline void _call_php_function_with_1_params(const char *function_name, zval *retval_ptr, zval *arg1);
310 | static inline void _call_php_function_with_2_params(const char *function_name, zval *retval_ptr, zval *arg1, zval *arg2);
311 | static void _call_php_function_with_3_params(const char *function_name, zval *retval_ptr, zval *arg1, zval *arg2, zval *arg3);
312 | static inline void _call_php_function_with_params(const char *function_name, zval *retval_ptr, uint32_t param_count, zval params[]);
313 |
314 | /* {{{ timecop_module_entry
315 | */
316 | zend_module_entry timecop_module_entry = {
317 | #if ZEND_MODULE_API_NO >= 20010901
318 | STANDARD_MODULE_HEADER,
319 | #endif
320 | "timecop",
321 | timecop_functions,
322 | PHP_MINIT(timecop),
323 | PHP_MSHUTDOWN(timecop),
324 | PHP_RINIT(timecop),
325 | PHP_RSHUTDOWN(timecop),
326 | PHP_MINFO(timecop),
327 | #if ZEND_MODULE_API_NO >= 20010901
328 | PHP_TIMECOP_VERSION,
329 | #endif
330 | STANDARD_MODULE_PROPERTIES
331 | };
332 | /* }}} */
333 |
334 | #ifdef COMPILE_DL_TIMECOP
335 | # ifdef ZTS
336 | ZEND_TSRMLS_CACHE_DEFINE();
337 | # endif
338 | ZEND_GET_MODULE(timecop)
339 | #endif
340 |
341 | /* {{{ PHP_INI
342 | */
343 | PHP_INI_BEGIN()
344 | STD_PHP_INI_ENTRY("timecop.func_override", "1",
345 | PHP_INI_SYSTEM, OnUpdateLong, func_override, zend_timecop_globals, timecop_globals)
346 | STD_PHP_INI_ENTRY("timecop.sync_request_time", "1",
347 | PHP_INI_SYSTEM, OnUpdateLong, sync_request_time, zend_timecop_globals, timecop_globals)
348 | PHP_INI_END()
349 | /* }}} */
350 |
351 | /* {{{ PHP_MINIT_FUNCTION
352 | */
353 | PHP_MINIT_FUNCTION(timecop)
354 | {
355 | ZEND_INIT_MODULE_GLOBALS(timecop, timecop_globals_ctor, NULL);
356 | REGISTER_INI_ENTRIES();
357 | register_timecop_classes();
358 | return SUCCESS;
359 | }
360 | /* }}} */
361 |
362 | /* {{{ PHP_MSHUTDOWN_FUNCTION
363 | */
364 | PHP_MSHUTDOWN_FUNCTION(timecop)
365 | {
366 | UNREGISTER_INI_ENTRIES();
367 | return SUCCESS;
368 | }
369 | /* }}} */
370 |
371 | /* {{{ PHP_RINIT_FUNCTION(timecop) */
372 | PHP_RINIT_FUNCTION(timecop)
373 | {
374 | #if defined(COMPILE_DL_TIMECOP) && defined(ZTS)
375 | ZEND_TSRMLS_CACHE_UPDATE();
376 | #endif
377 |
378 | if (TIMECOP_G(func_override)) {
379 | if (SUCCESS != timecop_func_override() ||
380 | SUCCESS != timecop_class_override()) {
381 | return FAILURE;
382 | }
383 | }
384 |
385 | return SUCCESS;
386 | }
387 | /* }}} */
388 |
389 | /* {{{ PHP_RSHUTDOWN_FUNCTION(timecop) */
390 | PHP_RSHUTDOWN_FUNCTION(timecop)
391 | {
392 | if (TIMECOP_G(func_override)) {
393 | timecop_func_override_clear();
394 | timecop_class_override_clear();
395 | }
396 |
397 | if (Z_TYPE(TIMECOP_G(orig_request_time)) == IS_NULL) {
398 | restore_request_time();
399 | }
400 |
401 | TIMECOP_G(timecop_mode) = TIMECOP_MODE_REALTIME;
402 | TIMECOP_G(scaling_factor) = 1;
403 |
404 | return SUCCESS;
405 | }
406 | /* }}} */
407 |
408 |
409 | /* {{{ PHP_MINFO_FUNCTION
410 | */
411 | PHP_MINFO_FUNCTION(timecop)
412 | {
413 | php_info_print_table_start();
414 | php_info_print_table_header(2, "timecop", "enabled");
415 | php_info_print_table_row(2, "Version", PHP_TIMECOP_VERSION);
416 | php_info_print_table_end();
417 |
418 | DISPLAY_INI_ENTRIES();
419 | }
420 | /* }}} */
421 |
422 | static int register_timecop_classes()
423 | {
424 | zend_class_entry ce;
425 | zend_class_entry *tmp, *date_ce, *timezone_ce, *immutable_ce, *interface_ce;
426 |
427 | date_ce = zend_hash_str_find_ptr(CG(class_table), "datetime", sizeof("datetime")-1);
428 | if (date_ce == NULL) {
429 | /* DateTime must be initialized before */
430 | php_error_docref("https://github.com/hnw/php-timecop", E_WARNING,
431 | "timecop couldn't find class %s.", "DateTime");
432 | return SUCCESS;
433 | }
434 |
435 | timezone_ce = zend_hash_str_find_ptr(CG(class_table), "datetimezone", sizeof("datetimezone")-1);
436 | if (timezone_ce == NULL) {
437 | /* DateTime must be initialized before */
438 | php_error_docref("https://github.com/hnw/php-timecop", E_WARNING,
439 | "timecop couldn't find class %s.", "DateTimeZone");
440 | return SUCCESS;
441 | }
442 |
443 | immutable_ce = zend_hash_str_find_ptr(CG(class_table), "datetimeimmutable", sizeof("datetimeimmutable")-1);
444 | if (immutable_ce == NULL) {
445 | /* DateTimeImmutable must be initialized before */
446 | php_error_docref("https://github.com/hnw/php-timecop", E_WARNING,
447 | "timecop couldn't find class %s.", "DateTimeImmutable");
448 | return SUCCESS;
449 | }
450 |
451 | interface_ce = zend_hash_str_find_ptr(CG(class_table), "datetimeinterface", sizeof("datetimeinterface")-1);
452 | if (interface_ce == NULL) {
453 | /* DateTimeInterface must be initialized before */
454 | php_error_docref("https://github.com/hnw/php-timecop", E_WARNING,
455 | "timecop couldn't find interface %s.", "DateTimeInterface");
456 | return SUCCESS;
457 | }
458 |
459 | INIT_CLASS_ENTRY(ce, "Timecop", timecop_funcs_timecop);
460 | zend_register_internal_class(&ce);
461 |
462 | TIMECOP_G(ce_DateTimeZone) = timezone_ce;
463 | TIMECOP_G(ce_DateTimeInterface) = interface_ce;
464 |
465 | /* replace DateTime */
466 | INIT_CLASS_ENTRY(ce, "TimecopDateTime", timecop_funcs_date);
467 | tmp = zend_register_internal_class_ex(&ce, date_ce);
468 | tmp->create_object = date_ce->create_object;
469 |
470 | TIMECOP_G(ce_DateTime) = date_ce;
471 | TIMECOP_G(ce_TimecopDateTime) = tmp;
472 |
473 | INIT_CLASS_ENTRY(ce, "TimecopOrigDateTime", timecop_funcs_orig_date);
474 | tmp = zend_register_internal_class_ex(&ce, date_ce);
475 | tmp->create_object = date_ce->create_object;
476 |
477 | /* replace DateTimeImmutable */
478 | INIT_CLASS_ENTRY(ce, "TimecopDateTimeImmutable", timecop_funcs_immutable);
479 | tmp = zend_register_internal_class_ex(&ce, immutable_ce);
480 | tmp->create_object = immutable_ce->create_object;
481 |
482 | TIMECOP_G(ce_DateTimeImmutable) = immutable_ce;
483 | TIMECOP_G(ce_TimecopDateTimeImmutable) = tmp;
484 |
485 | INIT_CLASS_ENTRY(ce, "TimecopOrigDateTimeImmutable", timecop_funcs_orig_immutable);
486 | tmp = zend_register_internal_class_ex(&ce, immutable_ce);
487 | tmp->create_object = immutable_ce->create_object;
488 |
489 | return SUCCESS;
490 | }
491 |
492 | static int timecop_func_override()
493 | {
494 | const struct timecop_override_func_entry *p;
495 | zend_function *zf_orig, *zf_ovrd, *zf_save;
496 |
497 | p = &(timecop_override_func_table[0]);
498 | while (p->orig_func != NULL) {
499 | zf_orig = zend_hash_str_find_ptr(EG(function_table), p->orig_func, strlen(p->orig_func));
500 | if (zf_orig == NULL) {
501 | /* Do nothing. Because some functions are introduced by optional extensions. */
502 | p++;
503 | continue;
504 | }
505 |
506 | zf_ovrd = zend_hash_str_find_ptr(EG(function_table), p->ovrd_func, strlen(p->ovrd_func));
507 | if (zf_ovrd == NULL) {
508 | php_error_docref("https://github.com/hnw/php-timecop", E_WARNING,
509 | "timecop couldn't find function %s.", p->ovrd_func);
510 | p++;
511 | continue;
512 | }
513 |
514 | zf_save = zend_hash_str_find_ptr(EG(function_table), p->save_func, strlen(p->save_func));
515 | if (zf_save != NULL) {
516 | php_error_docref("https://github.com/hnw/php-timecop", E_WARNING,
517 | "timecop couldn't create function %s because already exists.",
518 | p->save_func);
519 | p++;
520 | continue;
521 | }
522 |
523 | TIMECOP_ASSERT(zf_orig->type == ZEND_INTERNAL_FUNCTION);
524 | TIMECOP_ASSERT(zf_ovrd->type == ZEND_INTERNAL_FUNCTION);
525 |
526 | zend_hash_str_add_mem(EG(function_table), p->save_func, strlen(p->save_func),
527 | zf_orig, sizeof(zend_internal_function));
528 | function_add_ref(zf_orig);
529 |
530 | GUARD_FUNCTION_ARG_INFO_BEGIN(zf_orig);
531 | zend_hash_str_update_mem(EG(function_table), p->orig_func, strlen(p->orig_func),
532 | zf_ovrd, sizeof(zend_internal_function));
533 | GUARD_FUNCTION_ARG_INFO_END();
534 | function_add_ref(zf_ovrd);
535 |
536 | p++;
537 | }
538 | return SUCCESS;
539 | }
540 |
541 | static int timecop_class_override()
542 | {
543 | const struct timecop_override_class_entry *p;
544 | zend_class_entry *ce_orig, *ce_ovrd;
545 | zend_function *zf_orig, *zf_ovrd, *zf_save, *zf_new;
546 |
547 | p = &(timecop_override_class_table[0]);
548 | while (p->orig_class != NULL) {
549 | ce_orig = zend_hash_str_find_ptr(EG(class_table), p->orig_class, strlen(p->orig_class));
550 | if (ce_orig == NULL) {
551 | php_error_docref("https://github.com/hnw/php-timecop", E_WARNING,
552 | "timecop couldn't find class %s.", p->orig_class);
553 | p++;
554 | continue;
555 | }
556 |
557 | ce_ovrd = zend_hash_str_find_ptr(EG(class_table), p->ovrd_class, strlen(p->ovrd_class));
558 | if (ce_ovrd == NULL) {
559 | php_error_docref("https://github.com/hnw/php-timecop", E_WARNING,
560 | "timecop couldn't find class %s.", p->ovrd_class);
561 | p++;
562 | continue;
563 | }
564 |
565 | zf_orig = zend_hash_str_find_ptr(&ce_orig->function_table,
566 | p->orig_method, strlen(p->orig_method));
567 | if (zf_orig == NULL) {
568 | php_error_docref("https://github.com/hnw/php-timecop", E_WARNING,
569 | "timecop couldn't find method %s::%s.",
570 | p->orig_class, p->orig_method);
571 | p++;
572 | continue;
573 | }
574 |
575 | zf_ovrd = zend_hash_str_find_ptr(&ce_ovrd->function_table,
576 | p->orig_method, strlen(p->orig_method));
577 | if (zf_ovrd == NULL) {
578 | php_error_docref("https://github.com/hnw/php-timecop", E_WARNING,
579 | "timecop couldn't find method %s::%s.",
580 | p->ovrd_class, p->orig_method);
581 | p++;
582 | continue;
583 | }
584 |
585 | zf_save = zend_hash_str_find_ptr(&ce_orig->function_table,
586 | p->save_method, strlen(p->save_method));
587 | if (zf_save != NULL) {
588 | php_error_docref("https://github.com/hnw/php-timecop", E_WARNING,
589 | "timecop couldn't create method %s::%s because already exists.",
590 | p->orig_class, p->save_method);
591 | p++;
592 | continue;
593 | }
594 |
595 | TIMECOP_ASSERT(zf_orig->type == ZEND_INTERNAL_FUNCTION);
596 | TIMECOP_ASSERT(ce_orig->type & ZEND_INTERNAL_CLASS);
597 | TIMECOP_ASSERT(zf_ovrd->type == ZEND_INTERNAL_FUNCTION);
598 | TIMECOP_ASSERT(ce_ovrd->type & ZEND_INTERNAL_CLASS);
599 |
600 | zend_hash_str_add_mem(&ce_orig->function_table,
601 | p->save_method, strlen(p->save_method),
602 | zf_orig, sizeof(zend_internal_function));
603 | function_add_ref(zf_orig);
604 |
605 | zf_new = zend_hash_str_update_mem(&ce_orig->function_table,
606 | p->orig_method, strlen(p->orig_method),
607 | zf_ovrd, sizeof(zend_internal_function));
608 | function_add_ref(zf_ovrd);
609 |
610 | TIMECOP_ASSERT(zf_new != NULL);
611 | TIMECOP_ASSERT(zf_new != zf_orig);
612 |
613 | if (strcmp(p->orig_method, "__construct") == 0) {
614 | ce_orig->constructor = zf_new;
615 | }
616 | p++;
617 | }
618 | return SUCCESS;
619 | }
620 |
621 | /* clear function overriding. */
622 | static int timecop_func_override_clear()
623 | {
624 | const struct timecop_override_func_entry *p;
625 | zend_function *zf_orig, *zf_ovld;
626 |
627 | p = &(timecop_override_func_table[0]);
628 | while (p->orig_func != NULL) {
629 | zf_orig = zend_hash_str_find_ptr(EG(function_table),
630 | p->save_func, strlen(p->save_func));
631 | zf_ovld = zend_hash_str_find_ptr(EG(function_table),
632 | p->orig_func, strlen(p->orig_func));
633 | if (zf_orig == NULL || zf_ovld == NULL) {
634 | p++;
635 | continue;
636 | }
637 |
638 | GUARD_FUNCTION_ARG_INFO_BEGIN(zf_ovld);
639 | zend_hash_str_update_mem(EG(function_table), p->orig_func, strlen(p->orig_func),
640 | zf_orig, sizeof(zend_internal_function));
641 | GUARD_FUNCTION_ARG_INFO_END();
642 | function_add_ref(zf_orig);
643 |
644 | GUARD_FUNCTION_ARG_INFO_BEGIN(zf_orig);
645 | zend_hash_str_del(EG(function_table), p->save_func, strlen(p->save_func));
646 | GUARD_FUNCTION_ARG_INFO_END();
647 |
648 | p++;
649 | }
650 | return SUCCESS;
651 | }
652 |
653 | static int timecop_class_override_clear()
654 | {
655 | const struct timecop_override_class_entry *p;
656 | zend_class_entry *ce_orig;
657 | zend_function *zf_orig;
658 |
659 | p = &(timecop_override_class_table[0]);
660 | while (p->orig_class != NULL) {
661 | ce_orig = zend_hash_str_find_ptr(EG(class_table),
662 | p->orig_class, strlen(p->orig_class));
663 | if (ce_orig == NULL) {
664 | php_error_docref("https://github.com/hnw/php-timecop", E_WARNING,
665 | "timecop couldn't find class %s.", p->orig_class);
666 | p++;
667 | continue;
668 | }
669 |
670 | zf_orig = zend_hash_str_find_ptr(&ce_orig->function_table,
671 | p->save_method, strlen(p->save_method));
672 | if (zf_orig == NULL) {
673 | php_error_docref("https://github.com/hnw/php-timecop", E_WARNING,
674 | "timecop couldn't find method %s::%s.",
675 | p->orig_class, p->save_method);
676 | p++;
677 | continue;
678 | }
679 |
680 | zend_hash_str_update_mem(&ce_orig->function_table, p->orig_method, strlen(p->orig_method),
681 | zf_orig, sizeof(zend_internal_function));
682 | function_add_ref(zf_orig);
683 |
684 | zend_hash_str_del(&ce_orig->function_table, p->save_method, strlen(p->save_method));
685 |
686 | if (strcmp(p->orig_method, "__construct") == 0) {
687 | ce_orig->constructor = zf_orig;
688 | }
689 | p++;
690 | }
691 | return SUCCESS;
692 | }
693 |
694 | static int update_request_time(zend_long unixtime)
695 | {
696 | zval *server_vars, *request_time, tmp;
697 |
698 | server_vars = zend_hash_str_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER")-1);
699 | if (server_vars != NULL && Z_TYPE_P(server_vars) == IS_ARRAY) {
700 | request_time = zend_hash_str_find(Z_ARRVAL_P(server_vars), "REQUEST_TIME", sizeof("REQUEST_TIME")-1);
701 | if (request_time != NULL) {
702 | if (Z_TYPE(TIMECOP_G(orig_request_time)) == IS_NULL) {
703 | ZVAL_COPY_VALUE(&TIMECOP_G(orig_request_time), request_time);
704 | }
705 | }
706 | ZVAL_LONG(&tmp, unixtime);
707 | zend_hash_str_update(Z_ARRVAL_P(server_vars),
708 | "REQUEST_TIME", sizeof("REQUEST_TIME")-1,
709 | &tmp);
710 | }
711 |
712 | return SUCCESS;
713 | }
714 |
715 | static int restore_request_time()
716 | {
717 | zval *server_vars;
718 |
719 | server_vars = zend_hash_str_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER")-1);
720 | if (Z_TYPE(TIMECOP_G(orig_request_time)) != IS_NULL &&
721 | server_vars != NULL && Z_TYPE_P(server_vars) == IS_ARRAY) {
722 | zend_hash_str_update(Z_ARRVAL_P(server_vars),
723 | "REQUEST_TIME", sizeof("REQUEST_TIME")-1,
724 | &TIMECOP_G(orig_request_time));
725 | ZVAL_NULL(&TIMECOP_G(orig_request_time));
726 | }
727 |
728 | return SUCCESS;
729 | }
730 |
731 | static int fill_mktime_params(zval *fill_params, const char *date_function_name, int from)
732 | {
733 | char *formats[MKTIME_NUM_ARGS] = {"H", "i", "s", "n", "j", "Y"};
734 | zval format, timestamp;
735 | int i;
736 |
737 | ZVAL_LONG(×tamp, mock_timestamp());
738 |
739 | for (i = from; i < MKTIME_NUM_ARGS; i++) {
740 | ZVAL_STRING(&format, formats[i]);
741 | call_php_function_with_2_params(date_function_name, &fill_params[i], &format, ×tamp);
742 | zval_ptr_dtor(&format);
743 | }
744 |
745 | return MKTIME_NUM_ARGS;
746 | }
747 |
748 | /*
749 | * get_formatted_mock_time() : return formatted mock time like "2000-12-30 01:02:03.456000"
750 | *
751 | * pseudo code:
752 | *
753 | * function get_formatted_mock_time($time, $timezone_obj) {
754 | * if ($time === null || $time === false || $time === "") {
755 | * $time = "now";
756 | * }
757 | * $now = get_mock_timeval();
758 | * if ($timezone_obj) {
759 | * // save default timezone
760 | * $zonename = $timezone_obj->getName()
761 | * $orig_zonename = date_default_timezone_get();
762 | * date_default_timezone_set($zonename);
763 | * }
764 | * $fixed_sec = strtotime($time, $now->sec);
765 | * if ($timezone_obj && $orig_zonename) {
766 | * // restore default timezone
767 | * date_default_timezone_set($orig_zonename);
768 | * }
769 | * if ($fixed_sec === FALSE) {
770 | * return false;
771 | * }
772 | * $fixed_usec = get_mock_fraction($time, $timezone_obj);
773 | * if ($fixed_usec === -1) {
774 | * $fixed_usec = $now->usec;
775 | * }
776 | * $dt = date_create($time, $timezone_obj);
777 | * $dt->setTimestamp($fixed_sec);
778 | * $format = sprintf("Y-m-d H:i:s.%06d", $fixed_usec);
779 | * $formatted_time = $dt->format($format);
780 | * return $formatted_time;
781 | * }
782 | */
783 | static int get_formatted_mock_time(zval *time, zval *timezone_obj, zval *retval_time, zval *retval_timezone)
784 | {
785 | zval fixed_sec, orig_zonename;
786 | zval now_timestamp, str_now;
787 | tc_timeval now;
788 | zend_long fixed_usec;
789 |
790 | if (TIMECOP_G(timecop_mode) == TIMECOP_MODE_REALTIME) {
791 | ZVAL_FALSE(retval_time);
792 | ZVAL_NULL(retval_timezone);
793 | return -1;
794 | }
795 |
796 | if (time == NULL || Z_TYPE_P(time) == IS_NULL ||
797 | Z_TYPE_P(time) == IS_FALSE ||
798 | (Z_TYPE_P(time) == IS_STRING && Z_STRLEN_P(time) == 0)) {
799 | ZVAL_STRING(&str_now, "now");
800 | time = &str_now;
801 | }
802 |
803 | get_mock_timeval(&now, NULL);
804 |
805 | if (timezone_obj && Z_TYPE_P(timezone_obj) == IS_OBJECT) {
806 | zval zonename;
807 | call_php_method_with_0_params(timezone_obj, Z_OBJCE_P(timezone_obj), "getname", &zonename);
808 | call_php_function_with_0_params("date_default_timezone_get", &orig_zonename);
809 | call_php_function_with_1_params("date_default_timezone_set", NULL, &zonename);
810 | zval_ptr_dtor(&zonename);
811 | }
812 |
813 | ZVAL_LONG(&now_timestamp, now.sec);
814 | call_php_function_with_2_params(ORIG_FUNC_NAME("strtotime"), &fixed_sec, time, &now_timestamp);
815 |
816 | if (timezone_obj && Z_TYPE_P(timezone_obj) == IS_OBJECT) {
817 | call_php_function_with_1_params("date_default_timezone_set", NULL, &orig_zonename);
818 | zval_ptr_dtor(&orig_zonename);
819 | }
820 |
821 | if (Z_TYPE(fixed_sec) == IS_FALSE) {
822 | ZVAL_FALSE(retval_time);
823 | ZVAL_NULL(retval_timezone);
824 | return -1;
825 | }
826 |
827 | fixed_usec = get_mock_fraction(time, timezone_obj);
828 | if (fixed_usec == -1) {
829 | fixed_usec = now.usec;
830 | }
831 |
832 | {
833 | zval dt;
834 | zval format_str;
835 |
836 | char buf[64];
837 |
838 | call_php_function_with_2_params(ORIG_FUNC_NAME("date_create"), &dt, time, timezone_obj);
839 | if (Z_TYPE(dt) == IS_FALSE) {
840 | ZVAL_FALSE(retval_time);
841 | ZVAL_NULL(retval_timezone);
842 | return -1;
843 | }
844 | sprintf(buf, "Y-m-d H:i:s.%06ld", fixed_usec);
845 | ZVAL_STRING(&format_str, buf);
846 | call_php_method_with_1_params(&dt, TIMECOP_G(ce_DateTime), "settimestamp", NULL, &fixed_sec);
847 | call_php_method_with_0_params(&dt, TIMECOP_G(ce_DateTime), "gettimezone", retval_timezone);
848 | call_php_method_with_1_params(&dt, TIMECOP_G(ce_DateTime), "format", retval_time, &format_str);
849 | zval_ptr_dtor(&fixed_sec);
850 | zval_ptr_dtor(&format_str);
851 | zval_ptr_dtor(&dt);
852 | }
853 |
854 | if (time == &str_now) {
855 | zval_ptr_dtor(&str_now);
856 | }
857 | return 0;
858 | }
859 |
860 | /*
861 | * get_mock_fraction()
862 | *
863 | * pseudo code:
864 | *
865 | * function get_mock_fraction($time, $timezone_obj) {
866 | * $dt1 = date_create($time, $timezone_obj);
867 | * usleep(1);
868 | * $dt2 = date_create($time, $timezone_obj);
869 | * $usec1 = $dt1->format("u");
870 | * $usec2 = $dt2->format("u");
871 | * if ($usec1 === $usec2) {
872 | * $fixed_usec = $usec1;
873 | * } else {
874 | * $fixed_usec = -1;
875 | * }
876 | * return $fixed_usec;
877 | * }
878 | */
879 | static long get_mock_fraction(zval *time, zval *timezone_obj TSRMLS_DC)
880 | {
881 | zval dt1, dt2, usec1, usec2;
882 | zend_long fixed_usec;
883 | zval u_str, sleep_usec;
884 |
885 | call_php_function_with_2_params(ORIG_FUNC_NAME("date_create"), &dt1, time, timezone_obj);
886 | if (Z_TYPE(dt1) == IS_FALSE) {
887 | return -1;
888 | }
889 |
890 | ZVAL_LONG(&sleep_usec, 1);
891 | call_php_function_with_1_params("usleep", NULL, &sleep_usec);
892 |
893 | call_php_function_with_2_params(ORIG_FUNC_NAME("date_create"), &dt2, time, timezone_obj);
894 | if (Z_TYPE(dt2) == IS_FALSE) {
895 | zval_ptr_dtor(&dt1);
896 | return -1;
897 | }
898 | ZVAL_STRING(&u_str, "u");
899 | call_php_method_with_1_params(&dt1, TIMECOP_G(ce_DateTime), "format", &usec1, &u_str);
900 | call_php_method_with_1_params(&dt2, TIMECOP_G(ce_DateTime), "format", &usec2, &u_str);
901 | convert_to_long(&usec1);
902 | convert_to_long(&usec2);
903 |
904 | if (Z_LVAL(usec1) == Z_LVAL(usec2)) {
905 | fixed_usec = Z_LVAL(usec1);
906 | } else {
907 | fixed_usec = -1;
908 | }
909 | zval_ptr_dtor(&dt1);
910 | zval_ptr_dtor(&dt2);
911 | zval_ptr_dtor(&u_str);
912 |
913 | return fixed_usec;
914 | }
915 |
916 |
917 | static void _timecop_call_function(INTERNAL_FUNCTION_PARAMETERS, const char *function_name, int index_to_fill_timestamp)
918 | {
919 | zval *params;
920 | uint32_t param_count;
921 |
922 | param_count = MAX(ZEND_NUM_ARGS(), index_to_fill_timestamp+1);
923 | params = (zval *)safe_emalloc(param_count, sizeof(zval), 0);
924 |
925 | if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), params) == FAILURE) {
926 | efree(params);
927 | return;
928 | }
929 |
930 | param_count = ZEND_NUM_ARGS();
931 | if (param_count == index_to_fill_timestamp) {
932 | ZVAL_LONG(¶ms[param_count], mock_timestamp());
933 | param_count++;
934 | }
935 |
936 | call_php_function_with_params(function_name, return_value, param_count, params);
937 |
938 | efree(params);
939 | }
940 |
941 | /* {{{ _timecop_call_mktime - timecop_(gm)mktime helper */
942 | static void _timecop_call_mktime(INTERNAL_FUNCTION_PARAMETERS, const char *mktime_function_name, const char *date_function_name)
943 | {
944 | zval *params;
945 | uint32_t param_count;
946 |
947 | int i;
948 |
949 | param_count = MAX(ZEND_NUM_ARGS(), MKTIME_NUM_ARGS);
950 | params = (zval *)safe_emalloc(param_count, sizeof(zval), 0);
951 |
952 | if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), params) == FAILURE) {
953 | efree(params);
954 | zend_throw_error(NULL, "Cannot get arguments for calling");
955 | return;
956 | }
957 |
958 | param_count = ZEND_NUM_ARGS();
959 | if (param_count < MKTIME_NUM_ARGS) {
960 | fill_mktime_params(params, date_function_name, param_count);
961 | param_count = MKTIME_NUM_ARGS;
962 | }
963 |
964 | if (ZEND_NUM_ARGS() == 0) {
965 | php_error_docref(NULL, E_DEPRECATED, "You should be using the time() function instead");
966 | }
967 |
968 | call_php_function_with_params(mktime_function_name, return_value, param_count, params);
969 |
970 | for (i = ZEND_NUM_ARGS(); i < MKTIME_NUM_ARGS; i++) {
971 | zval_ptr_dtor(¶ms[i]);
972 | }
973 | efree(params);
974 | }
975 | /* }}} */
976 |
977 | /* {{{ proto int timecop_freeze(long timestamp)
978 | Time travel to specified timestamp and freeze */
979 | PHP_FUNCTION(timecop_freeze)
980 | {
981 | zval *dt;
982 | zend_long timestamp;
983 | tc_timeval freezed_tv;
984 |
985 | if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "O", &dt, TIMECOP_G(ce_DateTimeInterface)) != FAILURE) {
986 | get_timeval_from_datetime(&freezed_tv, dt);
987 | } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "l", ×tamp) != FAILURE) {
988 | freezed_tv.sec = timestamp;
989 | freezed_tv.usec = 0;
990 | } else {
991 | php_error_docref(NULL, E_WARNING, "This function accepts either (DateTimeInterface) OR (int) as arguments.");
992 | RETURN_FALSE;
993 | }
994 |
995 | TIMECOP_G(timecop_mode) = TIMECOP_MODE_FREEZE;
996 | TIMECOP_G(freezed_time) = freezed_tv;
997 |
998 | if (TIMECOP_G(sync_request_time)){
999 | update_request_time(freezed_tv.sec);
1000 | }
1001 |
1002 | RETURN_TRUE;
1003 | }
1004 | /* }}} */
1005 |
1006 | /* {{{ proto int timecop_travel(long timestamp)
1007 | Time travel to specified timestamp */
1008 | PHP_FUNCTION(timecop_travel)
1009 | {
1010 | zval *dt;
1011 | zend_long timestamp;
1012 | tc_timeval now, mock_tv;
1013 |
1014 | if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "O", &dt, TIMECOP_G(ce_DateTimeInterface)) != FAILURE) {
1015 | get_timeval_from_datetime(&mock_tv, dt);
1016 | } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "l", ×tamp) != FAILURE) {
1017 | mock_tv.sec = timestamp;
1018 | mock_tv.usec = 0;
1019 | } else {
1020 | php_error_docref(NULL, E_WARNING, "This function accepts either (DateTimeInterface) OR (int) as arguments.");
1021 | RETURN_FALSE;
1022 | }
1023 |
1024 | TIMECOP_G(timecop_mode) = TIMECOP_MODE_TRAVEL;
1025 | get_current_time(&now);
1026 | tc_timeval_sub(&TIMECOP_G(travel_offset), &mock_tv, &now);
1027 | TIMECOP_G(travel_origin) = now;
1028 |
1029 | if (TIMECOP_G(sync_request_time)){
1030 | update_request_time(mock_tv.sec);
1031 | }
1032 |
1033 | RETURN_TRUE;
1034 | }
1035 | /* }}} */
1036 |
1037 | /* {{{ proto int timecop_scale(long scale)
1038 | Accelerate time with specified scale */
1039 | PHP_FUNCTION(timecop_scale)
1040 | {
1041 | zend_long scale;
1042 | tc_timeval now, mock_time;
1043 |
1044 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &scale) == FAILURE) {
1045 | RETURN_FALSE;
1046 | }
1047 | if (scale < 0) {
1048 | RETURN_FALSE;
1049 | }
1050 | get_current_time(&now);
1051 | get_mock_timeval(&mock_time, &now);
1052 | TIMECOP_G(timecop_mode) = TIMECOP_MODE_TRAVEL;
1053 | TIMECOP_G(travel_origin) = now;
1054 | tc_timeval_sub(&TIMECOP_G(travel_offset), &mock_time, &now);
1055 | TIMECOP_G(scaling_factor) = scale;
1056 |
1057 | if (TIMECOP_G(sync_request_time)){
1058 | update_request_time(mock_time.sec);
1059 | }
1060 |
1061 | RETURN_TRUE;
1062 | }
1063 | /* }}} */
1064 |
1065 | /* {{{ proto int timecop_return(void)
1066 | Return to Time travel to specified timestamp */
1067 | PHP_FUNCTION(timecop_return)
1068 | {
1069 | TIMECOP_G(timecop_mode) = TIMECOP_MODE_REALTIME;
1070 |
1071 | if (TIMECOP_G(sync_request_time)){
1072 | restore_request_time();
1073 | }
1074 |
1075 | RETURN_TRUE;
1076 | }
1077 | /* }}} */
1078 |
1079 | /* {{{ proto int timecop_time(void)
1080 | Return virtual timestamp */
1081 | PHP_FUNCTION(timecop_time)
1082 | {
1083 | RETURN_LONG(mock_timestamp());
1084 | }
1085 | /* }}} */
1086 |
1087 | /* {{{ proto int timecop_mktime([int hour [, int min [, int sec [, int mon [, int day [, int year]]]]]])
1088 | Get UNIX timestamp for a date */
1089 | PHP_FUNCTION(timecop_mktime)
1090 | {
1091 | TIMECOP_CALL_MKTIME("mktime", "date");
1092 | }
1093 | /* }}} */
1094 |
1095 | /* {{{ proto int timecop_gmmktime([int hour [, int min [, int sec [, int mon [, int day [, int year]]]]]])
1096 | Get UNIX timestamp for a GMT date */
1097 | PHP_FUNCTION(timecop_gmmktime)
1098 | {
1099 | TIMECOP_CALL_MKTIME("gmmktime", "gmdate");
1100 | }
1101 | /* }}} */
1102 |
1103 | /* {{{ proto string timecop_date(string format [, long timestamp])
1104 | Format a local date/time */
1105 | PHP_FUNCTION(timecop_date)
1106 | {
1107 | TIMECOP_CALL_FUNCTION("date", 1);
1108 | }
1109 | /* }}} */
1110 |
1111 | /* {{{ proto string timecop_gmdate(string format [, long timestamp])
1112 | Format a GMT date/time */
1113 | PHP_FUNCTION(timecop_gmdate)
1114 | {
1115 | TIMECOP_CALL_FUNCTION("gmdate", 1);
1116 | }
1117 | /* }}} */
1118 |
1119 | /* {{{ proto int timecop_idate(string format [, int timestamp])
1120 | Format a local time/date as integer */
1121 | PHP_FUNCTION(timecop_idate)
1122 | {
1123 | TIMECOP_CALL_FUNCTION("idate", 1);
1124 | }
1125 | /* }}} */
1126 |
1127 | /* {{{ proto array timecop_getdate([int timestamp])
1128 | Get date/time information */
1129 | PHP_FUNCTION(timecop_getdate)
1130 | {
1131 | TIMECOP_CALL_FUNCTION("getdate", 0);
1132 | }
1133 | /* }}} */
1134 |
1135 | /* {{{ proto array timecop_localtime([int timestamp [, bool associative_array]])
1136 | Returns the results of the C system call localtime as an associative array if
1137 | the associative_array argument is set to 1 other wise it is a regular array */
1138 | PHP_FUNCTION(timecop_localtime)
1139 | {
1140 | TIMECOP_CALL_FUNCTION("localtime", 0);
1141 | }
1142 | /* }}} */
1143 |
1144 | /* {{{ proto int timecop_strtotime(string time [, int now ])
1145 | Convert string representation of date and time to a timestamp */
1146 | PHP_FUNCTION(timecop_strtotime)
1147 | {
1148 | TIMECOP_CALL_FUNCTION("strtotime", 1);
1149 | }
1150 | /* }}} */
1151 |
1152 | /* {{{ proto string timecop_strftime(string format [, int timestamp])
1153 | Format a local time/date according to locale settings */
1154 | PHP_FUNCTION(timecop_strftime)
1155 | {
1156 | TIMECOP_CALL_FUNCTION("strftime", 1);
1157 | }
1158 | /* }}} */
1159 |
1160 | /* {{{ proto string timecop_gmstrftime(string format [, int timestamp])
1161 | Format a GMT/UCT time/date according to locale settings */
1162 | PHP_FUNCTION(timecop_gmstrftime)
1163 | {
1164 | TIMECOP_CALL_FUNCTION("gmstrftime", 1);
1165 | }
1166 | /* }}} */
1167 |
1168 | /*
1169 | * get_mock_timeval(fixed, now)
1170 | *
1171 | *
1172 | * delta
1173 | * |<----------------------->|
1174 | * travel_offset delta * scaling_factor
1175 | * |<------------->|<------------------------------------------------->|
1176 | * ==@===============@=========@=========================================@==
1177 | * ^ ^ ^
1178 | * | | |
1179 | * travel_origin orig_time traveled_time
1180 | *
1181 | *
1182 | * delta = orig_time - travel_origin
1183 | * traveled_time = travel_origin + travel_offset + delta * scaling_factor
1184 | */
1185 | static int get_mock_timeval(tc_timeval *fixed, const tc_timeval *now)
1186 | {
1187 | if (TIMECOP_G(timecop_mode) == TIMECOP_MODE_FREEZE) {
1188 | *fixed = TIMECOP_G(freezed_time);
1189 | } else if (TIMECOP_G(timecop_mode) == TIMECOP_MODE_TRAVEL) {
1190 | tc_timeval delta, origin = TIMECOP_G(travel_origin);
1191 | zend_long scale = TIMECOP_G(scaling_factor);
1192 | if (now == NULL) {
1193 | get_current_time(&delta);
1194 | } else {
1195 | delta = *now;
1196 | }
1197 | tc_timeval_sub(&delta, &delta, &origin);
1198 | tc_timeval_mul(&delta, &delta, scale);
1199 | tc_timeval_add(fixed, &origin, &TIMECOP_G(travel_offset));
1200 | tc_timeval_add(fixed, fixed, &delta);
1201 | } else {
1202 | if (now == NULL) {
1203 | get_current_time(fixed);
1204 | } else {
1205 | *fixed = *now;
1206 | }
1207 | }
1208 | return 0;
1209 | }
1210 |
1211 | static zend_long mock_timestamp()
1212 | {
1213 | tc_timeval tv;
1214 | get_mock_timeval(&tv, NULL);
1215 | return tv.sec;
1216 | }
1217 |
1218 | static int get_timeval_from_datetime(tc_timeval *tp, zval *dt)
1219 | {
1220 | zval sec, usec;
1221 | zval u_str;
1222 |
1223 | call_php_method_with_0_params(dt, Z_OBJCE_P(dt), "gettimestamp", &sec);
1224 | ZVAL_STRING(&u_str, "u");
1225 | call_php_method_with_1_params(dt, Z_OBJCE_P(dt), "format", &usec, &u_str);
1226 | zval_ptr_dtor(&u_str);
1227 | convert_to_long(&usec);
1228 |
1229 | tp->sec = Z_LVAL(sec);
1230 | tp->usec = Z_LVAL(usec);
1231 |
1232 | return 0;
1233 | }
1234 |
1235 | static int get_current_time(tc_timeval *now)
1236 | {
1237 | int ret = 0;
1238 | #if HAVE_GETTIMEOFDAY
1239 | struct timeval tv;
1240 | ret = gettimeofday(&tv, NULL);
1241 | if (ret == 0) {
1242 | now->sec = (zend_long)tv.tv_sec;
1243 | now->usec = (zend_long)tv.tv_usec;
1244 | }
1245 | #else
1246 | time_t ts = time(NULL);
1247 | if (ts == -1) {
1248 | ret = -1;
1249 | } else {
1250 | now->sec = (zend_long)ts;
1251 | now->usec = 0;
1252 | }
1253 | #endif
1254 | return ret;
1255 | }
1256 |
1257 | #ifdef HAVE_GETTIMEOFDAY
1258 |
1259 | #define MICRO_IN_SEC 1000000.00
1260 | #define SEC_IN_MIN 60
1261 |
1262 | static void _timecop_gettimeofday(INTERNAL_FUNCTION_PARAMETERS, int mode)
1263 | {
1264 | zend_bool get_as_float = 0;
1265 | tc_timeval fixed;
1266 |
1267 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &get_as_float) == FAILURE) {
1268 | RETURN_FALSE;
1269 | }
1270 |
1271 | if (get_mock_timeval(&fixed, NULL)) {
1272 | RETURN_FALSE;
1273 | }
1274 |
1275 | if (get_as_float) {
1276 | RETURN_DOUBLE((double)(fixed.sec + fixed.usec / MICRO_IN_SEC));
1277 | }
1278 | if (mode) {
1279 | zval zv_offset, zv_dst, format, timestamp;
1280 | zend_long offset = 0, is_dst = 0;
1281 |
1282 | ZVAL_LONG(×tamp, fixed.sec);
1283 |
1284 | /* offset */
1285 | ZVAL_STRING(&format, "Z");
1286 | call_php_function_with_2_params(ORIG_FUNC_NAME("date"), &zv_offset, &format, ×tamp);
1287 | convert_to_long(&zv_offset);
1288 | offset = Z_LVAL(zv_offset);
1289 | zval_ptr_dtor(&zv_offset);
1290 | zval_ptr_dtor(&format);
1291 |
1292 | /* is_dst */
1293 | ZVAL_STRING(&format, "I");
1294 | call_php_function_with_2_params(ORIG_FUNC_NAME("date"), &zv_dst, &format, ×tamp);
1295 | convert_to_long(&zv_dst);
1296 | is_dst = Z_LVAL(zv_dst);
1297 | zval_ptr_dtor(&zv_dst);
1298 | zval_ptr_dtor(&format);
1299 |
1300 | array_init(return_value);
1301 | add_assoc_long(return_value, "sec", fixed.sec);
1302 | add_assoc_long(return_value, "usec", fixed.usec);
1303 | add_assoc_long(return_value, "minuteswest", -offset / SEC_IN_MIN);
1304 | add_assoc_long(return_value, "dsttime", is_dst);
1305 | } else {
1306 | char ret[100];
1307 | snprintf(ret, 100, "%.8F %ld", fixed.usec / MICRO_IN_SEC, fixed.sec);
1308 | RETURN_STRING(ret);
1309 | }
1310 | }
1311 |
1312 | /* {{{ proto mixed microtime([bool get_as_float])
1313 | Returns either a string or a float containing the current time in seconds and microseconds */
1314 | PHP_FUNCTION(timecop_microtime)
1315 | {
1316 | _timecop_gettimeofday(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1317 | }
1318 | /* }}} */
1319 |
1320 | /* {{{ proto array gettimeofday([bool get_as_float])
1321 | Returns the current time as array */
1322 | PHP_FUNCTION(timecop_gettimeofday)
1323 | {
1324 | _timecop_gettimeofday(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1325 | }
1326 | /* }}} */
1327 | #endif
1328 |
1329 | /* {{{ proto int timecop_unixtojd([int timestamp])
1330 | Convert UNIX timestamp to Julian Day */
1331 | PHP_FUNCTION(timecop_unixtojd)
1332 | {
1333 | TIMECOP_CALL_FUNCTION("unixtojd", 0);
1334 | }
1335 | /* }}} */
1336 |
1337 | static void _timecop_orig_datetime_constructor(INTERNAL_FUNCTION_PARAMETERS, int immutable)
1338 | {
1339 | zval *arg1 = NULL, *arg2 = NULL;
1340 | zend_class_entry *real_ce;
1341 |
1342 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|zz", &arg1, &arg2) == FAILURE) {
1343 | RETURN_FALSE;
1344 | }
1345 |
1346 | if (immutable) {
1347 | real_ce = TIMECOP_G(ce_DateTimeImmutable);
1348 | } else {
1349 | real_ce = TIMECOP_G(ce_DateTime);
1350 | }
1351 |
1352 | call_php_method_with_2_params(getThis(), real_ce, ORIG_FUNC_NAME("__construct"), NULL, arg1, arg2);
1353 | }
1354 |
1355 | static inline void _timecop_datetime_constructor(INTERNAL_FUNCTION_PARAMETERS, int immutable)
1356 | {
1357 | _timecop_datetime_constructor_ex(INTERNAL_FUNCTION_PARAM_PASSTHRU, getThis(), immutable);
1358 | }
1359 |
1360 | static inline void _timecop_date_create(INTERNAL_FUNCTION_PARAMETERS, int immutable)
1361 | {
1362 | _timecop_datetime_constructor_ex(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL, immutable);
1363 | }
1364 |
1365 | static void _timecop_datetime_constructor_ex(INTERNAL_FUNCTION_PARAMETERS, zval *obj, int immutable)
1366 | {
1367 | zval orig_time, *orig_timezone = NULL;
1368 | zval fixed_time, fixed_timezone, *arg1, *arg2;
1369 | char *orig_time_str = NULL;
1370 | size_t orig_time_len = 0;
1371 | const char *real_func;
1372 | zend_class_entry *real_ce;
1373 |
1374 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sO!", &orig_time_str, &orig_time_len, &orig_timezone, TIMECOP_G(ce_DateTimeZone)) == FAILURE) {
1375 | RETURN_FALSE;
1376 | }
1377 |
1378 | if (orig_time_str == NULL) {
1379 | ZVAL_NULL(&orig_time);
1380 | } else {
1381 | ZVAL_STRINGL(&orig_time, orig_time_str, orig_time_len);
1382 | }
1383 | if (immutable) {
1384 | real_func = ORIG_FUNC_NAME("date_create_immutable");
1385 | real_ce = TIMECOP_G(ce_DateTimeImmutable);
1386 | } else {
1387 | real_func = ORIG_FUNC_NAME("date_create");
1388 | real_ce = TIMECOP_G(ce_DateTime);
1389 | }
1390 |
1391 | if (get_formatted_mock_time(&orig_time, orig_timezone, &fixed_time, &fixed_timezone TSRMLS_CC) == 0) {
1392 | arg1 = &fixed_time;
1393 | arg2 = &fixed_timezone;
1394 | } else {
1395 | arg1 = &orig_time;
1396 | arg2 = orig_timezone;
1397 | }
1398 | if (obj == NULL) {
1399 | call_php_function_with_2_params(real_func, return_value, arg1, arg2);
1400 | } else {
1401 | call_php_method_with_2_params(obj, real_ce, ORIG_FUNC_NAME("__construct"), NULL, arg1, arg2);
1402 | }
1403 | zval_ptr_dtor(&orig_time);
1404 | zval_ptr_dtor(&fixed_time);
1405 | zval_ptr_dtor(&fixed_timezone);
1406 | }
1407 |
1408 | /* {{{ proto DateTime timecop_date_create([string time[, DateTimeZone object]])
1409 | Returns new DateTime object initialized with traveled time */
1410 | PHP_FUNCTION(timecop_date_create)
1411 | {
1412 | _timecop_date_create(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1413 | }
1414 | /* }}} */
1415 |
1416 | static void _timecop_date_create_from_format(INTERNAL_FUNCTION_PARAMETERS, int immutable)
1417 | {
1418 | zval *orig_timezone = NULL;
1419 | zval orig_format, orig_time, fixed_format, fixed_time, new_format, new_time;
1420 | zval dt, dti, now_timestamp, tmp;
1421 | char *orig_format_str, *orig_time_str;
1422 | size_t orig_format_len, orig_time_len;
1423 | tc_timeval now;
1424 | char buf[64];
1425 | const char *real_func;
1426 |
1427 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|O!", &orig_format_str, &orig_format_len, &orig_time_str, &orig_time_len, &orig_timezone, TIMECOP_G(ce_DateTimeZone)) == FAILURE) {
1428 | RETURN_FALSE;
1429 | }
1430 |
1431 | ZVAL_STRINGL(&orig_format, orig_format_str, orig_format_len);
1432 | ZVAL_STRINGL(&orig_time, orig_time_str, orig_time_len);
1433 |
1434 | call_php_function_with_3_params(ORIG_FUNC_NAME("date_create_from_format"), &dt, &orig_format, &orig_time, orig_timezone);
1435 | if (Z_TYPE(dt) == IS_FALSE) {
1436 | zval_ptr_dtor(&orig_format);
1437 | zval_ptr_dtor(&orig_time);
1438 | RETURN_FALSE;
1439 | }
1440 |
1441 | if (memchr(orig_format_str, '!', orig_format_len) ||
1442 | memchr(orig_format_str, '|', orig_format_len)) {
1443 | zval_ptr_dtor(&orig_format);
1444 | zval_ptr_dtor(&orig_time);
1445 |
1446 | if (immutable) {
1447 | call_php_method_with_1_params(NULL, TIMECOP_G(ce_DateTimeImmutable), "createfrommutable", &dti, &dt);
1448 | zval_ptr_dtor(&dt);
1449 | RETURN_ZVAL(&dti, 1, 1);
1450 | }
1451 |
1452 | RETURN_ZVAL(&dt, 1, 1);
1453 | }
1454 |
1455 | get_mock_timeval(&now, NULL);
1456 |
1457 | ZVAL_LONG(&now_timestamp, now.sec);
1458 | call_php_method_with_1_params(&dt, TIMECOP_G(ce_DateTime), "settimestamp", NULL, &now_timestamp);
1459 | sprintf(buf, "Y-m-d H:i:s.%06ld ", now.usec);
1460 | ZVAL_STRING(&tmp, buf);
1461 | call_php_method_with_1_params(&dt, TIMECOP_G(ce_DateTime), "format", &fixed_time, &tmp);
1462 | zval_ptr_dtor(&tmp);
1463 |
1464 | if (
1465 | #if PHP_VERSION_ID >= 70300
1466 | memchr(orig_format_str, 'u', orig_format_len) ||
1467 | #endif
1468 | memchr(orig_format_str, 'g', orig_format_len) ||
1469 | memchr(orig_format_str, 'h', orig_format_len) ||
1470 | memchr(orig_format_str, 'G', orig_format_len) ||
1471 | memchr(orig_format_str, 'H', orig_format_len) ||
1472 | memchr(orig_format_str, 'i', orig_format_len) ||
1473 | memchr(orig_format_str, 's', orig_format_len)
1474 | ) {
1475 | ZVAL_STRING(&fixed_format, "Y-m-d ??:??:??.??????");
1476 | } else if (memchr(orig_format_str, 'Y', orig_format_len) ||
1477 | memchr(orig_format_str, 'y', orig_format_len) ||
1478 | memchr(orig_format_str, 'F', orig_format_len) ||
1479 | memchr(orig_format_str, 'M', orig_format_len) ||
1480 | memchr(orig_format_str, 'm', orig_format_len) ||
1481 | memchr(orig_format_str, 'n', orig_format_len) ||
1482 | memchr(orig_format_str, 'd', orig_format_len) ||
1483 | memchr(orig_format_str, 'j', orig_format_len) ||
1484 | memchr(orig_format_str, 'D', orig_format_len) ||
1485 | memchr(orig_format_str, 'l', orig_format_len) ||
1486 | memchr(orig_format_str, 'U', orig_format_len)) {
1487 | ZVAL_STRING(&fixed_format, "Y-m-d H:i:s.??????");
1488 | } else {
1489 | #if PHP_VERSION_ID >= 70100
1490 | ZVAL_STRING(&fixed_format, "Y-m-d H:i:s.u");
1491 | #else
1492 | ZVAL_STRING(&fixed_format, "Y-m-d H:i:s.??????");
1493 | #endif
1494 | }
1495 |
1496 | ZVAL_STRING(&tmp, "%s %s");
1497 | call_php_function_with_3_params("sprintf", &new_format, &tmp, &fixed_format, &orig_format);
1498 | call_php_function_with_3_params("sprintf", &new_time, &tmp, &fixed_time, &orig_time);
1499 | zval_ptr_dtor(&tmp);
1500 |
1501 | if (immutable) {
1502 | real_func = ORIG_FUNC_NAME("date_create_immutable_from_format");
1503 | } else {
1504 | real_func = ORIG_FUNC_NAME("date_create_from_format");
1505 | }
1506 | call_php_function_with_3_params(real_func, return_value, &new_format, &new_time, orig_timezone);
1507 |
1508 | zval_ptr_dtor(&dt);
1509 | zval_ptr_dtor(&orig_format);
1510 | zval_ptr_dtor(&orig_time);
1511 | zval_ptr_dtor(&fixed_format);
1512 | zval_ptr_dtor(&fixed_time);
1513 | zval_ptr_dtor(&new_format);
1514 | zval_ptr_dtor(&new_time);
1515 | }
1516 |
1517 | /* {{{ proto DateTime timecop_date_create_from_format(string format, string time[, DateTimeZone object])
1518 | Returns new DateTime object initialized with traveled time */
1519 | PHP_FUNCTION(timecop_date_create_from_format)
1520 | {
1521 | _timecop_date_create_from_format(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1522 | }
1523 | /* }}} */
1524 |
1525 | /* {{{ proto DateTimeImmutable timecop_date_create_immutable([string time[, DateTimeZone object]])
1526 | Returns new DateTimeImmutable object initialized with traveled time */
1527 | PHP_FUNCTION(timecop_date_create_immutable)
1528 | {
1529 | _timecop_date_create(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1530 | }
1531 | /* }}} */
1532 |
1533 | /* {{{ proto DateTimeImmutable timecop_date_create_immutable_from_format(string format, string time[, DateTimeZone object])
1534 | Returns new DateTimeImmutable object initialized with traveled time */
1535 | PHP_FUNCTION(timecop_date_create_immutable_from_format)
1536 | {
1537 | _timecop_date_create_from_format(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1538 | }
1539 | /* }}} */
1540 |
1541 | /* {{{ proto TimecopDateTime::__construct([string time[, DateTimeZone object]])
1542 | Creates new TimecopDateTime object */
1543 | PHP_METHOD(TimecopDateTime, __construct)
1544 | {
1545 | _timecop_datetime_constructor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1546 | }
1547 | /* }}} */
1548 |
1549 | /* {{{ proto TimecopOrigDateTime::__construct([string time[, DateTimeZone object]])
1550 | Creates new TimecopOrigDateTime object */
1551 | PHP_METHOD(TimecopOrigDateTime, __construct)
1552 | {
1553 | _timecop_orig_datetime_constructor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1554 | }
1555 | /* }}} */
1556 |
1557 | /* {{{ proto TimecopDateTimeImmutable::__construct([string time[, DateTimeZone object]])
1558 | Creates new TimecopDateTimeImmutable object */
1559 | PHP_METHOD(TimecopDateTimeImmutable, __construct)
1560 | {
1561 | _timecop_datetime_constructor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1562 | }
1563 | /* }}} */
1564 |
1565 | /* {{{ proto TimecopOrigDateTimeImmutable::__construct([string time[, DateTimeZone object]])
1566 | Creates new TimecopOrigDateTimeImmutable object */
1567 | PHP_METHOD(TimecopOrigDateTimeImmutable, __construct)
1568 | {
1569 | _timecop_orig_datetime_constructor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1570 | }
1571 | /* }}} */
1572 |
1573 | static inline zval* _call_php_method_with_0_params(zval *object_pp, zend_class_entry *obj_ce, const char *method_name, zval *retval_ptr)
1574 | {
1575 | return _call_php_method(object_pp, obj_ce, method_name, retval_ptr, 0, NULL, NULL);
1576 | }
1577 |
1578 | static inline zval* _call_php_method_with_1_params(zval *object_pp, zend_class_entry *obj_ce, const char *method_name, zval *retval_ptr, zval *arg1)
1579 | {
1580 | int nparams = 1;
1581 | if (arg1 == NULL) {
1582 | nparams = 0;
1583 | }
1584 | return _call_php_method(object_pp, obj_ce, method_name, retval_ptr, nparams, arg1, NULL);
1585 | }
1586 |
1587 | static inline zval* _call_php_method_with_2_params(zval *object_pp, zend_class_entry *obj_ce, const char *method_name, zval *retval_ptr, zval *arg1, zval *arg2)
1588 | {
1589 | int nparams = 2;
1590 | if (arg1 == NULL) {
1591 | nparams = 0;
1592 | } else if (arg2 == NULL) {
1593 | nparams = 1;
1594 | }
1595 | return _call_php_method(object_pp, obj_ce, method_name, retval_ptr, nparams, arg1, arg2);
1596 | }
1597 |
1598 | static inline zval* _call_php_method(zval *object_pp, zend_class_entry *obj_ce, const char *method_name, zval *retval_ptr, int param_count, zval* arg1, zval* arg2)
1599 | {
1600 | return zend_call_method(object_pp, obj_ce, NULL, method_name, strlen(method_name), retval_ptr, param_count, arg1, arg2);
1601 | }
1602 |
1603 | static inline void _call_php_function_with_0_params(const char *function_name, zval *retval_ptr)
1604 | {
1605 | _call_php_method_with_0_params(NULL, NULL, function_name, retval_ptr);
1606 | }
1607 |
1608 | static inline void _call_php_function_with_1_params(const char *function_name, zval *retval_ptr, zval *arg1)
1609 | {
1610 | _call_php_method_with_1_params(NULL, NULL, function_name, retval_ptr, arg1);
1611 | }
1612 |
1613 | static inline void _call_php_function_with_2_params(const char *function_name, zval *retval_ptr, zval *arg1, zval *arg2)
1614 | {
1615 | _call_php_method_with_2_params(NULL, NULL, function_name, retval_ptr, arg1, arg2);
1616 | }
1617 |
1618 | static inline void _call_php_function_with_3_params(const char *function_name, zval *retval_ptr, zval *arg1, zval *arg2, zval *arg3)
1619 | {
1620 | if (arg3 == NULL) {
1621 | _call_php_function_with_2_params(function_name, retval_ptr, arg1, arg2);
1622 | } else {
1623 | zval params[3];
1624 | ZVAL_COPY(¶ms[0], arg1);
1625 | ZVAL_COPY(¶ms[1], arg2);
1626 | ZVAL_COPY(¶ms[2], arg3);
1627 | call_php_function_with_params(function_name, retval_ptr, 3, params);
1628 | zval_ptr_dtor(¶ms[0]);
1629 | zval_ptr_dtor(¶ms[1]);
1630 | zval_ptr_dtor(¶ms[2]);
1631 | }
1632 | }
1633 |
1634 | static inline void _call_php_function_with_params(const char *function_name, zval *retval_ptr, uint32_t param_count, zval *params)
1635 | {
1636 | zval callable;
1637 | ZVAL_STRING(&callable, function_name);
1638 |
1639 | call_user_function_ex(EG(function_table), NULL, &callable, retval_ptr, param_count, params, 1, NULL);
1640 |
1641 | zval_ptr_dtor(&callable);
1642 | }
1643 |
1644 | /*
1645 | * Local variables:
1646 | * tab-width: 4
1647 | * c-basic-offset: 4
1648 | * End:
1649 | * vim600: noet sw=4 ts=4 fdm=marker
1650 | * vim<600: noet sw=4 ts=4
1651 | */
1652 |
--------------------------------------------------------------------------------
/wercker.yml:
--------------------------------------------------------------------------------
1 | centos:
2 | box: library/centos
3 | steps:
4 | - script:
5 | name: yum -y install gcc make php php-devel rpm-build
6 | code: |-
7 | yum -y install gcc make php php-devel rpm-build
8 | - script:
9 | name: setenv TIMECOP_VER
10 | code: |-
11 | export TIMECOP_VER=$(grep '^Version' php-timecop.spec | sed 's/^.*[^0-9.]\([0-9.]*\)$/\1/')
12 | echo TIMECOP_VER=${TIMECOP_VER}
13 | - script:
14 | name: rpmbuild
15 | code: |-
16 | TIMECOP_TMP="$(dirname $(mktemp --dry-run 2>/dev/null || echo "/var/tmp/tmp_dir"))/php-timecop"
17 | echo TIMECOP_TMP=${TIMECOP_TMP}
18 | mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
19 | mkdir -p ${TIMECOP_TMP}/php-timecop-${TIMECOP_VER}/
20 | cp -R ./ ${TIMECOP_TMP}/php-timecop-${TIMECOP_VER}/
21 | tar cvzf ~/rpmbuild/SOURCES/php-timecop-${TIMECOP_VER}.tar.gz -C ${TIMECOP_TMP} php-timecop-${TIMECOP_VER}/
22 | rpmbuild -bb php-timecop.spec
23 | ubuntu-32bit:
24 | box: 32bit/ubuntu:16.04
25 | steps:
26 | - script:
27 | name: Install required software
28 | code: |-
29 | apt-get -y update
30 | DEBIAN_FRONTEND=noninteractive apt-get -y upgrade build-essential php-dev --no-install-recommends
31 | - script:
32 | name: Build test targets
33 | code: |-
34 | phpize && ./configure && make
35 | - script:
36 | name: Run test
37 | code: |-
38 | make test REPORT_EXIT_STATUS=1 NO_INTERACTION=1 TESTS="--show-all" | tee tests-output.txt && if grep -q 'TEST SUMMARY$' tests-output.txt ; then exit 1 ; fi
39 |
--------------------------------------------------------------------------------