Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
communication_ipc
提交
f7be6e37
C
communication_ipc
项目概览
OpenHarmony
/
communication_ipc
大约 1 年 前同步成功
通知
20
Star
3
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
communication_ipc
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
f7be6e37
编写于
12月 13, 2022
作者:
O
openharmony_ci
提交者:
Gitee
12月 13, 2022
浏览文件
操作
浏览文件
下载
差异文件
!530 分支覆盖率提升
Merge pull request !530 from dengliang/master
上级
7184cb8c
7265453c
变更
10
展开全部
隐藏空白更改
内联
并排
Showing
10 changed file
with
1960 addition
and
787 deletion
+1960
-787
ipc/native/test/unittest/common/BUILD.gn
ipc/native/test/unittest/common/BUILD.gn
+8
-4
ipc/native/test/unittest/common/databus_session_callback_unittest.cpp
...est/unittest/common/databus_session_callback_unittest.cpp
+48
-0
ipc/native/test/unittest/common/dbinder_callback_stub_unittest.cpp
...e/test/unittest/common/dbinder_callback_stub_unittest.cpp
+78
-1
ipc/native/test/unittest/common/dbinder_session_object_unittest.cpp
.../test/unittest/common/dbinder_session_object_unittest.cpp
+3
-6
ipc/native/test/unittest/common/ipc_core_unittest.cpp
ipc/native/test/unittest/common/ipc_core_unittest.cpp
+15
-776
ipc/native/test/unittest/common/ipc_file_desc_unittest.cpp
ipc/native/test/unittest/common/ipc_file_desc_unittest.cpp
+51
-0
ipc/native/test/unittest/common/ipc_object_stub_unittest.cpp
ipc/native/test/unittest/common/ipc_object_stub_unittest.cpp
+1012
-0
ipc/native/test/unittest/common/ipc_thread_pool_unittest.cpp
ipc/native/test/unittest/common/ipc_thread_pool_unittest.cpp
+154
-0
ipc/native/test/unittest/common/message_parcel_unittest.cpp
ipc/native/test/unittest/common/message_parcel_unittest.cpp
+516
-0
ipc/native/test/unittest/common/mock_iremote_invoker.h
ipc/native/test/unittest/common/mock_iremote_invoker.h
+75
-0
未找到文件。
ipc/native/test/unittest/common/BUILD.gn
浏览文件 @
f7be6e37
...
...
@@ -21,6 +21,7 @@ ohos_unittest("IPCNativeUnitTest") {
module_out_path = MODULE_OUTPUT_PATH
include_dirs = [
"//base/hiviewdfx/hitrace/interfaces/native/innerkits/include",
"//utils/system/safwk/native/include",
"//foundation/communication/ipc/ipc/native/c/rpc/include",
"//foundation/communication/ipc/ipc/native/c/ipc_adapter/include",
...
...
@@ -36,8 +37,12 @@ ohos_unittest("IPCNativeUnitTest") {
"dbinder_session_object_unittest.cpp",
"ipc_core_unittest.cpp",
"ipc_object_proxy_unittest.cpp",
"ipc_object_stub_unittest.cpp",
"ipc_process_skeleton_unittest.cpp",
"ipc_thread_pool_unittest.cpp",
"ipc_thread_skeleton_unittest.cpp",
"iremote_object_unitest.cpp",
"message_parcel_unittest.cpp",
]
configs = [
...
...
@@ -67,15 +72,14 @@ ohos_unittest("IPCFileDescOpsTest") {
include_dirs = [
"//utils/system/safwk/native/include",
"//foundation/communication/ipc/ipc/native/c/rpc/include",
"//foundation/communication/ipc/ipc/native/c/ipc_adapter/include",
"//foundation/communication/ipc/interfaces/innerkits/ipc_core/include",
"//foundation/communication/ipc/interfaces/innerkits/libdbinder/include",
"//foundation/communication/ipc/native/src/core/include",
]
sources = [
"ipc_file_desc_unittest.cpp",
"iremote_object_unitest.cpp",
]
sources = [ "ipc_file_desc_unittest.cpp" ]
configs = [
"$SUBSYSTEM_DIR:ipc_util_config",
...
...
ipc/native/test/unittest/common/databus_session_callback_unittest.cpp
浏览文件 @
f7be6e37
...
...
@@ -16,9 +16,13 @@
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#define private public
#include "databus_session_callback.h"
#include "ipc_thread_skeleton.h"
#include "ipc_types.h"
#include "iremote_object.h"
#include "mock_session_impl.h"
#undef private
using
namespace
testing
::
ext
;
using
namespace
OHOS
;
...
...
@@ -131,3 +135,47 @@ HWTEST_F(DbSessionCallbackUnitTest, OnSessionOpenedTest003, TestSize.Level1)
EXPECT_EQ
(
ret
,
SESSION_UNOPEN_ERR
);
}
/**
* @tc.name: OnSessionOpenedTest004
* @tc.desc: Verify the OnSessionOpened function
* @tc.type: FUNC
*/
HWTEST_F
(
DbSessionCallbackUnitTest
,
OnSessionOpenedTest004
,
TestSize
.
Level1
)
{
std
::
shared_ptr
<
MockSessionImpl
>
session
=
std
::
make_shared
<
MockSessionImpl
>
();
EXPECT_CALL
(
*
session
,
GetChannelId
())
.
WillRepeatedly
(
testing
::
Return
(
1
));
EXPECT_CALL
(
*
session
,
IsServerSide
())
.
WillRepeatedly
(
testing
::
Return
(
true
));
EXPECT_CALL
(
*
session
,
GetPeerPid
())
.
WillRepeatedly
(
testing
::
Return
(
PID_TEST
));
EXPECT_CALL
(
*
session
,
GetPeerUid
())
.
WillRepeatedly
(
testing
::
Return
(
UID_TEST
));
EXPECT_CALL
(
*
session
,
GetPeerDeviceId
())
.
WillRepeatedly
(
testing
::
ReturnRef
(
DEVICE_ID_TEST
));
EXPECT_CALL
(
*
session
,
GetMySessionName
())
.
WillRepeatedly
(
testing
::
ReturnRef
(
SESSION_NAME_TEST
));
EXPECT_CALL
(
*
session
,
GetPeerSessionName
())
.
WillRepeatedly
(
testing
::
ReturnRef
(
PEER_SESSION_NAME_TEST
));
IRemoteInvoker
*
invoker
=
nullptr
;
IPCThreadSkeleton
*
current
=
IPCThreadSkeleton
::
GetCurrent
();
current
->
invokers_
[
IRemoteObject
::
IF_PROT_DATABUS
]
=
invoker
;
DatabusSessionCallback
dbSessionCallback
;
int
ret
=
dbSessionCallback
.
OnSessionOpened
(
session
);
EXPECT_EQ
(
ret
,
SESSION_INVOKER_NULL_ERR
);
char
data
[]
=
"testdata"
;
ssize_t
len
=
strlen
(
data
);
dbSessionCallback
.
OnBytesReceived
(
session
,
data
,
len
);
dbSessionCallback
.
OnSessionClosed
(
session
);
}
\ No newline at end of file
ipc/native/test/unittest/common/dbinder_callback_stub_unittest.cpp
浏览文件 @
f7be6e37
...
...
@@ -28,6 +28,7 @@
#include "ipc_process_skeleton.h"
#include "dbinder_session_object.h"
#include "stub_refcount_object.h"
#include "mock_iremote_invoker.h"
#undef protected
#undef private
...
...
@@ -149,7 +150,7 @@ HWTEST_F(DBinderCallbackStubTest, ProcessProtoTest001, TestSize.Level1)
invoker
->
callerPid_
=
1
;
invoker
->
callerUid_
=
1
;
IPCThreadSkeleton
*
current
=
IPCThreadSkeleton
::
GetCurrent
();
current
->
invokers_
[
IRemoteObject
::
IF_PROT_
BINDER
]
=
invoker
;
current
->
invokers_
[
IRemoteObject
::
IF_PROT_
DATABUS
]
=
invoker
;
int32_t
ret
=
fakeStub
->
ProcessProto
(
code
,
data
,
reply
,
option
);
EXPECT_EQ
(
ret
,
BINDER_CALLBACK_AUTHCOMM_ERR
);
...
...
@@ -194,3 +195,79 @@ HWTEST_F(DBinderCallbackStubTest, OnRemoteRequestTest002, TestSize.Level1)
EXPECT_EQ
(
ret
,
DBINDER_CALLBACK_ERR
);
}
/**
* @tc.name: ProcessProtoTest002
* @tc.desc: Verify the ProcessProto function
* @tc.type: FUNC
*/
HWTEST_F
(
DBinderCallbackStubTest
,
ProcessProtoTest002
,
TestSize
.
Level1
)
{
sptr
<
DBinderCallbackStub
>
fakeStub
=
new
(
std
::
nothrow
)
DBinderCallbackStub
(
SERVICE_TEST
,
DEVICE_TEST
,
LOCALDEVICE_TEST
,
STUBINDEX_TEST
,
HANDLE_TEST
,
TOKENID_TEST
);
ASSERT_TRUE
(
fakeStub
!=
nullptr
);
uint32_t
code
=
DBINDER_DECREFS_TRANSACTION
;
MessageParcel
data
;
MessageParcel
reply
;
MessageOption
option
;
MockIRemoteInvoker
*
invoker
=
new
MockIRemoteInvoker
();
IPCThreadSkeleton
*
current
=
IPCThreadSkeleton
::
GetCurrent
();
current
->
invokers_
[
IRemoteObject
::
IF_PROT_BINDER
]
=
invoker
;
EXPECT_CALL
(
*
invoker
,
GetStatus
())
.
WillRepeatedly
(
testing
::
Return
(
IRemoteInvoker
::
ACTIVE_INVOKER
));
EXPECT_CALL
(
*
invoker
,
GetCallerPid
())
.
WillRepeatedly
(
testing
::
Return
(
-
1
));
EXPECT_CALL
(
*
invoker
,
GetCallerUid
())
.
WillRepeatedly
(
testing
::
Return
(
1114
));
EXPECT_CALL
(
*
invoker
,
SendRequest
(
testing
::
_
,
testing
::
_
,
testing
::
_
,
testing
::
_
,
testing
::
_
))
.
WillRepeatedly
(
testing
::
Return
(
1
));
int32_t
ret
=
fakeStub
->
ProcessProto
(
code
,
data
,
reply
,
option
);
EXPECT_EQ
(
ret
,
DBINDER_SERVICE_PROCESS_PROTO_ERR
);
current
->
invokers_
.
clear
();
delete
invoker
;
}
/**
* @tc.name: ProcessProtoTest003
* @tc.desc: Verify the ProcessProto function
* @tc.type: FUNC
*/
HWTEST_F
(
DBinderCallbackStubTest
,
ProcessProtoTest003
,
TestSize
.
Level1
)
{
sptr
<
DBinderCallbackStub
>
fakeStub
=
new
(
std
::
nothrow
)
DBinderCallbackStub
(
SERVICE_TEST
,
DEVICE_TEST
,
LOCALDEVICE_TEST
,
STUBINDEX_TEST
,
HANDLE_TEST
,
TOKENID_TEST
);
ASSERT_TRUE
(
fakeStub
!=
nullptr
);
uint32_t
code
=
DBINDER_DECREFS_TRANSACTION
;
MessageParcel
data
;
MessageParcel
reply
;
MessageOption
option
;
MockIRemoteInvoker
*
invoker
=
new
MockIRemoteInvoker
();
IPCThreadSkeleton
*
current
=
IPCThreadSkeleton
::
GetCurrent
();
current
->
invokers_
[
IRemoteObject
::
IF_PROT_BINDER
]
=
invoker
;
EXPECT_CALL
(
*
invoker
,
GetStatus
())
.
WillRepeatedly
(
testing
::
Return
(
IRemoteInvoker
::
ACTIVE_INVOKER
));
EXPECT_CALL
(
*
invoker
,
GetCallerPid
())
.
WillRepeatedly
(
testing
::
Return
(
1111
));
EXPECT_CALL
(
*
invoker
,
GetCallerUid
())
.
WillRepeatedly
(
testing
::
Return
(
-
1
));
EXPECT_CALL
(
*
invoker
,
SendRequest
(
testing
::
_
,
testing
::
_
,
testing
::
_
,
testing
::
_
,
testing
::
_
))
.
WillRepeatedly
(
testing
::
Return
(
1
));
int32_t
ret
=
fakeStub
->
ProcessProto
(
code
,
data
,
reply
,
option
);
EXPECT_EQ
(
ret
,
DBINDER_SERVICE_PROCESS_PROTO_ERR
);
current
->
invokers_
.
clear
();
delete
invoker
;
}
\ No newline at end of file
ipc/native/test/unittest/common/dbinder_session_object_unittest.cpp
浏览文件 @
f7be6e37
...
...
@@ -83,12 +83,10 @@ HWTEST_F(DBinderSessionObjectTest, GetBusSessionTest001, TestSize.Level1)
DBinderSessionObject
object
(
sessionMock
,
serviceName
,
serverDeviceId
,
1
,
nullptr
,
1
);
EXPECT_CALL
(
*
sessionMock
,
GetChannelId
())
.
Times
(
1
)
.
WillOnce
(
testing
::
Return
(
1
));
.
WillRepeatedly
(
testing
::
Return
(
1
));
EXPECT_CALL
(
*
sessionMock
,
GetSessionId
())
.
Times
(
1
)
.
WillOnce
(
testing
::
Return
(
1
));
.
WillRepeatedly
(
testing
::
Return
(
1
));
auto
session
=
object
.
GetBusSession
();
EXPECT_NE
(
session
,
nullptr
);
...
...
@@ -191,8 +189,7 @@ HWTEST_F(DBinderSessionObjectTest, GetSessionHandleTest001, TestSize.Level1)
DBinderSessionObject
object
(
sessionMock
,
serviceName
,
serverDeviceId
,
1
,
nullptr
,
1
);
EXPECT_CALL
(
*
sessionMock
,
GetChannelId
())
.
Times
(
1
)
.
WillOnce
(
testing
::
Return
(
1
));
.
WillRepeatedly
(
testing
::
Return
(
1
));
uint32_t
ret
=
object
.
GetSessionHandle
();
uint32_t
id
=
1
;
...
...
ipc/native/test/unittest/common/ipc_core_unittest.cpp
浏览文件 @
f7be6e37
此差异已折叠。
点击以展开。
ipc/native/test/unittest/common/ipc_file_desc_unittest.cpp
浏览文件 @
f7be6e37
...
...
@@ -18,9 +18,14 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <gtest/gtest.h>
#define private public
#include "binder_invoker.h"
#include "ipc_debug.h"
#include "ipc_file_descriptor.h"
#include "log_tags.h"
#include "ipc_thread_skeleton.h"
#undef private
namespace
OHOS
{
using
namespace
testing
::
ext
;
...
...
@@ -90,4 +95,50 @@ HWTEST_F(IPCFileDescOpsTest, fd_parcelable_003, TestSize.Level1)
fdesc
.
SetFd
(
fd
);
EXPECT_EQ
(
fd
,
fdesc
.
GetFd
());
}
HWTEST_F
(
IPCFileDescOpsTest
,
Marshalling001
,
TestSize
.
Level1
)
{
int
fd
=
9876
;
IPCFileDescriptor
fdesc
;
fdesc
.
SetFd
(
fd
);
BinderInvoker
*
invoker
=
nullptr
;
IPCThreadSkeleton
*
current
=
IPCThreadSkeleton
::
GetCurrent
();
current
->
invokers_
[
IRemoteObject
::
IF_PROT_DEFAULT
]
=
invoker
;
Parcel
parcel
;
auto
ret
=
fdesc
.
Marshalling
(
parcel
);
ASSERT_FALSE
(
ret
);
}
HWTEST_F
(
IPCFileDescOpsTest
,
Unmarshalling001
,
TestSize
.
Level1
)
{
int
fd
=
9876
;
IPCFileDescriptor
fdesc
;
fdesc
.
SetFd
(
fd
);
BinderInvoker
*
invoker
=
nullptr
;
IPCThreadSkeleton
*
current
=
IPCThreadSkeleton
::
GetCurrent
();
current
->
invokers_
[
IRemoteObject
::
IF_PROT_DEFAULT
]
=
invoker
;
Parcel
parcel
;
auto
ret
=
fdesc
.
Unmarshalling
(
parcel
);
ASSERT_TRUE
(
ret
==
nullptr
);
}
HWTEST_F
(
IPCFileDescOpsTest
,
Unmarshalling002
,
TestSize
.
Level1
)
{
int
fd
=
9876
;
IPCFileDescriptor
fdesc
;
Parcel
parcel
;
fdesc
.
SetFd
(
fd
);
BinderInvoker
*
invoker
=
new
BinderInvoker
();
invoker
->
WriteFileDescriptor
(
parcel
,
fd
,
true
);
IPCThreadSkeleton
*
current
=
IPCThreadSkeleton
::
GetCurrent
();
current
->
invokers_
[
IRemoteObject
::
IF_PROT_DEFAULT
]
=
invoker
;
auto
ret
=
fdesc
.
Unmarshalling
(
parcel
);
ASSERT_TRUE
(
ret
!=
nullptr
);
}
}
// namespace OHOS
ipc/native/test/unittest/common/ipc_object_stub_unittest.cpp
0 → 100644
浏览文件 @
f7be6e37
此差异已折叠。
点击以展开。
ipc/native/test/unittest/common/ipc_thread_pool_unittest.cpp
0 → 100644
浏览文件 @
f7be6e37
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#define private public
#include "ipc_types.h"
#include "ipc_thread_pool.h"
#include "ipc_workthread.h"
#undef private
using
namespace
testing
::
ext
;
using
namespace
OHOS
;
class
IPCWorkThreadPoolUnitTest
:
public
testing
::
Test
{
public:
static
void
SetUpTestCase
(
void
);
static
void
TearDownTestCase
(
void
);
void
SetUp
();
void
TearDown
();
};
void
IPCWorkThreadPoolUnitTest
::
SetUpTestCase
()
{
}
void
IPCWorkThreadPoolUnitTest
::
TearDownTestCase
()
{
}
void
IPCWorkThreadPoolUnitTest
::
SetUp
()
{}
void
IPCWorkThreadPoolUnitTest
::
TearDown
()
{}
/**
* @tc.name: RemoveThreadTest001
* @tc.desc: Verify the RemoveThread function
* @tc.type: FUNC
*/
HWTEST_F
(
IPCWorkThreadPoolUnitTest
,
RemoveThreadTest001
,
TestSize
.
Level1
)
{
IPCWorkThreadPool
threadPool
(
1
);
std
::
string
threadName
=
"threadName1"
;
auto
ipcThread
=
new
(
std
::
nothrow
)
IPCWorkThread
(
threadName
);
ASSERT_TRUE
(
ipcThread
!=
nullptr
);
ipcThread
->
proto_
=
IRemoteObject
::
IF_PROT_DEFAULT
;
threadPool
.
threads_
[
threadName
]
=
ipcThread
;
auto
ret
=
threadPool
.
RemoveThread
(
threadName
);
EXPECT_EQ
(
ret
,
true
);
threadPool
.
threads_
.
clear
();
ASSERT_TRUE
(
ipcThread
!=
nullptr
);
}
/**
* @tc.name: RemoveThreadTest002
* @tc.desc: Verify the RemoveThread function
* @tc.type: FUNC
*/
HWTEST_F
(
IPCWorkThreadPoolUnitTest
,
RemoveThreadTest002
,
TestSize
.
Level1
)
{
IPCWorkThreadPool
threadPool
(
1
);
std
::
string
threadName
=
"threadName2"
;
auto
ipcThread
=
new
(
std
::
nothrow
)
IPCWorkThread
(
threadName
);
ipcThread
->
proto_
=
IRemoteObject
::
IF_PROT_DATABUS
;
threadPool
.
threads_
[
threadName
]
=
ipcThread
;
auto
ret
=
threadPool
.
RemoveThread
(
threadName
);
EXPECT_EQ
(
ret
,
true
);
threadPool
.
threads_
.
clear
();
}
/**
* @tc.name: RemoveThreadTest003
* @tc.desc: Verify the RemoveThread function
* @tc.type: FUNC
*/
HWTEST_F
(
IPCWorkThreadPoolUnitTest
,
RemoveThreadTest003
,
TestSize
.
Level1
)
{
IPCWorkThreadPool
threadPool
(
1
);
std
::
string
threadName
=
"threadName3"
;
auto
ipcThread
=
new
(
std
::
nothrow
)
IPCWorkThread
(
threadName
);
ipcThread
->
proto_
=
IRemoteObject
::
IF_PROT_ERROR
;
threadPool
.
threads_
[
threadName
]
=
ipcThread
;
auto
ret
=
threadPool
.
RemoveThread
(
threadName
);
EXPECT_EQ
(
ret
,
true
);
threadPool
.
threads_
.
clear
();
}
/**
* @tc.name: RemoveThreadTest004
* @tc.desc: Verify the RemoveThread function
* @tc.type: FUNC
*/
HWTEST_F
(
IPCWorkThreadPoolUnitTest
,
RemoveThreadTest004
,
TestSize
.
Level1
)
{
IPCWorkThreadPool
threadPool
(
1
);
std
::
string
threadName
=
"threadName4"
;
sptr
<
IPCWorkThread
>
ipcThread
=
nullptr
;
threadPool
.
threads_
[
threadName
]
=
ipcThread
;
auto
ret
=
threadPool
.
RemoveThread
(
threadName
);
EXPECT_EQ
(
ret
,
false
);
threadPool
.
threads_
.
clear
();
}
/**
* @tc.name: RemoveThreadTest005
* @tc.desc: Verify the RemoveThread function
* @tc.type: FUNC
*/
HWTEST_F
(
IPCWorkThreadPoolUnitTest
,
RemoveThreadTest005
,
TestSize
.
Level1
)
{
IPCWorkThreadPool
threadPool
(
1
);
std
::
string
threadName
=
"threadName5"
;
auto
ret
=
threadPool
.
RemoveThread
(
threadName
);
EXPECT_EQ
(
ret
,
false
);
}
/**
* @tc.name: UpdateMaxThreadNumTest001
* @tc.desc: Verify the UpdateMaxThreadNum function
* @tc.type: FUNC
*/
HWTEST_F
(
IPCWorkThreadPoolUnitTest
,
UpdateMaxThreadNumTest001
,
TestSize
.
Level1
)
{
IPCWorkThreadPool
threadPool
(
1
);
threadPool
.
UpdateMaxThreadNum
(
0
);
EXPECT_EQ
(
threadPool
.
maxThreadNum_
,
2
);
}
\ No newline at end of file
ipc/native/test/unittest/common/message_parcel_unittest.cpp
0 → 100644
浏览文件 @
f7be6e37
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#define private public
#include "buffer_object.h"
#include "dbinder_session_object.h"
#include "ipc_object_proxy.h"
#include "ipc_process_skeleton.h"
#include "message_option.h"
#include "message_parcel.h"
#include "mock_session_impl.h"
#undef private
using
namespace
testing
::
ext
;
using
namespace
OHOS
;
namespace
{
constexpr
int
INVALID_LEN
=
9999
;
}
class
MessageParcelTest
:
public
testing
::
Test
{
public:
static
void
SetUpTestCase
(
void
);
static
void
TearDownTestCase
(
void
);
void
SetUp
();
void
TearDown
();
};
void
MessageParcelTest
::
SetUpTestCase
()
{
}
void
MessageParcelTest
::
TearDownTestCase
()
{
}
void
MessageParcelTest
::
SetUp
()
{
}
void
MessageParcelTest
::
TearDown
()
{
}
/**
* @tc.name: SyncTransaction010
* @tc.desc: Test write and read exception.
* @tc.type: FUNC
* @tc.require: AR000E1QEG
*/
HWTEST_F
(
MessageParcelTest
,
SyncTransaction010
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
parcel
.
WriteNoException
();
ASSERT_EQ
(
parcel
.
ReadException
(),
0
);
}
/**
* @tc.name: GetRawDataCapacityTest001
* @tc.desc: Verify the GetRawDataCapacity function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
GetRawDataCapacityTest001
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
size_t
ret
=
parcel
.
GetRawDataCapacity
();
EXPECT_EQ
(
ret
,
MAX_RAWDATA_SIZE
);
}
/**
* @tc.name: GetRawDataCapacityTest002
* @tc.desc: Verify the GetRawDataCapacity function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
GetRawDataCapacityTest002
,
TestSize
.
Level1
)
{
MessageParcel
data
;
uint8_t
bytes
[
8
]
=
{
0
};
data
.
WriteBuffer
(
bytes
,
8
);
MessageParcel
parcel
;
bool
ret
=
parcel
.
Append
(
data
);
EXPECT_EQ
(
ret
,
true
);
}
#ifndef CONFIG_IPC_SINGLE
/**
* @tc.name: WriteDBinderProxyTest001
* @tc.desc: Verify the MessageParcel::WriteDBinderProxy function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
WriteDBinderProxyTest001
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
uint32_t
handle
=
1
;
uint64_t
stubIndex
=
1
;
IPCProcessSkeleton
*
current
=
IPCProcessSkeleton
::
GetCurrent
();
sptr
<
IRemoteObject
>
object
=
new
IPCObjectStub
(
u"testObject"
);
std
::
shared_ptr
<
MockSessionImpl
>
sessionMock
=
std
::
make_shared
<
MockSessionImpl
>
();
auto
dbinderSessionObject
=
std
::
make_shared
<
DBinderSessionObject
>
(
sessionMock
,
"name"
,
"deviceId"
,
1
,
nullptr
,
1
);
current
->
proxyToSession_
[
handle
]
=
dbinderSessionObject
;
auto
ret
=
parcel
.
WriteDBinderProxy
(
object
,
handle
,
stubIndex
);
EXPECT_EQ
(
ret
,
true
);
current
->
proxyToSession_
.
erase
(
handle
);
}
/**
* @tc.name: WriteDBinderProxyTest002
* @tc.desc: Verify the MessageParcel::WriteDBinderProxy function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
WriteDBinderProxyTest002
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
sptr
<
IRemoteObject
>
object
=
new
IPCObjectStub
(
u"testObject"
);
uint32_t
handle
=
1
;
uint64_t
stubIndex
=
1
;
auto
ret
=
parcel
.
WriteDBinderProxy
(
object
,
handle
,
stubIndex
);
EXPECT_EQ
(
ret
,
false
);
}
/**
* @tc.name: WriteRemoteObjectTest001
* @tc.desc: Verify the MessageParcel::WriteRemoteObject function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
WriteRemoteObjectTest001
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
uint32_t
handle
=
IPCProcessSkeleton
::
DBINDER_HANDLE_BASE
+
1
;
sptr
<
IPCObjectProxy
>
objectProxy
=
new
IPCObjectProxy
(
handle
,
u"test"
);
auto
ret
=
parcel
.
WriteRemoteObject
(
objectProxy
);
EXPECT_EQ
(
ret
,
false
);
}
#endif
/**
* @tc.name: WriteFileDescriptorTest001
* @tc.desc: Verify the MessageParcel::WriteFileDescriptor function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
WriteFileDescriptorTest001
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
int
fd
=
1
;
auto
ret
=
parcel
.
WriteFileDescriptor
(
fd
);
EXPECT_EQ
(
ret
,
true
);
}
/**
* @tc.name: WriteFileDescriptorTest002
* @tc.desc: Verify the MessageParcel::WriteFileDescriptor function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
WriteFileDescriptorTest002
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
int
fd
=
-
1
;
auto
ret
=
parcel
.
WriteFileDescriptor
(
fd
);
EXPECT_EQ
(
ret
,
false
);
}
/**
* @tc.name: ClearFileDescriptorTest001
* @tc.desc: Verify the MessageParcel::ClearFileDescriptor function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
ClearFileDescriptorTest001
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
parcel
.
ClearFileDescriptor
();
ASSERT_TRUE
(
parcel
.
rawDataSize_
==
0
);
}
/**
* @tc.name: ContainFileDescriptorsTest001
* @tc.desc: Verify the MessageParcel::ContainFileDescriptors function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
ContainFileDescriptorsTest001
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
parcel
.
ContainFileDescriptors
();
ASSERT_TRUE
(
parcel
.
rawDataSize_
==
0
);
}
/**
* @tc.name: RestoreRawDataTest001
* @tc.desc: Verify the MessageParcel::RestoreRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
RestoreRawDataTest001
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
std
::
shared_ptr
<
char
>
rawData
=
std
::
make_shared
<
char
>
();
size_t
size
=
1
;
parcel
.
rawData_
=
nullptr
;
auto
ret
=
parcel
.
RestoreRawData
(
nullptr
,
size
);
ASSERT_FALSE
(
ret
);
ret
=
parcel
.
RestoreRawData
(
rawData
,
size
);
ASSERT_TRUE
(
ret
);
ret
=
parcel
.
RestoreRawData
(
nullptr
,
size
);
ASSERT_FALSE
(
ret
);
parcel
.
rawData_
=
rawData
;
ret
=
parcel
.
RestoreRawData
(
rawData
,
size
);
ASSERT_FALSE
(
ret
);
}
/**
* @tc.name: ReadRawDataTest001
* @tc.desc: Verify the MessageParcel::ReadRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
ReadRawDataTest001
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
auto
ret
=
parcel
.
ReadRawData
(
INVALID_LEN
);
ASSERT_TRUE
(
ret
==
nullptr
);
}
/**
* @tc.name: ReadRawDataTest002
* @tc.desc: Verify the MessageParcel::ReadRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
ReadRawDataTest002
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
parcel
.
WriteInt32
(
MessageParcel
::
MIN_RAWDATA_SIZE
);
auto
ret
=
parcel
.
ReadRawData
(
1
);
ASSERT_TRUE
(
ret
==
nullptr
);
}
/**
* @tc.name: ReadRawDataTest003
* @tc.desc: Verify the MessageParcel::ReadRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
ReadRawDataTest003
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
parcel
.
WriteInt32
(
MessageParcel
::
MIN_RAWDATA_SIZE
+
1
);
auto
ret
=
parcel
.
ReadRawData
(
MessageParcel
::
MIN_RAWDATA_SIZE
+
1
);
ASSERT_TRUE
(
ret
==
nullptr
);
}
/**
* @tc.name: ReadRawDataTest004
* @tc.desc: Verify the MessageParcel::ReadRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
ReadRawDataTest004
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
parcel
.
WriteInt32
(
MessageParcel
::
MIN_RAWDATA_SIZE
+
1
);
parcel
.
rawData_
=
std
::
make_shared
<
char
>
(
1
);
parcel
.
rawDataSize_
=
1
;
parcel
.
writeRawDataFd_
=
0
;
auto
ret
=
parcel
.
ReadRawData
(
1
);
ASSERT_TRUE
(
ret
==
nullptr
);
}
/**
* @tc.name: ReadRawDataTest005
* @tc.desc: Verify the MessageParcel::ReadRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
ReadRawDataTest005
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
parcel
.
WriteInt32
(
MessageParcel
::
MIN_RAWDATA_SIZE
+
1
);
parcel
.
rawData_
=
std
::
make_shared
<
char
>
(
1
);
parcel
.
rawDataSize_
=
1
;
parcel
.
writeRawDataFd_
=
-
1
;
auto
ret
=
parcel
.
ReadRawData
(
1
);
ASSERT_TRUE
(
ret
==
nullptr
);
}
/**
* @tc.name: ReadRawDataTest006
* @tc.desc: Verify the MessageParcel::ReadRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
ReadRawDataTest006
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
parcel
.
WriteInt32
(
MessageParcel
::
MIN_RAWDATA_SIZE
+
1
);
parcel
.
rawData_
=
nullptr
;
parcel
.
rawDataSize_
=
0
;
parcel
.
writeRawDataFd_
=
-
1
;
auto
ret
=
parcel
.
ReadRawData
(
1
);
ASSERT_TRUE
(
ret
==
nullptr
);
}
/**
* @tc.name: ReadRawDataTest007
* @tc.desc: Verify the MessageParcel::ReadRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
ReadRawDataTest007
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
parcel
.
WriteInt32
(
MessageParcel
::
MIN_RAWDATA_SIZE
+
1
);
parcel
.
rawDataSize_
=
0
;
parcel
.
writeRawDataFd_
=
0
;
parcel
.
rawData_
=
std
::
make_shared
<
char
>
(
MessageParcel
::
MIN_RAWDATA_SIZE
+
1
);
auto
ret
=
parcel
.
ReadRawData
(
MessageParcel
::
MIN_RAWDATA_SIZE
+
1
);
ASSERT_TRUE
(
ret
==
nullptr
);
}
/**
* @tc.name: ReadRawDataTest008
* @tc.desc: Verify the MessageParcel::ReadRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
ReadRawDataTest008
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
parcel
.
WriteInt32
(
MessageParcel
::
MIN_RAWDATA_SIZE
+
1
);
parcel
.
rawData_
=
std
::
make_shared
<
char
>
(
MessageParcel
::
MIN_RAWDATA_SIZE
+
1
);
parcel
.
writeRawDataFd_
=
0
;
auto
ret
=
parcel
.
ReadRawData
(
MessageParcel
::
MIN_RAWDATA_SIZE
);
ASSERT_TRUE
(
ret
==
nullptr
);
}
/**
* @tc.name: GetRawDataTest001
* @tc.desc: Verify the MessageParcel::GetRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
GetRawDataTest001
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
parcel
.
rawData_
=
std
::
make_shared
<
char
>
(
1
);
auto
ret
=
parcel
.
GetRawData
();
ASSERT_TRUE
(
ret
!=
nullptr
);
}
/**
* @tc.name: GetRawDataTest002
* @tc.desc: Verify the MessageParcel::GetRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
GetRawDataTest002
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
parcel
.
rawData_
=
nullptr
;
auto
ret
=
parcel
.
GetRawData
();
ASSERT_TRUE
(
ret
==
nullptr
);
}
/**
* @tc.name: GetRawDataTest003
* @tc.desc: Verify the MessageParcel::GetRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
GetRawDataTest003
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
parcel
.
rawData_
=
nullptr
;
int
tmp
=
1
;
void
*
ptr
=
&
tmp
;
parcel
.
kernelMappedWrite_
=
ptr
;
auto
ret
=
parcel
.
GetRawData
();
ASSERT_TRUE
(
ret
!=
nullptr
);
}
/**
* @tc.name: GetRawDataTest004
* @tc.desc: Verify the MessageParcel::GetRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
GetRawDataTest004
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
parcel
.
rawData_
=
nullptr
;
parcel
.
kernelMappedWrite_
=
nullptr
;
int
tmp
=
1
;
void
*
ptr
=
&
tmp
;
parcel
.
kernelMappedRead_
=
ptr
;
auto
ret
=
parcel
.
GetRawData
();
ASSERT_TRUE
(
ret
!=
nullptr
);
}
/**
* @tc.name: WriteAshmemTest001
* @tc.desc: Verify the MessageParcel::WriteAshmem function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
WriteAshmemTest001
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
std
::
string
name
=
"ashmem1"
;
sptr
<
Ashmem
>
ashmem
=
Ashmem
::
CreateAshmem
(
name
.
c_str
(),
1
);
ASSERT_TRUE
(
ashmem
!=
nullptr
);
auto
ret
=
parcel
.
WriteAshmem
(
ashmem
);
ASSERT_TRUE
(
ret
==
true
);
ashmem
->
CloseAshmem
();
}
/**
* @tc.name: ReadAshmemTest001
* @tc.desc: Verify the MessageParcel::ReadAshmem function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
ReadAshmemTest001
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
auto
ret
=
parcel
.
ReadAshmem
();
ASSERT_TRUE
(
ret
==
nullptr
);
}
/**
* @tc.name: AppendTest001
* @tc.desc: Verify the MessageParcel::Append function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
AppendTest001
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
MessageParcel
data
;
auto
ret
=
parcel
.
Append
(
data
);
ASSERT_TRUE
(
ret
);
}
/**
* @tc.name: WriteRawDataTest001
* @tc.desc: Verify the MessageParcel::WriteRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
WriteRawDataTest001
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
char
data
[
1
]
=
{
0
};
auto
ret
=
parcel
.
WriteRawData
(
data
,
1
);
ASSERT_TRUE
(
ret
);
}
/**
* @tc.name: WriteRawDataTest002
* @tc.desc: Verify the MessageParcel::WriteRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
WriteRawDataTest002
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
auto
ret
=
parcel
.
WriteRawData
(
nullptr
,
1
);
ASSERT_TRUE
(
!
ret
);
}
/**
* @tc.name: WriteRawDataTest003
* @tc.desc: Verify the MessageParcel::WriteRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
WriteRawDataTest003
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
char
data
[
1
]
=
{
0
};
auto
ret
=
parcel
.
WriteRawData
(
data
,
MAX_RAWDATA_SIZE
+
1
);
ASSERT_TRUE
(
!
ret
);
}
/**
* @tc.name: WriteRawDataTest004
* @tc.desc: Verify the MessageParcel::WriteRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
WriteRawDataTest004
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
char
data
[
MessageParcel
::
MIN_RAWDATA_SIZE
+
1
]
=
{
0
};
auto
ret
=
parcel
.
WriteRawData
(
data
,
MessageParcel
::
MIN_RAWDATA_SIZE
+
1
);
ASSERT_TRUE
(
ret
);
}
/**
* @tc.name: WriteRawDataTest005
* @tc.desc: Verify the MessageParcel::WriteRawData function
* @tc.type: FUNC
*/
HWTEST_F
(
MessageParcelTest
,
WriteRawDataTest005
,
TestSize
.
Level1
)
{
MessageParcel
parcel
;
char
data
[
1
]
=
{
0
};
parcel
.
kernelMappedWrite_
=
data
;
auto
ret
=
parcel
.
WriteRawData
(
data
,
1
);
ASSERT_TRUE
(
!
ret
);
}
ipc/native/test/unittest/common/mock_iremote_invoker.h
0 → 100644
浏览文件 @
f7be6e37
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_MOCK_IPC_IREMOTE_INVOKER_H
#define OHOS_MOCK_IPC_IREMOTE_INVOKER_H
#include <unistd.h>
#include <sys/types.h>
#include "binder_connector.h"
#include "iremote_invoker.h"
#include "invoker_factory.h"
namespace
OHOS
{
#ifdef CONFIG_IPC_SINGLE
namespace
IPC_SINGLE
{
#endif
class
MockIRemoteInvoker
:
public
IRemoteInvoker
{
public:
MockIRemoteInvoker
()
=
default
;
MOCK_METHOD1
(
AcquireHandle
,
bool
(
int32_t
handle
));
MOCK_METHOD1
(
ReleaseHandle
,
bool
(
int32_t
handle
));
MOCK_METHOD1
(
PingService
,
bool
(
int32_t
handle
));
MOCK_METHOD3
(
SendReply
,
int
(
MessageParcel
&
reply
,
uint32_t
flags
,
int32_t
result
));
MOCK_METHOD5
(
SendRequest
,
int
(
int
handle
,
uint32_t
code
,
MessageParcel
&
data
,
MessageParcel
&
reply
,
MessageOption
&
option
));
MOCK_METHOD2
(
AddDeathRecipient
,
bool
(
int32_t
handle
,
void
*
cookie
));
MOCK_METHOD2
(
RemoveDeathRecipient
,
bool
(
int32_t
handle
,
void
*
cookie
));
MOCK_METHOD1
(
SetMaxWorkThread
,
bool
(
int
maxThreadNum
));
MOCK_METHOD1
(
JoinThread
,
void
(
bool
initiative
));
MOCK_METHOD1
(
JoinProcessThread
,
void
(
bool
initiative
));
MOCK_METHOD1
(
FreeBuffer
,
void
(
void
*
data
));
MOCK_METHOD1
(
SetRegistryObject
,
bool
(
sptr
<
IRemoteObject
>
&
object
));
MOCK_METHOD0
(
StopWorkThread
,
void
());
MOCK_CONST_METHOD0
(
GetCallerPid
,
pid_t
());
MOCK_CONST_METHOD0
(
GetCallerUid
,
uid_t
());
MOCK_CONST_METHOD0
(
GetCallerTokenID
,
uint64_t
());
MOCK_CONST_METHOD0
(
GetFirstCallerTokenID
,
uint64_t
());
MOCK_CONST_METHOD0
(
GetSelfTokenID
,
uint64_t
());
MOCK_CONST_METHOD0
(
GetSelfFirstCallerTokenID
,
uint64_t
());
MOCK_CONST_METHOD0
(
GetStatus
,
uint32_t
());
MOCK_METHOD0
(
IsLocalCalling
,
bool
());
MOCK_METHOD0
(
GetLocalDeviceID
,
std
::
string
());
MOCK_CONST_METHOD0
(
GetCallerDeviceID
,
std
::
string
());
MOCK_CONST_METHOD2
(
FlattenObject
,
bool
(
Parcel
&
parcel
,
const
IRemoteObject
*
object
));
MOCK_METHOD1
(
UnflattenObject
,
sptr
<
IRemoteObject
>
(
Parcel
&
parcel
));
MOCK_METHOD1
(
ReadFileDescriptor
,
int
(
Parcel
&
parcel
));
MOCK_METHOD3
(
WriteFileDescriptor
,
bool
(
Parcel
&
parcel
,
int
fd
,
bool
takeOwnership
));
MOCK_METHOD1
(
FlushCommands
,
int
(
IRemoteObject
*
object
));
MOCK_METHOD0
(
ResetCallingIdentity
,
std
::
string
());
MOCK_METHOD1
(
SetCallingIdentity
,
bool
(
std
::
string
&
identity
));
#ifndef CONFIG_IPC_SINGLE
MOCK_METHOD0
(
GetSAMgrObject
,
sptr
<
IRemoteObject
>
());
MOCK_METHOD2
(
TranslateIRemoteObject
,
int
(
int32_t
cmd
,
const
sptr
<
IRemoteObject
>
&
obj
));
#endif
};
#ifdef CONFIG_IPC_SINGLE
}
// namespace IPC_SINGLE
#endif
}
// namespace OHOS
#endif // OHOS_MOCK_IPC_IREMOTE_INVOKER_H
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录