diff --git a/README.md b/README.md
index 3c137afa0..aa31e382c 100755
--- a/README.md
+++ b/README.md
@@ -152,6 +152,7 @@ Please select according to languages:
### V3 changes
+* 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
diff --git a/trunk/src/protocol/srs_protocol_amf0.cpp b/trunk/src/protocol/srs_protocol_amf0.cpp
index 2a65a8274..556c068ad 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;
diff --git a/trunk/src/utest/srs_utest.cpp b/trunk/src/utest/srs_utest.cpp
index 03ec996bc..ad92a4c9d 100644
--- a/trunk/src/utest/srs_utest.cpp
+++ b/trunk/src/utest/srs_utest.cpp
@@ -28,6 +28,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include
#include
#include
+#include
+#include
+#include
+
+#include
+using namespace std;
// Temporary disk config.
std::string _srs_tmp_file_prefix = "/tmp/srs-utest-";
@@ -130,3 +136,284 @@ VOID TEST(SampleTest, FastSampleMacrosTest)
EXPECT_NEAR(10, 15, 5);
}
+VOID TEST(ProtocolAMF0Test, Interfaces)
+{
+ 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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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;
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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());
+ }
+}
+