-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TODO - Split into serialWrapper (first) and test execution (second) commits - Make Ethan a co-author of the seriaLWrapper commit: https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors
- Loading branch information
Showing
7 changed files
with
331 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
#include "serialWrapper.h" | ||
|
||
|
||
/** | ||
* Reads in a line of text, excluding newline | ||
* Writes a null-terminated string into the provided destination buffer | ||
* | ||
* Parameters: | ||
* dest: Pointer to destination buffer | ||
* buffSize: Size of destination buffer | ||
* * NOTE: Although the newline is not included in the final buffer | ||
* contents, you must ensure that buffSize accounts for both | ||
* the newline and null-terminator at the end of the buffer | ||
* timeout: Time (in milliseconds) to wait for a line to be read | ||
* * If timeout is negative, this will not time out | ||
* * Default timeout is 10000ms (10s) | ||
* | ||
* Returns: | ||
* size_t: Length of string written to buffer or -1 on error or timeout | ||
**/ | ||
size_t SerialWrapper::readLine(char* dest, size_t buffSize, int timeout) { | ||
// Length of string stored in character buffer | ||
size_t strlen = 0; | ||
// Stores value returned by BufferedSerial.read() | ||
int err = 0; | ||
// Calling printf within loop is too slow | ||
bool overflow = false; | ||
// Whether or not there is a timeout | ||
bool canTimeout = timeout >= 0; | ||
|
||
while(1) { | ||
// Check for buffer overflow before read | ||
/*TODO if(strlen >= BUFFER_SIZE) { | ||
overflow = true; | ||
break; | ||
}*/ | ||
|
||
// Read in from serial | ||
if((err = this->read(dest + strlen, buffSize)) > 0) { | ||
strlen += err; | ||
// TODO Check for buffer overflow after read | ||
if(strlen >= buffSize) { | ||
overflow = true; | ||
break; | ||
} | ||
// Convert to string | ||
dest[strlen] = '\0'; | ||
|
||
// Check for newline | ||
char* newline; // Location of newline | ||
char n[2] {'\n', '\0'}; // Newline character string TODO Any particular reason 0xd was used instead of '\n'? | ||
if((newline = strstr(dest, n)) != NULL) { | ||
// Change \n to \0 | ||
*newline = '\0'; | ||
strlen = newline - dest; | ||
break; | ||
} | ||
} else if(err == 0) { | ||
// Nothing read | ||
if(canTimeout) { | ||
if(timeout <= 0) { | ||
// Time out | ||
return -1; | ||
} | ||
ThisThread::sleep_for(100ms); | ||
timeout -= 100; | ||
} | ||
} else { | ||
// Error reading from buffer | ||
return -1; | ||
} | ||
} | ||
|
||
if(overflow) { | ||
// Buffer overflow | ||
return -1; | ||
} | ||
|
||
return strlen; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#ifndef __SERIAL_WRAPPER_H__ | ||
#define __SERIAL_WRAPPER_H__ | ||
|
||
#include "mbed.h" | ||
#include <string.h> | ||
|
||
// TODO REMOVE: #define BUFFER_SIZE 16 | ||
|
||
class SerialWrapper : public BufferedSerial { | ||
public: | ||
SerialWrapper(PinName tx, PinName rx, int baud=MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE): BufferedSerial(tx, rx, baud) {}; | ||
size_t readLine(char* dest, size_t buffSize, int timeout=10000); | ||
|
||
// TODO private: | ||
// BufferedSerial *serial; | ||
|
||
}; | ||
|
||
#endif // __SERIAL_WRAPPER_H__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# Tests | ||
This is where all test classes will be defined. | ||
|
||
## Creating a New Test Class | ||
All custom test classes must inherit the base `Test` class, as it defines a standard test structure that is required for communicating with the [BTF](https://github.com/badgerloop-software/BTF) test runner. Additionally, `test.h` provides a declaration of `pc`, a `SerialWrapper` object for communicating with the BTF test runner. The following is an example custom test class with implementation notes: | ||
```cpp | ||
#ifndef __CUSTOM_TEST__ | ||
#define __CUSTOM_TEST__ | ||
|
||
#include "test.h" | ||
#include <string> | ||
|
||
using namespace std; | ||
|
||
|
||
class CustomTest : public Test { | ||
public: | ||
// REQUIRED: Pass the name of the test to the base class' constructor | ||
// The test name should be formatted as shown below, using the keys from tests.yml | ||
// NOTE: If multiple tests have the same setup() and teardown(), you could use | ||
// `CustomTest(const string name): Test(name) {` to run different tests in runTest() | ||
// based on the name and save on redefining setup() and teardown() | ||
CustomTest(): Test("<driver>_<test_name>") { | ||
// Add initialization here | ||
}; | ||
private: | ||
// OPTIONAL: Test setup. If not defined, there is no setup | ||
// This is called before starting the test in the BTF | ||
void setup() { | ||
// Add custom setup here | ||
} | ||
|
||
// REQUIRED: Main test content | ||
// Returns true if test passes, false otherwise | ||
bool runTest() { | ||
char buf[5]; | ||
// You can use printf() and the pc object to communicate with the BTF | ||
printf("foo\n"); // pc.write() also works | ||
pc.readLine(buff, sizeof(buff)); | ||
if(strcmp(buff, "bar") == 0) { | ||
// TODO REMOVE Be sure to let the BTF know if the test passes or fails! | ||
// printf("PASS\n"); | ||
return true; | ||
} | ||
// TODO REMOVE Be sure to let the BTF know if the test passes or fails! | ||
// printf("FAIL\n"); | ||
return false; | ||
} | ||
|
||
// OPTIONAL: Test teardown. If not defined, there is no teardown | ||
// This is called after ending the test in the BTF | ||
void teardown() { | ||
// Add custom teardown here | ||
} | ||
}; | ||
|
||
#endif // __CUSTOM_TEST__ | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#ifndef __SERIAL_TEST__ | ||
#define __SERIAL_TEST__ | ||
|
||
#include "test.h" | ||
|
||
|
||
class SerialTest : public Test { | ||
public: | ||
SerialTest(): Test("serial_basic") {}; | ||
private: | ||
bool runTest() { | ||
// Simply pass, as signalStart() and signalEnd() will indicate success or failure | ||
return true; | ||
} | ||
}; | ||
|
||
#endif // __SERIAL_TEST__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
#ifndef __TEST_H__ | ||
#define __TEST_H__ | ||
|
||
#include "mbed.h" | ||
#include "serialWrapper.h" | ||
#include <string> | ||
|
||
using namespace std; | ||
|
||
// Serial interface for BTF communication | ||
extern SerialWrapper pc; | ||
|
||
|
||
class Test { | ||
public: | ||
Test(const string name) { | ||
this->testName = name; | ||
} | ||
|
||
// Execute the test, including any setup and teardown | ||
bool execute() { | ||
bool ret; | ||
setup(); | ||
if(signalStart()) { | ||
ret = runTest(); | ||
// Even if the test passed, modify the return value to indicate serial | ||
// communication status. This is particularly useful in verifying the | ||
// success of the initial serial test | ||
ret = signalEnd(ret); | ||
} else { | ||
ret = false; | ||
} | ||
teardown(); | ||
|
||
return ret; | ||
} | ||
protected: | ||
// Name of the test, as defined in tests.yml | ||
string testName; | ||
private: | ||
// Setup for a given test. Does nothing by default | ||
virtual void setup() {}; | ||
// Main test content | ||
virtual bool runTest() = 0; | ||
// Teardown for a given test. Does nothing by default | ||
virtual void teardown() {}; | ||
|
||
// Signal to the BTF test runner to start the test | ||
bool signalStart() { | ||
// REMOVE bool started = false; | ||
// REMOVE int attempts = 0; | ||
char buff[7]; | ||
|
||
// Send start message to BTF test runner | ||
printf("START TEST %s\n", testName.c_str()); | ||
|
||
// Read response from BTF test runner | ||
// REMOVE Need this? memset(buff, '\0', sizeof(buff)); | ||
size_t nread = pc.readLine(buff, sizeof(buff)); | ||
|
||
// The response should be "READY" | ||
return (nread == 5) && (strcmp(buff, "READY") == 0); | ||
/* REMOVE | ||
do { | ||
// TODO Change to readLine with timeout | ||
if(pc.readable()) { | ||
pc.read(buff, sizeof(buff)); | ||
started = strncmp(buff, "READY", 5) == 0; | ||
} else { | ||
ThisThread::sleep_for(100); | ||
attempts++; | ||
} | ||
} while(!started && (attempts < 100)); | ||
return started;*/ | ||
} | ||
|
||
// Signal to the BTF test runner to end the test | ||
bool signalEnd(bool result) { | ||
// REMOVE bool ended = false; | ||
// REMOVE int attempts = 0; | ||
char buff[6]; | ||
|
||
// Send end message to BTF test runner | ||
if(result) { | ||
printf("PASS\n"); | ||
} else { | ||
printf("FAIL\n"); | ||
} | ||
|
||
// Read response from BTF test runner | ||
// REMOVE Need this? memset(buff, '\0', sizeof(buff)); | ||
size_t nread = pc.readLine(buff, sizeof(buff)); | ||
|
||
// The response should be 'DONE'. If so, preserve the test result | ||
return result && (nread == 4) && (strcmp(buff, "DONE") == 0); | ||
|
||
/* REMOVE | ||
do { | ||
// TODO Change to readLine with timeout | ||
if(pc.readable()) { | ||
pc.read(buff, sizeof(buff)); | ||
ended = strncmp(buff, "DONE", 4) == 0; | ||
} else { | ||
ThisThread::sleep_for(100); | ||
attempts++; | ||
} | ||
} while(!ended && (attempts < 100)); | ||
return ended;*/ | ||
} | ||
}; | ||
|
||
#endif // __TEST_H__ |