提交 4ff1b7fb 编写于 作者: Y yangbo

fix errcode case

Signed-off-by: Nyangbo <yangbo258@h-partners.com>
上级 5c49f339
......@@ -55,6 +55,10 @@ group("multimedia") {
"medialibrary/mediaLibrary_getThumbnail:mediaLibrary_getThumbnail_hap",
"medialibrary/mediaLibrary_mediafetchoptions:mediaLibrary_mediafetchoptions_hap",
"medialibrary/mediaLibrary_trash:mediaLibrary_trash_js_hap",
"userfilemgr/userfilemgr_album:userfilemgr_album_js_hap",
"userfilemgr/userfilemgr_base:userfilemgr_base_js_hap",
"userfilemgr/userfilemgr_fileAsset:userfilemgr_fileAsset_js_hap",
"userfilemgr/userfilemgr_noPermission:userfilemgr_noPermission_js_hap",
]
} else {
deps = [
......
......@@ -17,7 +17,6 @@ import userFileManager from '@ohos.filemanagement.userFileManager';
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import bundle from '@ohos.bundle';
import dataSharePredicates from '@ohos.data.dataSharePredicates';
import mediaLibrary from '@ohos.multimedia.mediaLibrary';
const presetsCount = {
ActsUserFileMgrAlbumJsTest: { albumsCount: 3, assetsCount: 3 },
......@@ -32,7 +31,7 @@ const AUDIO_TYPE = userFileManager.FileType.AUDIO;
const AUDIOKEY = userFileManager.AudioKey;
const IMAGEVIDEOKEY = userFileManager.ImageVideoKey;
const ALBUMKEY = userFileManager.AlbumKey;
const FILEKEY = mediaLibrary.FileKey;
const THROW_ERROR_CODE = 13900020;
const sleep = async function sleep(times) {
if (times == undefined) {
times = 10
......@@ -50,58 +49,58 @@ const allFetchOp = function () {
const audioFetchOps = function (testNum, path) {
let predicates = new dataSharePredicates.DataSharePredicates();
predicates.equalTo(FILEKEY.RELATIVE_PATH, path);
predicates.equalTo("relative_path", path);
let ops = {
fetchColumns: [],
predicates: predicates
};
console.info(`${testNum} queryOps: ${FILEKEY.RELATIVE_PATH} = ${path}`);
console.info(`${testNum} queryOps: relative_path = ${path}`);
return ops
}
const imageVideoFetchOps = function (testNum, path) {
let predicates = new dataSharePredicates.DataSharePredicates();
predicates.equalTo(FILEKEY.RELATIVE_PATH, path);
predicates.equalTo("relative_path", path);
let ops = {
fetchColumns: [],
predicates: predicates
};
console.info(`${testNum} queryOps: ${FILEKEY.RELATIVE_PATH} = ${path}`);
console.info(`${testNum} queryOps: relative_path = ${path}`);
return ops
}
const audioNameFetchOps = function (testNum, path, displayName) {
let predicates = new dataSharePredicates.DataSharePredicates();
predicates.equalTo(FILEKEY.RELATIVE_PATH, path)
predicates.equalTo("relative_path", path)
.equalTo(AUDIOKEY.DISPLAY_NAME, displayName);
let ops = {
fetchColumns: [],
predicates: predicates
};
console.info(`${testNum} queryOps: ${FILEKEY.RELATIVE_PATH} = ${path} AND display_name = ${displayName}`);
console.info(`${testNum} queryOps: relative_path = ${path} AND display_name = ${displayName}`);
return ops
}
const imageVideoNameFetchOps = function (testNum, path, displayName) {
let predicates = new dataSharePredicates.DataSharePredicates();
predicates.equalTo(FILEKEY.RELATIVE_PATH, path)
predicates.equalTo("relative_path", path)
.equalTo(IMAGEVIDEOKEY.DISPLAY_NAME, displayName);
let ops = {
fetchColumns: [],
predicates: predicates
};
console.info(`${testNum} queryOps: ${FILEKEY.RELATIVE_PATH} = ${path} AND display_name = ${displayName}`);
console.info(`${testNum} queryOps: relative_path = ${path} AND display_name = ${displayName}`);
return ops
}
const albumFetchOps = function (testNum, path, albumName) {
let predicates = new dataSharePredicates.DataSharePredicates();
predicates.equalTo(FILEKEY.RELATIVE_PATH, path)
.equalTo("bucket_display_name", albumName);
predicates.equalTo("relative_path", path)
.equalTo(ALBUMKEY.ALBUM_NAME, albumName);
let ops = {
predicates: predicates
};
console.info(`${testNum} queryOps: ${FILEKEY.RELATIVE_PATH} = ${path} AND bucket_display_name = ${albumName}`);
console.info(`${testNum} queryOps: relative_path = ${path} AND bucket_display_name = ${albumName}`);
return ops
}
......@@ -170,6 +169,7 @@ export {
IMAGE_TYPE,
VIDEO_TYPE,
AUDIO_TYPE,
THROW_ERROR_CODE,
sleep,
allFetchOp,
audioFetchOps,
......
......@@ -14,10 +14,10 @@
*/
import userFileManager from '@ohos.filemanagement.userFileManager';
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index';
import dataSharePredicates from '@ohos.data.dataSharePredicates';
import {
sleep,
THROW_ERROR_CODE,
allFetchOp,
albumFetchOps,
checkPresetsAssets,
......@@ -69,6 +69,32 @@ export default function albumGetFileAssetsCallback(abilityContext) {
}
}
const getPhotoAssetsErrCodeTest = async function (done, testNum, fetchOp, expectAlbumCount = 1, expectAssetsCount = 1) {
try {
const fetchAlbumResult = await userfilemgr.getPhotoAlbums(fetchOp);
const albumCountPass = await checkAssetsCount(done, testNum, fetchAlbumResult, expectAlbumCount);
if (!albumCountPass) return;
const album = await fetchAlbumResult.getFirstObject();
fetchAlbumResult.close();
let invalidOps : userFileManager.FetchOptions;
album.getPhotoAssets(invalidOps, (error, fetchAssetResult) => {
if (error != undefined) {
console.info(`${testNum} getPhotoAssetsErrCodeTest error: ${error}`);
expect(false).assertTrue();
done();
return;
}
expect(false).assertTrue();
fetchAssetResult.close();
done();
});
} catch (error) {
console.info(`${testNum}, errCode :${JSON.stringify(error)}`);
expect(error.code).assertEqual(THROW_ERROR_CODE.toString());
done();
}
}
/**
* @tc.number : SUB_USERFILE_MGR_ALBUM_GETPHOTOASSETS_CALLBACK_01
* @tc.name : getPhotoAssets
......@@ -82,5 +108,19 @@ export default function albumGetFileAssetsCallback(abilityContext) {
let currentFetchOp = albumFetchOps(testNum, 'Pictures/', 'Static');
await getPhotoAssetsTest(done, testNum, currentFetchOp);
});
/**
* @tc.number : SUB_USERFILE_MGR_ALBUM_GETPHOTOASSETS_ERRCODE_CALLBACK_01
* @tc.name : getPhotoAssets
* @tc.desc : invalid AlbumFetchOptions
* @tc.size : MEDIUM
* @tc.type : Function
* @tc.level : Level 0
*/
it('SUB_USERFILE_MGR_ALBUM_GETPHOTOASSETS_ERRCODE_CALLBACK_01', 0, async function (done) {
const testNum = 'SUB_USERFILE_MGR_ALBUM_GETPHOTOASSETS_ERRCODE_CALLBACK_01';
let currentFetchOp = albumFetchOps(testNum, 'Pictures/', 'Static');
await getPhotoAssetsErrCodeTest(done, testNum, currentFetchOp);
});
});
}
\ No newline at end of file
......@@ -16,10 +16,10 @@
import userFileManager from '@ohos.filemanagement.userFileManager';
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index';
import dataSharePredicates from '@ohos.data.dataSharePredicates';
import {
sleep,
THROW_ERROR_CODE,
allFetchOp,
albumFetchOps,
checkPresetsAssets,
......@@ -70,6 +70,25 @@ export default function albumGetFileAssetsPromise(abilityContext) {
}
}
const getPhotoAssetsErrCodeTest = async function (done, testNum, fetchOp, expectAlbumCount = 1, expectAssetsCount = 1) {
try {
const fetchAlbumResult = await userfilemgr.getPhotoAlbums(fetchOp);
const albumCountPass = await checkAssetsCount(done, testNum, fetchAlbumResult, expectAlbumCount);
if (!albumCountPass) return;
const album = await fetchAlbumResult.getFirstObject();
fetchAlbumResult.close();
let invalidOps : userFileManager.FetchOptions;
let fetchAssetResult = await album.getPhotoAssets(invalidOps);
expect(false).assertTrue();
fetchAssetResult.close();
done();
} catch (error) {
console.info(`${testNum}, errCode :${JSON.stringify(error)}`);
expect(error.code).assertEqual(THROW_ERROR_CODE.toString());
done();
}
}
/**
* @tc.number : SUB_USERFILE_MGR_ALBUM_GETPHOTOASSETS_PROMISE_01
* @tc.name : getPhotoAssets
......@@ -83,5 +102,19 @@ export default function albumGetFileAssetsPromise(abilityContext) {
let currentFetchOp = albumFetchOps(testNum, 'Pictures/', 'Static');
await getPhotoAssetsTest(done, testNum, currentFetchOp);
});
/**
* @tc.number : SUB_USERFILE_MGR_ALBUM_GETPHOTOASSETS_ERRCODE_PROMISE_01
* @tc.name : getPhotoAssets
* @tc.desc : invalid AlbumFetchOptions
* @tc.size : MEDIUM
* @tc.type : Function
* @tc.level : Level 0
*/
it('SUB_USERFILE_MGR_ALBUM_GETPHOTOASSETS_ERRCODE_PROMISE_01', 0, async function (done) {
const testNum = 'SUB_USERFILE_MGR_ALBUM_GETPHOTOASSETS_ERRCODE_PROMISE_01';
let currentFetchOp = albumFetchOps(testNum, 'Pictures/', 'Static');
await getPhotoAssetsErrCodeTest(done, testNum, currentFetchOp);
});
});
}
\ No newline at end of file
......@@ -18,6 +18,7 @@ import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from
import {
sleep,
THROW_ERROR_CODE,
albumFetchOps,
checkPresetsAssets,
checkAssetsCount,
......@@ -107,6 +108,27 @@ export default function getAlbumsCallbackTest(abilityContext) {
}
}
const getPhotoAlbumsErrCodeTest = async function (done, testNum) {
try {
let invalidOps : userFileManager.FetchOptions;
userfilemgr.getPhotoAlbums(invalidOps, async (err, fetchAlbumResult) => {
if(err) {
console.info(`${testNum} getPhotoAlbums err: ${err}`)
expect(false).assertTrue();
done();
return;
}
expect(false).assertTrue();
fetchAlbumResult.close();
done();
});
} catch (error) {
console.info(`${testNum}, errCode :${JSON.stringify(error)}`);
expect(error.code).assertEqual(THROW_ERROR_CODE.toString());
done();
}
}
/**
* @tc.number : SUB_USERFILE_MGR_GETPHOTOALBUMS_CALLBACK_01
* @tc.name : getPhotoAlbums
......@@ -121,6 +143,19 @@ export default function getAlbumsCallbackTest(abilityContext) {
let relativePaths = 'Pictures/';
await checkAlbumInfo(done, testNum, currentFetchOp, relativePaths);
});
/**
* @tc.number : SUB_USERFILE_MGR_GETPHOTOALBUMS_ERRCODE_CALLBACK_01
* @tc.name : getPhotoAlbums
* @tc.desc : getPhotoAlbums by invalid
* @tc.size : MEDIUM
* @tc.type : Function
* @tc.level : Level 0
*/
it('SUB_USERFILE_MGR_GETPHOTOALBUMS_ERRCODE_CALLBACK_01', 0, async function (done) {
let testNum = 'SUB_USERFILE_MGR_GETPHOTOALBUMS_ERRCODE_CALLBACK_01';
await getPhotoAlbumsErrCodeTest(done, testNum);
});
});
}
......
......@@ -18,6 +18,7 @@ import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from
import {
sleep,
THROW_ERROR_CODE,
albumFetchOps,
checkPresetsAssets,
checkAssetsCount,
......@@ -94,6 +95,20 @@ export default function getAlbumsPromiseTest(abilityContext) {
}
}
const getPhotoAlbumsErrCodeTest = async function (done, testNum) {
try {
let invalidOps : userFileManager.FetchOptions;
let fetchAlbumResult = await userfilemgr.getPhotoAlbums(invalidOps);
expect(false).assertTrue();
fetchAlbumResult.close();
done();
} catch (error) {
console.info(`${testNum}, errCode :${JSON.stringify(error)}`);
expect(error.code).assertEqual(THROW_ERROR_CODE.toString());
done();
}
}
/**
* @tc.number : SUB_USERFILE_MGR_GETPHOTOALBUMS_PROMISE_01
* @tc.name : getPhotoAlbums
......@@ -108,6 +123,19 @@ export default function getAlbumsPromiseTest(abilityContext) {
let relativePaths = 'Pictures/';
await checkAlbumInfo(done, testNum, currentFetchOp, relativePaths);
});
/**
* @tc.number : SUB_USERFILE_MGR_GETPHOTOALBUMS_ERRCODE_PROMISE_01
* @tc.name : getPhotoAlbums
* @tc.desc : getPhotoAlbums by invalid
* @tc.size : MEDIUM
* @tc.type : Function
* @tc.level : Level 0
*/
it('SUB_USERFILE_MGR_GETPHOTOALBUMS_ERRCODE_PROMISE_01', 0, async function (done) {
let testNum = 'SUB_USERFILE_MGR_GETPHOTOALBUMS_ERRCODE_PROMISE_01';
await getPhotoAlbumsErrCodeTest(done, testNum);
});
});
}
......
......@@ -20,6 +20,7 @@ import {
IMAGE_TYPE,
VIDEO_TYPE,
AUDIO_TYPE,
THROW_ERROR_CODE,
audioFetchOps,
imageVideoFetchOps,
checkPresetsAssets,
......@@ -190,7 +191,7 @@ export default function getFileAssetsCallbackTest(abilityContext) {
let expectCount = 4;
let checkAssetCountPass = await checkAssetsCount(done, testNum, fetchAssetResult, expectCount);
if (!checkAssetCountPass) return;
fetchAssetResult.getFirstObject(async (err, asset) => {
fetchAssetResult.getFirstObject((err, asset) => {
if (err) {
console.info(`${testNum} err : ${err}`)
expect.assertFail();
......@@ -199,6 +200,7 @@ export default function getFileAssetsCallbackTest(abilityContext) {
return;
}
expect(asset.displayName).assertEqual(props[type].displayName);
expect(asset.fileType.toString()).assertEqual(props[type].fileType);
expect(asset.uri != undefined).assertTrue();
fetchAssetResult.close();
done();
......@@ -210,6 +212,39 @@ export default function getFileAssetsCallbackTest(abilityContext) {
}
}
async function getFileAssetsErrCodeTest(done, testNum, isAudio) {
try {
let invalidOps : userFileManager.FetchOptions;
if (isAudio) {
await userfilemgr.getAudioAssets(invalidOps, (err, fetchAssetResult) => {
if (err != undefined) {
console.info(`${testNum}:: getAudioAssets error :${err}`);
expect(false).assertTrue();
done();
return;
}
expect(false).assertTrue();
done();
})
} else {
await userfilemgr.getPhotoAssets(invalidOps, (err, fetchAssetResult) => {
if (err != undefined) {
console.info(`${testNum}:: getAudioAssets error :${err}`);
expect(false).assertTrue();
done();
return;
}
expect(false).assertTrue();
done();
})
}
} catch (error) {
console.info(`${testNum}:: errCode :${JSON.stringify(error)}`);
expect(error.code).assertEqual(THROW_ERROR_CODE.toString());
done();
}
}
/**
* @tc.number : SUB_USERFILE_MGR_GETPHOTOASSETS_CALLBACK_01_001
* @tc.name : getFirstObject
......@@ -352,7 +387,7 @@ export default function getFileAssetsCallbackTest(abilityContext) {
await getPositionObjectTest(done, testNum, currentFetchOps, pos, isAudio);
});
//------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------
/**
* @tc.number : SUB_USERFILE_MGR_GETPHOTOASSETS_CALLBACK_04_001
......@@ -448,6 +483,36 @@ export default function getFileAssetsCallbackTest(abilityContext) {
let isAudio = false;
await checkFileAssetAttr(done, testNum, currentFetchOps, type, isAudio);
});
//------------------------------------------------------------------------------
/**
* @tc.number : SUB_USERFILE_MGR_GETPHOTOASSETS_ERRCODE_CALLBACK_01
* @tc.name : getPhotoAssets
* @tc.desc : invalid FetchOptions
* @tc.size : MEDIUM
* @tc.type : Function
* @tc.level : Level 0
*/
it('SUB_USERFILE_MGR_GETPHOTOASSETS_ERRCODE_CALLBACK_01', 0, async function (done) {
let testNum = 'SUB_USERFILE_MGR_GETPHOTOASSETS_ERRCODE_CALLBACK_01';
let isAudio = false;
await getFileAssetsErrCodeTest(done, testNum, isAudio);
});
/**
* @tc.number : SUB_USERFILE_MGR_GETPHOTOASSETS_ERRCODE_CALLBACK_02
* @tc.name : getPhotoAssets
* @tc.desc : invalid FetchOptions
* @tc.size : MEDIUM
* @tc.type : Function
* @tc.level : Level 0
*/
it('SUB_USERFILE_MGR_GETPHOTOASSETS_ERRCODE_CALLBACK_02', 0, async function (done) {
let testNum = 'SUB_USERFILE_MGR_GETPHOTOASSETS_ERRCODE_CALLBACK_02';
let isAudio = true;
await getFileAssetsErrCodeTest(done, testNum, isAudio);
});
});
}
......@@ -20,9 +20,9 @@ import {
IMAGE_TYPE,
VIDEO_TYPE,
AUDIO_TYPE,
THROW_ERROR_CODE,
checkPresetsAssets,
checkAssetsCount,
allFetchOp,
audioFetchOps,
imageVideoFetchOps,
} from '../../../../../../common';
......@@ -166,18 +166,12 @@ export default function getFileAssetsPromiseTest(abilityContext) {
let expectCount = 4;
let checkAssetCountPass = await checkAssetsCount(done, testNum, fetchAssetResult, expectCount);
if (!checkAssetCountPass) return;
fetchAssetResult.getFirstObject(async (err, asset) => {
if (err) {
console.info(`${testNum} err : ${err}`)
expect.assertFail();
fetchAssetResult.close();
done();
return;
}
let asset = await fetchAssetResult.getFirstObject();
expect(asset.displayName).assertEqual(props[type].displayName);
expect(asset.fileType.toString()).assertEqual(props[type].fileType);
expect(asset.uri != undefined).assertTrue();
fetchAssetResult.close();
done();
});
} catch (error) {
console.info(`${testNum}:: error :${error}`);
expect(false).assertTrue();
......@@ -185,6 +179,23 @@ export default function getFileAssetsPromiseTest(abilityContext) {
}
}
async function getFileAssetsErrCodeTest(done, testNum, isAudio) {
try {
let fetchAssetResult;
let invalidOps : userFileManager.FetchOptions;
if (isAudio) {
fetchAssetResult = await userfilemgr.getAudioAssets(invalidOps);
} else {
fetchAssetResult = await userfilemgr.getPhotoAssets(invalidOps);
}
expect(false).assertTrue();
} catch (error) {
console.info(`${testNum}:: errCode :${JSON.stringify(error)}`);
expect(error.code).assertEqual(THROW_ERROR_CODE.toString());
done();
}
}
//
/**
* @tc.number : SUB_USERFILE_MGR_GETPHOTOASSETS_PROMISE_01_001
* @tc.name : getFirstObject
......@@ -423,6 +434,36 @@ export default function getFileAssetsPromiseTest(abilityContext) {
let isAudio = false;
await checkFileAssetAttr(done, testNum, currentFetchOps, type, isAudio);
});
//------------------------------------------------------------------------------
/**
* @tc.number : SUB_USERFILE_MGR_GETPHOTOASSETS_ERRCODE_PROMISE_01
* @tc.name : getPhotoAssets
* @tc.desc : invalid FetchOptions
* @tc.size : MEDIUM
* @tc.type : Function
* @tc.level : Level 0
*/
it('SUB_USERFILE_MGR_GETPHOTOASSETS_ERRCODE_PROMISE_01', 0, async function (done) {
let testNum = 'SUB_USERFILE_MGR_GETPHOTOASSETS_ERRCODE_PROMISE_01';
let isAudio = false;
await getFileAssetsErrCodeTest(done, testNum, isAudio);
});
/**
* @tc.number : SUB_USERFILE_MGR_GETPHOTOASSETS_ERRCODE_PROMISE_02
* @tc.name : getPhotoAssets
* @tc.desc : invalid FetchOptions
* @tc.size : MEDIUM
* @tc.type : Function
* @tc.level : Level 0
*/
it('SUB_USERFILE_MGR_GETPHOTOASSETS_ERRCODE_PROMISE_02', 0, async function (done) {
let testNum = 'SUB_USERFILE_MGR_GETPHOTOASSETS_ERRCODE_PROMISE_02';
let isAudio = true;
await getFileAssetsErrCodeTest(done, testNum, isAudio);
});
});
}
......@@ -74,7 +74,6 @@ export default function fileAssetFileKeyTest(abilityContext) {
}
const fetchCount = newAlbumResult.getCount();
const currentAlbum = await newAlbumResult.getFirstObject();
//expect(currentAlbum.get(type)).assertEqual(album.get(type));
expect(currentAlbum[type]).assertEqual(album[type]);
expect(fetchCount > 0).assertTrue();
console.info(`${testNum} newAlbum : ${currentAlbum[type]} count: ${fetchCount}`)
......@@ -141,7 +140,6 @@ export default function fileAssetFileKeyTest(abilityContext) {
fetchColumns: [],
predicates: predicates
};
userfilemgr.getAudioAssets(ops, async (err, newAssetResult) => {
if (err) {
console.info(`${testNum}, err: ${err}`)
......@@ -162,6 +160,20 @@ export default function fileAssetFileKeyTest(abilityContext) {
}
}
/**
* @tc.number : SUB_USERFILE_MGR_GETPHOTOALBUMSBYKEY_02
* @tc.name : AlbumKey
* @tc.desc : AlbumKey.ALBUM_NAME
* @tc.size : MEDIUM
* @tc.type : Function
* @tc.level : Level 0
*/
it('SUB_USERFILE_MGR_GETPHOTOALBUMSBYKEY_02', 0, async function (done) {
let testNum = 'SUB_USERFILE_MGR_GETPHOTOALBUMSBYKEY_02';
let type = 'albumName';
let fileKey = AlbumKey.ALBUM_NAME;
await getAlbumsByKey(done, testNum, type, fileKey);
})
/**
* @tc.number : SUB_USERFILE_MGR_GETPHOTOALBUMSBYKEY_03
* @tc.name : AlbumKey
......@@ -420,6 +432,20 @@ export default function fileAssetFileKeyTest(abilityContext) {
await getAudioAssetsByKey(done, testNum, fileKey);
});
/**
* @tc.number : SUB_USERFILE_MGR_GETAUDIOASSETSBYKEY_07
* @tc.name : AUDIOKEY
* @tc.desc : AUDIOKEY.AUDIOALBUM
* @tc.size : MEDIUM
* @tc.type : Function
* @tc.level : Level 0
*/
it('SUB_USERFILE_MGR_GETAUDIOASSETSBYKEY_07', 0, async function (done) {
let testNum = 'SUB_USERFILE_MGR_GETAUDIOASSETSBYKEY_07';
let fileKey = AUDIOKEY.AUDIOALBUM;
await getAudioAssetsByKey(done, testNum, fileKey);
});
/**
* @tc.number : SUB_USERFILE_MGR_GETAUDIOASSETSBYKEY_08
* @tc.name : AUDIOKEY
......
......@@ -18,9 +18,6 @@ import fileio from '@ohos.fileio';
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index';
import {
sleep,
IMAGE_TYPE,
VIDEO_TYPE,
AUDIO_TYPE,
audioFetchOps,
imageVideoFetchOps,
audioNameFetchOps,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册