views:

33

answers:

3

Ok, so here's the issue I've run into. On some of our production systems, we have magic quotes gpc enabled. There's nothing I can do about that. So, I've built my request data handing classes to compensate:

protected static function clean($var)
{
     if (get_magic_quotes_gpc()) {
        if (is_array($var)) {
            foreach ($var as $k => $v) {
                $var[$k] = self::clean($v);
            }
        } else {
            $var = stripslashes($var);
        }
    }
    return $var;
}

I do some other things in that method, but that's not an issue.

So, I'm currently trying to write a set of Unit-Tests for that method, and I've run into a road bock. How can I test both execution paths with respect to the result of get_magic_quotes_gpc()? I can't modify the ini settings at run time for that (because it's already loaded)... I've tried searching the PHPUnit docs, but I can't find anything related to this type of issue. Is there something that I'm missing here? Or will I have to live with being unable to test all possible code execution paths?

Thanks

A: 

I'm not 100% certain about this, but I think magic_quotes_gpc just means that all strings have had addslashes() applied to them. So to emulate having magic_quotes_gpc, you can apply addslashes recursively to the $_GET, $_POST and $_COOKIE arrays. That doesn't solve the fact that get_magic_quotes_gpc() will be returning false - you'll just have to replace get_magic_quotes_gpc() with true when doing the appropriate unit test, I guess.

Edit: As stated in http://www.php.net/manual/en/function.addslashes.php

'The PHP directive magic_quotes_gpc is on by default, and it essentially runs addslashes() on all GET, POST, and COOKIE data.'

Hammerite
+1  A: 

A possible (but not perfect) solution would be to pass the value of get_magic_quotes_gpc() as parameter, like:

protected static function clean($var, $magic_quotes = null)
{
  if ($magic_quotes === null) $magic_quotes = get_magic_quotes_gpc();
  do_stuff();
}

Ofc this has the disadvantage of... well, being ugly, but ini settings and defines are always horrible to test, thats why you should try to avoid them. One way to avoid using them directly would be:

class Config
{
  private static $magic_quotes = null;

  public static GetMagicQuotes()
  {
    if (Config::$magic_quotes === null)
    {
      Config::$magic_quotes = get_magic_quotes_gpc();
    }
    return Config::$magic_quotes;
  }

  public static SetMagicQuotes($new_value)
  {
    Config::$magic_quotes = $new_value;
  }
}

[...somewhere else...]

protected static function clean($var)
{
  if (Config::GetMagicQuotes())
  {
    do_stuff();
  }
}

[... in your tests...]


public test_clean_with_quotes()
{
  Config::SetMagicQuotes(true);
  doTests();
}

public test_clean_without_quotes()
{
  Config::SetMagicQuotes(false);
  doTests();
}
dbemerlin
Well, that got me on the right track... I implemented something different (See my answer), but it's similar to both of your examples (but different)... Thanks again...
ircmaxell
+1  A: 

Well, I came across a workaround...

In the constructor, I call get_magic_quotes_gpc():

protected $magicQuotes = null;

public function __construct() {
    $this->magicQuotes = get_magic_quotes_gpc();
}

protected function clean($var) {
    if ($this->magicQuotes) {
        //...
    }
}

Then, for testing, I just sub-class it, and then provide a public method for manually setting $this->magicQuotes. It's not really clean, but it's nice since it saves the overhead of a function call on each recursion...

ircmaxell