Test.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  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. // To know if parameter array is malloc buffer or static buffer in C array
  89. enum ParameterKind
  90. {
  91. kStaticBuffer=0,
  92. kDynamicBuffer=1,
  93. };
  94. }
  95. namespace Client
  96. {
  97. /*
  98. Client code
  99. */
  100. class Suite;
  101. class Group;
  102. // Type of a test function
  103. // It is not a function pointer (because the function is
  104. // a method of a CPP class)
  105. typedef void (Suite::*test)();
  106. /*
  107. API of Memory managers used in the test framework
  108. */
  109. class Memory
  110. {
  111. public:
  112. // Allocate a new buffer of size length
  113. // and generate a pointer to this buffer.
  114. // It does not imply that any malloc is done.
  115. // It depends on how the Memory manager is implemented.
  116. virtual char *NewBuffer(size_t length)=0;
  117. // Free all the memory allocated by the memory manager
  118. // and increment the memory generation number.
  119. virtual void FreeMemory()=0;
  120. // Memory allocation errors must be tracked during a test.
  121. // The runner should force the test status to FAILED
  122. // when a memory error occured.
  123. virtual bool HasMemError()=0;
  124. // When memory manager is supporting tail
  125. // then we can check that the tail of the buffer has not been
  126. // corrupted.
  127. // The tail being the additional words after the end of the buffer allocated
  128. // by the memory manager so that there is some seperation between
  129. // successive buffers.
  130. // When memory manager is not supporting tail, this function should
  131. // always succeed.
  132. virtual bool IsTailEmpty(char *, size_t)=0;
  133. // Get the memory generation number
  134. unsigned long generation()
  135. {
  136. return(m_generation);
  137. }
  138. protected:
  139. unsigned long m_generation=0;
  140. };
  141. // A runner is a class driving the tests
  142. // It can use information from driving files
  143. // or in the future could communicate with a process
  144. // on a host computer which would be the real driver of the
  145. // testing.
  146. // It is following the visitor pattern. IT is the reason for an accept
  147. // function in Group class.
  148. // Run is the visitor
  149. class Runner
  150. {
  151. public:
  152. virtual Testing::TestStatus run(Suite*) = 0;
  153. virtual Testing::TestStatus run(Group*) = 0;
  154. };
  155. // Abstract the IO needs of the test framework.
  156. // IO could be done from semihosting, socket, C array in memory etc ...
  157. class IO
  158. {
  159. public:
  160. /** Read the identification of a node from driver data.
  161. Update the node kind and node id and local folder.
  162. To be used for group and suite. Generally update
  163. the path to the folder by using this new local folder
  164. which is appended to the path.
  165. */
  166. virtual void ReadIdentification()=0;
  167. /** Read the identification of a node driver data.
  168. Update the node kind and node id and local folder.
  169. */
  170. virtual void ReadTestIdentification()=0;
  171. /** Read the number of parameters for all the tests in a suite
  172. Used for benchmarking. Same functions executed with
  173. different initializations controlled by the parameters.
  174. */
  175. virtual Testing::nbParameters_t ReadNbParameters()=0;
  176. /** Dump the test status
  177. For format of output, refer to Python script.
  178. The format must be coherent with the Python script
  179. parsing the output.
  180. */
  181. virtual void DispStatus(Testing::TestStatus,Testing::errorID_t,unsigned long,Testing::cycles_t cycles)=0;
  182. /** Dump additional details for the error
  183. For instance, for SNR error, it may contain the SNR value.
  184. */
  185. virtual void DispErrorDetails(const char* )=0;
  186. /** Dump parameters for a test
  187. When a test is run several time with different
  188. parameters for benchmarking,
  189. the parameters are displayed after test status.
  190. Line should begin with b
  191. */
  192. virtual void DumpParams(std::vector<Testing::param_t>&)=0;
  193. /** Dump an end of group/suite to output
  194. Used by Python script parsing the output.
  195. */
  196. virtual void EndGroup()=0;
  197. /** Get the zize of a pattern in this suite.
  198. Pattern is identified with an ID.
  199. Using the local path and ID, the IO implementatiom should
  200. be able to access the pattern.
  201. The path do not have to be a file path. Just a way
  202. to identify patterns in a suite and know
  203. how to access them.
  204. */
  205. virtual Testing::nbSamples_t GetPatternSize(Testing::PatternID_t)=0;
  206. /** Get the size of a parameter pattern in this suite.
  207. Parameter is identified with an ID.
  208. Using the local path and ID, the IO implementatiom should
  209. be able to access the data.
  210. The path do not have to be a file path. Just a way
  211. to identify data in a suite and know
  212. how to access them.
  213. */
  214. //virtual Testing::nbSamples_t GetParameterSize(Testing::PatternID_t id)=0;
  215. /** Check if some parameters are controlling this test
  216. */
  217. virtual bool hasParam()=0;
  218. /** Get ID of parameter generator
  219. */
  220. virtual Testing::PatternID_t getParamID()=0;
  221. /** Import pattern.
  222. The nb field can be used to limit the number of samples read
  223. to a smaller value than the number of samples available in the
  224. pattern.
  225. */
  226. virtual void ImportPattern_f64(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  227. virtual void ImportPattern_f32(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  228. virtual void ImportPattern_q63(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  229. virtual void ImportPattern_q31(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  230. virtual void ImportPattern_q15(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  231. virtual void ImportPattern_q7(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  232. virtual void ImportPattern_u32(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  233. virtual void ImportPattern_u16(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  234. virtual void ImportPattern_u8(Testing::PatternID_t,char*,Testing::nbSamples_t nb=MAX_NB_SAMPLES)=0;
  235. /** Import params.
  236. This is allocating memory.
  237. The runner should free it after use.
  238. It is not using the Memory manager since tests don't have access
  239. to the array of parameters.
  240. They receive parameters as a vector argument for the setUp fucntion.
  241. */
  242. virtual Testing::param_t* ImportParams(Testing::PatternID_t,Testing::nbParameterEntries_t &,Testing::ParameterKind &)=0;
  243. /** Dump pattern.
  244. The output ID (and test ID) must be used to uniquely identify
  245. the dump.
  246. */
  247. virtual void DumpPattern_f64(Testing::outputID_t,Testing::nbSamples_t nb, float64_t*)=0;
  248. virtual void DumpPattern_f32(Testing::outputID_t,Testing::nbSamples_t nb, float32_t*)=0;
  249. virtual void DumpPattern_q63(Testing::outputID_t,Testing::nbSamples_t nb, q63_t*)=0;
  250. virtual void DumpPattern_q31(Testing::outputID_t,Testing::nbSamples_t nb, q31_t*)=0;
  251. virtual void DumpPattern_q15(Testing::outputID_t,Testing::nbSamples_t nb, q15_t*)=0;
  252. virtual void DumpPattern_q7(Testing::outputID_t,Testing::nbSamples_t nb, q7_t*)=0;
  253. virtual void DumpPattern_u32(Testing::outputID_t,Testing::nbSamples_t nb, uint32_t*)=0;
  254. virtual void DumpPattern_u16(Testing::outputID_t,Testing::nbSamples_t nb, uint16_t*)=0;
  255. virtual void DumpPattern_u8(Testing::outputID_t,Testing::nbSamples_t nb, uint8_t*)=0;
  256. /** Import list of patterns from the driver
  257. for current suite.
  258. This list is used to identify a pattern from its pattern ID.
  259. The information of this list (local to the suite) is
  260. combined with the path to identify patterns in other part of the class.
  261. */
  262. virtual void ReadPatternList()=0;
  263. /** Import list of output from the driver
  264. for current suite.
  265. This list is used to identify an output from its pattern ID (and current test ID)
  266. The information of this list (local to the suite) is
  267. combined with the path and current test ID
  268. to identify output in other part of the class.
  269. */
  270. virtual void ReadOutputList()=0;
  271. /** Import list of parameters from the driver
  272. for current suite.
  273. This list is used to control a functions with different parameters
  274. for benchmarking purpose.
  275. A parameter can be a file of parameters or a generator
  276. of parameters (cartesian product of lists only).
  277. */
  278. virtual void ReadParameterList(Testing::nbParameters_t)=0;
  279. /** Get current node ID
  280. group, suite or test. A group of test is considered as a test hence
  281. the name of the function.
  282. */
  283. virtual Testing::testID_t CurrentTestID()=0;
  284. };
  285. // A pattern manager is making the link between
  286. // IO and the Memory manager.
  287. // It knows how to import patterns into memory or dump
  288. // memory into outputs (output which may be different from a file)
  289. // The running mode is controlling if dumping is disabled or not.
  290. // But cna also be used by the runner to know if test results must be ignored or not.
  291. // Pattern manager is used by the tests
  292. // In current version load and dump functions are visible to any body.
  293. // In theory they should only be visible to Patterns
  294. class PatternMgr
  295. {
  296. public:
  297. PatternMgr(IO*,Memory*);
  298. /** In those loading APIs, nb samples is coming from the pattern read.
  299. maxSamples is coming from the test.
  300. A test does not know what is the length of a pattern since the test
  301. has no visiblity on how the pattern is imported (file, serial port, include files
  302. etc ...).
  303. So the test is specifying the max sampls it needs.
  304. The pattern is specifying its lengths.
  305. Those functions are importing at most what is needed and what is available.
  306. */
  307. float64_t *load_f64(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  308. float32_t *load_f32(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  309. q63_t *load_q63(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  310. q31_t *load_q31(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  311. q15_t *load_q15(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  312. q7_t *load_q7(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  313. uint32_t *load_u32(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  314. uint16_t *load_u16(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  315. uint8_t *load_u8(Testing::PatternID_t,Testing::nbSamples_t&,Testing::nbSamples_t maxSamples=MAX_NB_SAMPLES);
  316. /** Create a local pattern.
  317. Generally it is used as output of a test and has no
  318. correspondance to a pattern in the suite.
  319. */
  320. float64_t *local_f64(Testing::nbSamples_t);
  321. float32_t *local_f32(Testing::nbSamples_t);
  322. q63_t *local_q63(Testing::nbSamples_t);
  323. q31_t *local_q31(Testing::nbSamples_t);
  324. q15_t *local_q15(Testing::nbSamples_t);
  325. q7_t *local_q7(Testing::nbSamples_t);
  326. uint32_t *local_u32(Testing::nbSamples_t);
  327. uint16_t *local_u16(Testing::nbSamples_t);
  328. uint8_t *local_u8(Testing::nbSamples_t);
  329. /** Dump a pattern
  330. */
  331. void dumpPattern_f64(Testing::outputID_t,Testing::nbSamples_t,float64_t*);
  332. void dumpPattern_f32(Testing::outputID_t,Testing::nbSamples_t,float32_t*);
  333. void dumpPattern_q63(Testing::outputID_t,Testing::nbSamples_t,q63_t*);
  334. void dumpPattern_q31(Testing::outputID_t,Testing::nbSamples_t,q31_t*);
  335. void dumpPattern_q15(Testing::outputID_t,Testing::nbSamples_t,q15_t*);
  336. void dumpPattern_q7(Testing::outputID_t,Testing::nbSamples_t,q7_t*);
  337. void dumpPattern_u32(Testing::outputID_t,Testing::nbSamples_t,uint32_t*);
  338. void dumpPattern_u16(Testing::outputID_t,Testing::nbSamples_t,uint16_t*);
  339. void dumpPattern_u8(Testing::outputID_t,Testing::nbSamples_t,uint8_t*);
  340. /** Free all allocated patterns.
  341. Just wrapper around the memory manager free function.
  342. */
  343. void freeAll();
  344. /** MeMory manager generation
  345. */
  346. unsigned long generation()
  347. {
  348. return(m_mem->generation());
  349. }
  350. // Memory allocation errors must be tracked during a test.
  351. // The runner should force the test status to FAILED
  352. // when a memory error occured.
  353. bool HasMemError()
  354. {
  355. return(m_mem->HasMemError());
  356. }
  357. // Set by the runner when in dump mode
  358. void setDumpMode()
  359. {
  360. this->m_runningMode = Testing::kDumpOnly;
  361. }
  362. void setTestAndDumpMode()
  363. {
  364. this->m_runningMode = Testing::kTestAndDump;
  365. }
  366. Testing::RunningMode runningMode()
  367. {
  368. return(this->m_runningMode);
  369. }
  370. bool IsTailEmpty(char *ptr, size_t length)
  371. {
  372. return(m_mem->IsTailEmpty(ptr,length));
  373. }
  374. private:
  375. IO *m_io;
  376. Memory *m_mem;
  377. Testing::RunningMode m_runningMode=Testing::kTestOnly;
  378. };
  379. // TestContainer which is a node of the tree of tests
  380. class TestContainer
  381. {
  382. public:
  383. TestContainer(Testing::testID_t);
  384. // Used for implementing the visitor pattern.
  385. // The visitor pattern is allowing to implement
  386. // different Runner for a tree of tests.
  387. virtual Testing::TestStatus accept(Runner* v) = 0;
  388. protected:
  389. // Node ID (test ID)
  390. Testing::testID_t m_containerID;
  391. };
  392. // A suite object
  393. // It contains a list of tests
  394. // Methods to get a test from the test ID
  395. // Initialization and cleanup (setUp and tearDown) to be called
  396. // between each test.
  397. // Those functions are used by the Runner to execute the tests
  398. class Suite:public TestContainer
  399. {
  400. public:
  401. Suite(Testing::testID_t);
  402. // Prepare memory for a test
  403. // (Load input and reference patterns)
  404. virtual void setUp(Testing::testID_t,std::vector<Testing::param_t>&,PatternMgr *mgr)=0;
  405. // Clean memory after a test
  406. // Free all memory
  407. // DUmp outputs
  408. virtual void tearDown(Testing::testID_t,PatternMgr *mgr)=0;
  409. // Add a test to be run.
  410. void addTest(Testing::testID_t,test aTest);
  411. // Get a test from its index. Used by runner when iterating
  412. // on all the tests. Index is not the test ID.
  413. // It is the index in internal list of tests
  414. test getTest(Testing::testIndex_t);
  415. // Get number of test in this suite.
  416. // The suite is only containing the active tests
  417. // (deprecated tests are never generated by python scripts)
  418. int getNbTests();
  419. // Used for implementing the visitor pattern.
  420. // The visitor pattern is allowing to implement
  421. // different Runner for a tree of tests.
  422. virtual Testing::TestStatus accept(Runner* v) override
  423. {
  424. return(v->run(this));
  425. }
  426. private:
  427. // List of tests
  428. std::vector<test> m_tests;
  429. // List of tests IDs (since they are not contiguous
  430. // due to deprecation feature in python scripts)
  431. std::vector<Testing::testID_t> m_testIds;
  432. };
  433. // A group
  434. // It is possible to add subgroups to a group
  435. // and get a subgroup from its ID.
  436. class Group:public TestContainer
  437. {
  438. public:
  439. Group(Testing::testID_t);
  440. // Add a group or suite to this group.
  441. void addContainer(TestContainer*);
  442. // Get a container from its index. (index is not the node ID)
  443. TestContainer *getContainer(Testing::testIndex_t);
  444. // Get number of containers
  445. int getNbContainer();
  446. virtual Testing::TestStatus accept(Runner* v) override
  447. {
  448. return(v->run(this));
  449. }
  450. public:
  451. std::vector<TestContainer*> m_groups;
  452. };
  453. }
  454. #endif