Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add files needed to compile Ethernet library #180

Closed
wants to merge 12 commits into from
Closed
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions SampleProjects/NetworkLib/.arduino-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
unittest:
platforms:
- mega2560
libraries:
- "Ethernet"

compile:
platforms:
- mega2560
libraries:
- "Ethernet"
1 change: 1 addition & 0 deletions SampleProjects/NetworkLib/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.bundle
2 changes: 2 additions & 0 deletions SampleProjects/NetworkLib/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
source 'https://rubygems.org'
gem 'arduino_ci', path: '../../'
3 changes: 3 additions & 0 deletions SampleProjects/NetworkLib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# NetworkLib

This is an example of a library that depends on Ethernet.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <NetworkLib.h>
// if it seems bare, that's because it's only meant to
// demonstrate compilation -- that references work
void setup() {}

void loop() {}
10 changes: 10 additions & 0 deletions SampleProjects/NetworkLib/library.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name=Ethernet
version=0.1.0
author=James Foster <[email protected]>
maintainer=James Foster <[email protected]>
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
7 changes: 7 additions & 0 deletions SampleProjects/NetworkLib/scripts/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

# if we don't have an Ethernet library, then get the standard one
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a bug in the core library, was it not able to fetch this by specifying a dependency in .arduino-ci.yml?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dependency in .arduino-ci.yml would bring in the official library (code here?). But for the purposes of this test in Arduino Ci, we'd like to test against our fork of the Ethernet library, since it is our fork that has arduino_ci support.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I'm missing something, this behavior of "install a standard library if a local one does not exist" is also implemented in the core library:
https://github.com/Arduino-CI/arduino_ci/blob/master/exe/arduino_ci.rb#L170-L173

In other words, if you manually install your own ethernet library locally, then listing a library of the same name in .arduino-ci.yml will not cause the CI runner to overwrite it. The check is simple directory existence: https://github.com/Arduino-CI/arduino_ci/blob/master/lib/arduino_ci/arduino_cmd.rb#L238-L240

So I think this entire script and the reference to it can be deleted

Copy link
Member Author

@jgfoster jgfoster Nov 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment does not do a good job of explaining what I want, so I've revised it.
When we are running the CI tests (on Travis, Appveyor, or GitHub Actions), we won't have the Ethernet library present at first. We don't want arduino_ci to install it because it will install the "standard" one and we want the "custom" one (my bad on the comment). But, I am running the CI tests on my development machine, I don't want it replacing my existing (development) Ethernet library. So, unless .arduino-ci.yml can specify a source (like a Gemfile), then I need the custom script. At least I think so! Does that make more sense?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the purpose was to use our custom Ethernet library (the reference to the "standard" library was a mistake), for purposes of validating that arduino_ci has the required pieces to compile the custom library it is probably sufficient to compile against the standard library, so the above comment can be ignored.

cd $(bundle exec arduino_library_location.rb)
if [ ! -d ./Ethernet ] ; then
git clone https://github.com/arduino-libraries/Ethernet.git
fi
1 change: 1 addition & 0 deletions SampleProjects/NetworkLib/src/NetworkLib.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "Ethernet.h"
3 changes: 3 additions & 0 deletions SampleProjects/NetworkLib/src/NetworkLib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

#include <Arduino.h>
15 changes: 15 additions & 0 deletions SampleProjects/NetworkLib/test/test.cpp
Original file line number Diff line number Diff line change
@@ -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 <Arduino.h>
#include <ArduinoUnitTests.h>
#include <Ethernet.h>

unittest(test) { assertEqual(EthernetNoHardware, Ethernet.hardwareStatus()); }

unittest_main()
87 changes: 87 additions & 0 deletions SampleProjects/TestSomething/test/clientServer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include <Arduino.h>
#include <ArduinoUnitTests.h>
#include <Client.h>
#include <IPAddress.h>
#include <Printable.h>
#include <Server.h>
#include <Udp.h>

// 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()
6 changes: 6 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions cpp/arduino/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
26 changes: 26 additions & 0 deletions cpp/arduino/Client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include <Stream.h>

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(); }
};
59 changes: 59 additions & 0 deletions cpp/arduino/IPAddress.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#pragma once

#include <stdint.h>

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);
21 changes: 9 additions & 12 deletions cpp/arduino/Print.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <stdio.h>
#include <avr/pgmspace.h>

#include "Printable.h"
#include "WString.h"

#define DEC 10
Expand All @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions cpp/arduino/Printable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

class Print;

class Printable {
public:
virtual size_t printTo(Print &p) const = 0;
};
5 changes: 5 additions & 0 deletions cpp/arduino/Server.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#include <Stream.h>

class Server : public Print {};
27 changes: 27 additions & 0 deletions cpp/arduino/Udp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include <IPAddress.h>
#include <Stream.h>

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;
}
};