diff --git a/.travis.yml b/.travis.yml index 2603ca2c..661959fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,3 +27,9 @@ script: - cd SampleProjects/TestSomething - bundle install - bundle exec arduino_ci.rb + - cd ../NetworkLib + - bundle install + - cd scripts + - bash -x ./install.sh + - cd .. + - bundle exec arduino_ci.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index db353f1c..41b1714d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - Add `__AVR__` to defines when compiling - Add support for `diditalPinToPort()`, `digitalPinToBitMask()`, and `portOutputRegister()` +- Add stubs for `Client.h`, `IPAddress.h`, `Printable.h`, `Server.h`, and `Udp.h` ### Changed - Move repository from https://github.com/ianfixes/arduino_ci to https://github.com/Arduino-CI/arduino_ci diff --git a/SampleProjects/NetworkLib/.arduino-ci.yml b/SampleProjects/NetworkLib/.arduino-ci.yml new file mode 100644 index 00000000..a242a79b --- /dev/null +++ b/SampleProjects/NetworkLib/.arduino-ci.yml @@ -0,0 +1,11 @@ +unittest: + platforms: + - mega2560 + libraries: + - "Ethernet" + +compile: + platforms: + - mega2560 + libraries: + - "Ethernet" diff --git a/SampleProjects/NetworkLib/.gitignore b/SampleProjects/NetworkLib/.gitignore new file mode 100644 index 00000000..06de90aa --- /dev/null +++ b/SampleProjects/NetworkLib/.gitignore @@ -0,0 +1 @@ +.bundle \ No newline at end of file diff --git a/SampleProjects/NetworkLib/Gemfile b/SampleProjects/NetworkLib/Gemfile new file mode 100644 index 00000000..b2b3b1fd --- /dev/null +++ b/SampleProjects/NetworkLib/Gemfile @@ -0,0 +1,2 @@ +source 'https://rubygems.org' +gem 'arduino_ci', path: '../../' diff --git a/SampleProjects/NetworkLib/README.md b/SampleProjects/NetworkLib/README.md new file mode 100644 index 00000000..b25d2e14 --- /dev/null +++ b/SampleProjects/NetworkLib/README.md @@ -0,0 +1,3 @@ +# NetworkLib + +This is an example of a library that depends on Ethernet. diff --git a/SampleProjects/NetworkLib/examples/EthernetExample/EthernetExample.ino b/SampleProjects/NetworkLib/examples/EthernetExample/EthernetExample.ino new file mode 100644 index 00000000..127afc76 --- /dev/null +++ b/SampleProjects/NetworkLib/examples/EthernetExample/EthernetExample.ino @@ -0,0 +1,6 @@ +#include +// if it seems bare, that's because it's only meant to +// demonstrate compilation -- that references work +void setup() {} + +void loop() {} diff --git a/SampleProjects/NetworkLib/library.properties b/SampleProjects/NetworkLib/library.properties new file mode 100644 index 00000000..2efc89bd --- /dev/null +++ b/SampleProjects/NetworkLib/library.properties @@ -0,0 +1,10 @@ +name=Ethernet +version=0.1.0 +author=James Foster +maintainer=James Foster +sentence=Sample Ethernet library to validate Client/Server mocks +paragraph=Sample Ethernet library to validate Client/Server mocks +category=Other +url=https://github.com/Arduino-CI/arduino_ci/SampleProjects/Ethernet +architectures=avr,esp8266 +includes=NetworkLib.h diff --git a/SampleProjects/NetworkLib/scripts/install.sh b/SampleProjects/NetworkLib/scripts/install.sh new file mode 100755 index 00000000..c4eb0517 --- /dev/null +++ b/SampleProjects/NetworkLib/scripts/install.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# if we don't have an Ethernet library already (say, in new install or for an automated test), +# then get the custom one we want to use for testing +cd $(bundle exec arduino_library_location.rb) +if [ ! -d ./Ethernet ] ; then + git clone https://github.com/arduino-libraries/Ethernet.git +fi diff --git a/SampleProjects/NetworkLib/src/NetworkLib.cpp b/SampleProjects/NetworkLib/src/NetworkLib.cpp new file mode 100644 index 00000000..01e5d5b0 --- /dev/null +++ b/SampleProjects/NetworkLib/src/NetworkLib.cpp @@ -0,0 +1 @@ +#include "Ethernet.h" diff --git a/SampleProjects/NetworkLib/src/NetworkLib.h b/SampleProjects/NetworkLib/src/NetworkLib.h new file mode 100644 index 00000000..9ee81b24 --- /dev/null +++ b/SampleProjects/NetworkLib/src/NetworkLib.h @@ -0,0 +1,3 @@ +#pragma once + +#include diff --git a/SampleProjects/NetworkLib/test/test.cpp b/SampleProjects/NetworkLib/test/test.cpp new file mode 100644 index 00000000..4c2d4eca --- /dev/null +++ b/SampleProjects/NetworkLib/test/test.cpp @@ -0,0 +1,15 @@ +/* +cd SampleProjects/NetworkLib +bundle config --local path vendor/bundle +bundle install +bundle exec arduino_ci_remote.rb --skip-compilation +# bundle exec arduino_ci_remote.rb --skip-examples-compilation +*/ + +#include +#include +#include + +unittest(test) { assertEqual(EthernetNoHardware, Ethernet.hardwareStatus()); } + +unittest_main() diff --git a/SampleProjects/TestSomething/test/clientServer.cpp b/SampleProjects/TestSomething/test/clientServer.cpp new file mode 100644 index 00000000..f088c821 --- /dev/null +++ b/SampleProjects/TestSomething/test/clientServer.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include +#include +#include + +// Provide some rudamentary tests for these classes +// They get more thoroughly tested in SampleProjects/NetworkLib + +unittest(Client) { + Client client; + assertEqual(0, client.available()); // subclass of Stream + assertEqual(0, client.availableForWrite()); // subclass of Print + String outData = "Hello, world!"; + client.println(outData); + String inData = client.readString(); + assertEqual(outData + "\r\n", inData); +} + +unittest(IPAddress) { + IPAddress ipAddress0; + assertEqual(0, ipAddress0.asWord()); + uint32_t one = 0x01020304; + IPAddress ipAddress1(one); + assertEqual(one, ipAddress1.asWord()); + IPAddress ipAddress2(2, 3, 4, 5); + assertEqual(0x05040302, ipAddress2.asWord()); + uint8_t bytes[] = {3, 4, 5, 6}; + IPAddress ipAddress3(bytes); + assertEqual(0x06050403, ipAddress3.asWord()); + uint8_t *pBytes = ipAddress1.raw_address(); + assertEqual(*(pBytes + 0), 4); + assertEqual(*(pBytes + 1), 3); + assertEqual(*(pBytes + 2), 2); + assertEqual(*(pBytes + 3), 1); + IPAddress ipAddress1a(one); + assertTrue(ipAddress1 == ipAddress1a); + assertTrue(ipAddress1 != ipAddress2); + assertEqual(1, ipAddress1[3]); + ipAddress1[1] = 11; + assertEqual(11, ipAddress1[1]); + assertEqual(1, ipAddress0 + 1); +} + +class TestPrintable : public Printable { +public: + virtual size_t printTo(Print &p) const { + p.print("TestPrintable"); + return 13; + } +}; + +unittest(Printable) { + TestPrintable printable; + Client client; + client.print(printable); + assertEqual("TestPrintable", client.readString()); +} + +class TestServer : public Server { +public: + uint8_t data; + virtual size_t write(uint8_t value) { + data = value; + return 1; + }; +}; + +unittest(Server) { + TestServer server; + server.write(67); + assertEqual(67, server.data); +} + +unittest(Udp) { + UDP udp; + assertEqual(0, udp.available()); // subclass of Stream + assertEqual(0, udp.availableForWrite()); // subclass of Print + String outData = "Hello, world!"; + udp.println(outData); + String inData = udp.readString(); + assertEqual(outData + "\r\n", inData); +} + +unittest_main() diff --git a/appveyor.yml b/appveyor.yml index af4bd854..2a68c341 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -25,3 +25,9 @@ test_script: - cd SampleProjects\TestSomething - bundle install - bundle exec arduino_ci.rb + - cd ../NetworkLib + - bundle install + - cd scripts + - install.sh + - cd .. + - bundle exec arduino_ci.rb diff --git a/cpp/arduino/Arduino.h b/cpp/arduino/Arduino.h index e107126e..2c4f347e 100644 --- a/cpp/arduino/Arduino.h +++ b/cpp/arduino/Arduino.h @@ -9,6 +9,7 @@ Where possible, variable names from the Arduino library are used to avoid confli #include "ArduinoDefines.h" +#include "IPAddress.h" #include "WCharacter.h" #include "WString.h" #include "Print.h" diff --git a/cpp/arduino/Client.h b/cpp/arduino/Client.h new file mode 100644 index 00000000..b08e183e --- /dev/null +++ b/cpp/arduino/Client.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +class Client : public Stream { +public: + Client() { + // The Stream mock defines a String buffer but never puts anyting in it! + if (!mGodmodeDataIn) { + mGodmodeDataIn = new String; + } + } + ~Client() { + if (mGodmodeDataIn) { + delete mGodmodeDataIn; + mGodmodeDataIn = nullptr; + } + } + virtual size_t write(uint8_t value) { + mGodmodeDataIn->concat(value); + return 1; + } + +protected: + uint8_t *rawIPAddress(IPAddress &addr) { return addr.raw_address(); } +}; diff --git a/cpp/arduino/IPAddress.h b/cpp/arduino/IPAddress.h new file mode 100644 index 00000000..89a343e1 --- /dev/null +++ b/cpp/arduino/IPAddress.h @@ -0,0 +1,59 @@ +#pragma once + +#include + +class IPAddress { +private: + union { + uint8_t bytes[4]; + uint32_t dword; + operator uint8_t *() const { return (uint8_t *)bytes; } + } _address; + +public: + // Constructors + IPAddress() : IPAddress(0, 0, 0, 0) {} + IPAddress(uint8_t octet1, uint8_t octet2, uint8_t octet3, uint8_t octet4) { + _address.bytes[0] = octet1; + _address.bytes[1] = octet2; + _address.bytes[2] = octet3; + _address.bytes[3] = octet4; + } + IPAddress(uint32_t dword) { _address.dword = dword; } + IPAddress(const uint8_t bytes[]) { + _address.bytes[0] = bytes[0]; + _address.bytes[1] = bytes[1]; + _address.bytes[2] = bytes[2]; + _address.bytes[3] = bytes[3]; + } + IPAddress(unsigned long dword) { _address.dword = (uint32_t)dword; } + + // Accessors + uint32_t asWord() const { return _address.dword; } + uint8_t *raw_address() { return _address.bytes; } + + // Comparisons + bool operator==(const IPAddress &rhs) const { + return _address.dword == rhs.asWord(); + } + + bool operator!=(const IPAddress &rhs) const { + return _address.dword != rhs.asWord(); + } + + // Indexing + uint8_t operator[](int index) const { return _address.bytes[index]; } + uint8_t &operator[](int index) { return _address.bytes[index]; } + + // Conversions + operator uint32_t() const { return _address.dword; }; + + friend class EthernetClass; + friend class UDP; + friend class Client; + friend class Server; + friend class DhcpClass; + friend class DNSClient; +}; + +const IPAddress INADDR_NONE(0, 0, 0, 0); diff --git a/cpp/arduino/Print.h b/cpp/arduino/Print.h index b7d8a522..261b116d 100644 --- a/cpp/arduino/Print.h +++ b/cpp/arduino/Print.h @@ -2,6 +2,8 @@ #include #include + +#include "Printable.h" #include "WString.h" #define DEC 10 @@ -12,22 +14,17 @@ #endif #define BIN 2 -class Print; - -class Printable -{ - public: - virtual size_t printTo(Print& p) const = 0; -}; - class Print { + private: + int write_error; + protected: + void setWriteError(int err = 1) { write_error = err; } public: - Print() {} + Print() : write_error(0) {} - // Arduino's version of this is richer but until I see an actual error case I'm not sure how to mock - int getWriteError() { return 0; } - void clearWriteError() { } + int getWriteError() { return write_error; } + void clearWriteError() { setWriteError(0); } virtual int availableForWrite() { return 0; } virtual size_t write(uint8_t) = 0; diff --git a/cpp/arduino/Printable.h b/cpp/arduino/Printable.h new file mode 100644 index 00000000..cdd361d3 --- /dev/null +++ b/cpp/arduino/Printable.h @@ -0,0 +1,8 @@ +#pragma once + +class Print; + +class Printable { +public: + virtual size_t printTo(Print &p) const = 0; +}; diff --git a/cpp/arduino/Server.h b/cpp/arduino/Server.h new file mode 100644 index 00000000..dd1993ff --- /dev/null +++ b/cpp/arduino/Server.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +class Server : public Print {}; diff --git a/cpp/arduino/Udp.h b/cpp/arduino/Udp.h new file mode 100644 index 00000000..8352f7f6 --- /dev/null +++ b/cpp/arduino/Udp.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +class UDP : public Stream { +protected: + uint8_t *rawIPAddress(IPAddress &addr) { return addr.raw_address(); }; + +public: + UDP() { + // The Stream mock defines a String buffer but never puts anyting in it! + if (!mGodmodeDataIn) { + mGodmodeDataIn = new String; + } + } + ~UDP() { + if (mGodmodeDataIn) { + delete mGodmodeDataIn; + mGodmodeDataIn = nullptr; + } + } + virtual size_t write(uint8_t value) { + mGodmodeDataIn->concat(value); + return 1; + } +};