<?php 
declare(strict_types=1); 
 
namespace ParagonIE\EasyDB\Tests; 
 
use Exception; 
use ParagonIE\EasyDB\EasyDB; 
use PDO; 
use PDOException; 
 
class SetAttributeTest extends GetAttributeTest 
{ 
 
    /** 
     * @dataProvider goodFactoryCreateArgument2EasyDBWithPDOAttributeProvider 
     * @depends      ParagonIE\EasyDB\Tests\GetAttributeTest::testAttribute 
     * @param callable $cb 
     * @param $attr 
     * @param string $attrName 
     * @throws Exception 
     */ 
    public function testAttribute(callable $cb, $attr, string $attrName) 
    { 
        $db = $this->easyDBExpectedFromCallable($cb); 
        $skipping = [ 
            'ATTR_STATEMENT_CLASS' 
        ]; 
        if (in_array($attrName, $skipping)) { 
            $this->markTestSkipped( 
                'Skipping tests for ' . 
                EasyDB::class . 
                '::setAttribute() with ' . 
                PDO::class . 
                '::' . 
                $attrName . 
                ' as provider for ' . 
                static::class . 
                '::' . 
                __METHOD__ . 
                '() currently does not provide values' 
            ); 
        } 
        try { 
            $initial = $db->getAttribute($attr); 
            $this->assertSame( 
                $db->getAttribute($attr), 
                $db->getPdo()->getAttribute($attr) 
            ); 
            $this->assertSame( 
                $db->setAttribute($attr, $db->getAttribute($attr)), 
                $db->getPdo()->setAttribute($attr, $db->getAttribute($attr)) 
            ); 
            $this->assertSame( 
                $db->setAttribute($attr, $db->getPdo()->getAttribute($attr)), 
                $db->getPdo()->setAttribute($attr, $db->getPdo()->getAttribute($attr)) 
            ); 
            $this->assertSame( 
                $db->getAttribute($attr), 
                $initial 
            ); 
            $this->assertSame( 
                $db->getPdo()->getAttribute($attr), 
                $initial 
            ); 
        } catch (PDOException $e) { 
            if (strpos( 
                $e->getMessage(), 
                ': Driver does not support this function: driver does not support that attribute' 
            ) !== false 
            ) { 
                $this->markTestSkipped( 
                    'Skipping tests for ' . 
                    EasyDB::class . 
                    '::setAttribute() with ' . 
                    PDO::class . 
                    '::' . 
                    $attrName . 
                    ' as driver "' . 
                    $db->getDriver() . 
                    '" does not support that attribute' 
                ); 
            } else { 
                throw $e; 
            } 
        } catch (Exception $e) { 
            if (( 
                    $attrName === 'ATTR_ERRMODE' && 
                    $e->getMessage() === 'EasyDB only allows the safest-by-default error mode (exceptions).' 
                ) || 
                ( 
                    $attrName === 'ATTR_EMULATE_PREPARES' && 
                    $e->getMessage() === ( 
                        'EasyDB does not allow the use of emulated prepared statements' . 
                        ', which would be a security downgrade.' 
                    ) 
                ) 
            ) { 
                $this->markTestSkipped( 
                    'Skipping tests for ' . 
                    EasyDB::class . 
                    '::setAttribute() with ' . 
                    PDO::class . 
                    '::' . 
                    $attrName . 
                    ' as ' . 
                    $e->getMessage() 
                ); 
            } else { 
                throw $e; 
            } 
        } 
    } 
 
    /** 
    * EasyDB data provider 
    * Returns an array of callables that return instances of EasyDB 
    * @return array 
    * @see EasyDBTest::goodFactoryCreateArgument2EasyDBProvider() 
    */ 
    public function goodFactoryCreateArgument2EasyDBForSetPDOAttributeThrowsExceptionProvider() 
    { 
        $exceptionProvider = [ 
            [ 
                PDO::ATTR_ERRMODE, 
                PDO::ERRMODE_SILENT, 
                Exception::class, 
                'EasyDB only allows the safest-by-default error mode (exceptions).', 
            ], 
            [ 
                PDO::ATTR_ERRMODE, 
                PDO::ERRMODE_WARNING, 
                Exception::class, 
                'EasyDB only allows the safest-by-default error mode (exceptions).', 
            ], 
            [ 
                PDO::ATTR_EMULATE_PREPARES, 
                true, 
                Exception::class, 
                'EasyDB does not allow the use of emulated prepared statements, which would be a security downgrade.', 
            ], 
            [ 
                PDO::ATTR_EMULATE_PREPARES, 
                1, 
                Exception::class, 
                'EasyDB does not allow the use of emulated prepared statements, which would be a security downgrade.', 
            ], 
        ]; 
        return array_reduce( 
            $this->goodFactoryCreateArgument2EasyDBProvider(), 
            function (array $was, array $cbArgs) use ($exceptionProvider) { 
                return array_merge( 
                    $was, 
                    array_map( 
                        function (array $args) use ($cbArgs) { 
                            foreach (array_reverse($cbArgs) as $cbArg) { 
                                array_unshift($args, $cbArg); 
                            } 
                            return $args; 
                        }, 
                        $exceptionProvider 
                    ) 
                ); 
            }, 
            [] 
        ); 
    } 
 
    /** 
     * Test which attributes will always throw an exception when set 
     * @dataProvider goodFactoryCreateArgument2EasyDBForSetPDOAttributeThrowsExceptionProvider 
     * @depends      testAttribute 
     * @param callable $cb 
     * @param int $attribute 
     * @param $value 
     * @param string $exceptionClassName 
     * @param string $exceptionMessage 
     */ 
    public function testSetAttributeThrowsException( 
        callable $cb, 
        int $attribute, 
        $value, 
        string $exceptionClassName, 
        string $exceptionMessage 
    ) { 
        $db = $this->easyDBExpectedFromCallable($cb); 
        $this->expectException($exceptionClassName); 
        $this->expectExceptionMessage($exceptionMessage); 
 
        $db->setAttribute($attribute, $value); 
    } 
} 
 
 |