217 lines
6.6 KiB
Python
217 lines
6.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
import copy
|
|
import os
|
|
import re
|
|
import traceback
|
|
|
|
import typer
|
|
|
|
TESTSUITE_TEMPLATE = """
|
|
/*
|
|
* Copyright (C) 2023 Xiaomi Corporation
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <setjmp.h>
|
|
#include <stdarg.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <cmocka.h>
|
|
|
|
/****************************************************************************
|
|
* Name: cmocka_{suite_file}_main
|
|
****************************************************************************/
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
|
|
/* Add Test Cases */
|
|
const struct CMUnitTest {suite_name}[] = {
|
|
cmocka_unit_test_setup_teardown(write case name here, NULL, NULL),
|
|
};
|
|
|
|
/* Run Test cases */
|
|
cmocka_run_group_tests({suite_name}, NULL, NULL);
|
|
|
|
printf("hello cmocka auto-tests\\n");
|
|
|
|
return 0;
|
|
}
|
|
"""
|
|
|
|
TESTCASE_TEMPLATE = """
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <syslog.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <cmocka.h>
|
|
|
|
|
|
/****************************************************************************
|
|
* Name: {case_file}
|
|
* Description: Testing for scene "describe scene here".
|
|
* The detail test steps are as following:
|
|
* 1. describe step 1 here
|
|
* 2. describe step 2 here
|
|
* 3. describe step 3 here
|
|
****************************************************************************/
|
|
|
|
void {case_name}(FAR void **state)
|
|
{
|
|
printf("case: {case_name}\\n");
|
|
assert(true);
|
|
}
|
|
"""
|
|
|
|
|
|
class CmockaGen:
|
|
def __init__(self, path):
|
|
self.path = path
|
|
self.suite_path = None
|
|
self.suite_file = None
|
|
self.suite_name = None
|
|
self.case_path = None
|
|
self.case_file = None
|
|
self.case_name = None
|
|
|
|
def check_path(self):
|
|
if not self.path:
|
|
print("request correct path option")
|
|
return 1
|
|
if not os.path.exists(self.path):
|
|
os.makedirs(self.path)
|
|
return 0
|
|
|
|
def check_suite_option(self, suite_option):
|
|
if not suite_option:
|
|
return 1
|
|
opts = suite_option.split("::")
|
|
if len(opts) != 2:
|
|
print("suite option must like aaa/bbb/ccc.c::VelaAutoTestSuite")
|
|
return 1
|
|
else:
|
|
self.suite_path = opts[0]
|
|
self.suite_name = opts[1]
|
|
paths = self.suite_path.split("/")
|
|
if not paths[-1].endswith(".c"):
|
|
print("suite option must like aaa/bbb/ccc.c::VelaAutoTestSuite")
|
|
return 1
|
|
else:
|
|
self.suite_file = paths[-1]
|
|
return 0
|
|
|
|
def generate_suite(self):
|
|
content = copy.deepcopy(TESTSUITE_TEMPLATE)
|
|
file_without_ext = self.suite_file.replace(".c", "")
|
|
content = content.replace("{suite_file}", file_without_ext)
|
|
content = content.replace("{suite_name}", self.suite_name)
|
|
full_path = os.path.join(self.path, self.suite_path)
|
|
dir_path = os.path.dirname(full_path)
|
|
if not os.path.exists(dir_path):
|
|
os.makedirs(dir_path)
|
|
with open(full_path, "w") as fl:
|
|
fl.write(content)
|
|
|
|
def check_case_option(self, case_option):
|
|
if not case_option:
|
|
return 1
|
|
opts = case_option.split("::")
|
|
if len(opts) != 2:
|
|
print("case option must like aaa/bbb/ccc.c::test_playback_uv_01")
|
|
return 1
|
|
else:
|
|
self.case_path = opts[0]
|
|
self.case_name = opts[1]
|
|
if not self.case_name.startswith("test"):
|
|
print("case function name start with 'test'")
|
|
return 1
|
|
paths = self.case_path.split("/")
|
|
if not paths[-1].endswith(".c"):
|
|
print("case option must like aaa/bbb/ccc.c::VelaAutoTestcase")
|
|
return 1
|
|
file_parts = paths[-1].split("_")
|
|
pattern = r"[0-9]{2,3}\.c$"
|
|
if file_parts[0] != "test":
|
|
print("case file name must start with 'test'")
|
|
return 1
|
|
elif not re.search(pattern, file_parts[-1]):
|
|
print("case file name must end with '00-99' or '000-999'")
|
|
return 1
|
|
else:
|
|
self.case_file = paths[-1]
|
|
return 0
|
|
|
|
def generate_case(self):
|
|
content = copy.deepcopy(TESTCASE_TEMPLATE)
|
|
content = content.replace("{case_file}", self.case_file)
|
|
content = content.replace("{case_name}", self.case_name)
|
|
full_path = os.path.join(self.path, self.case_path)
|
|
dir_path = os.path.dirname(full_path)
|
|
if not os.path.exists(dir_path):
|
|
os.makedirs(dir_path)
|
|
with open(full_path, "w") as fl:
|
|
fl.write(content)
|
|
|
|
def main(self, suite_option, case_option):
|
|
try:
|
|
if self.check_path():
|
|
return
|
|
if not self.check_suite_option(suite_option):
|
|
self.generate_suite()
|
|
print("generate suite success")
|
|
if not self.check_case_option(case_option):
|
|
self.generate_case()
|
|
print("generate case success")
|
|
except Exception:
|
|
traceback.print_exc()
|
|
|
|
|
|
app = typer.Typer()
|
|
|
|
|
|
@app.command()
|
|
def main(
|
|
path: str = typer.Option("", help="where to gnerate suite/case file"),
|
|
suite: str = typer.Option(
|
|
default="",
|
|
help="suite file name and suite function name, path/suite::name, eg aaa/bbb/ccc.c::VelaAutoTestcase",
|
|
),
|
|
case: str = typer.Option(
|
|
default="",
|
|
help="case file name and case function name, path/case::function, eg ddd/eee/fff.c::test_playback_uv_01",
|
|
),
|
|
):
|
|
"""
|
|
:param path: where to gnerate suite/case file
|
|
:param suite: suite file name and suite function name
|
|
:param case: case file name and case function name
|
|
:return:
|
|
"""
|
|
gen = CmockaGen(path)
|
|
gen.main(suite, case)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app()
|