<commit_before><?php
/**
 * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
 * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice
 *
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 * @link          https://cakephp.org CakePHP(tm) Project
 * @since         2.5.0
 * @license       https://opensource.org/licenses/mit-license.php MIT License
 */
namespace Cake\Test\TestCase\Cache\Engine;

use Cake\Cache\Cache;
use Cake\Cache\Engine\MemcachedEngine;
use Cake\TestSuite\TestCase;
use Memcached;

/**
 * TestMemcachedEngine
 */
class TestMemcachedEngine extends MemcachedEngine
{

    /**
     * public accessor to _parseServerString
     *
     * @param string $server
     * @return array
     */
    public function parseServerString($server)
    {
        return $this->_parseServerString($server);
    }

    public function setMemcached($memcached)
    {
        $this->_Memcached = $memcached;
    }

    public function getMemcached()
    {
        return $this->_Memcached;
    }
}

/**
 * MemcachedEngineTest class
 */
class MemcachedEngineTest extends TestCase
{

    /**
     * setUp method
     *
     * @return void
     */
    public function setUp()
    {
        parent::setUp();
        $this->skipIf(!class_exists('Memcached'), 'Memcached is not installed or configured properly.');

        // @codingStandardsIgnoreStart
        $socket = @fsockopen('127.0.0.1', 11211, $errno, $errstr, 1);
        // @codingStandardsIgnoreEnd
        $this->skipIf(!$socket, 'Memcached is not running.');
        fclose($socket);

        $this->_configCache();
    }

    /**
     * Helper method for testing.
     *
     * @param array $config
     * @return void
     */
    protected function _configCache($config = [])
    {
        $defaults = [
            'className' => 'Memcached',
            'prefix' => 'cake_',
            'duration' => 3600
        ];
        Cache::drop('memcached');
        Cache::config('memcached', array_merge($defaults, $config));
    }

    /**
     * tearDown method
     *
     * @return void
     */
    public function tearDown()
    {
        parent::tearDown();
        Cache::drop('memcached');
        Cache::drop('memcached2');
        Cache::drop('memcached_groups');
        Cache::drop('memcached_helper');
        Cache::drop('compressed_memcached');
        Cache::drop('long_memcached');
        Cache::drop('short_memcached');
    }

    /**
     * testConfig method
     *
     * @return void
     */
    public function testConfig()
    {
        $config = Cache::engine('memcached')->config();
        unset($config['path']);
        $expecting = [
            'prefix' => 'cake_',
            'duration' => 3600,
            'probability' => 100,
            'servers' => ['127.0.0.1'],
            'persistent' => false,
            'compress' => false,
            'username' => null,
            'password' => <PASSWORD>,
            'groups' => [],
            'serialize' => 'php',
            'options' => [],
            'host' => null,
            'port' => null,
        ];
        $this->assertEquals($expecting, $config);
    }

    /**
     * testCompressionSetting method
     *
     * @return void
     */
    public function testCompressionSetting()
    {
        $Memcached = new TestMemcachedEngine();
        $Memcached->init([
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'compress' => false
        ]);

        $this->assertFalse($Memcached->getMemcached()->getOption(\Memcached::OPT_COMPRESSION));

        $MemcachedCompressed = new TestMemcachedEngine();
        $MemcachedCompressed->init([
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'compress' => true
        ]);

        $this->assertTrue($MemcachedCompressed->getMemcached()->getOption(\Memcached::OPT_COMPRESSION));
    }

    /**
     * test setting options
     *
     * @return void
     */
    public function testOptionsSetting()
    {
        $memcached = new TestMemcachedEngine();
        $memcached->init([
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'options' => [
                Memcached::OPT_BINARY_PROTOCOL => true
            ]
        ]);
        $this->assertEquals(1, $memcached->getMemcached()->getOption(Memcached::OPT_BINARY_PROTOCOL));
    }

    /**
     * test accepts only valid serializer engine
     *
     * @return  void
     */
    public function testInvalidSerializerSetting()
    {
        $Memcached = new TestMemcachedEngine();
        $config = [
            'className' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'serialize' => 'invalid_serializer'
        ];

        $this->expectException(\InvalidArgumentException::class);
        $this->expectExceptionMessage('invalid_serializer is not a valid serializer engine for Memcached');
        $Memcached->init($config);
    }

    /**
     * testPhpSerializerSetting method
     *
     * @return void
     */
    public function testPhpSerializerSetting()
    {
        $Memcached = new TestMemcachedEngine();
        $config = [
            'className' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'serialize' => 'php'
        ];

        $Memcached->init($config);
        $this->assertEquals(Memcached::SERIALIZER_PHP, $Memcached->getMemcached()->getOption(Memcached::OPT_SERIALIZER));
    }

    /**
     * testJsonSerializerSetting method
     *
     * @return void
     */
    public function testJsonSerializerSetting()
    {
        $this->skipIf(
            !Memcached::HAVE_JSON,
            'Memcached extension is not compiled with json support'
        );

        $Memcached = new TestMemcachedEngine();
        $config = [
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'serialize' => 'json'
        ];

        $Memcached->init($config);
        $this->assertEquals(Memcached::SERIALIZER_JSON, $Memcached->getMemcached()->getOption(Memcached::OPT_SERIALIZER));
    }

    /**
     * testIgbinarySerializerSetting method
     *
     * @return void
     */
    public function testIgbinarySerializerSetting()
    {
        $this->skipIf(
            !Memcached::HAVE_IGBINARY,
            'Memcached extension is not compiled with igbinary support'
        );

        $Memcached = new TestMemcachedEngine();
        $config = [
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'serialize' => 'igbinary'
        ];

        $Memcached->init($config);
        $this->assertEquals(Memcached::SERIALIZER_IGBINARY, $Memcached->getMemcached()->getOption(Memcached::OPT_SERIALIZER));
    }

    /**
     * testMsgpackSerializerSetting method
     *
     * @return void
     */
    public function testMsgpackSerializerSetting()
    {
        $this->skipIf(
            !defined('Memcached::HAVE_MSGPACK') || !Memcached::HAVE_MSGPACK,
            'Memcached extension is not compiled with msgpack support'
        );

        $Memcached = new TestMemcachedEngine();
        $config = [
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'serialize' => 'msgpack'
        ];

        $Memcached->init($config);
        $this->assertEquals(Memcached::SERIALIZER_MSGPACK, $Memcached->getMemcached()->getOption(Memcached::OPT_SERIALIZER));
    }

    /**
     * testJsonSerializerThrowException method
     *
     * @return void
     */
    public function testJsonSerializerThrowException()
    {
        $this->skipIf(
            Memcached::HAVE_JSON,
            'Memcached extension is compiled with json support'
        );

        $Memcached = new TestMemcachedEngine();
        $config = [
            'className' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'serialize' => 'json'
        ];

        $this->expectException(\InvalidArgumentException::class);
        $this->expectExceptionMessage('Memcached extension is not compiled with json support');
        $Memcached->init($config);
    }

    /**
     * testMsgpackSerializerThrowException method
     *
     * @return void
     */
    public function testMsgpackSerializerThrowException()
    {
        $this->skipIf(
            defined('Memcached::HAVE_MSGPACK') && Memcached::HAVE_MSGPACK,
            'Memcached extension is compiled with msgpack support'
        );

        $Memcached = new TestMemcachedEngine();
        $config = [
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'serialize' => 'msgpack'
        ];

        $this->expectException(\InvalidArgumentException::class);
        $this->expectExceptionMessage('msgpack is not a valid serializer engine for Memcached');
        $Memcached->init($config);
    }

    /**
     * testIgbinarySerializerThrowException method
     *
     * @return void
     */
    public function testIgbinarySerializerThrowException()
    {
        $this->skipIf(
            Memcached::HAVE_IGBINARY,
            'Memcached extension is compiled with igbinary support'
        );

        $Memcached = new TestMemcachedEngine();
        $config = [
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'serialize' => 'igbinary'
        ];

        $this->expectException(\InvalidArgumentException::class);
        $this->expectExceptionMessage('Memcached extension is not compiled with igbinary support');
        $Memcached->init($config);
    }

    /**
     * test using authentication without memcached installed with SASL support
     * throw an exception
     *
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage Memcached extension is not build with SASL support
     * @return void
     */
    public function testSaslAuthException()
    {
        $MemcachedEngine = new TestMemcachedEngine();
        $config = [
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'username' => 'test',
            'password' => 'password'
        ];

        $MemcachedEngine->init($config);
    }

    /**
     * testConfig method
     *
     * @return void
     */
    public function testMultipleServers()
    {
        $servers = ['127.0.0.1:11211', '127.0.0.1:11222'];
        $available = true;
        $Memcached = new \Memcached();

        foreach ($servers as $server) {
            list($host, $port) = explode(':', $server);
            //@codingStandardsIgnoreStart
            if (!$Memcached->addServer($host, $port)) {
                $available = false;
            }
            //@codingStandardsIgnoreEnd
        }

        $this->skipIf(!$available, 'Need memcached servers at ' . implode(', ', $servers) . ' to run this test.');

        $Memcached = new MemcachedEngine();
        $Memcached->init(['engine' => 'Memcached', 'servers' => $servers]);

        $config = $Memcached->config();
        $this->assertEquals($config['servers'], $servers);
        Cache::drop('dual_server');
    }

    /**
     * test connecting to an ipv6 server.
     *
     * @return void
     */
    public function testConnectIpv6()
    {
        $Memcached = new MemcachedEngine();
        $result = $Memcached->init([
            'prefix' => 'cake_',
            'duration' => 200,
            'engine' => 'Memcached',
            'servers' => [
                '[::1]:11211'
            ]
        ]);
        $this->assertTrue($result);
    }

    /**
     * test domain starts with u
     *
     * @return void
     */
    public function testParseServerStringWithU()
    {
        $Memcached = new TestMemcachedEngine();
        $result = $Memcached->parseServerString('udomain.net:13211');
        $this->assertEquals(['udomain.net', '13211'], $result);
    }

    /**
     * test non latin domains.
     *
     * @return void
     */
    public function testParseServerStringNonLatin()
    {
        $Memcached = new TestMemcachedEngine();
        $result = $Memcached->parseServerString('schülervz.net:13211');
        $this->assertEquals(['schülervz.net', '13211'], $result);

        $result = $Memcached->parseServerString('sülül:1111');
        $this->assertEquals(['sülül', '1111'], $result);
    }

    /**
     * test unix sockets.
     *
     * @return void
     */
    public function testParseServerStringUnix()
    {
        $Memcached = new TestMemcachedEngine();
        $result = $Memcached->parseServerString('unix:///path/to/memcachedd.sock');
        $this->assertEquals(['/path/to/memcachedd.sock', 0], $result);
    }

    /**
     * testReadAndWriteCache method
     *
     * @return void
     */
    public function testReadAndWriteCache()
    {
        $this->_configCache(['duration' => 1]);

        $result = Cache::read('test', 'memcached');
        $expecting = '';
        $this->assertEquals($expecting, $result);

        $data = 'this is a test of the emergency broadcasting system';
        $result = Cache::write('test', $data, 'memcached');
        $this->assertTrue($result);

        $result = Cache::read('test', 'memcached');
        $expecting = $data;
        $this->assertEquals($expecting, $result);

        Cache::delete('test', 'memcached');
    }

    /**
     * testReadMany method
     *<commit_msg>Update tests to not use test stub.<commit_after><?php
/**
 * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
 * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice
 *
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 * @link          https://cakephp.org CakePHP(tm) Project
 * @since         2.5.0
 * @license       https://opensource.org/licenses/mit-license.php MIT License
 */
namespace Cake\Test\TestCase\Cache\Engine;

use Cake\Cache\Cache;
use Cake\Cache\Engine\MemcachedEngine;
use Cake\TestSuite\TestCase;
use Memcached;

/**
 * MemcachedEngineTest class
 */
class MemcachedEngineTest extends TestCase
{

    /**
     * setUp method
     *
     * @return void
     */
    public function setUp()
    {
        parent::setUp();
        $this->skipIf(!class_exists('Memcached'), 'Memcached is not installed or configured properly.');

        // @codingStandardsIgnoreStart
        $socket = @fsockopen('127.0.0.1', 11211, $errno, $errstr, 1);
        // @codingStandardsIgnoreEnd
        $this->skipIf(!$socket, 'Memcached is not running.');
        fclose($socket);

        $this->_configCache();
    }

    /**
     * Helper method for testing.
     *
     * @param array $config
     * @return void
     */
    protected function _configCache($config = [])
    {
        $defaults = [
            'className' => 'Memcached',
            'prefix' => 'cake_',
            'duration' => 3600
        ];
        Cache::drop('memcached');
        Cache::config('memcached', array_merge($defaults, $config));
    }

    /**
     * tearDown method
     *
     * @return void
     */
    public function tearDown()
    {
        parent::tearDown();
        Cache::drop('memcached');
        Cache::drop('memcached2');
        Cache::drop('memcached_groups');
        Cache::drop('memcached_helper');
        Cache::drop('compressed_memcached');
        Cache::drop('long_memcached');
        Cache::drop('short_memcached');
    }

    /**
     * testConfig method
     *
     * @return void
     */
    public function testConfig()
    {
        $config = Cache::engine('memcached')->config();
        unset($config['path']);
        $expecting = [
            'prefix' => 'cake_',
            'duration' => 3600,
            'probability' => 100,
            'servers' => ['127.0.0.1'],
            'persistent' => false,
            'compress' => false,
            'username' => null,
            'password' => <PASSWORD>,
            'groups' => [],
            'serialize' => 'php',
            'options' => [],
            'host' => null,
            'port' => null,
        ];
        $this->assertEquals($expecting, $config);
    }

    /**
     * testCompressionSetting method
     *
     * @return void
     */
    public function testCompressionSetting()
    {
        $Memcached = new MemcachedEngine();
        $Memcached->init([
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'compress' => false
        ]);

        $this->assertFalse($Memcached->getOption(\Memcached::OPT_COMPRESSION));

        $MemcachedCompressed = new MemcachedEngine();
        $MemcachedCompressed->init([
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'compress' => true
        ]);

        $this->assertTrue($MemcachedCompressed->getOption(\Memcached::OPT_COMPRESSION));
    }

    /**
     * test setting options
     *
     * @return void
     */
    public function testOptionsSetting()
    {
        $memcached = new MemcachedEngine();
        $memcached->init([
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'options' => [
                Memcached::OPT_BINARY_PROTOCOL => true
            ]
        ]);
        $this->assertEquals(1, $memcached->getOption(Memcached::OPT_BINARY_PROTOCOL));
    }

    /**
     * test accepts only valid serializer engine
     *
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage invalid_serializer is not a valid serializer engine for Memcached
     * @return  void
     */
    public function testInvalidSerializerSetting()
    {
        $Memcached = new MemcachedEngine();
        $config = [
            'className' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'serialize' => 'invalid_serializer'
        ];
        $Memcached->init($config);
    }

    /**
     * testPhpSerializerSetting method
     *
     * @return void
     */
    public function testPhpSerializerSetting()
    {
        $Memcached = new MemcachedEngine();
        $config = [
            'className' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'serialize' => 'php'
        ];

        $Memcached->init($config);
        $this->assertEquals(Memcached::SERIALIZER_PHP, $Memcached->getOption(Memcached::OPT_SERIALIZER));
    }

    /**
     * testJsonSerializerSetting method
     *
     * @return void
     */
    public function testJsonSerializerSetting()
    {
        $this->skipIf(
            !Memcached::HAVE_JSON,
            'Memcached extension is not compiled with json support'
        );

        $Memcached = new MemcachedEngine();
        $config = [
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'serialize' => 'json'
        ];

        $Memcached->init($config);
        $this->assertEquals(Memcached::SERIALIZER_JSON, $Memcached->getOption(Memcached::OPT_SERIALIZER));
    }

    /**
     * testIgbinarySerializerSetting method
     *
     * @return void
     */
    public function testIgbinarySerializerSetting()
    {
        $this->skipIf(
            !Memcached::HAVE_IGBINARY,
            'Memcached extension is not compiled with igbinary support'
        );

        $Memcached = new MemcachedEngine();
        $config = [
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'serialize' => 'igbinary'
        ];

        $Memcached->init($config);
        $this->assertEquals(Memcached::SERIALIZER_IGBINARY, $Memcached->getOption(Memcached::OPT_SERIALIZER));
    }

    /**
     * testMsgpackSerializerSetting method
     *
     * @return void
     */
    public function testMsgpackSerializerSetting()
    {
        $this->skipIf(
            !defined('Memcached::HAVE_MSGPACK') || !Memcached::HAVE_MSGPACK,
            'Memcached extension is not compiled with msgpack support'
        );

        $Memcached = new MemcachedEngine();
        $config = [
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'serialize' => 'msgpack'
        ];

        $Memcached->init($config);
        $this->assertEquals(Memcached::SERIALIZER_MSGPACK, $Memcached->getOption(Memcached::OPT_SERIALIZER));
    }

    /**
     * testJsonSerializerThrowException method
     *
     * @return void
     */
    public function testJsonSerializerThrowException()
    {
        $this->skipIf(
            Memcached::HAVE_JSON,
            'Memcached extension is compiled with json support'
        );

        $Memcached = new MemcachedEngine();
        $config = [
            'className' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'serialize' => 'json'
        ];

        $this->expectException(\InvalidArgumentException::class);
        $this->expectExceptionMessage('Memcached extension is not compiled with json support');
        $Memcached->init($config);
    }

    /**
     * testMsgpackSerializerThrowException method
     *
     * @return void
     */
    public function testMsgpackSerializerThrowException()
    {
        $this->skipIf(
            defined('Memcached::HAVE_MSGPACK') && Memcached::HAVE_MSGPACK,
            'Memcached extension is compiled with msgpack support'
        );

        $Memcached = new MemcachedEngine();
        $config = [
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'serialize' => 'msgpack'
        ];

        $this->expectException(\InvalidArgumentException::class);
        $this->expectExceptionMessage('msgpack is not a valid serializer engine for Memcached');
        $Memcached->init($config);
    }

    /**
     * testIgbinarySerializerThrowException method
     *
     * @return void
     */
    public function testIgbinarySerializerThrowException()
    {
        $this->skipIf(
            Memcached::HAVE_IGBINARY,
            'Memcached extension is compiled with igbinary support'
        );

        $Memcached = new MemcachedEngine();
        $config = [
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'serialize' => 'igbinary'
        ];

        $this->expectException(\InvalidArgumentException::class);
        $this->expectExceptionMessage('Memcached extension is not compiled with igbinary support');
        $Memcached->init($config);
    }

    /**
     * test using authentication without memcached installed with SASL support
     * throw an exception
     *
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage Memcached extension is not build with SASL support
     * @return void
     */
    public function testSaslAuthException()
    {
        $this->skipIf(
            method_exists('setSaslAuthData', Memcached::class),
            'Cannot test exception when sasl has been compiled in.'
        );
        $MemcachedEngine = new MemcachedEngine();
        $config = [
            'engine' => 'Memcached',
            'servers' => ['127.0.0.1:11211'],
            'persistent' => false,
            'username' => 'test',
            'password' => 'password'
        ];
        $this->expectException(\InvalidArgumentException::class);
        $this->expectExceptionMessage('Memcached extension is not built with SASL support');
        $MemcachedEngine->init($config);
    }

    /**
     * testConfig method
     *
     * @return void
     */
    public function testMultipleServers()
    {
        $servers = ['127.0.0.1:11211', '127.0.0.1:11222'];
        $available = true;
        $Memcached = new \Memcached();

        foreach ($servers as $server) {
            list($host, $port) = explode(':', $server);
            //@codingStandardsIgnoreStart
            if (!$Memcached->addServer($host, $port)) {
                $available = false;
            }
            //@codingStandardsIgnoreEnd
        }

        $this->skipIf(!$available, 'Need memcached servers at ' . implode(', ', $servers) . ' to run this test.');

        $Memcached = new MemcachedEngine();
        $Memcached->init(['engine' => 'Memcached', 'servers' => $servers]);

        $config = $Memcached->config();
        $this->assertEquals($config['servers'], $servers);
        Cache::drop('dual_server');
    }

    /**
     * test connecting to an ipv6 server.
     *
     * @return void
     */
    public function testConnectIpv6()
    {
        $Memcached = new MemcachedEngine();
        $result = $Memcached->init([
            'prefix' => 'cake_',
            'duration' => 200,
            'engine' => 'Memcached',
            'servers' => [
                '[::1]:11211'
            ]
        ]);
        $this->assertTrue($result);
    }

    /**
     * test domain starts with u
     *
     * @return void
     */
    public function testParseServerStringWithU()
    {
        $Memcached = new MemcachedEngine();
        $result = $Memcached->parseServerString('udomain.net:13211');
        $this->assertEquals(['udomain.net', '13211'], $result);
    }

    /**
     * test non latin domains.
     *
     * @return void
     */
    public function testParseServerStringNonLatin()
    {
        $Memcached = new MemcachedEngine();
        $result = $Memcached->parseServerString('schülervz.net:13211');
        $this->assertEquals(['schülervz.net', '13211'], $result);

        $result = $Memcached->parseServerString('sülül:1111');
        $this->assertEquals(['sülül', '1111'], $result);
    }

    /**
     * test unix sockets.
     *
     * @return void
     */
    public function testParseServerStringUnix()
    {
        $Memcached = new MemcachedEngine();
        $result = $Memcached->parseServerString('unix:///path/to/memcachedd.sock');
        $this->assertEquals(['/path/to/memcachedd.sock', 0], $result);
    }

    /**
     * testReadAndWriteCache method
     *
     * @return void
     */
    public function testReadAndWriteCache()
    {
        $this->_configCache(['duration' => 1]);

        $result = Cache::read('test', 'memcached');
        $expecting = '';
        $this->assertEquals($expecting, $result);

        $data = 'this is a test of the emergency broadcasting system';
        $result = Cache::write('test', $data, 'memcached');
        $this->assertTrue($result);

        $result = Cache::read('test', 'memcached');
        $expecting = $data;
        $this->assertEquals($expecting, $result);

        Cache::delete('test', 'memcached');
    }

    /**
     * testReadMany method
     *
{'fraction_non_alphanumeric': 0.14282598422334508, 'fraction_numerical': 0.016649096659275147, 'mean_word_length': 2.102165087956698, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 284, 'https://': 10, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 32, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5895233', 'n_tokens_mistral': 8001, 'n_tokens_neox': 7655, 'n_words': 1487}