chore(hmos): 导入生产环境鸿蒙工程
- 以 D:\SmartSenior 生产工程为源,纳入 AppScope、entry、cjagent、hvigor 及根配置 - 移除 build-profile.json5 的 signingConfigs(p12/p7b/cer 路径与加密口令)及 products.signingConfig 引用 - 不纳入本地与开发产物:local.properties、.idea、.hvigor、.codegenie、demo、backup_a2a_native、SESSION_LOG.md、build_err.txt、build/、oh_modules - .gitignore 追加 .codegenie 与密钥文件通配(*.p12/*.p7b/*.cer/*.jks/*.keystore/*.pem)
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
/node_modules
|
||||
/oh_modules
|
||||
/.preview
|
||||
/build
|
||||
/.cxx
|
||||
/.test
|
||||
**/IDL_Dependencies_List~
|
||||
**/build-script-cache
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Use these variables when you tailor your ArkTS code. They must be of the const type.
|
||||
*/
|
||||
export const HAR_VERSION = '1.0.0';
|
||||
export const BUILD_MODE_NAME = 'debug';
|
||||
export const DEBUG = true;
|
||||
export const TARGET_NAME = 'default';
|
||||
|
||||
/**
|
||||
* BuildProfile Class is used only for compatibility purposes.
|
||||
*/
|
||||
export default class BuildProfile {
|
||||
static readonly HAR_VERSION = HAR_VERSION;
|
||||
static readonly BUILD_MODE_NAME = BUILD_MODE_NAME;
|
||||
static readonly DEBUG = DEBUG;
|
||||
static readonly TARGET_NAME = TARGET_NAME;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"apiType": "stageMode",
|
||||
"buildOption": {
|
||||
"cangjieOptions": {
|
||||
"path": "./cjpm.toml",
|
||||
"abiFilters": ["arm64-v8a","x86_64"]
|
||||
},
|
||||
"nativeLib": {
|
||||
"filter": {
|
||||
"enableOverride": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"buildOptionSet": [
|
||||
],
|
||||
"targets": [
|
||||
{
|
||||
"name": "default"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
version = 0
|
||||
|
||||
[requires]
|
||||
@@ -0,0 +1,37 @@
|
||||
[package]
|
||||
cjc-version = "1.2.0"
|
||||
compile-option = "--dy-std --cfg=\"${COMPILE_CONDITION}\""
|
||||
override-compile-option = "${OVERRIDE_COMPILE_OPTION}"
|
||||
description = "CangjieUI Application"
|
||||
name = "ohos_app_cangjie_cjagent"
|
||||
output-type = "dynamic"
|
||||
src-dir = "./src/main/cangjie"
|
||||
target-dir = ""
|
||||
version = "1.0.0"
|
||||
|
||||
[profile]
|
||||
[profile.build]
|
||||
incremental = true
|
||||
lto = ""
|
||||
[profile.build.combined]
|
||||
ohos_app_cangjie_cjagent = "dynamic"
|
||||
[profile.customized-option]
|
||||
debug = "-g -Woff all -Won apilevel-check"
|
||||
release = "--fast-math -O2 -s -Woff all -Won apilevel-check"
|
||||
asan = "--sanitize=address -lclang_rt.asan"
|
||||
[profile.test]
|
||||
|
||||
[target.aarch64-linux-ohos]
|
||||
compile-option = "-B \"${DEVECO_CANGJIE_HOME}/build-tools/third_party/llvm/bin\" -B \"${DEVECO_OH_NATIVE_HOME}/sysroot/usr/lib/aarch64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/sysroot/usr/lib/aarch64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/llvm/lib/clang/15.0.4/lib/aarch64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/llvm/lib/aarch64-linux-ohos\" --sysroot \"${DEVECO_OH_NATIVE_HOME}/sysroot\""
|
||||
[target.aarch64-linux-ohos.bin-dependencies]
|
||||
path-option = ["${AARCH64_LIBS}", "${AARCH64_MACRO_LIBS}", "${AARCH64_KIT_LIBS}"]
|
||||
package-option = { }
|
||||
|
||||
[target.x86_64-linux-ohos]
|
||||
compile-option = "-B \"${DEVECO_CANGJIE_HOME}/build-tools/third_party/llvm/bin\" -B \"${DEVECO_OH_NATIVE_HOME}/sysroot/usr/lib/x86_64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/sysroot/usr/lib/x86_64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/llvm/lib/clang/15.0.4/lib/x86_64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/llvm/lib/x86_64-linux-ohos\" --sysroot \"${DEVECO_OH_NATIVE_HOME}/sysroot\""
|
||||
[target.x86_64-linux-ohos.bin-dependencies]
|
||||
path-option = ["${X86_64_OHOS_LIBS}", "${X86_64_OHOS_MACRO_LIBS}", "${X86_64_OHOS_KIT_LIBS}"]
|
||||
|
||||
[target.x86_64-w64-mingw32.bin-dependencies]
|
||||
path-option = ["${X86_64_LIBS}", "${X86_64_MACRO_LIBS}", "${X86_64_KIT_LIBS}"]
|
||||
package-option = { }
|
||||
@@ -0,0 +1,8 @@
|
||||
cjpm.exe : Warning: field 'profile.build.combined' in '.\cjpm.toml' is experimental, it is unstable and has some limita
|
||||
tions, please refer to related documentation for more details
|
||||
所在位置 行:4 字符: 582
|
||||
+ ... t=default"; & "$sdk\build-tools\tools\bin\cjpm.exe" build --target=aa ...
|
||||
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
+ CategoryInfo : NotSpecified: (Warning: field ...or more details:String) [], RemoteException
|
||||
+ FullyQualifiedErrorId : NativeCommandError
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { harTasks } from '@ohos/hvigor-ohos-plugin';
|
||||
|
||||
export default {
|
||||
system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
|
||||
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "cjagent",
|
||||
"version": "1.0.0",
|
||||
"description": "Please describe the basic information.",
|
||||
"main": "",
|
||||
"author": "",
|
||||
"types": "./Index.d.ets",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export declare interface CustomLib {
|
||||
parseIntent(text: string): string
|
||||
cjAgentVersion(): string
|
||||
sm4EncryptText(keyHex: string, plain: string): string
|
||||
sm4DecryptText(keyHex: string, cipherHex: string): string
|
||||
sm4SelfTest(): boolean
|
||||
splitIntents(text: string): string
|
||||
inferSlot(hour: number): string
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "libark_interop_api.so",
|
||||
"types": "./ark_interop_api.d.ts",
|
||||
"version": "1.0.0",
|
||||
"description": ""
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package ohos_app_cangjie_cjagent
|
||||
|
||||
import kit.PerformanceAnalysisKit.Hilog
|
||||
|
||||
public func sayHello(): Unit {
|
||||
Hilog.info(0, "Cangjie", "Hello Cangjie!")
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
package ohos_app_cangjie_cjagent
|
||||
|
||||
// 数智护老 · 仓颉意图引擎
|
||||
// 输入小艺转发的用户文本,输出结构化意图 JSON:{"action":"...","slot":"...","date":"...","jump":"..."}
|
||||
// 纯逻辑零依赖:只做文本解析,后端调用仍由 ArkTS 侧执行(业务零风险)
|
||||
|
||||
import ohos.ark_interop.*
|
||||
import ohos.ark_interop_macro.*
|
||||
import kit.PerformanceAnalysisKit.Hilog
|
||||
import std.collection.ArrayList
|
||||
|
||||
// 日志过滤约定:仓颉侧统一用 Domain=0xC1C1 Tag=CJCJAGENT
|
||||
let CJ_DOMAIN: UInt32 = 0xC1C1
|
||||
let CJ_TAG: String = "CJCJAGENT"
|
||||
|
||||
// 包含判断的小工具
|
||||
func has(text: String, key: String): Bool {
|
||||
return text.contains(key)
|
||||
}
|
||||
|
||||
// ASR 转写容错:方言/口音经小艺转写后常见错别字归一
|
||||
// 例:四川话"定个餐"→"定餐","叁"被听成数字三等
|
||||
let ASR_FIXES: Array<Array<String>> = [
|
||||
["定餐", "订餐"], ["定饭", "订饭"], ["定个", "订个"], ["定明", "订明"],
|
||||
["订叁", "订餐"], ["订叄", "订餐"], ["订散", "订餐"],
|
||||
["午叁", "午餐"], ["晚叁", "晚餐"], ["早叁", "早餐"],
|
||||
["天汽", "天气"], ["查寻", "查询"], ["枢查", "查询"],
|
||||
["抱告", "报告"], ["健慷", "健康"]
|
||||
]
|
||||
|
||||
func normalizeAsr(text: String): String {
|
||||
var out = text
|
||||
for (pair in ASR_FIXES) {
|
||||
if (pair.size >= 2 && out.contains(pair[0])) {
|
||||
out = out.replace(pair[0], pair[1])
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func detectSlot(text: String): String {
|
||||
if (has(text, "早")) {
|
||||
return "breakfast"
|
||||
}
|
||||
if (has(text, "晚")) {
|
||||
return "dinner"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func detectDate(text: String): String {
|
||||
if (has(text, "明天") || has(text, "明日")) {
|
||||
return "tomorrow"
|
||||
}
|
||||
return "today"
|
||||
}
|
||||
|
||||
// 跳转页面判断
|
||||
func detectJump(text: String): String {
|
||||
if (has(text, "天气") || has(text, "气温") || has(text, "下雨")) {
|
||||
return "pages/elderly/ElderlyWeather"
|
||||
}
|
||||
if (has(text, "活动") || has(text, "八段锦") || has(text, "健身")) {
|
||||
return "pages/elderly/Activities"
|
||||
}
|
||||
if ((has(text, "订餐") && has(text, "看")) || has(text, "菜单")) {
|
||||
return "pages/elderly/ElderlyMealOrder"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// 主意图分类:直接返回动作名(避免枚举相等性比较)
|
||||
func classify(text: String): String {
|
||||
// 时间/日期问答:纯本地播报
|
||||
if (has(text, "几点") || has(text, "时间") || has(text, "几号") || has(text, "几月")
|
||||
|| has(text, "星期几") || has(text, "周几") || has(text, "日期")) {
|
||||
return "time"
|
||||
}
|
||||
// 菜单查询:今天有什么餐/吃什么("看菜单"仍走页面跳转)
|
||||
if (has(text, "有什么餐") || has(text, "有什么菜") || has(text, "有什么吃的")
|
||||
|| (has(text, "吃什么") && !has(text, "订")) || (has(text, "菜单") && !has(text, "看"))) {
|
||||
return "menu"
|
||||
}
|
||||
// 活动查询:有什么活动/活动安排
|
||||
if (has(text, "活动") && !has(text, "看") && !has(text, "打开") && !has(text, "去")) {
|
||||
return "activities"
|
||||
}
|
||||
// 跳转类优先(看天气/看活动/看菜单)
|
||||
if (!detectJump(text).isEmpty()) {
|
||||
return "jump"
|
||||
}
|
||||
// 问候:仍走 ArkTS 侧(带时段个性化),此处归 fallback
|
||||
if (has(text, "你好") || has(text, "您好") || has(text, "早上好") || has(text, "下午好")
|
||||
|| has(text, "晚上好") || has(text, "嗨") || text == "在吗") {
|
||||
return "fallback"
|
||||
}
|
||||
let wantCancel = has(text, "取消") || has(text, "退订") || has(text, "不订")
|
||||
|| has(text, "不要") || has(text, "不吃了")
|
||||
let mealWord = has(text, "餐") || has(text, "饭") || has(text, "订") || has(text, "吃")
|
||||
// 状态查询:先于下单/取消判断,避免"我订了什么"被当成下单
|
||||
let statusWord = has(text, "状态") || has(text, "订了") || has(text, "订没订")
|
||||
|| has(text, "订的") || has(text, "订好") || has(text, "记录") || has(text, "查询")
|
||||
|| has(text, "查查") || has(text, "查一下") || has(text, "哪些") || has(text, "吃什么")
|
||||
|| (has(text, "看看") && has(text, "订"))
|
||||
if (mealWord && statusWord && !wantCancel) {
|
||||
return "status"
|
||||
}
|
||||
if (wantCancel) {
|
||||
return "cancel"
|
||||
}
|
||||
// 跨业务编排 回家
|
||||
if (has(text, "回家") || has(text, "回家去") || has(text, "回家里")) {
|
||||
return "gohome"
|
||||
}
|
||||
// 下单
|
||||
if (has(text, "回家") || has(text, "回家去") || has(text, "回家里")) {
|
||||
return "gohome"
|
||||
}
|
||||
// 求助
|
||||
if (has(text, "护士") || has(text, "护理员") || has(text, "救命") || has(text, "紧急")
|
||||
|| has(text, "不舒服") || has(text, "摔倒") || has(text, "疼") || has(text, "头晕")) {
|
||||
return "help"
|
||||
}
|
||||
// AI 健康报告
|
||||
if (has(text, "报告") && (has(text, "健康") || has(text, "看") || has(text, "查"))) {
|
||||
return "report"
|
||||
}
|
||||
return "fallback"
|
||||
}
|
||||
|
||||
// JSON 字符串转义(按 Rune 处理,中文原样保留)
|
||||
func jsonEscape(s: String): String {
|
||||
var out = ""
|
||||
for (r in s.runes()) {
|
||||
if (r == r'"') {
|
||||
out = out + "\\\""
|
||||
} else if (r == r'\\') {
|
||||
out = out + "\\\\"
|
||||
} else if (r == r'\n') {
|
||||
out = out + "\\n"
|
||||
} else {
|
||||
out = out + r.toString()
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
//导出给ArkTS调用
|
||||
@Interop[ArkTS]
|
||||
public func parseIntent(text: String): String {
|
||||
let normalized = normalizeAsr(text)
|
||||
let action = classify(normalized)
|
||||
var jump = ""
|
||||
if (action == "jump") {
|
||||
jump = detectJump(normalized)
|
||||
}
|
||||
var slot = ""
|
||||
var date = ""
|
||||
if (action == "order" || action == "cancel" || action == "status") {
|
||||
slot = detectSlot(normalized)
|
||||
date = detectDate(normalized)
|
||||
}
|
||||
let result = "{\"action\":\"" + action
|
||||
+ "\",\"slot\":\"" + slot
|
||||
+ "\",\"date\":\"" + date
|
||||
+ "\",\"jump\":\"" + jsonEscape(jump)
|
||||
+ "\"}"
|
||||
Hilog.info(CJ_DOMAIN, CJ_TAG, "parseIntent input=<${text}> result=<${result}>")
|
||||
return result
|
||||
}
|
||||
|
||||
// 餐次推断:按当前小时推断该订/取消哪一餐(订餐决策链下沉仓颉)
|
||||
// 9 点前早餐、9-15 点午餐、15 点后晚餐;返回 JSON 保持与 parseIntent 同构的互操作风格
|
||||
@Interop[ArkTS]
|
||||
public func inferSlot(hour: Int64): String {
|
||||
var slot = "lunch"
|
||||
if (hour < 9) {
|
||||
slot = "breakfast"
|
||||
} else if (hour >= 15) {
|
||||
slot = "dinner"
|
||||
}
|
||||
let result = "{\"slot\":\"" + slot + "\"}"
|
||||
Hilog.info(CJ_DOMAIN, CJ_TAG, "inferSlot hour=<" + hour.toString() + "> result=<" + result + ">")
|
||||
return result
|
||||
}
|
||||
|
||||
// 健康检查:ArkTS 侧启动时调用,确认仓颉 so 加载成功
|
||||
@Interop[ArkTS]
|
||||
public func cjAgentVersion(): String {
|
||||
return "cjagent-1.1.0"
|
||||
}
|
||||
|
||||
// ── 多意图拆分 ──
|
||||
// "订明天的晚饭,然后看看活动" → ["订明天的晚饭", "看看活动"]
|
||||
// 拆分依据:标点(,。!?;、)与连接词(然后/接着/再/还/另外/并且/以及/顺便/同时)
|
||||
|
||||
func toRunes(s: String): ArrayList<Rune> {
|
||||
let out = ArrayList<Rune>()
|
||||
for (r in s.runes()) {
|
||||
out.add(r)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func runeEqAt(hay: ArrayList<Rune>, needle: ArrayList<Rune>, off: Int64): Bool {
|
||||
if (off + needle.size > hay.size) {
|
||||
return false
|
||||
}
|
||||
var i: Int64 = 0
|
||||
while (i < needle.size) {
|
||||
if (hay[off + i] != needle[i]) {
|
||||
return false
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isPunct(r: Rune): Bool {
|
||||
return r == r',' || r == r'。' || r == r'!' || r == r'?' || r == r';'
|
||||
|| r == r'、' || r == r',' || r == r'.' || r == r'!' || r == r'?'
|
||||
}
|
||||
|
||||
let CONNECTORS: Array<ArrayList<Rune>> = [
|
||||
toRunes("然后"), toRunes("接着"), toRunes("再帮我"), toRunes("帮我再"),
|
||||
toRunes("另外"), toRunes("并且"), toRunes("以及"), toRunes("顺便"),
|
||||
toRunes("同时"), toRunes("还要"), toRunes("再")
|
||||
]
|
||||
|
||||
// 主入口:返回 {"segments":[...]};单意图时 segments 只有原文一段
|
||||
@Interop[ArkTS]
|
||||
public func splitIntents(text: String): String {
|
||||
let rs = toRunes(text)
|
||||
let parts = ArrayList<String>()
|
||||
var buf = ""
|
||||
var i: Int64 = 0
|
||||
while (i < rs.size) {
|
||||
let ch = rs[i]
|
||||
if (isPunct(ch)) {
|
||||
if (!buf.isEmpty()) {
|
||||
parts.add(buf)
|
||||
buf = ""
|
||||
}
|
||||
i = i + 1
|
||||
continue
|
||||
}
|
||||
var matched = false
|
||||
var connLen: Int64 = 0
|
||||
for (c in CONNECTORS) {
|
||||
if (runeEqAt(rs, c, i)) {
|
||||
matched = true
|
||||
connLen = c.size
|
||||
break
|
||||
}
|
||||
}
|
||||
if (matched) {
|
||||
if (!buf.isEmpty()) {
|
||||
parts.add(buf)
|
||||
buf = ""
|
||||
}
|
||||
i = i + connLen
|
||||
continue
|
||||
}
|
||||
buf = buf + ch.toString()
|
||||
i = i + 1
|
||||
}
|
||||
if (!buf.isEmpty()) {
|
||||
parts.add(buf)
|
||||
}
|
||||
// 过滤过短片段(多半是"再""还"残余),最多取 3 段
|
||||
let segs = ArrayList<String>()
|
||||
for (p in parts) {
|
||||
if (segs.size < 3 && p.size >= 2) {
|
||||
segs.add(p)
|
||||
}
|
||||
}
|
||||
var out = "{\"segments\":["
|
||||
var n: Int64 = 0
|
||||
if (segs.size <= 1) {
|
||||
out = out + "\"" + jsonEscape(text) + "\""
|
||||
n = 1
|
||||
} else {
|
||||
for (s in segs) {
|
||||
if (n > 0) {
|
||||
out = out + ","
|
||||
}
|
||||
out = out + "\"" + jsonEscape(s) + "\""
|
||||
n = n + 1
|
||||
}
|
||||
}
|
||||
out = out + "]}"
|
||||
Hilog.info(CJ_DOMAIN, CJ_TAG, "splitIntents input=<${text}> segments=<${out}>")
|
||||
return out
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
export declare function parseIntent(text: string): string
|
||||
|
||||
export declare function cjAgentVersion(): string
|
||||
|
||||
export declare function splitIntents(text: string): string
|
||||
|
||||
export declare function inferSlot(hour: number): string
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "libohos_app_cangjie_cjagent.so",
|
||||
"types": "./Index.d.ts",
|
||||
"version": "1.0.0",
|
||||
"description": ""
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"module": {
|
||||
"name": "cjagent",
|
||||
"type": "har",
|
||||
"deviceTypes": [
|
||||
"default",
|
||||
"tablet"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "page_show",
|
||||
"value": "page from npm package"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "page_show",
|
||||
"value": "page from npm package"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "page_show",
|
||||
"value": "page from npm package"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package ohos_app_cangjie_cjagent_test
|
||||
|
||||
import kit.AbilityKit.AbilityStage
|
||||
import kit.PerformanceAnalysisKit.Hilog
|
||||
|
||||
class MyAbilityStage <: AbilityStage {
|
||||
public override func onCreate(): Unit {
|
||||
Hilog.info(1, "Cangjie", "MyAbilityStage onCreated.")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
[package]
|
||||
cjc-version = "1.2.0"
|
||||
compile-option = "--dy-std --cfg=\"${COMPILE_CONDITION}\""
|
||||
override-compile-option = "${OVERRIDE_COMPILE_OPTION}"
|
||||
description = "CangjieUI Application"
|
||||
link-option = "--unresolved-symbols=ignore-all"
|
||||
name = "ohos_app_cangjie_cjagent_test"
|
||||
output-type = "dynamic"
|
||||
src-dir = "."
|
||||
target-dir = ""
|
||||
version = "1.0.0"
|
||||
|
||||
[dependencies]
|
||||
[dependencies.ohos_app_cangjie_cjagent]
|
||||
path = "../../../"
|
||||
|
||||
[profile]
|
||||
[profile.build]
|
||||
incremental = true
|
||||
lto = ""
|
||||
[profile.build.combined]
|
||||
ohos_app_cangjie_cjagent_test = "dynamic"
|
||||
[profile.customized-option]
|
||||
debug = "-g -Woff all -Won apilevel-check"
|
||||
release = "--fast-math -O2 -s -Woff all -Won apilevel-check"
|
||||
withoutCoverage = "--cfg=\"coverage=false\""
|
||||
withCoverage = "--cfg=\"coverage=true\""
|
||||
asan = "--sanitize=address -lclang_rt.asan"
|
||||
[profile.test]
|
||||
|
||||
[target.aarch64-linux-ohos]
|
||||
compile-option = "-B \"${DEVECO_CANGJIE_HOME}/build-tools/third_party/llvm/bin\" -B \"${DEVECO_OH_NATIVE_HOME}/sysroot/usr/lib/aarch64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/sysroot/usr/lib/aarch64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/llvm/lib/clang/15.0.4/lib/aarch64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/llvm/lib/aarch64-linux-ohos\" --sysroot \"${DEVECO_OH_NATIVE_HOME}/sysroot\""
|
||||
[target.aarch64-linux-ohos.bin-dependencies]
|
||||
path-option = ["${AARCH64_LIBS}", "${AARCH64_MACRO_LIBS}", "${AARCH64_KIT_LIBS}"]
|
||||
package-option = { }
|
||||
|
||||
[target.x86_64-linux-ohos]
|
||||
compile-option = "-B \"${DEVECO_CANGJIE_HOME}/build-tools/third_party/llvm/bin\" -B \"${DEVECO_OH_NATIVE_HOME}/sysroot/usr/lib/x86_64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/sysroot/usr/lib/x86_64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/llvm/lib/clang/15.0.4/lib/x86_64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/llvm/lib/x86_64-linux-ohos\" --sysroot \"${DEVECO_OH_NATIVE_HOME}/sysroot\""
|
||||
[target.x86_64-linux-ohos.bin-dependencies]
|
||||
path-option = ["${X86_64_OHOS_LIBS}", "${X86_64_OHOS_MACRO_LIBS}", "${X86_64_OHOS_KIT_LIBS}"]
|
||||
|
||||
[target.x86_64-w64-mingw32.bin-dependencies]
|
||||
path-option = ["${X86_64_LIBS}", "${X86_64_MACRO_LIBS}", "${X86_64_KIT_LIBS}"]
|
||||
package-option = { }
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Created on 2025/2/26
|
||||
*/
|
||||
package ohos_app_cangjie_cjagent_test
|
||||
|
||||
import std.unittest.expectEqual
|
||||
import std.unittest.testmacro.Expect
|
||||
|
||||
func unittest() {
|
||||
let a = "abc"
|
||||
let b = "b"
|
||||
@Expect(a.contains(b))
|
||||
@Expect(a, a)
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package ohos_app_cangjie_cjagent_test
|
||||
|
||||
import std.unittest.TestClass
|
||||
import std.unittest.TestPackage
|
||||
import std.unittest.TestSuite
|
||||
import std.unittest.UnitTestCase
|
||||
import std.unittest.common.Configuration
|
||||
import std.unittest.testmacro.Test
|
||||
import std.unittest.testmacro.TestCase
|
||||
|
||||
@Test
|
||||
class TestExample00 {
|
||||
@TestCase
|
||||
func test00(): Unit {
|
||||
unittest()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package ohos_app_cangjie_cjagent_test
|
||||
|
||||
import kit.ArkUI.LengthProp
|
||||
import kit.ArkUI.Column
|
||||
import kit.ArkUI.Row
|
||||
import kit.ArkUI.Text
|
||||
import kit.ArkUI.CustomView
|
||||
import kit.ArkUI.CJEntry
|
||||
import kit.ArkUI.loadNativeView
|
||||
import kit.ArkUI.FontWeight
|
||||
import kit.ArkUI.SubscriberManager
|
||||
import kit.ArkUI.ObservedProperty
|
||||
import kit.ArkUI.LocalStorage
|
||||
import ohos.arkui.state_macro_manage.Entry
|
||||
import ohos.arkui.state_macro_manage.Component
|
||||
import ohos.arkui.state_macro_manage.State
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
class CjagentView {
|
||||
@State
|
||||
var message: String = "Hello World"
|
||||
|
||||
func build() {
|
||||
Row {
|
||||
Column {
|
||||
Text(this.message)
|
||||
.fontSize(50)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.onClick ({
|
||||
evt => this.message = "Hello Cangjie"
|
||||
})
|
||||
}.width(100.percent)
|
||||
}.height(100.percent)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package ohos_app_cangjie_cjagent_test
|
||||
|
||||
import ohos_app_cangjie_cjagent_test.unittest_support.registerTestSuite
|
||||
|
||||
private let register = testsuite()
|
||||
|
||||
func testsuite() {
|
||||
registerTestSuite {TestExample00()}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package ohos_app_cangjie_cjagent_test
|
||||
|
||||
import kit.PerformanceAnalysisKit.Hilog
|
||||
import kit.AbilityKit.Want
|
||||
import kit.AbilityKit.UIAbility
|
||||
import kit.AbilityKit.LaunchParam
|
||||
import kit.AbilityKit.LaunchReason
|
||||
import kit.ArkUI.WindowStage
|
||||
|
||||
class MainAbility <: UIAbility {
|
||||
public init() {
|
||||
super()
|
||||
registerSelf()
|
||||
}
|
||||
|
||||
public override func onCreate(want: Want, launchParam: LaunchParam): Unit {
|
||||
Hilog.info(1, "Cangjie", "MainAbility OnCreated.${want.abilityName}")
|
||||
match (launchParam.launchReason) {
|
||||
case LaunchReason.StartAbility => Hilog.info(1, "Cangjie", "START_ABILITY")
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
||||
public override func onWindowStageCreate(windowStage: WindowStage): Unit {
|
||||
Hilog.info(1, "Cangjie", "MainAbility onWindowStageCreate.")
|
||||
windowStage.loadContent("CjagentView")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
package ohos_app_cangjie_cjagent_test.unittest_support
|
||||
|
||||
import std.fs.Path
|
||||
import std.fs.Directory
|
||||
import std.collection.filter
|
||||
import std.fs.FileInfo
|
||||
import std.collection.first
|
||||
import std.fs.File
|
||||
import std.collection.forEach
|
||||
import std.convert.Parsable
|
||||
import std.collection.any
|
||||
import std.collection.HashMap
|
||||
import std.collection.ArrayList
|
||||
import std.unittest.common.Configuration
|
||||
import std.unittest.TestClass
|
||||
import std.unittest.TestSuite
|
||||
import std.unittest.XmlReporter
|
||||
import kit.AbilityKit.BundleManager
|
||||
import kit.AbilityKit.BundleFlag
|
||||
import kit.AbilityKit.Want
|
||||
import kit.PerformanceAnalysisKit.Hilog
|
||||
import kit.TestKit.AbilityDelegator
|
||||
import kit.TestKit.AbilityDelegatorRegistry
|
||||
import kit.TestKit.TestRunner
|
||||
import std.env.setVariable
|
||||
|
||||
@When[coverage == "true"]
|
||||
foreign func __gcov_dump(): Unit
|
||||
|
||||
@When[coverage == "true"]
|
||||
public func gcov_dump(coveragePath: String): Unit {
|
||||
Hilog.info(0, "Cangjie-Test", "execute test with coverage")
|
||||
unsafe { __gcov_dump() }
|
||||
let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
|
||||
abilityDelegator.print("GENERATE_COVERAGE: ${coveragePath}")
|
||||
}
|
||||
|
||||
@When[coverage == "false"]
|
||||
public func gcov_dump(coveragePath: String): Unit {
|
||||
Hilog.info(0, "Cangjie-Test", "execute test without coverage")
|
||||
}
|
||||
|
||||
public func registerTestSuite(testClassInstanceGenerator: () -> TestClass): Unit {
|
||||
OpenHarmonyTestRunner
|
||||
.testClassInstanceGenerators
|
||||
.add(testClassInstanceGenerator)
|
||||
}
|
||||
|
||||
public class OpenHarmonyTestRunner <: TestRunner {
|
||||
public static let testSuiteMap = HashMap<String, TestSuite>()
|
||||
public static let testClassInstanceGenerators = ArrayList<() -> TestClass>()
|
||||
private static func getDetailedInfoOf(e: Exception): String {
|
||||
let sb = StringBuilder("exception: ${e.toString()}\n")
|
||||
e.getStackTrace() |>
|
||||
forEach {
|
||||
s => sb.append(" at ${s.declaringClass}.${s.methodName}(${s.fileName}:${s.lineNumber})\n")
|
||||
}
|
||||
sb.toString()
|
||||
}
|
||||
|
||||
private static func joinStrings(list: ArrayList<String>, separator: String): String {
|
||||
if (list.isEmpty()) {
|
||||
return ""
|
||||
}
|
||||
let sb = StringBuilder()
|
||||
for (i in 0..list.size) {
|
||||
if (i > 0) {
|
||||
sb.append(separator)
|
||||
}
|
||||
sb.append(list[i])
|
||||
}
|
||||
sb.toString()
|
||||
}
|
||||
|
||||
private func executeTestClass(testClassName: String): Unit {
|
||||
let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
|
||||
Hilog.info(0, "Cangjie-Test", "EXECUTE_CLASS_START: \"${testClassName}\"")
|
||||
abilityDelegator.print("EXECUTE_CLASS_START: \"${testClassName}\"")
|
||||
let testSuite = match (OpenHarmonyTestRunner
|
||||
.testSuiteMap
|
||||
.get(testClassName)) {
|
||||
case None => return
|
||||
case Some(testClassInstanceGenerator) => testClassInstanceGenerator
|
||||
}
|
||||
|
||||
testSuite
|
||||
.runTests()
|
||||
.reportTo(XmlReporter(Path("/data/storage/el2/base")))
|
||||
|
||||
let testReportXmlFileName = "test-default.${testClassName}.xml"
|
||||
match (Directory.readFrom("/data/storage/el2/base/tests") |>
|
||||
filter {fileInfo => fileInfo.name == testReportXmlFileName} |> first) {
|
||||
case None => Hilog.error(1, "Cangjie-Test", "${testReportXmlFileName} not found.")
|
||||
case Some(testReportXmlFileInfo) =>
|
||||
let testReportXmlFilePath = testReportXmlFileInfo.path
|
||||
let testReportXmlFileContent = File.readFrom(testReportXmlFilePath)
|
||||
let xmlReport = String.fromUtf8(testReportXmlFileContent)
|
||||
reportTestReport("test-default.${testClassName}.xml")
|
||||
Hilog.info(0, "Cangjie-Test", "XML_REPORT_CONTENT_LENGTH: ${xmlReport.size}")
|
||||
abilityDelegator.print("XML_REPORT_CONTENT_LENGTH: ${xmlReport.size}")
|
||||
splitPrint(xmlReport, abilityDelegator)
|
||||
Hilog.info(0, "Cangjie-Test", "EXECUTE_CLASS_END: \"${testClassName}\"")
|
||||
abilityDelegator.print("EXECUTE_CLASS_END: \"${testClassName}\"")
|
||||
}
|
||||
}
|
||||
private func executeAllTestClasses(): Unit {
|
||||
for (testClassName in OpenHarmonyTestRunner
|
||||
.testSuiteMap
|
||||
.keys()) {
|
||||
executeTestClass(testClassName)
|
||||
}
|
||||
}
|
||||
private func executeTestCase(testClassName: String, testCaseName: String): Unit {
|
||||
let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
|
||||
abilityDelegator.print("EXECUTE_CLASS_START: \"${testClassName}\"")
|
||||
Hilog.info(0, "Cangjie-Test", "EXECUTE_METHOD_START: \"${testClassName}#${testCaseName}\"")
|
||||
let testSuite = match (OpenHarmonyTestRunner
|
||||
.testSuiteMap
|
||||
.get(testClassName)) {
|
||||
case None => return
|
||||
case Some(testClassInstanceGenerator) => testClassInstanceGenerator
|
||||
}
|
||||
let configuration = Configuration()
|
||||
configuration.setByName("filter", "${testClassName}.${testCaseName}")
|
||||
testSuite
|
||||
.runTests(configuration)
|
||||
.reportTo(XmlReporter(Path("/data/storage/el2/base")))
|
||||
|
||||
let testReportXmlFileName = "test-default.${testClassName}.xml"
|
||||
match (Directory.readFrom("/data/storage/el2/base/tests") |>
|
||||
filter {fileInfo => fileInfo.name == testReportXmlFileName} |> first) {
|
||||
case None => Hilog.error(1, "Cangjie-Test", "${testReportXmlFileName} not found.")
|
||||
case Some(testReportXmlFileInfo) =>
|
||||
let testReportXmlFilePath = testReportXmlFileInfo.path
|
||||
let testReportXmlFileContent = File.readFrom(testReportXmlFilePath)
|
||||
let xmlReport = String.fromUtf8(testReportXmlFileContent)
|
||||
reportTestReport("test-default.${testClassName}.xml")
|
||||
Hilog.info(0, "Cangjie-Test", "XML_REPORT_CONTENT_LENGTH: ${xmlReport.size}")
|
||||
abilityDelegator.print("XML_REPORT_CONTENT_LENGTH: ${xmlReport.size}")
|
||||
splitPrint(xmlReport, abilityDelegator)
|
||||
Hilog.info(0, "Cangjie-Test", "EXECUTE_METHOD_END: \"${testClassName}#${testCaseName}\"")
|
||||
abilityDelegator.print("EXECUTE_CLASS_END: \"${testClassName}\"")
|
||||
}
|
||||
}
|
||||
private func splitPrint(xmlReport: String, abilityDelegator: AbilityDelegator): Unit {
|
||||
let lines = xmlReport.split("\n", removeEmpty: true)
|
||||
let tempArray = ArrayList<String>()
|
||||
for (line in lines) {
|
||||
let trimmedLine = line.trimAscii()
|
||||
if (trimmedLine.isEmpty()) {
|
||||
continue
|
||||
}
|
||||
tempArray.add(line)
|
||||
if (tempArray.size == 10) {
|
||||
let output = OpenHarmonyTestRunner.joinStrings(tempArray, "\n")
|
||||
Hilog.error(0, "Cangjie-Test", output)
|
||||
abilityDelegator.print(output)
|
||||
tempArray.clear()
|
||||
}
|
||||
}
|
||||
if (tempArray.size > 0) {
|
||||
let output = OpenHarmonyTestRunner.joinStrings(tempArray, "\n")
|
||||
Hilog.error(0, "Cangjie-Test", output)
|
||||
abilityDelegator.print(output)
|
||||
}
|
||||
}
|
||||
private func reportTestReport(testReportName: String): Unit {
|
||||
let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
|
||||
let abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
|
||||
let bundleName = abilityDelegatorArguments.bundleName
|
||||
abilityDelegator.print("REPORT_TEST_RESULT: /data/app/el2/100/base/${bundleName}/tests/${testReportName}")
|
||||
}
|
||||
public override func onPrepare(): Unit {
|
||||
Hilog.info(0, "Cangjie-Test", "OpenHarmonyTestRunner onPrepare")
|
||||
for (testClassInstanceGenerator in OpenHarmonyTestRunner.testClassInstanceGenerators) {
|
||||
let testClassInstance = try {
|
||||
testClassInstanceGenerator()
|
||||
} catch (e: Exception) {
|
||||
Hilog.error(1, "Cangjie-Test", "exception occurred during testsuite generation:\n${getDetailedInfoOf(e)}")
|
||||
continue
|
||||
}
|
||||
let testSuite = testClassInstance.asTestSuite()
|
||||
let testSuiteName = testSuite.name
|
||||
Hilog.info(0, "Cangjie-Test", "Registering TestSuite ${testSuiteName}")
|
||||
OpenHarmonyTestRunner
|
||||
.testSuiteMap
|
||||
.add(testSuiteName, testSuite)
|
||||
}
|
||||
}
|
||||
public override func onRun(): Unit {
|
||||
Hilog.info(0, "Cangjie-Test", "OpenHarmonyTestRunner onRun")
|
||||
let abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
|
||||
let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
|
||||
Hilog.info(0, "Cangjie-Test", "bundleName = ${abilityDelegatorArguments.bundleName}")
|
||||
Hilog.info(0, "Cangjie-Test", "abilityDelegatorArguments.testRunnerClassName = ${abilityDelegatorArguments.testRunnerClassName}")
|
||||
Hilog.info(0, "Cangjie-Test", "abilityDelegatorArguments.testCaseNames = ${abilityDelegatorArguments.testCaseNames}")
|
||||
Hilog.info(0, "Cangjie-Test", "abilityDelegatorArguments.parameters = ${abilityDelegatorArguments.parameters}")
|
||||
Hilog.info(0, "Cangjie-Test", "Started running tests.")
|
||||
abilityDelegator.print("OpenHarmonyTestRunner onRun")
|
||||
let parameters = abilityDelegatorArguments.parameters
|
||||
let bundleName = abilityDelegatorArguments.bundleName
|
||||
let bundleInfo = BundleManager.getBundleInfoForSelf(
|
||||
BundleFlag.GET_BUNDLE_INFO_WITH_HAP_MODULE | BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION)
|
||||
let moduleName = match (parameters.get("-m")) {
|
||||
case None =>
|
||||
abilityDelegator.finishTest("Module name was not specified.", -1)
|
||||
return
|
||||
case Some(moduleName) =>
|
||||
if (bundleInfo.hapModulesInfo |> any {hapModuleInfo => hapModuleInfo.name == moduleName}) {
|
||||
moduleName
|
||||
} else {
|
||||
abilityDelegator.finishTest(
|
||||
"No module with name \"${moduleName}\" was found in bundle ${bundleName}.", -1)
|
||||
return
|
||||
}
|
||||
}
|
||||
let abilityName = match (bundleInfo.hapModulesInfo |> filter {hapModuleInfo => hapModuleInfo.name == moduleName} |>
|
||||
first) {
|
||||
case None =>
|
||||
abilityDelegator.finishTest("No module with name \"${moduleName}\" was found in bundle ${bundleName}.",
|
||||
-1)
|
||||
return
|
||||
case Some(hapModuleInfo) =>
|
||||
let mainElementName = hapModuleInfo.mainElementName
|
||||
Hilog.info(0, "Cangjie-Test", "mainElementName = ${mainElementName}")
|
||||
mainElementName
|
||||
}
|
||||
let want = Want(bundleName: bundleName, moduleName: moduleName, abilityName: abilityName)
|
||||
abilityDelegator.startAbility(want)
|
||||
let timeOut = match (parameters.get("-s timeout")) {
|
||||
case None => None<Int64>
|
||||
case Some(timeOutText) => match (Int64.tryParse(timeOutText)) {
|
||||
case None =>
|
||||
abilityDelegator.finishTest("The parameter \"timeout\": ${timeOutText} is invalid", -1)
|
||||
return
|
||||
case Some(timeOutValue) => timeOutValue
|
||||
}
|
||||
}
|
||||
spawn {
|
||||
try {
|
||||
match (parameters.get("-s class")) {
|
||||
case None => executeAllTestClasses()
|
||||
case Some(text) => text.split(",", removeEmpty: true) |>
|
||||
forEach {
|
||||
t: String =>
|
||||
let pair = t.split("#", removeEmpty: true)
|
||||
let testClassName = match (pair.get(0)) {
|
||||
case None => return
|
||||
case Some(text) => text.trimAscii()
|
||||
}
|
||||
match (pair.get(1)) {
|
||||
case None => executeTestClass(testClassName)
|
||||
case Some(testCaseName) => executeTestCase(testClassName, testCaseName)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Hilog.error(1, "Cangjie-Test", "an exception occurred:\n${getDetailedInfoOf(e)}")
|
||||
}
|
||||
var coverage = false
|
||||
setVariable("GCOV_PREFIX", "/data/storage/el2/base/cov")
|
||||
gcov_dump("/data/app/el2/100/base/${bundleName}/cov/")
|
||||
|
||||
abilityDelegator.finishTest("Test finished.", 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let _ = TestRunner.registerCreator("OpenHarmonyTestRunner") {OpenHarmonyTestRunner()}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"module": {
|
||||
"name": "cjagent_test",
|
||||
"type": "feature",
|
||||
"description": "$string:module_desc",
|
||||
"mainElement": "EntryAbility",
|
||||
"deviceTypes": [
|
||||
"default",
|
||||
"tablet"
|
||||
],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
"srcEntry": "ohos_app_cangjie_cjagent_test.MyAbilityStage",
|
||||
"abilities": [
|
||||
{
|
||||
"name": "EntryAbility",
|
||||
"srcEntry": "ohos_app_cangjie_cjagent_test.MainAbility",
|
||||
"description": "$string:EntryAbility_desc",
|
||||
"icon": "$media:layered_image",
|
||||
"label": "$string:EntryAbility_label",
|
||||
"startWindowIcon": "$media:startIcon",
|
||||
"startWindowBackground": "$color:start_window_background",
|
||||
"exported": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "module description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "label"
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"layered-image":
|
||||
{
|
||||
"background" : "$media:background",
|
||||
"foreground" : "$media:foreground"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
[package]
|
||||
cjc-version = "1.2.0"
|
||||
compile-option = "--dy-std --cfg=\"${COMPILE_CONDITION}\""
|
||||
override-compile-option = "${OVERRIDE_COMPILE_OPTION}"
|
||||
description = "CangjieUI Application"
|
||||
name = "ohos_app_cangjie_cjagent_local_test"
|
||||
output-type = "dynamic"
|
||||
src-dir = "."
|
||||
target-dir = ""
|
||||
version = "1.0.0"
|
||||
|
||||
[profile]
|
||||
[profile.build]
|
||||
incremental = true
|
||||
lto = ""
|
||||
[profile.build.combined]
|
||||
ohos_app_cangjie_cjagent_local_test = "dynamic"
|
||||
[profile.customized-option]
|
||||
debug = "-g -Woff all -Won apilevel-check"
|
||||
release = "--fast-math -O2 -s -Woff all -Won apilevel-check"
|
||||
asan = "--sanitize=address -lclang_rt.asan"
|
||||
[profile.test]
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Created on 2025/2/26
|
||||
*/
|
||||
package ohos_app_cangjie_cjagent_local_test
|
||||
|
||||
import std.unittest.expectEqual
|
||||
import std.unittest.testmacro.Expect
|
||||
|
||||
func unittest() {
|
||||
let a = "abc"
|
||||
let b = "b"
|
||||
@Expect(a.contains(b))
|
||||
@Expect(a, a)
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package ohos_app_cangjie_cjagent_local_test
|
||||
|
||||
import std.unittest.TestClass
|
||||
import std.unittest.TestPackage
|
||||
import std.unittest.TestSuite
|
||||
import std.unittest.UnitTestCase
|
||||
import std.unittest.common.Configuration
|
||||
import std.unittest.testmacro.Test
|
||||
import std.unittest.testmacro.TestCase
|
||||
|
||||
@Test
|
||||
class TestExample00 {
|
||||
@TestCase
|
||||
func test00(): Unit {
|
||||
unittest()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user