File indexing completed on 2024-12-22 03:47:06

0001 <?php
0002 /*
0003     SPDX-FileCopyrightText: 2016 Volker Krause <vkrause@kde.org>
0004 
0005     SPDX-License-Identifier: MIT
0006 */
0007 
0008 require_once('datastoretesthelper.php');
0009 require_once('../src/server/shared/product.php');
0010 
0011 class ProductTest extends PHPUnit\Framework\TestCase
0012 {
0013     private static $db;
0014 
0015     public static function setUpBeforeClass(): void
0016     {
0017         self::$db = DatastoreTestHelper::setup();
0018     }
0019 
0020     public static function tableName_data()
0021     {
0022         return [
0023             'normal' => [ 'foo', 'pd_foo' ],
0024             'dot' => [ 'org.kde.foo', 'pd_org_kde_foo' ]
0025         ];
0026     }
0027 
0028     /** @dataProvider tableName_data */
0029     public function testTableName($input, $output)
0030     {
0031         $p = new Product;
0032         $p->name = $input;
0033         $this->assertEquals($output, $p->dataTableName());
0034     }
0035 
0036     public function testFromJson()
0037     {
0038         $p = Product::fromJson('{
0039             "name": "org.kde.product",
0040             "schema": [
0041                 {
0042                     "name": "entry1",
0043                     "type": "scalar",
0044                     "elements" : [
0045                         { "name": "element1", "type": "int" },
0046                         { "name": "element2", "type": "bool" }
0047                     ]
0048                 }
0049             ],
0050             "aggregation": [ { "type": "category", "name": "n1", "elements": [
0051                 { "type": "value", "schemaEntry": "entry1", "schemaEntryElement": "element1" }
0052             ] } ]
0053         }');
0054         $this->assertEquals($p->name, 'org.kde.product');
0055         $this->assertEquals(1, count($p->schema));
0056         $this->assertEquals('pd_org_kde_product', $p->dataTableName());
0057         $entry = $p->schema[0];
0058         $this->assertEquals($entry->name, 'entry1');
0059         $this->assertEquals($entry->type, 'scalar');
0060 
0061         $this->assertEquals(2, count($entry->elements));
0062         $elem = $entry->elements[1];
0063         $this->assertInstanceOf(SchemaEntryElement::class, $elem);
0064         $this->assertEquals('element2', $elem->name);
0065         $this->assertEquals('bool', $elem->type);
0066 
0067         $this->assertCount(1, $p->aggregation);
0068     }
0069 
0070     public function testToJson()
0071     {
0072         $p = new Product();
0073         $p->name = 'org.kde.product';
0074         $entry = new SchemaEntry($p);
0075         $entry->name = 'entry1';
0076         $entry->type = 'list';
0077         $elem = new SchemaEntryElement($entry);
0078         $elem->name = 'element3';
0079         $elem->type = 'number';
0080         array_push($entry->elements, $elem);
0081         array_push($p->schema, $entry);
0082         $a = new Aggregation;
0083         $a->type = 'numeric';
0084         $a->name = 'n1';
0085         $a->elements = json_decode('[{ "type": "size", "schemaEntry": "entry1" }]');
0086         array_push($p->aggregation, $a);
0087 
0088         $this->assertJsonStringEqualsJsonString(json_encode($p), '{
0089             "name": "org.kde.product",
0090             "schema": [
0091                 {
0092                     "name": "entry1",
0093                     "type": "list",
0094                     "elements" : [
0095                         { "name": "element3", "type": "number" }
0096                     ]
0097                 }
0098             ],
0099             "aggregation": [ { "type": "numeric", "name": "n1", "elements": [
0100                 { "type": "size", "schemaEntry": "entry1" }
0101             ] } ]
0102         }');
0103     }
0104 
0105     public function testAllProducts()
0106     {
0107         $ps = Product::allProducts(self::$db);
0108         $this->assertEquals(1, count($ps));
0109         $p = $ps[0];
0110         $this->assertInstanceOf(Product::class, $p);
0111         $this->assertEquals('org.kde.UnitTest', $p->name);
0112         $this->assertEquals(2, count($p->schema));
0113 
0114         $entry1 = $p->schema[0];
0115         $entry2 = $p->schema[1];
0116         if ($entry1->name > $entry2->name) {
0117             $entry1 = $p->schema[1];
0118             $entry2 = $p->schema[0];
0119         }
0120 
0121         $this->assertInstanceOf(SchemaEntry::class, $entry1);
0122         $this->assertEquals($entry1->name, 'entry1');
0123         $this->assertEquals($entry1->type, 'scalar');
0124         $this->assertEquals(2, count($entry1->elements));
0125         $elem = $entry1->elements[1];
0126         $this->assertInstanceOf(SchemaEntryElement::class, $elem);
0127         $this->assertEquals('element12', $elem->name);
0128         $this->assertEquals('bool', $elem->type);
0129 
0130         $this->assertInstanceOf(SchemaEntry::class, $entry2);
0131         $this->assertEquals($entry2->name, 'entry2');
0132         $this->assertEquals($entry2->type, 'list');
0133 
0134         $this->assertCount(2, $p->aggregation);
0135     }
0136 
0137     public function testProductByName()
0138     {
0139         $p = Product::productByName(self::$db, 'I don\'t exist');
0140         $this->assertNull($p);
0141 
0142         $p = Product::productByName(self::$db, 'org.kde.UnitTest');
0143         $this->assertInstanceOf(Product::class, $p);
0144         $this->assertEquals('org.kde.UnitTest', $p->name);
0145         $this->assertEquals(2, count($p->schema));
0146 
0147         $entry1 = $p->schema[0];
0148         $entry2 = $p->schema[1];
0149         if ($entry1->name > $entry2->name) {
0150             $entry1 = $p->schema[1];
0151             $entry2 = $p->schema[0];
0152         }
0153 
0154         $this->assertInstanceOf(SchemaEntry::class, $entry1);
0155         $this->assertEquals($entry1->name, 'entry1');
0156         $this->assertEquals($entry1->type, 'scalar');
0157         $elem = $entry1->elements[1];
0158         $this->assertInstanceOf(SchemaEntryElement::class, $elem);
0159         $this->assertEquals('element12', $elem->name);
0160         $this->assertEquals('bool', $elem->type);
0161 
0162         $this->assertInstanceOf(SchemaEntry::class, $entry2);
0163         $this->assertEquals($entry2->name, 'entry2');
0164         $this->assertEquals($entry2->type, 'list');
0165     }
0166 
0167     public function testProductInsert()
0168     {
0169         $json = '{
0170             "name": "org.kde.NewProduct",
0171             "schema": [
0172                 {
0173                     "name": "entryA",
0174                     "type": "scalar",
0175                     "elements" : [
0176                         { "name": "elementA1", "type": "int" },
0177                         { "name": "elementA2", "type": "bool" }
0178                     ]
0179                 },
0180                 {
0181                     "name": "entryB",
0182                     "type": "map",
0183                     "elements" : [
0184                         { "name": "elementB1", "type": "number" },
0185                         { "name": "elementB2", "type": "string" }
0186                     ]
0187                 }
0188             ],
0189             "aggregation": [
0190                 {
0191                     "type": "category",
0192                     "name": "n1",
0193                     "elements": [
0194                         { "type": "value", "schemaEntry": "entryA", "schemaEntryElement": "elementA1" }
0195                     ]
0196                 },
0197                 {
0198                     "type": "ratio_set",
0199                     "name": "n2",
0200                     "elements": [
0201                         { "type": "value", "schemaEntry": "entryB", "schemaEntryElement": "elementB1" }
0202                     ]
0203                 }
0204             ]
0205         }';
0206 
0207         $p = Product::fromJson($json);
0208         $p->insert(self::$db);
0209 
0210         $p = Product::productByName(self::$db, 'org.kde.NewProduct');
0211         $p->aggregation = Aggregation::aggregationsForProduct(self::$db, $p);
0212         $this->assertJsonStringEqualsJsonString($json, json_encode($p));
0213     }
0214 
0215     public function testProductUpdate()
0216     {
0217         $jsonOld = '{
0218             "name": "org.kde.ProductToUpdate",
0219             "schema": [
0220                 {
0221                     "name": "entryA",
0222                     "type": "scalar",
0223                     "elements" : [
0224                         { "name": "elementA1", "type": "int" },
0225                         { "name": "elementA2", "type": "bool" }
0226                     ]
0227                 },
0228                 {
0229                     "name": "entryB",
0230                     "type": "list",
0231                     "elements" : [
0232                         { "name": "elementB1", "type": "number" },
0233                         { "name": "elementB2", "type": "string" }
0234                     ]
0235                 }
0236             ],
0237             "aggregation": [
0238                 {
0239                     "type": "ratio_set",
0240                     "name": "n2",
0241                     "elements": [
0242                         { "type": "value", "schemaEntry": "entryB", "schemaEntryElement": "elementB1" }
0243                     ]
0244                 }
0245             ]
0246         }';
0247 
0248         $p = Product::fromJson($jsonOld);
0249         $p->insert(self::$db);
0250 
0251         $p = Product::productByName(self::$db, 'org.kde.ProductToUpdate');
0252         $p->aggregation = Aggregation::aggregationsForProduct(self::$db, $p);
0253         $this->assertJsonStringEqualsJsonString($jsonOld, json_encode($p));
0254 
0255         $jsonNew = '{
0256             "name": "org.kde.ProductToUpdate",
0257             "schema": [
0258                 {
0259                     "name": "entryA",
0260                     "type": "scalar",
0261                     "elements" : [
0262                         { "name": "elementA1", "type": "int" }
0263                     ]
0264                 },
0265                 {
0266                     "name": "entryC",
0267                     "type": "map",
0268                     "elements" : [
0269                         { "name": "elementC1", "type": "number" },
0270                         { "name": "elementC2", "type": "number" }
0271                     ]
0272                 }
0273             ],
0274             "aggregation": [
0275                 {
0276                     "type": "category",
0277                     "name": "n1",
0278                     "elements": [
0279                         { "type": "value", "schemaEntry": "entryA", "schemaEntryElement": "elementA1" }
0280                     ]
0281                 },
0282                 {
0283                     "type": "xy",
0284                     "name": "n3",
0285                     "elements": [
0286                         { "type": "value", "schemaEntry": "entryC", "schemaEntryElement": "elementC1" },
0287                         { "type": "value", "schemaEntry": "entryC", "schemaEntryElement": "elementC2" }
0288                     ]
0289                 }
0290             ]
0291         }';
0292         $newP = Product::fromJson($jsonNew);
0293         $p->update(self::$db, $newP);
0294 
0295         $p = Product::productByName(self::$db, 'org.kde.ProductToUpdate');
0296         $p->aggregation = Aggregation::aggregationsForProduct(self::$db, $p);
0297         $this->assertJsonStringEqualsJsonString($jsonNew, json_encode($p));
0298     }
0299 
0300     public function testProductDelete()
0301     {
0302         $json = '{
0303             "name": "org.kde.DeletedProduct",
0304             "schema": [
0305                 {
0306                     "name": "entry1",
0307                     "type": "list",
0308                     "elements" : [
0309                         { "name": "element3", "type": "number" }
0310                     ]
0311                 }
0312             ],
0313             "aggregation": [
0314                 {
0315                     "type": "numeric",
0316                     "name": "n4",
0317                     "elements": [
0318                         { "type": "size", "schemaEntry": "entry1" }
0319                     ]
0320                 }
0321             ]
0322         }';
0323 
0324         $p = Product::fromJson($json);
0325         $p->insert(self::$db);
0326         $p = Product::productByName(self::$db, 'org.kde.DeletedProduct');
0327         $p->aggregation = Aggregation::aggregationsForProduct(self::$db, $p);
0328         $this->assertJsonStringEqualsJsonString($json, json_encode($p));
0329 
0330         $p->delete(self::$db);
0331         $p = Product::productByName(self::$db, 'org.kde.DeletedProduct');
0332         $this->assertNull($p);
0333     }
0334 
0335     public static function invalidInput_data()
0336     {
0337         return [
0338             'empty' => [ '{}' ],
0339             'empty name' => [ '{ "name": "", "schema": [] }' ],
0340             'invalid name' => [ '{ "name": "123", "schema": [] }' ],
0341             'non-string name' => [ '{ "name": 123, "schema": [] }' ]
0342         ];
0343     }
0344 
0345     /**
0346      * @dataProvider invalidInput_data
0347      */
0348     public function testInvalidInput($json)
0349     {
0350         $this->expectException(RESTException::class);
0351         $this->expectExceptionCode(400);
0352         $p = Product::fromJson($json);
0353     }
0354 }
0355