strind

Dec 182011
 

Some time it is necessary to fool your PHP application to test functionality related to a “current date”.

Fooling php cli is simple using faketime:

Say you have this PHP script:

#!/usr/bin/env php 
<?php
print date( 'F j. Y [H:i]' )."\n";

Rendering this script with php through faketime will give you results like this:

$ faketime 'last Friday 5 pm' ./time.php 
December 9. 2011 [17:00]

The same can be achieved using the datefudge command:

$ datefudge "2007-04-01 10:23" ./time.php 
April 1. 2007 [10:23]

Faking time for a webapplication

Faking time for a web application is not that simple since apache will fork a process for each request and thus create a new php processes.
In this post I will show you how to use FakeTime Preload Library to fake time system wide while running tests on a web application.

First I need to install faketimelib as described on the librarys homepage.
In short:

wget http://www.code-wizards.com/projects/libfaketime/libfaketime-0.8.1.tar.gz
tar -xvzf libfaketime-0.8.1.tar.gz
cd libfaketime-0.8.1
vim README
make
sudo make install
export LD_PRELOAD=/usr/local/lib/faketime/libfaketime.so.1

For the demonstration I will use a php script like this:

<?php
printf( "The current time of the server is: %s\n", date('l F j. Y [H:i:s]') );

Running this script should yield something like:

$ php time.php 
The current time of the server is: Friday December 16. 2011 [08:02:43]

Now I create a file in my home folder, faketimerc, with a new future time. I will use this file in different ways to show how I can manipulate the time.

echo "@2012-12-21 12:12:12" > faketimerc

If you now create an environment variable, FAKETIME, give it a future time, and running the same script would yield something like this:

$ php time.php 
The current time of the server is: Friday December 16. 2011 [08:19:39]
$ export FAKETIME=$(cat faketimerc)
$ php time.php 
The current time of the server is: Friday December 21. 2012 [12:12:12]
$ unset FAKETIME
$ php time.php 
The current time of the server is: Friday December 16. 2011 [08:19:56]

As you can see, the processes you run while the environment variable is set to a future time will get a fake time. Once the variable is unset new processes will get normal time.

This can be achieved also by creating a file. “.faketimerc” in your home folder:

$ php time.php 
The current time of the server is: Friday December 16. 2011 [08:23:12]
$ cp faketimerc .faketimerc
$ php time.php 
The current time of the server is: Friday December 21. 2012 [12:12:12]
$ rm -f .faketimerc 
$ php time.php 
The current time of the server is: Friday December 16. 2011 [08:23:36]

If you want to change time for a php application that runs though apache you may want to set the fake time system wide so that the php processes spowned use the faked time. To do this you need to create a file, /etc/.faketimerc, just the same as the one I created in my home folder.

I will use w3m for this demonstration. I assume a normal ubuntu server with apache2 installed.

sudo cp time.php /var/www
sudo cp faketimerc /etc/
$ sudo /etc/init.d/apache2 restart
 * Restarting web server apache2                                                                                                                                                                                                                                                   ... waiting
$ php /var/www/time.php
The current time of the server is: Friday December 21. 2012 [12:12:12]
$ date
fr. 21. des. 12:12:12 +0100 2012
$ w3m -dump localhost/time.php
The current time of the server is: Friday December 16. 2011 [11:16:24]

As you can see, the date command and when rendering the script with php, gives me the fake time, but when rendering the script through apache I loose the fake time. This is because the environment variable LD_PRELOAD is not set for the apache process.

To fix this I need to set LD_PRELOAD for apache by editing /etc/apache/envvars. Lets test it again:

$ sudo bash -c "echo \"export LD_PRELOAD='/usr/local/lib/faketime/libfaketime.so.1'\" >> /etc/apache2/envvars"
$ sudo /etc/init.d/apache2 restart
 * Restarting web server apache2                                                                                                                                                                                                                                                   ... waiting
$ w3m -dump localhost/time.php
The current time of the server is: Friday December 21. 2012 [12:12:16]

Fake time! :)

PS! If you also want your PostgreSQL server to use fake time:

$ sudo bash -c "echo \"LD_PRELOAD='/usr/local/lib/faketime/libfaketime.so.1'\" >> /etc/postgresql/8.4/main/environment"
$ sudo /etc/init.d/postgresql-8.4 restart
 Posted by at 12:47 pm