Test.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. /* ----------------------------------------------------------------------
  2. * Project: CMSIS DSP Library
  3. * Title: Test.h
  4. * Description: Test Framework Header
  5. *
  6. * $Date: 20. June 2019
  7. * $Revision: V1.0.0
  8. *
  9. * Target Processor: Cortex-M cores
  10. * -------------------------------------------------------------------- */
  11. /*
  12. * Copyright (C) 2010-2019 ARM Limited or its affiliates. All rights reserved.
  13. *
  14. * SPDX-License-Identifier: Apache-2.0
  15. *
  16. * Licensed under the Apache License, Version 2.0 (the License); you may
  17. * not use this file except in compliance with the License.
  18. * You may obtain a copy of the License at
  19. *
  20. * www.apache.org/licenses/LICENSE-2.0
  21. *
  22. * Unless required by applicable law or agreed to in writing, software
  23. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  24. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  25. * See the License for the specific language governing permissions and
  26. * limitations under the License.
  27. */
  28. #ifndef _TEST_H_
  29. #define _TEST_H_
  30. #include <cstdlib>
  31. #include <vector>
  32. #include <queue>
  33. #include <cstdio>
  34. #include "arm_math.h"
  35. // This special value means no limit on the number of samples.
  36. // It is used when importing patterns and we want to read
  37. // all the samples contained in the pattern.
  38. #define MAX_NB_SAMPLES 0
  39. // Pattern files are containing hexadecimal values.
  40. // So we need to be able to convert some int into float without convertion
  41. #define TOINT32(v) *((uint32_t*)&v)
  42. #define TOINT64(v) *((uint64_t*)&v)
  43. // Or convert some float into a uint32 or uint64 without convertion
  44. #define TOTYP(TYP,v) *((TYP*)&v)
  45. // So it is a cast and not a data conversion.
  46. // (uint32_t)1.0 would give 1. We want the hexadecimal representation of the float.
  47. // TOINT32(1.0) can be used
  48. namespace Testing
  49. {
  50. enum TestStatus
  51. {
  52. kTestFailed=0,
  53. kTestPassed=1
  54. };
  55. /* In Dump only, reference patterns are never read.
  56. So tests are failing
  57. and we dump output.
  58. In this mode we are only interested in the output data and
  59. not the test status.
  60. In test only mode, no output is dumped.
  61. */
  62. enum RunningMode
  63. {
  64. kTestOnly=0,
  65. kDumpOnly=1,
  66. kTestAndDump=2
  67. };
  68. // test ID are ID of nodes in the tree of tests.
  69. // So a group ID, suite ID or test ID all have the same type
  70. // testID_t
  71. typedef unsigned long testID_t;
  72. typedef unsigned long outputID_t;
  73. typedef unsigned long PatternID_t;
  74. typedef unsigned long testIndex_t;
  75. typedef unsigned long nbSamples_t;
  76. typedef unsigned long errorID_t;
  77. typedef uint32_t cycles_t;
  78. typedef unsigned long nbMeasurements_t;
  79. // parameter value
  80. // (always int since we need to be able to iterate on
  81. // different parameter values which are often dimensions of
  82. // input data)
  83. typedef int param_t;
  84. // Number of parameters for a given configuration
  85. typedef unsigned long nbParameters_t;
  86. // Number of parameter configurations
  87. typedef unsigned long nbParameterEntries_t;
  88. }
  89. namespace Client
  90. {
  91. /*
  92. Client code
  93. */
  94. class Suite;
  95. class Group;
  96. // Type of a test function
  97. // It is not a function pointer (because the function is
  98. // a method of a CPP class)
  99. typedef void (Suite::*test)();
  100. /*
  101. API of Memory managers used in the test framework
  102. */
  103. class Memory
  104. {
  105. public:
  106. // Allocate a new buffer of size length
  107. // and generate a pointer to this buffer.
  108. // It does not imply that any malloc is done.
  109. // It depends on how the Memory manager is implemented.
  110. virtual char *NewBuffer(size_t length)=0;
  111. // Free all the memory allocated by the memory manager
  112. // and increment the memory generation number.
  113. virtual void FreeMemory()=0;
  114. // Get the memory generation number
  115. unsigned long generation()
  116. {
  117. return(m_generation);
  118. }
  119. protected:
  120. unsigned long m_generation=0;
  121. };
  122. // A runner is a class driving the tests
  123. // It can use information from driving files
  124. // or in the future could communicate with a process
  125. // on a host computer which would be the real driver of the
  126. // testing.
  127. // It is following the visitor pattern. IT is the reason for an accept
  128. // function in Group class.
  129. // Run is the visitor
  130. class Runner
  131. {
  132. public:
  133. virtual Testing::TestStatus run(Suite*) = 0;
  134. virtual Testing::TestStatus run(Group*) = 0;
  135. };
  136. // Abstract the IO needs of the test framework.
  137. // IO could be done from semihosting, socket, C array in memory etc ...
  138. class IO
  139. {
  140. public:
  141. /** Read the identification of a node from driver data.
  142. Update the node kind and node id and local folder.
  143. To be used for group and suite. Generally update
  144. the path to the folder by using this new local folder
  145. which is appended to the path.
  146. */
  147. virtual void ReadIdentification()=0;
  148. /** Read the identification of a node driver data.
  149. Update the node kind and node id and local folder.
  150. */
  151. virtual void ReadTestIdentification()=0;
  152. /** Read the number of parameters for all the tests in a suite
  153. Used for benchmarking. Same functions executed with
  154. different initializations controlled by the parameters.
  155. */
  156. virtual Testing::nbParameters_t ReadNbParameters()=0;
  157. /** Dump the test status
  158. For format of output, refer to Python script.
  159. The format must be coherent with the Python script
  160. parsing the output.
  161. */
  162. virtual void DispStatus(Testing::TestStatus,Testing::errorID_t,unsigned long,Testing::cycles_t cycles)=0;
  163. /** Dump parameters for a test
  164. When a test is run several time with different
  165. parameters for benchmarking,
  166. the parameters are displayed after test status.
  167. Line should begin with b
  168. */
  169. virtual void DumpParams(std::vector<Testing::param_t>&)=0;
  170. /** Dump an end of group/suite to output
  171. Used by Python script parsing the output.
  172. */
  173. virtual void EndGroup()=0;
  174. /** Get the zize of a pattern in this suite.
  175. Pattern is identified with an ID.
  176. Using the local path and ID, the IO implementatiom should
  177. be able to access the pattern.
  178. The path do not have to be a file path. Just a way
  179. to identify patterns in a suite and know
  180. how to access them.
  181. */
  182. virtual Testing::nbSamples_t GetPatternSize(Testing::PatternID_t)=0;
  183. /** Get the size of a parameter pattern in this suite.
  184. Parameter is identified with an ID.
  185. Using the local path and ID, the IO implementatiom should
  186. be able to access the data.
  187. The path do not have to be a file path. Just a way
  188. to identify data in a suite and know
  189. how to access them.
  190. */
  191. //virtual Testing::nbSamples_t GetParameterSize(Testing::PatternID_t id)=0;
  192. /** Check if some parameters are controlling this test
  193. */
  194. virtual bool hasParam()=0;
  195. /** Get ID of parameter generator
  196. */
  197. virtual Testing::PatternID_t getParamID()=0;
  198. /** Import pattern.
  199. The nb field can be used to limit the number of samples read
  200. to a smaller value than the number of samples available in the
  201. pattern.
  202. */
  203. virtual void ImportPattern_f64(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  204. virtual void ImportPattern_f32(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  205. virtual void ImportPattern_q31(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  206. virtual void ImportPattern_q15(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  207. virtual void ImportPattern_q7(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  208. virtual void ImportPattern_u32(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  209. virtual void ImportPattern_u16(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  210. virtual void ImportPattern_u8(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  211. /** Import params.
  212. This is allocating memory.
  213. The runner should free it after use.
  214. It is not using the Memory manager since tests don't have access
  215. to the array of parameters.
  216. They receive parameters as a vector argument for the setUp fucntion.
  217. */
  218. virtual Testing::param_t* ImportParams(Testing::PatternID_t,Testing::nbParameterEntries_t &)=0;
  219. /** Dump pattern.
  220. The output ID (and test ID) must be used to uniquely identify
  221. the dump.
  222. */
  223. virtual void DumpPattern_f64(Testing::outputID_t,Testing::nbSamples_t nb, float64_t*)=0;
  224. virtual void DumpPattern_f32(Testing::outputID_t,Testing::nbSamples_t nb, float32_t*)=0;
  225. virtual void DumpPattern_q31(Testing::outputID_t,Testing::nbSamples_t nb, q31_t*)=0;
  226. virtual void DumpPattern_q15(Testing::outputID_t,Testing::nbSamples_t nb, q15_t*)=0;
  227. virtual void DumpPattern_q7(Testing::outputID_t,Testing::nbSamples_t nb, q7_t*)=0;
  228. virtual void DumpPattern_u32(Testing::outputID_t,Testing::nbSamples_t nb, uint32_t*)=0;
  229. virtual void DumpPattern_u16(Testing::outputID_t,Testing::nbSamples_t nb, uint16_t*)=0;
  230. virtual void DumpPattern_u8(Testing::outputID_t,Testing::nbSamples_t nb, uint8_t*)=0;
  231. /** Import list of patterns from the driver
  232. for current suite.
  233. This list is used to identify a pattern from its pattern ID.
  234. The information of this list (local to the suite) is
  235. combined with the path to identify patterns in other part of the class.
  236. */
  237. virtual void ReadPatternList()=0;
  238. /** Import list of output from the driver
  239. for current suite.
  240. This list is used to identify an output from its pattern ID (and current test ID)
  241. The information of this list (local to the suite) is
  242. combined with the path and current test ID
  243. to identify output in other part of the class.
  244. */
  245. virtual void ReadOutputList()=0;
  246. /** Import list of parameters from the driver
  247. for current suite.
  248. This list is used to control a functions with different parameters
  249. for benchmarking purpose.
  250. A parameter can be a file of parameters or a generator
  251. of parameters (cartesian product of lists only).
  252. */
  253. virtual void ReadParameterList(Testing::nbParameters_t)=0;
  254. /** Get current node ID
  255. group, suite or test. A group of test is considered as a test hence
  256. the name of the function.
  257. */
  258. virtual Testing::testID_t CurrentTestID()=0;
  259. };
  260. // A pattern manager is making the link between
  261. // IO and the Memory manager.
  262. // It knows how to import patterns into memory or dump
  263. // memory into outputs (output which may be different from a file)
  264. // The running mode is controlling if dumping is disabled or not.
  265. // But cna also be used by the runner to know if test results must be ignored or not.
  266. // Pattern manager is used by the tests
  267. // In current version load and dump functions are visible to any body.
  268. // In theory they should only be visible to Patterns
  269. class PatternMgr
  270. {
  271. public:
  272. PatternMgr(IO*,Memory*);
  273. /** In those loading APIs, nb samples is coming from the pattern read.
  274. maxSamples is coming from the test.
  275. A test does not know what is the length of a pattern since the test
  276. has no visiblity on how the pattern is imported (file, serial port, include files
  277. etc ...).
  278. So the test is specifying the max sampls it needs.
  279. The pattern is specifying its lengths.
  280. Those functions are importing at most what is needed and what is available.
  281. */
  282. float64_t *load_f64(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  283. float32_t *load_f32(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  284. q31_t *load_q31(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  285. q15_t *load_q15(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  286. q7_t *load_q7(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  287. uint32_t *load_u32(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  288. uint16_t *load_u16(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  289. uint8_t *load_u8(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  290. /** Create a local pattern.
  291. Generally it is used as output of a test and has no
  292. correspondance to a pattern in the suite.
  293. */
  294. float64_t *local_f64(Testing::nbSamples_t);
  295. float32_t *local_f32(Testing::nbSamples_t);
  296. q31_t *local_q31(Testing::nbSamples_t);
  297. q15_t *local_q15(Testing::nbSamples_t);
  298. q7_t *local_q7(Testing::nbSamples_t);
  299. uint32_t *local_u32(Testing::nbSamples_t);
  300. uint16_t *local_u16(Testing::nbSamples_t);
  301. uint8_t *local_u8(Testing::nbSamples_t);
  302. /** Dump a pattern
  303. */
  304. void dumpPattern_f64(Testing::outputID_t,Testing::nbSamples_t,float64_t*);
  305. void dumpPattern_f32(Testing::outputID_t,Testing::nbSamples_t,float32_t*);
  306. void dumpPattern_q31(Testing::outputID_t,Testing::nbSamples_t,q31_t*);
  307. void dumpPattern_q15(Testing::outputID_t,Testing::nbSamples_t,q15_t*);
  308. void dumpPattern_q7(Testing::outputID_t,Testing::nbSamples_t,q7_t*);
  309. void dumpPattern_u32(Testing::outputID_t,Testing::nbSamples_t,uint32_t*);
  310. void dumpPattern_u16(Testing::outputID_t,Testing::nbSamples_t,uint16_t*);
  311. void dumpPattern_u8(Testing::outputID_t,Testing::nbSamples_t,uint8_t*);
  312. /** Free all allocated patterns.
  313. Just wrapper around the memory manager free function.
  314. */
  315. void freeAll();
  316. /** MEMory manager generation
  317. */
  318. unsigned long generation()
  319. {
  320. return(m_mem->generation());
  321. }
  322. // Set by the runner when in dump mode
  323. void setDumpMode()
  324. {
  325. this->m_runningMode = Testing::kDumpOnly;
  326. }
  327. void setTestAndDumpMode()
  328. {
  329. this->m_runningMode = Testing::kTestAndDump;
  330. }
  331. Testing::RunningMode runningMode()
  332. {
  333. return(this->m_runningMode);
  334. }
  335. private:
  336. IO *m_io;
  337. Memory *m_mem;
  338. Testing::RunningMode m_runningMode=Testing::kTestOnly;
  339. };
  340. // TestContainer which is a node of the tree of tests
  341. class TestContainer
  342. {
  343. public:
  344. TestContainer(Testing::testID_t);
  345. // Used for implementing the visitor pattern.
  346. // The visitor pattern is allowing to implement
  347. // different Runner for a tree of tests.
  348. virtual Testing::TestStatus accept(Runner* v) = 0;
  349. protected:
  350. // Node ID (test ID)
  351. Testing::testID_t m_containerID;
  352. };
  353. // A suite object
  354. // It contains a list of tests
  355. // Methods to get a test from the test ID
  356. // Initialization and cleanup (setUp and tearDown) to be called
  357. // between each test.
  358. // Those functions are used by the Runner to execute the tests
  359. class Suite:public TestContainer
  360. {
  361. public:
  362. Suite(Testing::testID_t);
  363. // Prepare memory for a test
  364. // (Load input and reference patterns)
  365. virtual void setUp(Testing::testID_t,std::vector<Testing::param_t>&,PatternMgr *mgr)=0;
  366. // Clean memory after a test
  367. // Free all memory
  368. // DUmp outputs
  369. virtual void tearDown(Testing::testID_t,PatternMgr *mgr)=0;
  370. // Add a test to be run.
  371. void addTest(Testing::testID_t,test aTest);
  372. // Get a test from its index. Used by runner when iterating
  373. // on all the tests. Index is not the test ID.
  374. // It is the index in internal list of tests
  375. test getTest(Testing::testIndex_t);
  376. // Get number of test in this suite.
  377. // The suite is only containing the active tests
  378. // (deprecated tests are never generated by python scripts)
  379. int getNbTests();
  380. // Used for implementing the visitor pattern.
  381. // The visitor pattern is allowing to implement
  382. // different Runner for a tree of tests.
  383. virtual Testing::TestStatus accept(Runner* v) override
  384. {
  385. return(v->run(this));
  386. }
  387. private:
  388. // List of tests
  389. std::vector<test> m_tests;
  390. // List of tests IDs (since they are not contiguous
  391. // due to deprecation feature in python scripts)
  392. std::vector<Testing::testID_t> m_testIds;
  393. };
  394. // A group
  395. // It is possible to add subgroups to a group
  396. // and get a subgroup from its ID.
  397. class Group:public TestContainer
  398. {
  399. public:
  400. Group(Testing::testID_t);
  401. // Add a group or suite to this group.
  402. void addContainer(TestContainer*);
  403. // Get a container from its index. (index is not the node ID)
  404. TestContainer *getContainer(Testing::testIndex_t);
  405. // Get number of containers
  406. int getNbContainer();
  407. virtual Testing::TestStatus accept(Runner* v) override
  408. {
  409. return(v->run(this));
  410. }
  411. public:
  412. std::vector<TestContainer*> m_groups;
  413. };
  414. }
  415. #endif