aboutsummaryrefslogtreecommitdiffhomepage
path: root/php/tests
diff options
context:
space:
mode:
authorGravatar Paul Yang <TeBoring@users.noreply.github.com>2017-03-08 14:31:34 -0800
committerGravatar GitHub <noreply@github.com>2017-03-08 14:31:34 -0800
commitdd8d5f57d7068080283c2c03af01d806efbe6cf4 (patch)
treecbb2cb26804889ddfe61094044faaa6be4a47a12 /php/tests
parent2b7430d96aeff2bb624c8d52182ff5e4b9f7f18a (diff)
Rename encode/decode to serializeToString/mergeFromString (#2795)
This better shows the semantic of the API. For already setted fields, mergeFromString do replacement for singular fields and appending for repeated fields.
Diffstat (limited to 'php/tests')
-rw-r--r--php/tests/encode_decode_test.php60
-rw-r--r--php/tests/memory_leak_test.php20
-rw-r--r--php/tests/php_implementation_test.php4
-rw-r--r--php/tests/proto/test.proto1
-rw-r--r--php/tests/test_base.php138
-rw-r--r--php/tests/test_util.php81
6 files changed, 269 insertions, 35 deletions
diff --git a/php/tests/encode_decode_test.php b/php/tests/encode_decode_test.php
index 3218aa63..b54b1239 100644
--- a/php/tests/encode_decode_test.php
+++ b/php/tests/encode_decode_test.php
@@ -21,7 +21,7 @@ class EncodeDecodeTest extends TestBase
$this->setFields($from);
$this->expectFields($from);
- $data = $from->encode();
+ $data = $from->serializeToString();
$this->assertSame(bin2hex(TestUtil::getGoldenTestMessage()),
bin2hex($data));
}
@@ -29,7 +29,7 @@ class EncodeDecodeTest extends TestBase
public function testDecode()
{
$to = new TestMessage();
- $to->decode(TestUtil::getGoldenTestMessage());
+ $to->mergeFromString(TestUtil::getGoldenTestMessage());
$this->expectFields($to);
}
@@ -40,10 +40,10 @@ class EncodeDecodeTest extends TestBase
$this->setFields($from);
$this->expectFields($from);
- $data = $from->encode();
+ $data = $from->serializeToString();
$to = new TestMessage();
- $to->decode($data);
+ $to->mergeFromString($data);
$this->expectFields($to);
}
@@ -52,10 +52,10 @@ class EncodeDecodeTest extends TestBase
$from = new TestMessage();
$this->expectEmptyFields($from);
- $data = $from->encode();
+ $data = $from->serializeToString();
$to = new TestMessage();
- $to->decode($data);
+ $to->mergeFromString($data);
$this->expectEmptyFields($to);
}
@@ -64,29 +64,29 @@ class EncodeDecodeTest extends TestBase
$m = new TestMessage();
$m->setOneofInt32(1);
- $data = $m->encode();
+ $data = $m->serializeToString();
$n = new TestMessage();
- $n->decode($data);
+ $n->mergeFromString($data);
$this->assertSame(1, $n->getOneofInt32());
$m->setOneofFloat(2.0);
- $data = $m->encode();
+ $data = $m->serializeToString();
$n = new TestMessage();
- $n->decode($data);
+ $n->mergeFromString($data);
$this->assertSame(2.0, $n->getOneofFloat());
$m->setOneofString('abc');
- $data = $m->encode();
+ $data = $m->serializeToString();
$n = new TestMessage();
- $n->decode($data);
+ $n->mergeFromString($data);
$this->assertSame('abc', $n->getOneofString());
$sub_m = new TestMessage_Sub();
$sub_m->setA(1);
$m->setOneofMessage($sub_m);
- $data = $m->encode();
+ $data = $m->serializeToString();
$n = new TestMessage();
- $n->decode($data);
+ $n->mergeFromString($data);
$this->assertSame(1, $n->getOneofMessage()->getA());
}
@@ -95,20 +95,20 @@ class EncodeDecodeTest extends TestBase
$from = new TestPackedMessage();
TestUtil::setTestPackedMessage($from);
$this->assertSame(TestUtil::getGoldenTestPackedMessage(),
- $from->encode());
+ $from->serializeToString());
}
public function testPackedDecodePacked()
{
$to = new TestPackedMessage();
- $to->decode(TestUtil::getGoldenTestPackedMessage());
+ $to->mergeFromString(TestUtil::getGoldenTestPackedMessage());
TestUtil::assertTestPackedMessage($to);
}
public function testPackedDecodeUnpacked()
{
$to = new TestPackedMessage();
- $to->decode(TestUtil::getGoldenTestUnpackedMessage());
+ $to->mergeFromString(TestUtil::getGoldenTestUnpackedMessage());
TestUtil::assertTestPackedMessage($to);
}
@@ -117,20 +117,20 @@ class EncodeDecodeTest extends TestBase
$from = new TestUnpackedMessage();
TestUtil::setTestPackedMessage($from);
$this->assertSame(TestUtil::getGoldenTestUnpackedMessage(),
- $from->encode());
+ $from->serializeToString());
}
public function testUnpackedDecodePacked()
{
$to = new TestUnpackedMessage();
- $to->decode(TestUtil::getGoldenTestPackedMessage());
+ $to->mergeFromString(TestUtil::getGoldenTestPackedMessage());
TestUtil::assertTestPackedMessage($to);
}
public function testUnpackedDecodeUnpacked()
{
$to = new TestUnpackedMessage();
- $to->decode(TestUtil::getGoldenTestUnpackedMessage());
+ $to->mergeFromString(TestUtil::getGoldenTestUnpackedMessage());
TestUtil::assertTestPackedMessage($to);
}
@@ -161,19 +161,33 @@ class EncodeDecodeTest extends TestBase
$msg = new TestMessage();
foreach ($testVals as $original => $encoded) {
$msg->setOptionalInt64($original);
- $data = $msg->encode();
+ $data = $msg->serializeToString();
$this->assertSame($encoded, bin2hex($data));
$msg->setOptionalInt64(0);
- $msg->decode($data);
+ $msg->mergeFromString($data);
$this->assertEquals($original, $msg->getOptionalInt64());
}
}
+ public function testDecodeToExistingMessage()
+ {
+ $m1 = new TestMessage();
+ $this->setFields($m1);
+ $this->expectFields($m1);
+
+ $m2 = new TestMessage();
+ $this->setFields2($m2);
+ $data = $m2->serializeToString();
+
+ $m1->mergeFromString($data);
+ $this->expectFieldsMerged($m1);
+ }
+
public function testDecodeFieldNonExist()
{
$data = hex2bin('c80501');
$m = new TestMessage();
- $m->decode($data);
+ $m->mergeFromString($data);
}
# TODO(teboring): Add test back when php implementation is ready for json
diff --git a/php/tests/memory_leak_test.php b/php/tests/memory_leak_test.php
index d4776d6f..cfcbe62e 100644
--- a/php/tests/memory_leak_test.php
+++ b/php/tests/memory_leak_test.php
@@ -22,10 +22,10 @@ $from = new TestMessage();
TestUtil::setTestMessage($from);
TestUtil::assertTestMessage($from);
-$data = $from->encode();
+$data = $from->serializeToString();
$to = new TestMessage();
-$to->decode($data);
+$to->mergeFromString($data);
TestUtil::assertTestMessage($to);
@@ -43,9 +43,9 @@ assert(1 === $m->getOneofInt32());
assert(0.0 === $m->getOneofFloat());
assert('' === $m->getOneofString());
assert(NULL === $m->getOneofMessage());
-$data = $m->encode();
+$data = $m->serializeToString();
$n = new TestMessage();
-$n->decode($data);
+$n->mergeFromString($data);
assert(1 === $n->getOneofInt32());
$m->setOneofFloat(2.0);
@@ -53,9 +53,9 @@ assert(0 === $m->getOneofInt32());
assert(2.0 === $m->getOneofFloat());
assert('' === $m->getOneofString());
assert(NULL === $m->getOneofMessage());
-$data = $m->encode();
+$data = $m->serializeToString();
$n = new TestMessage();
-$n->decode($data);
+$n->mergeFromString($data);
assert(2.0 === $n->getOneofFloat());
$m->setOneofString('abc');
@@ -63,9 +63,9 @@ assert(0 === $m->getOneofInt32());
assert(0.0 === $m->getOneofFloat());
assert('abc' === $m->getOneofString());
assert(NULL === $m->getOneofMessage());
-$data = $m->encode();
+$data = $m->serializeToString();
$n = new TestMessage();
-$n->decode($data);
+$n->mergeFromString($data);
assert('abc' === $n->getOneofString());
$sub_m = new TestMessage_Sub();
@@ -75,9 +75,9 @@ assert(0 === $m->getOneofInt32());
assert(0.0 === $m->getOneofFloat());
assert('' === $m->getOneofString());
assert(1 === $m->getOneofMessage()->getA());
-$data = $m->encode();
+$data = $m->serializeToString();
$n = new TestMessage();
-$n->decode($data);
+$n->mergeFromString($data);
assert(1 === $n->getOneofMessage()->getA());
$from = new TestMessage();
diff --git a/php/tests/php_implementation_test.php b/php/tests/php_implementation_test.php
index 00125db4..ec6b8d5a 100644
--- a/php/tests/php_implementation_test.php
+++ b/php/tests/php_implementation_test.php
@@ -290,14 +290,14 @@ class ImplementationTest extends TestBase
public function testDecode()
{
$m = new TestMessage();
- $m->decode(TestUtil::getGoldenTestMessage());
+ $m->mergeFromString(TestUtil::getGoldenTestMessage());
TestUtil::assertTestMessage($m);
}
public function testDescriptorDecode()
{
$file_desc_set = new FileDescriptorSet();
- $file_desc_set->decode(hex2bin(
+ $file_desc_set->mergeFromString(hex2bin(
"0a3b0a12746573745f696e636c7564652e70726f746f120362617222180a" .
"0b54657374496e636c75646512090a0161180120012805620670726f746f33"));
diff --git a/php/tests/proto/test.proto b/php/tests/proto/test.proto
index c971df21..e5dee0fb 100644
--- a/php/tests/proto/test.proto
+++ b/php/tests/proto/test.proto
@@ -100,6 +100,7 @@ message TestMessage {
enum TestEnum {
ZERO = 0;
ONE = 1;
+ TWO = 2;
}
message TestPackedMessage {
diff --git a/php/tests/test_base.php b/php/tests/test_base.php
index 729fea3b..67048f4c 100644
--- a/php/tests/test_base.php
+++ b/php/tests/test_base.php
@@ -12,6 +12,11 @@ class TestBase extends PHPUnit_Framework_TestCase
TestUtil::setTestMessage($m);
}
+ public function setFields2(TestMessage $m)
+ {
+ TestUtil::setTestMessage2($m);
+ }
+
public function expectFields(TestMessage $m)
{
$this->assertSame(-44, $m->getOptionalSint32());
@@ -98,6 +103,139 @@ class TestBase extends PHPUnit_Framework_TestCase
$this->assertEquals(36, $m->getMapInt32Message()[1]->GetA());
}
+ // Test message merged from setFields and setFields2.
+ public function expectFieldsMerged(TestMessage $m)
+ {
+ $this->assertSame(-144, $m->getOptionalSint32());
+ $this->assertSame(146, $m->getOptionalFixed32());
+ $this->assertSame(-146, $m->getOptionalSfixed32());
+ $this->assertSame(11.5, $m->getOptionalFloat());
+ $this->assertSame(11.6, $m->getOptionalDouble());
+ $this->assertSame(true, $m->getOptionalBool());
+ $this->assertSame('aa', $m->getOptionalString());
+ $this->assertSame('bb', $m->getOptionalBytes());
+ $this->assertSame(133, $m->getOptionalMessage()->getA());
+ if (PHP_INT_SIZE == 4) {
+ $this->assertSame('-143', $m->getOptionalInt64());
+ $this->assertSame('143', $m->getOptionalUint64());
+ $this->assertSame('-145', $m->getOptionalSint64());
+ $this->assertSame('147', $m->getOptionalFixed64());
+ $this->assertSame('-147', $m->getOptionalSfixed64());
+ } else {
+ $this->assertSame(-143, $m->getOptionalInt64());
+ $this->assertSame(143, $m->getOptionalUint64());
+ $this->assertSame(-145, $m->getOptionalSint64());
+ $this->assertSame(147, $m->getOptionalFixed64());
+ $this->assertSame(-147, $m->getOptionalSfixed64());
+ }
+
+ $this->assertEquals(-42, $m->getRepeatedInt32()[0]);
+ $this->assertEquals(42, $m->getRepeatedUint32()[0]);
+ $this->assertEquals(-43, $m->getRepeatedInt64()[0]);
+ $this->assertEquals(43, $m->getRepeatedUint64()[0]);
+ $this->assertEquals(-44, $m->getRepeatedSint32()[0]);
+ $this->assertEquals(-45, $m->getRepeatedSint64()[0]);
+ $this->assertEquals(46, $m->getRepeatedFixed32()[0]);
+ $this->assertEquals(47, $m->getRepeatedFixed64()[0]);
+ $this->assertEquals(-46, $m->getRepeatedSfixed32()[0]);
+ $this->assertEquals(-47, $m->getRepeatedSfixed64()[0]);
+ $this->assertEquals(1.5, $m->getRepeatedFloat()[0]);
+ $this->assertEquals(1.6, $m->getRepeatedDouble()[0]);
+ $this->assertEquals(true, $m->getRepeatedBool()[0]);
+ $this->assertEquals('a', $m->getRepeatedString()[0]);
+ $this->assertEquals('b', $m->getRepeatedBytes()[0]);
+ $this->assertEquals(TestEnum::ZERO, $m->getRepeatedEnum()[0]);
+ $this->assertEquals(34, $m->getRepeatedMessage()[0]->GetA());
+
+ $this->assertEquals(-52, $m->getRepeatedInt32()[1]);
+ $this->assertEquals(52, $m->getRepeatedUint32()[1]);
+ $this->assertEquals(-53, $m->getRepeatedInt64()[1]);
+ $this->assertEquals(53, $m->getRepeatedUint64()[1]);
+ $this->assertEquals(-54, $m->getRepeatedSint32()[1]);
+ $this->assertEquals(-55, $m->getRepeatedSint64()[1]);
+ $this->assertEquals(56, $m->getRepeatedFixed32()[1]);
+ $this->assertEquals(57, $m->getRepeatedFixed64()[1]);
+ $this->assertEquals(-56, $m->getRepeatedSfixed32()[1]);
+ $this->assertEquals(-57, $m->getRepeatedSfixed64()[1]);
+ $this->assertEquals(2.5, $m->getRepeatedFloat()[1]);
+ $this->assertEquals(2.6, $m->getRepeatedDouble()[1]);
+ $this->assertEquals(false, $m->getRepeatedBool()[1]);
+ $this->assertEquals('c', $m->getRepeatedString()[1]);
+ $this->assertEquals('d', $m->getRepeatedBytes()[1]);
+ $this->assertEquals(TestEnum::ONE, $m->getRepeatedEnum()[1]);
+ $this->assertEquals(35, $m->getRepeatedMessage()[1]->GetA());
+
+ $this->assertEquals(-142, $m->getRepeatedInt32()[2]);
+ $this->assertEquals(142, $m->getRepeatedUint32()[2]);
+ $this->assertEquals(-143, $m->getRepeatedInt64()[2]);
+ $this->assertEquals(143, $m->getRepeatedUint64()[2]);
+ $this->assertEquals(-144, $m->getRepeatedSint32()[2]);
+ $this->assertEquals(-145, $m->getRepeatedSint64()[2]);
+ $this->assertEquals(146, $m->getRepeatedFixed32()[2]);
+ $this->assertEquals(147, $m->getRepeatedFixed64()[2]);
+ $this->assertEquals(-146, $m->getRepeatedSfixed32()[2]);
+ $this->assertEquals(-147, $m->getRepeatedSfixed64()[2]);
+ $this->assertEquals(11.5, $m->getRepeatedFloat()[2]);
+ $this->assertEquals(11.6, $m->getRepeatedDouble()[2]);
+ $this->assertEquals(false, $m->getRepeatedBool()[2]);
+ $this->assertEquals('aa', $m->getRepeatedString()[2]);
+ $this->assertEquals('bb', $m->getRepeatedBytes()[2]);
+ $this->assertEquals(TestEnum::TWO, $m->getRepeatedEnum()[2]);
+ $this->assertEquals(134, $m->getRepeatedMessage()[2]->GetA());
+
+ if (PHP_INT_SIZE == 4) {
+ $this->assertEquals('-163', $m->getMapInt64Int64()['-63']);
+ $this->assertEquals('163', $m->getMapUint64Uint64()['63']);
+ $this->assertEquals('-165', $m->getMapSint64Sint64()['-65']);
+ $this->assertEquals('167', $m->getMapFixed64Fixed64()['67']);
+ $this->assertEquals('-169', $m->getMapSfixed64Sfixed64()['-69']);
+ } else {
+ $this->assertEquals(-163, $m->getMapInt64Int64()[-63]);
+ $this->assertEquals(163, $m->getMapUint64Uint64()[63]);
+ $this->assertEquals(-165, $m->getMapSint64Sint64()[-65]);
+ $this->assertEquals(167, $m->getMapFixed64Fixed64()[67]);
+ $this->assertEquals(-169, $m->getMapSfixed64Sfixed64()[-69]);
+ }
+ $this->assertEquals(-162, $m->getMapInt32Int32()[-62]);
+ $this->assertEquals(162, $m->getMapUint32Uint32()[62]);
+ $this->assertEquals(-164, $m->getMapSint32Sint32()[-64]);
+ $this->assertEquals(166, $m->getMapFixed32Fixed32()[66]);
+ $this->assertEquals(-168, $m->getMapSfixed32Sfixed32()[-68]);
+ $this->assertEquals(13.5, $m->getMapInt32Float()[1]);
+ $this->assertEquals(13.6, $m->getMapInt32Double()[1]);
+ $this->assertEquals(false , $m->getMapBoolBool()[true]);
+ $this->assertEquals('ee', $m->getMapStringString()['e']);
+ $this->assertEquals('ff', $m->getMapInt32Bytes()[1]);
+ $this->assertEquals(TestEnum::TWO, $m->getMapInt32Enum()[1]);
+ $this->assertEquals(136, $m->getMapInt32Message()[1]->GetA());
+
+ if (PHP_INT_SIZE == 4) {
+ $this->assertEquals('-163', $m->getMapInt64Int64()['-163']);
+ $this->assertEquals('163', $m->getMapUint64Uint64()['163']);
+ $this->assertEquals('-165', $m->getMapSint64Sint64()['-165']);
+ $this->assertEquals('167', $m->getMapFixed64Fixed64()['167']);
+ $this->assertEquals('-169', $m->getMapSfixed64Sfixed64()['-169']);
+ } else {
+ $this->assertEquals(-163, $m->getMapInt64Int64()[-163]);
+ $this->assertEquals(163, $m->getMapUint64Uint64()[163]);
+ $this->assertEquals(-165, $m->getMapSint64Sint64()[-165]);
+ $this->assertEquals(167, $m->getMapFixed64Fixed64()[167]);
+ $this->assertEquals(-169, $m->getMapSfixed64Sfixed64()[-169]);
+ }
+ $this->assertEquals(-162, $m->getMapInt32Int32()[-162]);
+ $this->assertEquals(162, $m->getMapUint32Uint32()[162]);
+ $this->assertEquals(-164, $m->getMapSint32Sint32()[-164]);
+ $this->assertEquals(166, $m->getMapFixed32Fixed32()[166]);
+ $this->assertEquals(-168, $m->getMapSfixed32Sfixed32()[-168]);
+ $this->assertEquals(13.5, $m->getMapInt32Float()[2]);
+ $this->assertEquals(13.6, $m->getMapInt32Double()[2]);
+ $this->assertEquals(false , $m->getMapBoolBool()[false]);
+ $this->assertEquals('ee', $m->getMapStringString()['ee']);
+ $this->assertEquals('ff', $m->getMapInt32Bytes()[2]);
+ $this->assertEquals(TestEnum::TWO, $m->getMapInt32Enum()[2]);
+ $this->assertEquals(136, $m->getMapInt32Message()[2]->GetA());
+ }
+
public function expectEmptyFields(TestMessage $m)
{
$this->assertSame(0, $m->getOptionalInt32());
diff --git a/php/tests/test_util.php b/php/tests/test_util.php
index b7db5c1d..9c8e34d2 100644
--- a/php/tests/test_util.php
+++ b/php/tests/test_util.php
@@ -130,6 +130,87 @@ class TestUtil
$m->getMapInt32Message()[1]->SetA(36);
}
+ public static function setTestMessage2(TestMessage $m)
+ {
+ $sub = new TestMessage_Sub();
+
+ $m->setOptionalInt32(-142);
+ $m->setOptionalInt64(-143);
+ $m->setOptionalUint32(142);
+ $m->setOptionalUint64(143);
+ $m->setOptionalSint32(-144);
+ $m->setOptionalSint64(-145);
+ $m->setOptionalFixed32(146);
+ $m->setOptionalFixed64(147);
+ $m->setOptionalSfixed32(-146);
+ $m->setOptionalSfixed64(-147);
+ $m->setOptionalFloat(11.5);
+ $m->setOptionalDouble(11.6);
+ $m->setOptionalBool(true);
+ $m->setOptionalString('aa');
+ $m->setOptionalBytes('bb');
+ $m->setOptionalEnum(TestEnum::TWO);
+ $m->setOptionalMessage($sub);
+ $m->getOptionalMessage()->SetA(133);
+
+ $m->getRepeatedInt32() []= -142;
+ $m->getRepeatedInt64() []= -143;
+ $m->getRepeatedUint32() []= 142;
+ $m->getRepeatedUint64() []= 143;
+ $m->getRepeatedSint32() []= -144;
+ $m->getRepeatedSint64() []= -145;
+ $m->getRepeatedFixed32() []= 146;
+ $m->getRepeatedFixed64() []= 147;
+ $m->getRepeatedSfixed32() []= -146;
+ $m->getRepeatedSfixed64() []= -147;
+ $m->getRepeatedFloat() []= 11.5;
+ $m->getRepeatedDouble() []= 11.6;
+ $m->getRepeatedBool() []= false;
+ $m->getRepeatedString() []= 'aa';
+ $m->getRepeatedBytes() []= 'bb';
+ $m->getRepeatedEnum() []= TestEnum::TWO;
+ $m->getRepeatedMessage() []= new TestMessage_Sub();
+ $m->getRepeatedMessage()[0]->setA(134);
+
+ $m->getMapInt32Int32()[-62] = -162;
+ $m->getMapInt64Int64()[-63] = -163;
+ $m->getMapUint32Uint32()[62] = 162;
+ $m->getMapUint64Uint64()[63] = 163;
+ $m->getMapSint32Sint32()[-64] = -164;
+ $m->getMapSint64Sint64()[-65] = -165;
+ $m->getMapFixed32Fixed32()[66] = 166;
+ $m->getMapFixed64Fixed64()[67] = 167;
+ $m->getMapSfixed32Sfixed32()[-68] = -168;
+ $m->getMapSfixed64Sfixed64()[-69] = -169;
+ $m->getMapInt32Float()[1] = 13.5;
+ $m->getMapInt32Double()[1] = 13.6;
+ $m->getMapBoolBool()[true] = false;
+ $m->getMapStringString()['e'] = 'ee';
+ $m->getMapInt32Bytes()[1] = 'ff';
+ $m->getMapInt32Enum()[1] = TestEnum::TWO;
+ $m->getMapInt32Message()[1] = new TestMessage_Sub();
+ $m->getMapInt32Message()[1]->SetA(136);
+
+ $m->getMapInt32Int32()[-162] = -162;
+ $m->getMapInt64Int64()[-163] = -163;
+ $m->getMapUint32Uint32()[162] = 162;
+ $m->getMapUint64Uint64()[163] = 163;
+ $m->getMapSint32Sint32()[-164] = -164;
+ $m->getMapSint64Sint64()[-165] = -165;
+ $m->getMapFixed32Fixed32()[166] = 166;
+ $m->getMapFixed64Fixed64()[167] = 167;
+ $m->getMapSfixed32Sfixed32()[-168] = -168;
+ $m->getMapSfixed64Sfixed64()[-169] = -169;
+ $m->getMapInt32Float()[2] = 13.5;
+ $m->getMapInt32Double()[2] = 13.6;
+ $m->getMapBoolBool()[false] = false;
+ $m->getMapStringString()['ee'] = 'ee';
+ $m->getMapInt32Bytes()[2] = 'ff';
+ $m->getMapInt32Enum()[2] = TestEnum::TWO;
+ $m->getMapInt32Message()[2] = new TestMessage_Sub();
+ $m->getMapInt32Message()[2]->SetA(136);
+ }
+
public static function assertTestMessage(TestMessage $m)
{
if (PHP_INT_SIZE == 4) {