0, 'items' => ['a', 'b'], 'user' => $userClass, 'metadata' => null, ]); $schema = $validator->deriveSchema($data); echo "✓ Schema derived successfully\n"; echo " Fields: " . json_encode($schema->toArray()) . "\n"; echo " Field count: " . $schema->getFieldCount() . "\n"; // Test 2: Valid State Validation echo "\nTest 2: Valid State Validation\n"; echo "-------------------------------\n"; $newData = ComponentData::fromArray([ 'count' => 5, 'items' => ['c', 'd', 'e'], 'user' => $userClass, // Same user class instance 'metadata' => null, ]); try { $validator->validate($newData, $schema); echo "✓ Valid state passed validation\n"; } catch (StateValidationException $e) { echo "✗ Unexpected validation error: " . $e->getMessage() . "\n"; exit(1); } // Test 3: Type Mismatch Detection echo "\nTest 3: Type Mismatch Detection\n"; echo "--------------------------------\n"; $invalidData = ComponentData::fromArray([ 'count' => 'five', // String instead of int 'items' => ['a', 'b'], 'user' => $userClass, 'metadata' => null, ]); try { $validator->validate($invalidData, $schema); echo "✗ Should have thrown StateValidationException!\n"; exit(1); } catch (StateValidationException $e) { echo "✓ Correctly detected type mismatch\n"; echo " Error: " . $e->getUserMessage() . "\n"; echo " Field: " . ($e->getField() ?? 'N/A') . "\n"; } // Test 4: Missing Required Field echo "\nTest 4: Missing Required Field\n"; echo "-------------------------------\n"; $incompleteData = ComponentData::fromArray([ 'count' => 10, // 'items' missing 'user' => $userClass, 'metadata' => null, ]); try { $validator->validate($incompleteData, $schema); echo "✗ Should have thrown StateValidationException!\n"; exit(1); } catch (StateValidationException $e) { echo "✓ Correctly detected missing field\n"; echo " Error: " . $e->getUserMessage() . "\n"; echo " Field: " . ($e->getField() ?? 'N/A') . "\n"; } // Test 5: Unexpected Field echo "\nTest 5: Unexpected Field\n"; echo "------------------------\n"; $extraFieldData = ComponentData::fromArray([ 'count' => 0, 'items' => ['a', 'b'], 'user' => $userClass, 'metadata' => null, 'extra_field' => 'unexpected', // Not in original schema ]); try { $validator->validate($extraFieldData, $schema); echo "✗ Should have thrown StateValidationException!\n"; exit(1); } catch (StateValidationException $e) { echo "✓ Correctly detected unexpected field\n"; echo " Error: " . $e->getUserMessage() . "\n"; echo " Field: " . ($e->getField() ?? 'N/A') . "\n"; } // Test 6: SchemaCache Functionality echo "\nTest 6: SchemaCache Functionality\n"; echo "----------------------------------\n"; $componentClass = 'App\\Test\\TestComponent'; echo " Checking cache (should be empty): " . ($schemaCache->has($componentClass) ? 'cached' : 'not cached') . "\n"; $schemaCache->set($componentClass, $schema); echo " After set: " . ($schemaCache->has($componentClass) ? 'cached' : 'not cached') . "\n"; $cachedSchema = $schemaCache->get($componentClass); if ($cachedSchema !== null && $cachedSchema->toArray() === $schema->toArray()) { echo "✓ SchemaCache correctly stores and retrieves schemas\n"; } else { echo "✗ SchemaCache retrieval failed\n"; exit(1); } $stats = $schemaCache->getStats(); echo " Cache stats: " . $stats['cached_count'] . " schema(s) cached\n"; $schemaCache->clear($componentClass); echo " After clear: " . ($schemaCache->has($componentClass) ? 'cached' : 'not cached') . "\n"; // Test 7: DerivedSchema Helper Methods echo "\nTest 7: DerivedSchema Helper Methods\n"; echo "-------------------------------------\n"; echo " Has 'count' field: " . ($schema->hasField('count') ? 'yes' : 'no') . "\n"; echo " Has 'nonexistent' field: " . ($schema->hasField('nonexistent') ? 'yes' : 'no') . "\n"; echo " Type of 'count': " . ($schema->getType('count') ?? 'N/A') . "\n"; echo " Is 'metadata' nullable: " . ($schema->isNullable('metadata') ? 'yes' : 'no') . "\n"; echo " Is 'count' nullable: " . ($schema->isNullable('count') ? 'yes' : 'no') . "\n"; echo " All fields: " . json_encode($schema->getFields()) . "\n"; echo "✓ DerivedSchema helper methods work correctly\n"; // Test 8: ValidationResult for non-throwing checks echo "\nTest 8: ValidationResult for Non-Throwing Checks\n"; echo "-------------------------------------------------\n"; $result = $validator->check($newData, $schema); if ($result->isValid()) { echo "✓ Valid data check returns valid result\n"; echo " Error count: " . $result->getErrorCount() . "\n"; } else { echo "✗ Valid data should pass check\n"; exit(1); } $result = $validator->check($invalidData, $schema); if ($result->isFailed()) { echo "✓ Invalid data check returns failed result\n"; echo " Error count: " . $result->getErrorCount() . "\n"; echo " Errors: " . json_encode($result->getErrors()) . "\n"; echo " Field errors: " . json_encode($result->getFieldErrors()) . "\n"; } else { echo "✗ Invalid data should fail check\n"; exit(1); } echo "\n=== All Tests Passed! ===\n"; echo "\nSummary:\n"; echo " ✓ Schema derivation from component data\n"; echo " ✓ Valid state passes validation\n"; echo " ✓ Type mismatch detection\n"; echo " ✓ Missing field detection\n"; echo " ✓ Unexpected field detection\n"; echo " ✓ SchemaCache stores and retrieves schemas\n"; echo " ✓ DerivedSchema helper methods\n"; echo " ✓ ValidationResult for non-throwing checks\n"; echo "\nState Validation Implementation: COMPLETE\n";