未验证 提交 068d8a44 编写于 作者: O openharmony_ci 提交者: Gitee

!9306 完成distributeddatamgr子系统data.preferences模块的跨平台测试套 ...

!9306 完成distributeddatamgr子系统data.preferences模块的跨平台测试套  完成distributeddatamgr子系统data.relationalStore模块的跨平台测试套
Merge pull request !9306 from huyanqiang/distributeddatamgr_lifangyuan
......@@ -16,7 +16,8 @@ group("distributeddatamgr") {
testonly = true
if (is_standard_system) {
deps = [
"UDMFtest:UDMFtest",
"crossplatform/preferencesetstest:ActsCrossplatformPreferencesTest",
"crossplatform/relationalstoreetstest:ActsCrossplatformRelationalStoreTest",
"dataObjectjstest/hap:dataObject_js_test",
"dataSharejstest/hap:dataShare_js_test",
"distributedKVStoretest:distributedKVStoretest",
......
{
"app": {
"bundleName": "ohos.acts.distributeddatamgr.crossplatform.preferences.normal",
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:app_icon",
"label": "$string:app_name",
"minAPIVersion": 10,
"targetAPIVersion": 10,
"car": {
"apiCompatibleVersion": 10,
"singleUser": false
}
}
}
# Copyright (C) 2023 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.
import("//test/xts/tools/build/suite.gni")
ohos_js_hap_suite("ActsCrossplatformPreferencesTest") {
hap_profile = "src/main/module.json"
deps = [
":windowStage_js_assets",
":windowStage_resources",
]
ets2abc = true
certificate_profile = "./signature/openharmony_sx.p7b"
# hap_name: HAP的名字,可选,默认为目标名
hap_name = "ActsCrossplatformPreferencesTest"
subsystem_name = "distributeddatamgr"
part_name = "preferences"
}
ohos_app_scope("windowStage_app_profile") {
# app_profile: HAP的AppScope中的app.json,只在Stage模型下使用
app_profile = "AppScope/app.json"
# sources: 资源文件路径
sources = [ "AppScope/resources" ]
}
ohos_js_assets("windowStage_js_assets") {
# source_dir: js或ets代码路径,兼容FA模型的单ability配置到ability目录
source_dir = "src/main/ets"
}
ohos_resources("windowStage_resources") {
# sources: 资源文件路径
sources = [ "src/main/resources" ]
# deps: 当前目标的依赖
deps = [ ":windowStage_app_profile" ]
# hap_profile: HAP的config.json,Stage模型对应module.json
hap_profile = "src/main/module.json"
}
{
"description": "Configuration for hjunit demo Tests",
"driver": {
"type": "OHJSUnitTest",
"test-timeout": "60000",
"shell-timeout": "60000",
"bundle-name": "ohos.acts.distributeddatamgr.crossplatform.preferences.normal",
"module-name": "preferences_test_normal_ets"
},
"kits": [
{
"test-file-name": [
"ActsCrossplatformPreferencesTest.hap"
],
"type": "AppInstallKit",
"cleanup-apps": true
}
]
}
\ No newline at end of file
/*
* Copyright (c) 2023 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.
*/
import UIAbility from "@ohos.app.ability.UIAbility";
import AbilityDelegatorRegistry from "@ohos.app.ability.abilityDelegatorRegistry";
import hilog from "@ohos.hilog";
import { Hypium } from "@ohos/hypium";
import testsuite from "../test/List.test";
import window from "@ohos.window";
export default class TestAbility extends UIAbility {
onCreate(want, launchParam) {
hilog.info(0x0000, "testTag", "%{public}s", "TestAbility onCreate");
hilog.info(0x0000, "testTag", "%{public}s", "want param:" + JSON.stringify(want) ?? "");
hilog.info(0x0000, "testTag", "%{public}s", "launchParam:" + JSON.stringify(launchParam) ?? "");
var abilityDelegator: any;
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
var abilityDelegatorArguments: any;
abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments();
hilog.info(0x0000, "testTag", "%{public}s", "start run testcase!!!");
Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite);
}
onDestroy() {
hilog.info(0x0000, "testTag", "%{public}s", "TestAbility onDestroy");
}
onWindowStageCreate(windowStage: window.WindowStage) {
hilog.info(0x0000, "testTag", "%{public}s", "TestAbility onWindowStageCreate");
globalThis.abilityContext = this.context;
windowStage.loadContent("TestAbility/pages/Index", (err, data) => {
if (err.code) {
hilog.error(0x0000, "testTag", "Failed to load the content. Cause: %{public}s", JSON.stringify(err) ?? "");
return;
}
hilog.info(0x0000, "testTag", "Succeeded in loading the content. Data: %{public}s", JSON.stringify(data) ?? "");
});
}
onWindowStageDestroy() {
hilog.info(0x0000, "testTag", "%{public}s", "TestAbility onWindowStageDestroy");
}
onForeground() {
hilog.info(0x0000, "testTag", "%{public}s", "TestAbility onForeground");
}
onBackground() {
hilog.info(0x0000, "testTag", "%{public}s", "TestAbility onBackground");
}
}
/*
* Copyright (c) 2023 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.
*/
import hilog from '@ohos.hilog';
@Entry
@Component
struct Index {
aboutToAppear() {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear');
}
@State message: string = 'Hello World'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
Button() {
Text('next page')
.fontSize(20)
.fontWeight(FontWeight.Bold)
}.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('35%')
.height('5%')
.onClick(()=>{
})
}
.width('100%')
}
.height('100%')
}
}
\ No newline at end of file
import hilog from '@ohos.hilog';
import TestRunner from '@ohos.application.testRunner';
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
var abilityDelegator = undefined
var abilityDelegatorArguments = undefined
async function onAbilityCreateCallback() {
hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback');
}
async function addAbilityMonitorCallback(err: any) {
hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
}
export default class OpenHarmonyTestRunner implements TestRunner {
constructor() {
}
onPrepare() {
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare ');
}
async onRun() {
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run');
abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility'
let lMonitor = {
abilityName: testAbilityName,
onAbilityCreate: onAbilityCreateCallback,
};
abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName
var debug = abilityDelegatorArguments.parameters['-D']
if (debug == 'true')
{
cmd += ' -D'
}
hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd);
abilityDelegator.executeShellCommand(cmd,
(err: any, d: any) => {
hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? '');
hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.stdResult ?? '');
hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.exitCode ?? '');
})
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end');
}
}
\ No newline at end of file
/*
* Copyright (c) 2023 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.
*/
import preferencescallback from './PreferencesCallBack.test'
import preferenceshelper from './PreferencesHelper.test'
import preferencespromise from './PreferencesPromise.test'
import preferencescallbackwitherror from './PreferencesCallBackWithError.test'
import preferencespromisewitherror from './PreferencesPromiseWithError.test'
import preferencesIgnoreTest from './PreferencesIgnore.test'
export default function testsuite() {
preferencescallback()
preferenceshelper()
preferencespromise()
preferencescallbackwitherror()
preferencespromisewitherror()
preferencesIgnoreTest()
}
\ No newline at end of file
/*
* Copyright (c) 2023 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.
*/
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from "@ohos/hypium";
import data_preferences from "@ohos.data.preferences";
const NAME = "test_preferences_callback_with_error";
const KEY_TEST_INT_ELEMENT = "key_test_int";
const KEY_TEST_STRING_ELEMENT = "key_test_string";
let mPreference = undefined;
let context;
export default function preferencesCallbackWithErrorTest() {
describe("preferencesCallbackWithErrorTest", async function () {
beforeAll(async function () {
console.info("beforeAll");
context = globalThis.abilityContext;
mPreference = await data_preferences.getPreferences(context, NAME);
});
afterAll(async function () {
console.info("afterAll");
await data_preferences.deletePreferences(context, NAME);
});
/**
* @tc.number : SUB_DDM_TEST_PREFERENCES_CALLBACK_WITH_ERROR_0000
* @tc.name : testPreferencesCallbackWithError0000
* @tc.desc : Clear、Put、Has、Delete、Get、Flush String callback interface test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testPreferencesCallbackWithError0000", 0, function (done) {
console.log("testPreferencesCallbackWithError0000 begin.");
try {
mPreference.clear(function (err, val) {
if (err) {
console.log("clear err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
mPreference.put(KEY_TEST_STRING_ELEMENT, "abc", function (err, ret) {
if (err) {
console.log("put err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
mPreference.get(KEY_TEST_STRING_ELEMENT, "defaultvalue", function (err, pre) {
if (err) {
console.log("get err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
expect("abc").assertEqual(pre);
mPreference.flush(function (err, val) {
if (err) {
console.log("flush err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
mPreference.delete(KEY_TEST_STRING_ELEMENT, function (err) {
expect(!err).assertTrue();
console.log("Succeeded in deleting .");
done();
console.log("testPreferencesCallbackWithError0000 end.");
});
});
});
});
});
} catch (err) {
console.log("trycatch err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
});
/**
* @tc.number : SUB_DDM_TEST_MPREFERENCES_GET_0000
* @tc.name : testMpreferencesGet0000
* @tc.desc : mPreference.get callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testMpreferencesGet0000", 0, function (done) {
console.log("testMpreferencesGet0000 begin.");
try {
mPreference.get(123, function (err, val) {
console.log("get err");
expect(!err).assertTrue();
});
} catch (err) {
console.log("trycatch err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(err.code === "401" && err.message === "Parameter error. Need 2 or 3 parameters!").assertTrue();
done();
console.log("testMpreferencesGet0000 end.");
}
});
/**
* @tc.number : SUB_DDM_TEST_MPREFERENCES_GET_0100
* @tc.name : testMpreferencesGet0001
* @tc.desc : mPreference.get callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testMpreferencesGet0001", 0, function (done) {
console.log("testMpreferencesGet0001 begin.");
try {
mPreference.get(-1, 123, function (err, val) {
if (err) {
console.log("get err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
done();
}
done();
console.log("testMpreferencesGet0001 end.");
});
} catch (err) {
console.log("trycatch err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(err.code === "401" && err.message === "Parameter error. The type of 'value' must be string.").assertTrue();
done();
}
});
/**
* @tc.number : SUB_DDM_TEST_MPREFERENCES_GET_0200
* @tc.name : testMpreferencesGet0002
* @tc.desc : mPreference.get callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testMpreferencesGet0002", 0, async function (done) {
console.log("testMpreferencesGet0002 begin.");
try {
await mPreference.put(KEY_TEST_INT_ELEMENT, 3);
mPreference.get(KEY_TEST_STRING_ELEMENT, 123, function (err, val) {
if (err) {
console.log("get err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
done();
}
expect(val !== 3).assertTrue();
done();
console.log("testMpreferencesGet0002 end.");
});
} catch (err) {
console.log("trycatch err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
done();
}
});
/**
* @tc.number : SUB_DDM_TEST_MPREFERENCES_GET_ALL_0000
* @tc.name : testMpreferencesGetALL0000
* @tc.desc : mPreference.getAll callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testMpreferencesGetALL0000", 0, function (done) {
console.log("testMpreferencesGetALL0000 begin.");
try {
mPreference.getAll(function (err, val) {
if (err) {
console.log("getAll err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
expect(!err).assertTrue();
done();
console.log("testMpreferencesGetALL0000 end.");
});
} catch (err) {
console.log("trycatch err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
});
/**
* @tc.number : SUB_DDM_TEST_MPREFERENCES_HAS_0100
* @tc.name : testMpreferencesHas0001
* @tc.desc : mPreference.has callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testMpreferencesHas0001", 0, function (done) {
console.log("testMpreferencesHas0001 begin.");
try {
mPreference.has(123, function (err, val) {
console.log("has err");
expect(!err).assertTrue();
});
} catch (err) {
console.log("trycatch err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(err.code === "401" && err.message === "Parameter error. The type of 'value' must be string.").assertTrue();
done();
console.log("testMpreferencesHas0001 end.");
}
});
/**
* @tc.number : SUB_DDM_TEST_MPREFERENCES_HAS_0200
* @tc.name : testMpreferencesHas0002
* @tc.desc : mPreference.has callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testMpreferencesHas0002", 0, function (done) {
console.log("testMpreferencesHas0002 begin.");
try {
mPreference.has(KEY_TEST_STRING_ELEMENT, function (err, val) {
if (err) {
console.log("has err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
expect(!err).assertTrue();
done();
console.log("testMpreferencesHas0002 end.");
});
} catch (err) {
console.log("trycatch err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
});
/**
* @tc.number : SUB_DDM_TEST_MPREFERENCES_PUT_0100
* @tc.name : testMpreferencesPut0001
* @tc.desc : mPreference.put callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testMpreferencesPut0001", 0, function (done) {
console.log("testMpreferencesPut0001 begin.");
try {
mPreference.put(123, function (err) {
console.log("put err");
expect(!err).assertTrue();
});
} catch (err) {
console.log("trycatch err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(err.code === "401" && err.message === "Parameter error. Need 2 or 3 parameters!").assertTrue();
done();
console.log("testMpreferencesPut0001 end.");
}
});
/**
* @tc.number : SUB_DDM_TEST_MPREFERENCES_PUT_0200
* @tc.name : testMpreferencesPut0002
* @tc.desc : mPreference.put callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testMpreferencesPut0002", 0, function (done) {
console.log("testMpreferencesPut0002 begin.");
try {
mPreference.put(KEY_TEST_STRING_ELEMENT, "", async (err) => {
if (err) {
console.log("put err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
done();
}
let pre = await mPreference.get(KEY_TEST_STRING_ELEMENT, "123");
expect(pre === "").assertTrue();
done();
console.log("testMpreferencesPut0002 end.");
});
} catch (err) {
console.log("trycatch err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
done();
}
});
/**
* @tc.number : SUB_DDM_TEST_MPREFERENCES_PUT_0300
* @tc.name : testMpreferencesPut0003
* @tc.desc : mPreference.put callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testMpreferencesPut0003", 0, function (done) {
console.log("testMpreferencesPut0003 begin.");
try {
mPreference.put(KEY_TEST_STRING_ELEMENT, " ", async (err) => {
if (err) {
console.log("put err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
done();
}
let pre = await mPreference.get(KEY_TEST_STRING_ELEMENT, "123");
expect(pre === " ").assertTrue();
done();
console.log("testMpreferencesPut0003 end.");
});
} catch (err) {
console.log("trycatch err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
done();
}
});
/**
* @tc.number : SUB_DDM_TEST_MPREFERENCES_PUT_0400
* @tc.name : testMpreferencesPut0004
* @tc.desc : mPreference.put callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testMpreferencesPut0004", 0, function (done) {
console.log("testMpreferencesPut0004 begin.");
try {
mPreference.put(-1, 123, function (err) {
if (err) {
console.log("put err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
done();
}
expect(!err).assertTrue();
done();
console.log("testMpreferencesPut0004 end.");
});
} catch (err) {
console.log("trycatch err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(err.code === "401" && err.message === "Parameter error. The type of 'value' must be string.").assertTrue();
done();
}
});
/**
* @tc.number : SUB_DDM_TEST_MPREFERENCES_PUT_0500
* @tc.name : testMpreferencesPut0005
* @tc.desc : mPreference.put callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testMpreferencesPut0005", 0, function (done) {
console.log("testMpreferencesPut0005 begin.");
try {
mPreference.put(KEY_TEST_STRING_ELEMENT, null, function (err) {
if (err) {
console.log("put err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
done();
}
expect(!err).assertTrue();
done();
console.log("testMpreferencesPut0005 end.");
});
} catch (err) {
console.log("trycatch err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(err.code === "401" && err.message === "Parameter error. The type of 'value' must be ValueType.").assertTrue();
done();
}
});
/**
* @tc.number : SUB_DDM_TEST_MPREFERENCES_DELETE_0100
* @tc.name : testMpreferencesDelete0001
* @tc.desc : mPreference.delete callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testMpreferencesDelete0001", 0, function (done) {
console.log("testMpreferencesDelete0001 begin.");
try {
mPreference.delete(1233, function (err) {
console.log("delete err");
expect(!err).assertTrue();
});
} catch (err) {
console.log("trycatch err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(err.code === "401" && err.message === "Parameter error. The type of 'value' must be string.").assertTrue();
done();
console.log("testMpreferencesDelete0001 end.");
}
});
/**
* @tc.number : SUB_DDM_TEST_MPREFERENCES_DELETE_0200
* @tc.name : testMpreferencesDelete0002
* @tc.desc : mPreference.delete callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testMpreferencesDelete0002", 0, function (done) {
console.log("testMpreferencesDelete0002 begin.");
try {
mPreference.delete(KEY_TEST_STRING_ELEMENT, function (err) {
if (err) {
console.log("delete err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
expect(!err).assertTrue();
done();
console.log("testMpreferencesDelete0002 end.");
});
} catch (err) {
console.log("trycatch err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
});
/**
* @tc.number : SUB_DDM_TEST_MPREFERENCES_CLEAR_0100
* @tc.name : testMpreferencesClear0001
* @tc.desc : mPreference.clear callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testMpreferencesClear0001", 0, function (done) {
console.log("testMpreferencesClear0001 begin.");
try {
mPreference.clear(function (err) {
if (err) {
console.log("clear err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
expect(!err).assertTrue();
done();
console.log("testMpreferencesClear0001 end.");
});
} catch (err) {
console.log("trycatch err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
});
/**
* @tc.number : SUB_DDM_TEST_MPREFERENCES_FLUSH_0100
* @tc.name : testMpreferencesFlush0001
* @tc.desc : mPreference.flush callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testMpreferencesFlush0001", 0, function (done) {
console.log("testMpreferencesFlush0001 begin.");
try {
mPreference.flush(function (err) {
if (err) {
console.log("flush err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
expect(!err).assertTrue();
done();
console.log("testMpreferencesFlush0001 end.");
});
} catch (err) {
console.log("trycatch err =" + err + ", code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
});
});
}
/*
* Copyright (c) 2023 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.
*/
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from "@ohos/hypium";
import dataPreferences from "@ohos.data.preferences";
const NAME = "test_preferences";
const KEY_TEST_STRING_ELEMENT = "key_test_string";
const KEY_TEST_INT_ELEMENT = "key_test_int";
let mPreferences;
let context;
export default function preferencesHelperTest() {
describe("preferencesHelperTest", function () {
beforeAll(async function () {
console.info("beforeAll");
context = globalThis.abilityContext;
mPreferences = await dataPreferences.getPreferences(context, NAME);
});
afterAll(async function () {
console.info("afterAll");
await dataPreferences.deletePreferences(context, NAME);
});
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
/**
* @tc.number : SUB_DDM_TEST_GET_PREFERENCES_HELPER_0100
* @tc.name : testGetPreferencesHelper0001
* @tc.desc : GetPreferencesSync interface test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testGetPreferencesHelper0001", 0, async function () {
mPreferences = await dataPreferences.getPreferences(context, NAME);
await mPreferences.put(KEY_TEST_STRING_ELEMENT, "test");
await mPreferences.flush();
var value = await mPreferences.get(KEY_TEST_STRING_ELEMENT, 0);
expect(value).assertEqual("test");
});
/**
* @tc.number : SUB_DDM_TEST_GET_PREFERENCES_HELPER_0200
* @tc.name : testGetPreferencesHelper0002
* @tc.desc : GetPreferences interface test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testGetPreferencesHelper0002", 0, async function (done) {
const promise = dataPreferences.getPreferences(context, NAME);
let preferences = null;
promise
.then(async (pref) => {
preferences = pref;
await preferences.put(KEY_TEST_STRING_ELEMENT, "test");
preferences.get(KEY_TEST_STRING_ELEMENT, "defaultvalue", function (err, ret) {
expect("test").assertEqual(ret);
});
await dataPreferences.deletePreferences(context, NAME);
console.info("Succeeded in getting preferences.");
done();
})
.catch((err) => {
expect(!err).assertTrue();
});
});
/**
* @tc.number : SUB_DDM_TEST_REMOVE_PREFERENCES_FROM_CACHE_HELPER_0100
* @tc.name : testRemovePreferencesFromCacheHelper0001
* @tc.desc : RemovePreferencesFromCache interface test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testRemovePreferencesFromCacheHelper0001", 0, async function (done) {
let preferences = null;
preferences = await dataPreferences.getPreferences(context, NAME);
const promise = dataPreferences.removePreferencesFromCache(context, NAME);
promise
.then(() => {
console.info("Succeeded in removing preferences.");
expect("{}").assertEqual(JSON.stringify(preferences));
done();
})
.catch((err) => {
expect(!err).assertTrue();
});
});
/**
* @tc.number : SUB_DDM_TEST_REMOVE_PREFERENCES_FROM_CACHE_HELPER_0400
* @tc.name : testRemovePreferencesFromCacheHelper0004
* @tc.desc : RemovePreferencesFromCache interface test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testRemovePreferencesFromCacheHelper0004", 0, async function (done) {
let preferences = null;
preferences = await dataPreferences.getPreferences(context, NAME);
await preferences.put(KEY_TEST_STRING_ELEMENT, "test");
preferences.get(KEY_TEST_STRING_ELEMENT, "defaultvalue", function (err, ret) {
expect("test").assertEqual(ret);
});
dataPreferences
.removePreferencesFromCache(context, "test_preferences1")
.then(() => {
console.info("Succeeded in removing preferences.");
preferences.get(KEY_TEST_STRING_ELEMENT, "defaultvalue", function (err, pre) {
expect("test").assertEqual(pre);
done();
});
})
.catch((err) => {
console.info("Remove preferences from cache error: " + err);
expect(!err).assertTrue();
done();
});
});
/**
* @tc.number : SUB_DDM_TEST_PREFERENCES_DELETE_HELPER_0100
* @tc.name : testPreferencesDeleteHelper0001
* @tc.desc : DeletePreferences interface test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testPreferencesDeleteHelper0001", 0, async function (done) {
let preferences = null;
preferences = await dataPreferences.getPreferences(context, NAME);
const promise = dataPreferences.deletePreferences(context, NAME);
promise
.then(() => {
console.info("Succeeded in deleting preferences.");
expect("{}").assertEqual(JSON.stringify(preferences));
done();
})
.catch((err) => {
console.info("Delete preferences err: " + err);
expect(!err).assertTrue();
});
});
/**
* @tc.number : SUB_DDM_TEST_PREFERENCES_DELETE_HELPER_0400
* @tc.name : testPreferencesDeleteHelper0004
* @tc.desc : DeletePreferences interface test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testPreferencesDeleteHelper0004", 0, async function (done) {
let preferences = null;
preferences = await dataPreferences.getPreferences(context, NAME);
await preferences.put(KEY_TEST_STRING_ELEMENT, "test");
preferences.get(KEY_TEST_STRING_ELEMENT, "defaultvalue", function (err, ret) {
expect("test").assertEqual(ret);
});
dataPreferences
.deletePreferences(context, "test_preferences1")
.then(() => {
console.info("Succeeded in deleting preferences.");
preferences.get(KEY_TEST_STRING_ELEMENT, "defaultvalue", function (err, pre) {
expect("test").assertEqual(pre);
done();
});
})
.catch((err) => {
console.info("Delete preferences err: " + err);
expect(!err).assertTrue();
done();
});
});
/**
* @tc.number : SUB_DDM_TEST_MAX_KEY_LENGTH_0100
* @tc.name : testMaxKeyLength001
* @tc.desc : Test key length
* @tc.size : MediumTest
* @tc.type : Constant
* @tc.level : Level 0
*/
it("testMaxKeyLength001", 0, function () {
expect(dataPreferences.MAX_KEY_LENGTH == 80).assertTrue();
});
/**
* @tc.number : SUB_DDM_TEST_MAX_VALUE_LENGTH_0100
* @tc.name : testMaxValueLength001
* @tc.desc : Test value length
* @tc.size : MediumTest
* @tc.type : Constant
* @tc.level : Level 0
*/
it("testMaxValueLength001", 0, function () {
expect(dataPreferences.MAX_VALUE_LENGTH == 8192).assertTrue();
});
/**
* @tc.number : SUB_DDM_TEST_PREFERENCES_ON_0100
* @tc.name : testPreferencesOn001
* @tc.desc : Test on interface
* @tc.size : MediumTest
* @tc.type : Constant
* @tc.level : Level 2
*/
it("testPreferencesOn001", 0, async function () {
try {
await mPreferences.clear();
var observer = function (key) {
console.info("testPreferencesOn001 key " + key);
expect(KEY_TEST_STRING_ELEMENT).assertEqual(key);
};
mPreferences.on("change", observer);
await mPreferences.put(KEY_TEST_STRING_ELEMENT, "abcd");
await mPreferences.flush();
} catch (err) {
console.info("Failed to testPreferencesOn001. code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
});
/**
* @tc.number : SUB_DDM_TEST_PREFERENCES_ON_0200
* @tc.name : testPreferencesOn002
* @tc.desc : Test on interface
* @tc.size : MediumTest
* @tc.type : Constant
* @tc.level : Level 2
*/
it("testPreferencesOn002", 0, async function () {
try {
await mPreferences.clear();
var observer = function (key) {
console.info("testPreferencesOn002 key " + key);
expect(KEY_TEST_STRING_ELEMENT).assertEqual(key);
};
mPreferences.on("change");
} catch (err) {
console.info("Failed to testPreferencesOn002. code =" + err.code + ", message =" + err.message);
expect(err.code === "401" && err.message === "Parameter error. Need 2 parameters!").assertTrue();
}
});
/**
* @tc.number : SUB_DDM_TEST_PREFERENCES_ON_0300
* @tc.name : testPreferencesOn003
* @tc.desc : Test on interface
* @tc.size : MediumTest
* @tc.type : Constant
* @tc.level : Level 2
*/
it("testPreferencesOn003", 0, async function () {
try {
await mPreferences.clear();
var observer = function (key) {
console.info("testPreferencesOn003 key " + key);
expect(KEY_TEST_STRING_ELEMENT).assertEqual(key);
};
mPreferences.on(null, observer);
} catch (err) {
console.info("Failed to testPreferencesOn003. code =" + err.code + ", message =" + err.message);
expect(err.code === "401" && err.message === "Parameter error. The type of 'type' must be string 'change'.").assertTrue();
}
});
/**
* @tc.number : SUB_DDM_TEST_PREFERENCES_ON_0400
* @tc.name : testPreferencesOn004
* @tc.desc : Test on interface
* @tc.size : MediumTest
* @tc.type : Constant
* @tc.level : Level 2
*/
it("testPreferencesOn004", 0, async function () {
try {
await mPreferences.clear();
var observer = function (key) {
console.info("testPreferencesOn004 key " + key);
expect(KEY_TEST_STRING_ELEMENT).assertEqual(key);
};
mPreferences.on("", observer);
} catch (err) {
console.info("Failed to testPreferencesOn004. code =" + err.code + ", message =" + err.message);
expect(err.code === "401" && err.message === "Parameter error. The type of 'type' must be string 'change'.").assertTrue();
}
});
/**
* @tc.number : SUB_DDM_TEST_PREFERENCES_OFF_0100
* @tc.name : testPreferencesOff001
* @tc.desc : Test off interface
* @tc.size : MediumTest
* @tc.type : Constant
* @tc.level : Level 2
*/
it("testPreferencesOff001", 0, async function () {
try {
await mPreferences.clear();
let isTrigger = false;
var observer = function (key) {
console.info("testPreferencesOff001 key" + key);
isTrigger = true;
};
mPreferences.on("change", observer);
mPreferences.off("change", observer);
await mPreferences.put(KEY_TEST_STRING_ELEMENT, "abc");
await mPreferences.flush();
await sleep(1000);
expect(isTrigger === false).assertTrue();
} catch (err) {
console.info("Failed to testPreferencesOff001. code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
});
/**
* @tc.number : SUB_DDM_TEST_PREFERENCES_OFF_0200
* @tc.name : testPreferencesOff002
* @tc.desc : Test off interface
* @tc.size : MediumTest
* @tc.type : Constant
* @tc.level : Level 2
*/
it("testPreferencesOff002", 0, async function () {
try {
await mPreferences.clear();
let isTrigger = false;
var observer = function (key) {
console.info("testPreferencesOff001 key" + key);
isTrigger = true;
};
mPreferences.on("change", observer);
mPreferences.off("change");
await mPreferences.put(KEY_TEST_STRING_ELEMENT, "abc");
await mPreferences.flush();
await sleep(1000);
expect(isTrigger === false).assertTrue();
} catch (err) {
console.info("Failed to testPreferencesOff001. code =" + err.code + ", message =" + err.message);
expect(!err).assertTrue();
}
});
/**
* @tc.number : SUB_DDM_TEST_PREFERENCES_OFF_0300
* @tc.name : testPreferencesOff003
* @tc.desc : Test off interface
* @tc.size : MediumTest
* @tc.type : Constant
* @tc.level : Level 2
*/
it("testPreferencesOff003", 0, async function () {
try {
await mPreferences.clear();
let isTrigger = false;
var observer = function (key) {
console.info("testPreferencesOff003 key" + key);
isTrigger = true;
};
mPreferences.on("change", observer);
mPreferences.off(null);
} catch (err) {
console.info("Failed to testPreferencesOff003. code =" + err.code + ", message =" + err.message);
expect(err.code === "401" && err.message === "Parameter error. The type of 'type' must be string 'change'.").assertTrue();
}
});
/**
* @tc.number : SUB_DDM_TEST_PREFERENCES_OFF_0400
* @tc.name : testPreferencesOff004
* @tc.desc : Test off interface
* @tc.size : MediumTest
* @tc.type : Constant
* @tc.level : Level 2
*/
it("testPreferencesOff004", 0, async function () {
try {
await mPreferences.clear();
let isTrigger = false;
var observer = function (key) {
console.info("testPreferencesOff004 key" + key);
isTrigger = true;
};
mPreferences.on("change", observer);
mPreferences.off("");
} catch (err) {
console.info("Failed to testPreferencesOff004. code =" + err.code + ", message =" + err.message);
expect(err.code === "401" && err.message === "Parameter error. The type of 'type' must be string 'change'.").assertTrue();
}
});
});
}
/*
* Copyright (c) 2023 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.
*/
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from "@ohos/hypium";
import dataPreferences from "@ohos.data.preferences";
const NAME = "test_preferences";
const NAME1 = "getPreferencesTest";
let mPreferences;
let context;
const TAG = "[PREFERENCES_IGNORE_TEST]";
export default function preferencesIgnoreTest() {
describe("preferencesIgnoreTest", function () {
beforeAll(async function () {
console.info("beforeAll");
context = globalThis.abilityContext;
mPreferences = await dataPreferences.getPreferences(context, NAME);
});
afterAll(async function () {
console.info("afterAll");
await dataPreferences.deletePreferences(context, NAME);
});
/**
* @tc.number : SUB_DDM_TEST_PREFERENCES_GET_PREFERENCES_0100
* @tc.name : testPreferencesGetPreferences001
* @tc.desc : GetPreferences callback interface test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testPreferencesGetPreferences001", 0, async function (done) {
try {
// @ts-ignore
await dataPreferences.getPreferences(context, -1, (err, preferences) => {
if (err) {
console.info(TAG + "Get preferences err: " + err);
expect(!err).assertTrue();
done();
} else {
console.info(TAG + "Get preferences success" + preferences);
done();
}
});
} catch (err) {
console.info("testPreferencesGetPreferences001 fail: " + err.message + "code: " + err.code);
expect(err.code === "401" && err.message == "Parameter error. The type of 'name' must be a without path non empty string.").assertTrue();
done();
}
});
/**
* @tc.number : SUB_DDM_TEST_PREFERENCES_DELETE_PREFERENCES_0200
* @tc.name : testPreferencesDeletePreferences002
* @tc.desc : DeletePreferences callback interface test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testPreferencesDeletePreferences002", 0, async function (done) {
dataPreferences.getPreferences(context, NAME1, (err, preferences) => {
if (err) {
console.info(TAG + "Get preferences err: " + err);
expect(!err).assertTrue();
} else {
console.info(TAG + "Get preferences success");
expect(preferences !== null).assertTrue();
try {
// @ts-ignore
dataPreferences.deletePreferences(context, -1, (err) => {
if (err) {
console.info(TAG + "Delete preferences err: " + err);
expect(!err).assertTrue();
done();
}
});
} catch (err) {
console.info("testPreferencesDeletePreferences002 fail: " + err.message + "code: " + err.code);
expect(err.code === "401" && err.message === "Parameter error. The type of 'name' must be a without path non empty string.").assertTrue();
done();
}
}
});
});
/**
* @tc.number : SUB_DDM_TEST_REMOVE_PREFERENCES_FROM_CACHE_0200
* @tc.name : testRemovePreferencesFromCache002
* @tc.desc : RemovePreferencesFromCache callback interface test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testRemovePreferencesFromCache002", 0, async function (done) {
dataPreferences.getPreferences(context, NAME, (err, preferences) => {
if (err) {
console.info(TAG + "Get preferences err: " + err);
expect(!err).assertTrue();
} else {
console.info(TAG + "Get preferences success");
expect(preferences !== null).assertTrue();
try {
// @ts-ignore
dataPreferences.removePreferencesFromCache(context, -1, (err) => {
if (err) {
console.info(TAG + "Remove preferences from cache error: " + err);
expect(!err).assertTrue();
done();
}
});
} catch (err) {
console.info("testRemovePreferencesFromCache002 fail: " + err.message + "code: " + err.code);
expect(err.code === "401" && err.message === "Parameter error. The type of 'name' must be a without path non empty string.").assertTrue();
done();
}
}
});
});
/**
* @tc.number : SUB_DDM_TEST_GET_PREFERENCES_HELPER_0300
* @tc.name : testGetPreferencesHelper0003
* @tc.desc : GetPreferences interface test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testGetPreferencesHelper0003", 0, async function (done) {
try {
// @ts-ignore
await dataPreferences.getPreferences(context, -1);
} catch (err) {
console.info("testGetPreferencesHelper0003 fail: " + err.message + "code: " + err.code);
expect(err.code === "401" && err.message === "Parameter error. The type of 'name' must be a without path non empty string.").assertTrue();
done();
}
});
/**
* @tc.number : SUB_DDM_TEST_GET_PREFERENCES_HELPER_0400
* @tc.name : testGetPreferencesHelper0004
* @tc.desc : GetPreferences interface test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testGetPreferencesHelper0004", 0, async function (done) {
try {
// @ts-ignore
await dataPreferences.getPreferences(context);
} catch (err) {
console.info("testGetPreferencesHelper0004 fail: " + err.message + "code: " + err.code);
expect(err.code === "401" && err.message === "Parameter error. Need 2 or 3 parameters!").assertTrue();
done();
}
});
/**
* @tc.number : SUB_DDM_TEST_REMOVE_PREFERENCES_FROM_CACHE_HELPER_0200
* @tc.name : testRemovePreferencesFromCacheHelper0002
* @tc.desc : RemovePreferencesFromCache interface test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testRemovePreferencesFromCacheHelper0002", 0, async function (done) {
try {
await dataPreferences.getPreferences(context, NAME);
// @ts-ignore
await dataPreferences.removePreferencesFromCache(context);
} catch (err) {
console.info("testRemovePreferencesFromCacheHelper0002 fail: " + err.message + "code: " + err.code);
expect(err.code === "401" && err.message === "Parameter error. Need 2 or 3 parameters!").assertTrue();
done();
}
});
/**
* @tc.number : SUB_DDM_TEST_REMOVE_PREFERENCES_FROM_CACHE_HELPER_0300
* @tc.name : testRemovePreferencesFromCacheHelper0003
* @tc.desc : RemovePreferencesFromCache interface test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testRemovePreferencesFromCacheHelper0003", 0, async function (done) {
try {
await dataPreferences.getPreferences(context, NAME);
// @ts-ignore
await dataPreferences.removePreferencesFromCache(context, -1);
} catch (err) {
console.info("testRemovePreferencesFromCacheHelper0003 fail: " + err.message + "code: " + err.code);
expect(err.code === "401" && err.message === "Parameter error. The type of 'name' must be a without path non empty string.").assertTrue();
done();
}
});
/**
* @tc.number : SUB_DDM_TEST_PREFERENCES_DELETE_HELPER_0200
* @tc.name : testPreferencesDeleteHelper0002
* @tc.desc : DeletePreferences interface test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testPreferencesDeleteHelper0002", 0, async function (done) {
try {
await dataPreferences.getPreferences(context, NAME);
// @ts-ignore
await dataPreferences.deletePreferences(context);
} catch (err) {
console.info("testPreferencesDeleteHelper0002 fail: " + err.message + "code: " + err.code);
expect(err.code === "401" && err.message === "Parameter error. Need 2 or 3 parameters!").assertTrue();
done();
}
});
/**
* @tc.number : SUB_DDM_TEST_PREFERENCES_DELETE_HELPER_0300
* @tc.name : testPreferencesDeleteHelper0003
* @tc.desc : DeletePreferences interface test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testPreferencesDeleteHelper0003", 0, async function (done) {
try {
await dataPreferences.getPreferences(context, NAME);
// @ts-ignore
await dataPreferences.deletePreferences(context, -1);
} catch (err) {
console.info("testPreferencesDeleteHelper0003 fail: " + err.message + "code: " + err.code);
expect(err.code === "401" && err.message === "Parameter error. The type of 'name' must be a without path non empty string.").assertTrue();
done();
}
});
});
}
{
"module": {
"name": "preferences_test_normal_ets",
"type": "feature",
"description": "$string:module_test_desc",
"mainElement": "TestAbility",
"deviceTypes": [
"phone"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:test_pages",
"abilities": [
{
"name": "TestAbility",
"srcEntry": "./ets/TestAbility/TestAbility.ets",
"description": "$string:TestAbility_desc",
"icon": "$media:icon",
"label": "$string:TestAbility_label",
"exported": true,
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:start_window_background",
"skills": [
{
"actions": [
"action.system.home"
],
"entities": [
"entity.system.home"
]
}
]
}
]
}
}
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
}
]
}
\ No newline at end of file
{
"string": [
{
"name": "module_test_desc",
"value": "test ability description"
},
{
"name": "TestAbility_desc",
"value": "the test ability"
},
{
"name": "TestAbility_label",
"value": "test label"
}
]
}
\ No newline at end of file
{
"app": {
"bundleName": "ohos.acts.distributeddatamgr.crossplatform.relationalstore.normal",
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:app_icon",
"label": "$string:app_name",
"minAPIVersion": 10,
"targetAPIVersion": 10,
"car": {
"apiCompatibleVersion": 10,
"singleUser": false
}
}
}
# Copyright (C) 2023 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.
import("//test/xts/tools/build/suite.gni")
ohos_js_hap_suite("ActsCrossplatformRelationalStoreTest") {
hap_profile = "src/main/module.json"
deps = [
":windowStage_js_assets",
":windowStage_resources",
]
ets2abc = true
certificate_profile = "./signature/openharmony_sx.p7b"
# hap_name: HAP的名字,可选,默认为目标名
hap_name = "ActsCrossplatformRelationalStoreTest"
subsystem_name = "distributeddatamgr"
part_name = "relational_store"
}
ohos_app_scope("windowStage_app_profile") {
# app_profile: HAP的AppScope中的app.json,只在Stage模型下使用
app_profile = "AppScope/app.json"
# sources: 资源文件路径
sources = [ "AppScope/resources" ]
}
ohos_js_assets("windowStage_js_assets") {
# source_dir: js或ets代码路径,兼容FA模型的单ability配置到ability目录
source_dir = "src/main/ets"
}
ohos_resources("windowStage_resources") {
# sources: 资源文件路径
sources = [ "src/main/resources" ]
# deps: 当前目标的依赖
deps = [ ":windowStage_app_profile" ]
# hap_profile: HAP的config.json,Stage模型对应module.json
hap_profile = "src/main/module.json"
}
{
"description": "Configuration for hjunit demo Tests",
"driver": {
"type": "OHJSUnitTest",
"test-timeout": "60000",
"shell-timeout": "60000",
"bundle-name": "ohos.acts.distributeddatamgr.crossplatform.relationalstore.normal",
"module-name": "relationalstore_test_normal_ets"
},
"kits": [
{
"test-file-name": [
"ActsCrossplatformRelationalStoreTest.hap"
],
"type": "AppInstallKit",
"cleanup-apps": true
}
]
}
\ No newline at end of file
/*
* Copyright (C) 2023 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.
*/
import UIAbility from "@ohos.app.ability.UIAbility";
import AbilityDelegatorRegistry from "@ohos.app.ability.abilityDelegatorRegistry";
import hilog from "@ohos.hilog";
import { Hypium } from "@ohos/hypium";
import testsuite from "../test/List.test";
import window from "@ohos.window";
export default class TestAbility extends UIAbility {
onCreate(want, launchParam) {
hilog.info(0x0000, "testTag", "%{public}s", "TestAbility onCreate");
hilog.info(0x0000, "testTag", "%{public}s", "want param:" + JSON.stringify(want) ?? "");
hilog.info(0x0000, "testTag", "%{public}s", "launchParam:" + JSON.stringify(launchParam) ?? "");
var abilityDelegator: any;
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
var abilityDelegatorArguments: any;
abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments();
hilog.info(0x0000, "testTag", "%{public}s", "start run testcase!!!");
Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite);
}
onDestroy() {
hilog.info(0x0000, "testTag", "%{public}s", "TestAbility onDestroy");
}
onWindowStageCreate(windowStage: window.WindowStage) {
hilog.info(0x0000, "testTag", "%{public}s", "TestAbility onWindowStageCreate");
globalThis.abilityContext = this.context;
windowStage.loadContent("TestAbility/pages/Index", (err, data) => {
if (err.code) {
hilog.error(0x0000, "testTag", "Failed to load the content. Cause: %{public}s", JSON.stringify(err) ?? "");
return;
}
hilog.info(0x0000, "testTag", "Succeeded in loading the content. Data: %{public}s", JSON.stringify(data) ?? "");
});
}
onWindowStageDestroy() {
hilog.info(0x0000, "testTag", "%{public}s", "TestAbility onWindowStageDestroy");
}
onForeground() {
hilog.info(0x0000, "testTag", "%{public}s", "TestAbility onForeground");
}
onBackground() {
hilog.info(0x0000, "testTag", "%{public}s", "TestAbility onBackground");
}
}
/*
* Copyright (C) 2023 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.
*/
import hilog from '@ohos.hilog';
@Entry
@Component
struct Index {
aboutToAppear() {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear');
}
@State message: string = 'Hello World'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
Button() {
Text('next page')
.fontSize(20)
.fontWeight(FontWeight.Bold)
}.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('35%')
.height('5%')
.onClick(()=>{
})
}
.width('100%')
}
.height('100%')
}
}
\ No newline at end of file
import hilog from '@ohos.hilog';
import TestRunner from '@ohos.application.testRunner';
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
var abilityDelegator = undefined
var abilityDelegatorArguments = undefined
async function onAbilityCreateCallback() {
hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback');
}
async function addAbilityMonitorCallback(err: any) {
hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
}
export default class OpenHarmonyTestRunner implements TestRunner {
constructor() {
}
onPrepare() {
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare ');
}
async onRun() {
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run');
abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility'
let lMonitor = {
abilityName: testAbilityName,
onAbilityCreate: onAbilityCreateCallback,
};
abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName
var debug = abilityDelegatorArguments.parameters['-D']
if (debug == 'true')
{
cmd += ' -D'
}
hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd);
abilityDelegator.executeShellCommand(cmd,
(err: any, d: any) => {
hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? '');
hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.stdResult ?? '');
hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.exitCode ?? '');
})
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end');
}
}
\ No newline at end of file
/*
* Copyright (C) 2023 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.
*/
import RdbPredicates from './RdbPredicates.test'
import ResultSet from './ResultSet.test'
import RdbStoreInsert from './RdbStoreInsert.test'
import RdbStoreUpdate from './RdbStoreUpdate.test'
import RdbStoreDelete from './RdbStoreDelete.test'
import RdbStoreQuery from './RdbStoreQuery.test'
import RdbStoreQuerySql from './RdbStoreQuerySql.test'
import RdbStoreExecuteSql from './RdbStoreExecuteSql.test'
import RdbStoreTransaction from './RdbStoreTransaction.test'
import RdbStoreBackupRestore from './RdbStoreBackupRestore.test'
import RelationalStore from './RelationalStore.test'
export default function testsuite() {
RdbPredicates()
ResultSet()
RdbStoreInsert()
RdbStoreUpdate()
RdbStoreDelete()
RdbStoreQuery()
RdbStoreQuerySql()
RdbStoreExecuteSql()
RdbStoreTransaction()
RdbStoreBackupRestore()
RelationalStore()
}
\ No newline at end of file
/*
* Copyright (C) 2023 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.
*/
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from "@ohos/hypium";
import relationalStore from "@ohos.data.relationalStore";
const TAG = "[RDB_JSKITS_TEST]";
const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS backupTest (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)";
let RdbStore = undefined;
let context = null;
const STORE_CONFIG = {
name: "BackupResotreTest.db",
securityLevel: relationalStore.SecurityLevel.S1,
};
const DATABASE_BACKUP_NAME = "Backup.db";
async function CreatRdbStore(context, STORE_CONFIG) {
context = globalThis.abilityContext;
let RdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG);
await RdbStore.executeSql(CREATE_TABLE_TEST, null);
let u8 = new Uint8Array([1, 2, 3]);
{
const valueBucket = {
name: "zhangsan",
age: 18,
salary: 100.5,
blobType: u8,
};
await RdbStore.insert("backupTest", valueBucket);
}
{
const valueBucket = {
name: "lisi",
age: 28,
salary: 100.5,
blobType: u8,
};
await RdbStore.insert("backupTest", valueBucket);
}
{
const valueBucket = {
name: "wangwu",
age: 38,
salary: 90.0,
blobType: u8,
};
await RdbStore.insert("backupTest", valueBucket);
}
return RdbStore;
}
export default function RdbStoreBackupRestoreCallbackTest() {
describe("RdbStoreBackupRestoreCallbackTest", function () {
beforeAll(async function () {
console.info(TAG + "beforeAll");
});
beforeEach(async function () {
console.info(TAG + "beforeEach");
RdbStore = await CreatRdbStore(context, STORE_CONFIG);
});
afterEach(async function () {
console.info(TAG + "afterEach");
context = globalThis.abilityContext;
await relationalStore.deleteRdbStore(context, STORE_CONFIG.name);
await relationalStore.deleteRdbStore(context, DATABASE_BACKUP_NAME);
await relationalStore.deleteRdbStore(context, "BackupTest003.db");
});
afterAll(async function () {
console.info(TAG + "afterAll");
});
console.info(TAG + "*************Unit Test Begin*************");
/**
* @tc.number : SUB_DDM_TEST_RDB_STORE_BACKUP_RESTORE_0100
* @tc.name : testRdbStoreBackupRestore001
* @tc.desc : RdbStore backup and restore callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testRdbStoreBackupRestore001", 0, async function (done) {
console.info(TAG + "************* testRdbStoreBackupRestore001 start *************");
RdbStore.backup(DATABASE_BACKUP_NAME, async (err) => {
if (err) {
console.info(TAG + "backup err ttt: " + err);
expect(!err).assertTrue();
} else {
console.info(`Backup success.`);
let deleteData = new relationalStore.RdbPredicates("backupTest");
deleteData.equalTo("name", "zhangsan");
await RdbStore.delete(deleteData);
RdbStore.restore(DATABASE_BACKUP_NAME, async (err) => {
if (err) {
expect(!err).assertTrue();
} else {
let predicates = new relationalStore.RdbPredicates("backupTest");
predicates.equalTo("name", "zhangsan");
let resultSet = await RdbStore.query(predicates);
try {
console.info(TAG + "After restore resultSet query done");
expect(true).assertEqual(resultSet.goToFirstRow());
const id = resultSet.getLong(resultSet.getColumnIndex("id"));
const name = resultSet.getString(resultSet.getColumnIndex("name"));
const blobType = resultSet.getBlob(resultSet.getColumnIndex("blobType"));
expect(1).assertEqual(id);
expect("zhangsan").assertEqual(name);
expect(1).assertEqual(blobType[0]);
resultSet.close();
done();
} catch (err) {
expect(!err).assertTrue();
}
resultSet = null;
RdbStore = null;
}
console.info(TAG + "************* testRdbStoreBackupRestore001 end *************");
});
}
});
});
/**
* @tc.number : SUB_DDM_TEST_RDB_STORE_BACKUP_RESTORE_0200
* @tc.name : testRdbStoreBackupRestore002
* @tc.desc : RdbStore backup and restore promise test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testRdbStoreBackupRestore002", 0, async function (done) {
console.info(TAG + "************* testRdbStoreBackupRestore002 start *************");
let promiseBackup = RdbStore.backup(DATABASE_BACKUP_NAME);
promiseBackup
.then(async () => {
console.info(`Backup success.`);
let deleteData = new relationalStore.RdbPredicates("backupTest");
deleteData.equalTo("name", "zhangsan");
await RdbStore.delete(deleteData);
let promiseRestore = RdbStore.restore(DATABASE_BACKUP_NAME);
promiseRestore
.then(async () => {
console.info(`Restore success.`);
let predicates = new relationalStore.RdbPredicates("backupTest");
predicates.equalTo("name", "zhangsan");
let resultSet = await RdbStore.query(predicates);
try {
console.info(TAG + "After restore resultSet query done");
expect(true).assertEqual(resultSet.goToFirstRow());
const id = resultSet.getLong(resultSet.getColumnIndex("id"));
const name = resultSet.getString(resultSet.getColumnIndex("name"));
const blobType = resultSet.getBlob(resultSet.getColumnIndex("blobType"));
expect(1).assertEqual(id);
expect("zhangsan").assertEqual(name);
expect(1).assertEqual(blobType[0]);
resultSet.close();
done();
} catch (err) {
console.info(TAG + "testRdbStoreBackupRestore002 error: " + err);
expect(!err).assertTrue();
}
resultSet = null;
RdbStore = null;
console.info(TAG + "************* testRdbStoreBackupRestore002 end *************");
})
.catch((err) => {
console.info(TAG + "Restore error: " + err);
expect(!err).assertTrue();
});
})
.catch((err) => {
console.info(TAG + "Backup error: " + err);
expect(!err).assertTrue();
});
});
/**
* @tc.number : SUB_DDM_TEST_RDB_STORE_BACKUP_0100
* @tc.name : testRdbStoreBackup001
* @tc.desc : RdbStore backup callback test: file name empty
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testRdbStoreBackup001", 0, async function (done) {
console.info(TAG + "************* testRdbStoreBackup001 start *************");
try {
RdbStore.backup("", async (err) => {
console.info(`Backup success.`);
expect(!err).assertTrue();
done();
});
} catch (errInfo) {
console.info(TAG + "testRdbStoreBackup001 error: " + errInfo);
expect(errInfo == "Error: Parameter error. The table must be not empty").assertTrue();
done();
}
console.info(TAG + "************* testRdbStoreBackup001 end *************");
});
/**
* @tc.number : SUB_DDM_TEST_RDB_STORE_BACKUP_0200
* @tc.name : testRdbStoreBackup002
* @tc.desc : RdbStore backup callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testRdbStoreBackup002", 0, async function (done) {
console.info(TAG + "************* testRdbStoreBackup002 start *************");
try {
RdbStore.backup(STORE_CONFIG.name, async (err) => {
console.info(TAG + "backup err ttt: " + err.message + "code: " + err.code);
expect(err.code == 14800011 && err.message == "Failed to open database by database corrupted").assertTrue();
done();
});
} catch (errInfo) {
console.info(TAG + "testRdbStoreBackup002 error: " + errInfo);
expect(!errInfo).assertTrue();
done();
}
console.info(TAG + "************* testRdbStoreBackup002 end *************");
});
/**
* @tc.number : SUB_DDM_TEST_RDB_STORE_BACKUP_0300
* @tc.name : testRdbStoreBackup003
* @tc.desc : RdbStore backup promise test: file name empty
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testRdbStoreBackup003", 0, async function (done) {
console.info(TAG + "************* testRdbStoreBackup003 start *************");
try {
await RdbStore.backup("");
done();
} catch (errInfo) {
console.info(TAG + "testRdbStoreBackup003 error: " + errInfo);
console.info(`Backup err: file name empty.`);
expect(errInfo == "Error: Parameter error. The table must be not empty").assertTrue();
done();
}
console.info(TAG + "************* testRdbStoreBackup003 end *************");
});
/**
* @tc.number : SUB_DDM_TEST_RDB_STORE_BACKUP_0400
* @tc.name : testRdbStoreBackup004
* @tc.desc : RdbStore backup promise test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testRdbStoreBackup004", 0, async function (done) {
console.info(TAG + "************* testRdbStoreBackup004 start *************");
try {
let promiseBackup = RdbStore.backup(STORE_CONFIG.name);
promiseBackup
.then(() => {
console.info(`Backup success.`);
done();
})
.catch((err) => {
console.info(TAG + "backup err ttt1: " + err.message + "code: " + err.code);
expect(err.code == 14800011 && err.message == "Failed to open database by database corrupted").assertTrue();
done();
});
} catch (err) {
console.info(TAG + "testRdbStoreBackup004 error: " + err.message + "code: " + err.code);
expect(!err).assertTrue();
done();
}
console.info(TAG + "************* testRdbStoreBackup004 end *************");
});
/**
* @tc.number : SUB_DDM_TEST_RDB_STORE_RESTORE_0100
* @tc.name : testRdbStoreRestore001
* @tc.desc : RdbStore retore callback test: file name empty
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testRdbStoreRestore001", 0, async function (done) {
console.info(TAG + "************* testRdbStoreRestore001 start *************");
let backupName = "BackupTest003.db";
await RdbStore.backup(backupName);
try {
RdbStore.restore("", async (err) => {
console.info(`restore success.`);
expect(!err).assertTrue();
done();
});
} catch (errInfo) {
console.info(TAG + "testRdbStoreRestore001 error: " + errInfo);
expect(errInfo == "Error: Parameter error. The srcName must be not empty").assertTrue();
done();
}
console.info(TAG + "************* testRdbStoreRestore001 end *************");
});
/**
* @tc.number : SUB_DDM_TEST_RDB_STORE_RESTORE_0200
* @tc.name : testRdbStoreRestore002
* @tc.desc : RdbStore retore callback test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testRdbStoreRestore002", 0, async function (done) {
console.info(TAG + "************* testRdbStoreRestore002 start *************");
let backupName = "BackupTest003.db";
await RdbStore.backup(backupName);
try {
RdbStore.restore(STORE_CONFIG.name, async (err) => {
expect(err !== null).assertTrue();
console.info(TAG + "restore err ttt: " + err);
console.info(`Restore err: file name wrong.`);
done();
});
} catch (errInfo) {
console.info(TAG + "testRdbStoreRestore002 error: " + errInfo);
expect(!errInfo).assertTrue();
}
console.info(TAG + "************* testRdbStoreRestore002 end *************");
});
/**
* @tc.number : SUB_DDM_TEST_RDB_STORE_RESTORE_0300
* @tc.name : testRdbStoreRestore003
* @tc.desc : RdbStore retore promise test: file name empty
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testRdbStoreRestore003", 0, async function (done) {
console.info(TAG + "************* testRdbStoreRestore003 start *************");
let backupName = "BackupTest003.db";
await RdbStore.backup(backupName);
try {
await RdbStore.retore("");
done();
} catch (errInfo) {
console.info(TAG + "testRdbStoreRestore003 error: " + errInfo);
console.info(`retore err: file name empty.`);
expect(errInfo == "TypeError: is not callable").assertTrue();
done();
}
console.info(TAG + "************* testRdbStoreRestore003 end *************");
});
/**
* @tc.number : SUB_DDM_TEST_RDB_STORE_RESTORE_0400
* @tc.name : testRdbStoreRestore004
* @tc.desc : RdbStore retore promise test
* @tc.size : MediumTest
* @tc.type : Function
* @tc.level : Level 2
*/
it("testRdbStoreRestore004", 0, async function (done) {
console.info(TAG + "************* testRdbStoreRestore004 start *************");
let backupName = "BackupTest003.db";
await RdbStore.backup(backupName);
try {
await RdbStore.retore(STORE_CONFIG.name);
done();
} catch (errInfo) {
console.info(TAG + "testRdbStoreRestore004 error: " + errInfo);
console.info(`Restore err: file name wrong.`);
expect(errInfo == "TypeError: is not callable").assertTrue();
done();
}
console.info(TAG + "************* testRdbStoreRestore004 end *************");
});
});
}
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
}
]
}
\ No newline at end of file
{
"string": [
{
"name": "module_test_desc",
"value": "test ability description"
},
{
"name": "TestAbility_desc",
"value": "the test ability"
},
{
"name": "TestAbility_label",
"value": "test label"
}
]
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册