aboutsummaryrefslogtreecommitdiffstats
path: root/tests/unit/includes/dba/DbaPdoTest.php
blob: 5d85a16048894cd9157ef16a2f9a52fa707d42b8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<?php
/**
 * Tests for `includes/dba_pdo.php`.
 *
 * SPDX-FileCopyrightText: 2024 Hubzilla Community
 * SPDX-FileContributor: Harald Eilertsen
 *
 * SPDX-License-Identifier: MIT
 */

namespace Zotlabs\Tests\Unit\includes;

use DBA;
use PDO;
use PDOStatement;
use PHPUnit\Framework\Attributes\DataProvider;
use Zotlabs\Tests\Unit\UnitTestCase;

class DbaPdoTest extends UnitTestCase
{
	public function testInsertingRowWithRturningClauseReturnsInsertedRow(): void
	{
		// MySQL does not support the `returning` clause, so we skip the test
		// for that DB backend.
		$this->skipIfMySQL();

		// Let's manually insert a row in the config table.
		// This is just because it's a conventient table to test
		// against
		$res = q(<<<SQL
			INSERT INTO config (cat, k, v)
				VALUES ('test', 'a key', 'A value')
				RETURNING *
			SQL);

		$this->assertIsArray($res);
		$this->assertIsArray($res[0]);
		$this->assertTrue($res[0]['id'] > 0);
		$this->assertEquals('test', $res[0]['cat']);
		$this->assertEquals('a key', $res[0]['k']);
		$this->assertEquals('A value', $res[0]['v']);
	}

	#[DataProvider('insertRowProvider')]
	public function testInsertRow(string $table, array $data, string $id): void
	{
		$res = DBA::$dba->insert($table, $data, $id);

		$this->assertIsArray($res);

		// Make sure the result contains the expected id
		$this->assertArrayHasKey($id, $res);

		foreach ($data as $key => $value) {
			$this->assertEquals($value, $res[$key]);
		}
	}

	#[DataProvider('insertRowProvider')]
	public function testInsertShouldReturnFalseIfInsertFails(
		string $table,
		array $data,
		string $id
		): void
	{
		$res1 = DBA::$dba->insert($table, $data, $id);
		$this->assertIsArray($res1);

		// Inserting the same row again should fail.
		$res2 = DBA::$dba->insert($table, $data, $id);
		$this->assertFalse($res2);
	}

	/**
	 * Dataprovider for testInertRow.
	 *
	 * @return array	An array of [ $table, $data, $id ] elements.
	 */
	public static function insertRowProvider(): array
	{
		return [
			'table with numeric primary id' => [
				'config',
				[ 'cat' => 'test', 'k' => 'a key', 'v' => 'A value' ],
				'id',
			],
			'table with text primary id' => [
				'cache',
				[ 'k' => 'some key', 'v' => 'cached value', 'updated' => date('Y-m-d H:i:s')],
				'k',
			],
		];
	}

	public function testUpdateRow(): void
	{
		// Let's fetch a row from the config table
		$res = q('SELECT * FROM config WHERE cat = "system" AND k = "baseurl"');

		$this->assertIsArray($res);
		$this->assertIsArray($res[0]);

		$row = $res[0];

		// Update the baseurl
		$updated = DBA::$dba->update(
			'config',
			[ 'v' => 'https://some.other_site.test/' ],
			'id',
			$row['id']
		);

		$this->assertTrue($updated);

		// Verify that the record was updated
		$updated_res = q('SELECT * FROM config WHERE cat = "system" AND k = "baseurl"');
		$this->assertIsArray($updated_res);

		$updated_row = $updated_res[0];

		$this->assertIsArray($updated_row);
		$this->assertEquals($row['id'], $updated_row['id']);
		$this->assertEquals('system', $updated_row['cat']);
		$this->assertEquals('baseurl', $updated_row['k']);
		$this->assertEquals('https://some.other_site.test/', $updated_row['v']);
	}

	/**
	 * Mark the test as skipped if the current db is MySQL.
	 */
	private function skipIfMySQL(): void {
		$driver = DBA::$dba->db->getAttribute(PDO::ATTR_DRIVER_NAME);
		$version = DBA::$dba->db->getAttribute(PDO::ATTR_SERVER_VERSION);

		if ($driver === 'mysql' && stripos($version, 'mariadb') === false) {
			$this->markTestSkipped("RETURNING clause not supported for {$driver}");
		}

	}
}