diff --git a/README.md b/README.md index e160b3b02..76341197e 100755 --- a/README.md +++ b/README.md @@ -145,6 +145,7 @@ Please select according to languages: - [ ] Support publishing stream by WebRTC. - [ ] Support change user to run SRS, [#1111][bug #1111]. - [ ] Support HLS variant, [#463][bug #463]. +- [ ] Support playing stream by WebRTC. > Remark: About the milestone and product plan, please read ([CN][v1_CN_Product], [EN][v1_EN_Product]) wiki. @@ -153,6 +154,8 @@ Please select according to languages: ### V3 changes +* v3.0, 2019-10-13, Use http://ossrs.net:8000 as homepage. +* v3.0, 2019-10-10, Cover AMF0 codec. 3.0.61 * v3.0, 2019-10-07, [3.0 alpha1(3.0.60)][r3.0a1] released. 107962 lines. * v3.0, 2019-10-06, Support log rotate by init.d command. 3.0.60 * v3.0, 2019-10-06, We prefer ipv4, only use ipv6 if ipv4 is disabled. 3.0.59 @@ -170,7 +173,7 @@ Please select according to languages: * v3.0, 2019-04-06, Merge [#1304][bug #1304], Fix ST coroutine pull error. 3.0.47 * v3.0, 2019-04-05, Merge [#1339][bug #1339], Support HTTP-FLV params. 3.0.46 * v3.0, 2018-11-11, Merge [#1261][bug #1261], Support `_definst_` for Wowza. 3.0.44 -* v3.0, 2018-08-26, SRS [console](https://github.com/ossrs/srs-ngb) support both [Chinese](http://182.92.80.26:1985/console/ng_index.html) and [English](http://182.92.80.26:1985/console/en_index.html). +* v3.0, 2018-08-26, SRS [console](https://github.com/ossrs/srs-ngb) support both [Chinese](http://ossrs.net:1985/console/ng_index.html) and [English](http://ossrs.net:1985/console/en_index.html). * v3.0, 2018-08-25, Fix [#1093][bug #1093], Support HLS encryption. 3.0.42 * v3.0, 2018-08-25, Fix [#1051][bug #1051], Drop ts when republishing stream. 3.0.41 * v3.0, 2018-08-12, For [#1202][bug #1202], Support edge/forward to Aliyun CDN. 3.0.40 @@ -515,7 +518,7 @@ Please select according to languages: * v1.0, 2014-05-27, fix [#84][bug #84], unpublish when edge disconnect. 0.9.119 * v1.0, 2014-05-27, fix [#89][bug #89], config to /dev/null to disable ffmpeg log. 0.9.117 * v1.0, 2014-05-25, fix [#76][bug #76], allow edge vhost to add or remove. 0.9.114 -* v1.0, 2014-05-24, Johnny contribute [ossrs.net](http://182.92.80.26). karthikeyan start to translate wiki to English. +* v1.0, 2014-05-24, Johnny contribute [ossrs.net](http://ossrs.net:8000). karthikeyan start to translate wiki to English. * v1.0, 2014-05-22, fix [#78][bug #78], st joinable thread must be stop by other threads, 0.9.113 * v1.0, 2014-05-22, support amf0 StrictArray(0x0a). 0.9.111. * v1.0, 2014-05-22, support flv parser, add amf0 to librtmp. 0.9.110 @@ -1066,8 +1069,8 @@ Winlin [srs-ngb]: https://github.com/ossrs/srs-ngb [srs-librtmp]: https://github.com/ossrs/srs-librtmp [gitlab]: https://gitlab.com/winlinvip/srs-gitlab -[console]: http://182.92.80.26:1985/console -[player]: http://182.92.80.26/players/srs_player.html +[console]: http://ossrs.net:1985/console +[player]: http://ossrs.net:8000/players/srs_player.html [modules]: https://github.com/ossrs/srs/blob/develop/trunk/modules/readme.txt [docker]: https://github.com/ossrs/srs-docker/tree/centos#usage @@ -1114,8 +1117,8 @@ Winlin [v3_CN_Home]: https://github.com/ossrs/srs/wiki/v3_CN_Home [v3_EN_Home]: https://github.com/ossrs/srs/wiki/v3_EN_Home [donation0]: http://winlinvip.github.io/srs.release/donation/index.html -[donation1]: http://182.92.80.26/srs.release/donation/index.html -[donation2]: http://182.92.80.26/srs.release/donation/paypal.html +[donation1]: http://ossrs.net:8000/srs.release/donation/index.html +[donation2]: http://ossrs.net:8000/srs.release/donation/paypal.html [donations]: https://github.com/ossrs/srs/blob/develop/DONATIONS.txt [v1_CN_Compare]: https://github.com/ossrs/srs/wiki/v1_CN_Compare @@ -1536,7 +1539,7 @@ Winlin [contact]: https://github.com/ossrs/srs/wiki/v1_CN_Contact [more0]: http://winlinvip.github.io/srs.release/releases/ -[more1]: http://182.92.80.26/srs.release/releases/ +[more1]: http://ossrs.net:8000/srs.release/releases/ [LICENSE]: https://github.com/ossrs/srs/blob/develop/LICENSE [LicenseMixing]: https://github.com/ossrs/srs/wiki/LicenseMixing @@ -1548,5 +1551,5 @@ Winlin [release2]: https://github.com/ossrs/srs/wiki/v1_CN_Product#release20 [release3]: https://github.com/ossrs/srs/wiki/v1_CN_Product#release30 [centos0]: http://winlinvip.github.io/srs.release/releases/files/SRS-CentOS6-x86_64-3.0.56.zip -[centos1]: http://182.92.80.26/srs.release/releases/files/SRS-CentOS6-x86_64-3.0.56.zip +[centos1]: http://ossrs.net:8000/srs.release/releases/files/SRS-CentOS6-x86_64-3.0.56.zip diff --git a/trunk/src/protocol/srs_protocol_amf0.cpp b/trunk/src/protocol/srs_protocol_amf0.cpp index 2a65a8274..a1449e6be 100644 --- a/trunk/src/protocol/srs_protocol_amf0.cpp +++ b/trunk/src/protocol/srs_protocol_amf0.cpp @@ -216,6 +216,8 @@ void srs_amf0_do_print(SrsAmf0Any* any, stringstream& ss, int level) << "/" << std::hex << any->to_date_time_zone() << endl; } else if (any->is_null()) { ss << "Null" << endl; + } else if (any->is_undefined()) { + ss << "Undefined" << endl; } else if (any->is_ecma_array()) { SrsAmf0EcmaArray* obj = any->to_ecma_array(); ss << "EcmaArray " << "(" << obj->count() << " items)" << endl; @@ -1781,24 +1783,8 @@ namespace _srs_internal srs_error_t srs_amf0_write_object_eof(SrsBuffer* stream, SrsAmf0ObjectEOF* value) { - srs_error_t err = srs_success; - srs_assert(value != NULL); - - // value - if (!stream->require(2)) { - return srs_error_new(ERROR_RTMP_AMF0_ENCODE, "requires 2 only %d bytes", stream->left()); - } - stream->write_2bytes(0x00); - - // marker - if (!stream->require(1)) { - return srs_error_new(ERROR_RTMP_AMF0_ENCODE, "requires 1 only %d bytes", stream->left()); - } - - stream->write_1bytes(RTMP_AMF0_ObjectEnd); - - return err; + return value->write(stream); } srs_error_t srs_amf0_write_any(SrsBuffer* stream, SrsAmf0Any* value) diff --git a/trunk/src/utest/srs_utest.cpp b/trunk/src/utest/srs_utest.cpp index 03ec996bc..6e1fda1f2 100644 --- a/trunk/src/utest/srs_utest.cpp +++ b/trunk/src/utest/srs_utest.cpp @@ -29,6 +29,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include +using namespace std; + // Temporary disk config. std::string _srs_tmp_file_prefix = "/tmp/srs-utest-"; // Temporary network config. diff --git a/trunk/src/utest/srs_utest_amf0.cpp b/trunk/src/utest/srs_utest_amf0.cpp index 8f446e3ab..5f6efbf6e 100644 --- a/trunk/src/utest/srs_utest_amf0.cpp +++ b/trunk/src/utest/srs_utest_amf0.cpp @@ -22,14 +22,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include -#ifdef ENABLE_UTEST_AMF0 - #include using namespace std; #include #include #include +#include +#include +#include +#include +using namespace _srs_internal; /** * main scenario to use amf0. @@ -1264,5 +1267,1229 @@ VOID TEST(ProtocolAMF0Test, ObjectEcmaStrict) EXPECT_EQ(0, arr3->to_ecma_array()->count()); } -#endif +VOID TEST(ProtocolAMF0Test, InterfacesString) +{ + srs_error_t err; + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::str("hello"); + SrsAutoFree(SrsAmf0Any, p); + + EXPECT_TRUE(p->is_string()); + EXPECT_FALSE(p->is_boolean()); + EXPECT_FALSE(p->is_number()); + EXPECT_FALSE(p->is_null()); + EXPECT_FALSE(p->is_undefined()); + EXPECT_FALSE(p->is_object()); + EXPECT_FALSE(p->is_object_eof()); + EXPECT_FALSE(p->is_ecma_array()); + EXPECT_FALSE(p->is_strict_array()); + EXPECT_FALSE(p->is_date()); + EXPECT_FALSE(p->is_complex_object()); + EXPECT_TRUE(string("hello") == p->to_str()); + EXPECT_STREQ("hello", p->to_str_raw()); + + char* d = p->human_print(NULL, NULL); + EXPECT_STREQ("String hello\n", d); + delete[] d; + + SrsJsonAny* j = p->to_json(); + EXPECT_TRUE(j->is_string()); + EXPECT_TRUE(string("hello") == j->to_str()); + srs_freep(j); + + // For marshal and unmarshal. + char* bb = new char[p->total_size()]; + SrsAutoFreeA(char, bb); + SrsBuffer b(bb, p->total_size()); + HELPER_EXPECT_SUCCESS(p->write(&b)); + + b.skip(-1 * b.pos()); + SrsAmf0Any* pp = NULL; + SrsAutoFree(SrsAmf0Any, pp); + HELPER_EXPECT_SUCCESS(SrsAmf0Any::discovery(&b, &pp)); + + b.skip(-1 * b.pos()); + HELPER_EXPECT_SUCCESS(pp->read(&b)); + EXPECT_TRUE(string("hello") == pp->to_str()); + + // For copy. + SrsAmf0Any* cp = p->copy(); + EXPECT_TRUE(string("hello") == cp->to_str()); + } + + if (true) { + SrsBuffer b; + SrsAmf0Any* o = SrsAmf0Any::str(); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Any* o = SrsAmf0Any::str(); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00, 0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Any* o = SrsAmf0Any::str(); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00, 0x00, 0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Any* o = SrsAmf0Any::str(); + HELPER_EXPECT_SUCCESS(o->write(&b)); + srs_freep(o); + } + + if (true) { + SrsBuffer b; + SrsAmf0Any* o = SrsAmf0Any::str(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Any* o = SrsAmf0Any::str(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x02}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Any* o = SrsAmf0Any::str(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x02, 0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Any* o = SrsAmf0Any::str(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x02, 0x00, 0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Any* o = SrsAmf0Any::str(); + HELPER_EXPECT_SUCCESS(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x02, 0x00, 0x01}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Any* o = SrsAmf0Any::str(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } +} + +VOID TEST(ProtocolAMF0Test, InterfacesBoolean) +{ + srs_error_t err; + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::boolean(); + SrsAutoFree(SrsAmf0Any, p); + + EXPECT_FALSE(p->is_string()); + EXPECT_TRUE(p->is_boolean()); + EXPECT_FALSE(p->is_number()); + EXPECT_FALSE(p->is_null()); + EXPECT_FALSE(p->is_undefined()); + EXPECT_FALSE(p->is_object()); + EXPECT_FALSE(p->is_object_eof()); + EXPECT_FALSE(p->is_ecma_array()); + EXPECT_FALSE(p->is_strict_array()); + EXPECT_FALSE(p->is_date()); + EXPECT_FALSE(p->is_complex_object()); + EXPECT_FALSE(p->to_boolean()); + + char* d = p->human_print(NULL, NULL); + EXPECT_STREQ("Boolean false\n", d); + delete[] d; + + SrsJsonAny* j = p->to_json(); + EXPECT_TRUE(j->is_boolean()); + EXPECT_FALSE(j->to_boolean()); + srs_freep(j); + + // For marshal and unmarshal. + char* bb = new char[p->total_size()]; + SrsAutoFreeA(char, bb); + SrsBuffer b(bb, p->total_size()); + HELPER_EXPECT_SUCCESS(p->write(&b)); + + b.skip(-1 * b.pos()); + SrsAmf0Any* pp = NULL; + SrsAutoFree(SrsAmf0Any, pp); + HELPER_EXPECT_SUCCESS(SrsAmf0Any::discovery(&b, &pp)); + + b.skip(-1 * b.pos()); + HELPER_EXPECT_SUCCESS(pp->read(&b)); + EXPECT_FALSE(p->to_boolean()); + + // For copy. + SrsAmf0Any* cp = p->copy(); + EXPECT_FALSE(cp->to_boolean()); + } + + if (true) { + SrsBuffer b; + SrsAmf0Any* o = SrsAmf0Any::boolean(); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x01}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Any* o = SrsAmf0Any::boolean(); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + SrsBuffer b; + SrsAmf0Any* o = SrsAmf0Any::boolean(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x01}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Any* o = SrsAmf0Any::boolean(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Any* o = SrsAmf0Any::boolean(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } +} + +VOID TEST(ProtocolAMF0Test, InterfacesNumber) +{ + srs_error_t err; + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::number(); + SrsAutoFree(SrsAmf0Any, p); + + EXPECT_FALSE(p->is_string()); + EXPECT_FALSE(p->is_boolean()); + EXPECT_FALSE(!p->is_number()); + EXPECT_FALSE(p->is_null()); + EXPECT_FALSE(p->is_undefined()); + EXPECT_FALSE(p->is_object()); + EXPECT_FALSE(p->is_object_eof()); + EXPECT_FALSE(p->is_ecma_array()); + EXPECT_FALSE(p->is_strict_array()); + EXPECT_FALSE(p->is_date()); + EXPECT_FALSE(p->is_complex_object()); + EXPECT_TRUE(0.0 == p->to_number()); + + char* d = p->human_print(NULL, NULL); + EXPECT_STREQ("Number 0.0\n", d); + delete[] d; + + SrsJsonAny* j = p->to_json(); + EXPECT_TRUE(j->is_integer()); + EXPECT_TRUE(0.0 == j->to_integer()); + srs_freep(j); + + p->set_number(100.1); + EXPECT_TRUE(100.1 == p->to_number()); + + j = p->to_json(); + EXPECT_TRUE(j->is_number()); + EXPECT_TRUE(100.1 == j->to_number()); + srs_freep(j); + + // For marshal and unmarshal. + char* bb = new char[p->total_size()]; + SrsAutoFreeA(char, bb); + SrsBuffer b(bb, p->total_size()); + HELPER_EXPECT_SUCCESS(p->write(&b)); + + b.skip(-1 * b.pos()); + SrsAmf0Any* pp = NULL; + SrsAutoFree(SrsAmf0Any, pp); + HELPER_EXPECT_SUCCESS(SrsAmf0Any::discovery(&b, &pp)); + + b.skip(-1 * b.pos()); + HELPER_EXPECT_SUCCESS(pp->read(&b)); + EXPECT_TRUE(100.1 == p->to_number()); + + // For copy. + SrsAmf0Any* cp = p->copy(); + EXPECT_TRUE(100.1 == cp->to_number()); + } + + if (true) { + SrsBuffer b; + SrsAmf0Any* o = SrsAmf0Any::number(); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x01}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Any* o = SrsAmf0Any::number(); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + SrsBuffer b; + SrsAmf0Any* o = SrsAmf0Any::number(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Any* o = SrsAmf0Any::number(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x01}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Any* o = SrsAmf0Any::number(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } +} + +VOID TEST(ProtocolAMF0Test, InterfacesDate) +{ + srs_error_t err; + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::date(); + SrsAutoFree(SrsAmf0Any, p); + + EXPECT_FALSE(p->is_string()); + EXPECT_FALSE(p->is_boolean()); + EXPECT_FALSE(p->is_number()); + EXPECT_FALSE(p->is_null()); + EXPECT_FALSE(p->is_undefined()); + EXPECT_FALSE(p->is_object()); + EXPECT_FALSE(p->is_object_eof()); + EXPECT_FALSE(p->is_ecma_array()); + EXPECT_FALSE(p->is_strict_array()); + EXPECT_FALSE(!p->is_date()); + EXPECT_FALSE(p->is_complex_object()); + EXPECT_TRUE(0 == p->to_date()); + EXPECT_TRUE(0 == p->to_date_time_zone()); + + char* d = p->human_print(NULL, NULL); + EXPECT_STREQ("Date 0/0\n", d); + delete[] d; + + // For marshal and unmarshal. + char* bb = new char[p->total_size()]; + SrsAutoFreeA(char, bb); + SrsBuffer b(bb, p->total_size()); + HELPER_EXPECT_SUCCESS(p->write(&b)); + + b.skip(-1 * b.pos()); + SrsAmf0Any* pp = NULL; + SrsAutoFree(SrsAmf0Any, pp); + HELPER_EXPECT_SUCCESS(SrsAmf0Any::discovery(&b, &pp)); + + b.skip(-1 * b.pos()); + HELPER_EXPECT_SUCCESS(pp->read(&b)); + } +} + +VOID TEST(ProtocolAMF0Test, InterfacesNull) +{ + srs_error_t err; + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::null(); + SrsAutoFree(SrsAmf0Any, p); + + EXPECT_FALSE(p->is_string()); + EXPECT_FALSE(p->is_boolean()); + EXPECT_FALSE(p->is_number()); + EXPECT_FALSE(!p->is_null()); + EXPECT_FALSE(p->is_undefined()); + EXPECT_FALSE(p->is_object()); + EXPECT_FALSE(p->is_object_eof()); + EXPECT_FALSE(p->is_ecma_array()); + EXPECT_FALSE(p->is_strict_array()); + EXPECT_FALSE(p->is_date()); + EXPECT_FALSE(p->is_complex_object()); + + char* d = p->human_print(NULL, NULL); + EXPECT_STREQ("Null\n", d); + delete[] d; + + SrsJsonAny* j = p->to_json(); + EXPECT_TRUE(j->is_null()); + srs_freep(j); + + // For marshal and unmarshal. + char* bb = new char[p->total_size()]; + SrsAutoFreeA(char, bb); + SrsBuffer b(bb, p->total_size()); + HELPER_EXPECT_SUCCESS(p->write(&b)); + + b.skip(-1 * b.pos()); + SrsAmf0Any* pp = NULL; + SrsAutoFree(SrsAmf0Any, pp); + HELPER_EXPECT_SUCCESS(SrsAmf0Any::discovery(&b, &pp)); + + b.skip(-1 * b.pos()); + HELPER_EXPECT_SUCCESS(pp->read(&b)); + } + + if (true) { + SrsBuffer b; + SrsAmf0Any* o = SrsAmf0Any::null(); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + SrsBuffer b; + SrsAmf0Any* o = SrsAmf0Any::null(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Any* o = SrsAmf0Any::null(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } +} + +VOID TEST(ProtocolAMF0Test, InterfacesUndefined) +{ + srs_error_t err; + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::undefined(); + SrsAutoFree(SrsAmf0Any, p); + + EXPECT_FALSE(p->is_string()); + EXPECT_FALSE(p->is_boolean()); + EXPECT_FALSE(p->is_number()); + EXPECT_FALSE(p->is_null()); + EXPECT_FALSE(!p->is_undefined()); + EXPECT_FALSE(p->is_object()); + EXPECT_FALSE(p->is_object_eof()); + EXPECT_FALSE(p->is_ecma_array()); + EXPECT_FALSE(p->is_strict_array()); + EXPECT_FALSE(p->is_date()); + EXPECT_FALSE(p->is_complex_object()); + + char* d = p->human_print(NULL, NULL); + EXPECT_STREQ("Undefined\n", d); + delete[] d; + + SrsJsonAny* j = p->to_json(); + EXPECT_TRUE(j->is_null()); + srs_freep(j); + + // For marshal and unmarshal. + char* bb = new char[p->total_size()]; + SrsAutoFreeA(char, bb); + SrsBuffer b(bb, p->total_size()); + HELPER_EXPECT_SUCCESS(p->write(&b)); + + b.skip(-1 * b.pos()); + SrsAmf0Any* pp = NULL; + SrsAutoFree(SrsAmf0Any, pp); + HELPER_EXPECT_SUCCESS(SrsAmf0Any::discovery(&b, &pp)); + + b.skip(-1 * b.pos()); + HELPER_EXPECT_SUCCESS(pp->read(&b)); + } + + if (true) { + SrsBuffer b; + SrsAmf0Any* o = SrsAmf0Any::undefined(); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + SrsBuffer b; + SrsAmf0Any* o = SrsAmf0Any::undefined(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Any* o = SrsAmf0Any::undefined(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } +} + +VOID TEST(ProtocolAMF0Test, InterfacesObject) +{ + srs_error_t err; + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Any, p); + + EXPECT_FALSE(p->is_string()); + EXPECT_FALSE(p->is_boolean()); + EXPECT_FALSE(p->is_number()); + EXPECT_FALSE(p->is_null()); + EXPECT_FALSE(p->is_undefined()); + EXPECT_FALSE(!p->is_object()); + EXPECT_FALSE(p->is_object_eof()); + EXPECT_FALSE(p->is_ecma_array()); + EXPECT_FALSE(p->is_strict_array()); + EXPECT_FALSE(p->is_date()); + EXPECT_FALSE(!p->is_complex_object()); + EXPECT_TRUE(NULL != p->to_object()); + + char* d = p->human_print(NULL, NULL); + EXPECT_STREQ("Object (0 items)\n", d); + delete[] d; + + SrsJsonAny* j = p->to_json(); + EXPECT_TRUE(j->is_object()); + srs_freep(j); + + // For marshal and unmarshal. + char* bb = new char[p->total_size()]; + SrsAutoFreeA(char, bb); + SrsBuffer b(bb, p->total_size()); + HELPER_EXPECT_SUCCESS(p->write(&b)); + + b.skip(-1 * b.pos()); + SrsAmf0Any* pp = NULL; + SrsAutoFree(SrsAmf0Any, pp); + HELPER_EXPECT_SUCCESS(SrsAmf0Any::discovery(&b, &pp)); + + b.skip(-1 * b.pos()); + HELPER_EXPECT_SUCCESS(pp->read(&b)); + EXPECT_TRUE(NULL != pp->to_object()); + + // For copy. + SrsAmf0Any* cp = p->copy(); + EXPECT_TRUE(NULL != cp->to_object()); + } + + if (true) { + SrsBuffer b; + SrsAmf0Object* o = SrsAmf0Any::object(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + SrsBuffer b; + SrsAmf0Object* o = SrsAmf0Any::object(); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x01}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Object* o = SrsAmf0Any::object(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Object* o = SrsAmf0Any::object(); + o->set("id", SrsAmf0Any::number(3.0)); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x03, 0x00, 0x01}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Object* o = SrsAmf0Any::object(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00, 0x00, 0x02, 'i', 'd', 0x02, 0x00, 0x03}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Object* o = SrsAmf0Any::object(); + o->set("id", SrsAmf0Any::str("srs")); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x03, 0x00, 0x01, 'a'}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Object* o = SrsAmf0Any::object(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00, 0x00, 0x02, 'i', 'd', 0x02, 0x00, 0x03, 's', 'r', 's'}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0Object* o = SrsAmf0Any::object(); + o->set("id", SrsAmf0Any::str("srs")); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } +} + +VOID TEST(ProtocolAMF0Test, InterfacesObject2) +{ + if (true) { + SrsAmf0Any* p = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Any, p); + + SrsAmf0Object* o = p->to_object(); + EXPECT_TRUE(NULL != o); + + o->set("version", SrsAmf0Any::number(3.0)); + o->set("name", SrsAmf0Any::str("srs")); + EXPECT_STREQ("version", o->key_raw_at(0)); + + SrsAmf0Any* prop = o->get_property("version"); + EXPECT_TRUE(prop->is_number()); + EXPECT_TRUE(3.0 == prop->to_number()); + + prop = o->ensure_property_number("version"); + EXPECT_TRUE(NULL != prop); + + prop = o->ensure_property_string("name"); + EXPECT_TRUE(NULL != prop); + + o->remove("version"); + EXPECT_TRUE(NULL == o->get_property("version")); + + char* s = p->human_print(NULL, NULL); + EXPECT_TRUE(s != NULL); + srs_freepa(s); + + SrsJsonAny* j = o->to_json(); + EXPECT_TRUE(j != NULL); + srs_freep(j); + } + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::strict_array(); + SrsAutoFree(SrsAmf0Any, p); + + SrsAmf0StrictArray* o = p->to_strict_array(); + EXPECT_TRUE(NULL != o); + + o->append(SrsAmf0Any::number(3.0)); + o->append(SrsAmf0Any::str("srs")); + + SrsAmf0Any* prop = o->at(0); + EXPECT_TRUE(prop->is_number()); + EXPECT_TRUE(3.0 == prop->to_number()); + + prop = o->at(0); + EXPECT_TRUE(NULL != prop); + + prop = o->at(1); + EXPECT_TRUE(NULL != prop); + + char* s = p->human_print(NULL, NULL); + EXPECT_TRUE(s != NULL); + srs_freepa(s); + } + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::ecma_array(); + SrsAutoFree(SrsAmf0Any, p); + + SrsAmf0EcmaArray* o = p->to_ecma_array(); + EXPECT_TRUE(NULL != o); + + o->set("version", SrsAmf0Any::number(3.0)); + o->set("name", SrsAmf0Any::str("srs")); + + EXPECT_TRUE(string("version") == o->key_at(0)); + EXPECT_STREQ("version", o->key_raw_at(0)); + EXPECT_TRUE(string("name") == o->key_at(1)); + + SrsAmf0Any* prop = o->get_property("version"); + EXPECT_TRUE(prop->is_number()); + EXPECT_TRUE(3.0 == prop->to_number()); + + prop = o->ensure_property_number("version"); + EXPECT_TRUE(NULL != prop); + + prop = o->ensure_property_string("name"); + EXPECT_TRUE(NULL != prop); + + prop = o->value_at(1); + EXPECT_TRUE(NULL != prop); + EXPECT_TRUE(prop->is_string()); + + char* s = p->human_print(NULL, NULL); + EXPECT_TRUE(s != NULL); + srs_freepa(s); + } +} + +VOID TEST(ProtocolAMF0Test, InterfacesObjectEOF) +{ + srs_error_t err; + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::object_eof(); + SrsAutoFree(SrsAmf0Any, p); + + EXPECT_FALSE(p->is_string()); + EXPECT_FALSE(p->is_boolean()); + EXPECT_FALSE(p->is_number()); + EXPECT_FALSE(p->is_null()); + EXPECT_FALSE(p->is_undefined()); + EXPECT_FALSE(p->is_object()); + EXPECT_FALSE(!p->is_object_eof()); + EXPECT_FALSE(p->is_ecma_array()); + EXPECT_FALSE(p->is_strict_array()); + EXPECT_FALSE(p->is_date()); + EXPECT_FALSE(!p->is_complex_object()); + + SrsJsonAny* j = p->to_json(); + EXPECT_TRUE(j->is_null()); + srs_freep(j); + + // For marshal and unmarshal. + char* bb = new char[p->total_size()]; + SrsAutoFreeA(char, bb); + SrsBuffer b(bb, p->total_size()); + HELPER_EXPECT_SUCCESS(p->write(&b)); + + b.skip(-1 * b.pos()); + SrsAmf0Any* pp = NULL; + SrsAutoFree(SrsAmf0Any, pp); + HELPER_EXPECT_SUCCESS(SrsAmf0Any::discovery(&b, &pp)); + + b.skip(-1 * b.pos()); + HELPER_EXPECT_SUCCESS(pp->read(&b)); + + // For copy. + SrsAmf0Any* cp = p->copy(); + EXPECT_TRUE(cp->is_object_eof()); + } + + if (true) { + SrsBuffer b; + SrsAmf0ObjectEOF* o = new SrsAmf0ObjectEOF(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + SrsBuffer b; + SrsAmf0ObjectEOF* o = new SrsAmf0ObjectEOF(); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00, 0x01}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0ObjectEOF* o = new SrsAmf0ObjectEOF(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00, 0x01}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0ObjectEOF* o = new SrsAmf0ObjectEOF(); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00, 0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0ObjectEOF* o = new SrsAmf0ObjectEOF(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00, 0x00, 0x01}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0ObjectEOF* o = new SrsAmf0ObjectEOF(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } +} + +VOID TEST(ProtocolAMF0Test, InterfacesEcmaArray) +{ + srs_error_t err; + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::ecma_array(); + SrsAutoFree(SrsAmf0Any, p); + + EXPECT_FALSE(p->is_string()); + EXPECT_FALSE(p->is_boolean()); + EXPECT_FALSE(p->is_number()); + EXPECT_FALSE(p->is_null()); + EXPECT_FALSE(p->is_undefined()); + EXPECT_FALSE(p->is_object()); + EXPECT_FALSE(p->is_object_eof()); + EXPECT_FALSE(!p->is_ecma_array()); + EXPECT_FALSE(p->is_strict_array()); + EXPECT_FALSE(p->is_date()); + EXPECT_FALSE(!p->is_complex_object()); + EXPECT_TRUE(NULL != p->to_ecma_array()); + + char* d = p->human_print(NULL, NULL); + EXPECT_STREQ("EcmaArray (0 items)\n", d); + delete[] d; + + // For marshal and unmarshal. + char* bb = new char[p->total_size()]; + SrsAutoFreeA(char, bb); + SrsBuffer b(bb, p->total_size()); + HELPER_EXPECT_SUCCESS(p->write(&b)); + + b.skip(-1 * b.pos()); + SrsAmf0Any* pp = NULL; + SrsAutoFree(SrsAmf0Any, pp); + HELPER_EXPECT_SUCCESS(SrsAmf0Any::discovery(&b, &pp)); + + b.skip(-1 * b.pos()); + HELPER_EXPECT_SUCCESS(pp->read(&b)); + EXPECT_TRUE(NULL != pp->to_ecma_array()); + + // For copy. + SrsAmf0Any* cp = p->copy(); + EXPECT_TRUE(NULL != cp->to_ecma_array()); + } + + if (true) { + SrsBuffer b; + SrsAmf0EcmaArray* o = SrsAmf0Any::ecma_array(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + SrsBuffer b; + SrsAmf0EcmaArray* o = SrsAmf0Any::ecma_array(); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x01}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0EcmaArray* o = SrsAmf0Any::ecma_array(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0EcmaArray* o = SrsAmf0Any::ecma_array(); + o->set("id", SrsAmf0Any::number(3.0)); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x08, 0x00, 0x00, 0x00, 0x01, 0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0EcmaArray* o = SrsAmf0Any::ecma_array(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0EcmaArray* o = SrsAmf0Any::ecma_array(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 'i', 'd', 0x02, 0x00, 0x03}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0EcmaArray* o = SrsAmf0Any::ecma_array(); + o->set("id", SrsAmf0Any::str("srs")); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x08, 0x00, 0x00, 0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0EcmaArray* o = SrsAmf0Any::ecma_array(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 'a'}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0EcmaArray* o = SrsAmf0Any::ecma_array(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 'i', 'd', 0x02, 0x00, 0x03, 's', 'r', 's'}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0EcmaArray* o = SrsAmf0Any::ecma_array(); + o->set("id", SrsAmf0Any::str("srs")); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } +} + +VOID TEST(ProtocolAMF0Test, InterfacesStrictArray) +{ + srs_error_t err; + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::strict_array(); + SrsAutoFree(SrsAmf0Any, p); + + EXPECT_FALSE(p->is_string()); + EXPECT_FALSE(p->is_boolean()); + EXPECT_FALSE(p->is_number()); + EXPECT_FALSE(p->is_null()); + EXPECT_FALSE(p->is_undefined()); + EXPECT_FALSE(p->is_object()); + EXPECT_FALSE(p->is_object_eof()); + EXPECT_FALSE(p->is_ecma_array()); + EXPECT_FALSE(!p->is_strict_array()); + EXPECT_FALSE(p->is_date()); + EXPECT_FALSE(!p->is_complex_object()); + EXPECT_TRUE(NULL != p->to_strict_array()); + + char* d = p->human_print(NULL, NULL); + EXPECT_STREQ("StrictArray (0 items)\n", d); + delete[] d; + + // For marshal and unmarshal. + char* bb = new char[p->total_size()]; + SrsAutoFreeA(char, bb); + SrsBuffer b(bb, p->total_size()); + HELPER_EXPECT_SUCCESS(p->write(&b)); + + b.skip(-1 * b.pos()); + SrsAmf0Any* pp = NULL; + SrsAutoFree(SrsAmf0Any, pp); + HELPER_EXPECT_SUCCESS(SrsAmf0Any::discovery(&b, &pp)); + + b.skip(-1 * b.pos()); + HELPER_EXPECT_SUCCESS(pp->read(&b)); + EXPECT_TRUE(NULL != pp->to_strict_array()); + + // For copy. + SrsAmf0Any* cp = p->copy(); + EXPECT_TRUE(NULL != cp->to_strict_array()); + } + + if (true) { + SrsBuffer b; + SrsAmf0StrictArray* o = SrsAmf0Any::strict_array(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + SrsBuffer b; + SrsAmf0StrictArray* o = SrsAmf0Any::strict_array(); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x01}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0StrictArray* o = SrsAmf0Any::strict_array(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0StrictArray* o = SrsAmf0Any::strict_array(); + o->append(SrsAmf0Any::str("srs")); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x0a, 0x00, 0x00, 0x00, 0x01, 0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0StrictArray* o = SrsAmf0Any::strict_array(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x0a, 0x00, 0x00, 0x00}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0StrictArray* o = SrsAmf0Any::strict_array(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x0a, 0x00, 0x00, 0x00, 0x01, 0x02}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0StrictArray* o = SrsAmf0Any::strict_array(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x03}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0StrictArray* o = SrsAmf0Any::strict_array(); + o->append(SrsAmf0Any::str("srs")); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x0a, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x02, 'a'}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0StrictArray* o = SrsAmf0Any::strict_array(); + HELPER_EXPECT_FAILED(o->read(&b)); + srs_freep(o); + } + + if (true) { + uint8_t data[] = {0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x03, 's', 'r'}; + SrsBuffer b((char*)data, sizeof(data)); + SrsAmf0StrictArray* o = SrsAmf0Any::strict_array(); + o->append(SrsAmf0Any::str("srs")); + HELPER_EXPECT_FAILED(o->write(&b)); + srs_freep(o); + } +} + +VOID TEST(ProtocolAMF0Test, InterfacesOthers) +{ + if (true) { + SrsAmf0Any* p = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Any, p); + EXPECT_FALSE(!p->is_complex_object()); + } + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::object_eof(); + SrsAutoFree(SrsAmf0Any, p); + EXPECT_FALSE(!p->is_complex_object()); + } + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::ecma_array(); + SrsAutoFree(SrsAmf0Any, p); + EXPECT_FALSE(!p->is_complex_object()); + } + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::strict_array(); + SrsAutoFree(SrsAmf0Any, p); + EXPECT_FALSE(!p->is_complex_object()); + } +} + +VOID TEST(ProtocolAMF0Test, InterfacesError) +{ + srs_error_t err; + + if (true) { + SrsBuffer b; + HELPER_EXPECT_FAILED(SrsAmf0Any::discovery(&b, NULL)); + } + + if (true) { + char data = 0x3f; + SrsBuffer b(&data, 1); + HELPER_EXPECT_FAILED(SrsAmf0Any::discovery(&b, NULL)); + } + + if (true) { + SrsAmf0Object* o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, o); + + o->set("name", SrsAmf0Any::number(3.0)); + o->set("name", SrsAmf0Any::str("srs")); + + SrsAmf0Any* prop; + prop = o->ensure_property_number("name"); + EXPECT_TRUE(prop == NULL); + + prop = o->ensure_property_string("id"); + EXPECT_TRUE(prop == NULL); + + prop = o->ensure_property_string("name"); + ASSERT_TRUE(prop != NULL); + EXPECT_STREQ("srs", prop->to_str_raw()); + } + + if (true) { + SrsAmf0Object* o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, o); + + o->set("name", SrsAmf0Any::str("srs")); + o->set("name", SrsAmf0Any::number(3.0)); + + SrsAmf0Any* prop; + prop = o->ensure_property_number("id"); + EXPECT_TRUE(prop == NULL); + + prop = o->ensure_property_string("name"); + EXPECT_TRUE(prop == NULL); + + prop = o->ensure_property_number("name"); + ASSERT_TRUE(prop != NULL); + EXPECT_TRUE(3.0 == prop->to_number()); + } + + if (true) { + SrsAmf0Object* src = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, src); + + src->set("name", SrsAmf0Any::str("srs")); + src->set("name", SrsAmf0Any::number(3.0)); + + SrsAmf0Any* cp = src->copy(); + SrsAutoFree(SrsAmf0Any, cp); + + SrsAmf0Object* o = cp->to_object(); + + SrsAmf0Any* prop; + prop = o->ensure_property_number("id"); + EXPECT_TRUE(prop == NULL); + + prop = o->ensure_property_string("name"); + EXPECT_TRUE(prop == NULL); + + prop = o->ensure_property_number("name"); + ASSERT_TRUE(prop != NULL); + EXPECT_TRUE(3.0 == prop->to_number()); + } +} + +VOID TEST(ProtocolAMF0Test, Amf0Object2) +{ + srs_error_t err; + + if (true) { + SrsAmf0Object* o = SrsAmf0Any::object(); + o->set("id", SrsAmf0Any::number(3.0)); + EXPECT_EQ(1, o->count()); + + o->clear(); + EXPECT_EQ(0, o->count()); + + srs_freep(o); + } + + if (true) { + SrsAmf0EcmaArray* o = SrsAmf0Any::ecma_array(); + o->set("id", SrsAmf0Any::number(3.0)); + EXPECT_EQ(1, o->count()); + + o->clear(); + EXPECT_EQ(0, o->count()); + + srs_freep(o); + } + + if (true) { + SrsAmf0EcmaArray* o = SrsAmf0Any::ecma_array(); + o->set("id", SrsAmf0Any::number(3.0)); + + SrsJsonAny* j = o->to_json(); + EXPECT_TRUE(j->is_object()); + + SrsJsonObject* jo = j->to_object(); + EXPECT_EQ(1, jo->count()); + + srs_freep(j); + srs_freep(o); + } + + if (true) { + SrsAmf0StrictArray* o = SrsAmf0Any::strict_array(); + o->append(SrsAmf0Any::number(3.0)); + + SrsJsonAny* j = o->to_json(); + EXPECT_TRUE(j->is_array()); + + SrsJsonArray* ja = j->to_array(); + EXPECT_EQ(1, ja->count()); + + srs_freep(j); + srs_freep(o); + } + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::null(); + SrsAmf0Any* cp = p->copy(); + EXPECT_TRUE(cp->is_null()); + srs_freep(cp); + srs_freep(p); + } + + if (true) { + SrsAmf0Any* p = SrsAmf0Any::undefined(); + SrsAmf0Any* cp = p->copy(); + EXPECT_TRUE(cp->is_undefined()); + srs_freep(cp); + srs_freep(p); + } + + if (true) { + SrsBuffer b; + SrsAmf0Any* eof = SrsAmf0Any::object_eof(); + HELPER_EXPECT_FAILED(srs_amf0_write_object_eof(&b, (SrsAmf0ObjectEOF*)eof)); + srs_freep(eof); + } +}