diff --git a/.travis.yml b/.travis.yml index e945e8a3..fc2a483c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,9 @@ before_install: - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16" - sleep 3 - export DISPLAY=:1.0 - - wget http://downloads.arduino.cc/arduino-1.8.5-linux64.tar.xz - - tar xf arduino-1.8.5-linux64.tar.xz - - sudo mv arduino-1.8.5 /usr/local/share/arduino + - wget http://downloads.arduino.cc/arduino-1.8.6-linux64.tar.xz + - tar xf arduino-1.8.6-linux64.tar.xz + - sudo mv arduino-1.8.6 /usr/local/share/arduino - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino install: - ln -s $PWD /usr/local/share/arduino/OpenMQTTGateway @@ -31,7 +31,6 @@ install: - arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --save-prefs - arduino --install-boards esp8266:esp8266 - arduino --board $BD --save-prefs - - arduino --pref "compiler.warning_level=all" --save-prefs script: - arduino --verify --board $BD $PWD/OpenMQTTGateway.ino notifications: diff --git a/OpenMQTTGateway.ino b/OpenMQTTGateway.ino index e4de2b5c..3d7bdd8f 100644 --- a/OpenMQTTGateway.ino +++ b/OpenMQTTGateway.ino @@ -57,6 +57,18 @@ along with this program. If not, see . */ #include "User_config.h" + +// array to store previous received RFs, IRs codes and their timestamps +#if defined(ESP8266) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) + #define MQTT_MAX_PACKET_SIZE 1024 + #define array_size 12 + unsigned long ReceivedSignal[array_size][2] ={{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}}; +#else // boards with smaller memory + #define MQTT_MAX_PACKET_SIZE 256 + #define array_size 4 + unsigned long ReceivedSignal[array_size][2] ={{0,0},{0,0},{0,0},{0,0}}; +#endif + #include #include @@ -112,16 +124,7 @@ #ifdef ZsensorGPIOKeyCode #include "config_GPIOKeyCode.h" #endif -// array to store previous received RFs, IRs codes and their timestamps -#if defined(ESP8266) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) - #define MQTT_MAX_PACKET_SIZE 1024 - #define array_size 12 - unsigned long ReceivedSignal[array_size][2] ={{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}}; -#else // boards with smaller memory - #define MQTT_MAX_PACKET_SIZE 256 - #define array_size 4 - unsigned long ReceivedSignal[array_size][2] ={{0,0},{0,0},{0,0},{0,0}}; -#endif + /*------------------------------------------------------------------------*/ //adding this to bypass the problem of the arduino builder issue 50 @@ -129,9 +132,12 @@ void callback(char*topic, byte* payload,unsigned int length); boolean connectedOnce = false; //indicate if we have been connected once to MQTT +int failure_number = 0; // number of failure connecting to MQTT + #ifdef ESP32 #include #include + #include WiFiClient eClient; #ifdef MDNS_SD #include @@ -179,7 +185,6 @@ void saveConfigCallback () { boolean reconnect() { - int failure_number = 0; // Loop until we're reconnected while (!client.connected()) { trc(F("MQTT connection...")); //F function enable to decrease sram usage @@ -187,9 +192,9 @@ boolean reconnect() { trc(F("Connected to broker")); failure_number = 0; // Once connected, publish an announcement... - client.publish(will_Topic,Gateway_AnnouncementMsg,will_Retain); + pub(will_Topic,Gateway_AnnouncementMsg,will_Retain); // publish version - client.publish(version_Topic,OMG_VERSION,will_Retain); + pub(version_Topic,OMG_VERSION,will_Retain); //Subscribing to topic if (client.subscribe(subjectMQTTtoX)) { #ifdef ZgatewayRF @@ -205,6 +210,8 @@ boolean reconnect() { } } else { failure_number ++; // we count the failure + trc(F("failure_number")); + trc(failure_number); trc(F("failed, rc=")); trc(client.state()); trc(F("try again in 5s")); @@ -252,6 +259,7 @@ void setup() Serial.end(); Serial.begin(SERIAL_BAUD, SERIAL_8N1, SERIAL_TX_ONLY);// enable on ESP8266 to free some pin #endif + #if defined(ESP8266) && !defined(ESPWifiManualSetup) setup_wifimanager(); #else // ESP32 case we don't use Wifi manager yet @@ -308,6 +316,7 @@ void setup() delay(500); digitalWrite(led_receive, HIGH); digitalWrite(led_send, HIGH); + #endif #if defined(MDNS_SD) && defined(ESP8266) @@ -386,7 +395,8 @@ void setup() #endif #ifdef ZsensorGPIOKeyCode setupGPIOKeyCode(); - #endif + #endif + trc(F("MQTT_MAX_PACKET_SIZE")); trc(MQTT_MAX_PACKET_SIZE); trc(F("Setup OpenMQTTGateway end")); @@ -414,7 +424,6 @@ void setup_wifi() { failureAttempt++; //DIRTY FIX ESP32 if (failureAttempt > 30) setup_wifi(); //DIRTY FIX ESP32 } - trc(F("WiFi ok with manual config credentials")); } @@ -533,8 +542,8 @@ void setup_wifimanager(){ } } - #else // Arduino case + void setup_ethernet() { if (gateway[0] != 0 || Dns[0]!=0) { @@ -584,7 +593,6 @@ void setup_ethernet() { void loop() { - unsigned long now = millis(); //MQTT client connexion management if (!client.connected()) { // not connected @@ -642,27 +650,16 @@ void loop() MeasureADC(); //Addon to measure the analog value of analog pin #endif #ifdef ZgatewayRF - if(RFtoMQTT()){ - trc(F("RFtoMQTT OK")); - //GREEN ON - digitalWrite(led_receive, LOW); - timer_led_receive = millis(); - } + RFtoMQTT(); #endif #ifdef ZgatewayRF315 - if(RF315toMQTT()){ - trc(F("RF315toMQTT OK")); - //GREEN ON - digitalWrite(led_receive, LOW); - timer_led_receive = millis(); - } + RF315toMQTT(); #endif #ifdef ZgatewayRF2 - if(RF2toMQTT()){ - trc(F("RF2toMQTT OK")); - digitalWrite(led_receive, LOW); - timer_led_receive = millis(); - } + RF2toMQTT(); + #endif + #ifdef ZgatewayPilight + PilighttoMQTT(); #endif #ifdef ZgatewayPilight if(PilighttoMQTT()){ @@ -672,16 +669,10 @@ void loop() } #endif #ifdef ZgatewaySRFB - if(SRFBtoMQTT()) - trc(F("SRFBtoMQTT OK")); + SRFBtoMQTT(); #endif #ifdef ZgatewayIR - if(IRtoMQTT()) { - trc(F("IRtoMQTT OK")); - digitalWrite(led_receive, LOW); - timer_led_receive = millis(); - delay(100); - } + IRtoMQTT(); #endif #ifdef ZgatewayBT #ifndef multiCore @@ -709,7 +700,7 @@ void stateMeasures(){ unsigned long now = millis(); if (now > (timer_sys_measures + TimeBetweenReadingSYS)) {//retriving value of memory ram every TimeBetweenReadingSYS timer_sys_measures = millis(); - StaticJsonBuffer<200> jsonBuffer; + StaticJsonBuffer jsonBuffer; JsonObject& SYSdata = jsonBuffer.createObject(); trc("Uptime (s)"); unsigned long uptime = millis()/1000; @@ -737,46 +728,52 @@ void stateMeasures(){ modules = modules + ZgatewayRF315; #endif #ifdef ZsensorBME280 - modules = modules + ZsensorBME280; + modules = modules + ZsensorBME280; #endif #ifdef ZsensorBH1750 - modules = modules + ZsensorBH1750; + modules = modules + ZsensorBH1750; #endif #ifdef ZsensorTSL2561 - modules = modules + ZsensorTSL2561; + modules = modules + ZsensorTSL2561; #endif #ifdef ZactuatorONOFF - modules = modules + ZactuatorONOFF; + modules = modules + ZactuatorONOFF; #endif #ifdef Zgateway2G - modules = modules + Zgateway2G; + modules = modules + Zgateway2G; #endif #ifdef ZgatewayIR - modules = modules + ZgatewayIR; + modules = modules + ZgatewayIR; #endif #ifdef ZgatewayRF2 - modules = modules + ZgatewayRF2; + modules = modules + ZgatewayRF2; + #endif + #ifdef ZgatewayPilight + modules = modules + ZgatewayPilight; #endif #ifdef ZgatewayPilight modules = modules + ZgatewayPilight; #endif #ifdef ZgatewaySRFB - modules = modules + ZgatewaySRFB; + modules = modules + ZgatewaySRFB; #endif #ifdef ZgatewayBT - modules = modules + ZgatewayBT; + modules = modules + ZgatewayBT; #endif #ifdef ZgatewayRFM69 - modules = modules + ZgatewayRFM69; + modules = modules + ZgatewayRFM69; #endif #ifdef ZsensorINA226 - modules = modules + ZsensorINA226; + modules = modules + ZsensorINA226; #endif #ifdef ZsensorHCSR501 - modules = modules + ZsensorHCSR501; + modules = modules + ZsensorHCSR501; #endif #ifdef ZsensorGPIOInput - modules = modules + ZsensorGPIOInput; + modules = modules + ZsensorGPIOInput; + #endif + #ifdef ZsensorGPIOKeyCode + modules = modules + ZsensorGPIOKeyCode; #endif #ifdef ZsensorGPIOKeyCode modules = modules + ZsensorGPIOKeyCode; @@ -785,7 +782,7 @@ void stateMeasures(){ trc(modules); char JSONmessageBuffer[100]; SYSdata.printTo(JSONmessageBuffer, sizeof(JSONmessageBuffer)); - client.publish(subjectSYStoMQTT,JSONmessageBuffer); + pub(subjectSYStoMQTT,JSONmessageBuffer); } } #endif @@ -837,43 +834,78 @@ return false; } void receivingMQTT(char * topicOri, char * datacallback) { + if (strstr(topicOri, subjectMultiGTWKey) != NULL) // storing received value so as to avoid publishing this value if it has been already sent by this or another OpenMQTTGateway + { + trc(F("Storing signal")); + unsigned long data = strtoul(datacallback, NULL, 10); // we will not be able to pass values > 4294967295 + storeValue(data); + trc(F("Data stored")); + } + //YELLOW ON + digitalWrite(led_send, LOW); - if (strstr(topicOri, subjectMultiGTWKey) != NULL) // storing received value so as to avoid publishing this value if it has been already sent by this or another OpenMQTTGateway - { - trc(F("Storing signal")); - unsigned long data = strtoul(datacallback, NULL, 10); // we will not be able to pass values > 4294967295 - storeValue(data); - trc(F("Data stored")); - } -//YELLOW ON -digitalWrite(led_send, LOW); -#ifdef ZgatewayRF - MQTTtoRF(topicOri, datacallback); -#endif -#ifdef ZgatewayRF315 - MQTTtoRF315(topicOri, datacallback); -#endif -#ifdef ZgatewayRF2 - MQTTtoRF2(topicOri, datacallback); -#endif -#ifdef ZgatewayPilight - MQTTtoPilight(topicOri, datacallback); -#endif -#ifdef Zgateway2G - MQTTto2G(topicOri, datacallback); -#endif -#ifdef ZgatewaySRFB - MQTTtoSRFB(topicOri, datacallback); -#endif -#ifdef ZgatewayIR - MQTTtoIR(topicOri, datacallback); -#endif -#ifdef ZgatewayRFM69 - MQTTtoRFM69(topicOri, datacallback); -#endif -#ifdef ZactuatorONOFF - MQTTtoONOFF(topicOri, datacallback); -#endif + trc(F("Creating Json buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& jsondata = jsonBuffer.parseObject(datacallback); + + if (jsondata.success()) { // json object ok -> json decoding + #ifdef ZgatewayPilight // ZgatewayPilight is only defined with json publishing + MQTTtoPilight(topicOri, jsondata); + #endif + #ifdef jsonPublishing + #ifdef ZgatewayRF + MQTTtoRF(topicOri, jsondata); + #endif + #ifdef ZgatewayRF315 + MQTTtoRF315(topicOri, jsondata); + #endif + #ifdef ZgatewayRF2 + MQTTtoRF2(topicOri, jsondata); + #endif + #ifdef Zgateway2G + MQTTto2G(topicOri, jsondata); + #endif + #ifdef ZgatewaySRFB + MQTTtoSRFB(topicOri, jsondata); + #endif + #ifdef ZgatewayIR + MQTTtoIR(topicOri, jsondata); + #endif + #ifdef ZgatewayRFM69 + MQTTtoRFM69(topicOri, jsondata); + #endif + #ifdef ZactuatorONOFF + MQTTtoONOFF(topicOri, jsondata); + #endif + #endif + } else { // not a json object --> simple decoding + #ifdef simplePublishing + #ifdef ZgatewayRF + MQTTtoRF(topicOri, datacallback); + #endif + #ifdef ZgatewayRF315 + MQTTtoRF315(topicOri, datacallback); + #endif + #ifdef ZgatewayRF2 + MQTTtoRF2(topicOri, datacallback); + #endif + #ifdef Zgateway2G + MQTTto2G(topicOri, datacallback); + #endif + #ifdef ZgatewaySRFB + MQTTtoSRFB(topicOri, datacallback); + #endif + #ifdef ZgatewayIR + MQTTtoIR(topicOri, datacallback); + #endif + #ifdef ZgatewayRFM69 + MQTTtoRFM69(topicOri, datacallback); + #endif + #ifdef ZactuatorONOFF + MQTTtoONOFF(topicOri, datacallback); + #endif + #endif + } //YELLOW OFF digitalWrite(led_send, HIGH); } @@ -962,3 +994,112 @@ void trc(float msg){ Serial.println(msg); #endif } + +void pub(char * topic, char * payload, boolean retainFlag){ + client.publish(topic, payload, retainFlag); +} + +void pub(char * topicori, JsonObject& data){ + + String topic = topicori; + #ifdef valueAsASubject + unsigned long value = data["value"]; + if (value != 0){ + topic = topic + "/"+ String(value); + } + #endif + + #ifdef jsonPublishing + char JSONmessageBuffer[JSON_MSG_BUFFER]; + trc(F("Pub json into:")); + trc(topic); + data.printTo(JSONmessageBuffer, sizeof(JSONmessageBuffer)); + trc(JSONmessageBuffer); + pub(topic, JSONmessageBuffer); + #endif + + #ifdef simplePublishing + trc(F("Pub data per topic")); + // Loop through all the key-value pairs in obj + for (JsonPair& p : data) { + #if defined(ESP8266) + yield(); + #endif + if (p.value.is() || p.value.is()) { + trc(p.key); + trc(p.value.as()); + if (strcmp(p.key, "value") == 0){ // if data is a value we don't integrate the name into the topic + pub(topic,p.value.as()); + }else{ // if data is not a value we integrate the name into the topic + pub(topic + "/" + String(p.key),p.value.as()); + } + } else if (p.value.is()) { + trc(p.key); + trc(p.value.as()); + pub(topic + "/" + String(p.key),p.value.as()); + } else if (p.value.is()) { + trc(p.key); + trc(p.value.as()); + pub(topic + "/" + String(p.key),p.value.as()); + } + } + #endif +} + +void pub(char * topic, char * payload){ + client.publish(topic, payload); +} + +void pub(char * topic, String payload){ + client.publish(topic,(char *)payload.c_str()); +} + +void pub(String topic, String payload){ + client.publish((char *)topic.c_str(),(char *)payload.c_str()); +} + +void pub(String topic, char * payload){ + client.publish((char *)topic.c_str(),payload); +} + +void pub(String topic, int payload){ + char val[12]; + sprintf(val, "%d", payload); + client.publish((char *)topic.c_str(),val); +} + +void pub(String topic, float payload){ + char val[12]; + dtostrf(payload,3,1,val); + client.publish((char *)topic.c_str(),val); +} + +void pub(char * topic, float payload){ + char val[12]; + dtostrf(payload,3,1,val); + client.publish(topic,val); +} + +void pub(char * topic, int payload){ + char val[6]; + sprintf(val, "%d", payload); + client.publish(topic,val); +} + +void pub(char * topic, unsigned int payload){ + char val[6]; + sprintf(val, "%u", payload); + client.publish(topic,val); +} + +void pub(char * topic, unsigned long payload){ + char val[11]; + sprintf(val, "%lu", payload); + client.publish(topic,val); +} + +void pub(String topic, unsigned long payload){ + char val[11]; + sprintf(val, "%lu", payload); + client.publish((char *)topic.c_str(),val); +} diff --git a/User_config.h b/User_config.h index 4fb8d408..64f8f82b 100644 --- a/User_config.h +++ b/User_config.h @@ -5,11 +5,8 @@ Send and receiving command by MQTT This program enables to: - - receive MQTT data from a topic and send RF 433Mhz signal corresponding to the received MQTT data - - publish MQTT data to a different topic related to received 433Mhz signal - - receive MQTT data from a topic and send IR signal corresponding to the received MQTT data - - publish MQTT data to a different topic related to received IR signal - - publish MQTT data to a different topic related to BLE devices rssi signal + - receive MQTT data from a topic and send signals corresponding to the received MQTT data + - publish MQTT data to a different topic related to received signals Copyright: (c)Florian ROBERT @@ -29,7 +26,39 @@ along with this program. If not, see . */ /*-------------------VERSION----------------------*/ -#define OMG_VERSION "0.8" +#define OMG_VERSION "0.9beta" + +/*-------------CONFIGURE WIFIMANAGER-------------*/ +/* + * The following parameters are set during the WifiManager setup process: + * - wifi_ssid + * - wifi_password + * - mqtt_user + * - mqtt_pass + * - mqtt_server + * - mqtt_port + * + * To completely disable WifiManager, define ESPWifiManualSetup. + * If you do so, please don't forget to set these variables before compiling + * + * Otherwise you can provide these credentials on the web interface after connecting + * to the access point with your password (SSID: WifiManager_ssid, password: WifiManager_password) + */ + +/*-------------DEFINE YOUR NETWORK PARAMETERS BELOW----------------*/ +#if defined(ESP8266) // for nodemcu, weemos and esp8266 + //#define ESPWifiManualSetup true //uncomment you don't want to use wifimanager for your credential settings on ESP +#endif + +#if defined(ESP32) || defined(ESPWifiManualSetup) // for nodemcu, weemos and esp8266 + #define wifi_ssid "wifi ssid" + #define wifi_password "wifi password" +#else // for arduino + W5100 + const byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0x54, 0x95 }; //W5100 ethernet shield mac adress +#endif + +#define WifiManager_password "your_password" //this is going to be the WPA2-PSK password for the initial setup access point +#define WifiManager_ssid "OpenMQTTGateway" //this is the network name of the initial setup access point /*-------------CONFIGURE WIFIMANAGER-------------*/ /* @@ -61,6 +90,48 @@ char mqtt_server[40] = "192.168.1.17"; char mqtt_port[6] = "1883"; #define Gateway_Name "OpenMQTTGateway" + +//uncomment the line below to integrate msg value into the subject when receiving +//#define valueAsASubject true + +/*-------------DEFINE THE MODULES YOU WANT BELOW----------------*/ +//Addons and module management, comment the Z line + +#define ZgatewayRF "RF" //ESP8266, Arduino, ESP32 +//#define ZgatewayRF315 "RF315" //ESP8266, Arduino, ESP32 +#define ZgatewayIR "IR" //ESP8266, Arduino, Sonoff RF Bridge +//#define ZgatewayPilight "Pilight" //ESP8266, Arduino, ESP32 +#define ZgatewayBT "BT" //ESP8266, Arduino, ESP32 +//#define ZgatewayRF2 "RF2" //ESP8266, Arduino, ESP32 +//#define ZgatewaySRFB "SRFB" // Sonoff RF Bridge +//#define Zgateway2G "2G" //ESP8266, Arduino, ESP32 +//#define ZactuatorONOFF "ONOFF" //ESP8266, Arduino, ESP32, Sonoff RF Bridge +//#define ZsensorINA226 "INA226" //ESP8266, Arduino, ESP32 +//#define ZsensorHCSR501 "HCSR501" //ESP8266, Arduino, ESP32, Sonoff RF Bridge +//#define ZsensorADC "ADC" //ESP8266, Arduino, ESP32 +//#define ZsensorBH1750 "BH1750" //ESP8266, Arduino, ESP32 +//#define ZsensorTSL2561 "TSL2561" //ESP8266, Arduino, ESP32 +//#define ZsensorBME280 "BME280" //ESP8266, Arduino, ESP32 +//#define ZsensorDHT "DHT" //ESP8266, Arduino, ESP32, Sonoff RF Bridge +//#define ZgatewayRFM69 "RFM69" //ESP8266, Arduino, ESP32 +//#define ZsensorGPIOKeyCode "GPIOKeyCode" //ESP8266, Arduino, ESP32 +//#define ZsensorGPIOInput "GPIOInput" //ESP8266, Arduino, ESP32 + +/*-------------DEFINE YOUR ADVANCED NETWORK PARAMETERS BELOW----------------*/ +//#define MDNS_SD //uncomment if you want to use mdns for discovering automatically your ip server, please note that MDNS with ESP32 can cause the BLE to not work +//#define cleanFS true //uncomment if you want to clean the ESP memory and reenter your credentials +#define maxMQTTretry 4 //maximum MQTT connection attempts before going to wifi setup + +//set minimum quality of signal so it ignores AP's under that quality +#define MinimumWifiSignalQuality 8 + +// these values are only used if no dhcp configuration is available +const byte ip[] = { 192, 168, 1, 99 }; //ip adress +const byte gateway[] = { 0, 0, 0, 0 }; //ip adress, if first value is different from 0 advanced config network will be used and you should fill gateway & dns +const byte Dns[] = { 0, 0, 0, 0 }; //ip adress, if first value is different from 0 advanced config network will be used and you should fill gateway & dns +const byte subnet[] = { 255, 255, 255, 0 }; //ip adress + +/*-------------DEFINE YOUR MQTT ADVANCED PARAMETERS BELOW----------------*/ #define Base_Topic "home/" #define version_Topic Base_Topic Gateway_Name "/version" #define will_Topic Base_Topic Gateway_Name "/LWT" @@ -69,27 +140,13 @@ char mqtt_port[6] = "1883"; #define will_Message "Offline" #define Gateway_AnnouncementMsg "Online" -/*-------------DEFINE YOUR NETWORK PARAMETERS BELOW----------------*/ -//#define MDNS_SD //uncomment if you want to use mdns for discovering automatically your ip server, please note that MDNS with ESP32 can cause the BLE to not work -//#define cleanFS true //uncomment if you want to clean the ESP memory and reenter your credentials -#define maxMQTTretry 4 //maximum MQTT connection attempts before going to wifi setup +#define jsonPublishing true //comment if you don't want to use Json publishing (one topic for all the parameters) +//example home/OpenMQTTGateway_ESP32_DEVKIT/BTtoMQTT/4XXXXXXXXXX4 {"rssi":-63,"servicedata":"fe0000000000000000000000000000000000000000"} -//set minimum quality of signal so it ignores AP's under that quality -#define MinimumWifiSignalQuality 8 - -// Update these with values suitable for your network. -#if defined(ESP32) || defined(ESPWifiManualSetup) // for nodemcu, weemos and esp8266 - #define wifi_ssid "wifi ssid" - #define wifi_password "wifi password" -#else // for arduino + W5100 - const byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0x54, 0x95 }; //W5100 ethernet shield mac adress -#endif - -// these values are only used if no dhcp configuration is available -const byte ip[] = { 192, 168, 1, 99 }; //ip address -const byte gateway[] = { 0, 0, 0, 0 }; //ip address, if first value is different from 0 advanced config network will be used and you should fill gateway & dns -const byte Dns[] = { 0, 0, 0, 0 }; //ip address, if first value is different from 0 advanced config network will be used and you should fill gateway & dns -const byte subnet[] = { 255, 255, 255, 0 }; //ip address +#define simplePublishing true //comment if you don't want to use simple publishing (one topic for one parameter) +//example +// home/OpenMQTTGateway_ESP32_DEVKIT/BTtoMQTT/4XXXXXXXXXX4/rssi -63.0 +// home/OpenMQTTGateway_ESP32_DEVKIT/BTtoMQTT/4XXXXXXXXXX4/servicedata fe0000000000000000000000000000000000000000 /*-------------DEFINE YOUR OTA PARAMETERS BELOW----------------*/ #define ota_hostname Gateway_Name @@ -104,27 +161,6 @@ const byte subnet[] = { 255, 255, 255, 0 }; //ip address // VCC ------------D|-----------/\/\/\/\ ----------------- Arduino PIN // LED Resistor 270-510R -/*-------------DEFINE THE MODULES YOU WANT BELOW----------------*/ -//Addons and module management, comment the Z line - -#define ZgatewayRF "RF" //ESP8266, Arduino, ESP32 -//#define ZgatewayRF315 "RF315" //ESP8266, Arduino, ESP32 -#define ZgatewayIR "IR" //ESP8266, Arduino, Sonoff RF Bridge -#define ZgatewayBT "BT" //ESP8266, Arduino, ESP32 -//#define ZgatewayRF2 "RF2" //ESP8266, Arduino, ESP32 -//#define ZgatewayPilight "Pilight" //ESP8266 -//#define ZgatewaySRFB "SRFB" // Sonoff RF Bridge -//#define Zgateway2G "2G" //ESP8266, Arduino, ESP32 -//#define ZactuatorONOFF "ONOFF" //ESP8266, Arduino, ESP32, Sonoff RF Bridge -//#define ZsensorINA226 "INA226" //ESP8266, Arduino, ESP32 -//#define ZsensorHCSR501 "HCSR501" //ESP8266, Arduino, ESP32, Sonoff RF Bridge -//#define ZsensorADC "ADC" //ESP8266, Arduino, ESP32 -//#define ZsensorBH1750 "BH1750" //ESP8266, Arduino, ESP32 -//#define ZsensorTSL2561 "TSL2561" //ESP8266, Arduino, ESP32 -//#define ZsensorBME280 "BME280" //ESP8266, Arduino, ESP32 -//#define ZsensorDHT "DHT" //ESP8266, Arduino, ESP32, Sonoff RF Bridge -//#define ZgatewayRFM69 "RFM69" //ESP8266, Arduino, ESP32 - /*----------------------------OTHER PARAMETERS-----------------------------*/ /*-------------------CHANGING THEM IS NOT COMPULSORY-----------------------*/ /*----------------------------USER PARAMETERS-----------------------------*/ @@ -146,6 +182,8 @@ const byte subnet[] = { 255, 255, 255, 0 }; //ip address #define multiCore //comment to don't use multicore function of ESP32 for BLE #endif +#define JSON_MSG_BUFFER 256 // Json message max buffer size, don't put 1024 or higher it is causing unexpected behaviour on ESP8266 + #define TimeBetweenReadingSYS 120000 // time between system readings (like memory) #define subjectSYStoMQTT Base_Topic Gateway_Name "/SYStoMQTT" diff --git a/ZactuatorONOFF.ino b/ZactuatorONOFF.ino index 58e4138f..39029034 100644 --- a/ZactuatorONOFF.ino +++ b/ZactuatorONOFF.ino @@ -38,22 +38,41 @@ void setupONOFF(){ trc(F("ZactuatorONOFF setup done ")); } -void MQTTtoONOFF(char * topicOri, char * datacallback){ - - bool boolSWITCHTYPE; - boolSWITCHTYPE = to_bool(datacallback); - String topic = topicOri; - - if ((topic == subjectMQTTtoONOFF)){ - trc(F("MQTTtoONOFF")); - trc(boolSWITCHTYPE); - digitalWrite(ACTUATOR_ONOFF_PIN, boolSWITCHTYPE); - boolean result = client.publish(subjectGTWONOFFtoMQTT, datacallback);// we acknowledge the sending by publishing the value to an acknowledgement topic - if (result){ - trc(F("MQTTtoONOFF ack pub.")); - trc(datacallback); +#ifdef simplePublishing + void MQTTtoONOFF(char * topicOri, char * datacallback){ + + bool boolSWITCHTYPE; + boolSWITCHTYPE = to_bool(datacallback); + String topic = topicOri; + + if (topic == subjectMQTTtoONOFF){ + trc(F("MQTTtoONOFF data analysis")); + trc(boolSWITCHTYPE); + digitalWrite(ACTUATOR_ONOFF_PIN, boolSWITCHTYPE); + // we acknowledge the sending by publishing the value to an acknowledgement topic + pub(subjectGTWONOFFtoMQTT, datacallback); } } -} #endif +#ifdef jsonPublishing + void MQTTtoONOFF(char * topicOri, JsonObject& ONOFFdata){ + + String topic = topicOri; + + if (topic == subjectMQTTtoONOFF){ + trc(F("MQTTtoONOFF json data analysis")); + int boolSWITCHTYPE = ONOFFdata["switchType"] | 99; + if (boolSWITCHTYPE != 99) { + trc(F("MQTTtoONOFF boolSWITCHTYPE ok")); + trc(boolSWITCHTYPE); + digitalWrite(ACTUATOR_ONOFF_PIN, boolSWITCHTYPE); + // we acknowledge the sending by publishing the value to an acknowledgement topic + pub(subjectGTWONOFFtoMQTT, ONOFFdata); + }else{ + trc(F("MQTTtoONOFF Fail reading from json")); + } + } + } +#endif +#endif diff --git a/Zgateway2G.ino b/Zgateway2G.ino index 38b737aa..bc5cb867 100644 --- a/Zgateway2G.ino +++ b/Zgateway2G.ino @@ -81,53 +81,81 @@ void signalStrengthAnalysis(){ boolean _2GtoMQTT(){ // Get the memory locations of unread SMS messages. unreadSMSNum = A6l.getUnreadSMSLocs(unreadSMSLocs, 512); + trc(F("Creating SMS buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& SMSdata = jsonBuffer.createObject(); for (int i = 0; i < unreadSMSNum; i++) { trc("New message at index: "); trc(unreadSMSNum); sms = A6l.readSMS(unreadSMSLocs[i]); - trc(sms.number); - trc(sms.date); - trc(sms.message); + SMSdata.set("message", (char *)sms.message.c_str()); + SMSdata.set("date", (char *)sms.date.c_str()); + SMSdata.set("phone", (char *)sms.number.c_str()); A6l.deleteSMS(unreadSMSLocs[i]); // we delete the SMS received - trc(F("data 2GtoMQTT")); - client.publish(subject2GtoMQTTphone,(char *)sms.number.c_str()); - client.publish(subject2GtoMQTTdate,(char *)sms.date.c_str()); - client.publish(subject2GtoMQTTmessage,(char *)sms.message.c_str()); + trc(F("Adv data 2GtoMQTT")); + pub(subject2GtoMQTT,SMSdata); return true; } return false; } - -void MQTTto2G(char * topicOri, char * datacallback) { - - String data = datacallback; // we will not be able to pass values > 4294967295 - - // 2G DATA ANALYSIS - //We look into the subject to see if a special RF protocol is defined - String topic = topicOri; - String phone_number = ""; - int pos0 = topic.lastIndexOf(_2GPhoneKey); - if (pos0 != -1) { - pos0 = pos0 + strlen(_2GPhoneKey); - phone_number = topic.substring(pos0); - trc(F("Phone number to send SMS:")); - trc(phone_number); - } - if((strstr(topicOri, subjectMQTTto2G) != NULL) && (pos0 != -1)){ - trc(F("MQTTto2G")); - trc(data); - if (A6l.sendSMS(phone_number,data) == A6_OK ) { - trc("SMS OK"); - }else{ - trc("SMS KO"); - } - // Acknowledgement to the GTW2G topic - boolean result = client.publish(subjectGTW2GtoMQTT, datacallback);// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also - if (result){ - trc(F("MQTTto2G ack pub.")); - trc(data); - } - } +#ifdef simplePublishing + void MQTTto2G(char * topicOri, char * datacallback) { -} + String data = datacallback; + String topic = topicOri; + + if (topic == subjectMQTTto2G) { + trc(F("MQTTto2G data analysis")); + // 2G DATA ANALYSIS + String phone_number = ""; + int pos0 = topic.lastIndexOf(_2GPhoneKey); + if (pos0 != -1) { + pos0 = pos0 + strlen(_2GPhoneKey); + phone_number = topic.substring(pos0); + trc(F("MQTTto2G phone ok")); + trc(phone_number); + trc(F("MQTTto2G sms")); + trc(data); + if (A6l.sendSMS(phone_number,data) == A6_OK ) { + trc("SMS OK"); + // Acknowledgement to the GTW2G topic + pub(subjectGTW2GtoMQTT, datacallback);// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also + }else{ + trc("SMS KO"); + // Acknowledgement to the GTW2G topic + pub(subjectGTW2GtoMQTT, "SMS KO");// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also + } + }else{ + trc(F("MQTTto2G Fail reading phone number")); + } + } + } +#endif + +#ifdef jsonPublishing + void MQTTto2G(char * topicOri, JsonObject& SMSdata) { + + String topic = topicOri; + if (topic == subjectMQTTto2G) { + const char * sms = SMSdata["message"]; + const char * phone = SMSdata["phone"]; + trc(F("MQTTto2G json data analysis")); + if (sms && phone) { + trc(F("MQTTto2G sms & phone ok")); + trc(sms); + if (A6l.sendSMS(String(phone),String(sms)) == A6_OK ) { + trc("SMS OK"); + // Acknowledgement to the GTW2G topic + pub(subjectGTW2GtoMQTT, SMSdata);// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also + }else{ + trc("SMS KO"); + pub(subjectGTW2GtoMQTT, "SMS KO");// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also + } + }else{ + trc(F("MQTTto2G Fail reading from json")); + } + } + + } +#endif #endif diff --git a/ZgatewayBT.ino b/ZgatewayBT.ino index 6ecb04e5..bff4860f 100644 --- a/ZgatewayBT.ino +++ b/ZgatewayBT.ino @@ -50,40 +50,34 @@ Thanks to wolass https://github.com/wolass for suggesting me HM 10 and dinosd ht class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { void onResult(BLEAdvertisedDevice advertisedDevice) { + trc(F("Creating BLE buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& BLEdata = jsonBuffer.createObject(); String mac_adress = advertisedDevice.getAddress().toString().c_str(); + BLEdata.set("id", mac_adress); mac_adress.replace(":",""); mac_adress.toUpperCase(); String mactopic = subjectBTtoMQTT + mac_adress; if (advertisedDevice.haveName()){ - trc(F("Get Name ")); - String nameBLE = advertisedDevice.getName().c_str(); - trc(nameBLE); - client.publish((char *)(mactopic + "/name").c_str(),(char *)nameBLE.c_str()); + BLEdata.set("name", (char *)advertisedDevice.getName().c_str()); } if (advertisedDevice.haveManufacturerData()){ - trc(F("Get ManufacturerData ")); - String ManufacturerData = advertisedDevice.getManufacturerData().c_str(); - trc(ManufacturerData); - client.publish((char *)(mactopic + "/ManufacturerData").c_str(),(char *)ManufacturerData.c_str()); + BLEdata.set("manufacturerdata", (char *)advertisedDevice.getManufacturerData().c_str()); } if (advertisedDevice.haveRSSI()){ - trc(F("Get RSSI ")); - String rssi = String(advertisedDevice.getRSSI()); - String rssitopic = mactopic + subjectBTtoMQTTrssi; - trc(rssitopic + " " + rssi); - client.publish((char *)rssitopic.c_str(),(char *)rssi.c_str()); + BLEdata.set("rssi", (int) advertisedDevice.getRSSI()); + #ifdef subjectHomePresence + haRoomPresence(BLEdata);// this device has an rssi in consequence we can use it for home assistant room presence component + #endif } if (advertisedDevice.haveTXPower()){ - trc(F("Get TXPower ")); - int8_t TXPower = advertisedDevice.getTXPower(); - trc(TXPower); - char cTXPower[5]; - sprintf(cTXPower, "%d", TXPower); - client.publish((char *)(mactopic + "/tx").c_str(),cTXPower); + BLEdata.set("txpower", (int8_t) advertisedDevice.getTXPower()); } if (advertisedDevice.haveServiceData()){ + char mac[mac_adress.length()+1]; mac_adress.toCharArray(mac,mac_adress.length()+1); + trc(F("Get service data ")); std::string serviceData = advertisedDevice.getServiceData(); int serviceDataLength = serviceData.length(); @@ -100,28 +94,25 @@ Thanks to wolass https://github.com/wolass for suggesting me HM 10 and dinosd ht char service_data[returnedString.length()+1]; returnedString.toCharArray(service_data,returnedString.length()+1); service_data[returnedString.length()] = '\0'; - trc(F("service_data")); - trc(service_data); - String mactopic(mac); - mactopic = subjectBTtoMQTT + mactopic + subjectBTtoMQTTservicedata; - client.publish((char *)mactopic.c_str(),service_data); + BLEdata.set("servicedata", service_data); - trc(F("Get service data UUID")); - BLEUUID serviceDataUUID = advertisedDevice.getServiceDataUUID(); - trc(serviceDataUUID.toString().c_str()); - - if (strstr(serviceDataUUID.toString().c_str(),"fe95") != NULL){ + BLEdata.set("servicedatauuid", (char *)advertisedDevice.getServiceDataUUID().toString().c_str()); + + char topic[] = subjectBTtoMQTT; + strcat(topic, mac); + pub(topic,BLEdata); + + if (strstr(BLEdata["servicedatauuid"].as(),"fe95") != NULL){ trc("Processing BLE device data"); int pos = -1; pos = strpos(service_data,"209800"); - if (strstr(service_data,"209800") != NULL) { + if (pos != -1){ trc("mi flora data reading"); - boolean result = process_data(pos - 24,service_data,mac); } pos = -1; pos = strpos(service_data,"20aa01"); - if (strstr(service_data,"20aa01") != NULL){ + if (pos != -1){ trc("mi jia data reading"); boolean result = process_data(pos - 26,service_data,mac); } @@ -160,7 +151,7 @@ Thanks to wolass https://github.com/wolass for suggesting me HM 10 and dinosd ht "coreTask", /* Name of the task */ 10000, /* Stack size in words */ NULL, /* Task input parameter */ - 1, /* Priority of the task */ + 0, /* Priority of the task */ NULL, /* Task handle. */ taskCore); /* Core where the task should run */ trc(F("ZgatewayBT multicore ESP32 setup done ")); @@ -269,36 +260,45 @@ boolean BTtoMQTT() { if((strlen(d[0].extract)) == 12) // if a mac adress is detected we publish it { - strupp(d[0].extract); - String mactopic; - trc(d[0].extract); - trc(d[0].extract); - mactopic = subjectBTtoMQTT + String(d[0].extract) + subjectBTtoMQTTrssi; - int rssi = (int)strtol(d[2].extract, NULL, 16) - 256; - char val[12]; - sprintf(val, "%d", rssi); - client.publish((char *)mactopic.c_str(),val); - trc(F("service_data")); - String Service_data(d[5].extract); - Service_data = Service_data.substring(14); - trc(Service_data); - mactopic = subjectBTtoMQTT + String(d[0].extract) + subjectBTtoMQTTservicedata; - client.publish((char *)mactopic.c_str(),(char *)(Service_data).c_str()); - if (strcmp(d[4].extract, "fe95") == 0) { - int pos = -1; - pos = strpos(d[5].extract,"209800"); - if (pos != -1) { - trc("mi flora data reading"); - boolean result = process_data(pos - 38,(char *)Service_data.c_str(),d[0].extract); - } - pos = -1; - pos = strpos(d[5].extract,"20aa01"); - if (pos != -1){ - trc("mi jia data reading"); - boolean result = process_data(pos - 40,(char *)Service_data.c_str(),d[0].extract); - } - return true; + trc(F("Creating BLE buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& BLEdata = jsonBuffer.createObject(); + #ifdef subjectHomePresence + String HomePresenceId; + for (int i = 0; i++; i<13){ + String HomePresenceId = HomePresenceId + String(d[0].extract[i]); + if(i % 2 == 0) HomePresenceId += ":"; } + trc(F("HomePresenceId")); + trc(HomePresenceId); + BLEdata.set("id", HomePresenceId); + #endif + strupp(d[0].extract); + String topic = subjectBTtoMQTT + String(d[0].extract); + int rssi = (int)strtol(d[2].extract, NULL, 16) - 256; + BLEdata.set("rssi", (int)rssi); + #ifdef subjectHomePresence + haRoomPresence(BLEdata);// this device has an rssi in consequence we can use it for home assistant room presence component + #endif + String Service_data(d[5].extract); + Service_data = Service_data.substring(14); + BLEdata.set("servicedata", (char *)Service_data.c_str()); + pub((char *)topic.c_str(),BLEdata); + if (strcmp(d[4].extract, "fe95") == 0) { + int pos = -1; + pos = strpos(d[5].extract,"209800"); + if (pos != -1) { + trc("mi flora data reading"); + boolean result = process_data(pos - 38,(char *)Service_data.c_str(),d[0].extract); + } + pos = -1; + pos = strpos(d[5].extract,"20aa01"); + if (pos != -1){ + trc("mi jia data reading"); + boolean result = process_data(pos - 40,(char *)Service_data.c_str(),d[0].extract); + } + return true; + } } } } @@ -341,10 +341,8 @@ boolean BTtoMQTT() { String onedevice = discResult.substring(0,78); onedevice.replace(STRING_MSG,""); String mac = onedevice.substring(53,65); - String rssi = onedevice.substring(66,70); - String mactopic = subjectBTtoMQTT + mac + subjectBTtoMQTTrssi; trc(mactopic + " " + rssi); - client.publish((char *)mactopic.c_str(),(char *)rssi.c_str()); + pub(subjectBTtoMQTT + mac + subjectBTtoMQTTrssi,onedevice.substring(66,70)); discResult = discResult.substring(78); } return true; @@ -369,6 +367,11 @@ boolean BTtoMQTT() { #endif boolean process_data(int offset, char * rest_data, char * mac_adress){ + trc(F("Creating BLE buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& BLEdata = jsonBuffer.createObject(); + trc("rest_data"); + trc(rest_data); int data_length = 0; switch (rest_data[51 + offset]) { case '1' : @@ -376,6 +379,7 @@ boolean process_data(int offset, char * rest_data, char * mac_adress){ case '3' : case '4' : data_length = ((rest_data[51 + offset] - '0') * 2)+1; + trc("data_length"); trc(data_length); break; default: @@ -398,41 +402,38 @@ boolean process_data(int offset, char * rest_data, char * mac_adress){ // second value char val2[12]; - String mactopic2(mac_adress); - mactopic2 = subjectBTtoMQTT + mactopic2; - bool hasTopic2 = false; - - + trc("rest_data"); + trc(rest_data); // Mi flora provides tem(perature), (earth) moi(sture), fer(tility) and lux (illuminance) // Mi Jia provides tem(perature), batt(erry) and hum(idity) // following the value of digit 47 we determine the type of data we get from the sensor switch (rest_data[47 + offset]) { case '9' : - mactopic = mactopic + subjectBTtoMQTTfer; dtostrf(value,0,0,val); + BLEdata.set("fer", val); break; case '4' : - mactopic = mactopic + subjectBTtoMQTTtem; if (value > 65000) value = value - 65535; dtostrf(value/10,3,1,val); // temp has to be divided by 10 + BLEdata.set("tem", val); break; case '6' : - mactopic = mactopic + subjectBTtoMQTThum; if (value > 65000) value = value - 65535; dtostrf(value/10,3,1,val); // hum has to be divided by 10 + BLEdata.set("hum", val); break; case '7' : - mactopic = mactopic + subjectBTtoMQTTlux; dtostrf(value,0,0,val); + BLEdata.set("lux", val); break; case '8' : - mactopic = mactopic + subjectBTtoMQTTmoi; dtostrf(value,0,0,val); + BLEdata.set("moi", val); break; case 'a' : // batteryLevel - mactopic = mactopic + subjectBTtoMQTTbatt; dtostrf(value,0,0,val); + BLEdata.set("batt", val); break; case 'd' : // temp+hum @@ -443,28 +444,31 @@ boolean process_data(int offset, char * rest_data, char * mac_adress){ value = strtol(tempAr, NULL, 16); if (value > 65000) value = value - 65535; dtostrf(value/10,3,1,val); // hum has to be divided by 10 - trc(val); + BLEdata.set("hum", val); // temperature memcpy(tempAr, &data[4], 4); tempAr[4] = '\0'; value = strtol(tempAr, NULL, 16); if (value > 65000) value = value - 65535; dtostrf(value/10,3,1,val2); // hum has to be divided by 10 - trc(val2); - mactopic = mactopic + subjectBTtoMQTThum; - mactopic2 = mactopic2 + subjectBTtoMQTTtem; - hasTopic2 = true; + BLEdata.set("tem", val2); break; default: trc("can't read values"); return false; } - client.publish((char *)mactopic.c_str(),val); - if (hasTopic2){ - client.publish((char *)mactopic2.c_str(),val2); - } - trc(val); + pub((char *)mactopic.c_str(),BLEdata); return true; - } +} + +void haRoomPresence(JsonObject& HomePresence){ + trc("BLE DISTANCE :"); + double BLErssi = HomePresence["rssi"]; + double ratio = BLErssi/-59; + double distance = (0.89)* pow(ratio,7.7095) + 0.11; + HomePresence["distance"] = distance; + trc(distance); + pub(subjectHomePresence,HomePresence); +} #endif diff --git a/ZgatewayIR.ino b/ZgatewayIR.ino index 6fd063a8..16014321 100644 --- a/ZgatewayIR.ino +++ b/ZgatewayIR.ino @@ -89,22 +89,28 @@ trc(IR_RECEIVER_PIN); trc(F("ZgatewayIR setup done ")); } -boolean IRtoMQTT(){ +void IRtoMQTT(){ decode_results results; if (irrecv.decode(&results)){ + trc(F("Creating IR buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& IRdata = jsonBuffer.createObject(); + trc(F("Rcv. IR")); #ifdef ESP32 String taskMessage = "Task running on core "; taskMessage = taskMessage + xPortGetCoreID(); trc(taskMessage); #endif - unsigned long MQTTvalue = 0; - String MQTTprotocol; - String MQTTbits; - MQTTvalue = results.value; - MQTTprotocol = String(results.decode_type); - MQTTbits = String(results.bits); + IRdata.set("value", (unsigned long)(results.value)); + IRdata.set("protocol", (int)(results.decode_type)); + IRdata.set("bits",(int)(results.bits)); + + trc(F("LED MNG")); + digitalWrite(led_receive, LOW); + timer_led_receive = millis(); + String rawCode = ""; // Dump data for (uint16_t i = 1; i < results.rawlen; i++) { @@ -117,6 +123,7 @@ boolean IRtoMQTT(){ if ( i < results.rawlen-1 ) rawCode = rawCode + ","; // ',' not needed on last one } trc(rawCode); + IRdata.set("raw", rawCode); // if needed we directly resend the raw code if (RawDirectForward){ #ifdef ESP8266 @@ -129,353 +136,662 @@ boolean IRtoMQTT(){ #endif rawsend[i] = results.rawbuf[i]; } - irsend.sendRaw(rawsend, results.rawlen, RawFrequency); + irsend.sendRaw(rawsend, results.rawlen, RawFrequency); trc(F("raw signal redirected")); } irrecv.resume(); // Receive the next value - - if (pubIRunknownPrtcl == false && MQTTprotocol == "-1"){ // don't publish unknown IR protocol + unsigned long MQTTvalue = IRdata.get("value"); + if (pubIRunknownPrtcl == false && IRdata.get("protocol") == -1){ // don't publish unknown IR protocol trc(F("--no pub. unknown protocol--")); } else if (!isAduplicate(MQTTvalue) && MQTTvalue!=0) {// conditions to avoid duplications of RF -->MQTT - trc(F("Adv data IRtoMQTT")); - client.publish(subjectIRtoMQTTprotocol,(char *)MQTTprotocol.c_str()); - client.publish(subjectIRtoMQTTbits,(char *)MQTTbits.c_str()); - client.publish(subjectIRtoMQTTRaw,(char *)rawCode.c_str()); - trc(F("Sending IRtoMQTT")); - String value = String(MQTTvalue); - trc(value); - boolean result = client.publish(subjectIRtoMQTT,(char *)value.c_str()); + trc(F("Adv data IRtoMQTT")); + pub(subjectIRtoMQTT,IRdata); if (repeatIRwMQTT){ trc(F("Pub. IR for repeat")); - client.publish(subjectMQTTtoIR,(char *)value.c_str()); + pub(subjectMQTTtoIR,MQTTvalue); } - return result; } - } - return false; + } } -void MQTTtoIR(char * topicOri, char * datacallback) { - - // IR DATA ANALYSIS - //send received MQTT value by IR signal - boolean signalSent = false; - uint64_t data = 0; - String strcallback = String(datacallback); - trc(datacallback); - int s = strcallback.length(); - //number of "," value count - int count = 0; - for(int i = 0; i < s; i++) - { - if (datacallback[i] == ',') { - count++; - } - } - if(count == 0){ - data = strtoul(datacallback, NULL, 10); // standard sending with unsigned long, we will not be able to pass values > 4294967295 - } - #ifdef IR_GC - else if(strstr(topicOri, "IR_GC") != NULL){ // sending GC data from https://irdb.globalcache.com - trc("IR_GC"); - //buffer allocation from char datacallback - uint16_t GC[count+1]; - String value = ""; - int j = 0; - for(int i = 0; i < s; i++) - { - if (datacallback[i] != ',') { - value = value + String(datacallback[i]); - } - if ((datacallback[i] == ',') || (i == s - 1)) - { - GC[j]= value.toInt(); - value = ""; - j++; - } - } - irsend.sendGC(GC, j); - signalSent = true; - } - #endif - #ifdef IR_Raw - else if(strstr(topicOri, "IR_Raw") != NULL){ // sending Raw data - trc("IR_Raw"); - //buffer allocation from char datacallback - #ifdef ESP8266 - uint16_t Raw[count+1]; - #else - unsigned int Raw[count+1]; - #endif - String value = ""; - int j = 0; - for(int i = 0; i < s; i++) - { - if (datacallback[i] != ',') { - value = value + String(datacallback[i]); - } - if ((datacallback[i] == ',') || (i == s - 1)) - { - Raw[j]= value.toInt(); - value = ""; - j++; - } - } - irsend.sendRaw(Raw, j, RawFrequency); - signalSent = true; - } - #endif +#ifdef simplePublishing + void MQTTtoIR(char * topicOri, char * datacallback) { - //We look into the subject to see if a special Bits number is defined - String topic = topicOri; - unsigned int valueBITS = 0; - int pos = topic.lastIndexOf(IRbitsKey); - if (pos != -1){ - pos = pos + +strlen(IRbitsKey); - valueBITS = (topic.substring(pos,pos + 2)).toInt(); - trc(F("Bits nb:")); - trc(valueBITS); - } - //We look into the subject to see if a special repeat number is defined - uint16_t valueRPT = 0; - int pos2 = topic.lastIndexOf(IRRptKey); - if (pos2 != -1) { - pos2 = pos2 + strlen(IRRptKey); - valueRPT = (topic.substring(pos2,pos2 + 1)).toInt(); - trc(F("IR repeat:")); - trc(valueRPT); - } + // IR DATA ANALYSIS + //send received MQTT value by IR signal + boolean signalSent = false; + uint64_t data = 0; + String strcallback = String(datacallback); + trc(datacallback); + unsigned int s = strcallback.length(); + //number of "," value count + int count = 0; + for(int i = 0; i < s; i++) + { + if (datacallback[i] == ',') { + count++; + } + } + if(count == 0){ + data = strtoul(datacallback, NULL, 10); // standard sending with unsigned long, we will not be able to pass values > 4294967295 + } + #ifdef IR_GC + else if(strstr(topicOri, "IR_GC") != NULL){ // sending GC data from https://irdb.globalcache.com + trc("IR_GC"); + //buffer allocation from char datacallback + uint16_t GC[count+1]; + String value = ""; + int j = 0; + for(int i = 0; i < s; i++) + { + if (datacallback[i] != ',') { + value = value + String(datacallback[i]); + } + if ((datacallback[i] == ',') || (i == s - 1)) + { + GC[j]= value.toInt(); + value = ""; + j++; + } + } + irsend.sendGC(GC, j); + signalSent = true; + } + #endif + #ifdef IR_Raw + else if(strstr(topicOri, "IR_Raw") != NULL){ // sending Raw data + trc("IR_Raw"); + //buffer allocation from char datacallback + #ifdef ESP8266 + uint16_t Raw[count+1]; + #else + unsigned int Raw[count+1]; + #endif + String value = ""; + int j = 0; + for(int i = 0; i < s; i++) + { + if (datacallback[i] != ',') { + value = value + String(datacallback[i]); + } + if ((datacallback[i] == ',') || (i == s - 1)) + { + Raw[j]= value.toInt(); + value = ""; + j++; + } + } + irsend.sendRaw(Raw, j, RawFrequency); + signalSent = true; + } + #endif + + //We look into the subject to see if a special Bits number is defined + String topic = topicOri; + unsigned int valueBITS = 0; + int pos = topic.lastIndexOf(IRbitsKey); + if (pos != -1){ + pos = pos + +strlen(IRbitsKey); + valueBITS = (topic.substring(pos,pos + 2)).toInt(); + trc(F("Bits nb:")); + trc(valueBITS); + } + //We look into the subject to see if a special repeat number is defined + uint16_t valueRPT = 0; + int pos2 = topic.lastIndexOf(IRRptKey); + if (pos2 != -1) { + pos2 = pos2 + strlen(IRRptKey); + valueRPT = (topic.substring(pos2,pos2 + 1)).toInt(); + trc(F("IR repeat:")); + trc(valueRPT); + } + + #ifdef ESP8266 // send coolix not available for arduino IRRemote library + #ifdef IR_COOLIX + if (strstr(topicOri, "IR_COOLIX") != NULL){ + if (valueBITS == 0) valueBITS = COOLIX_BITS; + irsend.sendCOOLIX(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #endif + if (strstr(topicOri, "IR_NEC") != NULL || strstr(topicOri, subjectMQTTtoIR) != NULL ){ + if (valueBITS == 0) valueBITS = NEC_BITS; + #ifdef ESP8266 + irsend.sendNEC(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendNEC(data, valueBITS); + #endif + signalSent = true; + } + #ifdef IR_Whynter + if (strstr(topicOri, "IR_Whynter") != NULL){ + if (valueBITS == 0) valueBITS = WHYNTER_BITS; + #ifdef ESP8266 + irsend.sendWhynter(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendWhynter(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_LG + if (strstr(topicOri, "IR_LG") != NULL){ + if (valueBITS == 0) valueBITS = LG_BITS; + #ifdef ESP8266 + irsend.sendLG(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendLG(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_Sony + if (strstr(topicOri, "IR_Sony") != NULL){ + if (valueBITS == 0) valueBITS = SONY_12_BITS; + if (valueRPT == 0) valueRPT = repeatIRwNumber; + #ifdef ESP8266 + irsend.sendSony(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendSony(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_DISH + if (strstr(topicOri, "IR_DISH") != NULL){ + if (valueBITS == 0) valueBITS = DISH_BITS; + #ifdef ESP8266 + irsend.sendDISH(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendDISH(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_RC5 + if (strstr(topicOri, "IR_RC5") != NULL){ + if (valueBITS == 0) valueBITS = RC5_BITS; + #ifdef ESP8266 + irsend.sendRC5(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendRC5(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_RC6 + if (strstr(topicOri, "IR_RC6") != NULL){ + if (valueBITS == 0) valueBITS = RC6_MODE0_BITS; + #ifdef ESP8266 + irsend.sendRC6(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendRC6(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_Sharp + if (strstr(topicOri, "IR_Sharp") != NULL){ + if (valueBITS == 0) valueBITS = SHARP_BITS; + #ifdef ESP8266 + irsend.sendSharpRaw(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendSharpRaw(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_SAMSUNG + if (strstr(topicOri, "IR_SAMSUNG") != NULL){ + if (valueBITS == 0) valueBITS = SAMSUNG_BITS; + #ifdef ESP8266 + irsend.sendSAMSUNG(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendSAMSUNG(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_JVC + if (strstr(topicOri, "IR_JVC") != NULL){ + if (valueBITS == 0) valueBITS = JVC_BITS; + if (valueRPT == 0) valueRPT = repeatIRwNumber; + #ifdef ESP8266 + irsend.sendJVC(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendJVC(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_PANASONIC + if (strstr(topicOri, "IR_PANASONIC") != NULL){ + if (valueRPT == 0) valueRPT = repeatIRwNumber; + #ifdef ESP8266 + if (valueBITS == 0) valueBITS = PANASONIC_BITS; + irsend.sendPanasonic(PanasonicAddress, data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendPanasonic(PanasonicAddress, data); + #endif + signalSent = true; + } + #endif - #ifdef ESP8266 // send coolix not available for arduino IRRemote library - #ifdef IR_COOLIX - if (strstr(topicOri, "IR_COOLIX") != NULL){ - if (valueBITS == 0) valueBITS = COOLIX_BITS; - irsend.sendCOOLIX(data, valueBITS, valueRPT); + #ifdef ESP8266 // sendings not available on arduino + #ifdef IR_RCMM + if (strstr(topicOri, "IR_RCMM") != NULL){ + if (valueBITS == 0) valueBITS = RCMM_BITS; + irsend.sendRCMM(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_DENON + if (strstr(topicOri, "IR_DENON") != NULL){ + if (valueBITS == 0) valueBITS = DENON_BITS; + irsend.sendDenon(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_GICABLE + if (strstr(topicOri, "IR_GICABLE") != NULL){ + if (valueBITS == 0) valueBITS = GICABLE_BITS; + if (valueRPT == 0) valueRPT = std::max(valueRPT, (uint16_t) GICABLE_MIN_REPEAT); + irsend.sendGICable(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_SHERWOOD + if (strstr(topicOri, "IR_SHERWOOD") != NULL){ + if (valueBITS == 0) valueBITS = SHERWOOD_BITS; + if (valueRPT == 0) valueRPT = std::max(valueRPT, (uint16_t) SHERWOOD_MIN_REPEAT); + irsend.sendSherwood(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_MITSUBISHI + if (strstr(topicOri, "IR_MITSUBISHI") != NULL){ + if (valueBITS == 0) valueBITS = MITSUBISHI_BITS; + if (valueRPT == 0) valueRPT = std::max(valueRPT, (uint16_t) MITSUBISHI_MIN_REPEAT); + irsend.sendMitsubishi(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_NIKAI + if (strstr(topicOri, "IR_NIKAI") != NULL){ + if (valueBITS == 0) valueBITS = NIKAI_BITS; + irsend.sendNikai(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_MIDEA + if (strstr(topicOri, "IR_MIDEA") != NULL){ + if (valueBITS == 0) valueBITS = MIDEA_BITS; + irsend.sendMidea(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_MAGIQUEST + if (strstr(topicOri, "IR_MAGIQUEST") != NULL){ + if (valueBITS == 0) valueBITS = MAGIQUEST_BITS; + irsend.sendMagiQuest(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_LASERTAG + if (strstr(topicOri, "IR_LASERTAG") != NULL){ + if (valueBITS == 0) valueBITS = LASERTAG_BITS; + irsend.sendLasertag(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_CARRIER_AC + if (strstr(topicOri, "IR_CARRIER_AC") != NULL){ + if (valueBITS == 0) valueBITS = CARRIER_AC_BITS; + irsend.sendCarrierAC(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_MITSUBISHI2 + if (strstr(topicOri, "IR_MITSUBISHI2") != NULL){ + if (valueBITS == 0) valueBITS = MITSUBISHI_BITS; + if (valueRPT == 0) valueRPT = std::max(valueRPT, (uint16_t) MITSUBISHI_MIN_REPEAT); + irsend.sendMitsubishi2(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_AIWA_RC_T501 + if (strstr(topicOri, "IR_MITSUBISHI") != NULL){ + if (valueBITS == 0) valueBITS = AIWA_RC_T501_BITS; + if (valueRPT == 0) valueRPT = std::max(valueRPT, (uint16_t) AIWA_RC_T501_MIN_REPEAT); + irsend.sendAiwaRCT501(data, valueBITS, valueRPT); signalSent = true; } #endif #endif - if (strstr(topicOri, "IR_NEC") != NULL || strstr(topicOri, subjectMQTTtoIR) != NULL ){ - if (valueBITS == 0) valueBITS = NEC_BITS; - #ifdef ESP8266 - irsend.sendNEC(data, valueBITS, valueRPT); - #else - for (int i=0; i <= valueRPT; i++) irsend.sendNEC(data, valueBITS); - #endif - signalSent = true; + + if (signalSent){ // we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also + pub(subjectGTWIRtoMQTT, datacallback); + } + irrecv.enableIRIn(); // ReStart the IR receiver (if not restarted it is not able to receive data) } - #ifdef IR_Whynter - if (strstr(topicOri, "IR_Whynter") != NULL){ - if (valueBITS == 0) valueBITS = WHYNTER_BITS; - #ifdef ESP8266 - irsend.sendWhynter(data, valueBITS, valueRPT); - #else - for (int i=0; i <= valueRPT; i++) irsend.sendWhynter(data, valueBITS); - #endif - signalSent = true; - } - #endif - #ifdef IR_LG - if (strstr(topicOri, "IR_LG") != NULL){ - if (valueBITS == 0) valueBITS = LG_BITS; - #ifdef ESP8266 - irsend.sendLG(data, valueBITS, valueRPT); - #else - for (int i=0; i <= valueRPT; i++) irsend.sendLG(data, valueBITS); - #endif - signalSent = true; - } - #endif - #ifdef IR_Sony - if (strstr(topicOri, "IR_Sony") != NULL){ - if (valueBITS == 0) valueBITS = SONY_12_BITS; - if (valueRPT == 0) valueRPT = 2; - #ifdef ESP8266 - irsend.sendSony(data, valueBITS, valueRPT); - #else - for (int i=0; i <= valueRPT; i++) irsend.sendSony(data, valueBITS); - #endif - signalSent = true; - } - #endif - #ifdef IR_DISH - if (strstr(topicOri, "IR_DISH") != NULL){ - if (valueBITS == 0) valueBITS = DISH_BITS; - #ifdef ESP8266 - irsend.sendDISH(data, valueBITS, valueRPT); - #else - for (int i=0; i <= valueRPT; i++) irsend.sendDISH(data, valueBITS); - #endif - signalSent = true; - } - #endif - #ifdef IR_RC5 - if (strstr(topicOri, "IR_RC5") != NULL){ - if (valueBITS == 0) valueBITS = RC5_BITS; - #ifdef ESP8266 - irsend.sendRC5(data, valueBITS, valueRPT); - #else - for (int i=0; i <= valueRPT; i++) irsend.sendRC5(data, valueBITS); - #endif - signalSent = true; - } - #endif - #ifdef IR_RC6 - if (strstr(topicOri, "IR_RC6") != NULL){ - if (valueBITS == 0) valueBITS = RC6_MODE0_BITS; - #ifdef ESP8266 - irsend.sendRC6(data, valueBITS, valueRPT); - #else - for (int i=0; i <= valueRPT; i++) irsend.sendRC6(data, valueBITS); - #endif - signalSent = true; - } - #endif - #ifdef IR_Sharp - if (strstr(topicOri, "IR_Sharp") != NULL){ - if (valueBITS == 0) valueBITS = SHARP_BITS; - #ifdef ESP8266 - irsend.sendSharpRaw(data, valueBITS, valueRPT); - #else - for (int i=0; i <= valueRPT; i++) irsend.sendSharpRaw(data, valueBITS); - #endif - signalSent = true; - } - #endif - #ifdef IR_SAMSUNG - if (strstr(topicOri, "IR_SAMSUNG") != NULL){ - if (valueBITS == 0) valueBITS = SAMSUNG_BITS; - #ifdef ESP8266 - irsend.sendSAMSUNG(data, valueBITS, valueRPT); - #else - for (int i=0; i <= valueRPT; i++) irsend.sendSAMSUNG(data, valueBITS); - #endif - signalSent = true; - } - #endif - #ifdef IR_JVC - if (strstr(topicOri, "IR_JVC") != NULL){ - if (valueBITS == 0) valueBITS = JVC_BITS; - if (valueRPT == 0) valueRPT = 2; - #ifdef ESP8266 - irsend.sendJVC(data, valueBITS, valueRPT); - #else - for (int i=0; i <= valueRPT; i++) irsend.sendJVC(data, valueBITS); - #endif - signalSent = true; - } - #endif - #ifdef IR_PANASONIC - if (strstr(topicOri, "IR_PANASONIC") != NULL){ - if (valueRPT == 0) valueRPT = 2; - #ifdef ESP8266 - if (valueBITS == 0) valueBITS = PANASONIC_BITS; - irsend.sendPanasonic(PanasonicAddress, data, valueBITS, valueRPT); - #else - for (int i=0; i <= valueRPT; i++) irsend.sendPanasonic(PanasonicAddress, data); - #endif - signalSent = true; - } - #endif - -#ifdef ESP8266 // sendings not available on arduino - #ifdef IR_RCMM - if (strstr(topicOri, "IR_RCMM") != NULL){ - if (valueBITS == 0) valueBITS = RCMM_BITS; - irsend.sendRCMM(data, valueBITS, valueRPT); - signalSent = true; - } - #endif - #ifdef IR_DENON - if (strstr(topicOri, "IR_DENON") != NULL){ - if (valueBITS == 0) valueBITS = DENON_BITS; - irsend.sendDenon(data, valueBITS, valueRPT); - signalSent = true; - } - #endif - #ifdef IR_GICABLE - if (strstr(topicOri, "IR_GICABLE") != NULL){ - if (valueBITS == 0) valueBITS = GICABLE_BITS; - if (valueRPT == 0) valueRPT = std::max(valueRPT, (uint16_t) GICABLE_MIN_REPEAT); - irsend.sendGICable(data, valueBITS, valueRPT); - signalSent = true; - } - #endif - #ifdef IR_SHERWOOD - if (strstr(topicOri, "IR_SHERWOOD") != NULL){ - if (valueBITS == 0) valueBITS = SHERWOOD_BITS; - if (valueRPT == 0) valueRPT = std::max(valueRPT, (uint16_t) SHERWOOD_MIN_REPEAT); - irsend.sendSherwood(data, valueBITS, valueRPT); - signalSent = true; - } - #endif - #ifdef IR_MITSUBISHI - if (strstr(topicOri, "IR_MITSUBISHI") != NULL){ - if (valueBITS == 0) valueBITS = MITSUBISHI_BITS; - if (valueRPT == 0) valueRPT = std::max(valueRPT, (uint16_t) MITSUBISHI_MIN_REPEAT); - irsend.sendMitsubishi(data, valueBITS, valueRPT); - signalSent = true; - } - #endif - #ifdef IR_NIKAI - if (strstr(topicOri, "IR_NIKAI") != NULL){ - if (valueBITS == 0) valueBITS = NIKAI_BITS; - irsend.sendNikai(data, valueBITS, valueRPT); - signalSent = true; - } - #endif - #ifdef IR_MIDEA - if (strstr(topicOri, "IR_MIDEA") != NULL){ - if (valueBITS == 0) valueBITS = MIDEA_BITS; - irsend.sendMidea(data, valueBITS, valueRPT); - signalSent = true; - } - #endif - #ifdef IR_MAGIQUEST - if (strstr(topicOri, "IR_MAGIQUEST") != NULL){ - if (valueBITS == 0) valueBITS = MAGIQUEST_BITS; - irsend.sendMagiQuest(data, valueBITS, valueRPT); - signalSent = true; - } - #endif - #ifdef IR_LASERTAG - if (strstr(topicOri, "IR_LASERTAG") != NULL){ - if (valueBITS == 0) valueBITS = LASERTAG_BITS; - irsend.sendLasertag(data, valueBITS, valueRPT); - signalSent = true; - } - #endif - #ifdef IR_CARRIER_AC - if (strstr(topicOri, "IR_CARRIER_AC") != NULL){ - if (valueBITS == 0) valueBITS = CARRIER_AC_BITS; - irsend.sendCarrierAC(data, valueBITS, valueRPT); - signalSent = true; - } - #endif - #ifdef IR_MITSUBISHI2 - if (strstr(topicOri, "IR_MITSUBISHI2") != NULL){ - if (valueBITS == 0) valueBITS = MITSUBISHI_BITS; - if (valueRPT == 0) valueRPT = std::max(valueRPT, (uint16_t) MITSUBISHI_MIN_REPEAT); - irsend.sendMitsubishi2(data, valueBITS, valueRPT); - signalSent = true; - } - #endif - #ifdef IR_AIWA_RC_T501 - if (strstr(topicOri, "IR_MITSUBISHI") != NULL){ - if (valueBITS == 0) valueBITS = AIWA_RC_T501_BITS; - if (valueRPT == 0) valueRPT = std::max(valueRPT, (uint16_t) AIWA_RC_T501_MIN_REPEAT); - irsend.sendAiwaRCT501(data, valueBITS, valueRPT); - signalSent = true; - } - #endif #endif - if (signalSent){ // we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also - boolean result = client.publish(subjectGTWIRtoMQTT, datacallback); - if (result){ - trc(F("MQTTtoIR ack pub.")); - }; +#ifdef jsonPublishing + void MQTTtoIR(char * topicOri, JsonObject& IRdata) { + + String topic = topicOri; + + if (topic == subjectMQTTtoIR) { + trc(F("MQTTtoIR json data analysis")); + unsigned long data = IRdata["value"]; + const char * raw = IRdata["raw"]; + if (data != 0||raw) { + trc(F("MQTTtoIR data || raw ok")); + boolean signalSent = false; + trc(data); + const char * protocol_name = IRdata["protocol_name"]; + if(raw){ + unsigned int s = strlen(raw); + //number of "," value count + int count = 0; + for(int i = 0; i < s; i++) + { + if (raw[i] == ',') { + count++; + } + } + #ifdef IR_GC + if(strstr(protocol_name, "IR_GC") != NULL){ // sending GC data from https://irdb.globalcache.com + trc("IR_GC"); + //buffer allocation from char datacallback + uint16_t GC[count+1]; + String value = ""; + int j = 0; + for(int i = 0; i < s; i++) + { + if (raw[i] != ',') { + value = value + String(raw[i]); + } + if ((raw[i] == ',') || (i == s - 1)) + { + GC[j]= value.toInt(); + value = ""; + j++; + } + } + irsend.sendGC(GC, j); + signalSent = true; + } + #endif + #ifdef IR_Raw + if(strstr(protocol_name, "IR_Raw") != NULL){ // sending Raw data + trc("IR_Raw"); + //buffer allocation from char datacallback + #ifdef ESP8266 + uint16_t Raw[count+1]; + #else + unsigned int Raw[count+1]; + #endif + String value = ""; + int j = 0; + for(int i = 0; i < s; i++) + { + if (raw[i] != ',') { + value = value + String(raw[i]); + } + if ((raw[i] == ',') || (i == s - 1)) + { + Raw[j]= value.toInt(); + value = ""; + j++; + } + } + irsend.sendRaw(Raw, j, RawFrequency); + signalSent = true; + } + #endif + }else if(protocol_name){ + unsigned int valueBITS = IRdata["bits"]; + trc(F("Bits nb:")); + trc(valueBITS); + + uint16_t valueRPT = IRdata["repeat"]|repeatIRwNumber; + trc(F("IR repeat:")); + trc(valueRPT); + + #ifdef ESP8266 // send coolix not available for arduino IRRemote library + #ifdef IR_COOLIX + if (strstr(protocol_name, "IR_COOLIX") != NULL){ + if (valueBITS == 0) valueBITS = COOLIX_BITS; + irsend.sendCOOLIX(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #endif + if (strstr(protocol_name, "IR_NEC") != NULL || !protocol_name ){ + if (valueBITS == 0) valueBITS = NEC_BITS; + #ifdef ESP8266 + irsend.sendNEC(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendNEC(data, valueBITS); + #endif + signalSent = true; + } + #ifdef IR_Whynter + if (strstr(protocol_name, "IR_Whynter") != NULL){ + if (valueBITS == 0) valueBITS = WHYNTER_BITS; + #ifdef ESP8266 + irsend.sendWhynter(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendWhynter(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_LG + if (strstr(protocol_name, "IR_LG") != NULL){ + if (valueBITS == 0) valueBITS = LG_BITS; + #ifdef ESP8266 + irsend.sendLG(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendLG(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_Sony + if (strstr(protocol_name, "IR_Sony") != NULL){ + if (valueBITS == 0) valueBITS = SONY_12_BITS; + #ifdef ESP8266 + irsend.sendSony(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendSony(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_DISH + if (strstr(protocol_name, "IR_DISH") != NULL){ + if (valueBITS == 0) valueBITS = DISH_BITS; + #ifdef ESP8266 + irsend.sendDISH(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendDISH(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_RC5 + if (strstr(protocol_name, "IR_RC5") != NULL){ + if (valueBITS == 0) valueBITS = RC5_BITS; + #ifdef ESP8266 + irsend.sendRC5(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendRC5(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_RC6 + if (strstr(protocol_name, "IR_RC6") != NULL){ + if (valueBITS == 0) valueBITS = RC6_MODE0_BITS; + #ifdef ESP8266 + irsend.sendRC6(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendRC6(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_Sharp + if (strstr(protocol_name, "IR_Sharp") != NULL){ + if (valueBITS == 0) valueBITS = SHARP_BITS; + #ifdef ESP8266 + irsend.sendSharpRaw(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendSharpRaw(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_SAMSUNG + if (strstr(protocol_name, "IR_SAMSUNG") != NULL){ + if (valueBITS == 0) valueBITS = SAMSUNG_BITS; + #ifdef ESP8266 + irsend.sendSAMSUNG(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendSAMSUNG(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_JVC + if (strstr(protocol_name, "IR_JVC") != NULL){ + if (valueBITS == 0) valueBITS = JVC_BITS; + #ifdef ESP8266 + irsend.sendJVC(data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendJVC(data, valueBITS); + #endif + signalSent = true; + } + #endif + #ifdef IR_PANASONIC + if (strstr(protocol_name, "IR_PANASONIC") != NULL){ + #ifdef ESP8266 + if (valueBITS == 0) valueBITS = PANASONIC_BITS; + irsend.sendPanasonic(PanasonicAddress, data, valueBITS, valueRPT); + #else + for (int i=0; i <= valueRPT; i++) irsend.sendPanasonic(PanasonicAddress, data); + #endif + signalSent = true; + } + #endif + + #ifdef ESP8266 // sendings not available on arduino + #ifdef IR_RCMM + if (strstr(protocol_name, "IR_RCMM") != NULL){ + if (valueBITS == 0) valueBITS = RCMM_BITS; + irsend.sendRCMM(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_DENON + if (strstr(protocol_name, "IR_DENON") != NULL){ + if (valueBITS == 0) valueBITS = DENON_BITS; + irsend.sendDenon(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_GICABLE + if (strstr(protocol_name, "IR_GICABLE") != NULL){ + if (valueBITS == 0) valueBITS = GICABLE_BITS; + if (valueRPT == repeatIRwNumber) valueRPT = std::max(valueRPT, (uint16_t) GICABLE_MIN_REPEAT); + irsend.sendGICable(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_SHERWOOD + if (strstr(protocol_name, "IR_SHERWOOD") != NULL){ + if (valueBITS == 0) valueBITS = SHERWOOD_BITS; + if (valueRPT == repeatIRwNumber) valueRPT = std::max(valueRPT, (uint16_t) SHERWOOD_MIN_REPEAT); + irsend.sendSherwood(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_MITSUBISHI + if (strstr(protocol_name, "IR_MITSUBISHI") != NULL){ + if (valueBITS == 0) valueBITS = MITSUBISHI_BITS; + if (valueRPT == repeatIRwNumber) valueRPT = std::max(valueRPT, (uint16_t) MITSUBISHI_MIN_REPEAT); + irsend.sendMitsubishi(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_NIKAI + if (strstr(protocol_name, "IR_NIKAI") != NULL){ + if (valueBITS == 0) valueBITS = NIKAI_BITS; + irsend.sendNikai(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_MIDEA + if (strstr(protocol_name, "IR_MIDEA") != NULL){ + if (valueBITS == 0) valueBITS = MIDEA_BITS; + irsend.sendMidea(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_MAGIQUEST + if (strstr(protocol_name, "IR_MAGIQUEST") != NULL){ + if (valueBITS == 0) valueBITS = MAGIQUEST_BITS; + irsend.sendMagiQuest(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_LASERTAG + if (strstr(protocol_name, "IR_LASERTAG") != NULL){ + if (valueBITS == 0) valueBITS = LASERTAG_BITS; + irsend.sendLasertag(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_CARRIER_AC + if (strstr(protocol_name, "IR_CARRIER_AC") != NULL){ + if (valueBITS == 0) valueBITS = CARRIER_AC_BITS; + irsend.sendCarrierAC(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_MITSUBISHI2 + if (strstr(protocol_name, "IR_MITSUBISHI2") != NULL){ + if (valueBITS == 0) valueBITS = MITSUBISHI_BITS; + if (valueRPT == repeatIRwNumber) valueRPT = std::max(valueRPT, (uint16_t) MITSUBISHI_MIN_REPEAT); + irsend.sendMitsubishi2(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #ifdef IR_AIWA_RC_T501 + if (strstr(protocol_name, "IR_MITSUBISHI") != NULL){ + if (valueBITS == 0) valueBITS = AIWA_RC_T501_BITS; + if (valueRPT == repeatIRwNumber) valueRPT = std::max(valueRPT, (uint16_t) AIWA_RC_T501_MIN_REPEAT); + irsend.sendAiwaRCT501(data, valueBITS, valueRPT); + signalSent = true; + } + #endif + #endif + + if (signalSent){ // we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also + pub(subjectGTWIRtoMQTT, IRdata); + } + irrecv.enableIRIn(); // ReStart the IR receiver (if not restarted it is not able to receive data) + }else{ + trc(F("MQTTtoIR Fail reading protocol name from json")); + } + }else{ + trc(F("MQTTtoIR Fail reading from json")); + } + } } - irrecv.enableIRIn(); // ReStart the IR receiver (if not restarted it is not able to receive data) -} +#endif #endif diff --git a/ZgatewayPilight.ino b/ZgatewayPilight.ino index 3e62daff..bf4e1b35 100644 --- a/ZgatewayPilight.ino +++ b/ZgatewayPilight.ino @@ -17,23 +17,18 @@ the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - OpenMQTTGateway is distributed in the hope that it will be useful, + OpenMQTTGateway is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU General Public License along with this program. If not, see . */ - -#ifdef ZgatewayPilight - -#include - -ESPiLight rf(RF_EMITTER_PIN); // use -1 to disable transmitter - + #ifdef ZgatewayPilight + #include + ESPiLight rf(RF_EMITTER_PIN); // use -1 to disable transmitter void setupPilight(){ - #ifndef ZgatewayRF && ZgatewayRF2 //receiving with Pilight is not compatible with ZgatewayRF or RF2 as far as I can tell + #ifndef ZgatewayRF && ZgatewayRF2 && ZgatewayRF315 //receiving with Pilight is not compatible with ZgatewayRF or RF2 or RF315 as far as I can tell rf.setCallback(pilightCallback); rf.initReceiver(RF_RECEIVER_PIN); trc(F("RF_EMITTER_PIN ")); @@ -41,94 +36,64 @@ void setupPilight(){ trc(F("RF_RECEIVER_PIN ")); trc(String(RF_RECEIVER_PIN)); trc(F("ZgatewayPilight setup done ")); - #endif + #else + trc(F("ZgatewayPilight setup cannot be done, comment first ZgatewayRF && ZgatewayRF2 && ZgatewayRF315")); + #endif } -boolean PilighttoMQTT(){ +void PilighttoMQTT(){ rf.loop(); } void pilightCallback(const String &protocol, const String &message, int status, size_t repeats, const String &deviceID) { - - if (status == VALID) { - + if (status == VALID) { + trc(F("Creating RF PiLight buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& RFPiLightdata = jsonBuffer.createObject(); trc(F("Rcv. Pilight")); - String MQTTprotocol; - String MQTTdeviceID; - String MQTTmessage; - - MQTTprotocol = String(protocol); - MQTTdeviceID = String(deviceID); - MQTTmessage = String(message); - String MQTTPilightstring; - MQTTPilightstring = subjectPilighttoMQTT+String("/")+MQTTprotocol+String("/")+MQTTdeviceID; - trc(F("Adv data PilighttoMQTT")); - client.publish((char *)MQTTPilightstring.c_str(),(char *)MQTTmessage.c_str()); - - } + RFPiLightdata.set("message", (char *)message.c_str()); + RFPiLightdata.set("protocol",(char *)protocol.c_str()); + RFPiLightdata.set("length", (char *)deviceID.c_str()); + RFPiLightdata.set("repeats", (int)repeats); + RFPiLightdata.set("status", (int)status); + pub(subjectPilighttoMQTT,RFPiLightdata); + } } -void MQTTtoPilight(char * topicOri, char * datacallback) { - - String topic = topicOri; - - int pos = topic.lastIndexOf(subjectMQTTtoPilight); - if (pos == -1){ - return; - } - - trc(F("Adv data PilighttoMQTT")); - - char *last = strrchr(topicOri, '/'); - String protocol = ""; - - if (last+1 != NULL) { - protocol = last+1; - } - - int result = 0; - - if (protocol == PilightRAW){ - trc(F("RAW:")); - trc(String(datacallback)); - - uint16_t rawpulses[MAXPULSESTREAMLENGTH]; - int rawlen = - rf.stringToPulseTrain(datacallback, rawpulses, MAXPULSESTREAMLENGTH); - if (rawlen > 0) { - rf.sendPulseTrain(rawpulses, rawlen); - result = rawlen; - } else { +void MQTTtoPilight(char * topicOri, JsonObject& Pilightdata) { +String topic = topicOri; +int result = 0; + +if (topic == subjectMQTTtoPilight) { + trc(F("MQTTtoPilight json data analysis")); + const char * message = Pilightdata["message"]; + const char * protocol = Pilightdata["protocol"]; + if (message && protocol) { + trc(F("MQTTtoPilight msg & protocol ok")); + result = rf.send(protocol, message); + }else{ + trc(F("MQTTtoPilight fail reading from json")); + } + int msgLength = 0; + uint16_t codes[MAXPULSESTREAMLENGTH]; + msgLength = rf.stringToPulseTrain( + message, + codes, MAXPULSESTREAMLENGTH); + if (msgLength > 0) { + trc(F("MQTTtoPilight raw ok")); + rf.sendPulseTrain(codes, msgLength); + result = msgLength; + }else{ + trc(F("MQTTtoPilight raw KO")); result = -9999; } - } else { - trc(F("PROTO:")); - trc(protocol); - result = rf.send(protocol, datacallback); - } - - String MQTTmessage; - String MQTTprotocol = String(protocol); - String MQTTPilightstring = subjectPilighttoMQTT+String("/")+MQTTprotocol+String("/"); - - if (result > 0) { + + String MQTTmessage; + if (result > 0) { trc(F("Adv data MQTTtoPilight push state via PilighttoMQTT")); - - MQTTmessage = String(datacallback); - - char *deviceID = "0"; - - DynamicJsonBuffer jb; - JsonObject& rjson = jb.parseObject(MQTTmessage); - if (rjson.success()) { - strcpy(deviceID, rjson["id"]); - } - - MQTTmessage = String(datacallback); - MQTTPilightstring += String(deviceID); - - } else { + pub(subjectGTWPilighttoMQTT, Pilightdata); + } else { switch (result) { case ESPiLight::ERROR_UNAVAILABLE_PROTOCOL: MQTTmessage = "protocol is not avaiable"; @@ -148,13 +113,8 @@ void MQTTtoPilight(char * topicOri, char * datacallback) { } trc(F("ESPiLight Error: ")); trc(String(MQTTmessage)); - MQTTPilightstring += String("error"); - - } - - client.publish((char *)MQTTPilightstring.c_str(),(char *)MQTTmessage.c_str()); - + pub(subjectGTWPilighttoMQTT, MQTTmessage); + } + } } - -#endif - + #endif diff --git a/ZgatewayRF.ino b/ZgatewayRF.ino index 37be2c5c..71679d0a 100644 --- a/ZgatewayRF.ino +++ b/ZgatewayRF.ino @@ -44,43 +44,41 @@ void setupRF(){ trc(F("ZgatewayRF setup done ")); } -boolean RFtoMQTT(){ +void RFtoMQTT(){ if (mySwitch.available()){ + trc(F("Creating RF buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& RFdata = jsonBuffer.createObject(); trc(F("Rcv. RF")); #ifdef ESP32 String taskMessage = "RF Task running on core "; taskMessage = taskMessage + xPortGetCoreID(); trc(taskMessage); #endif - unsigned long MQTTvalue = 0; - String MQTTprotocol; - String MQTTbits; - String MQTTlength; - MQTTvalue = mySwitch.getReceivedValue(); - MQTTprotocol = String(mySwitch.getReceivedProtocol()); - MQTTbits = String(mySwitch.getReceivedBitlength()); - MQTTlength = String(mySwitch.getReceivedDelay()); + RFdata.set("value", (unsigned long)mySwitch.getReceivedValue()); + RFdata.set("protocol",(int)mySwitch.getReceivedProtocol()); + RFdata.set("length", (int)mySwitch.getReceivedBitlength()); + RFdata.set("delay", (int)mySwitch.getReceivedDelay()); mySwitch.resetAvailable(); + + trc(F("LED MNG")); + digitalWrite(led_receive, LOW); + timer_led_receive = millis(); + + unsigned long MQTTvalue = RFdata.get("value"); if (!isAduplicate(MQTTvalue) && MQTTvalue!=0) {// conditions to avoid duplications of RF -->MQTT - trc(F("Adv data RFtoMQTT")); - client.publish(subjectRFtoMQTTprotocol,(char *)MQTTprotocol.c_str()); - client.publish(subjectRFtoMQTTbits,(char *)MQTTbits.c_str()); - client.publish(subjectRFtoMQTTlength,(char *)MQTTlength.c_str()); - trc(F("Sending RFtoMQTT")); - String value = String(MQTTvalue); - trc(value); - boolean result = client.publish(subjectRFtoMQTT,(char *)value.c_str()); + trc(F("Adv data RFtoMQTT")); + pub(subjectRFtoMQTT,RFdata); if (repeatRFwMQTT){ trc(F("Publish RF for repeat")); - client.publish(subjectMQTTtoRF,(char *)value.c_str()); + pub(subjectMQTTtoRF,RFdata); } - return result; } } - return false; } +#ifdef simplePublishing void MQTTtoRF(char * topicOri, char * datacallback) { unsigned long data = strtoul(datacallback, NULL, 10); // we will not be able to pass values > 4294967295 @@ -119,9 +117,7 @@ void MQTTtoRF(char * topicOri, char * datacallback) { mySwitch.setProtocol(1,350); mySwitch.send(data, 24); // Acknowledgement to the GTWRF topic - boolean result = client.publish(subjectGTWRFtoMQTT, datacallback); - if (result)trc(F("Ack pub.")); - + pub(subjectGTWRFtoMQTT, datacallback); } else if ((valuePRT != 0) || (valuePLSL != 0)|| (valueBITS != 0)){ trc(F("MQTTtoRF usr par.")); if (valuePRT == 0) valuePRT = 1; @@ -133,12 +129,47 @@ void MQTTtoRF(char * topicOri, char * datacallback) { mySwitch.setProtocol(valuePRT,valuePLSL); mySwitch.send(data, valueBITS); // Acknowledgement to the GTWRF topic - boolean result = client.publish(subjectGTWRFtoMQTT, datacallback);// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also - if (result){ - trc(F("MQTTtoRF ack pub.")); - trc(data); - } - } - + pub(subjectGTWRFtoMQTT, datacallback);// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also + } } #endif + +#ifdef jsonPublishing + void MQTTtoRF(char * topicOri, JsonObject& RFdata) { // json object decoding + + String topic = topicOri; + + if (topic == subjectMQTTtoRF) { + trc(F("MQTTtoRF json data analysis")); + unsigned long data = RFdata["value"]; + if (data != 0) { + trc(F("MQTTtoRF data ok")); + int valuePRT = RFdata["protocol"]; + int valuePLSL = RFdata["delay"]; + int valueBITS = RFdata["length"]; + if ((valuePRT == 0) && (valuePLSL == 0) && (valueBITS == 0)){ + trc(F("MQTTtoRF dflt")); + mySwitch.setProtocol(1,350); + mySwitch.send(data, 24); + // Acknowledgement to the GTWRF topic + pub(subjectGTWRFtoMQTT, RFdata); + } else if ((valuePRT != 0) || (valuePLSL != 0)|| (valueBITS != 0)){ + trc(F("MQTTtoRF usr par.")); + if (valuePRT == 0) valuePRT = 1; + if (valuePLSL == 0) valuePLSL = 350; + if (valueBITS == 0) valueBITS = 24; + trc(valuePRT); + trc(valuePLSL); + trc(valueBITS); + mySwitch.setProtocol(valuePRT,valuePLSL); + mySwitch.send(data, valueBITS); + // Acknowledgement to the GTWRF topic + pub(subjectGTWRFtoMQTT, RFdata);// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also + } + }else{ + trc(F("MQTTtoRF Fail reading from json")); + } + } + } +#endif +#endif diff --git a/ZgatewayRF2.ino b/ZgatewayRF2.ino index cf1aba09..52206568 100644 --- a/ZgatewayRF2.ino +++ b/ZgatewayRF2.ino @@ -62,31 +62,29 @@ void setupRF2(){ digitalWrite(RF_EMITTER_PIN, LOW); } -boolean RF2toMQTT(){ +void RF2toMQTT(){ if(rf2rd.hasNewData){ + trc(F("Creating RF2 buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& RF2data = jsonBuffer.createObject(); + + rf2rd.hasNewData = false; - rf2rd.hasNewData=false; trc(F("Rcv. RF2")); - String MQTTAddress; - String MQTTperiod; - String MQTTunit; - String MQTTgroupBit; - String MQTTswitchType; - - MQTTAddress = String(rf2rd.address); - MQTTperiod = String(rf2rd.period); - MQTTunit = String(rf2rd.unit); - MQTTgroupBit = String(rf2rd.groupBit); - MQTTswitchType = String(rf2rd.switchType); - String MQTTRF2string; - MQTTRF2string = subjectRF2toMQTT+String("/")+RF2codeKey+MQTTAddress+String("/")+RF2unitKey+MQTTunit+String("/")+RF2groupKey+MQTTgroupBit+String("/")+RF2periodKey+MQTTperiod; - trc(F("Adv data RF2toMQTT")); - client.publish((char *)MQTTRF2string.c_str(),(char *)MQTTswitchType.c_str()); - return true; + RF2data.set("unit", (int)rf2rd.unit); + RF2data.set("groupBit", (int)rf2rd.groupBit); + RF2data.set("period", (int)rf2rd.period); + RF2data.set("address", (unsigned long)rf2rd.address); + RF2data.set("switchType", (int)rf2rd.switchType); + trc(F("LED MNG")); + digitalWrite(led_receive, LOW); + timer_led_receive = millis(); + + trc(F("Adv data RF2toMQTT")); + pub(subjectRF2toMQTT,RF2data); } - return false; } void rf2Callback(unsigned int period, unsigned long address, unsigned long groupBit, unsigned long unit, unsigned long switchType) { @@ -100,116 +98,177 @@ void rf2Callback(unsigned int period, unsigned long address, unsigned long group } -void MQTTtoRF2(char * topicOri, char * datacallback) { - - // RF DATA ANALYSIS - //We look into the subject to see if a special RF protocol is defined - String topic = topicOri; - bool boolSWITCHTYPE; - boolSWITCHTYPE = to_bool(datacallback); - bool isDimCommand = false; +#ifdef simplePublishing + void MQTTtoRF2(char * topicOri, char * datacallback) { - long valueCODE = 0; - int valueUNIT = -1; - int valuePERIOD = 0; - int valueGROUP = 0; - int valueDIM = -1; - - int pos = topic.lastIndexOf(RF2codeKey); - if (pos != -1){ - pos = pos + +strlen(RF2codeKey); - valueCODE = (topic.substring(pos,pos + 8)).toInt(); - trc(F("RF2 code:")); - trc(valueCODE); - } - int pos2 = topic.lastIndexOf(RF2periodKey); - if (pos2 != -1) { - pos2 = pos2 + strlen(RF2periodKey); - valuePERIOD = (topic.substring(pos2,pos2 + 3)).toInt(); - trc(F("RF2 Period:")); - trc(valuePERIOD); - } - int pos3 = topic.lastIndexOf(RF2unitKey); - if (pos3 != -1){ - pos3 = pos3 + strlen(RF2unitKey); - valueUNIT = (topic.substring(pos3, topic.indexOf("/", pos3))).toInt(); - trc(F("Unit:")); - trc(valueUNIT); - } - int pos4 = topic.lastIndexOf(RF2groupKey); - if (pos4 != -1) { - pos4 = pos4 + strlen(RF2groupKey); - valueGROUP = (topic.substring(pos4,pos4 + 1)).toInt(); - trc(F("RF2 Group:")); - trc(valueGROUP); - } - int pos5 = topic.lastIndexOf(RF2dimKey); - if (pos5 != -1) { - isDimCommand = true; - valueDIM = atoi(datacallback); - trc(F("RF2 Dim:")); - trc(valueDIM); - } - - if ((topic == subjectMQTTtoRF2) || (valueCODE != 0) || (valueUNIT != -1)|| (valuePERIOD != 0)){ - trc(F("MQTTtoRF2")); - if (valueCODE == 0) valueCODE = 8233378; - if (valueUNIT == -1) valueUNIT = 0; - if (valuePERIOD == 0) valuePERIOD = 272; - trc(valueCODE); - trc(valueUNIT); - trc(valuePERIOD); - trc(valueGROUP); - trc(boolSWITCHTYPE); - trc(valueDIM); - NewRemoteReceiver::disable(); - trc(F("Creating transmitter")); - NewRemoteTransmitter transmitter(valueCODE, RF_EMITTER_PIN, valuePERIOD); - trc(F("Sending data")); - if (valueGROUP) { - if (isDimCommand) { - transmitter.sendGroupDim(valueDIM); + // RF DATA ANALYSIS + //We look into the subject to see if a special RF protocol is defined + String topic = topicOri; + bool boolSWITCHTYPE; + boolSWITCHTYPE = to_bool(datacallback); + bool isDimCommand = false; + + long valueCODE = 0; + int valueUNIT = -1; + int valuePERIOD = 0; + int valueGROUP = 0; + int valueDIM = -1; + + int pos = topic.lastIndexOf(RF2codeKey); + if (pos != -1){ + pos = pos + +strlen(RF2codeKey); + valueCODE = (topic.substring(pos,pos + 8)).toInt(); + trc(F("RF2 code:")); + trc(valueCODE); + } + int pos2 = topic.lastIndexOf(RF2periodKey); + if (pos2 != -1) { + pos2 = pos2 + strlen(RF2periodKey); + valuePERIOD = (topic.substring(pos2,pos2 + 3)).toInt(); + trc(F("RF2 Period:")); + trc(valuePERIOD); + } + int pos3 = topic.lastIndexOf(RF2unitKey); + if (pos3 != -1){ + pos3 = pos3 + strlen(RF2unitKey); + valueUNIT = (topic.substring(pos3, topic.indexOf("/", pos3))).toInt(); + trc(F("Unit:")); + trc(valueUNIT); + } + int pos4 = topic.lastIndexOf(RF2groupKey); + if (pos4 != -1) { + pos4 = pos4 + strlen(RF2groupKey); + valueGROUP = (topic.substring(pos4,pos4 + 1)).toInt(); + trc(F("RF2 Group:")); + trc(valueGROUP); + } + int pos5 = topic.lastIndexOf(RF2dimKey); + if (pos5 != -1) { + isDimCommand = true; + valueDIM = atoi(datacallback); + trc(F("RF2 Dim:")); + trc(valueDIM); + } + + if ((topic == subjectMQTTtoRF2) || (valueCODE != 0) || (valueUNIT != -1)|| (valuePERIOD != 0)){ + trc(F("MQTTtoRF2")); + if (valueCODE == 0) valueCODE = 8233378; + if (valueUNIT == -1) valueUNIT = 0; + if (valuePERIOD == 0) valuePERIOD = 272; + trc(valueCODE); + trc(valueUNIT); + trc(valuePERIOD); + trc(valueGROUP); + trc(boolSWITCHTYPE); + trc(valueDIM); + NewRemoteReceiver::disable(); + trc(F("Creating transmitter")); + NewRemoteTransmitter transmitter(valueCODE, RF_EMITTER_PIN, valuePERIOD); + trc(F("Sending data")); + if (valueGROUP) { + if (isDimCommand) { + transmitter.sendGroupDim(valueDIM); + } + else { + transmitter.sendGroup(boolSWITCHTYPE); + } } else { - transmitter.sendGroup(boolSWITCHTYPE); + if (isDimCommand) { + transmitter.sendDim(valueUNIT, valueDIM); + } + else { + transmitter.sendUnit(valueUNIT, boolSWITCHTYPE); + } } - } - else { + trc(F("Data sent")); + NewRemoteReceiver::enable(); + + // Publish state change back to MQTT + String MQTTAddress; + String MQTTperiod; + String MQTTunit; + String MQTTgroupBit; + String MQTTswitchType; + String MQTTdimLevel; + + MQTTAddress = String(valueCODE); + MQTTperiod = String(valuePERIOD); + MQTTunit = String(valueUNIT); + MQTTgroupBit = String(rf2rd.groupBit); + MQTTswitchType = String(boolSWITCHTYPE); + MQTTdimLevel = String(valueDIM); + String MQTTRF2string; + trc(F("Adv data MQTTtoRF2 push state via RF2toMQTT")); if (isDimCommand) { - transmitter.sendDim(valueUNIT, valueDIM); + MQTTRF2string = subjectRF2toMQTT+String("/")+RF2codeKey+MQTTAddress+String("/")+RF2unitKey+MQTTunit+String("/")+RF2groupKey+MQTTgroupBit+String("/")+RF2dimKey+String("/")+RF2periodKey+MQTTperiod; + pub(MQTTRF2string,MQTTdimLevel); } - else { - transmitter.sendUnit(valueUNIT, boolSWITCHTYPE); + else { + MQTTRF2string = subjectRF2toMQTT+String("/")+RF2codeKey+MQTTAddress+String("/")+RF2unitKey+MQTTunit+String("/")+RF2groupKey+MQTTgroupBit+String("/")+RF2periodKey+MQTTperiod; + pub(MQTTRF2string,MQTTswitchType); } } - trc(F("Data sent")); - NewRemoteReceiver::enable(); - - // Publish state change back to MQTT - String MQTTAddress; - String MQTTperiod; - String MQTTunit; - String MQTTgroupBit; - String MQTTswitchType; - String MQTTdimLevel; - - MQTTAddress = String(valueCODE); - MQTTperiod = String(valuePERIOD); - MQTTunit = String(valueUNIT); - MQTTgroupBit = String(rf2rd.groupBit); - MQTTswitchType = String(boolSWITCHTYPE); - MQTTdimLevel = String(valueDIM); - String MQTTRF2string; - trc(F("Adv data MQTTtoRF2 push state via RF2toMQTT")); - if (isDimCommand) { - MQTTRF2string = subjectRF2toMQTT+String("/")+RF2codeKey+MQTTAddress+String("/")+RF2unitKey+MQTTunit+String("/")+RF2groupKey+MQTTgroupBit+String("/")+RF2dimKey+String("/")+RF2periodKey+MQTTperiod; - client.publish((char *)MQTTRF2string.c_str(),(char *)MQTTdimLevel.c_str()); - } - else { - MQTTRF2string = subjectRF2toMQTT+String("/")+RF2codeKey+MQTTAddress+String("/")+RF2unitKey+MQTTunit+String("/")+RF2groupKey+MQTTgroupBit+String("/")+RF2periodKey+MQTTperiod; - client.publish((char *)MQTTRF2string.c_str(),(char *)MQTTswitchType.c_str()); - } } -} - +#endif + +#ifdef jsonPublishing + void MQTTtoRF2(char * topicOri, JsonObject& RF2data) { // json object decoding + + String topic = topicOri; + + if (topic == subjectMQTTtoRF2) { + trc(F("MQTTtoRF2 json data analysis")); + int boolSWITCHTYPE = RF2data["switchType"] | 99; + if (boolSWITCHTYPE != 99) { + trc(F("MQTTtoRF2 switch type ok")); + bool isDimCommand = false; + unsigned long valueCODE = RF2data["adress"]; + int valueUNIT = RF2data["unit"] | -1; + int valuePERIOD = RF2data["period"]; + int valueGROUP = RF2data["groupBit"]; + int valueDIM = RF2data["dim"] | -1; + if ((valueCODE != 0) || (valueUNIT != -1)|| (valuePERIOD != 0)){ + trc(F("MQTTtoRF2")); + if (valueCODE == 0) valueCODE = 8233378; + if (valueUNIT == -1) valueUNIT = 0; + if (valuePERIOD == 0) valuePERIOD = 272; + trc(valueCODE); + trc(valueUNIT); + trc(valuePERIOD); + trc(valueGROUP); + trc(boolSWITCHTYPE); + trc(valueDIM); + NewRemoteReceiver::disable(); + trc(F("Creating transmitter")); + NewRemoteTransmitter transmitter(valueCODE, RF_EMITTER_PIN, valuePERIOD); + trc(F("Sending data")); + if (valueGROUP) { + if (isDimCommand) { + transmitter.sendGroupDim(valueDIM); + } + else { + transmitter.sendGroup(boolSWITCHTYPE); + } + } + else { + if (isDimCommand) { + transmitter.sendDim(valueUNIT, valueDIM); + } + else { + transmitter.sendUnit(valueUNIT, boolSWITCHTYPE); + } + } + trc(F("Data sent")); + NewRemoteReceiver::enable(); + + // Publish state change back to MQTT + pub(subjectGTWRF2toMQTT,RF2data); + } + }else{ + trc(F("MQTTto2G Fail reading from json")); + } + } + } +#endif #endif diff --git a/ZgatewayRF315.ino b/ZgatewayRF315.ino index 9c917bc5..645e7cbb 100644 --- a/ZgatewayRF315.ino +++ b/ZgatewayRF315.ino @@ -45,100 +45,128 @@ void setupRF315(){ } boolean RF315toMQTT(){ - if (mySwitch315.available()){ + trc(F("Creating RF315 buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& RF315data = jsonBuffer.createObject(); trc(F("Rcv. RF315")); #ifdef ESP32 String taskMessage = "RF Task running on core "; taskMessage = taskMessage + xPortGetCoreID(); trc(taskMessage); #endif - unsigned long MQTTvalue = 0; - String MQTTprotocol; - String MQTTbits; - String MQTTlength; - MQTTvalue = mySwitch315.getReceivedValue(); - MQTTprotocol = String(mySwitch315.getReceivedProtocol()); - MQTTbits = String(mySwitch315.getReceivedBitlength()); - MQTTlength = String(mySwitch315.getReceivedDelay()); + RF315data.set("value", (unsigned long)mySwitch315.getReceivedValue()); + RF315data.set("protocol",(int)mySwitch315.getReceivedProtocol()); + RF315data.set("length", (int)mySwitch315.getReceivedBitlength()); + RF315data.set("delay", (int)mySwitch315.getReceivedDelay()); mySwitch315.resetAvailable(); + + trc(F("LED MNG")); + digitalWrite(led_receive, LOW); + timer_led_receive = millis(); + + unsigned long MQTTvalue = RF315data.get("value"); if (!isAduplicate(MQTTvalue) && MQTTvalue!=0) {// conditions to avoid duplications of RF -->MQTT - trc(F("Adv data RF315toMQTT")); - client.publish(subjectRF315toMQTTprotocol,(char *)MQTTprotocol.c_str()); - client.publish(subjectRF315toMQTTbits,(char *)MQTTbits.c_str()); - client.publish(subjectRF315toMQTTlength,(char *)MQTTlength.c_str()); - trc(F("Sending RF315toMQTT")); - String value = String(MQTTvalue); - trc(value); - boolean result = client.publish(subjectRF315toMQTT,(char *)value.c_str()); + trc(F("Adv data RF315toMQTT")); + pub(subjectRF315toMQTT,RF315data); if (repeatRF315wMQTT){ trc(F("Publish RF315 for repeat")); - client.publish(subjectMQTTtoRF315,(char *)value.c_str()); + pub(subjectMQTTtoRF315,RF315data); } - return result; - } - } - return false; -} - -void MQTTtoRF315(char * topicOri, char * datacallback) { - - unsigned long data = strtoul(datacallback, NULL, 10); // we will not be able to pass values > 4294967295 - - // RF315 DATA ANALYSIS - //We look into the subject to see if a special RF protocol is defined - String topic = topicOri; - int valuePRT = 0; - int valuePLSL = 0; - int valueBITS = 0; - int pos = topic.lastIndexOf(RF315protocolKey); - if (pos != -1){ - pos = pos + +strlen(RF315protocolKey); - valuePRT = (topic.substring(pos,pos + 1)).toInt(); - trc(F("RF315 Protocol:")); - trc(valuePRT); - } - //We look into the subject to see if a special RF pulselength is defined - int pos2 = topic.lastIndexOf(RF315pulselengthKey); - if (pos2 != -1) { - pos2 = pos2 + strlen(RF315pulselengthKey); - valuePLSL = (topic.substring(pos2,pos2 + 3)).toInt(); - trc(F("RF315 Pulse Lgth:")); - trc(valuePLSL); - } - int pos3 = topic.lastIndexOf(RF315bitsKey); - if (pos3 != -1){ - pos3 = pos3 + strlen(RF315bitsKey); - valueBITS = (topic.substring(pos3,pos3 + 2)).toInt(); - trc(F("Bits nb:")); - trc(valueBITS); - } - - if ((topic == subjectMQTTtoRF315) && (valuePRT == 0) && (valuePLSL == 0) && (valueBITS == 0)){ - trc(F("MQTTtoRF315 dflt")); - mySwitch315.setProtocol(1,350); - mySwitch315.send(data, 24); - // Acknowledgement to the GTWRF topic - boolean result = client.publish(subjectGTWRF315toMQTT, datacallback); - if (result)trc(F("Ack pub.")); - - } else if ((valuePRT != 0) || (valuePLSL != 0)|| (valueBITS != 0)){ - trc(F("MQTTtoRF315 usr par.")); - if (valuePRT == 0) valuePRT = 1; - if (valuePLSL == 0) valuePLSL = 350; - if (valueBITS == 0) valueBITS = 24; - trc(valuePRT); - trc(valuePLSL); - trc(valueBITS); - mySwitch315.setProtocol(valuePRT,valuePLSL); - mySwitch315.send(data, valueBITS); - // Acknowledgement to the GTWRF topic - boolean result = client.publish(subjectGTWRF315toMQTT, datacallback);// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also - if (result){ - trc(F("MQTTtoRF315 ack pub.")); - trc(data); } } - } + +#ifdef simplePublishing + void MQTTtoRF315(char * topicOri, char * datacallback) { + + unsigned long data = strtoul(datacallback, NULL, 10); // we will not be able to pass values > 4294967295 + + // RF315 DATA ANALYSIS + //We look into the subject to see if a special RF protocol is defined + String topic = topicOri; + int valuePRT = 0; + int valuePLSL = 0; + int valueBITS = 0; + int pos = topic.lastIndexOf(RF315protocolKey); + if (pos != -1){ + pos = pos + +strlen(RF315protocolKey); + valuePRT = (topic.substring(pos,pos + 1)).toInt(); + trc(F("RF315 Protocol:")); + trc(valuePRT); + } + //We look into the subject to see if a special RF pulselength is defined + int pos2 = topic.lastIndexOf(RF315pulselengthKey); + if (pos2 != -1) { + pos2 = pos2 + strlen(RF315pulselengthKey); + valuePLSL = (topic.substring(pos2,pos2 + 3)).toInt(); + trc(F("RF315 Pulse Lgth:")); + trc(valuePLSL); + } + int pos3 = topic.lastIndexOf(RF315bitsKey); + if (pos3 != -1){ + pos3 = pos3 + strlen(RF315bitsKey); + valueBITS = (topic.substring(pos3,pos3 + 2)).toInt(); + trc(F("Bits nb:")); + trc(valueBITS); + } + + if ((topic == subjectMQTTtoRF315) && (valuePRT == 0) && (valuePLSL == 0) && (valueBITS == 0)){ + trc(F("MQTTtoRF315 dflt")); + mySwitch315.setProtocol(1,350); + mySwitch315.send(data, 24); + // Acknowledgement to the GTWRF topic + pub(subjectGTWRF315toMQTT, datacallback); + } else if ((valuePRT != 0) || (valuePLSL != 0)|| (valueBITS != 0)){ + trc(F("MQTTtoRF315 usr par.")); + if (valuePRT == 0) valuePRT = 1; + if (valuePLSL == 0) valuePLSL = 350; + if (valueBITS == 0) valueBITS = 24; + trc(valuePRT); + trc(valuePLSL); + trc(valueBITS); + mySwitch315.setProtocol(valuePRT,valuePLSL); + mySwitch315.send(data, valueBITS); + // Acknowledgement to the GTWRF topic + pub(subjectGTWRF315toMQTT, datacallback);// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also + } + } +#endif + +#ifdef jsonPublishing + void MQTTtoRF315(char * topicOri, JsonObject& RF315data) { // json object decoding + + String topic = topicOri; + + if (topic == subjectMQTTtoRF315) { + trc(F("MQTTtoRF315 json data analysis")); + unsigned long data = RF315data["value"]; + if (data != 0) { + trc(F("MQTTtoRF315 data ok")); + int valuePRT = RF315data["protocol"]; + int valuePLSL = RF315data["delay"]; + int valueBITS = RF315data["length"]; + if ((valuePRT == 0) && (valuePLSL == 0) && (valueBITS == 0)){ + trc(F("MQTTtoRF315 dflt")); + mySwitch315.setProtocol(1,350); + mySwitch315.send(data, 24); + // Acknowledgement to the GTWRF topic + pub(subjectGTWRF315toMQTT, RF315data); + } else if ((valuePRT != 0) || (valuePLSL != 0)|| (valueBITS != 0)){ + trc(F("MQTTtoRF315 usr par.")); + if (valuePRT == 0) valuePRT = 1; + if (valuePLSL == 0) valuePLSL = 350; + if (valueBITS == 0) valueBITS = 24; + trc(valuePRT); + trc(valuePLSL); + trc(valueBITS); + mySwitch315.setProtocol(valuePRT,valuePLSL); + mySwitch315.send(data, valueBITS); + // Acknowledgement to the GTWRF topic + pub(subjectGTWRF315toMQTT, RF315data);// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also + } + } + } + } +#endif #endif diff --git a/ZgatewayRFM69.ino b/ZgatewayRFM69.ino index 80272e29..0b31d0ca 100644 --- a/ZgatewayRFM69.ino +++ b/ZgatewayRFM69.ino @@ -138,23 +138,13 @@ void setupRFM69(void) { } } -#ifdef subjectRFM69toMQTTrssi -void publishRSSI(int16_t rssi) { - // Send the value of the rssi to MQTT - char buff[sizeof(subjectRFM69toMQTTrssi)+4]; - sprintf(buff, "%s/%d", subjectRFM69toMQTTrssi, radio.SENDERID); - char buff_rssi[5]; - sprintf(buff_rssi, "%d", radio.RSSI); - boolean result = client.publish(buff, buff_rssi); -} -#else -#define publishRSSI(input) -#endif - boolean RFM69toMQTT(void) { //check if something was received (could be an interrupt from the radio) if (radio.receiveDone()) { + trc(F("Creating RFM69 buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& RFM69data = jsonBuffer.createObject(); uint8_t data[RF69_MAX_DATA_LEN+1]; // For the null character uint8_t SENDERID = radio.SENDERID; uint8_t DATALEN = radio.DATALEN; @@ -177,9 +167,10 @@ boolean RFM69toMQTT(void) { char buff[sizeof(subjectRFM69toMQTT)+4]; sprintf(buff, "%s/%d", subjectRFM69toMQTT, SENDERID); - client.publish(buff,(char *)data); - - publishRSSI(RSSI); + RFM69data.set("data", (char *)data); + RFM69data.set("rssi", (int)radio.RSSI); + RFM69data.set("senderid", (int)radio.SENDERID); + pub(buff,RFM69data); return true; @@ -188,63 +179,95 @@ boolean RFM69toMQTT(void) { } } -boolean MQTTtoRFM69(char * topicOri, char * datacallback) { - int loops; - uint32_t startMillis; - static uint32_t deltaMillis = 0; - - bool good_topic = true; - for (int i=0; i> 8) & 0xFF) ; - hex_valueMiniPLSL[1] = (int)(valueMiniPLSL & 0xFF) ; - - byte hex_valueMaxiPLSL[2]; - hex_valueMaxiPLSL[0] = (int)((valueMaxiPLSL >> 8) & 0xFF) ; - hex_valueMaxiPLSL[1] = (int)(valueMaxiPLSL & 0xFF) ; - - byte hex_valueSYNC[2]; - hex_valueSYNC[0] = (int)((valueSYNC >> 8) & 0xFF) ; - hex_valueSYNC[1] = (int)(valueSYNC & 0xFF) ; - - unsigned long data = strtoul(datacallback, NULL, 10); // we will not be able to pass values > 4294967295 - byte hex_data[3]; - hex_data[0] = (unsigned long)((data >> 16) & 0xFF) ; - hex_data[1] = (unsigned long)((data >> 8) & 0xFF) ; - hex_data[2] = (unsigned long)(data & 0xFF) ; - - byte message_b[RF_MESSAGE_SIZE]; - - memcpy(message_b, hex_valueSYNC, 2); - memcpy(message_b + 2, hex_valueMiniPLSL, 2); - memcpy(message_b + 4, hex_valueMaxiPLSL, 2); - memcpy(message_b + 6, hex_data, 3); - - _rfbSend(message_b, valueRPT); - // Acknowledgement to the GTWRF topic - boolean result = client.publish(subjectGTWSRFBtoMQTT, datacallback);// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also - if (result) trc(F("MQTTtoSRFB ack pub.")); - } - if (topic == subjectMQTTtoSRFBRaw){ - - int pos = topic.lastIndexOf(SRFBRptKey); - if (pos != -1){ - pos = pos + +strlen(SRFBRptKey); - valueRPT = (topic.substring(pos,pos + 1)).toInt(); - trc(F("SRFB Repeat:")); - trc(valueRPT); - } - if (valueRPT == 0) valueRPT = 1; - - byte message_b[RF_MESSAGE_SIZE]; - _rfbToArray(datacallback,message_b); - _rfbSend(message_b, valueRPT); - // Acknowledgement to the GTWRF topic - boolean result = client.publish(subjectGTWSRFBtoMQTT, datacallback);// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also - if (result) trc(F("MQTTtoSRFBRaw ack pub.")); - } -} - void _rfbSend(byte * message) { Serial.println(); Serial.write(RF_CODE_START); @@ -201,24 +101,37 @@ void _rfbDecode() { if (action == RF_CODE_RFIN) { _rfbToChar(&_uartbuf[1], buffer); - client.publish(subjectSRFBtoMQTTRaw,buffer); + + trc(F("Creating SRFB buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& SRFBdata = jsonBuffer.createObject(); + SRFBdata.set("raw", (char *)buffer); char val[8]= {0}; - extract_char(buffer, val, 12 ,8, false,true); - client.publish(subjectSRFBtoMQTT,val); + extract_char(buffer, val, 12 ,8, false,true); + SRFBdata.set("value", (char *)val); char val_Tsyn[4]= {0}; - extract_char(buffer, val_Tsyn, 0 ,4, false, true); - client.publish(subjectSRFBtoMQTTTsyn,val_Tsyn); - + extract_char(buffer, val_Tsyn , 0 ,4, false, true); + SRFBdata.set("delay", (char *)val_Tsyn); + char val_Thigh[4]= {0}; - extract_char(buffer, val_Thigh, 4 ,4, false, true); - client.publish(subjectSRFBtoMQTTThigh,val_Thigh); + extract_char(buffer, val_Thigh , 4 ,4, false, true); + SRFBdata.set("val_Thigh", (char *)val_Thigh); char val_Tlow[4]= {0}; - extract_char(buffer, val_Tlow, 8 ,4, false, true); - client.publish(subjectSRFBtoMQTTTlow,val_Tlow); + extract_char(buffer,val_Tlow , 8 ,4, false, true); + SRFBdata.set("val_Tlow", (char *)val_Tlow); + unsigned long MQTTvalue = SRFBdata.get("value"); + if (!isAduplicate(MQTTvalue) && MQTTvalue!=0) {// conditions to avoid duplications of RF -->MQTT + trc(F("Adv data SRFBtoMQTT")); + pub(subjectSRFBtoMQTT,SRFBdata); + if (repeatSRFBwMQTT){ + trc(F("Publish SRFB for repeat")); + pub(subjectMQTTtoSRFB,SRFBdata); + } + } _rfbAck(); } } @@ -256,4 +169,165 @@ bool _rfbToChar(byte * in, char * out) { return true; } +#ifdef simplePublishing + void MQTTtoSRFB(char * topicOri, char * datacallback) { + + // RF DATA ANALYSIS + String topic = topicOri; + int valueRPT = 0; + + if (topic == subjectMQTTtoSRFB){ + + int valueMiniPLSL = 0; + int valueMaxiPLSL = 0; + int valueSYNC = 0; + + int pos = topic.lastIndexOf(SRFBRptKey); + if (pos != -1){ + pos = pos + +strlen(SRFBRptKey); + valueRPT = (topic.substring(pos,pos + 1)).toInt(); + trc(F("SRFB Repeat:")); + trc(valueRPT); + } + + int pos2 = topic.lastIndexOf(SRFBminipulselengthKey); + if (pos2 != -1) { + pos2 = pos2 + strlen(SRFBminipulselengthKey); + valueMiniPLSL = (topic.substring(pos2,pos2 + 3)).toInt(); + trc(F("RF Mini Pulse Lgth:")); + trc(valueMiniPLSL); + } + + int pos3 = topic.lastIndexOf(SRFBmaxipulselengthKey); + if (pos3 != -1){ + pos3 = pos3 + strlen(SRFBmaxipulselengthKey); + valueMaxiPLSL = (topic.substring(pos3,pos3 + 2)).toInt(); + trc(F("RF Maxi Pulse Lgth:")); + trc(valueMaxiPLSL); + } + + int pos4 = topic.lastIndexOf(SRFBsyncKey); + if (pos4 != -1){ + pos4 = pos4 + strlen(SRFBsyncKey); + valueSYNC = (topic.substring(pos4,pos4 + 2)).toInt(); + trc(F("RF sync:")); + trc(valueSYNC); + } + + trc(F("MQTTtoSRFB prts")); + if (valueRPT == 0) valueRPT = 1; + if (valueMiniPLSL == 0) valueMiniPLSL = 320; + if (valueMaxiPLSL == 0) valueMaxiPLSL = 900; + if (valueSYNC == 0) valueSYNC = 9500; + + byte hex_valueMiniPLSL[2]; + hex_valueMiniPLSL[0] = (int)((valueMiniPLSL >> 8) & 0xFF) ; + hex_valueMiniPLSL[1] = (int)(valueMiniPLSL & 0xFF) ; + + byte hex_valueMaxiPLSL[2]; + hex_valueMaxiPLSL[0] = (int)((valueMaxiPLSL >> 8) & 0xFF) ; + hex_valueMaxiPLSL[1] = (int)(valueMaxiPLSL & 0xFF) ; + + byte hex_valueSYNC[2]; + hex_valueSYNC[0] = (int)((valueSYNC >> 8) & 0xFF) ; + hex_valueSYNC[1] = (int)(valueSYNC & 0xFF) ; + + unsigned long data = strtoul(datacallback, NULL, 10); // we will not be able to pass values > 4294967295 + byte hex_data[3]; + hex_data[0] = (unsigned long)((data >> 16) & 0xFF) ; + hex_data[1] = (unsigned long)((data >> 8) & 0xFF) ; + hex_data[2] = (unsigned long)(data & 0xFF) ; + + byte message_b[RF_MESSAGE_SIZE]; + + memcpy(message_b, hex_valueSYNC, 2); + memcpy(message_b + 2, hex_valueMiniPLSL, 2); + memcpy(message_b + 4, hex_valueMaxiPLSL, 2); + memcpy(message_b + 6, hex_data, 3); + + _rfbSend(message_b, valueRPT); + // Acknowledgement to the GTWRF topic + pub(subjectGTWSRFBtoMQTT, datacallback);// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also + } + if (topic == subjectMQTTtoSRFBRaw){ + + int pos = topic.lastIndexOf(SRFBRptKey); + if (pos != -1){ + pos = pos + +strlen(SRFBRptKey); + valueRPT = (topic.substring(pos,pos + 1)).toInt(); + trc(F("SRFB Repeat:")); + trc(valueRPT); + } + if (valueRPT == 0) valueRPT = 1; + + byte message_b[RF_MESSAGE_SIZE]; + _rfbToArray(datacallback,message_b); + _rfbSend(message_b, valueRPT); + // Acknowledgement to the GTWRF topic + pub(subjectGTWSRFBtoMQTT, datacallback);// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also + } + } +#endif +#ifdef jsonPublishing + void MQTTtoSRFB(char * topicOri, JsonObject& SRFBdata) { + + // RF DATA ANALYSIS + String topic = topicOri; + const char * raw = SRFBdata["raw"]; + int valueRPT = SRFBdata["repeat"]|1; + if (topic == subjectMQTTtoSRFB){ + trc(F("MQTTtoSRFB json data analysis")); + if (raw){ // send raw in priority when defined in the json + trc(F("MQTTtoSRFB raw ok")); + byte message_b[RF_MESSAGE_SIZE]; + _rfbToArray(raw,message_b); + _rfbSend(message_b, valueRPT); + }else{ + unsigned long data = SRFBdata["value"]; + if (data != 0) { + trc(F("MQTTtoSRFB data ok")); + int valueMiniPLSL = SRFBdata["val_Tlow"]; + int valueMaxiPLSL =SRFBdata["val_Thigh"]; + int valueSYNC = SRFBdata["delay"]; + + if (valueRPT == 0) valueRPT = 1; + if (valueMiniPLSL == 0) valueMiniPLSL = 320; + if (valueMaxiPLSL == 0) valueMaxiPLSL = 900; + if (valueSYNC == 0) valueSYNC = 9500; + + byte hex_valueMiniPLSL[2]; + hex_valueMiniPLSL[0] = (int)((valueMiniPLSL >> 8) & 0xFF) ; + hex_valueMiniPLSL[1] = (int)(valueMiniPLSL & 0xFF) ; + + byte hex_valueMaxiPLSL[2]; + hex_valueMaxiPLSL[0] = (int)((valueMaxiPLSL >> 8) & 0xFF) ; + hex_valueMaxiPLSL[1] = (int)(valueMaxiPLSL & 0xFF) ; + + byte hex_valueSYNC[2]; + hex_valueSYNC[0] = (int)((valueSYNC >> 8) & 0xFF) ; + hex_valueSYNC[1] = (int)(valueSYNC & 0xFF) ; + + byte hex_data[3]; + hex_data[0] = (unsigned long)((data >> 16) & 0xFF) ; + hex_data[1] = (unsigned long)((data >> 8) & 0xFF) ; + hex_data[2] = (unsigned long)(data & 0xFF) ; + + byte message_b[RF_MESSAGE_SIZE]; + + memcpy(message_b, hex_valueSYNC, 2); + memcpy(message_b + 2, hex_valueMiniPLSL, 2); + memcpy(message_b + 4, hex_valueMaxiPLSL, 2); + memcpy(message_b + 6, hex_data, 3); + + trc(F("MQTTtoSRFB send")); + _rfbSend(message_b, valueRPT); + // Acknowledgement to the GTWRF topic + pub(subjectGTWSRFBtoMQTT, SRFBdata);// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also + }else{ + trc(F("MQTTtoSRFB error decoding value")); + } + } + } + } +#endif #endif diff --git a/ZsensorADC.ino b/ZsensorADC.ino index dd127dbc..6ec80586 100644 --- a/ZsensorADC.ino +++ b/ZsensorADC.ino @@ -47,13 +47,14 @@ void MeasureADC(){ trc(F("Failed to read from ADC !")); }else{ if(val >= persistedadc + ThresholdReadingADC || val <= persistedadc - ThresholdReadingADC){ - trc(F("Sending analog value to MQTT")); - trc(val); - client.publish(ADC,String(val).c_str()); + trc(F("Creating ADC buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& ADCdata = jsonBuffer.createObject(); + ADCdata.set("adc", (int)val); + pub(ADC,ADCdata); persistedadc = val; } } } } #endif - diff --git a/ZsensorBH1750.ino b/ZsensorBH1750.ino index 2531b32a..522c25a1 100644 --- a/ZsensorBH1750.ino +++ b/ZsensorBH1750.ino @@ -54,6 +54,10 @@ void setupZsensorBH1750() void MeasureLightIntensity() { if (millis() > (timebh1750 + TimeBetweenReadingBH1750)) {//retriving value of Lux, FtCd and Wattsm2 from BH1750 + trc(F("Creating BH1750 buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& BH1750data = jsonBuffer.createObject(); + timebh1750 = millis(); unsigned int i=0; static float persistedll; @@ -94,31 +98,25 @@ void MeasureLightIntensity() // Generate Lux if(Lux != persistedll || bh1750_always){ - trc(F("Sending Lux to MQTT")); - trc(Lux); - client.publish(LUX,String(Lux).c_str()); + BH1750data.set("lux", (unsigned int)Lux); }else{ trc(F("Same lux don't send it")); } // Generate FtCd if(FtCd != persistedlf || bh1750_always){ - trc(F("Sending FtCd to MQTT")); - trc(FtCd); - client.publish(FTCD,String(FtCd).c_str()); + BH1750data.set("ftCd", (unsigned int)FtCd); }else{ trc(F("Same ftcd don't send it")); } // Generate Watts/m2 if(Wattsm2 != persistedlw || bh1750_always){ - trc(F("Sending Wattsm2 to MQTT")); - trc(Wattsm2); - client.publish(WATTSM2,String(Wattsm2).c_str()); + BH1750data.set("wattsm2", (unsigned int)Wattsm2); }else{ trc(F("Same wattsm2 don't send it")); - } - + } + if(BH1750data.size()>0) pub(subjectBH1750toMQTT,BH1750data); } persistedll = Lux; persistedlf = FtCd; diff --git a/ZsensorBME280.ino b/ZsensorBME280.ino index 47f2e235..dc836be8 100644 --- a/ZsensorBME280.ino +++ b/ZsensorBME280.ino @@ -108,6 +108,7 @@ void MeasureTempHumAndPressure() { if (millis() > (timebme280 + TimeBetweenReadingbme280)) { + timebme280 = millis(); static float persisted_bme_tempc; static float persisted_bme_tempf; @@ -127,38 +128,33 @@ void MeasureTempHumAndPressure() if (isnan(BmeTempC) || isnan(BmeTempF) || isnan(BmeHum) || isnan(BmePa) || isnan(BmeAltiM) || isnan(BmeAltiFt)) { trc(F("Failed to read from Weather Sensor BME280!")); }else{ + trc(F("Creating BME280 buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& BME280data = jsonBuffer.createObject(); // Generate Temperature in degrees C if(BmeTempC != persisted_bme_tempc || bme280_always){ - trc(F("Sending Degrees C to MQTT")); - trc(BmeTempC); - client.publish(TEMPBMEC, String(BmeTempC).c_str()); + BME280data.set("tempc", (float)BmeTempC); }else{ trc(F("Same Degrees C don't send it")); } // Generate Temperature in degrees F if(BmeTempF != persisted_bme_tempf || bme280_always){ - trc(F("Sending Degrees F to MQTT")); - trc(BmeTempF); - client.publish(TEMPBMEF,String(BmeTempF).c_str()); + BME280data.set("tempf", (float)BmeTempF); }else{ trc(F("Same Degrees F don't send it")); } // Generate Humidity in percent if(BmeHum != persisted_bme_hum || bme280_always){ - trc(F("Sending Humidity to MQTT")); - trc(BmeHum); - client.publish(HUMBME, String(BmeHum).c_str()); + BME280data.set("hum", (float)BmeHum); }else{ trc(F("Same Humidity don't send it")); } // Generate Pressure in Pa if(BmePa != persisted_bme_pa || bme280_always){ - trc(F("Sending Pressure to MQTT")); - trc(BmePa); - client.publish(PRESSBME, String(BmePa).c_str()); + BME280data.set("pa", (float)BmePa); }else{ trc(F("Same Pressure don't send it")); } @@ -166,21 +162,18 @@ void MeasureTempHumAndPressure() // Generate Altitude in Meter if(BmeAltiM != persisted_bme_altim || bme280_always){ trc(F("Sending Altitude Meter to MQTT")); - trc(BmeAltiM); - client.publish(ALTIBMEM, String(BmeAltiM).c_str()); + BME280data.set("altim", (float)BmeAltiM); }else{ trc(F("Same Altitude Meter don't send it")); } // Generate Altitude in Feet if(BmeAltiFt != persisted_bme_altift || bme280_always){ - trc(F("Sending Altitude Feet to MQTT")); - trc(BmeAltiFt); - client.publish(ALTIBMEFT, String(BmeAltiFt).c_str()); + BME280data.set("altift", (float)BmeAltiFt); }else{ trc(F("Same Altitude Feet don't send it")); } - + if(BME280data.size()>0) pub(BME,BME280data); } persisted_bme_tempc = BmeTempC; persisted_bme_tempf = BmeTempF; diff --git a/ZsensorDHT.ino b/ZsensorDHT.ino index 55d7d3ed..ac1f11b4 100644 --- a/ZsensorDHT.ino +++ b/ZsensorDHT.ino @@ -48,20 +48,20 @@ void MeasureTempAndHum(){ if (isnan(h) || isnan(t)) { trc(F("Failed to read from DHT sensor!")); }else{ + trc(F("Creating DHT buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& DHTdata = jsonBuffer.createObject(); if(h != persistedh || dht_always){ - trc(F("Sending Hum to MQTT")); - trc(h); - client.publish(HUM1,String(h).c_str()); + DHTdata.set("hum", (float)h); }else{ trc(F("Same hum don't send it")); } if(t != persistedt || dht_always){ - trc(F("Sending Temp to MQTT")); - trc(t); - client.publish(TEMP1, String(t).c_str()); + DHTdata.set("temp", (float)t); }else{ trc(F("Same temp don't send it")); } + if(DHTdata.size()>0) pub(DHTTOPIC,DHTdata); } persistedh = h; persistedt = t; diff --git a/ZsensorGPIOInput.ino b/ZsensorGPIOInput.ino index 563fb2a3..db03a0ff 100644 --- a/ZsensorGPIOInput.ino +++ b/ZsensorGPIOInput.ino @@ -1,79 +1,83 @@ -/* - OpenMQTTGateway Addon - ESP8266 or Arduino program for home automation - Act as a wifi or ethernet gateway between your 433mhz/infrared IR signal and a MQTT broker - Send and receiving command by MQTT - - GPIO Input derived from HC SR-501 reading Addon and https://www.arduino.cc/en/Tutorial/Debounce - - This reads a high (open) or low (closed) through a circuit (switch, float sensor, etc.) connected to ground. - - Copyright: (c)Florian ROBERT - - Contributors: - - 1technophile - - QuagmireMan - - This file is part of OpenMQTTGateway. - - OpenMQTTGateway is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - OpenMQTTGateway is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifdef ZsensorGPIOInput - -unsigned long lastDebounceTime = 0; -int InputState = 3; // Set to 3 so that it reads on startup -int lastInputState = 3; - - -void setupGPIOInput() { - pinMode(GPIOInput_PIN, INPUT_PULLUP); // declare GPIOInput pin as input_pullup to prevent floating. Pin will be high when not connected to ground -} - -void MeasureGPIOInput(){ - int reading = digitalRead(GPIOInput_PIN); - - // check to see if you just pressed the button - // (i.e. the input went from LOW to HIGH), and you've waited long enough - // since the last press to ignore any noise: - - // If the switch changed, due to noise or pressing: - if (reading != lastInputState) { - // reset the debouncing timer - lastDebounceTime = millis(); - - } - - if ((millis() - lastDebounceTime) > GPIOInputDebounceDelay) { - // whatever the reading is at, it's been there for longer than the debounce - // delay, so take it as the actual current state: - #if defined(ESP8266) || defined(ESP32) - yield(); - #endif - // if the Input state has changed: - if (reading != InputState) { - InputState = reading; - - if (InputState == HIGH) { - trc(F("GPIO HIGH")); - client.publish(subjectGPIOInputtoMQTT,"HIGH"); - } - if (InputState == LOW) { - trc(F("GPIO LOW")); - client.publish(subjectGPIOInputtoMQTT,"LOW"); - } - } - } - - // save the reading. Next time through the loop, it'll be the lastInputState: - lastInputState = reading; - -} +/* + OpenMQTTGateway Addon - ESP8266 or Arduino program for home automation + Act as a wifi or ethernet gateway between your 433mhz/infrared IR signal and a MQTT broker + Send and receiving command by MQTT + + GPIO Input derived from HC SR-501 reading Addon and https://www.arduino.cc/en/Tutorial/Debounce + + This reads a high (open) or low (closed) through a circuit (switch, float sensor, etc.) connected to ground. + + Copyright: (c)Florian ROBERT + + Contributors: + - 1technophile + - QuagmireMan + + This file is part of OpenMQTTGateway. + + OpenMQTTGateway is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + OpenMQTTGateway is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#ifdef ZsensorGPIOInput + +unsigned long lastDebounceTime = 0; +int InputState = 3; // Set to 3 so that it reads on startup +int lastInputState = 3; + + +void setupGPIOInput() { + pinMode(GPIOInput_PIN, INPUT_PULLUP); // declare GPIOInput pin as input_pullup to prevent floating. Pin will be high when not connected to ground +} + +void MeasureGPIOInput(){ + int reading = digitalRead(GPIOInput_PIN); + + // check to see if you just pressed the button + // (i.e. the input went from LOW to HIGH), and you've waited long enough + // since the last press to ignore any noise: + + // If the switch changed, due to noise or pressing: + if (reading != lastInputState) { + // reset the debouncing timer + lastDebounceTime = millis(); + + } + + if ((millis() - lastDebounceTime) > GPIOInputDebounceDelay) { + // whatever the reading is at, it's been there for longer than the debounce + // delay, so take it as the actual current state: + #if defined(ESP8266) || defined(ESP32) + yield(); + #endif + // if the Input state has changed: + if (reading != InputState) { + InputState = reading; + trc(F("Creating GPIOInput buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& GPIOdata = jsonBuffer.createObject(); + if (InputState == HIGH) { + trc(F("GPIO HIGH")); + pub(subjectGPIOInputtoMQTT,"HIGH"); + GPIOdata.set("gpio", "HIGH"); + } + if (InputState == LOW) { + trc(F("GPIO LOW")); + GPIOdata.set("gpio","LOW"); + } + if(GPIOdata.size()>0) pub(subjectGPIOInputtoMQTT,GPIOdata); + } + } + + // save the reading. Next time through the loop, it'll be the lastInputState: + lastInputState = reading; + +} #endif diff --git a/ZsensorGPIOKeyCode.ino b/ZsensorGPIOKeyCode.ino index 43aa13e0..f8d78d6c 100644 --- a/ZsensorGPIOKeyCode.ino +++ b/ZsensorGPIOKeyCode.ino @@ -25,11 +25,10 @@ */ #ifdef ZsensorGPIOKeyCode +int InputStateGPIOKeyCode = 0x0f; // Set to 3 so that it reads on startup +int lastInputStateGPIOKeyCode = 0x0f; +int lastLatchStateGPIOKeyCode = 0; unsigned long lastDebounceTime = 0; -int InputState = 0x0f; // Set to 3 so that it reads on startup -int lastInputState = 0x0f; -int lastLatchState = 0; - void setupGPIOKeyCode() { pinMode(GPIOKeyCode_LATCH_PIN, INPUT_PULLUP); // @@ -54,8 +53,7 @@ void MeasureGPIOKeyCode(){ yield(); #endif // if the Input state has changed: - if (latch > 0 && lastLatchState != latch) { - + if (latch > 0 && lastLatchStateGPIOKeyCode != latch) { int reading = digitalRead(GPIOKeyCode_D0_PIN) | (digitalRead(GPIOKeyCode_D1_PIN) << 1) | (digitalRead(GPIOKeyCode_D2_PIN) << 2); @@ -63,23 +61,23 @@ void MeasureGPIOKeyCode(){ char hex[3]; - InputState = reading; - sprintf(hex, "%02x", InputState); + InputStateGPIOKeyCode = reading; + sprintf(hex, "%02x", InputStateGPIOKeyCode); hex[2] = 0; Serial.printf("GPIOKeyCode %s\n", hex); client.publish(subjectGPIOKeyCodetoMQTT,hex); - lastLatchState = latch; + lastLatchStateGPIOKeyCode = latch; } - if (latch != lastLatchState) { - lastLatchState = latch; + if (latch != lastLatchStateGPIOKeyCode) { + lastLatchStateGPIOKeyCode = latch; Serial.printf("GPIOKeyCode latch %d\n", latch); if (latch == 0) client.publish(subjectGPIOKeyCodeStatetoMQTT, "done"); } // save the reading. Next time through the loop, it'll be the lastInputState: - lastInputState = InputState; + lastInputStateGPIOKeyCode = InputStateGPIOKeyCode; } } #endif diff --git a/ZsensorHCSR501.ino b/ZsensorHCSR501.ino index 5b16d452..1d92ab4b 100644 --- a/ZsensorHCSR501.ino +++ b/ZsensorHCSR501.ino @@ -34,6 +34,9 @@ void setupHCSR501() { void MeasureHCSR501(){ if (millis() > TimeBeforeStartHCSR501) {//let time to init the PIR sensor + trc(F("Creating HCSR501 buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& HCSR501data = jsonBuffer.createObject(); static int pirState = LOW; int PresenceValue = digitalRead(HCSR501_PIN); #if defined(ESP8266) || defined(ESP32) @@ -41,19 +44,19 @@ void MeasureHCSR501(){ #endif if (PresenceValue == HIGH) { if (pirState == LOW) { - // turned on - client.publish(subjectHCSR501toMQTT,"true"); - trc(F("HC SR501 Motion detected")); + //turned on + HCSR501data.set("hcsr501", "true"); pirState = HIGH; } } else { if (pirState == HIGH){ - // turned off - client.publish(subjectHCSR501toMQTT,"false"); - trc(F("HC SR501 Motion ended")); - pirState = LOW; + // turned off + HCSR501data.set("hcsr501", "false"); + trc(F("HC SR501 Motion ended")); + pirState = LOW; } } + if(HCSR501data.size()>0) pub(subjectHCSR501toMQTT,HCSR501data); } } #endif diff --git a/ZsensorINA226.ino b/ZsensorINA226.ino index f13684ac..10380346 100644 --- a/ZsensorINA226.ino +++ b/ZsensorINA226.ino @@ -51,6 +51,9 @@ void setupINA226() { void MeasureINA226(){ if (millis() > (timeINA226 + TimeBetweenReadingINA226)) {//retriving value of temperature and humidity of the box from DHT every xUL timeINA226 = millis(); + trc(F("Creating INA226 buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& INA226data = jsonBuffer.createObject(); // Topic on which we will send data trc(F("Retrieving electrical data")); // Bus Spannung, read-only, 16Bit, 0...40.96V max., LSB 1.25mV @@ -78,11 +81,10 @@ void MeasureINA226(){ dtostrf(volt,6,3,volt_c); dtostrf(current,6,3,current_c); dtostrf(power,6,3,power_c); - - client.publish(subjectVolttoMQTT,volt_c); - client.publish(subjectCurrenttoMQTT,current_c); - client.publish(subjectPowertoMQTT,power_c); - + INA226data.set("Volt", (char *)volt_c); + INA226data.set("Current", (char *)current_c); + INA226data.set("Power", (char *)power_c); + pub(subjectINA226toMQTT,INA226data); } } diff --git a/ZsensorTSL2561.ino b/ZsensorTSL2561.ino index 219ee1c1..b0030359 100644 --- a/ZsensorTSL2561.ino +++ b/ZsensorTSL2561.ino @@ -90,6 +90,10 @@ void MeasureLightIntensityTSL2561() if (millis() > (timetsl2561 + TimeBetweenReadingtsl2561)) { static uint32_t persisted_lux; timetsl2561 = millis(); + + trc(F("Creating TSL2561 buffer")); + StaticJsonBuffer jsonBuffer; + JsonObject& TSL2561data = jsonBuffer.createObject(); sensors_event_t event; tsl.getEvent(&event); @@ -98,11 +102,12 @@ void MeasureLightIntensityTSL2561() { if (persisted_lux != event.light || tsl2561_always ) { persisted_lux = event.light; - - trc("Sending Light Intensity in Lux to MQTT " + String(event.light) + " lux"); - client.publish(LUX, String(event.light).c_str()); - client.publish(FTCD, String((event.light)/10.764).c_str()); - client.publish(WATTSM2, String((event.light)/683.0).c_str()); + + TSL2561data.set("lux", (float)event.light); + TSL2561data.set("ftcd", (float)(event.light)/10.764); + TSL2561data.set("wattsm2", (float)(event.light)/683.0); + + pub(subjectTSL12561toMQTT,TSL2561data); } else { trc("Same lux value, do not send"); } @@ -112,4 +117,3 @@ void MeasureLightIntensityTSL2561() } } #endif - diff --git a/config_2G.h b/config_2G.h index 1a41632b..a829659d 100644 --- a/config_2G.h +++ b/config_2G.h @@ -29,9 +29,6 @@ #define subjectMQTTto2G Base_Topic Gateway_Name "/commands/MQTTto2G" #define subject2GtoMQTT Base_Topic Gateway_Name "/2GtoMQTT" #define subjectGTW2GtoMQTT Base_Topic Gateway_Name "/2GtoMQTT" -#define subject2GtoMQTTphone Base_Topic Gateway_Name "/2GtoMQTT/phone" -#define subject2GtoMQTTdate Base_Topic Gateway_Name "/2GtoMQTT/date" -#define subject2GtoMQTTmessage Base_Topic Gateway_Name "/2GtoMQTT/message" #define _2GPhoneKey "PHO_" // phone number define the phone number to send the SMS MQTT->2G #define _2G_MODULE_BAUDRATE 9600 @@ -39,7 +36,16 @@ #define _2G_MAX_SIGNAL 1000 /*-------------------PIN DEFINITIONS----------------------*/ -#define _2G_TX_PIN D6 //D6 to A6 RX, -#define _2G_RX_PIN D7 //D7 to A6 TX -#define _2G_PWR_PIN D5 // connect a MOSFET to power on and off your A6/7 module - +#ifdef ESP8266 + #define _2G_TX_PIN D6 //D6 to A6 RX, + #define _2G_RX_PIN D7 //D7 to A6 TX + #define _2G_PWR_PIN D5 // connect a MOSFET to power on and off your A6/7 module +#elif defined(ESP32) + #define _2G_TX_PIN 16 //D16 to A6 RX, + #define _2G_RX_PIN 17 //D17 to A6 TX + #define _2G_PWR_PIN 5 // connect a MOSFET to power on and off your A6/7 module +#else + #define _2G_TX_PIN 6 //D6 to A6 RX, + #define _2G_RX_PIN 7 //D7 to A6 TX + #define _2G_PWR_PIN 5 // connect a MOSFET to power on and off your A6/7 module +#endif diff --git a/config_BH1750.h b/config_BH1750.h index 316e68d1..f2adb731 100644 --- a/config_BH1750.h +++ b/config_BH1750.h @@ -41,10 +41,7 @@ /*----------------------------USER PARAMETERS-----------------------------*/ /*-------------DEFINE YOUR MQTT PARAMETERS BELOW----------------*/ -#define LUX Base_Topic Gateway_Name "/LIGHTtoMQTT/lux" -#define FTCD Base_Topic Gateway_Name "/LIGHTtoMQTT/ftcd" -#define WATTSM2 Base_Topic Gateway_Name "/LIGHTtoMQTT/wattsm2" - +#define subjectBH1750toMQTT Base_Topic Gateway_Name "/BH1750toMQTT" //Time used to wait for an interval before resending measured values unsigned long timebh1750 = 0; int BH1750_i2c_addr = 0x23; // Light Sensor I2C Address diff --git a/config_BME280.h b/config_BME280.h index a0a045c7..b114e9ab 100644 --- a/config_BME280.h +++ b/config_BME280.h @@ -41,14 +41,7 @@ /*----------------------------USER PARAMETERS-----------------------------*/ /*-------------DEFINE YOUR MQTT PARAMETERS BELOW----------------*/ -#define TEMPBMEC Base_Topic Gateway_Name "/CLIMAtoMQTT/bme/tempc" -#define TEMPBMEF Base_Topic Gateway_Name "/CLIMAtoMQTT/bme/tempf" -#define HUMBME Base_Topic Gateway_Name "/CLIMAtoMQTT/bme/hum" -#define PRESSBME Base_Topic Gateway_Name "/CLIMAtoMQTT/bme/pa" -#define ALTIBMEM Base_Topic Gateway_Name "/CLIMAtoMQTT/bme/altim" -#define ALTIBMEFT Base_Topic Gateway_Name "/CLIMAtoMQTT/bme/altift" +#define BME Base_Topic Gateway_Name "/CLIMAtoMQTT/bme" //Time used to wait for an interval before resending measured values unsigned long timebme280 = 0; - - diff --git a/config_BT.h b/config_BT.h index 716782aa..a4aee293 100644 --- a/config_BT.h +++ b/config_BT.h @@ -25,15 +25,6 @@ */ /*----------------------BT topics & parameters-------------------------*/ #define subjectBTtoMQTT Base_Topic Gateway_Name "/BTtoMQTT/" -//#define subjectBTtoMQTTrssi "/rssi" // will be the default parameter on the next release, for the moment rssi is published on mac topic -#define subjectBTtoMQTTrssi "" -#define subjectBTtoMQTTtem "/tem" -#define subjectBTtoMQTThum "/hum" -#define subjectBTtoMQTTmoi "/moi" -#define subjectBTtoMQTTfer "/fer" -#define subjectBTtoMQTTlux "/lux" -#define subjectBTtoMQTTbatt "/batt" -#define subjectBTtoMQTTservicedata "/servicedata" #define TimeBtw_Read 55555 //define the time between 2 scans #define Scan_duration 10 //define the time for a scan #define HM-10 @@ -42,11 +33,9 @@ #define delimiter "4f4b2b444953413a" #define delimiter_length 16 -/*-------------------HOME ASSISTANT ROOM PRESENCE !!! ESP32 only !!!!----------------------*/ -#define roomPresence //Uncomment to enable -#ifdef roomPresence - #define subjectHomePresence "/homePresence/salon" // will send Home Assistant room presence message to this topic (first part is same for all rooms, second is room name) -#endif +/*-------------------HOME ASSISTANT ROOM PRESENCE ----------------------*/ +// if not commented Home presence integration with HOME ASSISTANT is activated +#define subjectHomePresence Base_Topic "/salon" // will send Home Assistant room presence message to this topic (first part is same for all rooms, second is room name) struct decompose diff --git a/config_DHT.h b/config_DHT.h index c18aea70..7719482c 100644 --- a/config_DHT.h +++ b/config_DHT.h @@ -26,8 +26,7 @@ /*----------------------------USER PARAMETERS-----------------------------*/ /*-------------DEFINE YOUR MQTT PARAMETERS BELOW----------------*/ -#define HUM1 Base_Topic Gateway_Name "/DHTtoMQTT/dht1/hum" -#define TEMP1 Base_Topic Gateway_Name "/DHTtoMQTT/dht1/temp" +#define DHTTOPIC Base_Topic Gateway_Name "/DHTtoMQTT/dht1" #define dht_always true // if false when the current value for temp or hum is the same as previous one don't send it by MQTT #define TimeBetweenReadingDHT 30000 // time between 2 DHT readings /*-------------DHT SENSOR TYPE-------------*/ diff --git a/config_HCSR501.h b/config_HCSR501.h index b0c076b6..0d4d7262 100644 --- a/config_HCSR501.h +++ b/config_HCSR501.h @@ -27,11 +27,14 @@ /*----------------------------USER PARAMETERS-----------------------------*/ /*-------------DEFINE YOUR MQTT PARAMETERS BELOW----------------*/ #define subjectHCSR501toMQTT Base_Topic Gateway_Name "/HCSR501toMQTT" + #define TimeBeforeStartHCSR501 60000 //define the time necessary for HC SR501 init /*-------------------PIN DEFINITIONS----------------------*/ -#if defined(ESP8266) || defined(ESP32) +#if defined(ESP8266) #define HCSR501_PIN D5 +#elif defined(ESP32) + #define HCSR501_PIN 5 #else #define HCSR501_PIN 7 #endif diff --git a/config_INA226.h b/config_INA226.h index b5e4ac2f..e0eae989 100644 --- a/config_INA226.h +++ b/config_INA226.h @@ -26,9 +26,5 @@ /*----------------------------USER PARAMETERS-----------------------------*/ /*-------------DEFINE YOUR MQTT PARAMETERS BELOW----------------*/ -#define subjectVolttoMQTT Base_Topic Gateway_Name "/INA226toMQTT/Volt" -#define subjectCurrenttoMQTT Base_Topic Gateway_Name "/INA226toMQTT/Current" -#define subjectPowertoMQTT Base_Topic Gateway_Name "/INA226toMQTT/Power" +#define subjectINA226toMQTT Base_Topic Gateway_Name "/INA226toMQTT" #define TimeBetweenReadingINA226 30000 // time between 2 INA226 readings - - diff --git a/config_IR.h b/config_IR.h index 2b838e83..7470a589 100644 --- a/config_IR.h +++ b/config_IR.h @@ -29,14 +29,13 @@ #define subjectGTWIRtoMQTT Base_Topic Gateway_Name "/IRtoMQTT" #define subjectIRtoMQTT Base_Topic Gateway_Name "/IRtoMQTT" #define subjectMQTTtoIR Base_Topic Gateway_Name "/commands/MQTTtoIR" -#define subjectIRtoMQTTprotocol Base_Topic Gateway_Name "/IRtoMQTT/protocol" -#define subjectIRtoMQTTbits Base_Topic Gateway_Name "/IRtoMQTT/bits" -#define subjectIRtoMQTTRaw Base_Topic Gateway_Name "/IRtoMQTT/raw" + // subject monitored to listen traffic processed by other gateways to store data and avoid ntuple #define subjectMultiGTWIR "+/+/IRtoMQTT" #define IRbitsKey "IRBITS_" // bits will be defined if a subject contains IRbitsKey followed by a value of 2 digits #define IRRptKey "RPT_" // repeats will be defined if a subject contains IRRptKey followed by a value of 1 digit #define repeatIRwMQTT false // do we repeat a received signal by using mqtt +#define repeatIRwNumber 3 // default repeat of the signal #define RawDirectForward false // direct repeat of IR signal with raw data #define RawFrequency 38 // raw frequency sending //#define DumpMode true // uncomment so as to see big dumps of IR codes diff --git a/config_RF.h b/config_RF.h index 6c4a2d30..3ef92da9 100644 --- a/config_RF.h +++ b/config_RF.h @@ -29,12 +29,10 @@ #define subjectMQTTtoRF Base_Topic Gateway_Name "/commands/MQTTto433" #define subjectRFtoMQTT Base_Topic Gateway_Name "/433toMQTT" #define subjectGTWRFtoMQTT Base_Topic Gateway_Name "/433toMQTT" -#define subjectRFtoMQTTprotocol Base_Topic Gateway_Name "/433toMQTT/protocol" -#define subjectRFtoMQTTbits Base_Topic Gateway_Name "/433toMQTT/bits" -#define subjectRFtoMQTTlength Base_Topic Gateway_Name "/433toMQTT/length" #define RFprotocolKey "433_" // protocol will be defined if a subject contains RFprotocolKey followed by a value of 1 digit #define RFbitsKey "RFBITS_" // bits will be defined if a subject contains RFbitsKey followed by a value of 2 digits -#define repeatRFwMQTT false // do we repeat a received signal by using mqtt +#define repeatRFwMQTT false // do we repeat a received signal by using mqtt with RF gateway +#define repeatSRFBwMQTT false // do we repeat a received signal by using mqtt with Sonoff RF Bridge /* RF supported protocols 433_1 @@ -54,6 +52,7 @@ RF supported protocols //433Mhz newremoteswitch MQTT Subjects and keys #define subjectMQTTtoRF2 Base_Topic Gateway_Name "/commands/MQTTtoRF2" #define subjectRF2toMQTT Base_Topic Gateway_Name "/RF2toMQTT" +#define subjectGTWRF2toMQTT Base_Topic Gateway_Name "/433toMQTT" #define RF2codeKey "CODE_" // code will be defined if a subject contains RF2codeKey followed by a value of 7 digits #define RF2periodKey "PERIOD_" // period will be defined if a subject contains RF2periodKey followed by a value of 3 digits #define RF2unitKey "UNIT_" // number of your unit value will be defined if a subject contains RF2unitKey followed by a value of 1-2 digits @@ -64,12 +63,13 @@ RF supported protocols //433Mhz Pilight MQTT Subjects and keys #define subjectMQTTtoPilight Base_Topic Gateway_Name "/commands/MQTTtoPilight" #define subjectPilighttoMQTT Base_Topic Gateway_Name "/PilighttoMQTT" +#define subjectGTWPilighttoMQTT Base_Topic Gateway_Name "/PilighttoMQTT" #define PilightRAW "RAW" /*-------------------PIN DEFINITIONS----------------------*/ #ifdef ESP8266 #define RF_RECEIVER_PIN 0 // D3 on nodemcu - #define RF_EMITTER_PIN 3 // RX on nodemcu + #define RF_EMITTER_PIN 4 // RX on nodemcu if it doesn't work with 3, try with 4 (D2) #elif defined(ESP32) #define RF_RECEIVER_PIN 13 // D13 on DOIT ESP32 #define RF_EMITTER_PIN 12 // D12 on DOIT ESP32 diff --git a/config_RF315.h b/config_RF315.h index 3d48b0ec..316a9868 100644 --- a/config_RF315.h +++ b/config_RF315.h @@ -29,9 +29,6 @@ #define subjectMQTTtoRF315 Base_Topic Gateway_Name "/commands/MQTTto315" #define subjectRF315toMQTT Base_Topic Gateway_Name "/315toMQTT" #define subjectGTWRF315toMQTT Base_Topic Gateway_Name "/315toMQTT" -#define subjectRF315toMQTTprotocol Base_Topic Gateway_Name "/315toMQTT/protocol" -#define subjectRF315toMQTTbits Base_Topic Gateway_Name "/315toMQTT/bits" -#define subjectRF315toMQTTlength Base_Topic Gateway_Name "/315toMQTT/length" #define RF315protocolKey "315_" // protocol will be defined if a subject contains RFprotocolKey followed by a value of 1 digit #define RF315bitsKey "RFBITS_" // bits will be defined if a subject contains RFbitsKey followed by a value of 2 digits #define repeatRF315wMQTT false // do we repeat a received signal by using mqtt @@ -63,4 +60,3 @@ RF supported protocols #define RF315_RECEIVER_PIN 1 //1 = D3 on arduino #define RF315_EMITTER_PIN 4 //4 = D4 on arduino #endif - diff --git a/config_RFM69.h b/config_RFM69.h index c19520f1..2adeb3b4 100644 --- a/config_RFM69.h +++ b/config_RFM69.h @@ -28,10 +28,7 @@ // Topic where the message from RFM69 will be published by the gateway, // appended with the nodeID of the sender #define subjectRFM69toMQTT Base_Topic Gateway_Name "/RFM69toMQTT" -// Upon reception of a packed, the RSSI of that packet will be publish to this topic, -// appended with the nodeID of the sender -#define subjectRFM69toMQTTrssi Base_Topic Gateway_Name "/RFM69toMQTT/rssi" // Comment this if you don't want the RSSI to be published. -#define subjectRFM69toMQTTsender Base_Topic Gateway_Name "/RFM69toMQTT/sender" + // Topic subscribed by the gateway. Messages received will be sent to RFM69 #define subjectMQTTtoRFM69 Base_Topic Gateway_Name "/commands/MQTTtoRFM69" #define RFM69receiverKey "RCV_" // receiver id will be defined if a subject contains RFM69receiverKey followed by a value of 3 digits @@ -55,11 +52,16 @@ const char PROGMEM RFM69AP_NAME[] = "RFM69-AP"; #define POWER_LEVEL 31 /*-------------------PIN DEFINITIONS----------------------*/ -#if defined(ESP8266) || defined(ESP32) +#if defined(ESP8266) #define RFM69_CS D1 #define RFM69_IRQ D8 // GPIO15/D8 #define RFM69_IRQN digitalPinToInterrupt(RFM69_IRQ) #define RFM69_RST D4 // GPIO02/D4 +#elif defined(ESP32) + #define RFM69_CS 1 + #define RFM69_IRQ 8 // GPIO15/D8 + #define RFM69_IRQN digitalPinToInterrupt(RFM69_IRQ) + #define RFM69_RST 4 // GPIO02/D4 #else //RFM69 not tested with arduino #define RFM69_CS 10 diff --git a/config_SRFB.h b/config_SRFB.h index e20f427f..227762b8 100644 --- a/config_SRFB.h +++ b/config_SRFB.h @@ -29,12 +29,8 @@ //433Mhz MQTT Subjects and keys #define subjectMQTTtoSRFB Base_Topic Gateway_Name "/commands/MQTTtoSRFB" #define subjectMQTTtoSRFBRaw Base_Topic Gateway_Name "/commands/MQTTtoSRFB/Raw" -#define subjectSRFBtoMQTTTsyn Base_Topic Gateway_Name "/SRFBtoMQTT/Tsyn" -#define subjectSRFBtoMQTTTlow Base_Topic Gateway_Name "/SRFBtoMQTT/Tlow" -#define subjectSRFBtoMQTTThigh Base_Topic Gateway_Name "/SRFBtoMQTT/Thigh" #define subjectSRFBtoMQTT Base_Topic Gateway_Name "/SRFBtoMQTT" #define subjectGTWSRFBtoMQTT Base_Topic Gateway_Name "/SRFBtoMQTT" -#define subjectSRFBtoMQTTRaw Base_Topic Gateway_Name "/SRFBtoMQTT/Raw" #define SRFBRptKey "RPT_" #define SRFBmaxipulselengthKey "Thigh_" #define SRFBminipulselengthKey "Tlow_" @@ -57,6 +53,3 @@ #define RF_CODE_RFIN 0xA4 #define RF_CODE_RFOUT 0xA5 #define RF_CODE_STOP 0x55 - - - diff --git a/config_TSL2561.h b/config_TSL2561.h index 44a7aa60..557dc170 100644 --- a/config_TSL2561.h +++ b/config_TSL2561.h @@ -40,9 +40,7 @@ #define TimeBetweenReadingtsl2561 30000 /*----------------------------USER PARAMETERS-----------------------------*/ /*-------------DEFINE YOUR MQTT PARAMETERS BELOW----------------*/ -#define LUX Base_Topic Gateway_Name "/LIGHTtoMQTT/lux" -#define FTCD Base_Topic Gateway_Name "/LIGHTtoMQTT/ftcd" -#define WATTSM2 Base_Topic Gateway_Name "/LIGHTtoMQTT/wattsm2" +#define subjectTSL12561toMQTT Base_Topic Gateway_Name "/LIGHTtoMQTT" //Time used to wait for an interval before resending measured values unsigned long timetsl2561 = 0; diff --git a/lib/Adafruit_TSL2561/.github/ISSUE_TEMPLATE.md b/lib/Adafruit_TSL2561/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..f0e26146 --- /dev/null +++ b/lib/Adafruit_TSL2561/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,46 @@ +Thank you for opening an issue on an Adafruit Arduino library repository. To +improve the speed of resolution please review the following guidelines and +common troubleshooting steps below before creating the issue: + +- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use + the forums at http://forums.adafruit.com to ask questions and troubleshoot why + something isn't working as expected. In many cases the problem is a common issue + that you will more quickly receive help from the forum community. GitHub issues + are meant for known defects in the code. If you don't know if there is a defect + in the code then start with troubleshooting on the forum first. + +- **If following a tutorial or guide be sure you didn't miss a step.** Carefully + check all of the steps and commands to run have been followed. Consult the + forum if you're unsure or have questions about steps in a guide/tutorial. + +- **For Arduino projects check these very common issues to ensure they don't apply**: + + - For uploading sketches or communicating with the board make sure you're using + a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes + very hard to tell the difference between a data and charge cable! Try using the + cable with other devices or swapping to another cable to confirm it is not + the problem. + + - **Be sure you are supplying adequate power to the board.** Check the specs of + your board and plug in an external power supply. In many cases just + plugging a board into your computer is not enough to power it and other + peripherals. + + - **Double check all soldering joints and connections.** Flakey connections + cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints. + + - **Ensure you are using an official Arduino or Adafruit board.** We can't + guarantee a clone board will have the same functionality and work as expected + with this code and don't support them. + +If you're sure this issue is a defect in the code and checked the steps above +please fill in the following fields to provide enough troubleshooting information. +You may delete the guideline and text above to just leave the following details: + +- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE** + +- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO + VERSION HERE** + +- List the steps to reproduce the problem below (if possible attach a sketch or + copy the sketch code in too): **LIST REPRO STEPS BELOW** diff --git a/lib/Adafruit_TSL2561/.github/PULL_REQUEST_TEMPLATE.md b/lib/Adafruit_TSL2561/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..7b641eb8 --- /dev/null +++ b/lib/Adafruit_TSL2561/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,26 @@ +Thank you for creating a pull request to contribute to Adafruit's GitHub code! +Before you open the request please review the following guidelines and tips to +help it be more easily integrated: + +- **Describe the scope of your change--i.e. what the change does and what parts + of the code were modified.** This will help us understand any risks of integrating + the code. + +- **Describe any known limitations with your change.** For example if the change + doesn't apply to a supported platform of the library please mention it. + +- **Please run any tests or examples that can exercise your modified code.** We + strive to not break users of the code and running tests/examples helps with this + process. + +Thank you again for contributing! We will try to test and integrate the change +as soon as we can, but be aware we have many GitHub repositories to manage and +can't immediately respond to every request. There is no need to bump or check in +on a pull request (it will clutter the discussion of the request). + +Also don't be worried if the request is closed or not integrated--sometimes the +priorities of Adafruit's GitHub code (education, ease of use) might not match the +priorities of the pull request. Don't fret, the open source community thrives on +forks and GitHub makes it easy to keep your changes in a forked repo. + +After reviewing the guidelines above you can delete this text from the pull request. diff --git a/lib/Adafruit_TSL2561/.travis.yml b/lib/Adafruit_TSL2561/.travis.yml new file mode 100644 index 00000000..a22fcb56 --- /dev/null +++ b/lib/Adafruit_TSL2561/.travis.yml @@ -0,0 +1,27 @@ +language: c +sudo: false + +# Blacklist +branches: + except: + - gh-pages + +env: + global: + - PRETTYNAME="Adafruit TSL2561 Arduino Library" +# Optional, will default to "$TRAVIS_BUILD_DIR/Doxyfile" +# - DOXYFILE: $TRAVIS_BUILD_DIR/Doxyfile + +before_install: + - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh) + +install: + - arduino --install-library "Adafruit Unified Sensor" + +script: + - build_main_platforms + +# Generate and deploy documentation +after_success: + - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/library_check.sh) + - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/doxy_gen_and_deploy.sh) \ No newline at end of file diff --git a/lib/Adafruit_TSL2561/Adafruit_TSL2561_U.cpp b/lib/Adafruit_TSL2561/Adafruit_TSL2561_U.cpp index 0111ef64..69663fa9 100644 --- a/lib/Adafruit_TSL2561/Adafruit_TSL2561_U.cpp +++ b/lib/Adafruit_TSL2561/Adafruit_TSL2561_U.cpp @@ -1,179 +1,58 @@ -/**************************************************************************/ /*! - @file Adafruit_TSL2561.cpp - @author K.Townsend (Adafruit Industries) - @license BSD (see license.txt) - - Driver for the TSL2561 digital luminosity (light) sensors. - - Pick one up at http://www.adafruit.com/products/439 - - Adafruit invests time and resources providing this open source code, - please support Adafruit and open-source hardware by purchasing - products from Adafruit! - - @section HISTORY - - v2.0 - Rewrote driver for Adafruit_Sensor and Auto-Gain support, and - added lux clipping check (returns 0 lux on sensor saturation) - v1.0 - First release (previously TSL2561) + * @file Adafruit_TSL2561_U.cpp + * + * @mainpage Adafruit TSL2561 Light/Lux sensor driver + * + * @section intro_sec Introduction + * + * This is the documentation for Adafruit's TSL2561 driver for the + * Arduino platform. It is designed specifically to work with the + * Adafruit TSL2561 breakout: http://www.adafruit.com/products/439 + * + * These sensors use I2C to communicate, 2 pins (SCL+SDA) are required + * to interface with the breakout. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * @section dependencies Dependencies + * + * This library depends on + * Adafruit_Sensor being present on your system. Please make sure you have + * installed the latest version before using this library. + * + * @section author Author + * + * Written by Kevin "KTOWN" Townsend for Adafruit Industries. + * + * @section license License + * + * BSD license, all text here must be included in any redistribution. + * + * @section HISTORY + * + * v2.0 - Rewrote driver for Adafruit_Sensor and Auto-Gain support, and + * added lux clipping check (returns 0 lux on sensor saturation) + * v1.0 - First release (previously TSL2561) */ /**************************************************************************/ -#if defined(__AVR__) -#include -#include -#else -#include "pgmspace.h" -#endif -#include #include "Adafruit_TSL2561_U.h" -#define TSL2561_DELAY_INTTIME_13MS (15) -#define TSL2561_DELAY_INTTIME_101MS (120) -#define TSL2561_DELAY_INTTIME_402MS (450) - -/*========================================================================*/ -/* PRIVATE FUNCTIONS */ -/*========================================================================*/ - -/**************************************************************************/ -/*! - @brief Writes a register and an 8 bit value over I2C -*/ -/**************************************************************************/ -void Adafruit_TSL2561_Unified::write8 (uint8_t reg, uint32_t value) -{ - Wire.beginTransmission(_addr); - #if ARDUINO >= 100 - Wire.write(reg); - Wire.write(value & 0xFF); - #else - Wire.send(reg); - Wire.send(value & 0xFF); - #endif - Wire.endTransmission(); -} - -/**************************************************************************/ -/*! - @brief Reads an 8 bit value over I2C -*/ -/**************************************************************************/ -uint8_t Adafruit_TSL2561_Unified::read8(uint8_t reg) -{ - Wire.beginTransmission(_addr); - #if ARDUINO >= 100 - Wire.write(reg); - #else - Wire.send(reg); - #endif - Wire.endTransmission(); - - Wire.requestFrom(_addr, 1); - #if ARDUINO >= 100 - return Wire.read(); - #else - return Wire.receive(); - #endif -} - -/**************************************************************************/ -/*! - @brief Reads a 16 bit values over I2C -*/ -/**************************************************************************/ -uint16_t Adafruit_TSL2561_Unified::read16(uint8_t reg) -{ - uint16_t x; uint16_t t; - - Wire.beginTransmission(_addr); - #if ARDUINO >= 100 - Wire.write(reg); - #else - Wire.send(reg); - #endif - Wire.endTransmission(); - - Wire.requestFrom(_addr, 2); - #if ARDUINO >= 100 - t = Wire.read(); - x = Wire.read(); - #else - t = Wire.receive(); - x = Wire.receive(); - #endif - x <<= 8; - x |= t; - return x; -} - -/**************************************************************************/ -/*! - Enables the device -*/ -/**************************************************************************/ -void Adafruit_TSL2561_Unified::enable(void) -{ - /* Enable the device by setting the control bit to 0x03 */ - write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWERON); -} - -/**************************************************************************/ -/*! - Disables the device (putting it in lower power sleep mode) -*/ -/**************************************************************************/ -void Adafruit_TSL2561_Unified::disable(void) -{ - /* Turn the device off to save power */ - write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF); -} - -/**************************************************************************/ -/*! - Private function to read luminosity on both channels -*/ -/**************************************************************************/ -void Adafruit_TSL2561_Unified::getData (uint16_t *broadband, uint16_t *ir) -{ - /* Enable the device by setting the control bit to 0x03 */ - enable(); - - /* Wait x ms for ADC to complete */ - switch (_tsl2561IntegrationTime) - { - case TSL2561_INTEGRATIONTIME_13MS: - delay(TSL2561_DELAY_INTTIME_13MS); // KTOWN: Was 14ms - break; - case TSL2561_INTEGRATIONTIME_101MS: - delay(TSL2561_DELAY_INTTIME_101MS); // KTOWN: Was 102ms - break; - default: - delay(TSL2561_DELAY_INTTIME_402MS); // KTOWN: Was 403ms - break; - } - - /* Reads a two byte value from channel 0 (visible + infrared) */ - *broadband = read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW); - - /* Reads a two byte value from channel 1 (infrared) */ - *ir = read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW); - - /* Turn the device off to save power */ - disable(); -} - /*========================================================================*/ /* CONSTRUCTORS */ /*========================================================================*/ /**************************************************************************/ /*! - Constructor + @brief Constructor + @param addr The I2C address this chip can be found on, 0x29, 0x39 or 0x49 + @param sensorID An optional ID that will be placed in sensor events to help + keep track if you have many sensors in use */ /**************************************************************************/ -Adafruit_TSL2561_Unified::Adafruit_TSL2561_Unified(uint8_t addr, int32_t sensorID) +Adafruit_TSL2561_Unified::Adafruit_TSL2561_Unified(uint8_t addr, int32_t sensorID) { _addr = addr; _tsl2561Initialised = false; @@ -189,18 +68,46 @@ Adafruit_TSL2561_Unified::Adafruit_TSL2561_Unified(uint8_t addr, int32_t sensorI /**************************************************************************/ /*! - Initializes I2C and configures the sensor (call this function before - doing anything else) + @brief Initializes I2C and configures the sensor with default Wire I2C + (call this function before doing anything else) + @returns True if sensor is found and initialized, false otherwise. */ /**************************************************************************/ -boolean Adafruit_TSL2561_Unified::begin(void) +boolean Adafruit_TSL2561_Unified::begin() { - Wire.begin(); + _i2c = &Wire; + _i2c->begin(); + return init(); +} +/**************************************************************************/ +/*! + @brief Initializes I2C and configures the sensor with provided I2C device + (call this function before doing anything else) + @param theWire A pointer to any I2C interface (e.g. &Wire1) + @returns True if sensor is found and initialized, false otherwise. +*/ +/**************************************************************************/ +boolean Adafruit_TSL2561_Unified::begin(TwoWire *theWire) +{ + _i2c = theWire; + _i2c-> begin(); + return init(); +} + +/**************************************************************************/ +/*! + @brief Initializes I2C connection and settings. + Attempts to determine if the sensor is contactable, then sets up a default + integration time and gain. Then powers down the chip. + @returns True if sensor is found and initialized, false otherwise. +*/ +/**************************************************************************/ +boolean Adafruit_TSL2561_Unified::init() +{ /* Make sure we're actually connected */ uint8_t x = read8(TSL2561_REGISTER_ID); - if (!(x & 0x0A)) - { + if (x & 0xF0 != 0x10) { // ID code for TSL2561 return false; } _tsl2561Initialised = true; @@ -214,11 +121,12 @@ boolean Adafruit_TSL2561_Unified::begin(void) return true; } - + /**************************************************************************/ /*! @brief Enables or disables the auto-gain settings when reading data from the sensor + @param enable Set to true to enable, False to disable */ /**************************************************************************/ void Adafruit_TSL2561_Unified::enableAutoRange(bool enable) @@ -228,7 +136,10 @@ void Adafruit_TSL2561_Unified::enableAutoRange(bool enable) /**************************************************************************/ /*! - Sets the integration time for the TSL2561 + @brief Sets the integration time for the TSL2561. Higher time means + more light captured (better for low light conditions) but will + take longer to run readings. + @param time The amount of time we'd like to add up values */ /**************************************************************************/ void Adafruit_TSL2561_Unified::setIntegrationTime(tsl2561IntegrationTime_t time) @@ -250,7 +161,8 @@ void Adafruit_TSL2561_Unified::setIntegrationTime(tsl2561IntegrationTime_t time) /**************************************************************************/ /*! - Adjusts the gain on the TSL2561 (adjusts the sensitivity to light) + @brief Adjusts the gain on the TSL2561 (adjusts the sensitivity to light) + @param gain The value we'd like to set the gain to */ /**************************************************************************/ void Adafruit_TSL2561_Unified::setGain(tsl2561Gain_t gain) @@ -274,6 +186,10 @@ void Adafruit_TSL2561_Unified::setGain(tsl2561Gain_t gain) /*! @brief Gets the broadband (mixed lighting) and IR only values from the TSL2561, adjusting gain if auto-gain is enabled + @param broadband Pointer to a uint16_t we will fill with a sensor + reading from the IR+visible light diode. + @param ir Pointer to a uint16_t we will fill with a sensor the + IR-only light diode. */ /**************************************************************************/ void Adafruit_TSL2561_Unified::getLuminosity (uint16_t *broadband, uint16_t *ir) @@ -358,18 +274,87 @@ void Adafruit_TSL2561_Unified::getLuminosity (uint16_t *broadband, uint16_t *ir) } while (!valid); } + + /**************************************************************************/ /*! - Converts the raw sensor values to the standard SI lux equivalent. - Returns 0 if the sensor is saturated and the values are unreliable. + Enables the device +*/ +/**************************************************************************/ +void Adafruit_TSL2561_Unified::enable(void) +{ + /* Enable the device by setting the control bit to 0x03 */ + write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWERON); +} + +/**************************************************************************/ +/*! + Disables the device (putting it in lower power sleep mode) +*/ +/**************************************************************************/ +void Adafruit_TSL2561_Unified::disable(void) +{ + /* Turn the device off to save power */ + write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF); +} + +/**************************************************************************/ +/*! + Private function to read luminosity on both channels +*/ +/**************************************************************************/ +void Adafruit_TSL2561_Unified::getData (uint16_t *broadband, uint16_t *ir) +{ + /* Enable the device by setting the control bit to 0x03 */ + enable(); + + /* Wait x ms for ADC to complete */ + switch (_tsl2561IntegrationTime) + { + case TSL2561_INTEGRATIONTIME_13MS: + delay(TSL2561_DELAY_INTTIME_13MS); // KTOWN: Was 14ms + break; + case TSL2561_INTEGRATIONTIME_101MS: + delay(TSL2561_DELAY_INTTIME_101MS); // KTOWN: Was 102ms + break; + default: + delay(TSL2561_DELAY_INTTIME_402MS); // KTOWN: Was 403ms + break; + } + + /* Reads a two byte value from channel 0 (visible + infrared) */ + *broadband = read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW); + + /* Reads a two byte value from channel 1 (infrared) */ + *ir = read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW); + + /* Turn the device off to save power */ + disable(); +} + + +/**************************************************************************/ +/*! + @brief Converts the raw sensor values to the standard SI lux equivalent. + @param broadband The 16-bit sensor reading from the IR+visible light diode. + @param ir The 16-bit sensor reading from the IR-only light diode. + @returns The integer Lux value we calcuated. + Returns 0 if the sensor is saturated and the values are + unreliable, or 65536 if the sensor is saturated. +*/ +/**************************************************************************/ +/**************************************************************************/ +/*! + + Returns */ /**************************************************************************/ uint32_t Adafruit_TSL2561_Unified::calculateLux(uint16_t broadband, uint16_t ir) { unsigned long chScale; unsigned long channel1; - unsigned long channel0; - + unsigned long channel0; + /* Make sure the sensor isn't saturated! */ uint16_t clipThreshold; switch (_tsl2561IntegrationTime) @@ -385,10 +370,10 @@ uint32_t Adafruit_TSL2561_Unified::calculateLux(uint16_t broadband, uint16_t ir) break; } - /* Return 0 lux if the sensor is saturated */ + /* Return 65536 lux if the sensor is saturated */ if ((broadband > clipThreshold) || (ir > clipThreshold)) { - return 0; + return 65536; } /* Get the correct scale depending on the intergration time */ @@ -476,15 +461,19 @@ uint32_t Adafruit_TSL2561_Unified::calculateLux(uint16_t broadband, uint16_t ir) /**************************************************************************/ /*! @brief Gets the most recent sensor event + @param event Pointer to a sensor_event_t type that will be filled + with the lux value, timestamp, data type and sensor ID. + @returns True if sensor reading is between 0 and 65535 lux, + false if sensor is saturated */ /**************************************************************************/ bool Adafruit_TSL2561_Unified::getEvent(sensors_event_t *event) { uint16_t broadband, ir; - + /* Clear the event */ memset(event, 0, sizeof(sensors_event_t)); - + event->version = sizeof(sensors_event_t); event->sensor_id = _tsl2561SensorID; event->type = SENSOR_TYPE_LIGHT; @@ -493,13 +482,18 @@ bool Adafruit_TSL2561_Unified::getEvent(sensors_event_t *event) /* Calculate the actual lux value */ getLuminosity(&broadband, &ir); event->light = calculateLux(broadband, ir); - + + if (event->light == 65536) { + return false; + } return true; } /**************************************************************************/ /*! @brief Gets the sensor_t data + @param sensor A pointer to a sensor_t structure that we will fill with + details about the TSL2561 and its capabilities */ /**************************************************************************/ void Adafruit_TSL2561_Unified::getSensor(sensor_t *sensor) @@ -515,6 +509,67 @@ void Adafruit_TSL2561_Unified::getSensor(sensor_t *sensor) sensor->type = SENSOR_TYPE_LIGHT; sensor->min_delay = 0; sensor->max_value = 17000.0; /* Based on trial and error ... confirm! */ - sensor->min_value = 0.0; + sensor->min_value = 1.0; sensor->resolution = 1.0; } + + + +/*========================================================================*/ +/* PRIVATE FUNCTIONS */ +/*========================================================================*/ + +/**************************************************************************/ +/*! + @brief Writes a register and an 8 bit value over I2C + @param reg I2C register to write the value to + @param value The 8-bit value we're writing to the register +*/ +/**************************************************************************/ +void Adafruit_TSL2561_Unified::write8 (uint8_t reg, uint8_t value) +{ + _i2c->beginTransmission(_addr); + _i2c->write(reg); + _i2c->write(value); + _i2c->endTransmission(); +} + +/**************************************************************************/ +/*! + @brief Reads an 8 bit value over I2C + @param reg I2C register to read from + @returns 8-bit value containing single byte data read +*/ +/**************************************************************************/ +uint8_t Adafruit_TSL2561_Unified::read8(uint8_t reg) +{ + _i2c->beginTransmission(_addr); + _i2c->write(reg); + _i2c->endTransmission(); + + _i2c->requestFrom(_addr, 1); + return _i2c-> read(); +} + +/**************************************************************************/ +/*! + @brief Reads a 16 bit values over I2C + @param reg I2C register to read from + @returns 16-bit value containing 2-byte data read +*/ +/**************************************************************************/ +uint16_t Adafruit_TSL2561_Unified::read16(uint8_t reg) +{ + uint16_t x, t; + + _i2c->beginTransmission(_addr); + _i2c->write(reg); + _i2c->endTransmission(); + + _i2c->requestFrom(_addr, 2); + t = _i2c->read(); + x = _i2c->read(); + x <<= 8; + x |= t; + return x; +} diff --git a/lib/Adafruit_TSL2561/Adafruit_TSL2561_U.h b/lib/Adafruit_TSL2561/Adafruit_TSL2561_U.h index 48990e44..e1aa191f 100644 --- a/lib/Adafruit_TSL2561/Adafruit_TSL2561_U.h +++ b/lib/Adafruit_TSL2561/Adafruit_TSL2561_U.h @@ -1,158 +1,146 @@ -/**************************************************************************/ -/*! - @file Adafruit_TSL2561.h - @author K. Townsend (Adafruit Industries) +/*! + * @file Adafruit_TSL2561_U.h + * + * This is part of Adafruit's FXOS8700 driver for the Arduino platform. It is + * designed specifically to work with the Adafruit FXOS8700 breakout: + * https://www.adafruit.com/products/3463 + * + * These sensors use I2C to communicate, 2 pins (SCL+SDA) are required + * to interface with the breakout. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Written by Kevin "KTOWN" Townsend for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ - @section LICENSE +#ifndef ADAFRUIT_TSL2561_H_ +#define ADAFRUIT_TSL2561_H_ - Software License Agreement (BSD License) - - Copyright (c) 2013, Adafruit Industries - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -/**************************************************************************/ -#ifndef _TSL2561_H_ -#define _TSL2561_H_ - -#if ARDUINO >= 100 - #include -#else - #include -#endif +#include #include #include -#define TSL2561_VISIBLE 2 // channel 0 - channel 1 -#define TSL2561_INFRARED 1 // channel 1 -#define TSL2561_FULLSPECTRUM 0 // channel 0 +#define TSL2561_VISIBLE 2 ///< channel 0 - channel 1 +#define TSL2561_INFRARED 1 ///< channel 1 +#define TSL2561_FULLSPECTRUM 0 ///< channel 0 // I2C address options -#define TSL2561_ADDR_LOW (0x29) -#define TSL2561_ADDR_FLOAT (0x39) // Default address (pin left floating) -#define TSL2561_ADDR_HIGH (0x49) +#define TSL2561_ADDR_LOW (0x29) ///< Default address (pin pulled low) +#define TSL2561_ADDR_FLOAT (0x39) ///< Default address (pin left floating) +#define TSL2561_ADDR_HIGH (0x49) ///< Default address (pin pulled high) // Lux calculations differ slightly for CS package -//#define TSL2561_PACKAGE_CS -#define TSL2561_PACKAGE_T_FN_CL +//#define TSL2561_PACKAGE_CS ///< Chip scale package +#define TSL2561_PACKAGE_T_FN_CL ///< Dual Flat No-Lead package -#define TSL2561_COMMAND_BIT (0x80) // Must be 1 -#define TSL2561_CLEAR_BIT (0x40) // Clears any pending interrupt (write 1 to clear) -#define TSL2561_WORD_BIT (0x20) // 1 = read/write word (rather than byte) -#define TSL2561_BLOCK_BIT (0x10) // 1 = using block read/write +#define TSL2561_COMMAND_BIT (0x80) ///< Must be 1 +#define TSL2561_CLEAR_BIT (0x40) ///< Clears any pending interrupt (write 1 to clear) +#define TSL2561_WORD_BIT (0x20) ///< 1 = read/write word (rather than byte) +#define TSL2561_BLOCK_BIT (0x10) ///< 1 = using block read/write -#define TSL2561_CONTROL_POWERON (0x03) -#define TSL2561_CONTROL_POWEROFF (0x00) +#define TSL2561_CONTROL_POWERON (0x03) ///< Control register setting to turn on +#define TSL2561_CONTROL_POWEROFF (0x00) ///< Control register setting to turn off -#define TSL2561_LUX_LUXSCALE (14) // Scale by 2^14 -#define TSL2561_LUX_RATIOSCALE (9) // Scale ratio by 2^9 -#define TSL2561_LUX_CHSCALE (10) // Scale channel values by 2^10 -#define TSL2561_LUX_CHSCALE_TINT0 (0x7517) // 322/11 * 2^TSL2561_LUX_CHSCALE -#define TSL2561_LUX_CHSCALE_TINT1 (0x0FE7) // 322/81 * 2^TSL2561_LUX_CHSCALE +#define TSL2561_LUX_LUXSCALE (14) ///< Scale by 2^14 +#define TSL2561_LUX_RATIOSCALE (9) ///< Scale ratio by 2^9 +#define TSL2561_LUX_CHSCALE (10) ///< Scale channel values by 2^10 +#define TSL2561_LUX_CHSCALE_TINT0 (0x7517) ///< 322/11 * 2^TSL2561_LUX_CHSCALE +#define TSL2561_LUX_CHSCALE_TINT1 (0x0FE7) ///< 322/81 * 2^TSL2561_LUX_CHSCALE // T, FN and CL package values -#define TSL2561_LUX_K1T (0x0040) // 0.125 * 2^RATIO_SCALE -#define TSL2561_LUX_B1T (0x01f2) // 0.0304 * 2^LUX_SCALE -#define TSL2561_LUX_M1T (0x01be) // 0.0272 * 2^LUX_SCALE -#define TSL2561_LUX_K2T (0x0080) // 0.250 * 2^RATIO_SCALE -#define TSL2561_LUX_B2T (0x0214) // 0.0325 * 2^LUX_SCALE -#define TSL2561_LUX_M2T (0x02d1) // 0.0440 * 2^LUX_SCALE -#define TSL2561_LUX_K3T (0x00c0) // 0.375 * 2^RATIO_SCALE -#define TSL2561_LUX_B3T (0x023f) // 0.0351 * 2^LUX_SCALE -#define TSL2561_LUX_M3T (0x037b) // 0.0544 * 2^LUX_SCALE -#define TSL2561_LUX_K4T (0x0100) // 0.50 * 2^RATIO_SCALE -#define TSL2561_LUX_B4T (0x0270) // 0.0381 * 2^LUX_SCALE -#define TSL2561_LUX_M4T (0x03fe) // 0.0624 * 2^LUX_SCALE -#define TSL2561_LUX_K5T (0x0138) // 0.61 * 2^RATIO_SCALE -#define TSL2561_LUX_B5T (0x016f) // 0.0224 * 2^LUX_SCALE -#define TSL2561_LUX_M5T (0x01fc) // 0.0310 * 2^LUX_SCALE -#define TSL2561_LUX_K6T (0x019a) // 0.80 * 2^RATIO_SCALE -#define TSL2561_LUX_B6T (0x00d2) // 0.0128 * 2^LUX_SCALE -#define TSL2561_LUX_M6T (0x00fb) // 0.0153 * 2^LUX_SCALE -#define TSL2561_LUX_K7T (0x029a) // 1.3 * 2^RATIO_SCALE -#define TSL2561_LUX_B7T (0x0018) // 0.00146 * 2^LUX_SCALE -#define TSL2561_LUX_M7T (0x0012) // 0.00112 * 2^LUX_SCALE -#define TSL2561_LUX_K8T (0x029a) // 1.3 * 2^RATIO_SCALE -#define TSL2561_LUX_B8T (0x0000) // 0.000 * 2^LUX_SCALE -#define TSL2561_LUX_M8T (0x0000) // 0.000 * 2^LUX_SCALE +#define TSL2561_LUX_K1T (0x0040) ///< 0.125 * 2^RATIO_SCALE +#define TSL2561_LUX_B1T (0x01f2) ///< 0.0304 * 2^LUX_SCALE +#define TSL2561_LUX_M1T (0x01be) ///< 0.0272 * 2^LUX_SCALE +#define TSL2561_LUX_K2T (0x0080) ///< 0.250 * 2^RATIO_SCALE +#define TSL2561_LUX_B2T (0x0214) ///< 0.0325 * 2^LUX_SCALE +#define TSL2561_LUX_M2T (0x02d1) ///< 0.0440 * 2^LUX_SCALE +#define TSL2561_LUX_K3T (0x00c0) ///< 0.375 * 2^RATIO_SCALE +#define TSL2561_LUX_B3T (0x023f) ///< 0.0351 * 2^LUX_SCALE +#define TSL2561_LUX_M3T (0x037b) ///< 0.0544 * 2^LUX_SCALE +#define TSL2561_LUX_K4T (0x0100) ///< 0.50 * 2^RATIO_SCALE +#define TSL2561_LUX_B4T (0x0270) ///< 0.0381 * 2^LUX_SCALE +#define TSL2561_LUX_M4T (0x03fe) ///< 0.0624 * 2^LUX_SCALE +#define TSL2561_LUX_K5T (0x0138) ///< 0.61 * 2^RATIO_SCALE +#define TSL2561_LUX_B5T (0x016f) ///< 0.0224 * 2^LUX_SCALE +#define TSL2561_LUX_M5T (0x01fc) ///< 0.0310 * 2^LUX_SCALE +#define TSL2561_LUX_K6T (0x019a) ///< 0.80 * 2^RATIO_SCALE +#define TSL2561_LUX_B6T (0x00d2) ///< 0.0128 * 2^LUX_SCALE +#define TSL2561_LUX_M6T (0x00fb) ///< 0.0153 * 2^LUX_SCALE +#define TSL2561_LUX_K7T (0x029a) ///< 1.3 * 2^RATIO_SCALE +#define TSL2561_LUX_B7T (0x0018) ///< 0.00146 * 2^LUX_SCALE +#define TSL2561_LUX_M7T (0x0012) ///< 0.00112 * 2^LUX_SCALE +#define TSL2561_LUX_K8T (0x029a) ///< 1.3 * 2^RATIO_SCALE +#define TSL2561_LUX_B8T (0x0000) ///< 0.000 * 2^LUX_SCALE +#define TSL2561_LUX_M8T (0x0000) ///< 0.000 * 2^LUX_SCALE // CS package values -#define TSL2561_LUX_K1C (0x0043) // 0.130 * 2^RATIO_SCALE -#define TSL2561_LUX_B1C (0x0204) // 0.0315 * 2^LUX_SCALE -#define TSL2561_LUX_M1C (0x01ad) // 0.0262 * 2^LUX_SCALE -#define TSL2561_LUX_K2C (0x0085) // 0.260 * 2^RATIO_SCALE -#define TSL2561_LUX_B2C (0x0228) // 0.0337 * 2^LUX_SCALE -#define TSL2561_LUX_M2C (0x02c1) // 0.0430 * 2^LUX_SCALE -#define TSL2561_LUX_K3C (0x00c8) // 0.390 * 2^RATIO_SCALE -#define TSL2561_LUX_B3C (0x0253) // 0.0363 * 2^LUX_SCALE -#define TSL2561_LUX_M3C (0x0363) // 0.0529 * 2^LUX_SCALE -#define TSL2561_LUX_K4C (0x010a) // 0.520 * 2^RATIO_SCALE -#define TSL2561_LUX_B4C (0x0282) // 0.0392 * 2^LUX_SCALE -#define TSL2561_LUX_M4C (0x03df) // 0.0605 * 2^LUX_SCALE -#define TSL2561_LUX_K5C (0x014d) // 0.65 * 2^RATIO_SCALE -#define TSL2561_LUX_B5C (0x0177) // 0.0229 * 2^LUX_SCALE -#define TSL2561_LUX_M5C (0x01dd) // 0.0291 * 2^LUX_SCALE -#define TSL2561_LUX_K6C (0x019a) // 0.80 * 2^RATIO_SCALE -#define TSL2561_LUX_B6C (0x0101) // 0.0157 * 2^LUX_SCALE -#define TSL2561_LUX_M6C (0x0127) // 0.0180 * 2^LUX_SCALE -#define TSL2561_LUX_K7C (0x029a) // 1.3 * 2^RATIO_SCALE -#define TSL2561_LUX_B7C (0x0037) // 0.00338 * 2^LUX_SCALE -#define TSL2561_LUX_M7C (0x002b) // 0.00260 * 2^LUX_SCALE -#define TSL2561_LUX_K8C (0x029a) // 1.3 * 2^RATIO_SCALE -#define TSL2561_LUX_B8C (0x0000) // 0.000 * 2^LUX_SCALE -#define TSL2561_LUX_M8C (0x0000) // 0.000 * 2^LUX_SCALE +#define TSL2561_LUX_K1C (0x0043) ///< 0.130 * 2^RATIO_SCALE +#define TSL2561_LUX_B1C (0x0204) ///< 0.0315 * 2^LUX_SCALE +#define TSL2561_LUX_M1C (0x01ad) ///< 0.0262 * 2^LUX_SCALE +#define TSL2561_LUX_K2C (0x0085) ///< 0.260 * 2^RATIO_SCALE +#define TSL2561_LUX_B2C (0x0228) ///< 0.0337 * 2^LUX_SCALE +#define TSL2561_LUX_M2C (0x02c1) ///< 0.0430 * 2^LUX_SCALE +#define TSL2561_LUX_K3C (0x00c8) ///< 0.390 * 2^RATIO_SCALE +#define TSL2561_LUX_B3C (0x0253) ///< 0.0363 * 2^LUX_SCALE +#define TSL2561_LUX_M3C (0x0363) ///< 0.0529 * 2^LUX_SCALE +#define TSL2561_LUX_K4C (0x010a) ///< 0.520 * 2^RATIO_SCALE +#define TSL2561_LUX_B4C (0x0282) ///< 0.0392 * 2^LUX_SCALE +#define TSL2561_LUX_M4C (0x03df) ///< 0.0605 * 2^LUX_SCALE +#define TSL2561_LUX_K5C (0x014d) ///< 0.65 * 2^RATIO_SCALE +#define TSL2561_LUX_B5C (0x0177) ///< 0.0229 * 2^LUX_SCALE +#define TSL2561_LUX_M5C (0x01dd) ///< 0.0291 * 2^LUX_SCALE +#define TSL2561_LUX_K6C (0x019a) ///< 0.80 * 2^RATIO_SCALE +#define TSL2561_LUX_B6C (0x0101) ///< 0.0157 * 2^LUX_SCALE +#define TSL2561_LUX_M6C (0x0127) ///< 0.0180 * 2^LUX_SCALE +#define TSL2561_LUX_K7C (0x029a) ///< 1.3 * 2^RATIO_SCALE +#define TSL2561_LUX_B7C (0x0037) ///< 0.00338 * 2^LUX_SCALE +#define TSL2561_LUX_M7C (0x002b) ///< 0.00260 * 2^LUX_SCALE +#define TSL2561_LUX_K8C (0x029a) ///< 1.3 * 2^RATIO_SCALE +#define TSL2561_LUX_B8C (0x0000) ///< 0.000 * 2^LUX_SCALE +#define TSL2561_LUX_M8C (0x0000) ///< 0.000 * 2^LUX_SCALE // Auto-gain thresholds -#define TSL2561_AGC_THI_13MS (4850) // Max value at Ti 13ms = 5047 -#define TSL2561_AGC_TLO_13MS (100) -#define TSL2561_AGC_THI_101MS (36000) // Max value at Ti 101ms = 37177 -#define TSL2561_AGC_TLO_101MS (200) -#define TSL2561_AGC_THI_402MS (63000) // Max value at Ti 402ms = 65535 -#define TSL2561_AGC_TLO_402MS (500) +#define TSL2561_AGC_THI_13MS (4850) ///< Max value at Ti 13ms = 5047 +#define TSL2561_AGC_TLO_13MS (100) ///< Min value at Ti 13ms = 100 +#define TSL2561_AGC_THI_101MS (36000) ///< Max value at Ti 101ms = 37177 +#define TSL2561_AGC_TLO_101MS (200) ///< Min value at Ti 101ms = 200 +#define TSL2561_AGC_THI_402MS (63000) ///< Max value at Ti 402ms = 65535 +#define TSL2561_AGC_TLO_402MS (500) ///< Min value at Ti 402ms = 500 // Clipping thresholds -#define TSL2561_CLIPPING_13MS (4900) -#define TSL2561_CLIPPING_101MS (37000) -#define TSL2561_CLIPPING_402MS (65000) +#define TSL2561_CLIPPING_13MS (4900) ///< # Counts that trigger a change in gain/integration +#define TSL2561_CLIPPING_101MS (37000) ///< # Counts that trigger a change in gain/integration +#define TSL2561_CLIPPING_402MS (65000) ///< # Counts that trigger a change in gain/integration +// Delay for integration times +#define TSL2561_DELAY_INTTIME_13MS (15) ///< Wait 15ms for 13ms integration +#define TSL2561_DELAY_INTTIME_101MS (120) ///< Wait 120ms for 101ms integration +#define TSL2561_DELAY_INTTIME_402MS (450) ///< Wait 450ms for 402ms integration + +/** TSL2561 I2C Registers */ enum { - TSL2561_REGISTER_CONTROL = 0x00, - TSL2561_REGISTER_TIMING = 0x01, - TSL2561_REGISTER_THRESHHOLDL_LOW = 0x02, - TSL2561_REGISTER_THRESHHOLDL_HIGH = 0x03, - TSL2561_REGISTER_THRESHHOLDH_LOW = 0x04, - TSL2561_REGISTER_THRESHHOLDH_HIGH = 0x05, - TSL2561_REGISTER_INTERRUPT = 0x06, - TSL2561_REGISTER_CRC = 0x08, - TSL2561_REGISTER_ID = 0x0A, - TSL2561_REGISTER_CHAN0_LOW = 0x0C, - TSL2561_REGISTER_CHAN0_HIGH = 0x0D, - TSL2561_REGISTER_CHAN1_LOW = 0x0E, - TSL2561_REGISTER_CHAN1_HIGH = 0x0F + TSL2561_REGISTER_CONTROL = 0x00, // Control/power register + TSL2561_REGISTER_TIMING = 0x01, // Set integration time register + TSL2561_REGISTER_THRESHHOLDL_LOW = 0x02, // Interrupt low threshold low-byte + TSL2561_REGISTER_THRESHHOLDL_HIGH = 0x03, // Interrupt low threshold high-byte + TSL2561_REGISTER_THRESHHOLDH_LOW = 0x04, // Interrupt high threshold low-byte + TSL2561_REGISTER_THRESHHOLDH_HIGH = 0x05, // Interrupt high threshold high-byte + TSL2561_REGISTER_INTERRUPT = 0x06, // Interrupt settings + TSL2561_REGISTER_CRC = 0x08, // Factory use only + TSL2561_REGISTER_ID = 0x0A, // TSL2561 identification setting + TSL2561_REGISTER_CHAN0_LOW = 0x0C, // Light data channel 0, low byte + TSL2561_REGISTER_CHAN0_HIGH = 0x0D, // Light data channel 0, high byte + TSL2561_REGISTER_CHAN1_LOW = 0x0E, // Light data channel 1, low byte + TSL2561_REGISTER_CHAN1_HIGH = 0x0F // Light data channel 1, high byte }; +/** Three options for how long to integrate readings for */ typedef enum { TSL2561_INTEGRATIONTIME_13MS = 0x00, // 13.7ms @@ -161,6 +149,7 @@ typedef enum } tsl2561IntegrationTime_t; +/** TSL2561 offers 2 gain settings */ typedef enum { TSL2561_GAIN_1X = 0x00, // No gain @@ -168,10 +157,19 @@ typedef enum } tsl2561Gain_t; + + +/**************************************************************************/ +/*! + @brief Class that stores state and functions for interacting with TSL2561 Light Sensor +*/ +/**************************************************************************/ class Adafruit_TSL2561_Unified : public Adafruit_Sensor { public: Adafruit_TSL2561_Unified(uint8_t addr, int32_t sensorID = -1); boolean begin(void); + boolean begin(TwoWire *theWire); + boolean init(); /* TSL2561 Functions */ void enableAutoRange(bool enable); @@ -185,6 +183,8 @@ class Adafruit_TSL2561_Unified : public Adafruit_Sensor { void getSensor(sensor_t*); private: + TwoWire *_i2c; + int8_t _addr; boolean _tsl2561Initialised; boolean _tsl2561AutoGain; @@ -194,9 +194,10 @@ class Adafruit_TSL2561_Unified : public Adafruit_Sensor { void enable (void); void disable (void); - void write8 (uint8_t reg, uint32_t value); + void write8 (uint8_t reg, uint8_t value); uint8_t read8 (uint8_t reg); uint16_t read16 (uint8_t reg); void getData (uint16_t *broadband, uint16_t *ir); }; -#endif + +#endif // ADAFRUIT_TSL2561_H diff --git a/lib/Adafruit_TSL2561/README.md b/lib/Adafruit_TSL2561/README.md index abd25c16..87dd30f4 100644 --- a/lib/Adafruit_TSL2561/README.md +++ b/lib/Adafruit_TSL2561/README.md @@ -1,7 +1,10 @@ -#Adafruit TSL2561 Light Sensor Driver # +# Adafruit TSL2561 Light Sensor Driver [![Build Status](https://travis-ci.org/adafruit/Adafruit_TSL2561.svg?branch=master)](https://travis-ci.org/adafruit/Adafruit_TSL2561) This driver is for the Adafruit TSL2561 Breakout, and is based on Adafruit's Unified Sensor Library (Adafruit_Sensor). + + + The driver supports manual or 'auto' gain. Adjusting the gain allows you to make the sensor more or less 'sensitive' to light (depending on if you are indoors or outdoors, for example): ``` tsl.setGain(TSL2561_GAIN_1X); /* No gain ... use in bright light to avoid sensor saturation */ @@ -9,7 +12,7 @@ tsl.setGain(TSL2561_GAIN_16X); /* 16x gain ... use in low light to boost sen tsl.enableAutoGain(true); /* Auto-gain ... switches automatically between 1x and 16x */ ``` -The driver also supports as automatic clipping detection, and will return '0' lux when the sensor is saturated and data is unreliable. +The driver also supports as automatic clipping detection, and will return '65536' lux when the sensor is saturated and data is unreliable. tsl.getEvent will return false in case of saturation and true in case of valid light data. ## About the TSL2561 ## @@ -44,4 +47,4 @@ Light sensors will always report units in lux, gyroscopes will always report uni Adafruit invests time and resources providing this open source code. Please support Adafruit and open-source hardware by purchasing products from Adafruit! -Written by Kevin (KTOWN) Townsend for Adafruit Industries. \ No newline at end of file +Written by Kevin (KTOWN) Townsend for Adafruit Industries. diff --git a/lib/Adafruit_TSL2561/examples/sensorapi/sensorapi.pde b/lib/Adafruit_TSL2561/examples/sensorapi/sensorapi.ino similarity index 94% rename from lib/Adafruit_TSL2561/examples/sensorapi/sensorapi.pde rename to lib/Adafruit_TSL2561/examples/sensorapi/sensorapi.ino index cacf9a7f..665d579e 100644 --- a/lib/Adafruit_TSL2561/examples/sensorapi/sensorapi.pde +++ b/lib/Adafruit_TSL2561/examples/sensorapi/sensorapi.ino @@ -16,9 +16,9 @@ Connections =========== - Connect SCL to analog 5 - Connect SDA to analog 4 - Connect VDD to 3.3V DC + Connect SCL to I2C SCL Clock + Connect SDA to I2C SDA Data + Connect VDD to 3.3V or 5V (whatever your logic level is) Connect GROUND to common ground I2C Address @@ -94,9 +94,11 @@ void setup(void) Serial.println("Light Sensor Test"); Serial.println(""); /* Initialise the sensor */ + //use tsl.begin() to default to Wire, + //tsl.begin(&Wire2) directs api to use Wire2, etc. if(!tsl.begin()) { - /* There was a problem detecting the ADXL345 ... check your connections */ + /* There was a problem detecting the TSL2561 ... check your connections */ Serial.print("Ooops, no TSL2561 detected ... Check your wiring or I2C ADDR!"); while(1); } diff --git a/lib/Adafruit_TSL2561/library.properties b/lib/Adafruit_TSL2561/library.properties index 45b50919..7656b9da 100644 --- a/lib/Adafruit_TSL2561/library.properties +++ b/lib/Adafruit_TSL2561/library.properties @@ -1,5 +1,5 @@ name=Adafruit TSL2561 -version=1.0.0 +version=1.0.2 author=Adafruit maintainer=Adafruit sentence=Unified sensor driver for Adafruit's TSL2561 breakouts diff --git a/lib/Adafruit_TSL2561/pgmspace.h b/lib/Adafruit_TSL2561/pgmspace.h deleted file mode 100644 index c4fb2e4d..00000000 --- a/lib/Adafruit_TSL2561/pgmspace.h +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************/ -/*! - @file pgmspace.h - @author Mike Roberts - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, Mike Roberts - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -/**************************************************************************/ - -#ifndef delorean_pgmspace_h -#define delorean_pgmspace_h - -#include - -#define PROGMEM -#define PGM_P const char * -#define PSTR(str) (str) - -typedef void prog_void; -typedef char prog_char; -typedef unsigned char prog_uchar; -typedef int8_t prog_int8_t; -typedef uint8_t prog_uint8_t; -typedef int16_t prog_int16_t; -typedef uint16_t prog_uint16_t; -typedef int32_t prog_int32_t; -typedef uint32_t prog_uint32_t; - -#define strcpy_P(dest, src) strcpy((dest), (src)) -#define strcat_P(dest, src) strcat((dest), (src)) -#define strcmp_P(a, b) strcmp((a), (b)) - -#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) -#define pgm_read_word(addr) (*(const unsigned short *)(addr)) -#define pgm_read_dword(addr) (*(const unsigned long *)(addr)) -#define pgm_read_float(addr) (*(const float *)(addr)) - -#define pgm_read_byte_near(addr) pgm_read_byte(addr) -#define pgm_read_word_near(addr) pgm_read_word(addr) -#define pgm_read_dword_near(addr) pgm_read_dword(addr) -#define pgm_read_float_near(addr) pgm_read_float(addr) -#define pgm_read_byte_far(addr) pgm_read_byte(addr) -#define pgm_read_word_far(addr) pgm_read_word(addr) -#define pgm_read_dword_far(addr) pgm_read_dword(addr) -#define pgm_read_float_far(addr) pgm_read_float(addr) - -#endif diff --git a/lib/ArduinoJson/.clang-format b/lib/ArduinoJson/.clang-format deleted file mode 100644 index 36809363..00000000 --- a/lib/ArduinoJson/.clang-format +++ /dev/null @@ -1,5 +0,0 @@ -# http://clang.llvm.org/docs/ClangFormatStyleOptions.html - -BasedOnStyle: Google -Standard: Cpp03 -AllowShortFunctionsOnASingleLine: Empty diff --git a/lib/ArduinoJson/.gitattributes b/lib/ArduinoJson/.gitattributes deleted file mode 100644 index 526c8a38..00000000 --- a/lib/ArduinoJson/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.sh text eol=lf \ No newline at end of file diff --git a/lib/ArduinoJson/.gitignore b/lib/ArduinoJson/.gitignore deleted file mode 100644 index 567dc13b..00000000 --- a/lib/ArduinoJson/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -.DS_Store -/.idea -/build -/bin -/lib -/sftp-config.json -.tags -.tags_sorted_by_file -/fuzzing/*_fuzzer -/fuzzing/*_fuzzer.options -/fuzzing/*_fuzzer_seed_corpus.zip diff --git a/lib/ArduinoJson/.mbedignore b/lib/ArduinoJson/.mbedignore deleted file mode 100644 index b52329d1..00000000 --- a/lib/ArduinoJson/.mbedignore +++ /dev/null @@ -1,6 +0,0 @@ -.github/ -examples/ -fuzzing/ -scripts/ -test/ -third-party/ diff --git a/lib/ArduinoJson/.travis.yml b/lib/ArduinoJson/.travis.yml deleted file mode 100644 index 9a9dddcd..00000000 --- a/lib/ArduinoJson/.travis.yml +++ /dev/null @@ -1,96 +0,0 @@ -sudo: false -language: cpp -matrix: - include: - - compiler: gcc - addons: - apt: - sources: ['ubuntu-toolchain-r-test'] - packages: ['g++-4.4'] - env: SCRIPT=cmake GCC=4.4 - - compiler: gcc - addons: - apt: - sources: ['ubuntu-toolchain-r-test'] - packages: ['g++-4.6'] - env: SCRIPT=cmake GCC=4.6 - - compiler: gcc - addons: - apt: - sources: ['ubuntu-toolchain-r-test'] - packages: ['g++-4.7'] - env: SCRIPT=cmake GCC=4.7 - - compiler: gcc - addons: - apt: - sources: ['ubuntu-toolchain-r-test'] - packages: ['g++-4.8'] - env: SCRIPT=cmake GCC=4.8 SANITIZE=address - - compiler: gcc - addons: - apt: - sources: ['ubuntu-toolchain-r-test'] - packages: ['g++-4.9'] - env: SCRIPT=cmake GCC=4.9 SANITIZE=leak - - compiler: gcc - addons: - apt: - sources: ['ubuntu-toolchain-r-test'] - packages: ['g++-5'] - env: SCRIPT=cmake GCC=5 SANITIZE=undefined - - compiler: gcc - addons: - apt: - sources: ['ubuntu-toolchain-r-test'] - packages: ['g++-6'] - env: SCRIPT=cmake GCC=6 - - compiler: gcc - addons: - apt: - sources: ['ubuntu-toolchain-r-test'] - packages: ['g++-7'] - env: SCRIPT=cmake GCC=7 - - compiler: clang - env: SCRIPT=cmake - - compiler: clang - addons: - apt: - sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5'] - packages: ['clang-3.5'] - env: SCRIPT=cmake CLANG=3.5 SANITIZE=address - - compiler: clang - addons: - apt: - sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.6'] - packages: ['clang-3.6'] - env: SCRIPT=cmake CLANG=3.6 SANITIZE=leak - - compiler: clang - addons: - apt: - sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.7'] - packages: ['clang-3.7'] - env: SCRIPT=cmake CLANG=3.7 - - compiler: clang - addons: - apt: - sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.8'] - packages: ['clang-3.8'] - env: SCRIPT=cmake CLANG=3.8 SANITIZE=undefined - - compiler: gcc - env: SCRIPT=coverage - - os: osx - osx_image: xcode6.4 - compiler: clang - env: SCRIPT=cmake - - os: osx - osx_image: xcode7.3 - compiler: clang - env: SCRIPT=cmake SANITIZE=address - - env: SCRIPT=arduino VERSION=1.6.7 BOARD=arduino:avr:uno - - env: SCRIPT=arduino VERSION=1.8.2 BOARD=arduino:avr:uno - - env: SCRIPT=platformio BOARD=uno - - env: SCRIPT=platformio BOARD=esp01 -cache: - directories: - - "~/.platformio" -script: scripts/travis/$SCRIPT.sh diff --git a/lib/ArduinoJson/CHANGELOG.md b/lib/ArduinoJson/CHANGELOG.md index 1924bd24..dc5206f0 100644 --- a/lib/ArduinoJson/CHANGELOG.md +++ b/lib/ArduinoJson/CHANGELOG.md @@ -1,6 +1,21 @@ ArduinoJson: change log ======================= +v5.13.3 +------- + +* Improved float serialization when `-fsingle-precision-constant` is used +* Fixed `JsonVariant::is()` that returned true for empty strings +* Fixed `JsonVariant::is()` (closes #763) + +v5.13.2 +------- + +* Fixed `JsonBuffer::parse()` not respecting nesting limit correctly (issue #693) +* Fixed inconsistencies in nesting level counting (PR #695 from Zhenyu Wu) +* Fixed null values that could be pass to `strcmp()` (PR #745 from Mike Karlesky) +* Added macros `ARDUINOJSON_VERSION`, `ARDUINOJSON_VERSION_MAJOR`... + v5.13.1 ------- diff --git a/lib/ArduinoJson/CMakeLists.txt b/lib/ArduinoJson/CMakeLists.txt deleted file mode 100644 index 66c565b5..00000000 --- a/lib/ArduinoJson/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -# ArduinoJson - arduinojson.org -# Copyright Benoit Blanchon 2014-2018 -# MIT License - -cmake_minimum_required(VERSION 3.0) -project(ArduinoJson) - -enable_testing() - -if(${COVERAGE}) - set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") -endif() - -include_directories(${CMAKE_CURRENT_LIST_DIR}/src) -add_subdirectory(third-party/catch) -add_subdirectory(test) diff --git a/lib/ArduinoJson/CONTRIBUTING.md b/lib/ArduinoJson/CONTRIBUTING.md deleted file mode 100644 index 5d4b96cf..00000000 --- a/lib/ArduinoJson/CONTRIBUTING.md +++ /dev/null @@ -1,11 +0,0 @@ -# Contribution to ArduinoJson - -First, thank you for taking the time to contribute to this project. - -You can submit changes via GitHub Pull Requests. - -Please: - -1. Unit test every change in behavior -2. Use clang-format in "file" mode to format the code -3. Consider using the Continuous Integration (Travis and AppVeyor) diff --git a/lib/ArduinoJson/SUPPORT.md b/lib/ArduinoJson/SUPPORT.md deleted file mode 100644 index c47e1b1b..00000000 --- a/lib/ArduinoJson/SUPPORT.md +++ /dev/null @@ -1,27 +0,0 @@ -# ArduinoJson Support - -First off, thank you very much for using ArduinoJson. - -We'll be very happy to help you, but first please read the following. - -## Before asking for help - -1. Read the [FAQ](https://arduinojson.org/faq/?utm_source=github&utm_medium=support) -2. Search in the [API Reference](https://arduinojson.org/api/?utm_source=github&utm_medium=support) - -If you did not find the answer, please create a [new issue on GitHub](https://github.com/bblanchon/ArduinoJson/issues/new). - -It is OK to add a comment to a currently opened issue, but please avoid adding comments to a closed issue. - -## Before hitting the Submit button - -Please provide all the relevant information: - -* Good title -* Short description of the problem -* Target platform -* Compiler model and version -* [MVCE](https://stackoverflow.com/help/mcve) -* Compiler output - -Good questions get fast answers! diff --git a/lib/ArduinoJson/appveyor.yml b/lib/ArduinoJson/appveyor.yml deleted file mode 100644 index f5d79b18..00000000 --- a/lib/ArduinoJson/appveyor.yml +++ /dev/null @@ -1,20 +0,0 @@ -version: 5.13.1.{build} -environment: - matrix: - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - CMAKE_GENERATOR: Visual Studio 15 2017 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - CMAKE_GENERATOR: Visual Studio 14 2015 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - CMAKE_GENERATOR: Visual Studio 12 2013 - - CMAKE_GENERATOR: Visual Studio 11 2012 - - CMAKE_GENERATOR: Visual Studio 10 2010 - - CMAKE_GENERATOR: MinGW Makefiles -configuration: Debug -before_build: -- set PATH=C:\MinGW\bin;%PATH:C:\Program Files\Git\usr\bin;=% # Workaround for CMake not wanting sh.exe on PATH for MinGW -- cmake -DCMAKE_BUILD_TYPE=%CONFIGURATION% -G "%CMAKE_GENERATOR%" . -build_script: -- cmake --build . --config %CONFIGURATION% -test_script: -- ctest --output-on-failure . diff --git a/lib/ArduinoJson/banner.svg b/lib/ArduinoJson/banner.svg deleted file mode 100644 index 51760962..00000000 --- a/lib/ArduinoJson/banner.svg +++ /dev/null @@ -1,367 +0,0 @@ - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/ArduinoJson/examples/JsonConfigFile/JsonConfigFile.ino b/lib/ArduinoJson/examples/JsonConfigFile/JsonConfigFile.ino index ce6dca3e..2ccf7d67 100644 --- a/lib/ArduinoJson/examples/JsonConfigFile/JsonConfigFile.ino +++ b/lib/ArduinoJson/examples/JsonConfigFile/JsonConfigFile.ino @@ -133,12 +133,12 @@ void loop() { // See also // -------- // -// The website arduinojson.org contains the documentation for all the functions +// https://arduinojson.org/ contains the documentation for all the functions // used above. It also includes an FAQ that will help you solve any // serialization or deserialization problem. -// Please check it out at: https://arduinojson.org/ // // The book "Mastering ArduinoJson" contains a case study of a project that has // a complex configuration with nested members. // Contrary to this example, the project in the book uses the SPIFFS filesystem. -// Please check it out at: https://arduinojson.org/book/ \ No newline at end of file +// Learn more at https://arduinojson.org/book/ +// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤ diff --git a/lib/ArduinoJson/examples/JsonGeneratorExample/JsonGeneratorExample.ino b/lib/ArduinoJson/examples/JsonGeneratorExample/JsonGeneratorExample.ino index d9efaba1..7b38227b 100644 --- a/lib/ArduinoJson/examples/JsonGeneratorExample/JsonGeneratorExample.ino +++ b/lib/ArduinoJson/examples/JsonGeneratorExample/JsonGeneratorExample.ino @@ -70,12 +70,12 @@ void loop() { // See also // -------- // -// The website arduinojson.org contains the documentation for all the functions +// https://arduinojson.org/ contains the documentation for all the functions // used above. It also includes an FAQ that will help you solve any // serialization problem. -// Please check it out at: https://arduinojson.org/ // // The book "Mastering ArduinoJson" contains a tutorial on serialization. // It begins with a simple example, like the one above, and then adds more // features like serializing directly to a file or an HTTP request. -// Please check it out at: https://arduinojson.org/book/ \ No newline at end of file +// Learn more at https://arduinojson.org/book/ +// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤ diff --git a/lib/ArduinoJson/examples/JsonHttpClient/JsonHttpClient.ino b/lib/ArduinoJson/examples/JsonHttpClient/JsonHttpClient.ino index 6e5c05ef..4ce1c20d 100644 --- a/lib/ArduinoJson/examples/JsonHttpClient/JsonHttpClient.ino +++ b/lib/ArduinoJson/examples/JsonHttpClient/JsonHttpClient.ino @@ -100,13 +100,13 @@ void loop() { // See also // -------- // -// The website arduinojson.org contains the documentation for all the functions +// https://arduinojson.org/ contains the documentation for all the functions // used above. It also includes an FAQ that will help you solve any // serialization problem. -// Please check it out at: https://arduinojson.org/ // // The book "Mastering ArduinoJson" contains a tutorial on deserialization // showing how to parse the response from Yahoo Weather. In the last chapter, // it shows how to parse the huge documents from OpenWeatherMap // and Weather Underground. -// Please check it out at: https://arduinojson.org/book/ \ No newline at end of file +// Learn more at https://arduinojson.org/book/ +// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤ diff --git a/lib/ArduinoJson/examples/JsonParserExample/JsonParserExample.ino b/lib/ArduinoJson/examples/JsonParserExample/JsonParserExample.ino index 0c771ab0..6c16211b 100644 --- a/lib/ArduinoJson/examples/JsonParserExample/JsonParserExample.ino +++ b/lib/ArduinoJson/examples/JsonParserExample/JsonParserExample.ino @@ -67,12 +67,12 @@ void loop() { // See also // -------- // -// The website arduinojson.org contains the documentation for all the functions +// https://arduinojson.org/ contains the documentation for all the functions // used above. It also includes an FAQ that will help you solve any // deserialization problem. -// Please check it out at: https://arduinojson.org/ // // The book "Mastering ArduinoJson" contains a tutorial on deserialization. // It begins with a simple example, like the one above, and then adds more // features like deserializing directly from a file or an HTTP request. -// Please check it out at: https://arduinojson.org/book/ \ No newline at end of file +// Learn more at https://arduinojson.org/book/ +// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤ diff --git a/lib/ArduinoJson/examples/JsonServer/JsonServer.ino b/lib/ArduinoJson/examples/JsonServer/JsonServer.ino index 229e289a..e693ae17 100644 --- a/lib/ArduinoJson/examples/JsonServer/JsonServer.ino +++ b/lib/ArduinoJson/examples/JsonServer/JsonServer.ino @@ -98,12 +98,12 @@ void loop() { // See also // -------- // -// The website arduinojson.org contains the documentation for all the functions +// https://arduinojson.org/ contains the documentation for all the functions // used above. It also includes an FAQ that will help you solve any // serialization problem. -// Please check it out at: https://arduinojson.org/ // // The book "Mastering ArduinoJson" contains a tutorial on serialization. // It begins with a simple example, then adds more features like serializing // directly to a file or an HTTP client. -// Please check it out at: https://arduinojson.org/book/ \ No newline at end of file +// Learn more at https://arduinojson.org/book/ +// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤ diff --git a/lib/ArduinoJson/examples/JsonUdpBeacon/JsonUdpBeacon.ino b/lib/ArduinoJson/examples/JsonUdpBeacon/JsonUdpBeacon.ino index eb9f19a6..b2328a62 100644 --- a/lib/ArduinoJson/examples/JsonUdpBeacon/JsonUdpBeacon.ino +++ b/lib/ArduinoJson/examples/JsonUdpBeacon/JsonUdpBeacon.ino @@ -90,12 +90,12 @@ void loop() { // See also // -------- // -// The website arduinojson.org contains the documentation for all the functions +// https://arduinojson.org/ contains the documentation for all the functions // used above. It also includes an FAQ that will help you solve any // serialization problem. -// Please check it out at: https://arduinojson.org/ // // The book "Mastering ArduinoJson" contains a tutorial on serialization. // It begins with a simple example, then adds more features like serializing // directly to a file or any stream. -// Please check it out at: https://arduinojson.org/book/ \ No newline at end of file +// Learn more at https://arduinojson.org/book/ +// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤ diff --git a/lib/ArduinoJson/examples/ProgmemExample/ProgmemExample.ino b/lib/ArduinoJson/examples/ProgmemExample/ProgmemExample.ino index 15be8ed1..ddde8fd1 100644 --- a/lib/ArduinoJson/examples/ProgmemExample/ProgmemExample.ino +++ b/lib/ArduinoJson/examples/ProgmemExample/ProgmemExample.ino @@ -59,12 +59,12 @@ void loop() { // See also // -------- // -// The website arduinojson.org contains the documentation for all the functions +// https://arduinojson.org/ contains the documentation for all the functions // used above. It also includes an FAQ that will help you solve any memory // problem. -// Please check it out at: https://arduinojson.org/ // // The book "Mastering ArduinoJson" contains a quick C++ course that explains // how your microcontroller stores strings in memory. It also tells why you // should not abuse Flash strings with ArduinoJson. -// Please check it out at: https://arduinojson.org/book/ \ No newline at end of file +// Learn more at https://arduinojson.org/book/ +// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤ diff --git a/lib/ArduinoJson/examples/StringExample/StringExample.ino b/lib/ArduinoJson/examples/StringExample/StringExample.ino index d5994ffb..fc7503d0 100644 --- a/lib/ArduinoJson/examples/StringExample/StringExample.ino +++ b/lib/ArduinoJson/examples/StringExample/StringExample.ino @@ -64,11 +64,11 @@ void loop() { // See also // -------- // -// The website arduinojson.org contains the documentation for all the functions +// https://arduinojson.org/ contains the documentation for all the functions // used above. It also includes an FAQ that will help you solve any problem. -// Please check it out at: https://arduinojson.org/ // // The book "Mastering ArduinoJson" contains a quick C++ course that explains // how your microcontroller stores strings in memory. On several occasions, it // shows how you can avoid String in your program. -// Please check it out at: https://arduinojson.org/book/ \ No newline at end of file +// Learn more at https://arduinojson.org/book/ +// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤ diff --git a/lib/ArduinoJson/fuzzing/Makefile b/lib/ArduinoJson/fuzzing/Makefile deleted file mode 100644 index f3ed397f..00000000 --- a/lib/ArduinoJson/fuzzing/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# CAUTION: this file is invoked by https://github.com/google/oss-fuzz - -CXXFLAGS += -I../src - -all: \ - $(OUT)/json_fuzzer \ - $(OUT)/json_fuzzer_seed_corpus.zip \ - $(OUT)/json_fuzzer.options - -$(OUT)/json_fuzzer: fuzzer.cpp $(shell find ../src -type f) - $(CXX) $(CXXFLAGS) $< -o$@ $(LIB_FUZZING_ENGINE) - -$(OUT)/json_fuzzer_seed_corpus.zip: seed_corpus/* - zip -j $@ $? - -$(OUT)/json_fuzzer.options: - @echo "[libfuzzer]" > $@ - @echo "max_len = 256" >> $@ - @echo "timeout = 10" >> $@ diff --git a/lib/ArduinoJson/fuzzing/fuzz.sh b/lib/ArduinoJson/fuzzing/fuzz.sh deleted file mode 100644 index e9f28c39..00000000 --- a/lib/ArduinoJson/fuzzing/fuzz.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -# This script mimics an invocation from https://github.com/google/oss-fuzz - -cd $(dirname $0) -export CXX='clang++' -export CXXFLAGS='-fsanitize-coverage=trace-pc-guard -fsanitize=address' -export LIB_FUZZING_ENGINE=-lFuzzer -make OUT=. -./json_fuzzer my_corpus seed_corpus -max_len=1024 -timeout=10 diff --git a/lib/ArduinoJson/fuzzing/fuzzer.cpp b/lib/ArduinoJson/fuzzing/fuzzer.cpp deleted file mode 100644 index 24b2f191..00000000 --- a/lib/ArduinoJson/fuzzing/fuzzer.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include - -class memstream : public std::istream { - struct membuf : std::streambuf { - membuf(const uint8_t *p, size_t l) { - setg((char *)p, (char *)p, (char *)p + l); - } - }; - membuf _buffer; - - public: - memstream(const uint8_t *p, size_t l) - : std::istream(&_buffer), _buffer(p, l) { - rdbuf(&_buffer); - } -}; - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - DynamicJsonBuffer jsonBuffer; - memstream json(data, size); - JsonVariant variant = jsonBuffer.parse(json); - if (variant.success()) { - variant.as(); // <- serialize to JSON - } - return 0; -} diff --git a/lib/ArduinoJson/fuzzing/my_corpus/.gitignore b/lib/ArduinoJson/fuzzing/my_corpus/.gitignore deleted file mode 100644 index d6b7ef32..00000000 --- a/lib/ArduinoJson/fuzzing/my_corpus/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/lib/ArduinoJson/fuzzing/seed_corpus/Comments.json b/lib/ArduinoJson/fuzzing/seed_corpus/Comments.json deleted file mode 100644 index bcc4cece..00000000 --- a/lib/ArduinoJson/fuzzing/seed_corpus/Comments.json +++ /dev/null @@ -1,10 +0,0 @@ -//comment -/*comment*/ -[ //comment -/*comment*/"comment"/*comment*/,//comment -/*comment*/{//comment -/* comment*/"key"//comment -: //comment -"value"//comment -}/*comment*/ -]//comment \ No newline at end of file diff --git a/lib/ArduinoJson/fuzzing/seed_corpus/EmptyArray.json b/lib/ArduinoJson/fuzzing/seed_corpus/EmptyArray.json deleted file mode 100644 index 0637a088..00000000 --- a/lib/ArduinoJson/fuzzing/seed_corpus/EmptyArray.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/lib/ArduinoJson/fuzzing/seed_corpus/EmptyObject.json b/lib/ArduinoJson/fuzzing/seed_corpus/EmptyObject.json deleted file mode 100644 index 9e26dfee..00000000 --- a/lib/ArduinoJson/fuzzing/seed_corpus/EmptyObject.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/lib/ArduinoJson/fuzzing/seed_corpus/ExcessiveNesting.json b/lib/ArduinoJson/fuzzing/seed_corpus/ExcessiveNesting.json deleted file mode 100644 index 9285019a..00000000 --- a/lib/ArduinoJson/fuzzing/seed_corpus/ExcessiveNesting.json +++ /dev/null @@ -1 +0,0 @@ -[1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,[14,[15,[16,[17,[18,[19,[20,[21,[22,[23,[24,[25,[26,[27,[28,[29,[30,[31,[32,[33,[34,[35,[36,[37,[38,[39,[40,[41,[42,[43,[44,[45,[46,[47,[48,[49,[50,[51,[52,[53,[54,[55,[56,[57,[58,[59,[60,[61,[62,[63,[64,[65,[66,[67,[68,[69,[70,[71,[72,[73,[74,[75,[76,[77,[78,[79,[80,[81,[82,[83,[84,[85,[86,[87,[88,[89,[90,[91,[92,[93,[94,[95,[96,[97,[98,[99,[100,[101,[102,[103,[104,[105,[106,[107,[108,[109,[110,[111,[112,[113,[114,[115,[116,[117,[118,[119,[120]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] \ No newline at end of file diff --git a/lib/ArduinoJson/fuzzing/seed_corpus/Numbers.json b/lib/ArduinoJson/fuzzing/seed_corpus/Numbers.json deleted file mode 100644 index f6b94194..00000000 --- a/lib/ArduinoJson/fuzzing/seed_corpus/Numbers.json +++ /dev/null @@ -1,24 +0,0 @@ -[ - 123, - -123, - 123.456, - -123.456, - 12e34, - 12e-34, - 12e+34, - 12E34, - 12E-34, - 12E+34, - 12.34e56, - 12.34e-56, - 12.34e+56, - 12.34E56, - 12.34E-56, - 12.34E+56, - NaN, - -NaN, - +NaN, - Infinity, - +Infinity, - -Infinity -] \ No newline at end of file diff --git a/lib/ArduinoJson/fuzzing/seed_corpus/OpenWeatherMap.json b/lib/ArduinoJson/fuzzing/seed_corpus/OpenWeatherMap.json deleted file mode 100644 index 27d6bafd..00000000 --- a/lib/ArduinoJson/fuzzing/seed_corpus/OpenWeatherMap.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "coord": { - "lon": -0.13, - "lat": 51.51 - }, - "weather": [ - { - "id": 301, - "main": "Drizzle", - "description": "drizzle", - "icon": "09n" - }, - { - "id": 701, - "main": "Mist", - "description": "mist", - "icon": "50n" - }, - { - "id": 741, - "main": "Fog", - "description": "fog", - "icon": "50n" - } - ], - "base": "stations", - "main": { - "temp": 281.87, - "pressure": 1032, - "humidity": 100, - "temp_min": 281.15, - "temp_max": 283.15 - }, - "visibility": 2900, - "wind": { - "speed": 1.5 - }, - "clouds": { - "all": 90 - }, - "dt": 1483820400, - "sys": { - "type": 1, - "id": 5091, - "message": 0.0226, - "country": "GB", - "sunrise": 1483776245, - "sunset": 1483805443 - }, - "id": 2643743, - "name": "London", - "cod": 200 -} diff --git a/lib/ArduinoJson/fuzzing/seed_corpus/Strings.json b/lib/ArduinoJson/fuzzing/seed_corpus/Strings.json deleted file mode 100644 index 3ffa235e..00000000 --- a/lib/ArduinoJson/fuzzing/seed_corpus/Strings.json +++ /dev/null @@ -1,8 +0,0 @@ -[ - "hello", - 'hello', - hello, - {"hello":"world"}, - {'hello':'world'}, - {hello:world} -] \ No newline at end of file diff --git a/lib/ArduinoJson/fuzzing/seed_corpus/WeatherUnderground.json b/lib/ArduinoJson/fuzzing/seed_corpus/WeatherUnderground.json deleted file mode 100644 index d53ce006..00000000 --- a/lib/ArduinoJson/fuzzing/seed_corpus/WeatherUnderground.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "response": { - "version": "0.1", - "termsofService": "http://www.wunderground.com/weather/api/d/terms.html", - "features": { - "conditions": 1 - } - }, - "current_observation": { - "image": { - "url": "http://icons-ak.wxug.com/graphics/wu2/logo_130x80.png", - "title": "Weather Underground", - "link": "http://www.wunderground.com" - }, - "display_location": { - "full": "San Francisco, CA", - "city": "San Francisco", - "state": "CA", - "state_name": "California", - "country": "US", - "country_iso3166": "US", - "zip": "94101", - "latitude": "37.77500916", - "longitude": "-122.41825867", - "elevation": "47.00000000" - }, - "observation_location": { - "full": "SOMA - Near Van Ness, San Francisco, California", - "city": "SOMA - Near Van Ness, San Francisco", - "state": "California", - "country": "US", - "country_iso3166": "US", - "latitude": "37.773285", - "longitude": "-122.417725", - "elevation": "49 ft" - }, - "estimated": {}, - "station_id": "KCASANFR58", - "observation_time": "Last Updated on June 27, 5:27 PM PDT", - "observation_time_rfc822": "Wed, 27 Jun 2012 17:27:13 -0700", - "observation_epoch": "1340843233", - "local_time_rfc822": "Wed, 27 Jun 2012 17:27:14 -0700", - "local_epoch": "1340843234", - "local_tz_short": "PDT", - "local_tz_long": "America/Los_Angeles", - "local_tz_offset": "-0700", - "weather": "Partly Cloudy", - "temperature_string": "66.3 F (19.1 C)", - "temp_f": 66.3, - "temp_c": 19.1, - "relative_humidity": "65%", - "wind_string": "From the NNW at 22.0 MPH Gusting to 28.0 MPH", - "wind_dir": "NNW", - "wind_degrees": 346, - "wind_mph": 22, - "wind_gust_mph": "28.0", - "wind_kph": 35.4, - "wind_gust_kph": "45.1", - "pressure_mb": "1013", - "pressure_in": "29.93", - "pressure_trend": "+", - "dewpoint_string": "54 F (12 C)", - "dewpoint_f": 54, - "dewpoint_c": 12, - "heat_index_string": "NA", - "heat_index_f": "NA", - "heat_index_c": "NA", - "windchill_string": "NA", - "windchill_f": "NA", - "windchill_c": "NA", - "feelslike_string": "66.3 F (19.1 C)", - "feelslike_f": "66.3", - "feelslike_c": "19.1", - "visibility_mi": "10.0", - "visibility_km": "16.1", - "solarradiation": "", - "UV": "5", - "precip_1hr_string": "0.00 in ( 0 mm)", - "precip_1hr_in": "0.00", - "precip_1hr_metric": " 0", - "precip_today_string": "0.00 in (0 mm)", - "precip_today_in": "0.00", - "precip_today_metric": "0", - "icon": "partlycloudy", - "icon_url": "http://icons-ak.wxug.com/i/c/k/partlycloudy.gif", - "forecast_url": "http://www.wunderground.com/US/CA/San_Francisco.html", - "history_url": "http://www.wunderground.com/history/airport/KCASANFR58/2012/6/27/DailyHistory.html", - "ob_url": "http://www.wunderground.com/cgi-bin/findweather/getForecast?query=37.773285,-122.417725" - } -} diff --git a/lib/ArduinoJson/library.json b/lib/ArduinoJson/library.json deleted file mode 100644 index eb790b92..00000000 --- a/lib/ArduinoJson/library.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "ArduinoJson", - "keywords": "json, rest, http, web", - "description": "An elegant and efficient JSON library for embedded systems", - "homepage": "https://arduinojson.org/?utm_source=meta&utm_medium=library.json", - "repository": { - "type": "git", - "url": "https://github.com/bblanchon/ArduinoJson.git" - }, - "version": "5.13.1", - "authors": { - "name": "Benoit Blanchon", - "url": "https://blog.benoitblanchon.fr" - }, - "exclude": [ - "fuzzing", - "scripts", - "test", - "third-party" - ], - "frameworks": "arduino", - "platforms": "*" -} diff --git a/lib/ArduinoJson/library.properties b/lib/ArduinoJson/library.properties index 97e2f03a..f9dd1dd1 100644 --- a/lib/ArduinoJson/library.properties +++ b/lib/ArduinoJson/library.properties @@ -1,5 +1,5 @@ name=ArduinoJson -version=5.13.1 +version=5.13.3 author=Benoit Blanchon maintainer=Benoit Blanchon sentence=An efficient and elegant JSON library for Arduino. diff --git a/lib/ArduinoJson/scripts/build-arduino-package.sh b/lib/ArduinoJson/scripts/build-arduino-package.sh deleted file mode 100644 index 6976bcd3..00000000 --- a/lib/ArduinoJson/scripts/build-arduino-package.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -TAG=$(git describe) -OUTPUT="ArduinoJson-$TAG.zip" - -cd $(dirname $0)/../.. - -# remove existing file -rm -f $OUTPUT - -# create zip -7z a $OUTPUT \ - ArduinoJson/CHANGELOG.md \ - ArduinoJson/examples \ - ArduinoJson/src \ - ArduinoJson/keywords.txt \ - ArduinoJson/library.properties \ - ArduinoJson/LICENSE.md \ - ArduinoJson/README.md \ - ArduinoJson/ArduinoJson.h diff --git a/lib/ArduinoJson/scripts/build-single-header.sh b/lib/ArduinoJson/scripts/build-single-header.sh deleted file mode 100644 index b09e91f6..00000000 --- a/lib/ArduinoJson/scripts/build-single-header.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash - -TAG=$(git describe) -RE_INCLUDE='^#include[[:space:]]*["<](.*)[">]' -RE_EMPTY='^(#pragma[[:space:]]+once)?[[:space:]]*(//.*)?$' - -declare -A INCLUDED - -process() -{ - local PARENT=$1 - local FOLDER=$(dirname $1) - local SHOW_COMMENT=$2 - while IFS= read -r LINE; do - if [[ $LINE =~ $RE_INCLUDE ]]; then - local CHILD=${BASH_REMATCH[1]} - pushd "$FOLDER" > /dev/null - if [[ -e $CHILD ]]; then - local CHILD_PATH=$(realpath $CHILD) - if [[ ! ${INCLUDED[$CHILD_PATH]} ]]; then - #echo "// $PARENT -> $CHILD" - INCLUDED[$CHILD_PATH]=true - process "$CHILD" false - fi - else - if [[ ! ${INCLUDED[$CHILD]} ]]; then - echo "$LINE" - INCLUDED[$CHILD]=true - fi - fi - popd > /dev/null - elif [[ "${SHOW_COMMENT}" = "true" ]] ; then - echo "$LINE" - elif [[ ! $LINE =~ $RE_EMPTY ]]; then - echo "$LINE" - fi - done < $PARENT -} - -cd $(dirname $0)/../ -INCLUDED=() -process src/ArduinoJson.h true > ../ArduinoJson-$TAG.h -g++ -x c++ -c -o ../smoketest.o - < ../ArduinoJson-$TAG.hpp -g++ -x c++ -c -o ../smoketest.o - < $OUTPUT - -cd $(dirname $(dirname $0)) - -git tag | while read TAG -do - - git checkout -q tags/$TAG - - DATE=$(git log -1 --date=short --pretty=format:%cd) - PARSER_SIZE=$(arduino --verify examples/JsonParserExample/JsonParserExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/') - - if [ -e 'examples/JsonGeneratorExample/JsonGeneratorExample.ino' ]; then - GENERATOR_SIZE=$(arduino --verify examples/JsonGeneratorExample/JsonGeneratorExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/') - else - GENERATOR_SIZE="" - fi - - echo $TAG - if [ ! -z "$PARSER_SIZE" ] - then - echo "JsonParserExample = $PARSER_SIZE bytes" - else - echo "JsonParserExample compilation failed." - fi - - if [ ! -z "$GENERATOR_SIZE" ] - then - echo "JsonGeneratorExample = $GENERATOR_SIZE bytes" - else - echo "JsonGeneratorExample compilation failed." - fi - - echo "$TAG;$DATE;$PARSER_SIZE;$GENERATOR_SIZE" >> $OUTPUT - -done diff --git a/lib/ArduinoJson/scripts/oss-fuzz/.gitignore b/lib/ArduinoJson/scripts/oss-fuzz/.gitignore deleted file mode 100644 index d50ee772..00000000 --- a/lib/ArduinoJson/scripts/oss-fuzz/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/.vagrant/ -*.log diff --git a/lib/ArduinoJson/scripts/oss-fuzz/Vagrantfile b/lib/ArduinoJson/scripts/oss-fuzz/Vagrantfile deleted file mode 100644 index 252c191c..00000000 --- a/lib/ArduinoJson/scripts/oss-fuzz/Vagrantfile +++ /dev/null @@ -1,33 +0,0 @@ -# A virtual machine to run https://github.com/google/oss-fuzz -Vagrant.configure(2) do |config| - config.vm.box = "ubuntu/xenial64" - - config.vm.synced_folder "E:\\Git\\Arduino\\libraries\\ArduinoJson", "/host/ArduinoJson" - config.vm.synced_folder "E:\\Git\\oss-fuzz", "/host/oss-fuzz" - - config.vm.network "forwarded_port", guest: 8001, host: 8001 - - config.vm.provision "shell", privileged: false, inline: <<-SHELL - set -x - - sudo apt-get update - sudo apt-get install -y make git docker.io zip - sudo groupadd docker - sudo usermod -aG docker $USER - - git clone https://github.com/google/fuzzer-test-suite.git FTS - ./FTS/tutorial/install-deps.sh # Get deps - ./FTS/tutorial/install-clang.sh # Get fresh clang binaries - # Get libFuzzer sources and build it - svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer - Fuzzer/build.sh - sudo mv libFuzzer.a /usr/local/lib/ - - echo "export PROJECT_NAME='arduinojson'" >> $HOME/.profile - echo "export CC='clang'" >> $HOME/.profile - echo "export CXX='clang++'" >> $HOME/.profile - echo "export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/" >> $HOME/.profile - - echo "Run /host/ArduinoJson/fuzzing/fuzz.sh" | sudo tee /etc/motd - SHELL -end diff --git a/lib/ArduinoJson/scripts/travis/arduino.sh b/lib/ArduinoJson/scripts/travis/arduino.sh deleted file mode 100644 index 4de24c15..00000000 --- a/lib/ArduinoJson/scripts/travis/arduino.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -eux - -/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16 -sleep 3 -export DISPLAY=:1.0 - -mkdir -p /tmp/arduino -curl -sS http://downloads.arduino.cc/arduino-$VERSION-linux64.tar.xz | tar xJ -C /tmp/arduino --strip 1 || -curl -sS http://downloads.arduino.cc/arduino-$VERSION-linux64.tgz | tar xz -C /tmp/arduino --strip 1 -export PATH=$PATH:/tmp/arduino/ - -ln -s $PWD /tmp/arduino/libraries/ArduinoJson - -for EXAMPLE in $PWD/examples/*/*.ino; do - arduino --verify --board $BOARD $EXAMPLE -done diff --git a/lib/ArduinoJson/scripts/travis/cmake.sh b/lib/ArduinoJson/scripts/travis/cmake.sh deleted file mode 100644 index 56691d9b..00000000 --- a/lib/ArduinoJson/scripts/travis/cmake.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh -ex - -if [ $(uname) = 'Darwin' ]; then - URL=https://cmake.org/files/v3.4/cmake-3.4.3-Darwin-x86_64.tar.gz - CMAKE=/tmp/CMake.app/Contents/bin/cmake - CTEST=/tmp/CMake.app/Contents/bin/ctest -else - URL=https://cmake.org/files/v3.4/cmake-3.4.3-Linux-x86_64.tar.gz - CMAKE=/tmp/bin/cmake - CTEST=/tmp/bin/ctest -fi -curl -sS $URL | tar xz -C /tmp --strip 1 - -if [ -n "$GCC" ]; then - export CC="gcc-$GCC" - export CXX="g++-$GCC" -fi - -if [ -n "$CLANG" ]; then - export CC="clang-$CLANG" - export CXX="clang++-$CLANG" -fi - -if [ -n "$SANITIZE" ]; then - export CXXFLAGS="-fsanitize=$SANITIZE" -fi - -$CMAKE . -$CMAKE --build . -$CTEST --output-on-failure . diff --git a/lib/ArduinoJson/scripts/travis/coverage.sh b/lib/ArduinoJson/scripts/travis/coverage.sh deleted file mode 100644 index 20de1e6a..00000000 --- a/lib/ArduinoJson/scripts/travis/coverage.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -eux - -curl https://cmake.org/files/v3.4/cmake-3.4.0-Linux-x86_64.tar.gz | tar xz -C /tmp --strip 1 - -/tmp/bin/cmake -DCOVERAGE=true . -make -make test - -pip install --user cpp-coveralls 'requests[security]' -coveralls --exclude third-party --gcov-options '\-lp'; fi diff --git a/lib/ArduinoJson/scripts/travis/platformio.sh b/lib/ArduinoJson/scripts/travis/platformio.sh deleted file mode 100644 index 4bb7a4c9..00000000 --- a/lib/ArduinoJson/scripts/travis/platformio.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -eux - -pip install --user platformio - -rm -r test - -for EXAMPLE in $PWD/examples/*/*.ino; -do - platformio ci $EXAMPLE -l '.' -b $BOARD -done diff --git a/lib/ArduinoJson/src/ArduinoJson.hpp b/lib/ArduinoJson/src/ArduinoJson.hpp index 445a2c8a..c493c06a 100644 --- a/lib/ArduinoJson/src/ArduinoJson.hpp +++ b/lib/ArduinoJson/src/ArduinoJson.hpp @@ -4,6 +4,8 @@ #pragma once +#include "ArduinoJson/version.hpp" + #include "ArduinoJson/DynamicJsonBuffer.hpp" #include "ArduinoJson/JsonArray.hpp" #include "ArduinoJson/JsonObject.hpp" diff --git a/lib/ArduinoJson/src/ArduinoJson/Deserialization/JsonParser.hpp b/lib/ArduinoJson/src/ArduinoJson/Deserialization/JsonParser.hpp index c348e759..4cbaf454 100644 --- a/lib/ArduinoJson/src/ArduinoJson/Deserialization/JsonParser.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Deserialization/JsonParser.hpp @@ -44,7 +44,6 @@ class JsonParser { const char *parseString(); bool parseAnythingTo(JsonVariant *destination); - FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination); inline bool parseArrayTo(JsonVariant *destination); inline bool parseObjectTo(JsonVariant *destination); diff --git a/lib/ArduinoJson/src/ArduinoJson/Deserialization/JsonParserImpl.hpp b/lib/ArduinoJson/src/ArduinoJson/Deserialization/JsonParserImpl.hpp index 33ad42e9..50426735 100644 --- a/lib/ArduinoJson/src/ArduinoJson/Deserialization/JsonParserImpl.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Deserialization/JsonParserImpl.hpp @@ -20,17 +20,6 @@ template inline bool ArduinoJson::Internals::JsonParser::parseAnythingTo( JsonVariant *destination) { - if (_nestingLimit == 0) return false; - _nestingLimit--; - bool success = parseAnythingToUnsafe(destination); - _nestingLimit++; - return success; -} - -template -inline bool -ArduinoJson::Internals::JsonParser::parseAnythingToUnsafe( - JsonVariant *destination) { skipSpacesAndComments(_reader); switch (_reader.current()) { @@ -48,6 +37,9 @@ ArduinoJson::Internals::JsonParser::parseAnythingToUnsafe( template inline ArduinoJson::JsonArray & ArduinoJson::Internals::JsonParser::parseArray() { + if (_nestingLimit == 0) return JsonArray::invalid(); + _nestingLimit--; + // Create an empty array JsonArray &array = _buffer->createArray(); @@ -69,6 +61,7 @@ ArduinoJson::Internals::JsonParser::parseArray() { SUCCESS_EMPTY_ARRAY: SUCCES_NON_EMPTY_ARRAY: + _nestingLimit++; return array; ERROR_INVALID_VALUE: @@ -91,6 +84,9 @@ inline bool ArduinoJson::Internals::JsonParser::parseArrayTo( template inline ArduinoJson::JsonObject & ArduinoJson::Internals::JsonParser::parseObject() { + if (_nestingLimit == 0) return JsonObject::invalid(); + _nestingLimit--; + // Create an empty object JsonObject &object = _buffer->createObject(); @@ -117,6 +113,7 @@ ArduinoJson::Internals::JsonParser::parseObject() { SUCCESS_EMPTY_OBJECT: SUCCESS_NON_EMPTY_OBJECT: + _nestingLimit++; return object; ERROR_INVALID_KEY: diff --git a/lib/ArduinoJson/src/ArduinoJson/JsonObject.hpp b/lib/ArduinoJson/src/ArduinoJson/JsonObject.hpp index c03bfa51..caf698a3 100644 --- a/lib/ArduinoJson/src/ArduinoJson/JsonObject.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/JsonObject.hpp @@ -286,15 +286,21 @@ class JsonObject : public Internals::JsonPrintable, template bool set_impl(TStringRef key, TValueRef value) { + // ignore null key + if (Internals::StringTraits::is_null(key)) return false; + + // search a matching key iterator it = findKey(key); if (it == end()) { + // add the key it = Internals::List::add(); if (it == end()) return false; - bool key_ok = Internals::ValueSaver::save(_buffer, it->key, key); if (!key_ok) return false; } + + // save the value return Internals::ValueSaver::save(_buffer, it->value, value); } @@ -318,5 +324,5 @@ struct JsonVariantDefault { return JsonObject::invalid(); } }; -} -} +} // namespace Internals +} // namespace ArduinoJson diff --git a/lib/ArduinoJson/src/ArduinoJson/JsonVariant.hpp b/lib/ArduinoJson/src/ArduinoJson/JsonVariant.hpp index 8326cbe8..43c51b77 100644 --- a/lib/ArduinoJson/src/ArduinoJson/JsonVariant.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/JsonVariant.hpp @@ -274,9 +274,11 @@ class JsonVariant : public Internals::JsonVariantBase { // // bool is() const; // bool is() const; + // bool is() const; template typename Internals::EnableIf::value || - Internals::IsSame::value, + Internals::IsSame::value || + Internals::StringTraits::has_append, bool>::type is() const { return variantIsString(); @@ -352,4 +354,4 @@ DEPRECATED("Decimal places are ignored, use the double value instead") inline JsonVariant double_with_n_digits(double value, uint8_t) { return JsonVariant(value); } -} +} // namespace ArduinoJson diff --git a/lib/ArduinoJson/src/ArduinoJson/JsonVariantComparisons.hpp b/lib/ArduinoJson/src/ArduinoJson/JsonVariantComparisons.hpp index cae53372..47f9d632 100644 --- a/lib/ArduinoJson/src/ArduinoJson/JsonVariantComparisons.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/JsonVariantComparisons.hpp @@ -129,10 +129,11 @@ class JsonVariantComparisons { if (is() && right.template is()) return as() == right.template as(); if (is() && right.template is()) - return strcmp(as(), right.template as()) == 0; + return StringTraits::equals(as(), + right.template as()); return false; } }; -} -} +} // namespace Internals +} // namespace ArduinoJson diff --git a/lib/ArduinoJson/src/ArduinoJson/Polyfills/isInteger.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/isInteger.hpp index 21f16689..8049079a 100644 --- a/lib/ArduinoJson/src/ArduinoJson/Polyfills/isInteger.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Polyfills/isInteger.hpp @@ -10,10 +10,10 @@ namespace ArduinoJson { namespace Internals { inline bool isInteger(const char* s) { - if (!s) return false; + if (!s || !*s) return false; if (issign(*s)) s++; while (isdigit(*s)) s++; return *s == '\0'; } -} -} +} // namespace Internals +} // namespace ArduinoJson diff --git a/lib/ArduinoJson/src/ArduinoJson/StringTraits/CharPointer.hpp b/lib/ArduinoJson/src/ArduinoJson/StringTraits/CharPointer.hpp index a9f30f78..98896ccf 100644 --- a/lib/ArduinoJson/src/ArduinoJson/StringTraits/CharPointer.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/StringTraits/CharPointer.hpp @@ -30,7 +30,9 @@ struct CharPointerTraits { }; static bool equals(const TChar* str, const char* expected) { - return strcmp(reinterpret_cast(str), expected) == 0; + const char* actual = reinterpret_cast(str); + if (!actual || !expected) return actual == expected; + return strcmp(actual, expected) == 0; } static bool is_null(const TChar* str) { @@ -58,5 +60,5 @@ struct CharPointerTraits { template struct StringTraits::value>::type> : CharPointerTraits {}; -} -} +} // namespace Internals +} // namespace ArduinoJson diff --git a/lib/ArduinoJson/src/ArduinoJson/StringTraits/FlashString.hpp b/lib/ArduinoJson/src/ArduinoJson/StringTraits/FlashString.hpp index 95f555d2..0701b9ba 100644 --- a/lib/ArduinoJson/src/ArduinoJson/StringTraits/FlashString.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/StringTraits/FlashString.hpp @@ -31,7 +31,9 @@ struct StringTraits { }; static bool equals(const __FlashStringHelper* str, const char* expected) { - return strcmp_P(expected, (const char*)str) == 0; + const char* actual = reinterpret_cast(str); + if (!actual || !expected) return actual == expected; + return strcmp_P(expected, actual) == 0; } static bool is_null(const __FlashStringHelper* str) { @@ -53,7 +55,7 @@ struct StringTraits { static const bool has_equals = true; static const bool should_duplicate = true; }; -} -} +} // namespace Internals +} // namespace ArduinoJson #endif diff --git a/lib/ArduinoJson/src/ArduinoJson/StringTraits/StdString.hpp b/lib/ArduinoJson/src/ArduinoJson/StringTraits/StdString.hpp index 39124dac..35f4461d 100644 --- a/lib/ArduinoJson/src/ArduinoJson/StringTraits/StdString.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/StringTraits/StdString.hpp @@ -40,7 +40,10 @@ struct StdStringTraits { }; static bool equals(const TString& str, const char* expected) { - return 0 == strcmp(str.c_str(), expected); + // Arduino's String::c_str() can return NULL + const char* actual = str.c_str(); + if (!actual || !expected) return actual == expected; + return 0 == strcmp(actual, expected); } static void append(TString& str, char c) { @@ -68,7 +71,7 @@ struct StringTraits : StdStringTraits { template <> struct StringTraits : StdStringTraits {}; #endif -} -} +} // namespace Internals +} // namespace ArduinoJson #endif diff --git a/lib/ArduinoJson/src/ArduinoJson/TypeTraits/FloatTraits.hpp b/lib/ArduinoJson/src/ArduinoJson/TypeTraits/FloatTraits.hpp index 5044807a..648cc82f 100644 --- a/lib/ArduinoJson/src/ArduinoJson/TypeTraits/FloatTraits.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/TypeTraits/FloatTraits.hpp @@ -44,28 +44,46 @@ struct FloatTraits { static T positiveBinaryPowerOfTen(int index) { static T factors[] = { - 1e1, 1e2, 1e4, 1e8, 1e16, 1e32, - // workaround to support platforms with single precision literals - forge(0x4D384F03, 0xE93FF9F5), forge(0x5A827748, 0xF9301D32), - forge(0x75154FDD, 0x7F73BF3C)}; + 1e1, + 1e2, + 1e4, + 1e8, + 1e16, + forge(0x4693B8B5, 0xB5056E17), // 1e32 + forge(0x4D384F03, 0xE93FF9F5), // 1e64 + forge(0x5A827748, 0xF9301D32), // 1e128 + forge(0x75154FDD, 0x7F73BF3C) // 1e256 + }; return factors[index]; } static T negativeBinaryPowerOfTen(int index) { static T factors[] = { - 1e-1, 1e-2, 1e-4, 1e-8, 1e-16, 1e-32, - // workaround to support platforms with single precision literals - forge(0x32A50FFD, 0x44F4A73D), forge(0x255BBA08, 0xCF8C979D), - forge(0x0AC80628, 0x64AC6F43)}; + forge(0x3FB99999, 0x9999999A), // 1e-1 + forge(0x3F847AE1, 0x47AE147B), // 1e-2 + forge(0x3F1A36E2, 0xEB1C432D), // 1e-4 + forge(0x3E45798E, 0xE2308C3A), // 1e-8 + forge(0x3C9CD2B2, 0x97D889BC), // 1e-16 + forge(0x3949F623, 0xD5A8A733), // 1e-32 + forge(0x32A50FFD, 0x44F4A73D), // 1e-64 + forge(0x255BBA08, 0xCF8C979D), // 1e-128 + forge(0x0AC80628, 0x64AC6F43) // 1e-256 + }; return factors[index]; } static T negativeBinaryPowerOfTenPlusOne(int index) { static T factors[] = { - 1e0, 1e-1, 1e-3, 1e-7, 1e-15, 1e-31, - // workaround to support platforms with single precision literals - forge(0x32DA53FC, 0x9631D10D), forge(0x25915445, 0x81B7DEC2), - forge(0x0AFE07B2, 0x7DD78B14)}; + 1e0, + forge(0x3FB99999, 0x9999999A), // 1e-1 + forge(0x3F50624D, 0xD2F1A9FC), // 1e-3 + forge(0x3E7AD7F2, 0x9ABCAF48), // 1e-7 + forge(0x3CD203AF, 0x9EE75616), // 1e-15 + forge(0x398039D6, 0x65896880), // 1e-31 + forge(0x32DA53FC, 0x9631D10D), // 1e-63 + forge(0x25915445, 0x81B7DEC2), // 1e-127 + forge(0x0AFE07B2, 0x7DD78B14) // 1e-255 + }; return factors[index]; } @@ -77,6 +95,9 @@ struct FloatTraits { return forge(0x7ff00000, 0x00000000); } + // constructs a double floating point values from its binary representation + // we use this function to workaround platforms with single precision literals + // (for example, when -fsingle-precision-constant is passed to GCC) static T forge(uint32_t msb, uint32_t lsb) { union { uint64_t integerBits; diff --git a/lib/ArduinoJson/src/ArduinoJson/version.hpp b/lib/ArduinoJson/src/ArduinoJson/version.hpp new file mode 100644 index 00000000..e5fa1e2e --- /dev/null +++ b/lib/ArduinoJson/src/ArduinoJson/version.hpp @@ -0,0 +1,10 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2018 +// MIT License + +#pragma once + +#define ARDUINOJSON_VERSION "5.13.3" +#define ARDUINOJSON_VERSION_MAJOR 5 +#define ARDUINOJSON_VERSION_MINOR 13 +#define ARDUINOJSON_VERSION_REVISION 3 diff --git a/lib/ArduinoJson/test/CMakeLists.txt b/lib/ArduinoJson/test/CMakeLists.txt deleted file mode 100644 index 4fee0ea1..00000000 --- a/lib/ArduinoJson/test/CMakeLists.txt +++ /dev/null @@ -1,76 +0,0 @@ -# ArduinoJson - arduinojson.org -# Copyright Benoit Blanchon 2014-2018 -# MIT License - -if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options( - -pedantic - -Wall - -Wcast-align - -Wcast-qual - -Wconversion - -Wctor-dtor-privacy - -Wdisabled-optimization - -Werror - -Wextra - -Wformat=2 - -Winit-self - -Wmissing-include-dirs - -Wnon-virtual-dtor - -Wold-style-cast - -Woverloaded-virtual - -Wparentheses - -Wredundant-decls - -Wshadow - -Wsign-promo - -Wstrict-aliasing - -Wstrict-overflow=5 - -Wundef - ) - - if(NOT MINGW) - add_compile_options( - -std=c++98 - ) - endif() -endif() - -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") - add_compile_options( - -Wstrict-null-sentinel - ) - - if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.5) - add_compile_options(-Wlogical-op) # the flag exists in 4.4 but is buggy - endif() - - if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.6) - add_compile_options(-Wnoexcept) - endif() -endif() - -if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_compile_options( - -Wc++11-compat - -Wdeprecated-register - ) -endif() - -if(MSVC) - add_definitions(-D_CRT_SECURE_NO_WARNINGS) - add_compile_options( - /W4 # Set warning level - /WX # Treats all compiler warnings as errors. - ) -endif() - -add_subdirectory(DynamicJsonBuffer) -add_subdirectory(IntegrationTests) -add_subdirectory(JsonArray) -add_subdirectory(JsonBuffer) -add_subdirectory(JsonObject) -add_subdirectory(JsonVariant) -add_subdirectory(JsonWriter) -add_subdirectory(Misc) -add_subdirectory(Polyfills) -add_subdirectory(StaticJsonBuffer) \ No newline at end of file diff --git a/lib/ArduinoJson/test/DynamicJsonBuffer/CMakeLists.txt b/lib/ArduinoJson/test/DynamicJsonBuffer/CMakeLists.txt deleted file mode 100644 index 9030f376..00000000 --- a/lib/ArduinoJson/test/DynamicJsonBuffer/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# ArduinoJson - arduinojson.org -# Copyright Benoit Blanchon 2014-2018 -# MIT License - -add_executable(DynamicJsonBufferTests - alloc.cpp - createArray.cpp - createObject.cpp - no_memory.cpp - size.cpp - startString.cpp -) - -target_link_libraries(DynamicJsonBufferTests catch) -add_test(DynamicJsonBuffer DynamicJsonBufferTests) diff --git a/lib/ArduinoJson/test/DynamicJsonBuffer/alloc.cpp b/lib/ArduinoJson/test/DynamicJsonBuffer/alloc.cpp deleted file mode 100644 index c45e6866..00000000 --- a/lib/ArduinoJson/test/DynamicJsonBuffer/alloc.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include -#include - -using namespace ArduinoJson::Internals; - -static bool isAligned(void* ptr) { - const size_t mask = sizeof(void*) - 1; - size_t addr = reinterpret_cast(ptr); - return (addr & mask) == 0; -} - -std::stringstream allocatorLog; - -struct SpyingAllocator : DefaultAllocator { - void* allocate(size_t n) { - allocatorLog << "A" << (n - DynamicJsonBuffer::EmptyBlockSize); - return DefaultAllocator::allocate(n); - } - void deallocate(void* p) { - allocatorLog << "F"; - return DefaultAllocator::deallocate(p); - } -}; - -TEST_CASE("DynamicJsonBuffer::alloc()") { - SECTION("Returns different pointers") { - DynamicJsonBuffer buffer; - void* p1 = buffer.alloc(1); - void* p2 = buffer.alloc(2); - REQUIRE(p1 != p2); - } - - SECTION("Doubles allocation size when full") { - allocatorLog.str(""); - { - DynamicJsonBufferBase buffer(1); - buffer.alloc(1); - buffer.alloc(1); - } - REQUIRE(allocatorLog.str() == "A1A2FF"); - } - - SECTION("Resets allocation size after clear()") { - allocatorLog.str(""); - { - DynamicJsonBufferBase buffer(1); - buffer.alloc(1); - buffer.alloc(1); - buffer.clear(); - buffer.alloc(1); - } - REQUIRE(allocatorLog.str() == "A1A2FFA1F"); - } - - SECTION("Makes a big allocation when needed") { - allocatorLog.str(""); - { - DynamicJsonBufferBase buffer(1); - buffer.alloc(42); - } - REQUIRE(allocatorLog.str() == "A42F"); - } - - SECTION("Alignment") { - // make room for two but not three - DynamicJsonBuffer tinyBuf(2 * sizeof(void*) + 1); - - REQUIRE(isAligned(tinyBuf.alloc(1))); // this on is aligned by design - REQUIRE(isAligned(tinyBuf.alloc(1))); // this one fits in the first block - REQUIRE(isAligned(tinyBuf.alloc(1))); // this one requires a new block - } -} diff --git a/lib/ArduinoJson/test/DynamicJsonBuffer/createArray.cpp b/lib/ArduinoJson/test/DynamicJsonBuffer/createArray.cpp deleted file mode 100644 index 34ab07e9..00000000 --- a/lib/ArduinoJson/test/DynamicJsonBuffer/createArray.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("DynamicJsonBuffer::createArray()") { - DynamicJsonBuffer jsonBuffer; - JsonArray &array = jsonBuffer.createArray(); - - SECTION("GrowsWithArray") { - REQUIRE(JSON_ARRAY_SIZE(0) == jsonBuffer.size()); - - array.add("hello"); - REQUIRE(JSON_ARRAY_SIZE(1) == jsonBuffer.size()); - - array.add("world"); - REQUIRE(JSON_ARRAY_SIZE(2) == jsonBuffer.size()); - } - - SECTION("CanAdd1000Values") { - for (size_t i = 1; i <= 1000; i++) { - array.add("hello"); - REQUIRE(array.size() == i); - } - } -} diff --git a/lib/ArduinoJson/test/DynamicJsonBuffer/createObject.cpp b/lib/ArduinoJson/test/DynamicJsonBuffer/createObject.cpp deleted file mode 100644 index 2193a659..00000000 --- a/lib/ArduinoJson/test/DynamicJsonBuffer/createObject.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("DynamicJsonBuffer::createObject()") { - DynamicJsonBuffer json; - - JsonObject &obj = json.createObject(); - REQUIRE(JSON_OBJECT_SIZE(0) == json.size()); - - obj["hello"] = 1; - REQUIRE(JSON_OBJECT_SIZE(1) == json.size()); - - obj["world"] = 2; - REQUIRE(JSON_OBJECT_SIZE(2) == json.size()); - - obj["world"] = 3; // <- same key, should not grow - REQUIRE(JSON_OBJECT_SIZE(2) == json.size()); -} diff --git a/lib/ArduinoJson/test/DynamicJsonBuffer/no_memory.cpp b/lib/ArduinoJson/test/DynamicJsonBuffer/no_memory.cpp deleted file mode 100644 index 824d968c..00000000 --- a/lib/ArduinoJson/test/DynamicJsonBuffer/no_memory.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -using namespace ArduinoJson::Internals; - -struct NoMemoryAllocator { - void* allocate(size_t) { - return NULL; - } - void deallocate(void*) {} -}; - -TEST_CASE("DynamicJsonBuffer no memory") { - DynamicJsonBufferBase _jsonBuffer; - - SECTION("FixCodeCoverage") { - // call this function to fix code coverage - NoMemoryAllocator().deallocate(NULL); - } - - SECTION("createArray()") { - REQUIRE_FALSE(_jsonBuffer.createArray().success()); - } - - SECTION("createObject()") { - REQUIRE_FALSE(_jsonBuffer.createObject().success()); - } - - SECTION("parseArray()") { - char json[] = "[]"; - REQUIRE_FALSE(_jsonBuffer.parseArray(json).success()); - } - - SECTION("parseObject()") { - char json[] = "{}"; - REQUIRE_FALSE(_jsonBuffer.parseObject(json).success()); - } - - SECTION("startString()") { - DynamicJsonBufferBase::String str = - _jsonBuffer.startString(); - str.append('!'); - REQUIRE(0 == str.c_str()); - } -} diff --git a/lib/ArduinoJson/test/DynamicJsonBuffer/size.cpp b/lib/ArduinoJson/test/DynamicJsonBuffer/size.cpp deleted file mode 100644 index 8ebba424..00000000 --- a/lib/ArduinoJson/test/DynamicJsonBuffer/size.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("DynamicJsonBuffer::size()") { - DynamicJsonBuffer buffer; - - SECTION("Initial size is 0") { - REQUIRE(0 == buffer.size()); - } - - SECTION("Increases after alloc()") { - buffer.alloc(1); - REQUIRE(1U <= buffer.size()); - buffer.alloc(1); - REQUIRE(2U <= buffer.size()); - } - - SECTION("Goes back to 0 after clear()") { - buffer.alloc(1); - buffer.clear(); - REQUIRE(0 == buffer.size()); - } -} diff --git a/lib/ArduinoJson/test/DynamicJsonBuffer/startString.cpp b/lib/ArduinoJson/test/DynamicJsonBuffer/startString.cpp deleted file mode 100644 index 2e5bef7f..00000000 --- a/lib/ArduinoJson/test/DynamicJsonBuffer/startString.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("DynamicJsonBuffer::startString()") { - SECTION("WorksWhenBufferIsBigEnough") { - DynamicJsonBuffer jsonBuffer(6); - - DynamicJsonBuffer::String str = jsonBuffer.startString(); - str.append('h'); - str.append('e'); - str.append('l'); - str.append('l'); - str.append('o'); - - REQUIRE(std::string("hello") == str.c_str()); - } - - SECTION("GrowsWhenBufferIsTooSmall") { - DynamicJsonBuffer jsonBuffer(5); - - DynamicJsonBuffer::String str = jsonBuffer.startString(); - str.append('h'); - str.append('e'); - str.append('l'); - str.append('l'); - str.append('o'); - - REQUIRE(std::string("hello") == str.c_str()); - } - - SECTION("SizeIncreases") { - DynamicJsonBuffer jsonBuffer(5); - - DynamicJsonBuffer::String str = jsonBuffer.startString(); - REQUIRE(0 == jsonBuffer.size()); - - str.append('h'); - REQUIRE(1 == jsonBuffer.size()); - - str.c_str(); - REQUIRE(2 == jsonBuffer.size()); - } -} diff --git a/lib/ArduinoJson/test/IntegrationTests/CMakeLists.txt b/lib/ArduinoJson/test/IntegrationTests/CMakeLists.txt deleted file mode 100644 index 9294bbbf..00000000 --- a/lib/ArduinoJson/test/IntegrationTests/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# ArduinoJson - arduinojson.org -# Copyright Benoit Blanchon 2014-2018 -# MIT License - -add_executable(IntegrationTests - gbathree.cpp - round_trip.cpp -) - -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") - target_compile_options(IntegrationTests - PUBLIC - -fsingle-precision-constant # issue 544 - ) -endif() - -target_link_libraries(IntegrationTests catch) -add_test(IntegrationTests IntegrationTests) diff --git a/lib/ArduinoJson/test/IntegrationTests/gbathree.cpp b/lib/ArduinoJson/test/IntegrationTests/gbathree.cpp deleted file mode 100644 index 9a514425..00000000 --- a/lib/ArduinoJson/test/IntegrationTests/gbathree.cpp +++ /dev/null @@ -1,208 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("Gbathree") { - DynamicJsonBuffer _buffer; - - const JsonObject& _object = _buffer.parseObject( - "{\"protocol_name\":\"fluorescence\",\"repeats\":1,\"wait\":0," - "\"averages\":1,\"measurements\":3,\"meas2_light\":15,\"meas1_" - "baseline\":0,\"act_light\":20,\"pulsesize\":25,\"pulsedistance\":" - "10000,\"actintensity1\":50,\"actintensity2\":255,\"measintensity\":" - "255,\"calintensity\":255,\"pulses\":[50,50,50],\"act\":[2,1,2,2]," - "\"red\":[2,2,2,2],\"detectors\":[[34,34,34,34],[34,34,34,34],[34," - "34,34,34],[34,34,34,34]],\"alta\":[2,2,2,2],\"altb\":[2,2,2,2]," - "\"measlights\":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15," - "15,15]],\"measlights2\":[[15,15,15,15],[15,15,15,15],[15,15,15,15]," - "[15,15,15,15]],\"altc\":[2,2,2,2],\"altd\":[2,2,2,2]}"); - - SECTION("Success") { - REQUIRE(_object.success()); - } - - SECTION("ProtocolName") { - REQUIRE("fluorescence" == _object["protocol_name"]); - } - - SECTION("Repeats") { - REQUIRE(1 == _object["repeats"]); - } - - SECTION("Wait") { - REQUIRE(0 == _object["wait"]); - } - - SECTION("Measurements") { - REQUIRE(3 == _object["measurements"]); - } - - SECTION("Meas2_Light") { - REQUIRE(15 == _object["meas2_light"]); - } - - SECTION("Meas1_Baseline") { - REQUIRE(0 == _object["meas1_baseline"]); - } - - SECTION("Act_Light") { - REQUIRE(20 == _object["act_light"]); - } - - SECTION("Pulsesize") { - REQUIRE(25 == _object["pulsesize"]); - } - - SECTION("Pulsedistance") { - REQUIRE(10000 == _object["pulsedistance"]); - } - - SECTION("Actintensity1") { - REQUIRE(50 == _object["actintensity1"]); - } - - SECTION("Actintensity2") { - REQUIRE(255 == _object["actintensity2"]); - } - - SECTION("Measintensity") { - REQUIRE(255 == _object["measintensity"]); - } - - SECTION("Calintensity") { - REQUIRE(255 == _object["calintensity"]); - } - - SECTION("Pulses") { - // "pulses":[50,50,50] - - JsonArray& array = _object["pulses"]; - REQUIRE(array.success()); - - REQUIRE(3 == array.size()); - - for (size_t i = 0; i < 3; i++) { - REQUIRE(50 == array[i]); - } - } - - SECTION("Act") { - // "act":[2,1,2,2] - - JsonArray& array = _object["act"]; - REQUIRE(array.success()); - - REQUIRE(4 == array.size()); - REQUIRE(2 == array[0]); - REQUIRE(1 == array[1]); - REQUIRE(2 == array[2]); - REQUIRE(2 == array[3]); - } - - SECTION("Detectors") { - // "detectors":[[34,34,34,34],[34,34,34,34],[34,34,34,34],[34,34,34,34]] - - JsonArray& array = _object["detectors"]; - REQUIRE(array.success()); - REQUIRE(4 == array.size()); - - for (size_t i = 0; i < 4; i++) { - JsonArray& nestedArray = array[i]; - REQUIRE(4 == nestedArray.size()); - - for (size_t j = 0; j < 4; j++) { - REQUIRE(34 == nestedArray[j]); - } - } - } - - SECTION("Alta") { - // alta:[2,2,2,2] - - JsonArray& array = _object["alta"]; - REQUIRE(array.success()); - - REQUIRE(4 == array.size()); - - for (size_t i = 0; i < 4; i++) { - REQUIRE(2 == array[i]); - } - } - - SECTION("Altb") { - // altb:[2,2,2,2] - - JsonArray& array = _object["altb"]; - REQUIRE(array.success()); - - REQUIRE(4 == array.size()); - - for (size_t i = 0; i < 4; i++) { - REQUIRE(2 == array[i]); - } - } - - SECTION("Measlights") { - // "measlights":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]] - - JsonArray& array = _object["measlights"]; - REQUIRE(array.success()); - REQUIRE(4 == array.size()); - - for (size_t i = 0; i < 4; i++) { - JsonArray& nestedArray = array[i]; - - REQUIRE(4 == nestedArray.size()); - - for (size_t j = 0; j < 4; j++) { - REQUIRE(15 == nestedArray[j]); - } - } - } - - SECTION("Measlights2") { - // "measlights2":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]] - - JsonArray& array = _object["measlights2"]; - REQUIRE(array.success()); - REQUIRE(4 == array.size()); - - for (size_t i = 0; i < 4; i++) { - JsonArray& nestedArray = array[i]; - REQUIRE(4 == nestedArray.size()); - - for (size_t j = 0; j < 4; j++) { - REQUIRE(15 == nestedArray[j]); - } - } - } - - SECTION("Altc") { - // altc:[2,2,2,2] - - JsonArray& array = _object["altc"]; - REQUIRE(array.success()); - - REQUIRE(4 == array.size()); - - for (size_t i = 0; i < 4; i++) { - REQUIRE(2 == array[i]); - } - } - - SECTION("Altd") { - // altd:[2,2,2,2] - - JsonArray& array = _object["altd"]; - REQUIRE(array.success()); - - REQUIRE(4 == array.size()); - - for (size_t i = 0; i < 4; i++) { - REQUIRE(2 == array[i]); - } - } -} diff --git a/lib/ArduinoJson/test/IntegrationTests/round_trip.cpp b/lib/ArduinoJson/test/IntegrationTests/round_trip.cpp deleted file mode 100644 index ec8c0b0c..00000000 --- a/lib/ArduinoJson/test/IntegrationTests/round_trip.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -void check(std::string originalJson) { - DynamicJsonBuffer jb; - - std::string prettyJson; - jb.parseObject(originalJson).prettyPrintTo(prettyJson); - - std::string finalJson; - jb.parseObject(prettyJson).printTo(finalJson); - - REQUIRE(originalJson == finalJson); -} - -TEST_CASE("Round Trip: parse -> prettyPrint -> parse -> print") { - SECTION("OpenWeatherMap") { - check( - "{\"coord\":{\"lon\":145.77,\"lat\":-16.92},\"sys\":{\"type\":1,\"id\":" - "8166,\"message\":0.1222,\"country\":\"AU\",\"sunrise\":1414784325," - "\"sunset\":1414830137},\"weather\":[{\"id\":801,\"main\":\"Clouds\"," - "\"description\":\"few clouds\",\"icon\":\"02n\"}],\"base\":\"cmc " - "stations\",\"main\":{\"temp\":296.15,\"pressure\":1014,\"humidity\":" - "83,\"temp_min\":296.15,\"temp_max\":296.15},\"wind\":{\"speed\":2.22," - "\"deg\":114.501},\"clouds\":{\"all\":20},\"dt\":1414846800,\"id\":" - "2172797,\"name\":\"Cairns\",\"cod\":200}"); - } - - SECTION("YahooQueryLanguage") { - check( - "{\"query\":{\"count\":40,\"created\":\"2014-11-01T14:16:49Z\"," - "\"lang\":\"fr-FR\",\"results\":{\"item\":[{\"title\":\"Burkina army " - "backs Zida as interim leader\"},{\"title\":\"British jets intercept " - "Russian bombers\"},{\"title\":\"Doubts chip away at nation's most " - "trusted agencies\"},{\"title\":\"Cruise ship stuck off Norway, no " - "damage\"},{\"title\":\"U.S. military launches 10 air strikes in " - "Syria, Iraq\"},{\"title\":\"Blackout hits Bangladesh as line from " - "India fails\"},{\"title\":\"Burkina Faso president in Ivory Coast " - "after ouster\"},{\"title\":\"Kurds in Turkey rally to back city " - "besieged by IS\"},{\"title\":\"A majority of Scots would vote for " - "independence now:poll\"},{\"title\":\"Tunisia elections possible " - "model for region\"},{\"title\":\"Islamic State kills 85 more members " - "of Iraqi tribe\"},{\"title\":\"Iraqi officials:IS extremists line " - "up, kill 50\"},{\"title\":\"Burkina Faso army backs presidential " - "guard official to lead transition\"},{\"title\":\"Kurdish peshmerga " - "arrive with weapons in Syria's Kobani\"},{\"title\":\"Driver sought " - "in crash that killed 3 on Halloween\"},{\"title\":\"Ex-Marine arrives " - "in US after release from Mexico jail\"},{\"title\":\"UN panel " - "scrambling to finish climate report\"},{\"title\":\"Investigators, " - "Branson go to spacecraft crash site\"},{\"title\":\"Soldiers vie for " - "power after Burkina Faso president quits\"},{\"title\":\"For a man " - "without a party, turnout is big test\"},{\"title\":\"'We just had a " - "hunch':US marshals nab Eric Frein\"},{\"title\":\"Boko Haram leader " - "threatens to kill German hostage\"},{\"title\":\"Nurse free to move " - "about as restrictions eased\"},{\"title\":\"Former Burkina president " - "Compaore arrives in Ivory Coast:sources\"},{\"title\":\"Libyan port " - "rebel leader refuses to hand over oil ports to rival " - "group\"},{\"title\":\"Iraqi peshmerga fighters prepare for Syria " - "battle\"},{\"title\":\"1 Dem Senate candidate welcoming Obama's " - "help\"},{\"title\":\"Bikers cancel party after police recover " - "bar\"},{\"title\":\"New question in Texas:Can Davis survive " - "defeat?\"},{\"title\":\"Ukraine rebels to hold election, despite " - "criticism\"},{\"title\":\"Iraqi officials say Islamic State group " - "lines up, kills 50 tribesmen, women in Anbar " - "province\"},{\"title\":\"James rebounds, leads Cavaliers past " - "Bulls\"},{\"title\":\"UK warns travelers they could be terror " - "targets\"},{\"title\":\"Hello Kitty celebrates 40th " - "birthday\"},{\"title\":\"A look at people killed during space " - "missions\"},{\"title\":\"Nigeria's purported Boko Haram leader says " - "has 'married off' girls:AFP\"},{\"title\":\"Mexico orders immediate " - "release of Marine veteran\"},{\"title\":\"As election closes in, " - "Obama on center stage\"},{\"title\":\"Body of Zambian president " - "arrives home\"},{\"title\":\"South Africa arrests 2 Vietnamese for " - "poaching\"}]}}}"); - } -} diff --git a/lib/ArduinoJson/test/JsonArray/CMakeLists.txt b/lib/ArduinoJson/test/JsonArray/CMakeLists.txt deleted file mode 100644 index ec0e5206..00000000 --- a/lib/ArduinoJson/test/JsonArray/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -# ArduinoJson - arduinojson.org -# Copyright Benoit Blanchon 2014-2018 -# MIT License - -add_executable(JsonArrayTests - add.cpp - basics.cpp - copyFrom.cpp - copyTo.cpp - invalid.cpp - iterator.cpp - prettyPrintTo.cpp - printTo.cpp - remove.cpp - set.cpp - size.cpp - subscript.cpp -) - -target_link_libraries(JsonArrayTests catch) -add_test(JsonArray JsonArrayTests) diff --git a/lib/ArduinoJson/test/JsonArray/add.cpp b/lib/ArduinoJson/test/JsonArray/add.cpp deleted file mode 100644 index 2e10754e..00000000 --- a/lib/ArduinoJson/test/JsonArray/add.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("JsonArray::add()") { - DynamicJsonBuffer _jsonBuffer; - JsonArray& _array = _jsonBuffer.createArray(); - - SECTION("int") { - _array.add(123); - REQUIRE(123 == _array[0].as()); - REQUIRE(_array[0].is()); - REQUIRE(_array[0].is()); - } - - SECTION("double") { - _array.add(123.45); - REQUIRE(123.45 == _array[0].as()); - REQUIRE(_array[0].is()); - REQUIRE_FALSE(_array[0].is()); - } - - SECTION("bool") { - _array.add(true); - REQUIRE(true == _array[0].as()); - REQUIRE(_array[0].is()); - REQUIRE_FALSE(_array[0].is()); - } - - SECTION("const char*") { - const char* str = "hello"; - _array.add(str); - REQUIRE(str == _array[0].as()); - REQUIRE(_array[0].is()); - REQUIRE_FALSE(_array[0].is()); - } - - SECTION("nested array") { - JsonArray& arr = _jsonBuffer.createArray(); - - _array.add(arr); - - REQUIRE(&arr == &_array[0].as()); - REQUIRE(_array[0].is()); - REQUIRE_FALSE(_array[0].is()); - } - - SECTION("nested object") { - JsonObject& obj = _jsonBuffer.createObject(); - - _array.add(obj); - - REQUIRE(&obj == &_array[0].as()); - REQUIRE(_array[0].is()); - REQUIRE_FALSE(_array[0].is()); - } - - SECTION("array subscript") { - const char* str = "hello"; - JsonArray& arr = _jsonBuffer.createArray(); - arr.add(str); - - _array.add(arr[0]); - - REQUIRE(str == _array[0]); - } - - SECTION("object subscript") { - const char* str = "hello"; - JsonObject& obj = _jsonBuffer.createObject(); - obj["x"] = str; - - _array.add(obj["x"]); - - REQUIRE(str == _array[0]); - } - - SECTION("should not duplicate const char*") { - _array.add("world"); - const size_t expectedSize = JSON_ARRAY_SIZE(1); - REQUIRE(expectedSize == _jsonBuffer.size()); - } - - SECTION("should duplicate char*") { - _array.add(const_cast("world")); - const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; - REQUIRE(expectedSize == _jsonBuffer.size()); - } - - SECTION("should duplicate std::string") { - _array.add(std::string("world")); - const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; - REQUIRE(expectedSize == _jsonBuffer.size()); - } - - SECTION("should not duplicate RawJson(const char*)") { - _array.add(RawJson("{}")); - const size_t expectedSize = JSON_ARRAY_SIZE(1); - REQUIRE(expectedSize == _jsonBuffer.size()); - } - - SECTION("should duplicate RawJson(char*)") { - _array.add(RawJson(const_cast("{}"))); - const size_t expectedSize = JSON_ARRAY_SIZE(1) + 3; - REQUIRE(expectedSize == _jsonBuffer.size()); - } -} diff --git a/lib/ArduinoJson/test/JsonArray/basics.cpp b/lib/ArduinoJson/test/JsonArray/basics.cpp deleted file mode 100644 index eada17e2..00000000 --- a/lib/ArduinoJson/test/JsonArray/basics.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("JsonArray basics") { - DynamicJsonBuffer jb; - JsonArray& array = jb.createArray(); - - SECTION("SuccessIsTrue") { - REQUIRE(array.success()); - } - - SECTION("InitialSizeIsZero") { - REQUIRE(0U == array.size()); - } - - SECTION("CreateNestedArray") { - JsonArray& arr = array.createNestedArray(); - REQUIRE(&arr == &array[0].as()); - } - - SECTION("CreateNestedObject") { - JsonObject& obj = array.createNestedObject(); - REQUIRE(&obj == &array[0].as()); - } -} diff --git a/lib/ArduinoJson/test/JsonArray/copyFrom.cpp b/lib/ArduinoJson/test/JsonArray/copyFrom.cpp deleted file mode 100644 index 850301a7..00000000 --- a/lib/ArduinoJson/test/JsonArray/copyFrom.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("JsonArray::copyFrom()") { - SECTION("OneDimension") { - DynamicJsonBuffer jsonBuffer; - JsonArray& array = jsonBuffer.createArray(); - char json[32]; - int source[] = {1, 2, 3}; - - bool ok = array.copyFrom(source); - REQUIRE(ok); - - array.printTo(json, sizeof(json)); - REQUIRE(std::string("[1,2,3]") == json); - } - - SECTION("OneDimension_JsonBufferTooSmall") { - const size_t SIZE = JSON_ARRAY_SIZE(2); - StaticJsonBuffer jsonBuffer; - JsonArray& array = jsonBuffer.createArray(); - char json[32]; - int source[] = {1, 2, 3}; - - bool ok = array.copyFrom(source); - REQUIRE_FALSE(ok); - - array.printTo(json, sizeof(json)); - REQUIRE(std::string("[1,2]") == json); - } - - SECTION("TwoDimensions") { - DynamicJsonBuffer jsonBuffer; - JsonArray& array = jsonBuffer.createArray(); - char json[32]; - int source[][3] = {{1, 2, 3}, {4, 5, 6}}; - - bool ok = array.copyFrom(source); - REQUIRE(ok); - - array.printTo(json, sizeof(json)); - REQUIRE(std::string("[[1,2,3],[4,5,6]]") == json); - } - - SECTION("TwoDimensions_JsonBufferTooSmall") { - const size_t SIZE = - JSON_ARRAY_SIZE(2) + JSON_ARRAY_SIZE(3) + JSON_ARRAY_SIZE(2); - StaticJsonBuffer jsonBuffer; - JsonArray& array = jsonBuffer.createArray(); - char json[32]; - int source[][3] = {{1, 2, 3}, {4, 5, 6}}; - - bool ok = array.copyFrom(source); - REQUIRE_FALSE(ok); - - array.printTo(json, sizeof(json)); - REQUIRE(std::string("[[1,2,3],[4,5]]") == json); - } -} diff --git a/lib/ArduinoJson/test/JsonArray/copyTo.cpp b/lib/ArduinoJson/test/JsonArray/copyTo.cpp deleted file mode 100644 index 90150590..00000000 --- a/lib/ArduinoJson/test/JsonArray/copyTo.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("JsonArray::copyTo()") { - DynamicJsonBuffer jsonBuffer; - - SECTION("BiggerOneDimensionIntegerArray") { - char json[] = "[1,2,3]"; - JsonArray& array = jsonBuffer.parseArray(json); - - int destination[4] = {0}; - size_t result = array.copyTo(destination); - - REQUIRE(3 == result); - REQUIRE(1 == destination[0]); - REQUIRE(2 == destination[1]); - REQUIRE(3 == destination[2]); - REQUIRE(0 == destination[3]); - } - - SECTION("SmallerOneDimensionIntegerArray") { - char json[] = "[1,2,3]"; - JsonArray& array = jsonBuffer.parseArray(json); - - int destination[2] = {0}; - size_t result = array.copyTo(destination); - - REQUIRE(2 == result); - REQUIRE(1 == destination[0]); - REQUIRE(2 == destination[1]); - } - - SECTION("TwoOneDimensionIntegerArray") { - char json[] = "[[1,2],[3],[4]]"; - - JsonArray& array = jsonBuffer.parseArray(json); - - int destination[3][2] = {{0}}; - array.copyTo(destination); - - REQUIRE(1 == destination[0][0]); - REQUIRE(2 == destination[0][1]); - REQUIRE(3 == destination[1][0]); - REQUIRE(0 == destination[1][1]); - REQUIRE(4 == destination[2][0]); - REQUIRE(0 == destination[2][1]); - } -} diff --git a/lib/ArduinoJson/test/JsonArray/invalid.cpp b/lib/ArduinoJson/test/JsonArray/invalid.cpp deleted file mode 100644 index 045517ba..00000000 --- a/lib/ArduinoJson/test/JsonArray/invalid.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -using namespace Catch::Matchers; - -TEST_CASE("JsonArray::invalid()") { - SECTION("SubscriptFails") { - REQUIRE_FALSE(JsonArray::invalid()[0].success()); - } - - SECTION("AddFails") { - JsonArray& array = JsonArray::invalid(); - array.add(1); - REQUIRE(0 == array.size()); - } - - SECTION("CreateNestedArrayFails") { - REQUIRE_FALSE(JsonArray::invalid().createNestedArray().success()); - } - - SECTION("CreateNestedObjectFails") { - REQUIRE_FALSE(JsonArray::invalid().createNestedObject().success()); - } - - SECTION("PrintToWritesBrackets") { - char buffer[32]; - JsonArray::invalid().printTo(buffer, sizeof(buffer)); - REQUIRE_THAT(buffer, Equals("[]")); - } -} diff --git a/lib/ArduinoJson/test/JsonArray/iterator.cpp b/lib/ArduinoJson/test/JsonArray/iterator.cpp deleted file mode 100644 index fff81964..00000000 --- a/lib/ArduinoJson/test/JsonArray/iterator.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -template -static void run_iterator_test() { - StaticJsonBuffer jsonBuffer; - - JsonArray &array = jsonBuffer.createArray(); - array.add(12); - array.add(34); - - TIterator it = array.begin(); - TIterator end = array.end(); - - REQUIRE(end != it); - REQUIRE(12 == it->template as()); - REQUIRE(12 == static_cast(*it)); - ++it; - REQUIRE(end != it); - REQUIRE(34 == it->template as()); - REQUIRE(34 == static_cast(*it)); - ++it; - REQUIRE(end == it); -} - -TEST_CASE("JsonArray::begin()/end()") { - SECTION("Mutable") { - run_iterator_test(); - } - - SECTION("Const") { - run_iterator_test(); - } -} diff --git a/lib/ArduinoJson/test/JsonArray/prettyPrintTo.cpp b/lib/ArduinoJson/test/JsonArray/prettyPrintTo.cpp deleted file mode 100644 index fc5c526d..00000000 --- a/lib/ArduinoJson/test/JsonArray/prettyPrintTo.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -static void check(JsonArray& array, std::string expected) { - std::string actual; - size_t actualLen = array.prettyPrintTo(actual); - size_t measuredLen = array.measurePrettyLength(); - CHECK(actualLen == expected.size()); - CHECK(measuredLen == expected.size()); - REQUIRE(expected == actual); -} - -TEST_CASE("JsonArray::prettyPrintTo()") { - DynamicJsonBuffer jb; - JsonArray& array = jb.createArray(); - - SECTION("Empty") { - check(array, "[]"); - } - - SECTION("OneElement") { - array.add(1); - - check(array, - "[\r\n" - " 1\r\n" - "]"); - } - - SECTION("TwoElements") { - array.add(1); - array.add(2); - - check(array, - "[\r\n" - " 1,\r\n" - " 2\r\n" - "]"); - } - - SECTION("EmptyNestedArrays") { - array.createNestedArray(); - array.createNestedArray(); - - check(array, - "[\r\n" - " [],\r\n" - " []\r\n" - "]"); - } - - SECTION("NestedArrays") { - JsonArray& nested1 = array.createNestedArray(); - nested1.add(1); - nested1.add(2); - - JsonObject& nested2 = array.createNestedObject(); - nested2["key"] = 3; - - check(array, - "[\r\n" - " [\r\n" - " 1,\r\n" - " 2\r\n" - " ],\r\n" - " {\r\n" - " \"key\": 3\r\n" - " }\r\n" - "]"); - } -} diff --git a/lib/ArduinoJson/test/JsonArray/printTo.cpp b/lib/ArduinoJson/test/JsonArray/printTo.cpp deleted file mode 100644 index 6b7f003c..00000000 --- a/lib/ArduinoJson/test/JsonArray/printTo.cpp +++ /dev/null @@ -1,132 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -static void check(JsonArray &array, std::string expected) { - std::string actual; - size_t actualLen = array.printTo(actual); - REQUIRE(expected == actual); - REQUIRE(actualLen == expected.size()); - size_t measuredLen = array.measureLength(); - REQUIRE(measuredLen == expected.size()); -} - -TEST_CASE("JsonArray::printTo()") { - StaticJsonBuffer jb; - JsonArray &array = jb.createArray(); - - SECTION("Empty") { - check(array, "[]"); - } - - SECTION("Null") { - array.add(static_cast(0)); - - check(array, "[null]"); - } - - SECTION("OneString") { - array.add("hello"); - - check(array, "[\"hello\"]"); - } - - SECTION("TwoStrings") { - array.add("hello"); - array.add("world"); - - check(array, "[\"hello\",\"world\"]"); - } - - SECTION("OneStringOverCapacity") { - array.add("hello"); - array.add("world"); - array.add("lost"); - - check(array, "[\"hello\",\"world\"]"); - } - - SECTION("One double") { - array.add(3.1415927); - check(array, "[3.1415927]"); - } - - SECTION("OneInteger") { - array.add(1); - - check(array, "[1]"); - } - - SECTION("TwoIntegers") { - array.add(1); - array.add(2); - - check(array, "[1,2]"); - } - - SECTION("RawJson(const char*)") { - array.add(RawJson("{\"key\":\"value\"}")); - - check(array, "[{\"key\":\"value\"}]"); - } - - SECTION("RawJson(char*)") { - DynamicJsonBuffer jb2; - JsonArray &arr = jb2.createArray(); - - char tmp[] = "{\"key\":\"value\"}"; - arr.add(RawJson(tmp)); - - check(arr, "[{\"key\":\"value\"}]"); - } - - SECTION("OneIntegerOverCapacity") { - array.add(1); - array.add(2); - array.add(3); - - check(array, "[1,2]"); - } - - SECTION("OneTrue") { - array.add(true); - - check(array, "[true]"); - } - - SECTION("OneFalse") { - array.add(false); - - check(array, "[false]"); - } - - SECTION("TwoBooleans") { - array.add(false); - array.add(true); - - check(array, "[false,true]"); - } - - SECTION("OneBooleanOverCapacity") { - array.add(false); - array.add(true); - array.add(false); - - check(array, "[false,true]"); - } - - SECTION("OneEmptyNestedArray") { - array.createNestedArray(); - - check(array, "[[]]"); - } - - SECTION("OneEmptyNestedHash") { - array.createNestedObject(); - - check(array, "[{}]"); - } -} diff --git a/lib/ArduinoJson/test/JsonArray/remove.cpp b/lib/ArduinoJson/test/JsonArray/remove.cpp deleted file mode 100644 index 08935818..00000000 --- a/lib/ArduinoJson/test/JsonArray/remove.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("JsonArray::remove()") { - DynamicJsonBuffer _jsonBuffer; - JsonArray& _array = _jsonBuffer.createArray(); - _array.add(1); - _array.add(2); - _array.add(3); - - SECTION("RemoveFirstByIndex") { - _array.remove(0); - - REQUIRE(2 == _array.size()); - REQUIRE(_array[0] == 2); - REQUIRE(_array[1] == 3); - } - - SECTION("RemoveMiddleByIndex") { - _array.remove(1); - - REQUIRE(2 == _array.size()); - REQUIRE(_array[0] == 1); - REQUIRE(_array[1] == 3); - } - - SECTION("RemoveLastByIndex") { - _array.remove(2); - - REQUIRE(2 == _array.size()); - REQUIRE(_array[0] == 1); - REQUIRE(_array[1] == 2); - } - - SECTION("RemoveFirstByIterator") { - JsonArray::iterator it = _array.begin(); - _array.remove(it); - - REQUIRE(2 == _array.size()); - REQUIRE(_array[0] == 2); - REQUIRE(_array[1] == 3); - } - - SECTION("RemoveMiddleByIterator") { - JsonArray::iterator it = _array.begin(); - ++it; - _array.remove(it); - - REQUIRE(2 == _array.size()); - REQUIRE(_array[0] == 1); - REQUIRE(_array[1] == 3); - } - - SECTION("RemoveLastByIterator") { - JsonArray::iterator it = _array.begin(); - ++it; - ++it; - _array.remove(it); - - REQUIRE(2 == _array.size()); - REQUIRE(_array[0] == 1); - REQUIRE(_array[1] == 2); - } -} diff --git a/lib/ArduinoJson/test/JsonArray/set.cpp b/lib/ArduinoJson/test/JsonArray/set.cpp deleted file mode 100644 index 901f9054..00000000 --- a/lib/ArduinoJson/test/JsonArray/set.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -using namespace Catch::Matchers; - -TEST_CASE("JsonArray::set()") { - DynamicJsonBuffer _jsonBuffer; - JsonArray& _array = _jsonBuffer.createArray(); - _array.add(0); - - SECTION("int") { - _array.set(0, 123); - REQUIRE(123 == _array[0].as()); - REQUIRE(_array[0].is()); - REQUIRE_FALSE(_array[0].is()); - } - - SECTION("double") { - _array.set(0, 123.45); - REQUIRE(123.45 == _array[0].as()); - REQUIRE(_array[0].is()); - REQUIRE_FALSE(_array[0].is()); - } - - SECTION("bool") { - _array.set(0, true); - REQUIRE(true == _array[0].as()); - REQUIRE(_array[0].is()); - REQUIRE_FALSE(_array[0].is()); - } - - SECTION("const char*") { - _array.set(0, "hello"); - REQUIRE_THAT(_array[0].as(), Equals("hello")); - REQUIRE(_array[0].is()); - REQUIRE_FALSE(_array[0].is()); - } - - SECTION("nested array") { - JsonArray& arr = _jsonBuffer.createArray(); - - _array.set(0, arr); - - REQUIRE(&arr == &_array[0].as()); - REQUIRE(_array[0].is()); - REQUIRE_FALSE(_array[0].is()); - } - - SECTION("nested object") { - JsonObject& obj = _jsonBuffer.createObject(); - - _array.set(0, obj); - - REQUIRE(&obj == &_array[0].as()); - REQUIRE(_array[0].is()); - REQUIRE_FALSE(_array[0].is()); - } - - SECTION("array subscript") { - JsonArray& arr = _jsonBuffer.createArray(); - arr.add("hello"); - - _array.set(0, arr[0]); - - REQUIRE_THAT(_array[0].as(), Equals("hello")); - } - - SECTION("object subscript") { - JsonObject& obj = _jsonBuffer.createObject(); - obj["x"] = "hello"; - - _array.set(0, obj["x"]); - - REQUIRE_THAT(_array[0].as(), Equals("hello")); - } - - SECTION("should not duplicate const char*") { - _array.set(0, "world"); - const size_t expectedSize = JSON_ARRAY_SIZE(1); - REQUIRE(expectedSize == _jsonBuffer.size()); - } - - SECTION("should duplicate char*") { - _array.set(0, const_cast("world")); - const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; - REQUIRE(expectedSize == _jsonBuffer.size()); - } - - SECTION("should duplicate std::string") { - _array.set(0, std::string("world")); - const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; - REQUIRE(expectedSize == _jsonBuffer.size()); - } -} diff --git a/lib/ArduinoJson/test/JsonArray/size.cpp b/lib/ArduinoJson/test/JsonArray/size.cpp deleted file mode 100644 index c45fe30e..00000000 --- a/lib/ArduinoJson/test/JsonArray/size.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("JsonArray::size()") { - DynamicJsonBuffer _jsonBuffer; - JsonArray& _array = _jsonBuffer.createArray(); - - SECTION("increases after add()") { - _array.add("hello"); - REQUIRE(1U == _array.size()); - - _array.add("world"); - REQUIRE(2U == _array.size()); - } - - SECTION("remains the same after set()") { - _array.add("hello"); - REQUIRE(1U == _array.size()); - - _array.set(0, "hello"); - REQUIRE(1U == _array.size()); - } - - SECTION("remains the same after assigment") { - _array.add("hello"); - REQUIRE(1U == _array.size()); - - _array[0] = "hello"; - REQUIRE(1U == _array.size()); - } -} diff --git a/lib/ArduinoJson/test/JsonArray/subscript.cpp b/lib/ArduinoJson/test/JsonArray/subscript.cpp deleted file mode 100644 index 69893c53..00000000 --- a/lib/ArduinoJson/test/JsonArray/subscript.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include -#include - -TEST_CASE("JsonArray::operator[]") { - DynamicJsonBuffer _jsonBuffer; - JsonArray& _array = _jsonBuffer.createArray(); - _array.add(0); - - SECTION("int") { - _array[0] = 123; - REQUIRE(123 == _array[0].as()); - REQUIRE(true == _array[0].is()); - REQUIRE(false == _array[0].is()); - } - -#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 - SECTION("long long") { - _array[0] = 9223372036854775807; - REQUIRE(9223372036854775807 == _array[0].as()); - REQUIRE(true == _array[0].is()); - REQUIRE(false == _array[0].is()); - } -#endif - - SECTION("double") { - _array[0] = 123.45; - REQUIRE(123.45 == _array[0].as()); - REQUIRE(true == _array[0].is()); - REQUIRE(false == _array[0].is()); - } - - SECTION("bool") { - _array[0] = true; - REQUIRE(true == _array[0].as()); - REQUIRE(true == _array[0].is()); - REQUIRE(false == _array[0].is()); - } - - SECTION("const char*") { - const char* str = "hello"; - - _array[0] = str; - REQUIRE(str == _array[0].as()); - REQUIRE(str == _array[0].as()); // <- short hand - REQUIRE(true == _array[0].is()); - REQUIRE(false == _array[0].is()); - } - - SECTION("nested array") { - JsonArray& arr = _jsonBuffer.createArray(); - - _array[0] = arr; - - REQUIRE(&arr == &_array[0].as()); - REQUIRE(&arr == &_array[0].as()); // <- short hand - REQUIRE(&arr == &_array[0].as()); - REQUIRE(&arr == &_array[0].as()); // <- short hand - REQUIRE(true == _array[0].is()); - REQUIRE(false == _array[0].is()); - } - - SECTION("nested object") { - JsonObject& obj = _jsonBuffer.createObject(); - - _array[0] = obj; - - REQUIRE(&obj == &_array[0].as()); - REQUIRE(&obj == &_array[0].as()); // <- short hand - REQUIRE(&obj == &_array[0].as()); - REQUIRE(&obj == &_array[0].as()); // <- short hand - REQUIRE(true == _array[0].is()); - REQUIRE(false == _array[0].is()); - } - - SECTION("array subscript") { - JsonArray& arr = _jsonBuffer.createArray(); - const char* str = "hello"; - - arr.add(str); - - _array[0] = arr[0]; - - REQUIRE(str == _array[0]); - } - - SECTION("object subscript") { - JsonObject& obj = _jsonBuffer.createObject(); - const char* str = "hello"; - - obj["x"] = str; - - _array[0] = obj["x"]; - - REQUIRE(str == _array[0]); - } - - SECTION("should not duplicate const char*") { - _array[0] = "world"; - const size_t expectedSize = JSON_ARRAY_SIZE(1); - REQUIRE(expectedSize == _jsonBuffer.size()); - } - - SECTION("should duplicate char*") { - _array[0] = const_cast("world"); - const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; - REQUIRE(expectedSize == _jsonBuffer.size()); - } - - SECTION("should duplicate std::string") { - _array[0] = std::string("world"); - const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; - REQUIRE(expectedSize == _jsonBuffer.size()); - } -} diff --git a/lib/ArduinoJson/test/JsonBuffer/CMakeLists.txt b/lib/ArduinoJson/test/JsonBuffer/CMakeLists.txt deleted file mode 100644 index 34b3e735..00000000 --- a/lib/ArduinoJson/test/JsonBuffer/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# ArduinoJson - arduinojson.org -# Copyright Benoit Blanchon 2014-2018 -# MIT License - -add_executable(JsonBufferTests - nested.cpp - nestingLimit.cpp - parse.cpp - parseArray.cpp - parseObject.cpp -) - -target_link_libraries(JsonBufferTests catch) -add_test(JsonBuffer JsonBufferTests) diff --git a/lib/ArduinoJson/test/JsonBuffer/nested.cpp b/lib/ArduinoJson/test/JsonBuffer/nested.cpp deleted file mode 100644 index 263e40e6..00000000 --- a/lib/ArduinoJson/test/JsonBuffer/nested.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("JsonBuffer nested objects") { - SECTION("ArrayNestedInObject") { - DynamicJsonBuffer jsonBuffer; - char jsonString[] = " { \"ab\" : [ 1 , 2 ] , \"cd\" : [ 3 , 4 ] } "; - - JsonObject &object = jsonBuffer.parseObject(jsonString); - JsonArray &array1 = object["ab"]; - const JsonArray &array2 = object["cd"]; - JsonArray &array3 = object["ef"]; - - REQUIRE(true == object.success()); - - REQUIRE(true == array1.success()); - REQUIRE(true == array2.success()); - REQUIRE(false == array3.success()); - - REQUIRE(2 == array1.size()); - REQUIRE(2 == array2.size()); - REQUIRE(0 == array3.size()); - - REQUIRE(1 == array1[0].as()); - REQUIRE(2 == array1[1].as()); - - REQUIRE(3 == array2[0].as()); - REQUIRE(4 == array2[1].as()); - - REQUIRE(0 == array3[0].as()); - } - - SECTION("ObjectNestedInArray") { - DynamicJsonBuffer jsonBuffer; - char jsonString[] = - " [ { \"a\" : 1 , \"b\" : 2 } , { \"c\" : 3 , \"d\" : 4 } ] "; - - JsonArray &array = jsonBuffer.parseArray(jsonString); - JsonObject &object1 = array[0]; - const JsonObject &object2 = array[1]; - JsonObject &object3 = array[2]; - - REQUIRE(true == array.success()); - - REQUIRE(true == object1.success()); - REQUIRE(true == object2.success()); - REQUIRE(false == object3.success()); - - REQUIRE(2 == object1.size()); - REQUIRE(2 == object2.size()); - REQUIRE(0 == object3.size()); - - REQUIRE(1 == object1["a"].as()); - REQUIRE(2 == object1["b"].as()); - REQUIRE(3 == object2["c"].as()); - REQUIRE(4 == object2["d"].as()); - REQUIRE(0 == object3["e"].as()); - } -} diff --git a/lib/ArduinoJson/test/JsonBuffer/nestingLimit.cpp b/lib/ArduinoJson/test/JsonBuffer/nestingLimit.cpp deleted file mode 100644 index 0d7be115..00000000 --- a/lib/ArduinoJson/test/JsonBuffer/nestingLimit.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -bool tryParseArray(const char *json, uint8_t nestingLimit) { - DynamicJsonBuffer buffer; - return buffer.parseArray(json, nestingLimit).success(); -} - -bool tryParseObject(const char *json, uint8_t nestingLimit) { - DynamicJsonBuffer buffer; - return buffer.parseObject(json, nestingLimit).success(); -} - -TEST_CASE("JsonParser nestingLimit") { - SECTION("ParseArrayWithNestingLimit0") { - REQUIRE(true == tryParseArray("[]", 0)); - REQUIRE(false == tryParseArray("[[]]", 0)); - } - - SECTION("ParseArrayWithNestingLimit1") { - REQUIRE(true == tryParseArray("[[]]", 1)); - REQUIRE(false == tryParseArray("[[[]]]", 1)); - } - - SECTION("ParseArrayWithNestingLimit2") { - REQUIRE(true == tryParseArray("[[[]]]", 2)); - REQUIRE(false == tryParseArray("[[[[]]]]", 2)); - } - - SECTION("ParseObjectWithNestingLimit0") { - REQUIRE(true == tryParseObject("{}", 0)); - REQUIRE(false == tryParseObject("{\"key\":{}}", 0)); - } - - SECTION("ParseObjectWithNestingLimit1") { - REQUIRE(true == tryParseObject("{\"key\":{}}", 1)); - REQUIRE(false == tryParseObject("{\"key\":{\"key\":{}}}", 1)); - } - - SECTION("ParseObjectWithNestingLimit2") { - REQUIRE(true == tryParseObject("{\"key\":{\"key\":{}}}", 2)); - REQUIRE(false == tryParseObject("{\"key\":{\"key\":{\"key\":{}}}}", 2)); - } -} diff --git a/lib/ArduinoJson/test/JsonBuffer/parse.cpp b/lib/ArduinoJson/test/JsonBuffer/parse.cpp deleted file mode 100644 index 70e57918..00000000 --- a/lib/ArduinoJson/test/JsonBuffer/parse.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -using namespace Catch::Matchers; - -TEST_CASE("JsonBuffer::parse()") { - DynamicJsonBuffer jb; - - SECTION("EmptyObject") { - JsonVariant variant = jb.parse("{}"); - REQUIRE(variant.success()); - REQUIRE(variant.is()); - } - - SECTION("EmptyArray") { - JsonVariant variant = jb.parse("[]"); - REQUIRE(variant.success()); - REQUIRE(variant.is()); - } - - SECTION("Integer") { - JsonVariant variant = jb.parse("-42"); - REQUIRE(variant.success()); - REQUIRE(variant.is()); - REQUIRE_FALSE(variant.is()); - REQUIRE(variant == -42); - } - - SECTION("Double") { - JsonVariant variant = jb.parse("-1.23e+4"); - REQUIRE(variant.success()); - REQUIRE_FALSE(variant.is()); - REQUIRE(variant.is()); - REQUIRE(variant.as() == Approx(-1.23e+4)); - } - - SECTION("Double quoted string") { - JsonVariant variant = jb.parse("\"hello world\""); - REQUIRE(variant.success()); - REQUIRE(variant.is()); - REQUIRE_THAT(variant.as(), Equals("hello world")); - } - - SECTION("Single quoted string") { - JsonVariant variant = jb.parse("\'hello world\'"); - REQUIRE(variant.success()); - REQUIRE(variant.is()); - REQUIRE_THAT(variant.as(), Equals("hello world")); - } - - SECTION("True") { - JsonVariant variant = jb.parse("true"); - REQUIRE(variant.success()); - REQUIRE(variant.is()); - REQUIRE(variant == true); - } - - SECTION("False") { - JsonVariant variant = jb.parse("false"); - REQUIRE(variant.success()); - REQUIRE(variant.is()); - REQUIRE(variant == false); - } - - SECTION("OpenBrace") { - JsonVariant variant = jb.parse("{"); - REQUIRE_FALSE(variant.success()); - } - - SECTION("Incomplete string") { - JsonVariant variant = jb.parse("\"hello"); - REQUIRE(variant.success()); - REQUIRE(variant.is()); - REQUIRE_THAT(variant.as(), Equals("hello")); - } -} diff --git a/lib/ArduinoJson/test/JsonBuffer/parseArray.cpp b/lib/ArduinoJson/test/JsonBuffer/parseArray.cpp deleted file mode 100644 index 2e843f8c..00000000 --- a/lib/ArduinoJson/test/JsonBuffer/parseArray.cpp +++ /dev/null @@ -1,318 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("JsonBuffer::parseArray()") { - DynamicJsonBuffer jb; - - SECTION("EmptyArray") { - JsonArray& arr = jb.parseArray("[]"); - - REQUIRE(arr.success()); - REQUIRE(0 == arr.size()); - } - - SECTION("MissingOpeningBracket") { - JsonArray& arr = jb.parseArray("]"); - REQUIRE_FALSE(arr.success()); - } - - SECTION("ArrayWithNoEnd") { - JsonArray& arr = jb.parseArray("["); - REQUIRE_FALSE(arr.success()); - } - - SECTION("EmptyArrayWithLeadingSpaces") { - JsonArray& arr = jb.parseArray(" []"); - - REQUIRE(arr.success()); - REQUIRE(0 == arr.size()); - } - - SECTION("Garbage") { - JsonArray& arr = jb.parseArray("%*$£¤"); - - REQUIRE_FALSE(arr.success()); - } - - SECTION("OneInteger") { - JsonArray& arr = jb.parseArray("[42]"); - - REQUIRE(arr.success()); - REQUIRE(1 == arr.size()); - REQUIRE(arr[0] == 42); - } - - SECTION("OneIntegerWithSpacesBefore") { - JsonArray& arr = jb.parseArray("[ \t\r\n42]"); - - REQUIRE(arr.success()); - REQUIRE(1 == arr.size()); - REQUIRE(arr[0] == 42); - } - - SECTION("OneIntegerWithSpaceAfter") { - JsonArray& arr = jb.parseArray("[42 \t\r\n]"); - - REQUIRE(arr.success()); - REQUIRE(1 == arr.size()); - REQUIRE(arr[0] == 42); - } - - SECTION("TwoIntegers") { - JsonArray& arr = jb.parseArray("[42,84]"); - - REQUIRE(arr.success()); - REQUIRE(2 == arr.size()); - REQUIRE(arr[0] == 42); - REQUIRE(arr[1] == 84); - } - - SECTION("TwoDoubles") { - JsonArray& arr = jb.parseArray("[4.2,1e2]"); - - REQUIRE(arr.success()); - REQUIRE(2 == arr.size()); - REQUIRE(arr[0] == 4.2); - REQUIRE(arr[1] == 1e2); - } - - SECTION("UnsignedLong") { - JsonArray& arr = jb.parseArray("[4294967295]"); - - REQUIRE(arr.success()); - REQUIRE(1 == arr.size()); - REQUIRE(arr[0] == 4294967295UL); - } - - SECTION("TwoBooleans") { - JsonArray& arr = jb.parseArray("[true,false]"); - - REQUIRE(arr.success()); - REQUIRE(2 == arr.size()); - REQUIRE(arr[0] == true); - REQUIRE(arr[1] == false); - } - - SECTION("TwoNulls") { - JsonArray& arr = jb.parseArray("[null,null]"); - - REQUIRE(arr.success()); - REQUIRE(2 == arr.size()); - REQUIRE(arr[0].as() == 0); - REQUIRE(arr[1].as() == 0); - } - - SECTION("TwoStringsDoubleQuotes") { - JsonArray& arr = jb.parseArray("[ \"hello\" , \"world\" ]"); - - REQUIRE(arr.success()); - REQUIRE(2 == arr.size()); - REQUIRE(arr[0] == "hello"); - REQUIRE(arr[1] == "world"); - } - - SECTION("TwoStringsSingleQuotes") { - JsonArray& arr = jb.parseArray("[ 'hello' , 'world' ]"); - - REQUIRE(arr.success()); - REQUIRE(2 == arr.size()); - REQUIRE(arr[0] == "hello"); - REQUIRE(arr[1] == "world"); - } - - SECTION("TwoStringsNoQuotes") { - JsonArray& arr = jb.parseArray("[ hello , world ]"); - - REQUIRE(arr.success()); - REQUIRE(2 == arr.size()); - REQUIRE(arr[0] == "hello"); - REQUIRE(arr[1] == "world"); - } - - SECTION("EmptyStringsDoubleQuotes") { - JsonArray& arr = jb.parseArray("[\"\",\"\"]"); - - REQUIRE(arr.success()); - REQUIRE(2 == arr.size()); - REQUIRE(arr[0] == ""); - REQUIRE(arr[1] == ""); - } - - SECTION("EmptyStringSingleQuotes") { - JsonArray& arr = jb.parseArray("[\'\',\'\']"); - - REQUIRE(arr.success()); - REQUIRE(2 == arr.size()); - REQUIRE(arr[0] == ""); - REQUIRE(arr[1] == ""); - } - - SECTION("EmptyStringNoQuotes") { - JsonArray& arr = jb.parseArray("[,]"); - - REQUIRE(arr.success()); - REQUIRE(2 == arr.size()); - REQUIRE(arr[0] == ""); - REQUIRE(arr[1] == ""); - } - - SECTION("ClosingDoubleQuoteMissing") { - JsonArray& arr = jb.parseArray("[\"]"); - - REQUIRE_FALSE(arr.success()); - } - - SECTION("ClosingSignleQuoteMissing") { - JsonArray& arr = jb.parseArray("[\']"); - - REQUIRE_FALSE(arr.success()); - } - - SECTION("StringWithEscapedChars") { - JsonArray& arr = jb.parseArray("[\"1\\\"2\\\\3\\/4\\b5\\f6\\n7\\r8\\t9\"]"); - - REQUIRE(arr.success()); - REQUIRE(1 == arr.size()); - REQUIRE(arr[0] == "1\"2\\3/4\b5\f6\n7\r8\t9"); - } - - SECTION("StringWithUnterminatedEscapeSequence") { - JsonArray& arr = jb.parseArray("\"\\\0\"", 4); - REQUIRE_FALSE(arr.success()); - } - - SECTION("CCommentBeforeOpeningBracket") { - JsonArray& arr = jb.parseArray("/*COMMENT*/ [\"hello\"]"); - - REQUIRE(arr.success()); - REQUIRE(1 == arr.size()); - REQUIRE(arr[0] == "hello"); - } - - SECTION("CCommentAfterOpeningBracket") { - JsonArray& arr = jb.parseArray("[/*COMMENT*/ \"hello\"]"); - - REQUIRE(arr.success()); - REQUIRE(1 == arr.size()); - REQUIRE(arr[0] == "hello"); - } - - SECTION("CCommentBeforeClosingBracket") { - JsonArray& arr = jb.parseArray("[\"hello\"/*COMMENT*/]"); - - REQUIRE(arr.success()); - REQUIRE(1 == arr.size()); - REQUIRE(arr[0] == "hello"); - } - - SECTION("CCommentAfterClosingBracket") { - JsonArray& arr = jb.parseArray("[\"hello\"]/*COMMENT*/"); - - REQUIRE(arr.success()); - REQUIRE(1 == arr.size()); - REQUIRE(arr[0] == "hello"); - } - - SECTION("CCommentBeforeComma") { - JsonArray& arr = jb.parseArray("[\"hello\"/*COMMENT*/,\"world\"]"); - - REQUIRE(arr.success()); - REQUIRE(2 == arr.size()); - REQUIRE(arr[0] == "hello"); - REQUIRE(arr[1] == "world"); - } - - SECTION("CCommentAfterComma") { - JsonArray& arr = jb.parseArray("[\"hello\",/*COMMENT*/ \"world\"]"); - - REQUIRE(arr.success()); - REQUIRE(2 == arr.size()); - REQUIRE(arr[0] == "hello"); - REQUIRE(arr[1] == "world"); - } - - SECTION("CppCommentBeforeOpeningBracket") { - JsonArray& arr = jb.parseArray("//COMMENT\n\t[\"hello\"]"); - - REQUIRE(arr.success()); - REQUIRE(1 == arr.size()); - REQUIRE(arr[0] == "hello"); - } - - SECTION("CppCommentAfterOpeningBracket") { - JsonArray& arr = jb.parseArray("[//COMMENT\n\"hello\"]"); - - REQUIRE(arr.success()); - REQUIRE(1 == arr.size()); - REQUIRE(arr[0] == "hello"); - } - - SECTION("CppCommentBeforeClosingBracket") { - JsonArray& arr = jb.parseArray("[\"hello\"//COMMENT\r\n]"); - - REQUIRE(arr.success()); - REQUIRE(1 == arr.size()); - REQUIRE(arr[0] == "hello"); - } - - SECTION("CppCommentAfterClosingBracket") { - JsonArray& arr = jb.parseArray("[\"hello\"]//COMMENT\n"); - - REQUIRE(arr.success()); - REQUIRE(1 == arr.size()); - REQUIRE(arr[0] == "hello"); - } - - SECTION("CppCommentBeforeComma") { - JsonArray& arr = jb.parseArray("[\"hello\"//COMMENT\n,\"world\"]"); - - REQUIRE(arr.success()); - REQUIRE(2 == arr.size()); - REQUIRE(arr[0] == "hello"); - REQUIRE(arr[1] == "world"); - } - - SECTION("CppCommentAfterComma") { - JsonArray& arr = jb.parseArray("[\"hello\",//COMMENT\n\"world\"]"); - - REQUIRE(arr.success()); - REQUIRE(2 == arr.size()); - REQUIRE(arr[0] == "hello"); - REQUIRE(arr[1] == "world"); - } - - SECTION("InvalidCppComment") { - JsonArray& arr = jb.parseArray("[/COMMENT\n]"); - REQUIRE_FALSE(arr.success()); - } - - SECTION("InvalidComment") { - JsonArray& arr = jb.parseArray("[/*/\n]"); - REQUIRE_FALSE(arr.success()); - } - - SECTION("UnfinishedCComment") { - JsonArray& arr = jb.parseArray("[/*COMMENT]"); - REQUIRE_FALSE(arr.success()); - } - - SECTION("EndsInCppComment") { - JsonArray& arr = jb.parseArray("[//COMMENT"); - REQUIRE_FALSE(arr.success()); - } - - SECTION("AfterClosingStar") { - JsonArray& arr = jb.parseArray("[/*COMMENT*"); - REQUIRE_FALSE(arr.success()); - } - - SECTION("DeeplyNested") { - JsonArray& arr = - jb.parseArray("[[[[[[[[[[[[[[[[[[[\"Not too deep\"]]]]]]]]]]]]]]]]]]]"); - REQUIRE(arr.success()); - } -} diff --git a/lib/ArduinoJson/test/JsonBuffer/parseObject.cpp b/lib/ArduinoJson/test/JsonBuffer/parseObject.cpp deleted file mode 100644 index 3a4067c5..00000000 --- a/lib/ArduinoJson/test/JsonBuffer/parseObject.cpp +++ /dev/null @@ -1,170 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("JsonBuffer::parseObject()") { - DynamicJsonBuffer jb; - - SECTION("An empty object") { - JsonObject& obj = jb.parseObject("{}"); - REQUIRE(obj.success()); - REQUIRE(obj.size() == 0); - } - - SECTION("Quotes") { - SECTION("Double quotes") { - JsonObject& obj = jb.parseObject("{\"key\":\"value\"}"); - REQUIRE(obj.success()); - REQUIRE(obj.size() == 1); - REQUIRE(obj["key"] == "value"); - } - - SECTION("Single quotes") { - JsonObject& obj = jb.parseObject("{'key':'value'}"); - REQUIRE(obj.success()); - REQUIRE(obj.size() == 1); - REQUIRE(obj["key"] == "value"); - } - - SECTION("No quotes") { - JsonObject& obj = jb.parseObject("{key:value}"); - REQUIRE(obj.success()); - REQUIRE(obj.size() == 1); - REQUIRE(obj["key"] == "value"); - } - - SECTION("No quotes, allow underscore in key") { - JsonObject& obj = jb.parseObject("{_k_e_y_:42}"); - REQUIRE(obj.success()); - REQUIRE(obj.size() == 1); - REQUIRE(obj["_k_e_y_"] == 42); - } - } - - SECTION("Spaces") { - SECTION("Before the key") { - JsonObject& obj = jb.parseObject("{ \"key\":\"value\"}"); - REQUIRE(obj.success()); - REQUIRE(obj.size() == 1); - REQUIRE(obj["key"] == "value"); - } - - SECTION("After the key") { - JsonObject& obj = jb.parseObject("{\"key\" :\"value\"}"); - REQUIRE(obj.success()); - REQUIRE(obj.size() == 1); - REQUIRE(obj["key"] == "value"); - } - - SECTION("Before the value") { - JsonObject& obj = jb.parseObject("{\"key\": \"value\"}"); - REQUIRE(obj.success()); - REQUIRE(obj.size() == 1); - REQUIRE(obj["key"] == "value"); - } - - SECTION("After the value") { - JsonObject& obj = jb.parseObject("{\"key\":\"value\" }"); - REQUIRE(obj.success()); - REQUIRE(obj.size() == 1); - REQUIRE(obj["key"] == "value"); - } - - SECTION("Before the colon") { - JsonObject& obj = - jb.parseObject("{\"key1\":\"value1\" ,\"key2\":\"value2\"}"); - REQUIRE(obj.success()); - REQUIRE(obj.size() == 2); - REQUIRE(obj["key1"] == "value1"); - REQUIRE(obj["key2"] == "value2"); - } - - SECTION("After the colon") { - JsonObject& obj = - jb.parseObject("{\"key1\":\"value1\" ,\"key2\":\"value2\"}"); - REQUIRE(obj.success()); - REQUIRE(obj.size() == 2); - REQUIRE(obj["key1"] == "value1"); - REQUIRE(obj["key2"] == "value2"); - } - } - - SECTION("Values types") { - SECTION("String") { - JsonObject& obj = - jb.parseObject("{\"key1\":\"value1\",\"key2\":\"value2\"}"); - REQUIRE(obj.success()); - REQUIRE(obj.size() == 2); - REQUIRE(obj["key1"] == "value1"); - REQUIRE(obj["key2"] == "value2"); - } - - SECTION("Integer") { - JsonObject& obj = jb.parseObject("{\"key1\":42,\"key2\":-42}"); - REQUIRE(obj.success()); - REQUIRE(obj.size() == 2); - REQUIRE(obj["key1"] == 42); - REQUIRE(obj["key2"] == -42); - } - - SECTION("Double") { - JsonObject& obj = jb.parseObject("{\"key1\":12.345,\"key2\":-7E89}"); - REQUIRE(obj.success()); - REQUIRE(obj.size() == 2); - REQUIRE(obj["key1"] == 12.345); - REQUIRE(obj["key2"] == -7E89); - } - - SECTION("Booleans") { - JsonObject& obj = jb.parseObject("{\"key1\":true,\"key2\":false}"); - REQUIRE(obj.success()); - REQUIRE(obj.size() == 2); - REQUIRE(obj["key1"] == true); - REQUIRE(obj["key2"] == false); - } - - SECTION("Null") { - JsonObject& obj = jb.parseObject("{\"key1\":null,\"key2\":null}"); - REQUIRE(obj.success()); - REQUIRE(obj.size() == 2); - REQUIRE(obj["key1"].as() == 0); - REQUIRE(obj["key2"].as() == 0); - } - } - - SECTION("Misc") { - SECTION("The opening brace is missing") { - JsonObject& obj = jb.parseObject("}"); - REQUIRE_FALSE(obj.success()); - } - - SECTION("The closing brace is missing") { - JsonObject& obj = jb.parseObject("{"); - REQUIRE_FALSE(obj.success()); - } - - SECTION("A quoted key without value") { - JsonObject& obj = jb.parseObject("{\"key\"}"); - REQUIRE_FALSE(obj.success()); - } - - SECTION("A non-quoted key without value") { - JsonObject& obj = jb.parseObject("{key}"); - REQUIRE_FALSE(obj.success()); - } - - SECTION("A dangling comma") { - JsonObject& obj = jb.parseObject("{\"key1\":\"value1\",}"); - REQUIRE_FALSE(obj.success()); - REQUIRE(obj.size() == 0); - } - - SECTION("null as a key") { - JsonObject& obj = jb.parseObject("null:\"value\"}"); - REQUIRE_FALSE(obj.success()); - } - } -} diff --git a/lib/ArduinoJson/test/JsonObject/CMakeLists.txt b/lib/ArduinoJson/test/JsonObject/CMakeLists.txt deleted file mode 100644 index 93e8f0de..00000000 --- a/lib/ArduinoJson/test/JsonObject/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# ArduinoJson - arduinojson.org -# Copyright Benoit Blanchon 2014-2018 -# MIT License - -add_executable(JsonObjectTests - basics.cpp - containsKey.cpp - get.cpp - invalid.cpp - iterator.cpp - prettyPrintTo.cpp - printTo.cpp - remove.cpp - set.cpp - size.cpp - subscript.cpp -) - -target_link_libraries(JsonObjectTests catch) -add_test(JsonObject JsonObjectTests) diff --git a/lib/ArduinoJson/test/JsonObject/basics.cpp b/lib/ArduinoJson/test/JsonObject/basics.cpp deleted file mode 100644 index dd981702..00000000 --- a/lib/ArduinoJson/test/JsonObject/basics.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("JsonObject basics") { - DynamicJsonBuffer _jsonBuffer; - JsonObject& _object = _jsonBuffer.createObject(); - - SECTION("InitialSizeIsZero") { - REQUIRE(0 == _object.size()); - } - - SECTION("SuccessIsTrue") { - REQUIRE(_object.success()); - } -} diff --git a/lib/ArduinoJson/test/JsonObject/containsKey.cpp b/lib/ArduinoJson/test/JsonObject/containsKey.cpp deleted file mode 100644 index f8d0a152..00000000 --- a/lib/ArduinoJson/test/JsonObject/containsKey.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("JsonObject::containsKey()") { - DynamicJsonBuffer _jsonBuffer; - JsonObject& _object = _jsonBuffer.createObject(); - - SECTION("ContainsKeyReturnsFalseForNonExistingKey") { - _object.set("hello", 42); - - REQUIRE(false == _object.containsKey("world")); - } - - SECTION("ContainsKeyReturnsTrueForDefinedValue") { - _object.set("hello", 42); - - REQUIRE(true == _object.containsKey("hello")); - } - - SECTION("ContainsKeyReturnsFalseAfterRemove") { - _object.set("hello", 42); - _object.remove("hello"); - - REQUIRE(false == _object.containsKey("hello")); - } -} diff --git a/lib/ArduinoJson/test/JsonObject/get.cpp b/lib/ArduinoJson/test/JsonObject/get.cpp deleted file mode 100644 index b3635956..00000000 --- a/lib/ArduinoJson/test/JsonObject/get.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -using namespace Catch::Matchers; - -TEST_CASE("JsonObject::get()") { - DynamicJsonBuffer jb; - JsonObject& obj = jb.createObject(); - - SECTION("GetConstCharPointer_GivenStringLiteral") { - obj.set("hello", "world"); - const char* value = obj.get("hello"); - REQUIRE_THAT(value, Equals("world")); - } -} diff --git a/lib/ArduinoJson/test/JsonObject/invalid.cpp b/lib/ArduinoJson/test/JsonObject/invalid.cpp deleted file mode 100644 index 019ced10..00000000 --- a/lib/ArduinoJson/test/JsonObject/invalid.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -using namespace Catch::Matchers; - -TEST_CASE("JsonObject::invalid()") { - JsonObject& obj = JsonObject::invalid(); - - SECTION("SubscriptFails") { - REQUIRE_FALSE(obj["key"].success()); - } - - SECTION("AddFails") { - obj.set("hello", "world"); - REQUIRE(0 == obj.size()); - } - - SECTION("CreateNestedArrayFails") { - REQUIRE_FALSE(obj.createNestedArray("hello").success()); - } - - SECTION("CreateNestedObjectFails") { - REQUIRE_FALSE(obj.createNestedObject("world").success()); - } - - SECTION("PrintToWritesBraces") { - char buffer[32]; - obj.printTo(buffer, sizeof(buffer)); - REQUIRE_THAT(buffer, Equals("{}")); - } -} diff --git a/lib/ArduinoJson/test/JsonObject/iterator.cpp b/lib/ArduinoJson/test/JsonObject/iterator.cpp deleted file mode 100644 index e765d5c7..00000000 --- a/lib/ArduinoJson/test/JsonObject/iterator.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -using namespace Catch::Matchers; - -TEST_CASE("JsonObject::begin()/end()") { - StaticJsonBuffer jb; - JsonObject& obj = jb.createObject(); - obj["ab"] = 12; - obj["cd"] = 34; - - SECTION("NonConstIterator") { - JsonObject::iterator it = obj.begin(); - REQUIRE(obj.end() != it); - REQUIRE_THAT(it->key, Equals("ab")); - REQUIRE(12 == it->value); - it->key = "a.b"; - it->value = 1.2; - ++it; - REQUIRE(obj.end() != it); - REQUIRE_THAT(it->key, Equals("cd")); - REQUIRE(34 == it->value); - it->key = "c.d"; - it->value = 3.4; - ++it; - REQUIRE(obj.end() == it); - - REQUIRE(2 == obj.size()); - REQUIRE(1.2 == obj["a.b"]); - REQUIRE(3.4 == obj["c.d"]); - } - - SECTION("ConstIterator") { - const JsonObject& const_object = obj; - JsonObject::const_iterator it = const_object.begin(); - - REQUIRE(const_object.end() != it); - REQUIRE_THAT(it->key, Equals("ab")); - REQUIRE(12 == it->value); - ++it; - REQUIRE(const_object.end() != it); - REQUIRE_THAT(it->key, Equals("cd")); - REQUIRE(34 == it->value); - ++it; - REQUIRE(const_object.end() == it); - } -} diff --git a/lib/ArduinoJson/test/JsonObject/prettyPrintTo.cpp b/lib/ArduinoJson/test/JsonObject/prettyPrintTo.cpp deleted file mode 100644 index 30459246..00000000 --- a/lib/ArduinoJson/test/JsonObject/prettyPrintTo.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include -#include - -void check(const JsonObject &obj, const std::string expected) { - char json[256]; - - size_t actualLen = obj.prettyPrintTo(json); - size_t measuredLen = obj.measurePrettyLength(); - - REQUIRE(json == expected); - REQUIRE(expected.size() == actualLen); - REQUIRE(expected.size() == measuredLen); -} - -TEST_CASE("JsonObject::prettyPrintTo()") { - DynamicJsonBuffer jb; - JsonObject &obj = jb.createObject(); - - SECTION("EmptyObject") { - check(obj, "{}"); - } - - SECTION("OneMember") { - obj["key"] = "value"; - - check(obj, - "{\r\n" - " \"key\": \"value\"\r\n" - "}"); - } - - SECTION("TwoMembers") { - obj["key1"] = "value1"; - obj["key2"] = "value2"; - - check(obj, - "{\r\n" - " \"key1\": \"value1\",\r\n" - " \"key2\": \"value2\"\r\n" - "}"); - } - - SECTION("EmptyNestedContainers") { - obj.createNestedObject("key1"); - obj.createNestedArray("key2"); - - check(obj, - "{\r\n" - " \"key1\": {},\r\n" - " \"key2\": []\r\n" - "}"); - } - - SECTION("NestedContainers") { - JsonObject &nested1 = obj.createNestedObject("key1"); - nested1["a"] = 1; - - JsonArray &nested2 = obj.createNestedArray("key2"); - nested2.add(2); - - check(obj, - "{\r\n" - " \"key1\": {\r\n" - " \"a\": 1\r\n" - " },\r\n" - " \"key2\": [\r\n" - " 2\r\n" - " ]\r\n" - "}"); - } -} diff --git a/lib/ArduinoJson/test/JsonObject/printTo.cpp b/lib/ArduinoJson/test/JsonObject/printTo.cpp deleted file mode 100644 index 6d0bcc9a..00000000 --- a/lib/ArduinoJson/test/JsonObject/printTo.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include -#include - -void check(const JsonObject &obj, const std::string &expected) { - char actual[256]; - size_t actualLen = obj.printTo(actual); - size_t measuredLen = obj.measureLength(); - - REQUIRE(expected == actual); - REQUIRE(expected.size() == actualLen); - REQUIRE(expected.size() == measuredLen); -} -TEST_CASE("JsonObject::printTo()") { - DynamicJsonBuffer _jsonBuffer; - JsonObject &obj = _jsonBuffer.createObject(); - - SECTION("EmptyObject") { - check(obj, "{}"); - } - - SECTION("TwoStrings") { - obj["key1"] = "value1"; - obj.set("key2", "value2"); - - check(obj, "{\"key1\":\"value1\",\"key2\":\"value2\"}"); - } - - SECTION("RemoveFirst") { - obj["key1"] = "value1"; - obj["key2"] = "value2"; - obj.remove("key1"); - - check(obj, "{\"key2\":\"value2\"}"); - } - - SECTION("RemoveLast") { - obj["key1"] = "value1"; - obj["key2"] = "value2"; - obj.remove("key2"); - - check(obj, "{\"key1\":\"value1\"}"); - } - - SECTION("RemoveUnexistingKey") { - obj["key1"] = "value1"; - obj["key2"] = "value2"; - obj.remove("key3"); - - check(obj, "{\"key1\":\"value1\",\"key2\":\"value2\"}"); - } - - SECTION("ReplaceExistingKey") { - obj["key"] = "value1"; - obj["key"] = "value2"; - - check(obj, "{\"key\":\"value2\"}"); - } - - SECTION("TwoIntegers") { - obj["a"] = 1; - obj.set("b", 2); - check(obj, "{\"a\":1,\"b\":2}"); - } - - SECTION("RawJson") { - obj["a"] = RawJson("[1,2]"); - obj.set("b", RawJson("[4,5]")); - check(obj, "{\"a\":[1,2],\"b\":[4,5]}"); - } - - SECTION("Two doubles") { - obj["a"] = 12.34; - obj.set("b", 56.78); - check(obj, "{\"a\":12.34,\"b\":56.78}"); - } - - SECTION("TwoNull") { - obj["a"] = static_cast(0); - obj.set("b", static_cast(0)); - check(obj, "{\"a\":null,\"b\":null}"); - } - - SECTION("TwoBooleans") { - obj["a"] = true; - obj.set("b", false); - check(obj, "{\"a\":true,\"b\":false}"); - } - - SECTION("ThreeNestedArrays") { - obj.createNestedArray("a"); - obj["b"] = _jsonBuffer.createArray(); - obj.set("c", _jsonBuffer.createArray()); - - check(obj, "{\"a\":[],\"b\":[],\"c\":[]}"); - } - - SECTION("ThreeNestedObjects") { - obj.createNestedObject("a"); - obj["b"] = _jsonBuffer.createObject(); - obj.set("c", _jsonBuffer.createObject()); - - check(obj, "{\"a\":{},\"b\":{},\"c\":{}}"); - } -} diff --git a/lib/ArduinoJson/test/JsonObject/remove.cpp b/lib/ArduinoJson/test/JsonObject/remove.cpp deleted file mode 100644 index 0e68eec0..00000000 --- a/lib/ArduinoJson/test/JsonObject/remove.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include -#include - -TEST_CASE("JsonObject::remove()") { - DynamicJsonBuffer jb; - - SECTION("SizeDecreased_WhenValuesAreRemoved") { - JsonObject& obj = jb.createObject(); - obj["hello"] = 1; - - obj.remove("hello"); - - REQUIRE(0 == obj.size()); - } - - SECTION("SizeUntouched_WhenRemoveIsCalledWithAWrongKey") { - JsonObject& obj = jb.createObject(); - obj["hello"] = 1; - - obj.remove("world"); - - REQUIRE(1 == obj.size()); - } - - SECTION("RemoveByIterator") { - JsonObject& obj = jb.parseObject("{\"a\":0,\"b\":1,\"c\":2}"); - - for (JsonObject::iterator it = obj.begin(); it != obj.end(); ++it) { - if (it->value == 1) obj.remove(it); - } - - std::string result; - obj.printTo(result); - REQUIRE("{\"a\":0,\"c\":2}" == result); - } -} diff --git a/lib/ArduinoJson/test/JsonObject/set.cpp b/lib/ArduinoJson/test/JsonObject/set.cpp deleted file mode 100644 index d5ae48b2..00000000 --- a/lib/ArduinoJson/test/JsonObject/set.cpp +++ /dev/null @@ -1,138 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include -#include - -TEST_CASE("JsonObject::set()") { - DynamicJsonBuffer jb; - JsonObject& _object = jb.createObject(); - - SECTION("int") { - _object.set("hello", 123); - - REQUIRE(123 == _object["hello"].as()); - REQUIRE(_object["hello"].is()); - REQUIRE_FALSE(_object["hello"].is()); - } - - SECTION("double") { - _object.set("hello", 123.45); - - REQUIRE(123.45 == _object["hello"].as()); - REQUIRE(_object["hello"].is()); - REQUIRE_FALSE(_object["hello"].is()); - } - - SECTION("bool") { - _object.set("hello", true); - - REQUIRE(_object["hello"].as()); - REQUIRE(_object["hello"].is()); - REQUIRE_FALSE(_object["hello"].is()); - } - - SECTION("const char*") { - _object.set("hello", "h3110"); - - REQUIRE(std::string("h3110") == _object["hello"].as()); - REQUIRE(_object["hello"].is()); - REQUIRE_FALSE(_object["hello"].is()); - } - - SECTION("nested array") { - JsonArray& arr = jb.createArray(); - - _object.set("hello", arr); - - REQUIRE(&arr == &_object["hello"].as()); - REQUIRE(_object["hello"].is()); - REQUIRE_FALSE(_object["hello"].is()); - } - - SECTION("nested object") { - JsonObject& obj = jb.createObject(); - - _object.set("hello", obj); - - REQUIRE(&obj == &_object["hello"].as()); - REQUIRE(_object["hello"].is()); - REQUIRE_FALSE(_object["hello"].is()); - } - - SECTION("array subscript") { - JsonArray& arr = jb.createArray(); - arr.add(42); - - _object.set("a", arr[0]); - - REQUIRE(42 == _object["a"]); - } - - SECTION("object subscript") { - JsonObject& obj = jb.createObject(); - obj.set("x", 42); - - _object.set("a", obj["x"]); - - REQUIRE(42 == _object["a"]); - } - - SECTION("returns true when allocation succeeds") { - StaticJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - - REQUIRE(true == obj.set(std::string("hello"), std::string("world"))); - } - - SECTION("returns false when allocation fails") { - StaticJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - - REQUIRE(false == obj.set(std::string("hello"), std::string("world"))); - } - - SECTION("should not duplicate const char*") { - _object.set("hello", "world"); - const size_t expectedSize = JSON_OBJECT_SIZE(1); - REQUIRE(expectedSize == jb.size()); - } - - SECTION("should duplicate char* value") { - _object.set("hello", const_cast("world")); - const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; - REQUIRE(expectedSize == jb.size()); - } - - SECTION("should duplicate char* key") { - _object.set(const_cast("hello"), "world"); - const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; - REQUIRE(expectedSize == jb.size()); - } - - SECTION("should duplicate char* key&value") { - _object.set(const_cast("hello"), const_cast("world")); - const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12; - REQUIRE(expectedSize <= jb.size()); - } - - SECTION("should duplicate std::string value") { - _object.set("hello", std::string("world")); - const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; - REQUIRE(expectedSize == jb.size()); - } - - SECTION("should duplicate std::string key") { - _object.set(std::string("hello"), "world"); - const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; - REQUIRE(expectedSize == jb.size()); - } - - SECTION("should duplicate std::string key&value") { - _object.set(std::string("hello"), std::string("world")); - const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12; - REQUIRE(expectedSize <= jb.size()); - } -} diff --git a/lib/ArduinoJson/test/JsonObject/size.cpp b/lib/ArduinoJson/test/JsonObject/size.cpp deleted file mode 100644 index eae88834..00000000 --- a/lib/ArduinoJson/test/JsonObject/size.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include -#include - -TEST_CASE("JsonObject::size()") { - DynamicJsonBuffer jb; - JsonObject& _object = jb.createObject(); - - SECTION("increases when values are added") { - _object.set("hello", 42); - REQUIRE(1 == _object.size()); - } - - SECTION("doesn't increase when the smae key is added twice") { - _object["hello"] = 1; - _object["hello"] = 2; - REQUIRE(1 == _object.size()); - } -} diff --git a/lib/ArduinoJson/test/JsonObject/subscript.cpp b/lib/ArduinoJson/test/JsonObject/subscript.cpp deleted file mode 100644 index d08e8c77..00000000 --- a/lib/ArduinoJson/test/JsonObject/subscript.cpp +++ /dev/null @@ -1,152 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("JsonObject::operator[]") { - DynamicJsonBuffer _jsonBuffer; - JsonObject& _object = _jsonBuffer.createObject(); - - SECTION("int") { - _object["hello"] = 123; - - REQUIRE(123 == _object["hello"].as()); - REQUIRE(true == _object["hello"].is()); - REQUIRE(false == _object["hello"].is()); - } - - SECTION("volatile int") { // issue #415 - volatile int i = 123; - _object["hello"] = i; - - REQUIRE(123 == _object["hello"].as()); - REQUIRE(true == _object["hello"].is()); - REQUIRE(false == _object["hello"].is()); - } - - SECTION("double") { - _object["hello"] = 123.45; - - REQUIRE(true == _object["hello"].is()); - REQUIRE(false == _object["hello"].is()); - REQUIRE(123.45 == _object["hello"].as()); - } - - SECTION("bool") { - _object["hello"] = true; - - REQUIRE(true == _object["hello"].is()); - REQUIRE(false == _object["hello"].is()); - REQUIRE(true == _object["hello"].as()); - } - - SECTION("const char*") { - _object["hello"] = "h3110"; - - REQUIRE(true == _object["hello"].is()); - REQUIRE(false == _object["hello"].is()); - REQUIRE(std::string("h3110") == _object["hello"].as()); - REQUIRE(std::string("h3110") == - _object["hello"].as()); // <- short hand - } - - SECTION("array") { - JsonArray& arr = _jsonBuffer.createArray(); - - _object["hello"] = arr; - - REQUIRE(&arr == &_object["hello"].as()); - REQUIRE(&arr == &_object["hello"].as()); // <- short hand - REQUIRE(&arr == &_object["hello"].as()); - REQUIRE(&arr == &_object["hello"].as()); // <- short hand - REQUIRE(true == _object["hello"].is()); - REQUIRE(true == _object["hello"].is()); - REQUIRE(true == _object["hello"].is()); - REQUIRE(true == _object["hello"].is()); - REQUIRE(false == _object["hello"].is()); - } - - SECTION("object") { - JsonObject& obj = _jsonBuffer.createObject(); - - _object["hello"] = obj; - - REQUIRE(&obj == &_object["hello"].as()); - REQUIRE(&obj == &_object["hello"].as()); // <- short hand - REQUIRE(&obj == &_object["hello"].as()); - REQUIRE(&obj == &_object["hello"].as()); // <- short hand - REQUIRE(true == _object["hello"].is()); - REQUIRE(true == _object["hello"].is()); - REQUIRE(true == _object["hello"].is()); - REQUIRE(true == _object["hello"].is()); - REQUIRE(false == _object["hello"].is()); - } - - SECTION("array subscript") { - JsonArray& arr = _jsonBuffer.createArray(); - arr.add(42); - - _object["a"] = arr[0]; - - REQUIRE(42 == _object["a"]); - } - - SECTION("object subscript") { - JsonObject& obj = _jsonBuffer.createObject(); - obj.set("x", 42); - - _object["a"] = obj["x"]; - - REQUIRE(42 == _object["a"]); - } - - SECTION("char key[]") { // issue #423 - char key[] = "hello"; - _object[key] = 42; - REQUIRE(42 == _object[key]); - } - - SECTION("should not duplicate const char*") { - _object["hello"] = "world"; - const size_t expectedSize = JSON_OBJECT_SIZE(1); - REQUIRE(expectedSize == _jsonBuffer.size()); - } - - SECTION("should duplicate char* value") { - _object["hello"] = const_cast("world"); - const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; - REQUIRE(expectedSize == _jsonBuffer.size()); - } - - SECTION("should duplicate char* key") { - _object[const_cast("hello")] = "world"; - const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; - REQUIRE(expectedSize == _jsonBuffer.size()); - } - - SECTION("should duplicate char* key&value") { - _object[const_cast("hello")] = const_cast("world"); - const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12; - REQUIRE(expectedSize <= _jsonBuffer.size()); - } - - SECTION("should duplicate std::string value") { - _object["hello"] = std::string("world"); - const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; - REQUIRE(expectedSize == _jsonBuffer.size()); - } - - SECTION("should duplicate std::string key") { - _object[std::string("hello")] = "world"; - const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; - REQUIRE(expectedSize == _jsonBuffer.size()); - } - - SECTION("should duplicate std::string key&value") { - _object[std::string("hello")] = std::string("world"); - const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12; - REQUIRE(expectedSize <= _jsonBuffer.size()); - } -} diff --git a/lib/ArduinoJson/test/JsonVariant/CMakeLists.txt b/lib/ArduinoJson/test/JsonVariant/CMakeLists.txt deleted file mode 100644 index 0a00a15a..00000000 --- a/lib/ArduinoJson/test/JsonVariant/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -# ArduinoJson - arduinojson.org -# Copyright Benoit Blanchon 2014-2018 -# MIT License - -add_executable(JsonVariantTests - as.cpp - compare.cpp - copy.cpp - is.cpp - or.cpp - printTo.cpp - set_get.cpp - subscript.cpp - success.cpp - undefined.cpp -) - -target_link_libraries(JsonVariantTests catch) -add_test(JsonVariant JsonVariantTests) diff --git a/lib/ArduinoJson/test/JsonVariant/as.cpp b/lib/ArduinoJson/test/JsonVariant/as.cpp deleted file mode 100644 index 6d3b11cc..00000000 --- a/lib/ArduinoJson/test/JsonVariant/as.cpp +++ /dev/null @@ -1,232 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include -#include - -static const char* null = 0; - -TEST_CASE("JsonVariant::as()") { - SECTION("DoubleAsBool") { - JsonVariant variant = 4.2; - REQUIRE(variant.as()); - } - - SECTION("DoubleAsCstr") { - JsonVariant variant = 4.2; - REQUIRE_FALSE(variant.as()); - } - - SECTION("DoubleAsString") { - JsonVariant variant = 4.2; - REQUIRE(std::string("4.2") == variant.as()); - } - - SECTION("DoubleAsLong") { - JsonVariant variant = 4.2; - REQUIRE(4L == variant.as()); - } - - SECTION("DoubleAsUnsigned") { - JsonVariant variant = 4.2; - REQUIRE(4U == variant.as()); - } - - SECTION("DoubleZeroAsBool") { - JsonVariant variant = 0.0; - REQUIRE_FALSE(variant.as()); - } - - SECTION("DoubleZeroAsLong") { - JsonVariant variant = 0.0; - REQUIRE(0L == variant.as()); - } - - SECTION("FalseAsBool") { - JsonVariant variant = false; - REQUIRE_FALSE(variant.as()); - } - - SECTION("FalseAsDouble") { - JsonVariant variant = false; - REQUIRE(0.0 == variant.as()); - } - - SECTION("FalseAsLong") { - JsonVariant variant = false; - REQUIRE(0L == variant.as()); - } - - SECTION("FalseAsString") { - JsonVariant variant = false; - REQUIRE(std::string("false") == variant.as()); - } - - SECTION("TrueAsBool") { - JsonVariant variant = true; - REQUIRE(variant.as()); - } - - SECTION("TrueAsDouble") { - JsonVariant variant = true; - REQUIRE(1.0 == variant.as()); - } - - SECTION("TrueAsLong") { - JsonVariant variant = true; - REQUIRE(1L == variant.as()); - } - - SECTION("TrueAsString") { - JsonVariant variant = true; - REQUIRE(std::string("true") == variant.as()); - } - - SECTION("LongAsBool") { - JsonVariant variant = 42L; - REQUIRE(variant.as()); - } - - SECTION("LongZeroAsBool") { - JsonVariant variant = 0L; - REQUIRE_FALSE(variant.as()); - } - - SECTION("PositiveLongAsDouble") { - JsonVariant variant = 42L; - REQUIRE(42.0 == variant.as()); - } - - SECTION("NegativeLongAsDouble") { - JsonVariant variant = -42L; - REQUIRE(-42.0 == variant.as()); - } - - SECTION("LongAsString") { - JsonVariant variant = 42L; - REQUIRE(std::string("42") == variant.as()); - } - - SECTION("LongZeroAsDouble") { - JsonVariant variant = 0L; - REQUIRE(0.0 == variant.as()); - } - - SECTION("NullAsBool") { - JsonVariant variant = null; - REQUIRE_FALSE(variant.as()); - } - - SECTION("NullAsDouble") { - JsonVariant variant = null; - REQUIRE(0.0 == variant.as()); - } - - SECTION("NullAsLong") { - JsonVariant variant = null; - REQUIRE(0L == variant.as()); - } - - SECTION("NullAsString") { - JsonVariant variant = null; - REQUIRE(std::string("null") == variant.as()); - } - - SECTION("NumberStringAsBool") { - JsonVariant variant = "42"; - REQUIRE(variant.as()); - } - - SECTION("NumberStringAsLong") { - JsonVariant variant = "42"; - REQUIRE(42L == variant.as()); - } - -#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 - SECTION("NumberStringAsInt64Negative") { - JsonVariant variant = "-9223372036854775808"; - REQUIRE(-9223372036854775807 - 1 == variant.as()); - } - - SECTION("NumberStringAsInt64Positive") { - JsonVariant variant = "9223372036854775807"; - REQUIRE(9223372036854775807 == variant.as()); - } -#endif - - SECTION("RandomStringAsBool") { - JsonVariant variant = "hello"; - REQUIRE_FALSE(variant.as()); - } - - SECTION("RandomStringAsLong") { - JsonVariant variant = "hello"; - REQUIRE(0L == variant.as()); - } - - SECTION("RandomStringAsConstCharPtr") { - JsonVariant variant = "hello"; - REQUIRE(std::string("hello") == variant.as()); - } - - SECTION("RandomStringAsCharPtr") { - JsonVariant variant = "hello"; - REQUIRE(std::string("hello") == variant.as()); - } - - SECTION("RandomStringAsString") { - JsonVariant variant = "hello"; - REQUIRE(std::string("hello") == variant.as()); - } - - SECTION("TrueStringAsBool") { - JsonVariant variant = "true"; - REQUIRE(variant.as()); - } - - SECTION("TrueStringAsLong") { - JsonVariant variant = "true"; - REQUIRE(1L == variant.as()); - } - - SECTION("ObjectAsString") { - DynamicJsonBuffer buffer; - - JsonObject& obj = buffer.createObject(); - obj["key"] = "value"; - - JsonVariant variant = obj; - REQUIRE(std::string("{\"key\":\"value\"}") == variant.as()); - } - - SECTION("ArrayAsString") { - DynamicJsonBuffer buffer; - - JsonArray& arr = buffer.createArray(); - arr.add(4); - arr.add(2); - - JsonVariant variant = arr; - REQUIRE(std::string("[4,2]") == variant.as()); - } - - SECTION("ArrayAsJsonArray") { - DynamicJsonBuffer buffer; - JsonArray& arr = buffer.createArray(); - - JsonVariant variant = arr; - REQUIRE(&arr == &variant.as()); - REQUIRE(&arr == &variant.as()); // <- shorthand - } - - SECTION("ObjectAsJsonObject") { - DynamicJsonBuffer buffer; - JsonObject& arr = buffer.createObject(); - - JsonVariant variant = arr; - REQUIRE(&arr == &variant.as()); - REQUIRE(&arr == &variant.as()); // <- shorthand - } -} diff --git a/lib/ArduinoJson/test/JsonVariant/compare.cpp b/lib/ArduinoJson/test/JsonVariant/compare.cpp deleted file mode 100644 index 965ec8ef..00000000 --- a/lib/ArduinoJson/test/JsonVariant/compare.cpp +++ /dev/null @@ -1,232 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -template -void checkEquals(JsonVariant a, T b) { - REQUIRE(b == a); - REQUIRE(a == b); - REQUIRE(b <= a); - REQUIRE(a <= b); - REQUIRE(b >= a); - REQUIRE(a >= b); - - REQUIRE_FALSE(b != a); - REQUIRE_FALSE(a != b); - REQUIRE_FALSE(b > a); - REQUIRE_FALSE(a > b); - REQUIRE_FALSE(b < a); - REQUIRE_FALSE(a < b); -} - -template -void checkGreater(JsonVariant a, T b) { - REQUIRE(a > b); - REQUIRE(b < a); - REQUIRE(a != b); - REQUIRE(b != a); - - REQUIRE_FALSE(a < b); - REQUIRE_FALSE(b > a); - REQUIRE_FALSE(a == b); - REQUIRE_FALSE(b == a); -} - -template -void checkLower(JsonVariant a, T b) { - REQUIRE(a < b); - REQUIRE(b > a); - REQUIRE(a != b); - REQUIRE(b != a); - - REQUIRE_FALSE(a > b); - REQUIRE_FALSE(b < a); - REQUIRE_FALSE(a == b); - REQUIRE_FALSE(b == a); -} - -template -void checkComparisons(T low, T mid, T high) { - checkEquals(mid, mid); - checkGreater(mid, low); - checkLower(mid, high); -} - -TEST_CASE("JsonVariant comparisons") { - SECTION("Double") { - checkComparisons(123.44, 123.45, 123.46); - } - - SECTION("Float") { - checkComparisons(123.44f, 123.45f, 123.46f); - } - - SECTION("SChar") { - checkComparisons(122, 123, 124); - } - - SECTION("SInt") { - checkComparisons(122, 123, 124); - } - - SECTION("SLong") { - checkComparisons(122L, 123L, 124L); - } - - SECTION("SShort") { - checkComparisons(122, 123, 124); - } - - SECTION("UChar") { - checkComparisons(122, 123, 124); - } - - SECTION("UInt") { - checkComparisons(122, 123, 124); - } - - SECTION("ULong") { - checkComparisons(122L, 123L, 124L); - } - - SECTION("UShort") { - checkComparisons(122, 123, 124); - } - - SECTION("StringLiteral") { - DynamicJsonBuffer jsonBuffer; - JsonVariant variant = jsonBuffer.parse("\"hello\""); - - REQUIRE(variant == "hello"); - REQUIRE_FALSE(variant != "hello"); - - REQUIRE(variant != "world"); - REQUIRE_FALSE(variant == "world"); - - REQUIRE("hello" == variant); - REQUIRE_FALSE("hello" != variant); - - REQUIRE("world" != variant); - REQUIRE_FALSE("world" == variant); - } - - SECTION("String") { - DynamicJsonBuffer jsonBuffer; - JsonVariant variant = jsonBuffer.parse("\"hello\""); - - REQUIRE(variant == std::string("hello")); - REQUIRE_FALSE(variant != std::string("hello")); - - REQUIRE(variant != std::string("world")); - REQUIRE_FALSE(variant == std::string("world")); - - REQUIRE(std::string("hello") == variant); - REQUIRE_FALSE(std::string("hello") != variant); - - REQUIRE(std::string("world") != variant); - REQUIRE_FALSE(std::string("world") == variant); - } - - SECTION("IntegerInVariant") { - JsonVariant variant1 = 42; - JsonVariant variant2 = 42; - JsonVariant variant3 = 666; - - REQUIRE(variant1 == variant2); - REQUIRE_FALSE(variant1 != variant2); - - REQUIRE(variant1 != variant3); - REQUIRE_FALSE(variant1 == variant3); - } - - SECTION("StringInVariant") { - JsonVariant variant1 = "0hello" + 1; // make sure they have - JsonVariant variant2 = "1hello" + 1; // different addresses - JsonVariant variant3 = "world"; - - REQUIRE(variant1 == variant2); - REQUIRE_FALSE(variant1 != variant2); - - REQUIRE(variant1 != variant3); - REQUIRE_FALSE(variant1 == variant3); - } - - SECTION("DoubleInVariant") { - JsonVariant variant1 = 42.0; - JsonVariant variant2 = 42.0; - JsonVariant variant3 = 666.0; - - REQUIRE(variant1 == variant2); - REQUIRE_FALSE(variant1 != variant2); - - REQUIRE(variant1 != variant3); - REQUIRE_FALSE(variant1 == variant3); - } - - SECTION("BoolInVariant") { - JsonVariant variant1 = true; - JsonVariant variant2 = true; - JsonVariant variant3 = false; - - REQUIRE(variant1 == variant2); - REQUIRE_FALSE(variant1 != variant2); - - REQUIRE(variant1 != variant3); - REQUIRE_FALSE(variant1 == variant3); - } - - SECTION("ArrayInVariant") { - DynamicJsonBuffer jsonBuffer; - JsonArray& array1 = jsonBuffer.createArray(); - JsonArray& array2 = jsonBuffer.createArray(); - - JsonVariant variant1 = array1; - JsonVariant variant2 = array1; - JsonVariant variant3 = array2; - - REQUIRE(variant1 == variant2); - REQUIRE_FALSE(variant1 != variant2); - - REQUIRE(variant1 != variant3); - REQUIRE_FALSE(variant1 == variant3); - } - - SECTION("ObjectInVariant") { - DynamicJsonBuffer jsonBuffer; - JsonObject& obj1 = jsonBuffer.createObject(); - JsonObject& obj2 = jsonBuffer.createObject(); - - JsonVariant variant1 = obj1; - JsonVariant variant2 = obj1; - JsonVariant variant3 = obj2; - - REQUIRE(variant1 == variant2); - REQUIRE_FALSE(variant1 != variant2); - - REQUIRE(variant1 != variant3); - REQUIRE_FALSE(variant1 == variant3); - } - - SECTION("VariantsOfDifferentTypes") { - DynamicJsonBuffer jsonBuffer; - JsonVariant variants[] = { - true, - 42, - 666.667, - "hello", - jsonBuffer.createArray(), - jsonBuffer.createObject(), - }; - size_t n = sizeof(variants) / sizeof(variants[0]); - - for (size_t i = 0; i < n; i++) { - for (size_t j = i + 1; j < n; j++) { - REQUIRE(variants[i] != variants[j]); - REQUIRE_FALSE(variants[i] == variants[j]); - } - } - } -} diff --git a/lib/ArduinoJson/test/JsonVariant/copy.cpp b/lib/ArduinoJson/test/JsonVariant/copy.cpp deleted file mode 100644 index 50e0a3bf..00000000 --- a/lib/ArduinoJson/test/JsonVariant/copy.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("JsonVariant copy") { - DynamicJsonBuffer _jsonBuffer; - JsonVariant _variant1; - JsonVariant _variant2; - - SECTION("IntegersAreCopiedByValue") { - _variant1 = 123; - _variant2 = _variant1; - _variant1 = 456; - - REQUIRE(123 == _variant2.as()); - } - - SECTION("DoublesAreCopiedByValue") { - _variant1 = 123.45; - _variant2 = _variant1; - _variant1 = 456.78; - - REQUIRE(123.45 == _variant2.as()); - } - - SECTION("BooleansAreCopiedByValue") { - _variant1 = true; - _variant2 = _variant1; - _variant1 = false; - - REQUIRE(_variant2.as()); - } - - SECTION("StringsAreCopiedByValue") { - _variant1 = "hello"; - _variant2 = _variant1; - _variant1 = "world"; - - REQUIRE(std::string("hello") == _variant2.as()); - } - - SECTION("ObjectsAreCopiedByReference") { - JsonObject &object = _jsonBuffer.createObject(); - - _variant1 = object; - - object["hello"] = "world"; - - REQUIRE(1 == _variant1.as().size()); - } - - SECTION("ArraysAreCopiedByReference") { - JsonArray &array = _jsonBuffer.createArray(); - - _variant1 = array; - - array.add("world"); - - REQUIRE(1 == _variant1.as().size()); - } -} diff --git a/lib/ArduinoJson/test/JsonVariant/is.cpp b/lib/ArduinoJson/test/JsonVariant/is.cpp deleted file mode 100644 index 1bb03cbb..00000000 --- a/lib/ArduinoJson/test/JsonVariant/is.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -void checkIsArray(JsonVariant var) { - REQUIRE(var.is()); - REQUIRE(var.is()); - REQUIRE(var.is()); - REQUIRE(var.is()); - - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); -} - -void checkIsBool(JsonVariant var) { - REQUIRE(var.is()); - - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); -} - -void checkIsFloat(JsonVariant var) { - REQUIRE(var.is()); - REQUIRE(var.is()); - - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); -} - -void checkIsInteger(JsonVariant var) { - REQUIRE(var.is()); - REQUIRE(var.is()); - REQUIRE(var.is()); - REQUIRE(var.is()); - - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); -} - -void checkIsString(JsonVariant var) { - REQUIRE(var.is()); - - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); -} - -TEST_CASE("JsonVariant::is()") { - DynamicJsonBuffer jsonBuffer; - - SECTION("JsonArray") { - checkIsArray(jsonBuffer.createArray()); - } - - SECTION("bool") { - checkIsBool(true); - checkIsBool(false); - } - - SECTION("double") { - checkIsFloat(4.2); - } - - SECTION("int") { - checkIsInteger(42); - } - - SECTION("long") { - checkIsInteger(42L); - } - - SECTION("string") { - checkIsString("42"); - } - - SECTION("unparsed bool") { - checkIsBool(RawJson("true")); - checkIsBool(RawJson("false")); - } - - SECTION("unparsed int") { - checkIsInteger(RawJson("42")); - } - - SECTION("unparsed float") { - checkIsFloat(RawJson("4.2e-10")); - } - - SECTION("unparsed null") { - checkIsString(RawJson("null")); - } -} diff --git a/lib/ArduinoJson/test/JsonVariant/or.cpp b/lib/ArduinoJson/test/JsonVariant/or.cpp deleted file mode 100644 index 84349463..00000000 --- a/lib/ArduinoJson/test/JsonVariant/or.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -static const JsonVariant undefined; -static const JsonVariant null = static_cast(0); - -TEST_CASE("JsonVariant::operator|()") { - SECTION("undefined | const char*") { - std::string result = undefined | "default"; - REQUIRE(result == "default"); - } - - SECTION("undefined | int") { - int result = undefined | 42; - REQUIRE(result == 42); - } - - SECTION("undefined | bool") { - bool result = undefined | true; - REQUIRE(result == true); - } - - SECTION("null | const char*") { - std::string result = null | "default"; - REQUIRE(result == "default"); - } - - SECTION("null | int") { - int result = null | 42; - REQUIRE(result == 42); - } - - SECTION("null | bool") { - bool result = null | true; - REQUIRE(result == true); - } - - SECTION("int | const char*") { - JsonVariant variant = 42; - std::string result = variant | "default"; - REQUIRE(result == "default"); - } - - SECTION("int | int") { - JsonVariant variant = 0; - int result = variant | 666; - REQUIRE(result == 0); - } - - SECTION("double | int") { - JsonVariant variant = 42.0; - int result = variant | 666; - REQUIRE(result == 42); - } - - SECTION("bool | bool") { - JsonVariant variant = false; - bool result = variant | true; - REQUIRE(result == false); - } - - SECTION("int | bool") { - JsonVariant variant = 0; - bool result = variant | true; - REQUIRE(result == true); - } - - SECTION("const char* | const char*") { - JsonVariant variant = "not default"; - std::string result = variant | "default"; - REQUIRE(result == "not default"); - } - - SECTION("const char* | int") { - JsonVariant variant = "not default"; - int result = variant | 42; - REQUIRE(result == 42); - } -} diff --git a/lib/ArduinoJson/test/JsonVariant/printTo.cpp b/lib/ArduinoJson/test/JsonVariant/printTo.cpp deleted file mode 100644 index 3431eaee..00000000 --- a/lib/ArduinoJson/test/JsonVariant/printTo.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include -#include - -void check(JsonVariant variant, const std::string &expected) { - char buffer[256] = ""; - size_t returnValue = variant.printTo(buffer, sizeof(buffer)); - REQUIRE(expected == buffer); - REQUIRE(expected.size() == returnValue); -} - -TEST_CASE("JsonVariant::printTo()") { - SECTION("Empty") { - check(JsonVariant(), ""); - } - - SECTION("Null") { - check(static_cast(0), "null"); - } - - SECTION("String") { - check("hello", "\"hello\""); - } - - SECTION("Double") { - check(3.1415927, "3.1415927"); - } - - SECTION("Integer") { - check(42, "42"); - } - - SECTION("NegativeLong") { - check(-42, "-42"); - } - - SECTION("UnsignedLong") { - check(4294967295UL, "4294967295"); - } - - SECTION("True") { - check(true, "true"); - } - - SECTION("OneFalse") { - check(false, "false"); - } - -#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 - SECTION("NegativeInt64") { - check(-9223372036854775807 - 1, "-9223372036854775808"); - } - - SECTION("PositiveInt64") { - check(9223372036854775807, "9223372036854775807"); - } - - SECTION("UInt64") { - check(18446744073709551615U, "18446744073709551615"); - } -#endif -} diff --git a/lib/ArduinoJson/test/JsonVariant/set_get.cpp b/lib/ArduinoJson/test/JsonVariant/set_get.cpp deleted file mode 100644 index af68c8b0..00000000 --- a/lib/ArduinoJson/test/JsonVariant/set_get.cpp +++ /dev/null @@ -1,130 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include -#include -#include - -template -void checkValue(T expected) { - JsonVariant variant = expected; - REQUIRE(expected == variant.as()); -} - -template -void checkReference(T &expected) { - JsonVariant variant = expected; - REQUIRE(expected == variant.as()); -} - -template -void checkNumericType() { - T min = std::numeric_limits::min(); - T max = std::numeric_limits::max(); - - JsonVariant variantMin(min); - JsonVariant variantMax(max); - - REQUIRE(min == variantMin.as()); - REQUIRE(max == variantMax.as()); -} - -TEST_CASE("JsonVariant set()/get()") { -#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 - SECTION("SizeOfJsonInteger") { - REQUIRE(8 == sizeof(Internals::JsonInteger)); - } -#endif - - SECTION("Null") { - checkValue(NULL); - } - SECTION("String") { - checkValue("hello"); - } - - SECTION("False") { - checkValue(false); - } - SECTION("True") { - checkValue(true); - } - - SECTION("Double") { - checkNumericType(); - } - SECTION("Float") { - checkNumericType(); - } - SECTION("Char") { - checkNumericType(); - } - SECTION("SChar") { - checkNumericType(); - } - SECTION("SInt") { - checkNumericType(); - } - SECTION("SLong") { - checkNumericType(); - } - SECTION("SShort") { - checkNumericType(); - } - SECTION("UChar") { - checkNumericType(); - } - SECTION("UInt") { - checkNumericType(); - } - SECTION("ULong") { - checkNumericType(); - } - SECTION("UShort") { - checkNumericType(); - } -#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 - SECTION("LongLong") { - checkNumericType(); - } - SECTION("ULongLong") { - checkNumericType(); - } -#endif - - SECTION("Int8") { - checkNumericType(); - } - SECTION("Uint8") { - checkNumericType(); - } - SECTION("Int16") { - checkNumericType(); - } - SECTION("Uint16") { - checkNumericType(); - } - SECTION("Int32") { - checkNumericType(); - } - SECTION("Uint32") { - checkNumericType(); - } -#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 - SECTION("Int64") { - checkNumericType(); - } - SECTION("Uint64") { - checkNumericType(); - } -#endif - - SECTION("CanStoreObject") { - DynamicJsonBuffer jsonBuffer; - JsonObject &object = jsonBuffer.createObject(); - - checkReference(object); - } -} diff --git a/lib/ArduinoJson/test/JsonVariant/subscript.cpp b/lib/ArduinoJson/test/JsonVariant/subscript.cpp deleted file mode 100644 index 5ce13e6f..00000000 --- a/lib/ArduinoJson/test/JsonVariant/subscript.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("JsonVariant::operator[]") { - DynamicJsonBuffer _jsonBuffer; - - SECTION("Array") { - JsonArray &array = _jsonBuffer.createArray(); - array.add("element at index 0"); - array.add("element at index 1"); - - JsonVariant var = array; - - REQUIRE(2 == var.size()); - REQUIRE(std::string("element at index 0") == var[0]); - REQUIRE(std::string("element at index 1") == var[1]); - REQUIRE(std::string("element at index 0") == - var[static_cast(0)]); // issue #381 - REQUIRE_FALSE(var[666].success()); - REQUIRE_FALSE(var[3].success()); - REQUIRE_FALSE(var["0"].success()); - } - - SECTION("Object") { - JsonObject &object = _jsonBuffer.createObject(); - object["a"] = "element at key \"a\""; - object["b"] = "element at key \"b\""; - - JsonVariant var = object; - - REQUIRE(2 == var.size()); - REQUIRE(std::string("element at key \"a\"") == var["a"]); - REQUIRE(std::string("element at key \"b\"") == var["b"]); - REQUIRE_FALSE(var["c"].success()); - REQUIRE_FALSE(var[0].success()); - } - - SECTION("Undefined") { - JsonVariant var = JsonVariant(); - REQUIRE(0 == var.size()); - REQUIRE_FALSE(var["0"].success()); - REQUIRE_FALSE(var[0].success()); - } - - SECTION("String") { - JsonVariant var = "hello world"; - REQUIRE(0 == var.size()); - REQUIRE_FALSE(var["0"].success()); - REQUIRE_FALSE(var[0].success()); - } - - SECTION("ObjectSetValue") { - JsonVariant var = _jsonBuffer.createObject(); - var["hello"] = "world"; - REQUIRE(1 == var.size()); - REQUIRE(std::string("world") == var["hello"]); - } - - SECTION("ArraySetValue") { - JsonVariant var = _jsonBuffer.parseArray("[\"hello\"]"); - var[0] = "world"; - REQUIRE(1 == var.size()); - REQUIRE(std::string("world") == var[0]); - } - - SECTION("NestedObjectSetValue") { - JsonVariant var = _jsonBuffer.parseArray("[{}]"); - var[0]["hello"] = "world"; - REQUIRE(1 == var.size()); - REQUIRE(1 == var[0].size()); - REQUIRE(std::string("world") == var[0]["hello"]); - } -} diff --git a/lib/ArduinoJson/test/JsonVariant/success.cpp b/lib/ArduinoJson/test/JsonVariant/success.cpp deleted file mode 100644 index af8aad94..00000000 --- a/lib/ArduinoJson/test/JsonVariant/success.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("JsonVariant::success()") { - SECTION("ReturnsFalse_WhenUndefined") { - JsonVariant variant; - REQUIRE(false == variant.success()); - } - - SECTION("ReturnsTrue_WhenInteger") { - JsonVariant variant = 0; - REQUIRE(true == variant.success()); - } - - SECTION("ReturnsTrue_WhenEmptyArray") { - DynamicJsonBuffer jsonBuffer; - - JsonVariant variant = jsonBuffer.createArray(); - REQUIRE(true == variant.success()); - } - - SECTION("ReturnsTrue_WhenEmptyObject") { - DynamicJsonBuffer jsonBuffer; - - JsonVariant variant = jsonBuffer.createObject(); - REQUIRE(true == variant.success()); - } - - SECTION("ReturnsFalse_WhenInvalidArray") { - JsonVariant variant = JsonArray::invalid(); - REQUIRE(false == variant.success()); - } - - SECTION("ReturnsFalse_WhenInvalidObject") { - JsonVariant variant = JsonObject::invalid(); - REQUIRE(false == variant.success()); - } -} diff --git a/lib/ArduinoJson/test/JsonVariant/undefined.cpp b/lib/ArduinoJson/test/JsonVariant/undefined.cpp deleted file mode 100644 index 9615f0f4..00000000 --- a/lib/ArduinoJson/test/JsonVariant/undefined.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("JsonVariant undefined") { - JsonVariant variant; - - SECTION("AsLongReturns0") { - REQUIRE(0 == variant.as()); - } - - SECTION("AsUnsignedReturns0") { - REQUIRE(0 == variant.as()); - } - - SECTION("AsStringReturnsNull") { - REQUIRE(0 == variant.as()); - } - - SECTION("AsDoubleReturns0") { - REQUIRE(0 == variant.as()); - } - - SECTION("AsBoolReturnsFalse") { - REQUIRE(false == variant.as()); - } - - SECTION("AsArrayReturnInvalid") { - REQUIRE(JsonArray::invalid() == variant.as()); - } - - SECTION("AsConstArrayReturnInvalid") { - REQUIRE(JsonArray::invalid() == variant.as()); - } - - SECTION("AsObjectReturnInvalid") { - REQUIRE(JsonObject::invalid() == variant.as()); - } - - SECTION("AsConstObjectReturnInvalid") { - REQUIRE(JsonObject::invalid() == variant.as()); - } - - SECTION("AsArrayWrapperReturnInvalid") { - REQUIRE(JsonArray::invalid() == variant.as()); - } - - SECTION("AsObjectWrapperReturnInvalid") { - REQUIRE(JsonObject::invalid() == variant.as()); - } -} diff --git a/lib/ArduinoJson/test/JsonWriter/CMakeLists.txt b/lib/ArduinoJson/test/JsonWriter/CMakeLists.txt deleted file mode 100644 index 12a12bfd..00000000 --- a/lib/ArduinoJson/test/JsonWriter/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# ArduinoJson - arduinojson.org -# Copyright Benoit Blanchon 2014-2018 -# MIT License - -add_executable(JsonWriterTests - writeFloat.cpp - writeString.cpp -) - -target_link_libraries(JsonWriterTests catch) -add_test(JsonWriter JsonWriterTests) diff --git a/lib/ArduinoJson/test/JsonWriter/writeFloat.cpp b/lib/ArduinoJson/test/JsonWriter/writeFloat.cpp deleted file mode 100644 index 532de5dc..00000000 --- a/lib/ArduinoJson/test/JsonWriter/writeFloat.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include -#include - -#include -#include - -using namespace ArduinoJson::Internals; - -template -void check(TFloat input, const std::string& expected) { - std::string output; - DynamicStringBuilder sb(output); - JsonWriter > writer(sb); - writer.writeFloat(input); - REQUIRE(writer.bytesWritten() == output.size()); - CHECK(expected == output); -} - -TEST_CASE("JsonWriter::writeFloat(double)") { - SECTION("Pi") { - check(3.14159265359, "3.141592654"); - } - - SECTION("Signaling NaN") { - double nan = std::numeric_limits::signaling_NaN(); - check(nan, "NaN"); - } - - SECTION("Quiet NaN") { - double nan = std::numeric_limits::quiet_NaN(); - check(nan, "NaN"); - } - - SECTION("Infinity") { - double inf = std::numeric_limits::infinity(); - check(inf, "Infinity"); - check(-inf, "-Infinity"); - } - - SECTION("Zero") { - check(0.0, "0"); - check(-0.0, "0"); - } - - SECTION("Espilon") { - check(2.2250738585072014E-308, "2.225073859e-308"); - check(-2.2250738585072014E-308, "-2.225073859e-308"); - } - - SECTION("Max double") { - check(1.7976931348623157E+308, "1.797693135e308"); - check(-1.7976931348623157E+308, "-1.797693135e308"); - } - - SECTION("Big exponent") { - // this test increases coverage of normalize() - check(1e255, "1e255"); - check(1e-255, "1e-255"); - } - - SECTION("Exponentation when <= 1e-5") { - check(1e-4, "0.0001"); - check(1e-5, "1e-5"); - - check(-1e-4, "-0.0001"); - check(-1e-5, "-1e-5"); - } - - SECTION("Exponentation when >= 1e7") { - check(9999999.999, "9999999.999"); - check(10000000.0, "1e7"); - - check(-9999999.999, "-9999999.999"); - check(-10000000.0, "-1e7"); - } - - SECTION("Rounding when too many decimals") { - check(0.000099999999999, "0.0001"); - check(0.0000099999999999, "1e-5"); - check(0.9999999996, "1"); - } - - SECTION("9 decimal places") { - check(0.100000001, "0.100000001"); - check(0.999999999, "0.999999999"); - - check(9.000000001, "9.000000001"); - check(9.999999999, "9.999999999"); - } - - SECTION("10 decimal places") { - check(0.1000000001, "0.1"); - check(0.9999999999, "1"); - - check(9.0000000001, "9"); - check(9.9999999999, "10"); - } -} - -TEST_CASE("JsonWriter::writeFloat(float)") { - SECTION("Pi") { - check(3.14159265359f, "3.141593"); - } - - SECTION("999.9") { // issue #543 - check(999.9f, "999.9"); - } - - SECTION("24.3") { // # issue #588 - check(24.3f, "24.3"); - } -} diff --git a/lib/ArduinoJson/test/JsonWriter/writeString.cpp b/lib/ArduinoJson/test/JsonWriter/writeString.cpp deleted file mode 100644 index e583fbcf..00000000 --- a/lib/ArduinoJson/test/JsonWriter/writeString.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include - -#include -#include - -using namespace ArduinoJson::Internals; - -void check(const char* input, std::string expected) { - char output[1024]; - StaticStringBuilder sb(output, sizeof(output)); - JsonWriter writer(sb); - writer.writeString(input); - REQUIRE(expected == output); - REQUIRE(writer.bytesWritten() == expected.size()); -} - -TEST_CASE("JsonWriter::writeString()") { - SECTION("Null") { - check(0, "null"); - } - - SECTION("EmptyString") { - check("", "\"\""); - } - - SECTION("QuotationMark") { - check("\"", "\"\\\"\""); - } - - SECTION("ReverseSolidus") { - check("\\", "\"\\\\\""); - } - - SECTION("Solidus") { - check("/", "\"/\""); // but the JSON format allows \/ - } - - SECTION("Backspace") { - check("\b", "\"\\b\""); - } - - SECTION("Formfeed") { - check("\f", "\"\\f\""); - } - - SECTION("Newline") { - check("\n", "\"\\n\""); - } - - SECTION("CarriageReturn") { - check("\r", "\"\\r\""); - } - - SECTION("HorizontalTab") { - check("\t", "\"\\t\""); - } -} diff --git a/lib/ArduinoJson/test/Misc/CMakeLists.txt b/lib/ArduinoJson/test/Misc/CMakeLists.txt deleted file mode 100644 index 0b54bd7b..00000000 --- a/lib/ArduinoJson/test/Misc/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# ArduinoJson - arduinojson.org -# Copyright Benoit Blanchon 2014-2018 -# MIT License - -add_executable(MiscTests - deprecated.cpp - FloatParts.cpp - std_stream.cpp - std_string.cpp - StringBuilder.cpp - StringTraits.cpp - TypeTraits.cpp - unsigned_char.cpp - vla.cpp -) - -target_link_libraries(MiscTests catch) -add_test(Misc MiscTests) diff --git a/lib/ArduinoJson/test/Misc/FloatParts.cpp b/lib/ArduinoJson/test/Misc/FloatParts.cpp deleted file mode 100644 index aeed52e7..00000000 --- a/lib/ArduinoJson/test/Misc/FloatParts.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -using namespace ArduinoJson::Internals; - -TEST_CASE("FloatParts") { - SECTION("1.7976931348623157E+308") { - FloatParts parts(1.7976931348623157E+308); - REQUIRE(parts.integral == 1); - REQUIRE(parts.decimal == 797693135); - REQUIRE(parts.decimalPlaces == 9); - REQUIRE(parts.exponent == 308); - } - - SECTION("4.94065645841247e-324") { - FloatParts parts(4.94065645841247e-324); - REQUIRE(parts.integral == 4); - REQUIRE(parts.decimal == 940656458); - REQUIRE(parts.decimalPlaces == 9); - REQUIRE(parts.exponent == -324); - } -} - -TEST_CASE("FloatParts") { - SECTION("3.4E+38") { - FloatParts parts(3.4E+38f); - REQUIRE(parts.integral == 3); - REQUIRE(parts.decimal == 4); - REQUIRE(parts.decimalPlaces == 1); - REQUIRE(parts.exponent == 38); - } - - SECTION("1.17549435e−38") { - FloatParts parts(1.17549435e-38f); - REQUIRE(parts.integral == 1); - REQUIRE(parts.decimal == 175494); - REQUIRE(parts.decimalPlaces == 6); - REQUIRE(parts.exponent == -38); - } -} diff --git a/lib/ArduinoJson/test/Misc/StringBuilder.cpp b/lib/ArduinoJson/test/Misc/StringBuilder.cpp deleted file mode 100644 index a7132dbd..00000000 --- a/lib/ArduinoJson/test/Misc/StringBuilder.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -using namespace ArduinoJson::Internals; - -template -void common_tests(StringBuilder& sb, const String& output) { - SECTION("InitialState") { - REQUIRE(std::string("") == output); - } - - SECTION("EmptyString") { - REQUIRE(0 == sb.print("")); - REQUIRE(std::string("") == output); - } - - SECTION("OneString") { - REQUIRE(4 == sb.print("ABCD")); - REQUIRE(std::string("ABCD") == output); - } - - SECTION("TwoStrings") { - REQUIRE(4 == sb.print("ABCD")); - REQUIRE(4 == sb.print("EFGH")); - REQUIRE(std::string("ABCDEFGH") == output); - } -} - -TEST_CASE("StaticStringBuilder") { - char output[20]; - StaticStringBuilder sb(output, sizeof(output)); - - common_tests(sb, static_cast(output)); - - SECTION("OverCapacity") { - REQUIRE(19 == sb.print("ABCDEFGHIJKLMNOPQRSTUVWXYZ")); - REQUIRE(0 == sb.print("ABC")); - REQUIRE(std::string("ABCDEFGHIJKLMNOPQRS") == output); - } -} - -TEST_CASE("DynamicStringBuilder") { - std::string output; - DynamicStringBuilder sb(output); - common_tests(sb, output); -} diff --git a/lib/ArduinoJson/test/Misc/StringTraits.cpp b/lib/ArduinoJson/test/Misc/StringTraits.cpp deleted file mode 100644 index db18648c..00000000 --- a/lib/ArduinoJson/test/Misc/StringTraits.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -using namespace ArduinoJson::Internals; - -template -bool should_duplicate() { - return StringTraits::should_duplicate; -} - -TEST_CASE("StringTraits") { - SECTION("should_duplicate") { - REQUIRE(false == should_duplicate()); - REQUIRE(true == should_duplicate()); - REQUIRE(true == should_duplicate >()); - REQUIRE(false == should_duplicate >()); - } -} diff --git a/lib/ArduinoJson/test/Misc/TypeTraits.cpp b/lib/ArduinoJson/test/Misc/TypeTraits.cpp deleted file mode 100644 index 8d730b21..00000000 --- a/lib/ArduinoJson/test/Misc/TypeTraits.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -using namespace ArduinoJson::Internals; - -TEST_CASE("TypeTraits") { - SECTION("IsBaseOf") { - REQUIRE_FALSE( - static_cast(IsBaseOf::value)); - REQUIRE( - static_cast(IsBaseOf::value)); - REQUIRE(static_cast( - IsBaseOf >, - JsonObjectSubscript >::value)); - } - - SECTION("IsArray") { - REQUIRE_FALSE((IsArray::value)); - REQUIRE((IsArray::value)); - REQUIRE((IsArray::value)); - } - - SECTION("IsVariant") { - REQUIRE( - static_cast(IsVariant >::value)); - REQUIRE(static_cast(IsVariant::value)); - } - - SECTION("IsConst") { - REQUIRE_FALSE((IsConst::value)); - REQUIRE((IsConst::value)); - } -} diff --git a/lib/ArduinoJson/test/Misc/deprecated.cpp b/lib/ArduinoJson/test/Misc/deprecated.cpp deleted file mode 100644 index 8fa4fe28..00000000 --- a/lib/ArduinoJson/test/Misc/deprecated.cpp +++ /dev/null @@ -1,140 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#define ARDUINOJSON_ENABLE_DEPRECATED 1 - -#include -#include - -#if defined(__clang__) -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -#elif defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#elif defined(_MSC_VER) -#pragma warning(disable : 4996) -#endif - -TEST_CASE("Deprecated functions") { - DynamicJsonBuffer jsonBuffer; - - SECTION("JsonVariant::asArray()") { - JsonVariant variant = jsonBuffer.createArray(); - REQUIRE(variant.asArray().success()); - } - - SECTION("JsonVariant::asObject()") { - JsonVariant variant = jsonBuffer.createObject(); - REQUIRE(variant.asObject().success()); - } - - SECTION("JsonVariant::asString()") { - JsonVariant variant = "hello"; - REQUIRE(std::string("hello") == variant.asString()); - } - - SECTION("JsonArray::removeAt()") { - JsonArray& arr = jsonBuffer.createArray(); - arr.removeAt(0); - } - - SECTION("JsonVariant::JsonVariant(float, uint8_t)") { - JsonVariant variant(3.14f, 2); - REQUIRE(variant == 3.14f); - } - - SECTION("JsonVariant::JsonVariant(double, uint8_t)") { - JsonVariant variant(3.14, 2); - REQUIRE(variant == 3.14); - } - - SECTION("float_with_n_digits()") { - JsonVariant variant = float_with_n_digits(3.14f, 4); - REQUIRE(variant == 3.14f); - } - - SECTION("double_with_n_digits()") { - JsonVariant variant = double_with_n_digits(3.14f, 4); - REQUIRE(variant == 3.14f); - } - - SECTION("JsonArraySubscript::set(double, uint8_t)") { - JsonArray& arr = jsonBuffer.createArray(); - arr.add(666); - arr[0].set(123.45, 2); - REQUIRE(123.45 == arr[0].as()); - REQUIRE(true == arr[0].is()); - REQUIRE(false == arr[0].is()); - } - - SECTION("JsonArray::add(double, uint8_t)") { - JsonArray& arr = jsonBuffer.createArray(); - arr.add(3.14159265358979323846, 4); - } - - SECTION("JsonArray::add(float, uint8_t)") { - JsonArray& arr = jsonBuffer.createArray(); - arr.add(3.14159265358979323846f, 4); - } - - SECTION("JsonObject::set(unsigned char[], double, uint8_t)") { - unsigned char key[] = "hello"; - - JsonObject& obj = jsonBuffer.createObject(); - obj.set(key, 3.14, 2); - - REQUIRE(3.14 == obj["hello"]); - } - - SECTION("JsonObject::set(const char*, double, uint8_t)") { - JsonObject& obj = jsonBuffer.createObject(); - obj.set("hello", 123.45, 2); - - REQUIRE(123.45 == obj["hello"].as()); - REQUIRE(obj["hello"].is()); - REQUIRE_FALSE(obj["hello"].is()); - } - - SECTION("JsonObjectSubscript::set(double, uint8_t)") { - JsonObject& obj = jsonBuffer.createObject(); - obj["hello"].set(123.45, 2); - - REQUIRE(true == obj["hello"].is()); - REQUIRE(false == obj["hello"].is()); - REQUIRE(123.45 == obj["hello"].as()); - } -} - -TEST_CASE("DynamicJsonBuffer::strdup()") { - DynamicJsonBuffer buffer; - - SECTION("char*") { - char original[] = "hello"; - const char* copy = buffer.strdup(original); - strcpy(original, "world"); - REQUIRE(std::string("hello") == copy); - } - - SECTION("unsigned char*") { - unsigned char value[] = "world"; - - DynamicJsonBuffer jsonBuffer; - const char* dup = jsonBuffer.strdup(value); - - REQUIRE(static_cast(value) != static_cast(dup)); - REQUIRE(std::string("world") == dup); - } - - SECTION("std::string") { - std::string original("hello"); - const char* copy = buffer.strdup(original); - original[0] = 'w'; - REQUIRE(std::string("hello") == copy); - } - - SECTION("NULL") { - const char* original = NULL; - const char* copy = buffer.strdup(original); - REQUIRE(0 == copy); - } -} diff --git a/lib/ArduinoJson/test/Misc/std_stream.cpp b/lib/ArduinoJson/test/Misc/std_stream.cpp deleted file mode 100644 index 170c9418..00000000 --- a/lib/ArduinoJson/test/Misc/std_stream.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include -#include - -TEST_CASE("std::stream") { - SECTION("JsonVariantFalse") { - std::ostringstream os; - JsonVariant variant = false; - os << variant; - REQUIRE("false" == os.str()); - } - - SECTION("JsonVariantString") { - std::ostringstream os; - JsonVariant variant = "coucou"; - os << variant; - REQUIRE("\"coucou\"" == os.str()); - } - - SECTION("JsonObject") { - std::ostringstream os; - DynamicJsonBuffer jsonBuffer; - JsonObject& object = jsonBuffer.createObject(); - object["key"] = "value"; - os << object; - REQUIRE("{\"key\":\"value\"}" == os.str()); - } - - SECTION("JsonObjectSubscript") { - std::ostringstream os; - DynamicJsonBuffer jsonBuffer; - JsonObject& object = jsonBuffer.createObject(); - object["key"] = "value"; - os << object["key"]; - REQUIRE("\"value\"" == os.str()); - } - - SECTION("JsonArray") { - std::ostringstream os; - DynamicJsonBuffer jsonBuffer; - JsonArray& array = jsonBuffer.createArray(); - array.add("value"); - os << array; - REQUIRE("[\"value\"]" == os.str()); - } - - SECTION("JsonArraySubscript") { - std::ostringstream os; - DynamicJsonBuffer jsonBuffer; - JsonArray& array = jsonBuffer.createArray(); - array.add("value"); - os << array[0]; - REQUIRE("\"value\"" == os.str()); - } - - SECTION("ParseArray") { - std::istringstream json(" [ 42 /* comment */ ] "); - DynamicJsonBuffer jsonBuffer; - JsonArray& arr = jsonBuffer.parseArray(json); - REQUIRE(true == arr.success()); - REQUIRE(1 == arr.size()); - REQUIRE(42 == arr[0]); - } - - SECTION("ParseObject") { - std::istringstream json(" { hello : world // comment\n }"); - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.parseObject(json); - REQUIRE(true == obj.success()); - REQUIRE(1 == obj.size()); - REQUIRE(std::string("world") == obj["hello"]); - } - - SECTION("ShouldNotReadPastTheEnd") { - std::istringstream json("{}123"); - DynamicJsonBuffer jsonBuffer; - jsonBuffer.parseObject(json); - REQUIRE('1' == json.get()); - } -} diff --git a/lib/ArduinoJson/test/Misc/std_string.cpp b/lib/ArduinoJson/test/Misc/std_string.cpp deleted file mode 100644 index aeb188dd..00000000 --- a/lib/ArduinoJson/test/Misc/std_string.cpp +++ /dev/null @@ -1,243 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -static void eraseString(std::string &str) { - char *p = const_cast(str.c_str()); - while (*p) *p++ = '*'; -} - -TEST_CASE("std::string") { - DynamicJsonBuffer jb; - - SECTION("JsonBuffer_ParseArray") { - std::string json("[\"hello\"]"); - JsonArray &array = jb.parseArray(json); - eraseString(json); - REQUIRE(true == array.success()); - REQUIRE(std::string("hello") == array[0]); - } - - SECTION("JsonBuffer_ParseObject") { - std::string json("{\"hello\":\"world\"}"); - JsonObject &object = jb.parseObject(json); - eraseString(json); - REQUIRE(true == object.success()); - REQUIRE(std::string("world") == object["hello"]); - } - - SECTION("JsonObject_Subscript") { - char json[] = "{\"key\":\"value\"}"; - JsonObject &object = jb.parseObject(json); - REQUIRE(std::string("value") == object[std::string("key")]); - } - - SECTION("JsonObject_ConstSubscript") { - char json[] = "{\"key\":\"value\"}"; - const JsonObject &object = jb.parseObject(json); - REQUIRE(std::string("value") == object[std::string("key")]); - } - - SECTION("JsonObject_SetKey") { - JsonObject &object = jb.createObject(); - std::string key("hello"); - object.set(key, "world"); - eraseString(key); - REQUIRE(std::string("world") == object["hello"]); - } - - SECTION("JsonObject_SetValue") { - JsonObject &object = jb.createObject(); - std::string value("world"); - object.set("hello", value); - eraseString(value); - REQUIRE(std::string("world") == object["hello"]); - } - - SECTION("JsonObject_SetKeyValue") { - JsonObject &object = jb.createObject(); - std::string key("hello"); - std::string value("world"); - object.set(key, value); - eraseString(key); - eraseString(value); - REQUIRE(std::string("world") == object["hello"]); - } - - SECTION("JsonObject_SetToArraySubscript") { - JsonArray &arr = jb.createArray(); - arr.add("world"); - - JsonObject &object = jb.createObject(); - object.set(std::string("hello"), arr[0]); - - REQUIRE(std::string("world") == object["hello"]); - } - - SECTION("JsonObject_SetToObjectSubscript") { - JsonObject &arr = jb.createObject(); - arr.set("x", "world"); - - JsonObject &object = jb.createObject(); - object.set(std::string("hello"), arr["x"]); - - REQUIRE(std::string("world") == object["hello"]); - } - - SECTION("JsonObject_Get") { - char json[] = "{\"key\":\"value\"}"; - const JsonObject &object = jb.parseObject(json); - REQUIRE(std::string("value") == - object.get(std::string("key"))); - } - - SECTION("JsonObject_GetT") { - char json[] = "{\"key\":\"value\"}"; - const JsonObject &object = jb.parseObject(json); - REQUIRE(std::string("value") == - object.get(std::string("key"))); - } - - SECTION("JsonObject_IsT") { - char json[] = "{\"key\":\"value\"}"; - const JsonObject &object = jb.parseObject(json); - REQUIRE(true == object.is(std::string("key"))); - } - - SECTION("JsonObject_CreateNestedObject") { - std::string key = "key"; - char json[64]; - JsonObject &object = jb.createObject(); - object.createNestedObject(key); - eraseString(key); - object.printTo(json, sizeof(json)); - REQUIRE(std::string("{\"key\":{}}") == json); - } - - SECTION("JsonObject_CreateNestedArray") { - std::string key = "key"; - char json[64]; - JsonObject &object = jb.createObject(); - object.createNestedArray(key); - eraseString(key); - object.printTo(json, sizeof(json)); - REQUIRE(std::string("{\"key\":[]}") == json); - } - - SECTION("JsonObject_ContainsKey") { - char json[] = "{\"key\":\"value\"}"; - const JsonObject &object = jb.parseObject(json); - REQUIRE(true == object.containsKey(std::string("key"))); - } - - SECTION("JsonObject_Remove") { - char json[] = "{\"key\":\"value\"}"; - JsonObject &object = jb.parseObject(json); - REQUIRE(1 == object.size()); - object.remove(std::string("key")); - REQUIRE(0 == object.size()); - } - - SECTION("JsonObjectSubscript_SetKey") { - JsonObject &object = jb.createObject(); - std::string key("hello"); - object[key] = "world"; - eraseString(key); - REQUIRE(std::string("world") == object["hello"]); - } - - SECTION("JsonObjectSubscript_SetValue") { - JsonObject &object = jb.createObject(); - std::string value("world"); - object["hello"] = value; - eraseString(value); - REQUIRE(std::string("world") == object["hello"]); - } - - SECTION("JsonArray_Add") { - JsonArray &array = jb.createArray(); - std::string value("hello"); - array.add(value); - eraseString(value); - REQUIRE(std::string("hello") == array[0]); - } - - SECTION("JsonArray_Set") { - JsonArray &array = jb.createArray(); - std::string value("world"); - array.add("hello"); - array.set(0, value); - eraseString(value); - REQUIRE(std::string("world") == array[0]); - } - - SECTION("JsonArraySubscript") { - JsonArray &array = jb.createArray(); - std::string value("world"); - array.add("hello"); - array[0] = value; - eraseString(value); - REQUIRE(std::string("world") == array[0]); - } - - SECTION("JsonArray_PrintTo") { - JsonArray &array = jb.createArray(); - array.add(4); - array.add(2); - std::string json; - array.printTo(json); - REQUIRE(std::string("[4,2]") == json); - } - - SECTION("JsonArray_PrettyPrintTo") { - JsonArray &array = jb.createArray(); - array.add(4); - array.add(2); - std::string json; - array.prettyPrintTo(json); - REQUIRE(std::string("[\r\n 4,\r\n 2\r\n]") == json); - } - - SECTION("JsonObject_PrintTo") { - JsonObject &object = jb.createObject(); - object["key"] = "value"; - std::string json; - object.printTo(json); - REQUIRE(std::string("{\"key\":\"value\"}") == json); - } - - SECTION("JsonObject_PrettyPrintTo") { - JsonObject &object = jb.createObject(); - object["key"] = "value"; - std::string json; - object.prettyPrintTo(json); - REQUIRE(std::string("{\r\n \"key\": \"value\"\r\n}") == json); - } - - SECTION("JsonBuffer_GrowWhenAddingNewKey") { - JsonObject &object = jb.createObject(); - std::string key1("hello"), key2("world"); - - object[key1] = 1; - size_t sizeBefore = jb.size(); - object[key2] = 2; - size_t sizeAfter = jb.size(); - - REQUIRE(sizeAfter - sizeBefore >= key2.size()); - } - - SECTION("JsonBuffer_DontGrowWhenReusingKey") { - JsonObject &object = jb.createObject(); - std::string key("hello"); - - object[key] = 1; - size_t sizeBefore = jb.size(); - object[key] = 2; - size_t sizeAfter = jb.size(); - - REQUIRE(sizeBefore == sizeAfter); - } -} diff --git a/lib/ArduinoJson/test/Misc/unsigned_char.cpp b/lib/ArduinoJson/test/Misc/unsigned_char.cpp deleted file mode 100644 index ce1c474a..00000000 --- a/lib/ArduinoJson/test/Misc/unsigned_char.cpp +++ /dev/null @@ -1,262 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -#if defined(__clang__) -#define CONFLICTS_WITH_BUILTIN_OPERATOR -#endif - -TEST_CASE("unsigned char string") { - SECTION("JsonBuffer::parseArray") { - unsigned char json[] = "[42]"; - - StaticJsonBuffer jsonBuffer; - JsonArray& arr = jsonBuffer.parseArray(json); - - REQUIRE(true == arr.success()); - } - - SECTION("JsonBuffer::parseObject") { - unsigned char json[] = "{\"a\":42}"; - - StaticJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.parseObject(json); - - REQUIRE(true == obj.success()); - } - - SECTION("JsonVariant constructor") { - unsigned char value[] = "42"; - - JsonVariant variant(value); - - REQUIRE(42 == variant.as()); - } - - SECTION("JsonVariant assignment operator") { - unsigned char value[] = "42"; - - JsonVariant variant(666); - variant = value; - - REQUIRE(42 == variant.as()); - } - -#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR - SECTION("JsonVariant::operator[]") { - unsigned char key[] = "hello"; - - DynamicJsonBuffer jsonBuffer; - JsonVariant variant = jsonBuffer.parseObject("{\"hello\":\"world\"}"); - - REQUIRE(std::string("world") == variant[key]); - } -#endif - -#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR - SECTION("JsonVariant::operator[] const") { - unsigned char key[] = "hello"; - - DynamicJsonBuffer jsonBuffer; - const JsonVariant variant = jsonBuffer.parseObject("{\"hello\":\"world\"}"); - - REQUIRE(std::string("world") == variant[key]); - } -#endif - - SECTION("JsonVariant::operator==") { - unsigned char comparand[] = "hello"; - - DynamicJsonBuffer jsonBuffer; - const JsonVariant variant = "hello"; - - REQUIRE(comparand == variant); - REQUIRE(variant == comparand); - REQUIRE_FALSE(comparand != variant); - REQUIRE_FALSE(variant != comparand); - } - - SECTION("JsonVariant::operator!=") { - unsigned char comparand[] = "hello"; - - DynamicJsonBuffer jsonBuffer; - const JsonVariant variant = "world"; - - REQUIRE(comparand != variant); - REQUIRE(variant != comparand); - REQUIRE_FALSE(comparand == variant); - REQUIRE_FALSE(variant == comparand); - } - -#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR - SECTION("JsonObject::operator[]") { - unsigned char key[] = "hello"; - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - obj[key] = "world"; - - REQUIRE(std::string("world") == obj["hello"]); - } -#endif - - SECTION("JsonObjectSubscript::operator=") { // issue #416 - unsigned char value[] = "world"; - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - obj["hello"] = value; - - REQUIRE(std::string("world") == obj["hello"]); - } - - SECTION("JsonObjectSubscript::set()") { - unsigned char value[] = "world"; - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - obj["hello"].set(value); - - REQUIRE(std::string("world") == obj["hello"]); - } - -#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR - SECTION("JsonObject::operator[] const") { - unsigned char key[] = "hello"; - - DynamicJsonBuffer jsonBuffer; - const JsonObject& obj = jsonBuffer.parseObject("{\"hello\":\"world\"}"); - - REQUIRE(std::string("world") == obj[key]); - } -#endif - - SECTION("JsonObject::get()") { - unsigned char key[] = "hello"; - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.parseObject("{\"hello\":\"world\"}"); - - REQUIRE(std::string("world") == obj.get(key)); - } - - SECTION("JsonObject::set() key") { - unsigned char key[] = "hello"; - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - obj.set(key, "world"); - - REQUIRE(std::string("world") == obj["hello"]); - } - - SECTION("JsonObject::set() value") { - unsigned char value[] = "world"; - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - obj.set("hello", value); - - REQUIRE(std::string("world") == obj["hello"]); - } - - SECTION("JsonObject::set key&value") { - unsigned char key[] = "world"; - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - obj.set(key, key); - - REQUIRE(std::string("world") == obj["world"]); - } - - SECTION("JsonObject::containsKey()") { - unsigned char key[] = "hello"; - - DynamicJsonBuffer jsonBuffer; - const JsonObject& obj = jsonBuffer.parseObject("{\"hello\":\"world\"}"); - - REQUIRE(true == obj.containsKey(key)); - } - - SECTION("JsonObject::remove()") { - unsigned char key[] = "hello"; - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.parseObject("{\"hello\":\"world\"}"); - obj.remove(key); - - REQUIRE(0 == obj.size()); - } - - SECTION("JsonObject::is()") { - unsigned char key[] = "hello"; - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.parseObject("{\"hello\":42}"); - - REQUIRE(true == obj.is(key)); - } - - SECTION("JsonObject::createNestedArray()") { - unsigned char key[] = "hello"; - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - obj.createNestedArray(key); - } - - SECTION("JsonObject::createNestedObject()") { - unsigned char key[] = "hello"; - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - obj.createNestedObject(key); - } - - SECTION("JsonArray::add()") { - unsigned char value[] = "world"; - - DynamicJsonBuffer jsonBuffer; - JsonArray& arr = jsonBuffer.createArray(); - arr.add(value); - - REQUIRE(std::string("world") == arr[0]); - } - - SECTION("JsonArray::set()") { - unsigned char value[] = "world"; - - DynamicJsonBuffer jsonBuffer; - JsonArray& arr = jsonBuffer.createArray(); - arr.add("hello"); - arr.set(0, value); - - REQUIRE(std::string("world") == arr[0]); - } - - SECTION("JsonArraySubscript::set()") { - unsigned char value[] = "world"; - - DynamicJsonBuffer jsonBuffer; - JsonArray& arr = jsonBuffer.createArray(); - arr.add("hello"); - arr[0].set(value); - - REQUIRE(std::string("world") == arr[0]); - } - - SECTION("JsonArraySubscript::operator=") { - unsigned char value[] = "world"; - - DynamicJsonBuffer jsonBuffer; - JsonArray& arr = jsonBuffer.createArray(); - arr.add("hello"); - arr[0] = value; - - REQUIRE(std::string("world") == arr[0]); - } -} diff --git a/lib/ArduinoJson/test/Misc/vla.cpp b/lib/ArduinoJson/test/Misc/vla.cpp deleted file mode 100644 index e9d1cb67..00000000 --- a/lib/ArduinoJson/test/Misc/vla.cpp +++ /dev/null @@ -1,331 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -#if defined(__clang__) -#pragma clang diagnostic ignored "-Wvla-extension" -#define CONFLICTS_WITH_BUILTIN_OPERATOR -#elif defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wvla" -#else -#define VLA_NOT_SUPPORTED -#endif - -#ifndef VLA_NOT_SUPPORTED - -TEST_CASE("Variable Length Array") { - SECTION("ParseArray") { - int i = 8; - char vla[i]; - strcpy(vla, "[42]"); - - StaticJsonBuffer jsonBuffer; - JsonArray& arr = jsonBuffer.parseArray(vla); - - REQUIRE(true == arr.success()); - } - - SECTION("ParseObject") { - int i = 16; - char vla[i]; - strcpy(vla, "{\"a\":42}"); - - StaticJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.parseObject(vla); - - REQUIRE(true == obj.success()); - } - - SECTION("Parse") { - int i = 16; - char vla[i]; - strcpy(vla, "42"); - - StaticJsonBuffer<1> jsonBuffer; - JsonVariant variant = jsonBuffer.parse(vla); - - REQUIRE(42 == variant.as()); - } - - SECTION("JsonVariant_Constructor") { - int i = 16; - char vla[i]; - strcpy(vla, "42"); - - JsonVariant variant(vla); - - REQUIRE(42 == variant.as()); - } - - SECTION("JsonVariant_Assign") { - int i = 16; - char vla[i]; - strcpy(vla, "42"); - - JsonVariant variant(666); - variant = vla; - - REQUIRE(42 == variant.as()); - } - -#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR - SECTION("JsonVariant_Subscript") { - int i = 16; - char vla[i]; - strcpy(vla, "hello"); - - DynamicJsonBuffer jsonBuffer; - JsonVariant variant = jsonBuffer.parseObject("{\"hello\":\"world\"}"); - - REQUIRE(std::string("world") == variant[vla]); - } -#endif - -#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR - SECTION("JsonVariant_Subscript_Const") { - int i = 16; - char vla[i]; - strcpy(vla, "hello"); - - DynamicJsonBuffer jsonBuffer; - const JsonVariant variant = jsonBuffer.parseObject("{\"hello\":\"world\"}"); - - REQUIRE(std::string("world") == variant[vla]); - } -#endif - - SECTION("JsonVariant_Equals") { - int i = 16; - char vla[i]; - strcpy(vla, "hello"); - - DynamicJsonBuffer jsonBuffer; - const JsonVariant variant = "hello"; - - REQUIRE((vla == variant)); - REQUIRE((variant == vla)); - REQUIRE_FALSE((vla != variant)); - REQUIRE_FALSE((variant != vla)); - } - - SECTION("JsonVariant_Differs") { - int i = 16; - char vla[i]; - strcpy(vla, "hello"); - - DynamicJsonBuffer jsonBuffer; - const JsonVariant variant = "world"; - - REQUIRE((vla != variant)); - REQUIRE((variant != vla)); - REQUIRE_FALSE((vla == variant)); - REQUIRE_FALSE((variant == vla)); - } - -#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR - SECTION("JsonObject_Subscript") { - int i = 16; - char vla[i]; - strcpy(vla, "hello"); - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - obj[vla] = "world"; - - REQUIRE(std::string("world") == obj["hello"]); - } -#endif - - SECTION("JsonObject_Subscript_Assign") { // issue #416 - int i = 32; - char vla[i]; - strcpy(vla, "world"); - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - obj["hello"] = vla; - - REQUIRE(std::string("world") == obj["hello"].as()); - } - - SECTION("JsonObject_Subscript_Set") { - int i = 32; - char vla[i]; - strcpy(vla, "world"); - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - obj["hello"].set(vla); - - REQUIRE(std::string("world") == obj["hello"].as()); - } - -#ifndef CONFLICTS_WITH_BUILTIN_OPERATOR - SECTION("JsonObject_Subscript_Const") { - int i = 16; - char vla[i]; - strcpy(vla, "hello"); - - DynamicJsonBuffer jsonBuffer; - const JsonObject& obj = jsonBuffer.parseObject("{\"hello\":\"world\"}"); - - REQUIRE(std::string("world") == obj[vla]); - } -#endif - - SECTION("JsonObject_Get") { - int i = 16; - char vla[i]; - strcpy(vla, "hello"); - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.parseObject("{\"hello\":\"world\"}"); - - REQUIRE(std::string("world") == obj.get(vla)); - } - - SECTION("JsonObject_Set_Key") { - int i = 16; - char vla[i]; - strcpy(vla, "hello"); - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - obj.set(vla, "world"); - - REQUIRE(std::string("world") == obj["hello"]); - } - - SECTION("JsonObject_Set_Value") { - int i = 16; - char vla[i]; - strcpy(vla, "world"); - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - obj.set("hello", vla); - - REQUIRE(std::string("world") == obj["hello"]); - } - - SECTION("JsonObject_Set_KeyAndValue") { - int i = 16; - char vla[i]; - strcpy(vla, "world"); - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - obj.set(vla, vla); - - REQUIRE(std::string("world") == obj["world"]); - } - - SECTION("JsonObject_ContainsKey") { - int i = 16; - char vla[i]; - strcpy(vla, "hello"); - - DynamicJsonBuffer jsonBuffer; - const JsonObject& obj = jsonBuffer.parseObject("{\"hello\":\"world\"}"); - - REQUIRE(true == obj.containsKey(vla)); - } - - SECTION("JsonObject_Remove") { - int i = 16; - char vla[i]; - strcpy(vla, "hello"); - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.parseObject("{\"hello\":\"world\"}"); - obj.remove(vla); - - REQUIRE(0 == obj.size()); - } - - SECTION("JsonObject_Is") { - int i = 16; - char vla[i]; - strcpy(vla, "hello"); - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.parseObject("{\"hello\":42}"); - - REQUIRE(true == obj.is(vla)); - } - - SECTION("JsonObject_CreateNestedArray") { - int i = 16; - char vla[i]; - strcpy(vla, "hello"); - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - obj.createNestedArray(vla); - } - - SECTION("JsonObject_CreateNestedObject") { - int i = 16; - char vla[i]; - strcpy(vla, "hello"); - - DynamicJsonBuffer jsonBuffer; - JsonObject& obj = jsonBuffer.createObject(); - obj.createNestedObject(vla); - } - - SECTION("JsonArray_Add") { - int i = 16; - char vla[i]; - strcpy(vla, "world"); - - DynamicJsonBuffer jsonBuffer; - JsonArray& arr = jsonBuffer.createArray(); - arr.add(vla); - - REQUIRE(std::string("world") == arr[0]); - } - - SECTION("JsonArray_Set") { - int i = 16; - char vla[i]; - strcpy(vla, "world"); - - DynamicJsonBuffer jsonBuffer; - JsonArray& arr = jsonBuffer.createArray(); - arr.add("hello"); - arr.set(0, vla); - - REQUIRE(std::string("world") == arr[0]); - } - - SECTION("JsonArraySubscript_Set") { - int i = 16; - char vla[i]; - strcpy(vla, "world"); - - DynamicJsonBuffer jsonBuffer; - JsonArray& arr = jsonBuffer.createArray(); - arr.add("hello"); - arr[0].set(vla); - - REQUIRE(std::string("world") == arr[0]); - } - - SECTION("JsonArraySubscript_Assign") { - int i = 16; - char vla[i]; - strcpy(vla, "world"); - - DynamicJsonBuffer jsonBuffer; - JsonArray& arr = jsonBuffer.createArray(); - arr.add("hello"); - arr[0] = vla; - - REQUIRE(std::string("world") == arr[0]); - } -} -#endif diff --git a/lib/ArduinoJson/test/Polyfills/CMakeLists.txt b/lib/ArduinoJson/test/Polyfills/CMakeLists.txt deleted file mode 100644 index d96ce719..00000000 --- a/lib/ArduinoJson/test/Polyfills/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# ArduinoJson - arduinojson.org -# Copyright Benoit Blanchon 2014-2018 -# MIT License - -add_executable(PolyfillsTests - isFloat.cpp - isInteger.cpp - parseFloat.cpp - parseInteger.cpp -) - -target_link_libraries(PolyfillsTests catch) -add_test(Polyfills PolyfillsTests) diff --git a/lib/ArduinoJson/test/Polyfills/isFloat.cpp b/lib/ArduinoJson/test/Polyfills/isFloat.cpp deleted file mode 100644 index 225d5221..00000000 --- a/lib/ArduinoJson/test/Polyfills/isFloat.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -using namespace ArduinoJson::Internals; - -TEST_CASE("isFloat()") { - SECTION("Input is NULL") { - REQUIRE(isFloat(NULL) == false); - } - - SECTION("NoExponent") { - REQUIRE(isFloat("3.14")); - REQUIRE(isFloat("-3.14")); - REQUIRE(isFloat("+3.14")); - } - - SECTION("IntegralPartMissing") { - REQUIRE(isFloat(".14")); - REQUIRE(isFloat("-.14")); - REQUIRE(isFloat("+.14")); - } - - SECTION("FractionalPartMissing") { - REQUIRE(isFloat("3.")); - REQUIRE(isFloat("-3.e14")); - REQUIRE(isFloat("+3.e-14")); - } - - SECTION("NoDot") { - REQUIRE(isFloat("3e14")); - REQUIRE(isFloat("3e-14")); - REQUIRE(isFloat("3e+14")); - } - - SECTION("Integer") { - REQUIRE(isFloat("14")); - REQUIRE(isFloat("-14")); - REQUIRE(isFloat("+14")); - } - - SECTION("ExponentMissing") { - REQUIRE_FALSE(isFloat("3.14e")); - REQUIRE_FALSE(isFloat("3.14e-")); - REQUIRE_FALSE(isFloat("3.14e+")); - } - - SECTION("JustASign") { - REQUIRE_FALSE(isFloat("-")); - REQUIRE_FALSE(isFloat("+")); - } - - SECTION("Empty") { - REQUIRE_FALSE(isFloat("")); - } - - SECTION("NaN") { - REQUIRE(isFloat("NaN")); - REQUIRE_FALSE(isFloat("n")); - REQUIRE_FALSE(isFloat("N")); - REQUIRE_FALSE(isFloat("nan")); - REQUIRE_FALSE(isFloat("-NaN")); - REQUIRE_FALSE(isFloat("+NaN")); - } - - SECTION("Infinity") { - REQUIRE(isFloat("Infinity")); - REQUIRE(isFloat("+Infinity")); - REQUIRE(isFloat("-Infinity")); - REQUIRE_FALSE(isFloat("infinity")); - REQUIRE_FALSE(isFloat("Inf")); - } -} diff --git a/lib/ArduinoJson/test/Polyfills/isInteger.cpp b/lib/ArduinoJson/test/Polyfills/isInteger.cpp deleted file mode 100644 index f0bec4ae..00000000 --- a/lib/ArduinoJson/test/Polyfills/isInteger.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -using namespace ArduinoJson::Internals; - -TEST_CASE("isInteger()") { - SECTION("Null") { - REQUIRE_FALSE(isInteger(NULL)); - } - - SECTION("FloatNotInteger") { - REQUIRE_FALSE(isInteger("3.14")); - REQUIRE_FALSE(isInteger("-3.14")); - REQUIRE_FALSE(isInteger("+3.14")); - } - - SECTION("Spaces") { - REQUIRE_FALSE(isInteger("42 ")); - REQUIRE_FALSE(isInteger(" 42")); - } - - SECTION("Valid") { - REQUIRE(isInteger("42")); - REQUIRE(isInteger("-42")); - REQUIRE(isInteger("+42")); - } - - SECTION("ExtraSign") { - REQUIRE_FALSE(isInteger("--42")); - REQUIRE_FALSE(isInteger("++42")); - } -} diff --git a/lib/ArduinoJson/test/Polyfills/parseFloat.cpp b/lib/ArduinoJson/test/Polyfills/parseFloat.cpp deleted file mode 100644 index 362e46d6..00000000 --- a/lib/ArduinoJson/test/Polyfills/parseFloat.cpp +++ /dev/null @@ -1,177 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -using namespace ArduinoJson::Internals; - -template -void check(const char* input, T expected) { - CAPTURE(input); - REQUIRE(parseFloat(input) == Approx(expected)); -} - -template -void checkNaN(const char* input) { - CAPTURE(input); - T result = parseFloat(input); - REQUIRE(result != result); -} - -template -void checkInf(const char* input, bool negative) { - CAPTURE(input); - T x = parseFloat(input); - if (negative) - REQUIRE(x < 0); - else - REQUIRE(x > 0); - REQUIRE(x == x); // not a NaN - REQUIRE(x * 2 == x); // a property of infinity -} - -TEST_CASE("parseFloat()") { - SECTION("Null") { - check(NULL, 0); - } - - SECTION("Float_Short_NoExponent") { - check("3.14", 3.14f); - check("-3.14", -3.14f); - check("+3.14", +3.14f); - } - - SECTION("Short_NoDot") { - check("1E+38", 1E+38f); - check("-1E+38", -1E+38f); - check("+1E-38", +1E-38f); - check("+1e+38", +1e+38f); - check("-1e-38", -1e-38f); - } - - SECTION("Max") { - check("340.2823e+36", 3.402823e+38f); - check("34.02823e+37", 3.402823e+38f); - check("3.402823e+38", 3.402823e+38f); - check("0.3402823e+39", 3.402823e+38f); - check("0.03402823e+40", 3.402823e+38f); - check("0.003402823e+41", 3.402823e+38f); - } - - SECTION("VeryLong") { - check("0.00000000000000000000000000000001", 1e-32f); - check("100000000000000000000000000000000.0", 1e+32f); - check( - "100000000000000000000000000000000.00000000000000000000000000000", - 1e+32f); - } - - SECTION("MantissaTooLongToFit") { - check("0.340282346638528861111111111111", 0.34028234663852886f); - check("34028234663852886.11111111111111", 34028234663852886.0f); - check("34028234.66385288611111111111111", 34028234.663852886f); - - check("-0.340282346638528861111111111111", -0.34028234663852886f); - check("-34028234663852886.11111111111111", -34028234663852886.0f); - check("-34028234.66385288611111111111111", -34028234.663852886f); - } - - SECTION("ExponentTooBig") { - checkInf("1e39", false); - checkInf("-1e39", true); - checkInf("1e255", false); - check("1e-255", 0.0f); - } - - SECTION("NaN") { - checkNaN("NaN"); - checkNaN("nan"); - } - - SECTION("Infinity") { - checkInf("Infinity", false); - checkInf("+Infinity", false); - checkInf("-Infinity", true); - checkInf("inf", false); - checkInf("+inf", false); - checkInf("-inf", true); - } - - SECTION("Boolean") { - check("false", 0.0f); - check("true", 1.0f); - } -} - -TEST_CASE("parseFloat()") { - SECTION("Null") { - check(NULL, 0); - } - - SECTION("Short_NoExponent") { - check("3.14", 3.14); - check("-3.14", -3.14); - check("+3.14", +3.14); - } - - SECTION("Short_NoDot") { - check("1E+308", 1E+308); - check("-1E+308", -1E+308); - check("+1E-308", +1E-308); - check("+1e+308", +1e+308); - check("-1e-308", -1e-308); - } - - SECTION("Max") { - check(".017976931348623147e+310", 1.7976931348623147e+308); - check(".17976931348623147e+309", 1.7976931348623147e+308); - check("1.7976931348623147e+308", 1.7976931348623147e+308); - check("17.976931348623147e+307", 1.7976931348623147e+308); - check("179.76931348623147e+306", 1.7976931348623147e+308); - } - - SECTION("Min") { - check(".022250738585072014e-306", 2.2250738585072014e-308); - check(".22250738585072014e-307", 2.2250738585072014e-308); - check("2.2250738585072014e-308", 2.2250738585072014e-308); - check("22.250738585072014e-309", 2.2250738585072014e-308); - check("222.50738585072014e-310", 2.2250738585072014e-308); - } - - SECTION("VeryLong") { - check("0.00000000000000000000000000000001", 1e-32); - check("100000000000000000000000000000000.0", 1e+32); - check( - "100000000000000000000000000000000.00000000000000000000000000000", - 1e+32); - } - - SECTION("MantissaTooLongToFit") { - check("0.179769313486231571111111111111", 0.17976931348623157); - check("17976931348623157.11111111111111", 17976931348623157.0); - check("1797693.134862315711111111111111", 1797693.1348623157); - - check("-0.179769313486231571111111111111", -0.17976931348623157); - check("-17976931348623157.11111111111111", -17976931348623157.0); - check("-1797693.134862315711111111111111", -1797693.1348623157); - } - - SECTION("ExponentTooBig") { - checkInf("1e309", false); - checkInf("-1e309", true); - checkInf("1e65535", false); - check("1e-65535", 0.0); - } - - SECTION("NaN") { - checkNaN("NaN"); - checkNaN("nan"); - } - - SECTION("Boolean") { - check("false", 0.0); - check("true", 1.0); - } -} diff --git a/lib/ArduinoJson/test/Polyfills/parseInteger.cpp b/lib/ArduinoJson/test/Polyfills/parseInteger.cpp deleted file mode 100644 index 3d25bdb2..00000000 --- a/lib/ArduinoJson/test/Polyfills/parseInteger.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include -#include - -using namespace ArduinoJson::Internals; - -template -void check(const char* input, T expected) { - CAPTURE(input); - T actual = parseInteger(input); - REQUIRE(expected == actual); -} - -TEST_CASE("parseInteger()") { - check("-128", -128); - check("127", 127); - check("+127", 127); - check("3.14", 3); - check("x42", 0); - check("128", -128); - check("-129", 127); - check(NULL, 0); - check("true", 1); - check("false", 0); -} - -TEST_CASE("parseInteger()") { - check("-32768", -32768); - check("32767", 32767); - check("+32767", 32767); - check("3.14", 3); - check("x42", 0); - check("-32769", 32767); - check("32768", -32768); - check(NULL, 0); - check("true", 1); - check("false", 0); -} - -TEST_CASE("parseInteger()") { - check("-2147483648", (-2147483647 - 1)); - check("2147483647", 2147483647); - check("+2147483647", 2147483647); - check("3.14", 3); - check("x42", 0); - check("-2147483649", 2147483647); - check("2147483648", (-2147483647 - 1)); - check("true", 1); - check("false", 0); -} - -TEST_CASE("parseInteger()") { - check("0", 0); - check("255", 255); - check("+255", 255); - check("3.14", 3); - check("x42", 0); - check("-1", 255); - check("256", 0); - check("true", 1); - check("false", 0); -} - -TEST_CASE("parseInteger()") { - check("0", 0); - check("65535", 65535); - check("+65535", 65535); - check("3.14", 3); - // check(" 42", 0); - check("x42", 0); - check("-1", 65535); - check("65536", 0); - check("true", 1); - check("false", 0); -} diff --git a/lib/ArduinoJson/test/StaticJsonBuffer/CMakeLists.txt b/lib/ArduinoJson/test/StaticJsonBuffer/CMakeLists.txt deleted file mode 100644 index 00c78dfa..00000000 --- a/lib/ArduinoJson/test/StaticJsonBuffer/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -# ArduinoJson - arduinojson.org -# Copyright Benoit Blanchon 2014-2018 -# MIT License - -add_executable(StaticJsonBufferTests - alloc.cpp - createArray.cpp - createObject.cpp - parseArray.cpp - parseObject.cpp - size.cpp - startString.cpp -) - -target_link_libraries(StaticJsonBufferTests catch) -add_test(StaticJsonBuffer StaticJsonBufferTests) diff --git a/lib/ArduinoJson/test/StaticJsonBuffer/alloc.cpp b/lib/ArduinoJson/test/StaticJsonBuffer/alloc.cpp deleted file mode 100644 index 9141def8..00000000 --- a/lib/ArduinoJson/test/StaticJsonBuffer/alloc.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -static bool isAligned(void *ptr) { - const size_t mask = sizeof(void *) - 1; - size_t addr = reinterpret_cast(ptr); - return (addr & mask) == 0; -} - -TEST_CASE("StaticJsonBuffer::alloc()") { - StaticJsonBuffer<64> buffer; - - SECTION("Returns different addresses") { - void *p1 = buffer.alloc(1); - void *p2 = buffer.alloc(1); - REQUIRE(p1 != p2); - } - - SECTION("Returns non-NULL when using full capacity") { - void *p = buffer.alloc(64); - REQUIRE(0 != p); - } - - SECTION("Returns NULL when full") { - buffer.alloc(64); - void *p = buffer.alloc(1); - REQUIRE(0 == p); - } - - SECTION("Returns NULL when buffer is too small") { - void *p = buffer.alloc(65); - REQUIRE(0 == p); - } - - SECTION("Returns aligned pointers") { - for (size_t size = 1; size <= sizeof(void *); size++) { - void *p = buffer.alloc(1); - REQUIRE(isAligned(p)); - } - } - - SECTION("Returns same address after clear()") { - void *p1 = buffer.alloc(1); - buffer.clear(); - void *p2 = buffer.alloc(1); - REQUIRE(p1 == p2); - } -} diff --git a/lib/ArduinoJson/test/StaticJsonBuffer/createArray.cpp b/lib/ArduinoJson/test/StaticJsonBuffer/createArray.cpp deleted file mode 100644 index 9f0d3bd5..00000000 --- a/lib/ArduinoJson/test/StaticJsonBuffer/createArray.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("StaticJsonBuffer::createArray()") { - SECTION("GrowsWithArray") { - StaticJsonBuffer json; - - JsonArray &array = json.createArray(); - REQUIRE(JSON_ARRAY_SIZE(0) == json.size()); - - array.add("hello"); - REQUIRE(JSON_ARRAY_SIZE(1) == json.size()); - - array.add("world"); - REQUIRE(JSON_ARRAY_SIZE(2) == json.size()); - } - - SECTION("SucceedWhenBigEnough") { - StaticJsonBuffer json; - - JsonArray &array = json.createArray(); - REQUIRE(array.success()); - } - - SECTION("FailsWhenTooSmall") { - StaticJsonBuffer json; - - JsonArray &array = json.createArray(); - REQUIRE_FALSE(array.success()); - } - - SECTION("ArrayDoesntGrowWhenFull") { - StaticJsonBuffer json; - - JsonArray &array = json.createArray(); - array.add("hello"); - array.add("world"); - - REQUIRE(1 == array.size()); - } -} diff --git a/lib/ArduinoJson/test/StaticJsonBuffer/createObject.cpp b/lib/ArduinoJson/test/StaticJsonBuffer/createObject.cpp deleted file mode 100644 index c51e9bb9..00000000 --- a/lib/ArduinoJson/test/StaticJsonBuffer/createObject.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("StaticJsonBuffer::createObject()") { - SECTION("GrowsWithObject") { - StaticJsonBuffer buffer; - - JsonObject &obj = buffer.createObject(); - REQUIRE(JSON_OBJECT_SIZE(0) == buffer.size()); - - obj["hello"]; - REQUIRE(JSON_OBJECT_SIZE(0) == buffer.size()); - - obj["hello"] = 1; - REQUIRE(JSON_OBJECT_SIZE(1) == buffer.size()); - - obj["world"] = 2; - REQUIRE(JSON_OBJECT_SIZE(2) == buffer.size()); - - obj["world"] = 3; // <- same key, should not grow - REQUIRE(JSON_OBJECT_SIZE(2) == buffer.size()); - } - - SECTION("SucceedWhenBigEnough") { - StaticJsonBuffer buffer; - - JsonObject &object = buffer.createObject(); - REQUIRE(object.success()); - } - - SECTION("FailsWhenTooSmall") { - StaticJsonBuffer buffer; - - JsonObject &object = buffer.createObject(); - REQUIRE_FALSE(object.success()); - } - - SECTION("ObjectDoesntGrowWhenFull") { - StaticJsonBuffer buffer; - - JsonObject &obj = buffer.createObject(); - obj["hello"] = 1; - obj["world"] = 2; - - REQUIRE(JSON_OBJECT_SIZE(1) == buffer.size()); - REQUIRE(1 == obj.size()); - - char json[64]; - obj.printTo(json, sizeof(json)); - REQUIRE(std::string("{\"hello\":1}") == json); - } -} diff --git a/lib/ArduinoJson/test/StaticJsonBuffer/parseArray.cpp b/lib/ArduinoJson/test/StaticJsonBuffer/parseArray.cpp deleted file mode 100644 index f2feda99..00000000 --- a/lib/ArduinoJson/test/StaticJsonBuffer/parseArray.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("StaticJsonBuffer::parseArray()") { - SECTION("TooSmallBufferForEmptyArray") { - StaticJsonBuffer bufferTooSmall; - char input[] = "[]"; - JsonArray& arr = bufferTooSmall.parseArray(input); - REQUIRE_FALSE(arr.success()); - } - - SECTION("BufferOfTheRightSizeForEmptyArray") { - StaticJsonBuffer bufferOfRightSize; - char input[] = "[]"; - JsonArray& arr = bufferOfRightSize.parseArray(input); - REQUIRE(arr.success()); - } - - SECTION("TooSmallBufferForArrayWithOneValue") { - StaticJsonBuffer bufferTooSmall; - char input[] = "[1]"; - JsonArray& arr = bufferTooSmall.parseArray(input); - REQUIRE_FALSE(arr.success()); - } - - SECTION("BufferOfTheRightSizeForArrayWithOneValue") { - StaticJsonBuffer bufferOfRightSize; - char input[] = "[1]"; - JsonArray& arr = bufferOfRightSize.parseArray(input); - REQUIRE(arr.success()); - } - - SECTION("TooSmallBufferForArrayWithNestedObject") { - StaticJsonBuffer - bufferTooSmall; - char input[] = "[{}]"; - JsonArray& arr = bufferTooSmall.parseArray(input); - REQUIRE_FALSE(arr.success()); - } - - SECTION("BufferOfTheRightSizeForArrayWithNestedObject") { - StaticJsonBuffer - bufferOfRightSize; - char input[] = "[{}]"; - JsonArray& arr = bufferOfRightSize.parseArray(input); - REQUIRE(arr.success()); - } - - SECTION("CharPtrNull") { - REQUIRE_FALSE( - StaticJsonBuffer<100>().parseArray(static_cast(0)).success()); - } - - SECTION("ConstCharPtrNull") { - REQUIRE_FALSE(StaticJsonBuffer<100>() - .parseArray(static_cast(0)) - .success()); - } - - SECTION("CopyStringNotSpaces") { - StaticJsonBuffer<100> jsonBuffer; - jsonBuffer.parseArray(" [ \"1234567\" ] "); - REQUIRE(JSON_ARRAY_SIZE(1) + sizeof("1234567") == jsonBuffer.size()); - // note we use a string of 8 bytes to be sure that the StaticJsonBuffer - // will not insert bytes to enforce alignement - } -} diff --git a/lib/ArduinoJson/test/StaticJsonBuffer/parseObject.cpp b/lib/ArduinoJson/test/StaticJsonBuffer/parseObject.cpp deleted file mode 100644 index 83601d67..00000000 --- a/lib/ArduinoJson/test/StaticJsonBuffer/parseObject.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include -TEST_CASE("StaticJsonBuffer::parseObject()") { - SECTION("TooSmallBufferForEmptyObject") { - StaticJsonBuffer bufferTooSmall; - char input[] = "{}"; - JsonObject& obj = bufferTooSmall.parseObject(input); - REQUIRE_FALSE(obj.success()); - } - - SECTION("BufferOfTheRightSizeForEmptyObject") { - StaticJsonBuffer bufferOfRightSize; - char input[] = "{}"; - JsonObject& obj = bufferOfRightSize.parseObject(input); - REQUIRE(obj.success()); - } - - SECTION("TooSmallBufferForObjectWithOneValue") { - StaticJsonBuffer bufferTooSmall; - char input[] = "{\"a\":1}"; - JsonObject& obj = bufferTooSmall.parseObject(input); - REQUIRE_FALSE(obj.success()); - } - - SECTION("BufferOfTheRightSizeForObjectWithOneValue") { - StaticJsonBuffer bufferOfRightSize; - char input[] = "{\"a\":1}"; - JsonObject& obj = bufferOfRightSize.parseObject(input); - REQUIRE(obj.success()); - } - - SECTION("TooSmallBufferForObjectWithNestedObject") { - StaticJsonBuffer - bufferTooSmall; - char input[] = "{\"a\":[]}"; - JsonObject& obj = bufferTooSmall.parseObject(input); - REQUIRE_FALSE(obj.success()); - } - - SECTION("BufferOfTheRightSizeForObjectWithNestedObject") { - StaticJsonBuffer - bufferOfRightSize; - char input[] = "{\"a\":[]}"; - JsonObject& obj = bufferOfRightSize.parseObject(input); - REQUIRE(obj.success()); - } - - SECTION("CharPtrNull") { - REQUIRE_FALSE( - StaticJsonBuffer<100>().parseObject(static_cast(0)).success()); - } - - SECTION("ConstCharPtrNull") { - REQUIRE_FALSE(StaticJsonBuffer<100>() - .parseObject(static_cast(0)) - .success()); - } -} diff --git a/lib/ArduinoJson/test/StaticJsonBuffer/size.cpp b/lib/ArduinoJson/test/StaticJsonBuffer/size.cpp deleted file mode 100644 index 5ef76bf4..00000000 --- a/lib/ArduinoJson/test/StaticJsonBuffer/size.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -TEST_CASE("StaticJsonBuffer::size()") { - StaticJsonBuffer<64> buffer; - - SECTION("Capacity equals template parameter") { - REQUIRE(64 == buffer.capacity()); - } - - SECTION("Initial size is 0") { - REQUIRE(0 == buffer.size()); - } - - SECTION("Increases after alloc()") { - buffer.alloc(1); - REQUIRE(1U <= buffer.size()); - buffer.alloc(1); - REQUIRE(2U <= buffer.size()); - } - - SECTION("Doesn't grow when buffer is full") { - buffer.alloc(64); - buffer.alloc(1); - REQUIRE(64 == buffer.size()); - } - - SECTION("Does't grow when buffer is too small for alloc") { - buffer.alloc(65); - REQUIRE(0 == buffer.size()); - } - - SECTION("Goes back to zero after clear()") { - buffer.alloc(1); - buffer.clear(); - REQUIRE(0 == buffer.size()); - } -} diff --git a/lib/ArduinoJson/test/StaticJsonBuffer/startString.cpp b/lib/ArduinoJson/test/StaticJsonBuffer/startString.cpp deleted file mode 100644 index 282823b7..00000000 --- a/lib/ArduinoJson/test/StaticJsonBuffer/startString.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include - -using namespace ArduinoJson::Internals; - -TEST_CASE("StaticJsonBuffer::startString()") { - SECTION("WorksWhenBufferIsBigEnough") { - StaticJsonBuffer<6> jsonBuffer; - - StaticJsonBufferBase::String str = jsonBuffer.startString(); - str.append('h'); - str.append('e'); - str.append('l'); - str.append('l'); - str.append('o'); - - REQUIRE(std::string("hello") == str.c_str()); - } - - SECTION("ReturnsNullWhenTooSmall") { - StaticJsonBuffer<5> jsonBuffer; - - StaticJsonBufferBase::String str = jsonBuffer.startString(); - str.append('h'); - str.append('e'); - str.append('l'); - str.append('l'); - str.append('o'); - - REQUIRE(0 == str.c_str()); - } - - SECTION("SizeIncreases") { - StaticJsonBuffer<5> jsonBuffer; - - StaticJsonBufferBase::String str = jsonBuffer.startString(); - REQUIRE(0 == jsonBuffer.size()); - - str.append('h'); - REQUIRE(1 == jsonBuffer.size()); - - str.c_str(); - REQUIRE(2 == jsonBuffer.size()); - } -} diff --git a/lib/ArduinoJson/third-party/catch/CMakeLists.txt b/lib/ArduinoJson/third-party/catch/CMakeLists.txt deleted file mode 100644 index 59515f54..00000000 --- a/lib/ArduinoJson/third-party/catch/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# ArduinoJson - arduinojson.org -# Copyright Benoit Blanchon 2014-2018 -# MIT License - -add_library(catch - catch.hpp - catch.cpp -) - -target_include_directories(catch - PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR} -) diff --git a/lib/ArduinoJson/third-party/catch/catch.cpp b/lib/ArduinoJson/third-party/catch/catch.cpp deleted file mode 100644 index 2eb9b09e..00000000 --- a/lib/ArduinoJson/third-party/catch/catch.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#define CATCH_CONFIG_MAIN -#include "catch.hpp" diff --git a/lib/ArduinoJson/third-party/catch/catch.hpp b/lib/ArduinoJson/third-party/catch/catch.hpp deleted file mode 100644 index 7c351e93..00000000 --- a/lib/ArduinoJson/third-party/catch/catch.hpp +++ /dev/null @@ -1,11618 +0,0 @@ -/* - * Catch v1.9.7 - * Generated: 2017-08-10 23:49:15.233907 - * ---------------------------------------------------------- - * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. - * - * Distributed under the Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - */ -#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED - -#define TWOBLUECUBES_CATCH_HPP_INCLUDED - -#ifdef __clang__ -# pragma clang system_header -#elif defined __GNUC__ -# pragma GCC system_header -#endif - -// #included from: internal/catch_suppress_warnings.h - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(push) -# pragma warning(disable: 161 1682) -# else // __ICC -# pragma clang diagnostic ignored "-Wglobal-constructors" -# pragma clang diagnostic ignored "-Wvariadic-macros" -# pragma clang diagnostic ignored "-Wc99-extensions" -# pragma clang diagnostic ignored "-Wunused-variable" -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wc++98-compat" -# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -# pragma clang diagnostic ignored "-Wswitch-enum" -# pragma clang diagnostic ignored "-Wcovered-switch-default" -# endif -#elif defined __GNUC__ -# pragma GCC diagnostic ignored "-Wvariadic-macros" -# pragma GCC diagnostic ignored "-Wunused-variable" -# pragma GCC diagnostic ignored "-Wparentheses" - -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wpadded" -#endif -#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) -# define CATCH_IMPL -#endif - -#ifdef CATCH_IMPL -# ifndef CLARA_CONFIG_MAIN -# define CLARA_CONFIG_MAIN_NOT_DEFINED -# define CLARA_CONFIG_MAIN -# endif -#endif - -// #included from: internal/catch_notimplemented_exception.h -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED - -// #included from: catch_common.h -#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED - -// #included from: catch_compiler_capabilities.h -#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED - -// Detect a number of compiler features - mostly C++11/14 conformance - by compiler -// The following features are defined: -// -// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? -// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? -// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods -// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? -// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported -// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? -// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? -// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) -// CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported? -// CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported? - -// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? - -// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? -// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? -// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? -// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? -// **************** -// Note to maintainers: if new toggles are added please document them -// in configuration.md, too -// **************** - -// In general each macro has a _NO_ form -// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. -// Many features, at point of detection, define an _INTERNAL_ macro, so they -// can be combined, en-mass, with the _NO_ forms later. - -// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 - -#ifdef __cplusplus - -# if __cplusplus >= 201103L -# define CATCH_CPP11_OR_GREATER -# endif - -# if __cplusplus >= 201402L -# define CATCH_CPP14_OR_GREATER -# endif - -#endif - -#ifdef __clang__ - -# if __has_feature(cxx_nullptr) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - -# if __has_feature(cxx_noexcept) -# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# endif - -# if defined(CATCH_CPP11_OR_GREATER) -# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ - _Pragma( "clang diagnostic pop" ) - -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic pop" ) -# endif - -#endif // __clang__ - -//////////////////////////////////////////////////////////////////////////////// -// We know some environments not to support full POSIX signals -#if defined(__CYGWIN__) || defined(__QNX__) - -# if !defined(CATCH_CONFIG_POSIX_SIGNALS) -# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -# endif - -#endif - -#ifdef __OS400__ -# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -# define CATCH_CONFIG_COLOUR_NONE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Cygwin -#ifdef __CYGWIN__ - -// Required for some versions of Cygwin to declare gettimeofday -// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin -# define _BSD_SOURCE - -#endif // __CYGWIN__ - -//////////////////////////////////////////////////////////////////////////////// -// Borland -#ifdef __BORLANDC__ - -#endif // __BORLANDC__ - -//////////////////////////////////////////////////////////////////////////////// -// EDG -#ifdef __EDG_VERSION__ - -#endif // __EDG_VERSION__ - -//////////////////////////////////////////////////////////////////////////////// -// Digital Mars -#ifdef __DMC__ - -#endif // __DMC__ - -//////////////////////////////////////////////////////////////////////////////// -// GCC -#ifdef __GNUC__ - -# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - -// - otherwise more recent versions define __cplusplus >= 201103L -// and will get picked up below - -#endif // __GNUC__ - -//////////////////////////////////////////////////////////////////////////////// -// Visual C++ -#ifdef _MSC_VER - -#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH - -#if (_MSC_VER >= 1600) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -#endif - -#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) -#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE -#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS -#endif - -#endif // _MSC_VER - -//////////////////////////////////////////////////////////////////////////////// - -// Use variadic macros if the compiler supports them -#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ - ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ - ( defined __GNUC__ && __GNUC__ >= 3 ) || \ - ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) - -#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS - -#endif - -// Use __COUNTER__ if the compiler supports it -#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ - ( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \ - ( defined __clang__ && __clang_major__ >= 3 ) - -#define CATCH_INTERNAL_CONFIG_COUNTER - -#endif - -//////////////////////////////////////////////////////////////////////////////// -// C++ language feature support - -// catch all support for C++11 -#if defined(CATCH_CPP11_OR_GREATER) - -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM -# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE -# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE -# endif - -# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS -# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS -# endif - -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) -# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG -# endif - -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) -# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE -# endif -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) -# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -# endif -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) -# define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE -# endif -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) -# define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS -# endif - -#endif // __cplusplus >= 201103L - -// Now set the actual defines based on the above + anything the user has configured -#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_NULLPTR -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_NOEXCEPT -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_GENERATED_METHODS -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_IS_ENUM -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_TUPLE -#endif -#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) -# define CATCH_CONFIG_VARIADIC_MACROS -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_LONG_LONG -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_OVERRIDE -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_UNIQUE_PTR -#endif -// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for -// analytics) because, at time of writing, __COUNTER__ is not properly handled by it. -// This does not affect compilation -#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__) -# define CATCH_CONFIG_COUNTER -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_SHUFFLE -#endif -# if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_TYPE_TRAITS -# endif -#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) -# define CATCH_CONFIG_WINDOWS_SEH -#endif -// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. -#if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) -# define CATCH_CONFIG_POSIX_SIGNALS -#endif - -#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS -#endif - -// noexcept support: -#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) -# define CATCH_NOEXCEPT noexcept -# define CATCH_NOEXCEPT_IS(x) noexcept(x) -#else -# define CATCH_NOEXCEPT throw() -# define CATCH_NOEXCEPT_IS(x) -#endif - -// nullptr support -#ifdef CATCH_CONFIG_CPP11_NULLPTR -# define CATCH_NULL nullptr -#else -# define CATCH_NULL NULL -#endif - -// override support -#ifdef CATCH_CONFIG_CPP11_OVERRIDE -# define CATCH_OVERRIDE override -#else -# define CATCH_OVERRIDE -#endif - -// unique_ptr support -#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR -# define CATCH_AUTO_PTR( T ) std::unique_ptr -#else -# define CATCH_AUTO_PTR( T ) std::auto_ptr -#endif - -#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line -#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) -#ifdef CATCH_CONFIG_COUNTER -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) -#else -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) -#endif - -#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr -#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) - -#include -#include - -namespace Catch { - - struct IConfig; - - struct CaseSensitive { enum Choice { - Yes, - No - }; }; - - class NonCopyable { -#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - NonCopyable( NonCopyable const& ) = delete; - NonCopyable( NonCopyable && ) = delete; - NonCopyable& operator = ( NonCopyable const& ) = delete; - NonCopyable& operator = ( NonCopyable && ) = delete; -#else - NonCopyable( NonCopyable const& info ); - NonCopyable& operator = ( NonCopyable const& ); -#endif - - protected: - NonCopyable() {} - virtual ~NonCopyable(); - }; - - class SafeBool { - public: - typedef void (SafeBool::*type)() const; - - static type makeSafe( bool value ) { - return value ? &SafeBool::trueValue : 0; - } - private: - void trueValue() const {} - }; - - template - void deleteAll( ContainerT& container ) { - typename ContainerT::const_iterator it = container.begin(); - typename ContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - delete *it; - } - template - void deleteAllValues( AssociativeContainerT& container ) { - typename AssociativeContainerT::const_iterator it = container.begin(); - typename AssociativeContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - delete it->second; - } - - bool startsWith( std::string const& s, std::string const& prefix ); - bool startsWith( std::string const& s, char prefix ); - bool endsWith( std::string const& s, std::string const& suffix ); - bool endsWith( std::string const& s, char suffix ); - bool contains( std::string const& s, std::string const& infix ); - void toLowerInPlace( std::string& s ); - std::string toLower( std::string const& s ); - std::string trim( std::string const& str ); - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); - - struct pluralise { - pluralise( std::size_t count, std::string const& label ); - - friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); - - std::size_t m_count; - std::string m_label; - }; - - struct SourceLineInfo { - - SourceLineInfo(); - SourceLineInfo( char const* _file, std::size_t _line ); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - SourceLineInfo(SourceLineInfo const& other) = default; - SourceLineInfo( SourceLineInfo && ) = default; - SourceLineInfo& operator = ( SourceLineInfo const& ) = default; - SourceLineInfo& operator = ( SourceLineInfo && ) = default; -# endif - bool empty() const; - bool operator == ( SourceLineInfo const& other ) const; - bool operator < ( SourceLineInfo const& other ) const; - - char const* file; - std::size_t line; - }; - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); - - // This is just here to avoid compiler warnings with macro constants and boolean literals - inline bool isTrue( bool value ){ return value; } - inline bool alwaysTrue() { return true; } - inline bool alwaysFalse() { return false; } - - void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); - - void seedRng( IConfig const& config ); - unsigned int rngSeed(); - - // Use this in variadic streaming macros to allow - // >> +StreamEndStop - // as well as - // >> stuff +StreamEndStop - struct StreamEndStop { - std::string operator+() { - return std::string(); - } - }; - template - T const& operator + ( T const& value, StreamEndStop ) { - return value; - } -} - -#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) -#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); - -namespace Catch { - - class NotImplementedException : public std::exception - { - public: - NotImplementedException( SourceLineInfo const& lineInfo ); - - virtual ~NotImplementedException() CATCH_NOEXCEPT {} - - virtual const char* what() const CATCH_NOEXCEPT; - - private: - std::string m_what; - SourceLineInfo m_lineInfo; - }; - -} // end namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) - -// #included from: internal/catch_context.h -#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED - -// #included from: catch_interfaces_generators.h -#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED - -#include - -namespace Catch { - - struct IGeneratorInfo { - virtual ~IGeneratorInfo(); - virtual bool moveNext() = 0; - virtual std::size_t getCurrentIndex() const = 0; - }; - - struct IGeneratorsForTest { - virtual ~IGeneratorsForTest(); - - virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; - virtual bool moveNext() = 0; - }; - - IGeneratorsForTest* createGeneratorsForTest(); - -} // end namespace Catch - -// #included from: catch_ptr.hpp -#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - - // An intrusive reference counting smart pointer. - // T must implement addRef() and release() methods - // typically implementing the IShared interface - template - class Ptr { - public: - Ptr() : m_p( CATCH_NULL ){} - Ptr( T* p ) : m_p( p ){ - if( m_p ) - m_p->addRef(); - } - Ptr( Ptr const& other ) : m_p( other.m_p ){ - if( m_p ) - m_p->addRef(); - } - ~Ptr(){ - if( m_p ) - m_p->release(); - } - void reset() { - if( m_p ) - m_p->release(); - m_p = CATCH_NULL; - } - Ptr& operator = ( T* p ){ - Ptr temp( p ); - swap( temp ); - return *this; - } - Ptr& operator = ( Ptr const& other ){ - Ptr temp( other ); - swap( temp ); - return *this; - } - void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } - T* get() const{ return m_p; } - T& operator*() const { return *m_p; } - T* operator->() const { return m_p; } - bool operator !() const { return m_p == CATCH_NULL; } - operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } - - private: - T* m_p; - }; - - struct IShared : NonCopyable { - virtual ~IShared(); - virtual void addRef() const = 0; - virtual void release() const = 0; - }; - - template - struct SharedImpl : T { - - SharedImpl() : m_rc( 0 ){} - - virtual void addRef() const { - ++m_rc; - } - virtual void release() const { - if( --m_rc == 0 ) - delete this; - } - - mutable unsigned int m_rc; - }; - -} // end namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -namespace Catch { - - class TestCase; - class Stream; - struct IResultCapture; - struct IRunner; - struct IGeneratorsForTest; - struct IConfig; - - struct IContext - { - virtual ~IContext(); - - virtual IResultCapture* getResultCapture() = 0; - virtual IRunner* getRunner() = 0; - virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; - virtual bool advanceGeneratorsForCurrentTest() = 0; - virtual Ptr getConfig() const = 0; - }; - - struct IMutableContext : IContext - { - virtual ~IMutableContext(); - virtual void setResultCapture( IResultCapture* resultCapture ) = 0; - virtual void setRunner( IRunner* runner ) = 0; - virtual void setConfig( Ptr const& config ) = 0; - }; - - IContext& getCurrentContext(); - IMutableContext& getCurrentMutableContext(); - void cleanUpContext(); - Stream createStream( std::string const& streamName ); - -} - -// #included from: internal/catch_test_registry.hpp -#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED - -// #included from: catch_interfaces_testcase.h -#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED - -#include - -namespace Catch { - - class TestSpec; - - struct ITestCase : IShared { - virtual void invoke () const = 0; - protected: - virtual ~ITestCase(); - }; - - class TestCase; - struct IConfig; - - struct ITestCaseRegistry { - virtual ~ITestCaseRegistry(); - virtual std::vector const& getAllTests() const = 0; - virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; - }; - - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); - std::vector const& getAllTestCasesSorted( IConfig const& config ); - -} - -namespace Catch { - -template -class MethodTestCase : public SharedImpl { - -public: - MethodTestCase( void (C::*method)() ) : m_method( method ) {} - - virtual void invoke() const { - C obj; - (obj.*m_method)(); - } - -private: - virtual ~MethodTestCase() {} - - void (C::*m_method)(); -}; - -typedef void(*TestFunction)(); - -struct NameAndDesc { - NameAndDesc( const char* _name = "", const char* _description= "" ) - : name( _name ), description( _description ) - {} - - const char* name; - const char* description; -}; - -void registerTestCase - ( ITestCase* testCase, - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ); - -struct AutoReg { - - AutoReg - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ); - - template - AutoReg - ( void (C::*method)(), - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - - registerTestCase - ( new MethodTestCase( method ), - className, - nameAndDesc, - lineInfo ); - } - - ~AutoReg(); - -private: - AutoReg( AutoReg const& ); - void operator= ( AutoReg const& ); -}; - -void registerTestCaseFunction - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ); - -} // end namespace Catch - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ - static void TestName(); \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); } /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ - static void TestName() - #define INTERNAL_CATCH_TESTCASE( ... ) \ - INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ \ - struct TestName : ClassName{ \ - void test(); \ - }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); /* NOLINT */ \ - } \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ - void TestName::test() - #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ - INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS - -#else - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ - static void TestName(); \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); } /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ - static void TestName() - #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ - INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ \ - struct TestCaseName : ClassName{ \ - void test(); \ - }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); /* NOLINT */ \ - } \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ - void TestCaseName::test() - #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ - INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS - -#endif - -// #included from: internal/catch_capture.hpp -#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED - -// #included from: catch_result_builder.h -#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED - -// #included from: catch_result_type.h -#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED - -namespace Catch { - - // ResultWas::OfType enum - struct ResultWas { enum OfType { - Unknown = -1, - Ok = 0, - Info = 1, - Warning = 2, - - FailureBit = 0x10, - - ExpressionFailed = FailureBit | 1, - ExplicitFailure = FailureBit | 2, - - Exception = 0x100 | FailureBit, - - ThrewException = Exception | 1, - DidntThrowException = Exception | 2, - - FatalErrorCondition = 0x200 | FailureBit - - }; }; - - inline bool isOk( ResultWas::OfType resultType ) { - return ( resultType & ResultWas::FailureBit ) == 0; - } - inline bool isJustInfo( int flags ) { - return flags == ResultWas::Info; - } - - // ResultDisposition::Flags enum - struct ResultDisposition { enum Flags { - Normal = 0x01, - - ContinueOnFailure = 0x02, // Failures fail test, but execution continues - FalseTest = 0x04, // Prefix expression with ! - SuppressFail = 0x08 // Failures are reported but do not fail the test - }; }; - - inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { - return static_cast( static_cast( lhs ) | static_cast( rhs ) ); - } - - inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } - inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } - inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } - -} // end namespace Catch - -// #included from: catch_assertionresult.h -#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED - -#include - -namespace Catch { - - struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; - - struct DecomposedExpression - { - virtual ~DecomposedExpression() {} - virtual bool isBinaryExpression() const { - return false; - } - virtual void reconstructExpression( std::string& dest ) const = 0; - - // Only simple binary comparisons can be decomposed. - // If more complex check is required then wrap sub-expressions in parentheses. - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& ); - - private: - DecomposedExpression& operator = (DecomposedExpression const&); - }; - - struct AssertionInfo - { - AssertionInfo(); - AssertionInfo( char const * _macroName, - SourceLineInfo const& _lineInfo, - char const * _capturedExpression, - ResultDisposition::Flags _resultDisposition, - char const * _secondArg = ""); - - char const * macroName; - SourceLineInfo lineInfo; - char const * capturedExpression; - ResultDisposition::Flags resultDisposition; - char const * secondArg; - }; - - struct AssertionResultData - { - AssertionResultData() : decomposedExpression( CATCH_NULL ) - , resultType( ResultWas::Unknown ) - , negated( false ) - , parenthesized( false ) {} - - void negate( bool parenthesize ) { - negated = !negated; - parenthesized = parenthesize; - if( resultType == ResultWas::Ok ) - resultType = ResultWas::ExpressionFailed; - else if( resultType == ResultWas::ExpressionFailed ) - resultType = ResultWas::Ok; - } - - std::string const& reconstructExpression() const { - if( decomposedExpression != CATCH_NULL ) { - decomposedExpression->reconstructExpression( reconstructedExpression ); - if( parenthesized ) { - reconstructedExpression.insert( 0, 1, '(' ); - reconstructedExpression.append( 1, ')' ); - } - if( negated ) { - reconstructedExpression.insert( 0, 1, '!' ); - } - decomposedExpression = CATCH_NULL; - } - return reconstructedExpression; - } - - mutable DecomposedExpression const* decomposedExpression; - mutable std::string reconstructedExpression; - std::string message; - ResultWas::OfType resultType; - bool negated; - bool parenthesized; - }; - - class AssertionResult { - public: - AssertionResult(); - AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); - ~AssertionResult(); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - AssertionResult( AssertionResult const& ) = default; - AssertionResult( AssertionResult && ) = default; - AssertionResult& operator = ( AssertionResult const& ) = default; - AssertionResult& operator = ( AssertionResult && ) = default; -# endif - - bool isOk() const; - bool succeeded() const; - ResultWas::OfType getResultType() const; - bool hasExpression() const; - bool hasMessage() const; - std::string getExpression() const; - std::string getExpressionInMacro() const; - bool hasExpandedExpression() const; - std::string getExpandedExpression() const; - std::string getMessage() const; - SourceLineInfo getSourceInfo() const; - std::string getTestMacroName() const; - void discardDecomposedExpression() const; - void expandDecomposedExpression() const; - - protected: - AssertionInfo m_info; - AssertionResultData m_resultData; - }; - -} // end namespace Catch - -// #included from: catch_matchers.hpp -#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED - -namespace Catch { -namespace Matchers { - namespace Impl { - - template struct MatchAllOf; - template struct MatchAnyOf; - template struct MatchNotOf; - - class MatcherUntypedBase { - public: - std::string toString() const { - if( m_cachedToString.empty() ) - m_cachedToString = describe(); - return m_cachedToString; - } - - protected: - virtual ~MatcherUntypedBase(); - virtual std::string describe() const = 0; - mutable std::string m_cachedToString; - private: - MatcherUntypedBase& operator = ( MatcherUntypedBase const& ); - }; - - template - struct MatcherMethod { - virtual bool match( ObjectT const& arg ) const = 0; - }; - template - struct MatcherMethod { - virtual bool match( PtrT* arg ) const = 0; - }; - - template - struct MatcherBase : MatcherUntypedBase, MatcherMethod { - - MatchAllOf operator && ( MatcherBase const& other ) const; - MatchAnyOf operator || ( MatcherBase const& other ) const; - MatchNotOf operator ! () const; - }; - - template - struct MatchAllOf : MatcherBase { - virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if (!m_matchers[i]->match(arg)) - return false; - } - return true; - } - virtual std::string describe() const CATCH_OVERRIDE { - std::string description; - description.reserve( 4 + m_matchers.size()*32 ); - description += "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - description += " and "; - description += m_matchers[i]->toString(); - } - description += " )"; - return description; - } - - MatchAllOf& operator && ( MatcherBase const& other ) { - m_matchers.push_back( &other ); - return *this; - } - - std::vector const*> m_matchers; - }; - template - struct MatchAnyOf : MatcherBase { - - virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if (m_matchers[i]->match(arg)) - return true; - } - return false; - } - virtual std::string describe() const CATCH_OVERRIDE { - std::string description; - description.reserve( 4 + m_matchers.size()*32 ); - description += "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - description += " or "; - description += m_matchers[i]->toString(); - } - description += " )"; - return description; - } - - MatchAnyOf& operator || ( MatcherBase const& other ) { - m_matchers.push_back( &other ); - return *this; - } - - std::vector const*> m_matchers; - }; - - template - struct MatchNotOf : MatcherBase { - - MatchNotOf( MatcherBase const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} - - virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { - return !m_underlyingMatcher.match( arg ); - } - - virtual std::string describe() const CATCH_OVERRIDE { - return "not " + m_underlyingMatcher.toString(); - } - MatcherBase const& m_underlyingMatcher; - }; - - template - MatchAllOf MatcherBase::operator && ( MatcherBase const& other ) const { - return MatchAllOf() && *this && other; - } - template - MatchAnyOf MatcherBase::operator || ( MatcherBase const& other ) const { - return MatchAnyOf() || *this || other; - } - template - MatchNotOf MatcherBase::operator ! () const { - return MatchNotOf( *this ); - } - - } // namespace Impl - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - // - deprecated: prefer ||, && and ! - template - Impl::MatchNotOf Not( Impl::MatcherBase const& underlyingMatcher ) { - return Impl::MatchNotOf( underlyingMatcher ); - } - template - Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { - return Impl::MatchAllOf() && m1 && m2; - } - template - Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { - return Impl::MatchAllOf() && m1 && m2 && m3; - } - template - Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { - return Impl::MatchAnyOf() || m1 || m2; - } - template - Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { - return Impl::MatchAnyOf() || m1 || m2 || m3; - } - -} // namespace Matchers - -using namespace Matchers; -using Matchers::Impl::MatcherBase; - -} // namespace Catch - -namespace Catch { - - struct TestFailureException{}; - - template class ExpressionLhs; - - struct CopyableStream { - CopyableStream() {} - CopyableStream( CopyableStream const& other ) { - oss << other.oss.str(); - } - CopyableStream& operator=( CopyableStream const& other ) { - oss.str(std::string()); - oss << other.oss.str(); - return *this; - } - std::ostringstream oss; - }; - - class ResultBuilder : public DecomposedExpression { - public: - ResultBuilder( char const* macroName, - SourceLineInfo const& lineInfo, - char const* capturedExpression, - ResultDisposition::Flags resultDisposition, - char const* secondArg = "" ); - ~ResultBuilder(); - - template - ExpressionLhs operator <= ( T const& operand ); - ExpressionLhs operator <= ( bool value ); - - template - ResultBuilder& operator << ( T const& value ) { - stream().oss << value; - return *this; - } - - ResultBuilder& setResultType( ResultWas::OfType result ); - ResultBuilder& setResultType( bool result ); - - void endExpression( DecomposedExpression const& expr ); - - virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE; - - AssertionResult build() const; - AssertionResult build( DecomposedExpression const& expr ) const; - - void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); - void captureResult( ResultWas::OfType resultType ); - void captureExpression(); - void captureExpectedException( std::string const& expectedMessage ); - void captureExpectedException( Matchers::Impl::MatcherBase const& matcher ); - void handleResult( AssertionResult const& result ); - void react(); - bool shouldDebugBreak() const; - bool allowThrows() const; - - template - void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString ); - - void setExceptionGuard(); - void unsetExceptionGuard(); - - private: - AssertionInfo m_assertionInfo; - AssertionResultData m_data; - - CopyableStream &stream() - { - if(!m_usedStream) - { - m_usedStream = true; - m_stream().oss.str(""); - } - return m_stream(); - } - - static CopyableStream &m_stream() - { - static CopyableStream s; - return s; - } - - bool m_shouldDebugBreak; - bool m_shouldThrow; - bool m_guardException; - bool m_usedStream; - }; - -} // namespace Catch - -// Include after due to circular dependency: -// #included from: catch_expression_lhs.hpp -#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED - -// #included from: catch_evaluate.hpp -#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4389) // '==' : signed/unsigned mismatch -#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) -#endif - -#include - -namespace Catch { -namespace Internal { - - enum Operator { - IsEqualTo, - IsNotEqualTo, - IsLessThan, - IsGreaterThan, - IsLessThanOrEqualTo, - IsGreaterThanOrEqualTo - }; - - template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; - template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; - template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; - template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; - template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; - template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; - template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; - - template - T& opCast(T const& t) { return const_cast(t); } - -// nullptr_t support based on pull request #154 from Konstantin Baumann -#ifdef CATCH_CONFIG_CPP11_NULLPTR - inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } -#endif // CATCH_CONFIG_CPP11_NULLPTR - - // So the compare overloads can be operator agnostic we convey the operator as a template - // enum, which is used to specialise an Evaluator for doing the comparison. - template - struct Evaluator{}; - - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs) { - return bool( opCast( lhs ) == opCast( rhs ) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) != opCast( rhs ) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) < opCast( rhs ) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) > opCast( rhs ) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) >= opCast( rhs ) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) <= opCast( rhs ) ); - } - }; - - template - bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { - return Evaluator::evaluate( lhs, rhs ); - } - - // This level of indirection allows us to specialise for integer types - // to avoid signed/ unsigned warnings - - // "base" overload - template - bool compare( T1 const& lhs, T2 const& rhs ) { - return Evaluator::evaluate( lhs, rhs ); - } - - // unsigned X to int - template bool compare( unsigned int lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned long lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned char lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - - // unsigned X to long - template bool compare( unsigned int lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned long lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned char lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - - // int to unsigned X - template bool compare( int lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( int lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( int lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // long to unsigned X - template bool compare( long lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // pointer to long (when comparing against NULL) - template bool compare( long lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); - } - template bool compare( T* lhs, long rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); - } - - // pointer to int (when comparing against NULL) - template bool compare( int lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); - } - template bool compare( T* lhs, int rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); - } - -#ifdef CATCH_CONFIG_CPP11_LONG_LONG - // long long to unsigned X - template bool compare( long long lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long long lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long long lhs, unsigned long long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long long lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // unsigned long long to X - template bool compare( unsigned long long lhs, int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( unsigned long long lhs, long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( unsigned long long lhs, long long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( unsigned long long lhs, char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // pointer to long long (when comparing against NULL) - template bool compare( long long lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); - } - template bool compare( T* lhs, long long rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); - } -#endif // CATCH_CONFIG_CPP11_LONG_LONG - -#ifdef CATCH_CONFIG_CPP11_NULLPTR - // pointer to nullptr_t (when comparing against nullptr) - template bool compare( std::nullptr_t, T* rhs ) { - return Evaluator::evaluate( nullptr, rhs ); - } - template bool compare( T* lhs, std::nullptr_t ) { - return Evaluator::evaluate( lhs, nullptr ); - } -#endif // CATCH_CONFIG_CPP11_NULLPTR - -} // end of namespace Internal -} // end of namespace Catch - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -// #included from: catch_tostring.h -#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED - -#include -#include -#include -#include -#include - -#ifdef __OBJC__ -// #included from: catch_objc_arc.hpp -#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED - -#import - -#ifdef __has_feature -#define CATCH_ARC_ENABLED __has_feature(objc_arc) -#else -#define CATCH_ARC_ENABLED 0 -#endif - -void arcSafeRelease( NSObject* obj ); -id performOptionalSelector( id obj, SEL sel ); - -#if !CATCH_ARC_ENABLED -inline void arcSafeRelease( NSObject* obj ) { - [obj release]; -} -inline id performOptionalSelector( id obj, SEL sel ) { - if( [obj respondsToSelector: sel] ) - return [obj performSelector: sel]; - return nil; -} -#define CATCH_UNSAFE_UNRETAINED -#define CATCH_ARC_STRONG -#else -inline void arcSafeRelease( NSObject* ){} -inline id performOptionalSelector( id obj, SEL sel ) { -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" -#endif - if( [obj respondsToSelector: sel] ) - return [obj performSelector: sel]; -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - return nil; -} -#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained -#define CATCH_ARC_STRONG __strong -#endif - -#endif - -#ifdef CATCH_CONFIG_CPP11_TUPLE -#include -#endif - -#ifdef CATCH_CONFIG_CPP11_IS_ENUM -#include -#endif - -namespace Catch { - -// Why we're here. -template -std::string toString( T const& value ); - -// Built in overloads - -std::string toString( std::string const& value ); -std::string toString( std::wstring const& value ); -std::string toString( const char* const value ); -std::string toString( char* const value ); -std::string toString( const wchar_t* const value ); -std::string toString( wchar_t* const value ); -std::string toString( int value ); -std::string toString( unsigned long value ); -std::string toString( unsigned int value ); -std::string toString( const double value ); -std::string toString( const float value ); -std::string toString( bool value ); -std::string toString( char value ); -std::string toString( signed char value ); -std::string toString( unsigned char value ); - -#ifdef CATCH_CONFIG_CPP11_LONG_LONG -std::string toString( long long value ); -std::string toString( unsigned long long value ); -#endif - -#ifdef CATCH_CONFIG_CPP11_NULLPTR -std::string toString( std::nullptr_t ); -#endif - -#ifdef __OBJC__ - std::string toString( NSString const * const& nsstring ); - std::string toString( NSString * CATCH_ARC_STRONG & nsstring ); - std::string toString( NSObject* const& nsObject ); -#endif - -namespace Detail { - - extern const std::string unprintableString; - - #if !defined(CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK) - struct BorgType { - template BorgType( T const& ); - }; - - struct TrueType { char sizer[1]; }; - struct FalseType { char sizer[2]; }; - - TrueType& testStreamable( std::ostream& ); - FalseType testStreamable( FalseType ); - - FalseType operator<<( std::ostream const&, BorgType const& ); - - template - struct IsStreamInsertable { - static std::ostream &s; - static T const&t; - enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; - }; -#else - template - class IsStreamInsertable { - template - static auto test(int) - -> decltype( std::declval() << std::declval(), std::true_type() ); - - template - static auto test(...) -> std::false_type; - - public: - static const bool value = decltype(test(0))::value; - }; -#endif - -#if defined(CATCH_CONFIG_CPP11_IS_ENUM) - template::value - > - struct EnumStringMaker - { - static std::string convert( T const& ) { return unprintableString; } - }; - - template - struct EnumStringMaker - { - static std::string convert( T const& v ) - { - return ::Catch::toString( - static_cast::type>(v) - ); - } - }; -#endif - template - struct StringMakerBase { -#if defined(CATCH_CONFIG_CPP11_IS_ENUM) - template - static std::string convert( T const& v ) - { - return EnumStringMaker::convert( v ); - } -#else - template - static std::string convert( T const& ) { return unprintableString; } -#endif - }; - - template<> - struct StringMakerBase { - template - static std::string convert( T const& _value ) { - std::ostringstream oss; - oss << _value; - return oss.str(); - } - }; - - std::string rawMemoryToString( const void *object, std::size_t size ); - - template - std::string rawMemoryToString( const T& object ) { - return rawMemoryToString( &object, sizeof(object) ); - } - -} // end namespace Detail - -template -struct StringMaker : - Detail::StringMakerBase::value> {}; - -template -struct StringMaker { - template - static std::string convert( U* p ) { - if( !p ) - return "NULL"; - else - return Detail::rawMemoryToString( p ); - } -}; - -template -struct StringMaker { - static std::string convert( R C::* p ) { - if( !p ) - return "NULL"; - else - return Detail::rawMemoryToString( p ); - } -}; - -namespace Detail { - template - std::string rangeToString( InputIterator first, InputIterator last ); -} - -//template -//struct StringMaker > { -// static std::string convert( std::vector const& v ) { -// return Detail::rangeToString( v.begin(), v.end() ); -// } -//}; - -template -std::string toString( std::vector const& v ) { - return Detail::rangeToString( v.begin(), v.end() ); -} - -#ifdef CATCH_CONFIG_CPP11_TUPLE - -// toString for tuples -namespace TupleDetail { - template< - typename Tuple, - std::size_t N = 0, - bool = (N < std::tuple_size::value) - > - struct ElementPrinter { - static void print( const Tuple& tuple, std::ostream& os ) - { - os << ( N ? ", " : " " ) - << Catch::toString(std::get(tuple)); - ElementPrinter::print(tuple,os); - } - }; - - template< - typename Tuple, - std::size_t N - > - struct ElementPrinter { - static void print( const Tuple&, std::ostream& ) {} - }; - -} - -template -struct StringMaker> { - - static std::string convert( const std::tuple& tuple ) - { - std::ostringstream os; - os << '{'; - TupleDetail::ElementPrinter>::print( tuple, os ); - os << " }"; - return os.str(); - } -}; -#endif // CATCH_CONFIG_CPP11_TUPLE - -namespace Detail { - template - std::string makeString( T const& value ) { - return StringMaker::convert( value ); - } -} // end namespace Detail - -/// \brief converts any type to a string -/// -/// The default template forwards on to ostringstream - except when an -/// ostringstream overload does not exist - in which case it attempts to detect -/// that and writes {?}. -/// Overload (not specialise) this template for custom typs that you don't want -/// to provide an ostream overload for. -template -std::string toString( T const& value ) { - return StringMaker::convert( value ); -} - - namespace Detail { - template - std::string rangeToString( InputIterator first, InputIterator last ) { - std::ostringstream oss; - oss << "{ "; - if( first != last ) { - oss << Catch::toString( *first ); - for( ++first ; first != last ; ++first ) - oss << ", " << Catch::toString( *first ); - } - oss << " }"; - return oss.str(); - } -} - -} // end namespace Catch - -namespace Catch { - -template -class BinaryExpression; - -template -class MatchExpression; - -// Wraps the LHS of an expression and overloads comparison operators -// for also capturing those and RHS (if any) -template -class ExpressionLhs : public DecomposedExpression { -public: - ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {} - - ExpressionLhs& operator = ( const ExpressionLhs& ); - - template - BinaryExpression - operator == ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator != ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator < ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator > ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator <= ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator >= ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - BinaryExpression operator == ( bool rhs ) { - return captureExpression( rhs ); - } - - BinaryExpression operator != ( bool rhs ) { - return captureExpression( rhs ); - } - - void endExpression() { - m_truthy = m_lhs ? true : false; - m_rb - .setResultType( m_truthy ) - .endExpression( *this ); - } - - virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { - dest = Catch::toString( m_lhs ); - } - -private: - template - BinaryExpression captureExpression( RhsT& rhs ) const { - return BinaryExpression( m_rb, m_lhs, rhs ); - } - - template - BinaryExpression captureExpression( bool rhs ) const { - return BinaryExpression( m_rb, m_lhs, rhs ); - } - -private: - ResultBuilder& m_rb; - T m_lhs; - bool m_truthy; -}; - -template -class BinaryExpression : public DecomposedExpression { -public: - BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs ) - : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {} - - BinaryExpression& operator = ( BinaryExpression& ); - - void endExpression() const { - m_rb - .setResultType( Internal::compare( m_lhs, m_rhs ) ) - .endExpression( *this ); - } - - virtual bool isBinaryExpression() const CATCH_OVERRIDE { - return true; - } - - virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { - std::string lhs = Catch::toString( m_lhs ); - std::string rhs = Catch::toString( m_rhs ); - char delim = lhs.size() + rhs.size() < 40 && - lhs.find('\n') == std::string::npos && - rhs.find('\n') == std::string::npos ? ' ' : '\n'; - dest.reserve( 7 + lhs.size() + rhs.size() ); - // 2 for spaces around operator - // 2 for operator - // 2 for parentheses (conditionally added later) - // 1 for negation (conditionally added later) - dest = lhs; - dest += delim; - dest += Internal::OperatorTraits::getName(); - dest += delim; - dest += rhs; - } - -private: - ResultBuilder& m_rb; - LhsT m_lhs; - RhsT m_rhs; -}; - -template -class MatchExpression : public DecomposedExpression { -public: - MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString ) - : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {} - - virtual bool isBinaryExpression() const CATCH_OVERRIDE { - return true; - } - - virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { - std::string matcherAsString = m_matcher.toString(); - dest = Catch::toString( m_arg ); - dest += ' '; - if( matcherAsString == Detail::unprintableString ) - dest += m_matcherString; - else - dest += matcherAsString; - } - -private: - ArgT m_arg; - MatcherT m_matcher; - char const* m_matcherString; -}; - -} // end namespace Catch - - -namespace Catch { - - template - ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { - return ExpressionLhs( *this, operand ); - } - - inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { - return ExpressionLhs( *this, value ); - } - - template - void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher, - char const* matcherString ) { - MatchExpression expr( arg, matcher, matcherString ); - setResultType( matcher.match( arg ) ); - endExpression( expr ); - } - -} // namespace Catch - -// #included from: catch_message.h -#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED - -#include - -namespace Catch { - - struct MessageInfo { - MessageInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ); - - std::string macroName; - SourceLineInfo lineInfo; - ResultWas::OfType type; - std::string message; - unsigned int sequence; - - bool operator == ( MessageInfo const& other ) const { - return sequence == other.sequence; - } - bool operator < ( MessageInfo const& other ) const { - return sequence < other.sequence; - } - private: - static unsigned int globalCount; - }; - - struct MessageBuilder { - MessageBuilder( std::string const& macroName, - SourceLineInfo const& lineInfo, - ResultWas::OfType type ) - : m_info( macroName, lineInfo, type ) - {} - - template - MessageBuilder& operator << ( T const& value ) { - m_stream << value; - return *this; - } - - MessageInfo m_info; - std::ostringstream m_stream; - }; - - class ScopedMessage { - public: - ScopedMessage( MessageBuilder const& builder ); - ScopedMessage( ScopedMessage const& other ); - ~ScopedMessage(); - - MessageInfo m_info; - }; - -} // end namespace Catch - -// #included from: catch_interfaces_capture.h -#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED - -#include - -namespace Catch { - - class TestCase; - class AssertionResult; - struct AssertionInfo; - struct SectionInfo; - struct SectionEndInfo; - struct MessageInfo; - class ScopedMessageBuilder; - struct Counts; - - struct IResultCapture { - - virtual ~IResultCapture(); - - virtual void assertionEnded( AssertionResult const& result ) = 0; - virtual bool sectionStarted( SectionInfo const& sectionInfo, - Counts& assertions ) = 0; - virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; - virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; - virtual void pushScopedMessage( MessageInfo const& message ) = 0; - virtual void popScopedMessage( MessageInfo const& message ) = 0; - - virtual std::string getCurrentTestName() const = 0; - virtual const AssertionResult* getLastResult() const = 0; - - virtual void exceptionEarlyReported() = 0; - - virtual void handleFatalErrorCondition( std::string const& message ) = 0; - - virtual bool lastAssertionPassed() = 0; - virtual void assertionPassed() = 0; - virtual void assertionRun() = 0; - }; - - IResultCapture& getResultCapture(); -} - -// #included from: catch_debugger.h -#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED - -// #included from: catch_platform.h -#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED - -#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) -# define CATCH_PLATFORM_MAC -#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) -# define CATCH_PLATFORM_IPHONE -#elif defined(linux) || defined(__linux) || defined(__linux__) -# define CATCH_PLATFORM_LINUX -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) -# define CATCH_PLATFORM_WINDOWS -# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) -# define CATCH_DEFINES_NOMINMAX -# endif -# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) -# define CATCH_DEFINES_WIN32_LEAN_AND_MEAN -# endif -#endif - -#include - -namespace Catch{ - - bool isDebuggerActive(); - void writeToDebugConsole( std::string const& text ); -} - -#ifdef CATCH_PLATFORM_MAC - - // The following code snippet based on: - // http://cocoawithlove.com/2008/03/break-into-debugger.html - #if defined(__ppc64__) || defined(__ppc__) - #define CATCH_TRAP() \ - __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ - : : : "memory","r0","r3","r4" ) /* NOLINT */ - #else - #define CATCH_TRAP() __asm__("int $3\n" : : /* NOLINT */ ) - #endif - -#elif defined(CATCH_PLATFORM_LINUX) - // If we can use inline assembler, do it because this allows us to break - // directly at the location of the failing check instead of breaking inside - // raise() called from it, i.e. one stack frame below. - #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) - #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */ - #else // Fall back to the generic way. - #include - - #define CATCH_TRAP() raise(SIGTRAP) - #endif -#elif defined(_MSC_VER) - #define CATCH_TRAP() __debugbreak() -#elif defined(__MINGW32__) - extern "C" __declspec(dllimport) void __stdcall DebugBreak(); - #define CATCH_TRAP() DebugBreak() -#endif - -#ifdef CATCH_TRAP - #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } -#else - #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); -#endif - -// #included from: catch_interfaces_runner.h -#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED - -namespace Catch { - class TestCase; - - struct IRunner { - virtual ~IRunner(); - virtual bool aborting() const = 0; - }; -} - -#if defined(CATCH_CONFIG_FAST_COMPILE) -/////////////////////////////////////////////////////////////////////////////// -// We can speedup compilation significantly by breaking into debugger lower in -// the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER -// macro in each assertion -#define INTERNAL_CATCH_REACT( resultBuilder ) \ - resultBuilder.react(); - -/////////////////////////////////////////////////////////////////////////////// -// Another way to speed-up compilation is to omit local try-catch for REQUIRE* -// macros. -// This can potentially cause false negative, if the test code catches -// the exception before it propagates back up to the runner. -#define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - __catchResult.setExceptionGuard(); \ - CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - ( __catchResult <= expr ).endExpression(); \ - CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - __catchResult.unsetExceptionGuard(); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::isTrue( false && static_cast( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look -// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. - -#define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ - __catchResult.setExceptionGuard(); \ - __catchResult.captureMatch( arg, matcher, #matcher ); \ - __catchResult.unsetExceptionGuard(); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -#else -/////////////////////////////////////////////////////////////////////////////// -// In the event of a failure works out if the debugger needs to be invoked -// and/or an exception thrown and takes appropriate action. -// This needs to be done as a macro so the debugger will stop in the user -// source code rather than in Catch library code -#define INTERNAL_CATCH_REACT( resultBuilder ) \ - if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ - resultBuilder.react(); -#endif - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - try { \ - CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - ( __catchResult <= expr ).endExpression(); \ - CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - } \ - catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ - } \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::isTrue( false && static_cast( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look - // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \ - INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ - if( Catch::getResultCapture().lastAssertionPassed() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \ - INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ - if( !Catch::getResultCapture().lastAssertionPassed() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - try { \ - static_cast(expr); \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - } \ - catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ - } \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ - if( __catchResult.allowThrows() ) \ - try { \ - static_cast(expr); \ - __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ - } \ - catch( ... ) { \ - __catchResult.captureExpectedException( matcher ); \ - } \ - else \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \ - if( __catchResult.allowThrows() ) \ - try { \ - static_cast(expr); \ - __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ - } \ - catch( exceptionType ) { \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - } \ - catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ - } \ - else \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -/////////////////////////////////////////////////////////////////////////////// -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ - __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ - __catchResult.captureResult( messageType ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) -#else - #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, log ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ - __catchResult << log + ::Catch::StreamEndStop(); \ - __catchResult.captureResult( messageType ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) -#endif - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_INFO( macroName, log ) \ - Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ - try { \ - __catchResult.captureMatch( arg, matcher, #matcher ); \ - } catch( ... ) { \ - __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ - } \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -// #included from: internal/catch_section.h -#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED - -// #included from: catch_section_info.h -#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED - -// #included from: catch_totals.hpp -#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED - -#include - -namespace Catch { - - struct Counts { - Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} - - Counts operator - ( Counts const& other ) const { - Counts diff; - diff.passed = passed - other.passed; - diff.failed = failed - other.failed; - diff.failedButOk = failedButOk - other.failedButOk; - return diff; - } - Counts& operator += ( Counts const& other ) { - passed += other.passed; - failed += other.failed; - failedButOk += other.failedButOk; - return *this; - } - - std::size_t total() const { - return passed + failed + failedButOk; - } - bool allPassed() const { - return failed == 0 && failedButOk == 0; - } - bool allOk() const { - return failed == 0; - } - - std::size_t passed; - std::size_t failed; - std::size_t failedButOk; - }; - - struct Totals { - - Totals operator - ( Totals const& other ) const { - Totals diff; - diff.assertions = assertions - other.assertions; - diff.testCases = testCases - other.testCases; - return diff; - } - - Totals delta( Totals const& prevTotals ) const { - Totals diff = *this - prevTotals; - if( diff.assertions.failed > 0 ) - ++diff.testCases.failed; - else if( diff.assertions.failedButOk > 0 ) - ++diff.testCases.failedButOk; - else - ++diff.testCases.passed; - return diff; - } - - Totals& operator += ( Totals const& other ) { - assertions += other.assertions; - testCases += other.testCases; - return *this; - } - - Counts assertions; - Counts testCases; - }; -} - -#include - -namespace Catch { - - struct SectionInfo { - SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name, - std::string const& _description = std::string() ); - - std::string name; - std::string description; - SourceLineInfo lineInfo; - }; - - struct SectionEndInfo { - SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) - : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) - {} - - SectionInfo sectionInfo; - Counts prevAssertions; - double durationInSeconds; - }; - -} // end namespace Catch - -// #included from: catch_timer.h -#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED - -#ifdef _MSC_VER - -namespace Catch { - typedef unsigned long long UInt64; -} -#else -#include -namespace Catch { - typedef uint64_t UInt64; -} -#endif - -namespace Catch { - class Timer { - public: - Timer() : m_ticks( 0 ) {} - void start(); - unsigned int getElapsedMicroseconds() const; - unsigned int getElapsedMilliseconds() const; - double getElapsedSeconds() const; - - private: - UInt64 m_ticks; - }; - -} // namespace Catch - -#include - -namespace Catch { - - class Section : NonCopyable { - public: - Section( SectionInfo const& info ); - ~Section(); - - // This indicates whether the section should be executed or not - operator bool() const; - - private: - SectionInfo m_info; - - std::string m_name; - Counts m_assertions; - bool m_sectionIncluded; - Timer m_timer; - }; - -} // end namespace Catch - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define INTERNAL_CATCH_SECTION( ... ) \ - if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) -#else - #define INTERNAL_CATCH_SECTION( name, desc ) \ - if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) -#endif - -// #included from: internal/catch_generators.hpp -#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED - -#include -#include -#include - -namespace Catch { - -template -struct IGenerator { - virtual ~IGenerator() {} - virtual T getValue( std::size_t index ) const = 0; - virtual std::size_t size () const = 0; -}; - -template -class BetweenGenerator : public IGenerator { -public: - BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} - - virtual T getValue( std::size_t index ) const { - return m_from+static_cast( index ); - } - - virtual std::size_t size() const { - return static_cast( 1+m_to-m_from ); - } - -private: - - T m_from; - T m_to; -}; - -template -class ValuesGenerator : public IGenerator { -public: - ValuesGenerator(){} - - void add( T value ) { - m_values.push_back( value ); - } - - virtual T getValue( std::size_t index ) const { - return m_values[index]; - } - - virtual std::size_t size() const { - return m_values.size(); - } - -private: - std::vector m_values; -}; - -template -class CompositeGenerator { -public: - CompositeGenerator() : m_totalSize( 0 ) {} - - // *** Move semantics, similar to auto_ptr *** - CompositeGenerator( CompositeGenerator& other ) - : m_fileInfo( other.m_fileInfo ), - m_totalSize( 0 ) - { - move( other ); - } - - CompositeGenerator& setFileInfo( const char* fileInfo ) { - m_fileInfo = fileInfo; - return *this; - } - - ~CompositeGenerator() { - deleteAll( m_composed ); - } - - operator T () const { - size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); - - typename std::vector*>::const_iterator it = m_composed.begin(); - typename std::vector*>::const_iterator itEnd = m_composed.end(); - for( size_t index = 0; it != itEnd; ++it ) - { - const IGenerator* generator = *it; - if( overallIndex >= index && overallIndex < index + generator->size() ) - { - return generator->getValue( overallIndex-index ); - } - index += generator->size(); - } - CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); - return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so - } - - void add( const IGenerator* generator ) { - m_totalSize += generator->size(); - m_composed.push_back( generator ); - } - - CompositeGenerator& then( CompositeGenerator& other ) { - move( other ); - return *this; - } - - CompositeGenerator& then( T value ) { - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( value ); - add( valuesGen ); - return *this; - } - -private: - - void move( CompositeGenerator& other ) { - m_composed.insert( m_composed.end(), other.m_composed.begin(), other.m_composed.end() ); - m_totalSize += other.m_totalSize; - other.m_composed.clear(); - } - - std::vector*> m_composed; - std::string m_fileInfo; - size_t m_totalSize; -}; - -namespace Generators -{ - template - CompositeGenerator between( T from, T to ) { - CompositeGenerator generators; - generators.add( new BetweenGenerator( from, to ) ); - return generators; - } - - template - CompositeGenerator values( T val1, T val2 ) { - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - generators.add( valuesGen ); - return generators; - } - - template - CompositeGenerator values( T val1, T val2, T val3 ){ - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - valuesGen->add( val3 ); - generators.add( valuesGen ); - return generators; - } - - template - CompositeGenerator values( T val1, T val2, T val3, T val4 ) { - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - valuesGen->add( val3 ); - valuesGen->add( val4 ); - generators.add( valuesGen ); - return generators; - } - -} // end namespace Generators - -using namespace Generators; - -} // end namespace Catch - -#define INTERNAL_CATCH_LINESTR2( line ) #line -#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) - -#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) - -// #included from: internal/catch_interfaces_exception.h -#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED - -#include -#include - -// #included from: catch_interfaces_registry_hub.h -#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED - -#include - -namespace Catch { - - class TestCase; - struct ITestCaseRegistry; - struct IExceptionTranslatorRegistry; - struct IExceptionTranslator; - struct IReporterRegistry; - struct IReporterFactory; - struct ITagAliasRegistry; - - struct IRegistryHub { - virtual ~IRegistryHub(); - - virtual IReporterRegistry const& getReporterRegistry() const = 0; - virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; - virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; - - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; - }; - - struct IMutableRegistryHub { - virtual ~IMutableRegistryHub(); - virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; - virtual void registerListener( Ptr const& factory ) = 0; - virtual void registerTest( TestCase const& testInfo ) = 0; - virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; - virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; - }; - - IRegistryHub& getRegistryHub(); - IMutableRegistryHub& getMutableRegistryHub(); - void cleanUp(); - std::string translateActiveException(); - -} - -namespace Catch { - - typedef std::string(*exceptionTranslateFunction)(); - - struct IExceptionTranslator; - typedef std::vector ExceptionTranslators; - - struct IExceptionTranslator { - virtual ~IExceptionTranslator(); - virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; - }; - - struct IExceptionTranslatorRegistry { - virtual ~IExceptionTranslatorRegistry(); - - virtual std::string translateActiveException() const = 0; - }; - - class ExceptionTranslatorRegistrar { - template - class ExceptionTranslator : public IExceptionTranslator { - public: - - ExceptionTranslator( std::string(*translateFunction)( T& ) ) - : m_translateFunction( translateFunction ) - {} - - virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { - try { - if( it == itEnd ) - throw; - else - return (*it)->translate( it+1, itEnd ); - } - catch( T& ex ) { - return m_translateFunction( ex ); - } - } - - protected: - std::string(*m_translateFunction)( T& ); - }; - - public: - template - ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { - getMutableRegistryHub().registerTranslator - ( new ExceptionTranslator( translateFunction ) ); - } - }; -} - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ - static std::string translatorName( signature ); \ - namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ - static std::string translatorName( signature ) - -#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) - -// #included from: internal/catch_approx.hpp -#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED - -#include -#include - -#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) -#include -#endif - -namespace Catch { -namespace Detail { - - class Approx { - public: - explicit Approx ( double value ) - : m_epsilon( std::numeric_limits::epsilon()*100 ), - m_margin( 0.0 ), - m_scale( 1.0 ), - m_value( value ) - {} - - static Approx custom() { - return Approx( 0 ); - } - -#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) - - template ::value>::type> - Approx operator()( T value ) { - Approx approx( static_cast(value) ); - approx.epsilon( m_epsilon ); - approx.margin( m_margin ); - approx.scale( m_scale ); - return approx; - } - - template ::value>::type> - explicit Approx( T value ): Approx(static_cast(value)) - {} - - template ::value>::type> - friend bool operator == ( const T& lhs, Approx const& rhs ) { - // Thanks to Richard Harris for his help refining this formula - auto lhs_v = double(lhs); - bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); - if (relativeOK) { - return true; - } - return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin; - } - - template ::value>::type> - friend bool operator == ( Approx const& lhs, const T& rhs ) { - return operator==( rhs, lhs ); - } - - template ::value>::type> - friend bool operator != ( T lhs, Approx const& rhs ) { - return !operator==( lhs, rhs ); - } - - template ::value>::type> - friend bool operator != ( Approx const& lhs, T rhs ) { - return !operator==( rhs, lhs ); - } - - template ::value>::type> - friend bool operator <= ( T lhs, Approx const& rhs ) { - return double(lhs) < rhs.m_value || lhs == rhs; - } - - template ::value>::type> - friend bool operator <= ( Approx const& lhs, T rhs ) { - return lhs.m_value < double(rhs) || lhs == rhs; - } - - template ::value>::type> - friend bool operator >= ( T lhs, Approx const& rhs ) { - return double(lhs) > rhs.m_value || lhs == rhs; - } - - template ::value>::type> - friend bool operator >= ( Approx const& lhs, T rhs ) { - return lhs.m_value > double(rhs) || lhs == rhs; - } - - template ::value>::type> - Approx& epsilon( T newEpsilon ) { - m_epsilon = double(newEpsilon); - return *this; - } - - template ::value>::type> - Approx& margin( T newMargin ) { - m_margin = double(newMargin); - return *this; - } - - template ::value>::type> - Approx& scale( T newScale ) { - m_scale = double(newScale); - return *this; - } - -#else - - Approx operator()( double value ) { - Approx approx( value ); - approx.epsilon( m_epsilon ); - approx.margin( m_margin ); - approx.scale( m_scale ); - return approx; - } - - friend bool operator == ( double lhs, Approx const& rhs ) { - // Thanks to Richard Harris for his help refining this formula - bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) ); - if (relativeOK) { - return true; - } - return std::fabs(lhs - rhs.m_value) < rhs.m_margin; - } - - friend bool operator == ( Approx const& lhs, double rhs ) { - return operator==( rhs, lhs ); - } - - friend bool operator != ( double lhs, Approx const& rhs ) { - return !operator==( lhs, rhs ); - } - - friend bool operator != ( Approx const& lhs, double rhs ) { - return !operator==( rhs, lhs ); - } - - friend bool operator <= ( double lhs, Approx const& rhs ) { - return lhs < rhs.m_value || lhs == rhs; - } - - friend bool operator <= ( Approx const& lhs, double rhs ) { - return lhs.m_value < rhs || lhs == rhs; - } - - friend bool operator >= ( double lhs, Approx const& rhs ) { - return lhs > rhs.m_value || lhs == rhs; - } - - friend bool operator >= ( Approx const& lhs, double rhs ) { - return lhs.m_value > rhs || lhs == rhs; - } - - Approx& epsilon( double newEpsilon ) { - m_epsilon = newEpsilon; - return *this; - } - - Approx& margin( double newMargin ) { - m_margin = newMargin; - return *this; - } - - Approx& scale( double newScale ) { - m_scale = newScale; - return *this; - } -#endif - - std::string toString() const { - std::ostringstream oss; - oss << "Approx( " << Catch::toString( m_value ) << " )"; - return oss.str(); - } - - private: - double m_epsilon; - double m_margin; - double m_scale; - double m_value; - }; -} - -template<> -inline std::string toString( Detail::Approx const& value ) { - return value.toString(); -} - -} // end namespace Catch - -// #included from: internal/catch_matchers_string.h -#define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED - -namespace Catch { -namespace Matchers { - - namespace StdString { - - struct CasedString - { - CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ); - std::string adjustString( std::string const& str ) const; - std::string caseSensitivitySuffix() const; - - CaseSensitive::Choice m_caseSensitivity; - std::string m_str; - }; - - struct StringMatcherBase : MatcherBase { - StringMatcherBase( std::string const& operation, CasedString const& comparator ); - virtual std::string describe() const CATCH_OVERRIDE; - - CasedString m_comparator; - std::string m_operation; - }; - - struct EqualsMatcher : StringMatcherBase { - EqualsMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const CATCH_OVERRIDE; - }; - struct ContainsMatcher : StringMatcherBase { - ContainsMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const CATCH_OVERRIDE; - }; - struct StartsWithMatcher : StringMatcherBase { - StartsWithMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const CATCH_OVERRIDE; - }; - struct EndsWithMatcher : StringMatcherBase { - EndsWithMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const CATCH_OVERRIDE; - }; - - } // namespace StdString - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - - StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); - StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); - StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); - StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); - -} // namespace Matchers -} // namespace Catch - -// #included from: internal/catch_matchers_vector.h -#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED - -namespace Catch { -namespace Matchers { - - namespace Vector { - - template - struct ContainsElementMatcher : MatcherBase, T> { - - ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} - - bool match(std::vector const &v) const CATCH_OVERRIDE { - return std::find(v.begin(), v.end(), m_comparator) != v.end(); - } - - virtual std::string describe() const CATCH_OVERRIDE { - return "Contains: " + Catch::toString( m_comparator ); - } - - T const& m_comparator; - }; - - template - struct ContainsMatcher : MatcherBase, std::vector > { - - ContainsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} - - bool match(std::vector const &v) const CATCH_OVERRIDE { - // !TBD: see note in EqualsMatcher - if (m_comparator.size() > v.size()) - return false; - for (size_t i = 0; i < m_comparator.size(); ++i) - if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end()) - return false; - return true; - } - virtual std::string describe() const CATCH_OVERRIDE { - return "Contains: " + Catch::toString( m_comparator ); - } - - std::vector const& m_comparator; - }; - - template - struct EqualsMatcher : MatcherBase, std::vector > { - - EqualsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} - - bool match(std::vector const &v) const CATCH_OVERRIDE { - // !TBD: This currently works if all elements can be compared using != - // - a more general approach would be via a compare template that defaults - // to using !=. but could be specialised for, e.g. std::vector etc - // - then just call that directly - if (m_comparator.size() != v.size()) - return false; - for (size_t i = 0; i < v.size(); ++i) - if (m_comparator[i] != v[i]) - return false; - return true; - } - virtual std::string describe() const CATCH_OVERRIDE { - return "Equals: " + Catch::toString( m_comparator ); - } - std::vector const& m_comparator; - }; - - } // namespace Vector - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - - template - Vector::ContainsMatcher Contains( std::vector const& comparator ) { - return Vector::ContainsMatcher( comparator ); - } - - template - Vector::ContainsElementMatcher VectorContains( T const& comparator ) { - return Vector::ContainsElementMatcher( comparator ); - } - - template - Vector::EqualsMatcher Equals( std::vector const& comparator ) { - return Vector::EqualsMatcher( comparator ); - } - -} // namespace Matchers -} // namespace Catch - -// #included from: internal/catch_interfaces_tag_alias_registry.h -#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED - -// #included from: catch_tag_alias.h -#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED - -#include - -namespace Catch { - - struct TagAlias { - TagAlias( std::string const& _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} - - std::string tag; - SourceLineInfo lineInfo; - }; - - struct RegistrarForTagAliases { - RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); - }; - -} // end namespace Catch - -#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } -// #included from: catch_option.hpp -#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED - -namespace Catch { - - // An optional type - template - class Option { - public: - Option() : nullableValue( CATCH_NULL ) {} - Option( T const& _value ) - : nullableValue( new( storage ) T( _value ) ) - {} - Option( Option const& _other ) - : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) - {} - - ~Option() { - reset(); - } - - Option& operator= ( Option const& _other ) { - if( &_other != this ) { - reset(); - if( _other ) - nullableValue = new( storage ) T( *_other ); - } - return *this; - } - Option& operator = ( T const& _value ) { - reset(); - nullableValue = new( storage ) T( _value ); - return *this; - } - - void reset() { - if( nullableValue ) - nullableValue->~T(); - nullableValue = CATCH_NULL; - } - - T& operator*() { return *nullableValue; } - T const& operator*() const { return *nullableValue; } - T* operator->() { return nullableValue; } - const T* operator->() const { return nullableValue; } - - T valueOr( T const& defaultValue ) const { - return nullableValue ? *nullableValue : defaultValue; - } - - bool some() const { return nullableValue != CATCH_NULL; } - bool none() const { return nullableValue == CATCH_NULL; } - - bool operator !() const { return nullableValue == CATCH_NULL; } - operator SafeBool::type() const { - return SafeBool::makeSafe( some() ); - } - - private: - T *nullableValue; - union { - char storage[sizeof(T)]; - - // These are here to force alignment for the storage - long double dummy1; - void (*dummy2)(); - long double dummy3; -#ifdef CATCH_CONFIG_CPP11_LONG_LONG - long long dummy4; -#endif - }; - }; - -} // end namespace Catch - -namespace Catch { - - struct ITagAliasRegistry { - virtual ~ITagAliasRegistry(); - virtual Option find( std::string const& alias ) const = 0; - virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; - - static ITagAliasRegistry const& get(); - }; - -} // end namespace Catch - -// These files are included here so the single_include script doesn't put them -// in the conditionally compiled sections -// #included from: internal/catch_test_case_info.h -#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED - -#include -#include - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - - struct ITestCase; - - struct TestCaseInfo { - enum SpecialProperties{ - None = 0, - IsHidden = 1 << 1, - ShouldFail = 1 << 2, - MayFail = 1 << 3, - Throws = 1 << 4, - NonPortable = 1 << 5 - }; - - TestCaseInfo( std::string const& _name, - std::string const& _className, - std::string const& _description, - std::set const& _tags, - SourceLineInfo const& _lineInfo ); - - TestCaseInfo( TestCaseInfo const& other ); - - friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); - - bool isHidden() const; - bool throws() const; - bool okToFail() const; - bool expectedToFail() const; - - std::string name; - std::string className; - std::string description; - std::set tags; - std::set lcaseTags; - std::string tagsAsString; - SourceLineInfo lineInfo; - SpecialProperties properties; - }; - - class TestCase : public TestCaseInfo { - public: - - TestCase( ITestCase* testCase, TestCaseInfo const& info ); - TestCase( TestCase const& other ); - - TestCase withName( std::string const& _newName ) const; - - void invoke() const; - - TestCaseInfo const& getTestCaseInfo() const; - - void swap( TestCase& other ); - bool operator == ( TestCase const& other ) const; - bool operator < ( TestCase const& other ) const; - TestCase& operator = ( TestCase const& other ); - - private: - Ptr test; - }; - - TestCase makeTestCase( ITestCase* testCase, - std::string const& className, - std::string const& name, - std::string const& description, - SourceLineInfo const& lineInfo ); -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - - -#ifdef __OBJC__ -// #included from: internal/catch_objc.hpp -#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED - -#import - -#include - -// NB. Any general catch headers included here must be included -// in catch.hpp first to make sure they are included by the single -// header for non obj-usage - -/////////////////////////////////////////////////////////////////////////////// -// This protocol is really only here for (self) documenting purposes, since -// all its methods are optional. -@protocol OcFixture - -@optional - --(void) setUp; --(void) tearDown; - -@end - -namespace Catch { - - class OcMethod : public SharedImpl { - - public: - OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} - - virtual void invoke() const { - id obj = [[m_cls alloc] init]; - - performOptionalSelector( obj, @selector(setUp) ); - performOptionalSelector( obj, m_sel ); - performOptionalSelector( obj, @selector(tearDown) ); - - arcSafeRelease( obj ); - } - private: - virtual ~OcMethod() {} - - Class m_cls; - SEL m_sel; - }; - - namespace Detail{ - - inline std::string getAnnotation( Class cls, - std::string const& annotationName, - std::string const& testCaseName ) { - NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; - SEL sel = NSSelectorFromString( selStr ); - arcSafeRelease( selStr ); - id value = performOptionalSelector( cls, sel ); - if( value ) - return [(NSString*)value UTF8String]; - return ""; - } - } - - inline size_t registerTestMethods() { - size_t noTestMethods = 0; - int noClasses = objc_getClassList( CATCH_NULL, 0 ); - - Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); - objc_getClassList( classes, noClasses ); - - for( int c = 0; c < noClasses; c++ ) { - Class cls = classes[c]; - { - u_int count; - Method* methods = class_copyMethodList( cls, &count ); - for( u_int m = 0; m < count ; m++ ) { - SEL selector = method_getName(methods[m]); - std::string methodName = sel_getName(selector); - if( startsWith( methodName, "Catch_TestCase_" ) ) { - std::string testCaseName = methodName.substr( 15 ); - std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); - std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); - const char* className = class_getName( cls ); - - getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); - noTestMethods++; - } - } - free(methods); - } - } - return noTestMethods; - } - - namespace Matchers { - namespace Impl { - namespace NSStringMatchers { - - struct StringHolder : MatcherBase{ - StringHolder( NSString* substr ) : m_substr( [substr copy] ){} - StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} - StringHolder() { - arcSafeRelease( m_substr ); - } - - virtual bool match( NSString* arg ) const CATCH_OVERRIDE { - return false; - } - - NSString* m_substr; - }; - - struct Equals : StringHolder { - Equals( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( NSString* str ) const CATCH_OVERRIDE { - return (str != nil || m_substr == nil ) && - [str isEqualToString:m_substr]; - } - - virtual std::string describe() const CATCH_OVERRIDE { - return "equals string: " + Catch::toString( m_substr ); - } - }; - - struct Contains : StringHolder { - Contains( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( NSString* str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location != NSNotFound; - } - - virtual std::string describe() const CATCH_OVERRIDE { - return "contains string: " + Catch::toString( m_substr ); - } - }; - - struct StartsWith : StringHolder { - StartsWith( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( NSString* str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location == 0; - } - - virtual std::string describe() const CATCH_OVERRIDE { - return "starts with: " + Catch::toString( m_substr ); - } - }; - struct EndsWith : StringHolder { - EndsWith( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( NSString* str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location == [str length] - [m_substr length]; - } - - virtual std::string describe() const CATCH_OVERRIDE { - return "ends with: " + Catch::toString( m_substr ); - } - }; - - } // namespace NSStringMatchers - } // namespace Impl - - inline Impl::NSStringMatchers::Equals - Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } - - inline Impl::NSStringMatchers::Contains - Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } - - inline Impl::NSStringMatchers::StartsWith - StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } - - inline Impl::NSStringMatchers::EndsWith - EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } - - } // namespace Matchers - - using namespace Matchers; - -} // namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define OC_TEST_CASE( name, desc )\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ -{\ -return @ name; \ -}\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ -{ \ -return @ desc; \ -} \ --(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) - -#endif - -#ifdef CATCH_IMPL - -// !TBD: Move the leak detector code into a separate header -#ifdef CATCH_CONFIG_WINDOWS_CRTDBG -#include -class LeakDetector { -public: - LeakDetector() { - int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - flag |= _CRTDBG_LEAK_CHECK_DF; - flag |= _CRTDBG_ALLOC_MEM_DF; - _CrtSetDbgFlag(flag); - _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); - _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); - // Change this to leaking allocation's number to break there - _CrtSetBreakAlloc(-1); - } -}; -#else -class LeakDetector {}; -#endif - -LeakDetector leakDetector; - -// #included from: internal/catch_impl.hpp -#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED - -// Collect all the implementation files together here -// These are the equivalent of what would usually be cpp files - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wweak-vtables" -#endif - -// #included from: ../catch_session.hpp -#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED - -// #included from: internal/catch_commandline.hpp -#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED - -// #included from: catch_config.hpp -#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED - -// #included from: catch_test_spec_parser.hpp -#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -// #included from: catch_test_spec.hpp -#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -// #included from: catch_wildcard_pattern.hpp -#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED - -#include - -namespace Catch -{ - class WildcardPattern { - enum WildcardPosition { - NoWildcard = 0, - WildcardAtStart = 1, - WildcardAtEnd = 2, - WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd - }; - - public: - - WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) - : m_caseSensitivity( caseSensitivity ), - m_wildcard( NoWildcard ), - m_pattern( adjustCase( pattern ) ) - { - if( startsWith( m_pattern, '*' ) ) { - m_pattern = m_pattern.substr( 1 ); - m_wildcard = WildcardAtStart; - } - if( endsWith( m_pattern, '*' ) ) { - m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); - m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); - } - } - virtual ~WildcardPattern(); - virtual bool matches( std::string const& str ) const { - switch( m_wildcard ) { - case NoWildcard: - return m_pattern == adjustCase( str ); - case WildcardAtStart: - return endsWith( adjustCase( str ), m_pattern ); - case WildcardAtEnd: - return startsWith( adjustCase( str ), m_pattern ); - case WildcardAtBothEnds: - return contains( adjustCase( str ), m_pattern ); - } - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - throw std::logic_error( "Unknown enum" ); -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - } - private: - std::string adjustCase( std::string const& str ) const { - return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; - } - CaseSensitive::Choice m_caseSensitivity; - WildcardPosition m_wildcard; - std::string m_pattern; - }; -} - -#include -#include - -namespace Catch { - - class TestSpec { - struct Pattern : SharedImpl<> { - virtual ~Pattern(); - virtual bool matches( TestCaseInfo const& testCase ) const = 0; - }; - class NamePattern : public Pattern { - public: - NamePattern( std::string const& name ) - : m_wildcardPattern( toLower( name ), CaseSensitive::No ) - {} - virtual ~NamePattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { - return m_wildcardPattern.matches( toLower( testCase.name ) ); - } - private: - WildcardPattern m_wildcardPattern; - }; - - class TagPattern : public Pattern { - public: - TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} - virtual ~TagPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { - return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); - } - private: - std::string m_tag; - }; - - class ExcludedPattern : public Pattern { - public: - ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} - virtual ~ExcludedPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } - private: - Ptr m_underlyingPattern; - }; - - struct Filter { - std::vector > m_patterns; - - bool matches( TestCaseInfo const& testCase ) const { - // All patterns in a filter must match for the filter to be a match - for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) { - if( !(*it)->matches( testCase ) ) - return false; - } - return true; - } - }; - - public: - bool hasFilters() const { - return !m_filters.empty(); - } - bool matches( TestCaseInfo const& testCase ) const { - // A TestSpec matches if any filter matches - for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) - if( it->matches( testCase ) ) - return true; - return false; - } - - private: - std::vector m_filters; - - friend class TestSpecParser; - }; -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -namespace Catch { - - class TestSpecParser { - enum Mode{ None, Name, QuotedName, Tag, EscapedName }; - Mode m_mode; - bool m_exclusion; - std::size_t m_start, m_pos; - std::string m_arg; - std::vector m_escapeChars; - TestSpec::Filter m_currentFilter; - TestSpec m_testSpec; - ITagAliasRegistry const* m_tagAliases; - - public: - TestSpecParser( ITagAliasRegistry const& tagAliases ) :m_mode(None), m_exclusion(false), m_start(0), m_pos(0), m_tagAliases( &tagAliases ) {} - - TestSpecParser& parse( std::string const& arg ) { - m_mode = None; - m_exclusion = false; - m_start = std::string::npos; - m_arg = m_tagAliases->expandAliases( arg ); - m_escapeChars.clear(); - for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) - visitChar( m_arg[m_pos] ); - if( m_mode == Name ) - addPattern(); - return *this; - } - TestSpec testSpec() { - addFilter(); - return m_testSpec; - } - private: - void visitChar( char c ) { - if( m_mode == None ) { - switch( c ) { - case ' ': return; - case '~': m_exclusion = true; return; - case '[': return startNewMode( Tag, ++m_pos ); - case '"': return startNewMode( QuotedName, ++m_pos ); - case '\\': return escape(); - default: startNewMode( Name, m_pos ); break; - } - } - if( m_mode == Name ) { - if( c == ',' ) { - addPattern(); - addFilter(); - } - else if( c == '[' ) { - if( subString() == "exclude:" ) - m_exclusion = true; - else - addPattern(); - startNewMode( Tag, ++m_pos ); - } - else if( c == '\\' ) - escape(); - } - else if( m_mode == EscapedName ) - m_mode = Name; - else if( m_mode == QuotedName && c == '"' ) - addPattern(); - else if( m_mode == Tag && c == ']' ) - addPattern(); - } - void startNewMode( Mode mode, std::size_t start ) { - m_mode = mode; - m_start = start; - } - void escape() { - if( m_mode == None ) - m_start = m_pos; - m_mode = EscapedName; - m_escapeChars.push_back( m_pos ); - } - std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } - template - void addPattern() { - std::string token = subString(); - for( size_t i = 0; i < m_escapeChars.size(); ++i ) - token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); - m_escapeChars.clear(); - if( startsWith( token, "exclude:" ) ) { - m_exclusion = true; - token = token.substr( 8 ); - } - if( !token.empty() ) { - Ptr pattern = new T( token ); - if( m_exclusion ) - pattern = new TestSpec::ExcludedPattern( pattern ); - m_currentFilter.m_patterns.push_back( pattern ); - } - m_exclusion = false; - m_mode = None; - } - void addFilter() { - if( !m_currentFilter.m_patterns.empty() ) { - m_testSpec.m_filters.push_back( m_currentFilter ); - m_currentFilter = TestSpec::Filter(); - } - } - }; - inline TestSpec parseTestSpec( std::string const& arg ) { - return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); - } - -} // namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -// #included from: catch_interfaces_config.h -#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED - -#include -#include -#include - -namespace Catch { - - struct Verbosity { enum Level { - NoOutput = 0, - Quiet, - Normal - }; }; - - struct WarnAbout { enum What { - Nothing = 0x00, - NoAssertions = 0x01 - }; }; - - struct ShowDurations { enum OrNot { - DefaultForReporter, - Always, - Never - }; }; - struct RunTests { enum InWhatOrder { - InDeclarationOrder, - InLexicographicalOrder, - InRandomOrder - }; }; - struct UseColour { enum YesOrNo { - Auto, - Yes, - No - }; }; - - class TestSpec; - - struct IConfig : IShared { - - virtual ~IConfig(); - - virtual bool allowThrows() const = 0; - virtual std::ostream& stream() const = 0; - virtual std::string name() const = 0; - virtual bool includeSuccessfulResults() const = 0; - virtual bool shouldDebugBreak() const = 0; - virtual bool warnAboutMissingAssertions() const = 0; - virtual int abortAfter() const = 0; - virtual bool showInvisibles() const = 0; - virtual ShowDurations::OrNot showDurations() const = 0; - virtual TestSpec const& testSpec() const = 0; - virtual RunTests::InWhatOrder runOrder() const = 0; - virtual unsigned int rngSeed() const = 0; - virtual UseColour::YesOrNo useColour() const = 0; - virtual std::vector const& getSectionsToRun() const = 0; - - }; -} - -// #included from: catch_stream.h -#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED - -// #included from: catch_streambuf.h -#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED - -#include - -namespace Catch { - - class StreamBufBase : public std::streambuf { - public: - virtual ~StreamBufBase() CATCH_NOEXCEPT; - }; -} - -#include -#include -#include -#include - -namespace Catch { - - std::ostream& cout(); - std::ostream& cerr(); - std::ostream& clog(); - - struct IStream { - virtual ~IStream() CATCH_NOEXCEPT; - virtual std::ostream& stream() const = 0; - }; - - class FileStream : public IStream { - mutable std::ofstream m_ofs; - public: - FileStream( std::string const& filename ); - virtual ~FileStream() CATCH_NOEXCEPT; - public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; - }; - - class CoutStream : public IStream { - mutable std::ostream m_os; - public: - CoutStream(); - virtual ~CoutStream() CATCH_NOEXCEPT; - - public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; - }; - - class DebugOutStream : public IStream { - CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf; - mutable std::ostream m_os; - public: - DebugOutStream(); - virtual ~DebugOutStream() CATCH_NOEXCEPT; - - public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; - }; -} - -#include -#include -#include -#include - -#ifndef CATCH_CONFIG_CONSOLE_WIDTH -#define CATCH_CONFIG_CONSOLE_WIDTH 80 -#endif - -namespace Catch { - - struct ConfigData { - - ConfigData() - : listTests( false ), - listTags( false ), - listReporters( false ), - listTestNamesOnly( false ), - listExtraInfo( false ), - showSuccessfulTests( false ), - shouldDebugBreak( false ), - noThrow( false ), - showHelp( false ), - showInvisibles( false ), - filenamesAsTags( false ), - abortAfter( -1 ), - rngSeed( 0 ), - verbosity( Verbosity::Normal ), - warnings( WarnAbout::Nothing ), - showDurations( ShowDurations::DefaultForReporter ), - runOrder( RunTests::InDeclarationOrder ), - useColour( UseColour::Auto ) - {} - - bool listTests; - bool listTags; - bool listReporters; - bool listTestNamesOnly; - bool listExtraInfo; - - bool showSuccessfulTests; - bool shouldDebugBreak; - bool noThrow; - bool showHelp; - bool showInvisibles; - bool filenamesAsTags; - - int abortAfter; - unsigned int rngSeed; - - Verbosity::Level verbosity; - WarnAbout::What warnings; - ShowDurations::OrNot showDurations; - RunTests::InWhatOrder runOrder; - UseColour::YesOrNo useColour; - - std::string outputFilename; - std::string name; - std::string processName; - - std::vector reporterNames; - std::vector testsOrTags; - std::vector sectionsToRun; - }; - - class Config : public SharedImpl { - private: - Config( Config const& other ); - Config& operator = ( Config const& other ); - virtual void dummy(); - public: - - Config() - {} - - Config( ConfigData const& data ) - : m_data( data ), - m_stream( openStream() ) - { - if( !data.testsOrTags.empty() ) { - TestSpecParser parser( ITagAliasRegistry::get() ); - for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) - parser.parse( data.testsOrTags[i] ); - m_testSpec = parser.testSpec(); - } - } - - virtual ~Config() {} - - std::string const& getFilename() const { - return m_data.outputFilename ; - } - - bool listTests() const { return m_data.listTests; } - bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } - bool listTags() const { return m_data.listTags; } - bool listReporters() const { return m_data.listReporters; } - bool listExtraInfo() const { return m_data.listExtraInfo; } - - std::string getProcessName() const { return m_data.processName; } - - std::vector const& getReporterNames() const { return m_data.reporterNames; } - std::vector const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; } - - virtual TestSpec const& testSpec() const CATCH_OVERRIDE { return m_testSpec; } - - bool showHelp() const { return m_data.showHelp; } - - // IConfig interface - virtual bool allowThrows() const CATCH_OVERRIDE { return !m_data.noThrow; } - virtual std::ostream& stream() const CATCH_OVERRIDE { return m_stream->stream(); } - virtual std::string name() const CATCH_OVERRIDE { return m_data.name.empty() ? m_data.processName : m_data.name; } - virtual bool includeSuccessfulResults() const CATCH_OVERRIDE { return m_data.showSuccessfulTests; } - virtual bool warnAboutMissingAssertions() const CATCH_OVERRIDE { return m_data.warnings & WarnAbout::NoAssertions; } - virtual ShowDurations::OrNot showDurations() const CATCH_OVERRIDE { return m_data.showDurations; } - virtual RunTests::InWhatOrder runOrder() const CATCH_OVERRIDE { return m_data.runOrder; } - virtual unsigned int rngSeed() const CATCH_OVERRIDE { return m_data.rngSeed; } - virtual UseColour::YesOrNo useColour() const CATCH_OVERRIDE { return m_data.useColour; } - virtual bool shouldDebugBreak() const CATCH_OVERRIDE { return m_data.shouldDebugBreak; } - virtual int abortAfter() const CATCH_OVERRIDE { return m_data.abortAfter; } - virtual bool showInvisibles() const CATCH_OVERRIDE { return m_data.showInvisibles; } - - private: - - IStream const* openStream() { - if( m_data.outputFilename.empty() ) - return new CoutStream(); - else if( m_data.outputFilename[0] == '%' ) { - if( m_data.outputFilename == "%debug" ) - return new DebugOutStream(); - else - throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); - } - else - return new FileStream( m_data.outputFilename ); - } - ConfigData m_data; - - CATCH_AUTO_PTR( IStream const ) m_stream; - TestSpec m_testSpec; - }; - -} // end namespace Catch - -// #included from: catch_clara.h -#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED - -// Use Catch's value for console width (store Clara's off to the side, if present) -#ifdef CLARA_CONFIG_CONSOLE_WIDTH -#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH -#undef CLARA_CONFIG_CONSOLE_WIDTH -#endif -#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - -// Declare Clara inside the Catch namespace -#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { -// #included from: ../external/clara.h - -// Version 0.0.2.4 - -// Only use header guard if we are not using an outer namespace -#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) - -#ifndef STITCH_CLARA_OPEN_NAMESPACE -#define TWOBLUECUBES_CLARA_H_INCLUDED -#define STITCH_CLARA_OPEN_NAMESPACE -#define STITCH_CLARA_CLOSE_NAMESPACE -#else -#define STITCH_CLARA_CLOSE_NAMESPACE } -#endif - -#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE - -// ----------- #included from tbc_text_format.h ----------- - -// Only use header guard if we are not using an outer namespace -#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) -#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -#define TBC_TEXT_FORMAT_H_INCLUDED -#endif - -#include -#include -#include -#include -#include - -// Use optional outer namespace -#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { -#endif - -namespace Tbc { - -#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH - const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - struct TextAttributes { - TextAttributes() - : initialIndent( std::string::npos ), - indent( 0 ), - width( consoleWidth-1 ), - tabChar( '\t' ) - {} - - TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } - TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } - TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } - TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } - - std::size_t initialIndent; // indent of first line, or npos - std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos - std::size_t width; // maximum width of text, including indent. Longer text will wrap - char tabChar; // If this char is seen the indent is changed to current pos - }; - - class Text { - public: - Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) - : attr( _attr ) - { - std::string wrappableChars = " [({.,/|\\-"; - std::size_t indent = _attr.initialIndent != std::string::npos - ? _attr.initialIndent - : _attr.indent; - std::string remainder = _str; - - while( !remainder.empty() ) { - if( lines.size() >= 1000 ) { - lines.push_back( "... message truncated due to excessive size" ); - return; - } - std::size_t tabPos = std::string::npos; - std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); - std::size_t pos = remainder.find_first_of( '\n' ); - if( pos <= width ) { - width = pos; - } - pos = remainder.find_last_of( _attr.tabChar, width ); - if( pos != std::string::npos ) { - tabPos = pos; - if( remainder[width] == '\n' ) - width--; - remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); - } - - if( width == remainder.size() ) { - spliceLine( indent, remainder, width ); - } - else if( remainder[width] == '\n' ) { - spliceLine( indent, remainder, width ); - if( width <= 1 || remainder.size() != 1 ) - remainder = remainder.substr( 1 ); - indent = _attr.indent; - } - else { - pos = remainder.find_last_of( wrappableChars, width ); - if( pos != std::string::npos && pos > 0 ) { - spliceLine( indent, remainder, pos ); - if( remainder[0] == ' ' ) - remainder = remainder.substr( 1 ); - } - else { - spliceLine( indent, remainder, width-1 ); - lines.back() += "-"; - } - if( lines.size() == 1 ) - indent = _attr.indent; - if( tabPos != std::string::npos ) - indent += tabPos; - } - } - } - - void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { - lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); - _remainder = _remainder.substr( _pos ); - } - - typedef std::vector::const_iterator const_iterator; - - const_iterator begin() const { return lines.begin(); } - const_iterator end() const { return lines.end(); } - std::string const& last() const { return lines.back(); } - std::size_t size() const { return lines.size(); } - std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } - std::string toString() const { - std::ostringstream oss; - oss << *this; - return oss.str(); - } - - friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { - for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); - it != itEnd; ++it ) { - if( it != _text.begin() ) - _stream << "\n"; - _stream << *it; - } - return _stream; - } - - private: - std::string str; - TextAttributes attr; - std::vector lines; - }; - -} // end namespace Tbc - -#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -} // end outer namespace -#endif - -#endif // TBC_TEXT_FORMAT_H_INCLUDED - -// ----------- end of #include from tbc_text_format.h ----------- -// ........... back in clara.h - -#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE - -// ----------- #included from clara_compilers.h ----------- - -#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED -#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED - -// Detect a number of compiler features - mostly C++11/14 conformance - by compiler -// The following features are defined: -// -// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? -// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? -// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods -// CLARA_CONFIG_CPP11_OVERRIDE : is override supported? -// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) - -// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? - -// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? - -// In general each macro has a _NO_ form -// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. -// Many features, at point of detection, define an _INTERNAL_ macro, so they -// can be combined, en-mass, with the _NO_ forms later. - -// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 - -#ifdef __clang__ - -#if __has_feature(cxx_nullptr) -#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR -#endif - -#if __has_feature(cxx_noexcept) -#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT -#endif - -#endif // __clang__ - -//////////////////////////////////////////////////////////////////////////////// -// GCC -#ifdef __GNUC__ - -#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) -#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR -#endif - -// - otherwise more recent versions define __cplusplus >= 201103L -// and will get picked up below - -#endif // __GNUC__ - -//////////////////////////////////////////////////////////////////////////////// -// Visual C++ -#ifdef _MSC_VER - -#if (_MSC_VER >= 1600) -#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR -#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -#endif - -#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) -#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT -#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#endif - -#endif // _MSC_VER - -//////////////////////////////////////////////////////////////////////////////// -// C++ language feature support - -// catch all support for C++11 -#if defined(__cplusplus) && __cplusplus >= 201103L - -#define CLARA_CPP11_OR_GREATER - -#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) -#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR -#endif - -#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT -#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT -#endif - -#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#endif - -#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) -#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE -#endif -#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) -#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -#endif - -#endif // __cplusplus >= 201103L - -// Now set the actual defines based on the above + anything the user has configured -#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_NULLPTR -#endif -#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_NOEXCEPT -#endif -#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_GENERATED_METHODS -#endif -#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_OVERRIDE -#endif -#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_UNIQUE_PTR -#endif - -// noexcept support: -#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) -#define CLARA_NOEXCEPT noexcept -# define CLARA_NOEXCEPT_IS(x) noexcept(x) -#else -#define CLARA_NOEXCEPT throw() -# define CLARA_NOEXCEPT_IS(x) -#endif - -// nullptr support -#ifdef CLARA_CONFIG_CPP11_NULLPTR -#define CLARA_NULL nullptr -#else -#define CLARA_NULL NULL -#endif - -// override support -#ifdef CLARA_CONFIG_CPP11_OVERRIDE -#define CLARA_OVERRIDE override -#else -#define CLARA_OVERRIDE -#endif - -// unique_ptr support -#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR -# define CLARA_AUTO_PTR( T ) std::unique_ptr -#else -# define CLARA_AUTO_PTR( T ) std::auto_ptr -#endif - -#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED - -// ----------- end of #include from clara_compilers.h ----------- -// ........... back in clara.h - -#include -#include -#include - -#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) -#define CLARA_PLATFORM_WINDOWS -#endif - -// Use optional outer namespace -#ifdef STITCH_CLARA_OPEN_NAMESPACE -STITCH_CLARA_OPEN_NAMESPACE -#endif - -namespace Clara { - - struct UnpositionalTag {}; - - extern UnpositionalTag _; - -#ifdef CLARA_CONFIG_MAIN - UnpositionalTag _; -#endif - - namespace Detail { - -#ifdef CLARA_CONSOLE_WIDTH - const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - using namespace Tbc; - - inline bool startsWith( std::string const& str, std::string const& prefix ) { - return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; - } - - template struct RemoveConstRef{ typedef T type; }; - template struct RemoveConstRef{ typedef T type; }; - template struct RemoveConstRef{ typedef T type; }; - template struct RemoveConstRef{ typedef T type; }; - - template struct IsBool { static const bool value = false; }; - template<> struct IsBool { static const bool value = true; }; - - template - void convertInto( std::string const& _source, T& _dest ) { - std::stringstream ss; - ss << _source; - ss >> _dest; - if( ss.fail() ) - throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); - } - inline void convertInto( std::string const& _source, std::string& _dest ) { - _dest = _source; - } - char toLowerCh(char c) { - return static_cast( std::tolower( c ) ); - } - inline void convertInto( std::string const& _source, bool& _dest ) { - std::string sourceLC = _source; - std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh ); - if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) - _dest = true; - else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) - _dest = false; - else - throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); - } - - template - struct IArgFunction { - virtual ~IArgFunction() {} -#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS - IArgFunction() = default; - IArgFunction( IArgFunction const& ) = default; -#endif - virtual void set( ConfigT& config, std::string const& value ) const = 0; - virtual bool takesArg() const = 0; - virtual IArgFunction* clone() const = 0; - }; - - template - class BoundArgFunction { - public: - BoundArgFunction() : functionObj( CLARA_NULL ) {} - BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} - BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} - BoundArgFunction& operator = ( BoundArgFunction const& other ) { - IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; - delete functionObj; - functionObj = newFunctionObj; - return *this; - } - ~BoundArgFunction() { delete functionObj; } - - void set( ConfigT& config, std::string const& value ) const { - functionObj->set( config, value ); - } - bool takesArg() const { return functionObj->takesArg(); } - - bool isSet() const { - return functionObj != CLARA_NULL; - } - private: - IArgFunction* functionObj; - }; - - template - struct NullBinder : IArgFunction{ - virtual void set( C&, std::string const& ) const {} - virtual bool takesArg() const { return true; } - virtual IArgFunction* clone() const { return new NullBinder( *this ); } - }; - - template - struct BoundDataMember : IArgFunction{ - BoundDataMember( M C::* _member ) : member( _member ) {} - virtual void set( C& p, std::string const& stringValue ) const { - convertInto( stringValue, p.*member ); - } - virtual bool takesArg() const { return !IsBool::value; } - virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } - M C::* member; - }; - template - struct BoundUnaryMethod : IArgFunction{ - BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} - virtual void set( C& p, std::string const& stringValue ) const { - typename RemoveConstRef::type value; - convertInto( stringValue, value ); - (p.*member)( value ); - } - virtual bool takesArg() const { return !IsBool::value; } - virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } - void (C::*member)( M ); - }; - template - struct BoundNullaryMethod : IArgFunction{ - BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} - virtual void set( C& p, std::string const& stringValue ) const { - bool value; - convertInto( stringValue, value ); - if( value ) - (p.*member)(); - } - virtual bool takesArg() const { return false; } - virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } - void (C::*member)(); - }; - - template - struct BoundUnaryFunction : IArgFunction{ - BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} - virtual void set( C& obj, std::string const& stringValue ) const { - bool value; - convertInto( stringValue, value ); - if( value ) - function( obj ); - } - virtual bool takesArg() const { return false; } - virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } - void (*function)( C& ); - }; - - template - struct BoundBinaryFunction : IArgFunction{ - BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} - virtual void set( C& obj, std::string const& stringValue ) const { - typename RemoveConstRef::type value; - convertInto( stringValue, value ); - function( obj, value ); - } - virtual bool takesArg() const { return !IsBool::value; } - virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } - void (*function)( C&, T ); - }; - - } // namespace Detail - - inline std::vector argsToVector( int argc, char const* const* const argv ) { - std::vector args( static_cast( argc ) ); - for( std::size_t i = 0; i < static_cast( argc ); ++i ) - args[i] = argv[i]; - - return args; - } - - class Parser { - enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional }; - Mode mode; - std::size_t from; - bool inQuotes; - public: - - struct Token { - enum Type { Positional, ShortOpt, LongOpt }; - Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} - Type type; - std::string data; - }; - - Parser() : mode( None ), from( 0 ), inQuotes( false ){} - - void parseIntoTokens( std::vector const& args, std::vector& tokens ) { - const std::string doubleDash = "--"; - for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i ) - parseIntoTokens( args[i], tokens); - } - - void parseIntoTokens( std::string const& arg, std::vector& tokens ) { - for( std::size_t i = 0; i < arg.size(); ++i ) { - char c = arg[i]; - if( c == '"' ) - inQuotes = !inQuotes; - mode = handleMode( i, c, arg, tokens ); - } - mode = handleMode( arg.size(), '\0', arg, tokens ); - } - Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { - switch( mode ) { - case None: return handleNone( i, c ); - case MaybeShortOpt: return handleMaybeShortOpt( i, c ); - case ShortOpt: - case LongOpt: - case SlashOpt: return handleOpt( i, c, arg, tokens ); - case Positional: return handlePositional( i, c, arg, tokens ); - default: throw std::logic_error( "Unknown mode" ); - } - } - - Mode handleNone( std::size_t i, char c ) { - if( inQuotes ) { - from = i; - return Positional; - } - switch( c ) { - case '-': return MaybeShortOpt; -#ifdef CLARA_PLATFORM_WINDOWS - case '/': from = i+1; return SlashOpt; -#endif - default: from = i; return Positional; - } - } - Mode handleMaybeShortOpt( std::size_t i, char c ) { - switch( c ) { - case '-': from = i+1; return LongOpt; - default: from = i; return ShortOpt; - } - } - - Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { - if( std::string( ":=\0", 3 ).find( c ) == std::string::npos ) - return mode; - - std::string optName = arg.substr( from, i-from ); - if( mode == ShortOpt ) - for( std::size_t j = 0; j < optName.size(); ++j ) - tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) ); - else if( mode == SlashOpt && optName.size() == 1 ) - tokens.push_back( Token( Token::ShortOpt, optName ) ); - else - tokens.push_back( Token( Token::LongOpt, optName ) ); - return None; - } - Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { - if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos ) - return mode; - - std::string data = arg.substr( from, i-from ); - tokens.push_back( Token( Token::Positional, data ) ); - return None; - } - }; - - template - struct CommonArgProperties { - CommonArgProperties() {} - CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} - - Detail::BoundArgFunction boundField; - std::string description; - std::string detail; - std::string placeholder; // Only value if boundField takes an arg - - bool takesArg() const { - return !placeholder.empty(); - } - void validate() const { - if( !boundField.isSet() ) - throw std::logic_error( "option not bound" ); - } - }; - struct OptionArgProperties { - std::vector shortNames; - std::string longName; - - bool hasShortName( std::string const& shortName ) const { - return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); - } - bool hasLongName( std::string const& _longName ) const { - return _longName == longName; - } - }; - struct PositionalArgProperties { - PositionalArgProperties() : position( -1 ) {} - int position; // -1 means non-positional (floating) - - bool isFixedPositional() const { - return position != -1; - } - }; - - template - class CommandLine { - - struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { - Arg() {} - Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} - - using CommonArgProperties::placeholder; // !TBD - - std::string dbgName() const { - if( !longName.empty() ) - return "--" + longName; - if( !shortNames.empty() ) - return "-" + shortNames[0]; - return "positional args"; - } - std::string commands() const { - std::ostringstream oss; - bool first = true; - std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); - for(; it != itEnd; ++it ) { - if( first ) - first = false; - else - oss << ", "; - oss << "-" << *it; - } - if( !longName.empty() ) { - if( !first ) - oss << ", "; - oss << "--" << longName; - } - if( !placeholder.empty() ) - oss << " <" << placeholder << ">"; - return oss.str(); - } - }; - - typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; - - friend void addOptName( Arg& arg, std::string const& optName ) - { - if( optName.empty() ) - return; - if( Detail::startsWith( optName, "--" ) ) { - if( !arg.longName.empty() ) - throw std::logic_error( "Only one long opt may be specified. '" - + arg.longName - + "' already specified, now attempting to add '" - + optName + "'" ); - arg.longName = optName.substr( 2 ); - } - else if( Detail::startsWith( optName, "-" ) ) - arg.shortNames.push_back( optName.substr( 1 ) ); - else - throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); - } - friend void setPositionalArg( Arg& arg, int position ) - { - arg.position = position; - } - - class ArgBuilder { - public: - ArgBuilder( Arg* arg ) : m_arg( arg ) {} - - // Bind a non-boolean data member (requires placeholder string) - template - void bind( M C::* field, std::string const& placeholder ) { - m_arg->boundField = new Detail::BoundDataMember( field ); - m_arg->placeholder = placeholder; - } - // Bind a boolean data member (no placeholder required) - template - void bind( bool C::* field ) { - m_arg->boundField = new Detail::BoundDataMember( field ); - } - - // Bind a method taking a single, non-boolean argument (requires a placeholder string) - template - void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { - m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); - m_arg->placeholder = placeholder; - } - - // Bind a method taking a single, boolean argument (no placeholder string required) - template - void bind( void (C::* unaryMethod)( bool ) ) { - m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); - } - - // Bind a method that takes no arguments (will be called if opt is present) - template - void bind( void (C::* nullaryMethod)() ) { - m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); - } - - // Bind a free function taking a single argument - the object to operate on (no placeholder string required) - template - void bind( void (* unaryFunction)( C& ) ) { - m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); - } - - // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) - template - void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { - m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); - m_arg->placeholder = placeholder; - } - - ArgBuilder& describe( std::string const& description ) { - m_arg->description = description; - return *this; - } - ArgBuilder& detail( std::string const& detail ) { - m_arg->detail = detail; - return *this; - } - - protected: - Arg* m_arg; - }; - - class OptBuilder : public ArgBuilder { - public: - OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} - OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} - - OptBuilder& operator[]( std::string const& optName ) { - addOptName( *ArgBuilder::m_arg, optName ); - return *this; - } - }; - - public: - - CommandLine() - : m_boundProcessName( new Detail::NullBinder() ), - m_highestSpecifiedArgPosition( 0 ), - m_throwOnUnrecognisedTokens( false ) - {} - CommandLine( CommandLine const& other ) - : m_boundProcessName( other.m_boundProcessName ), - m_options ( other.m_options ), - m_positionalArgs( other.m_positionalArgs ), - m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), - m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) - { - if( other.m_floatingArg.get() ) - m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); - } - - CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { - m_throwOnUnrecognisedTokens = shouldThrow; - return *this; - } - - OptBuilder operator[]( std::string const& optName ) { - m_options.push_back( Arg() ); - addOptName( m_options.back(), optName ); - OptBuilder builder( &m_options.back() ); - return builder; - } - - ArgBuilder operator[]( int position ) { - m_positionalArgs.insert( std::make_pair( position, Arg() ) ); - if( position > m_highestSpecifiedArgPosition ) - m_highestSpecifiedArgPosition = position; - setPositionalArg( m_positionalArgs[position], position ); - ArgBuilder builder( &m_positionalArgs[position] ); - return builder; - } - - // Invoke this with the _ instance - ArgBuilder operator[]( UnpositionalTag ) { - if( m_floatingArg.get() ) - throw std::logic_error( "Only one unpositional argument can be added" ); - m_floatingArg.reset( new Arg() ); - ArgBuilder builder( m_floatingArg.get() ); - return builder; - } - - template - void bindProcessName( M C::* field ) { - m_boundProcessName = new Detail::BoundDataMember( field ); - } - template - void bindProcessName( void (C::*_unaryMethod)( M ) ) { - m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); - } - - void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { - typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; - std::size_t maxWidth = 0; - for( it = itBegin; it != itEnd; ++it ) - maxWidth = (std::max)( maxWidth, it->commands().size() ); - - for( it = itBegin; it != itEnd; ++it ) { - Detail::Text usage( it->commands(), Detail::TextAttributes() - .setWidth( maxWidth+indent ) - .setIndent( indent ) ); - Detail::Text desc( it->description, Detail::TextAttributes() - .setWidth( width - maxWidth - 3 ) ); - - for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { - std::string usageCol = i < usage.size() ? usage[i] : ""; - os << usageCol; - - if( i < desc.size() && !desc[i].empty() ) - os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) - << desc[i]; - os << "\n"; - } - } - } - std::string optUsage() const { - std::ostringstream oss; - optUsage( oss ); - return oss.str(); - } - - void argSynopsis( std::ostream& os ) const { - for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { - if( i > 1 ) - os << " "; - typename std::map::const_iterator it = m_positionalArgs.find( i ); - if( it != m_positionalArgs.end() ) - os << "<" << it->second.placeholder << ">"; - else if( m_floatingArg.get() ) - os << "<" << m_floatingArg->placeholder << ">"; - else - throw std::logic_error( "non consecutive positional arguments with no floating args" ); - } - // !TBD No indication of mandatory args - if( m_floatingArg.get() ) { - if( m_highestSpecifiedArgPosition > 1 ) - os << " "; - os << "[<" << m_floatingArg->placeholder << "> ...]"; - } - } - std::string argSynopsis() const { - std::ostringstream oss; - argSynopsis( oss ); - return oss.str(); - } - - void usage( std::ostream& os, std::string const& procName ) const { - validate(); - os << "usage:\n " << procName << " "; - argSynopsis( os ); - if( !m_options.empty() ) { - os << " [options]\n\nwhere options are: \n"; - optUsage( os, 2 ); - } - os << "\n"; - } - std::string usage( std::string const& procName ) const { - std::ostringstream oss; - usage( oss, procName ); - return oss.str(); - } - - ConfigT parse( std::vector const& args ) const { - ConfigT config; - parseInto( args, config ); - return config; - } - - std::vector parseInto( std::vector const& args, ConfigT& config ) const { - std::string processName = args.empty() ? std::string() : args[0]; - std::size_t lastSlash = processName.find_last_of( "/\\" ); - if( lastSlash != std::string::npos ) - processName = processName.substr( lastSlash+1 ); - m_boundProcessName.set( config, processName ); - std::vector tokens; - Parser parser; - parser.parseIntoTokens( args, tokens ); - return populate( tokens, config ); - } - - std::vector populate( std::vector const& tokens, ConfigT& config ) const { - validate(); - std::vector unusedTokens = populateOptions( tokens, config ); - unusedTokens = populateFixedArgs( unusedTokens, config ); - unusedTokens = populateFloatingArgs( unusedTokens, config ); - return unusedTokens; - } - - std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { - std::vector unusedTokens; - std::vector errors; - for( std::size_t i = 0; i < tokens.size(); ++i ) { - Parser::Token const& token = tokens[i]; - typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); - for(; it != itEnd; ++it ) { - Arg const& arg = *it; - - try { - if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || - ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { - if( arg.takesArg() ) { - if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) - errors.push_back( "Expected argument to option: " + token.data ); - else - arg.boundField.set( config, tokens[++i].data ); - } - else { - arg.boundField.set( config, "true" ); - } - break; - } - } - catch( std::exception& ex ) { - errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); - } - } - if( it == itEnd ) { - if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) - unusedTokens.push_back( token ); - else if( errors.empty() && m_throwOnUnrecognisedTokens ) - errors.push_back( "unrecognised option: " + token.data ); - } - } - if( !errors.empty() ) { - std::ostringstream oss; - for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); - it != itEnd; - ++it ) { - if( it != errors.begin() ) - oss << "\n"; - oss << *it; - } - throw std::runtime_error( oss.str() ); - } - return unusedTokens; - } - std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { - std::vector unusedTokens; - int position = 1; - for( std::size_t i = 0; i < tokens.size(); ++i ) { - Parser::Token const& token = tokens[i]; - typename std::map::const_iterator it = m_positionalArgs.find( position ); - if( it != m_positionalArgs.end() ) - it->second.boundField.set( config, token.data ); - else - unusedTokens.push_back( token ); - if( token.type == Parser::Token::Positional ) - position++; - } - return unusedTokens; - } - std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { - if( !m_floatingArg.get() ) - return tokens; - std::vector unusedTokens; - for( std::size_t i = 0; i < tokens.size(); ++i ) { - Parser::Token const& token = tokens[i]; - if( token.type == Parser::Token::Positional ) - m_floatingArg->boundField.set( config, token.data ); - else - unusedTokens.push_back( token ); - } - return unusedTokens; - } - - void validate() const - { - if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) - throw std::logic_error( "No options or arguments specified" ); - - for( typename std::vector::const_iterator it = m_options.begin(), - itEnd = m_options.end(); - it != itEnd; ++it ) - it->validate(); - } - - private: - Detail::BoundArgFunction m_boundProcessName; - std::vector m_options; - std::map m_positionalArgs; - ArgAutoPtr m_floatingArg; - int m_highestSpecifiedArgPosition; - bool m_throwOnUnrecognisedTokens; - }; - -} // end namespace Clara - -STITCH_CLARA_CLOSE_NAMESPACE -#undef STITCH_CLARA_OPEN_NAMESPACE -#undef STITCH_CLARA_CLOSE_NAMESPACE - -#endif // TWOBLUECUBES_CLARA_H_INCLUDED -#undef STITCH_CLARA_OPEN_NAMESPACE - -// Restore Clara's value for console width, if present -#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#endif - -#include -#include - -namespace Catch { - - inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } - inline void abortAfterX( ConfigData& config, int x ) { - if( x < 1 ) - throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); - config.abortAfter = x; - } - inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } - inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); } - inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } - - inline void addWarning( ConfigData& config, std::string const& _warning ) { - if( _warning == "NoAssertions" ) - config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); - else - throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' ); - } - inline void setOrder( ConfigData& config, std::string const& order ) { - if( startsWith( "declared", order ) ) - config.runOrder = RunTests::InDeclarationOrder; - else if( startsWith( "lexical", order ) ) - config.runOrder = RunTests::InLexicographicalOrder; - else if( startsWith( "random", order ) ) - config.runOrder = RunTests::InRandomOrder; - else - throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' ); - } - inline void setRngSeed( ConfigData& config, std::string const& seed ) { - if( seed == "time" ) { - config.rngSeed = static_cast( std::time(0) ); - } - else { - std::stringstream ss; - ss << seed; - ss >> config.rngSeed; - if( ss.fail() ) - throw std::runtime_error( "Argument to --rng-seed should be the word 'time' or a number" ); - } - } - inline void setVerbosity( ConfigData& config, int level ) { - // !TBD: accept strings? - config.verbosity = static_cast( level ); - } - inline void setShowDurations( ConfigData& config, bool _showDurations ) { - config.showDurations = _showDurations - ? ShowDurations::Always - : ShowDurations::Never; - } - inline void setUseColour( ConfigData& config, std::string const& value ) { - std::string mode = toLower( value ); - - if( mode == "yes" ) - config.useColour = UseColour::Yes; - else if( mode == "no" ) - config.useColour = UseColour::No; - else if( mode == "auto" ) - config.useColour = UseColour::Auto; - else - throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); - } - inline void forceColour( ConfigData& config ) { - config.useColour = UseColour::Yes; - } - inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { - std::ifstream f( _filename.c_str() ); - if( !f.is_open() ) - throw std::domain_error( "Unable to load input file: " + _filename ); - - std::string line; - while( std::getline( f, line ) ) { - line = trim(line); - if( !line.empty() && !startsWith( line, '#' ) ) { - if( !startsWith( line, '"' ) ) - line = '"' + line + '"'; - addTestOrTags( config, line + ',' ); - } - } - } - - inline Clara::CommandLine makeCommandLineParser() { - - using namespace Clara; - CommandLine cli; - - cli.bindProcessName( &ConfigData::processName ); - - cli["-?"]["-h"]["--help"] - .describe( "display usage information" ) - .bind( &ConfigData::showHelp ); - - cli["-l"]["--list-tests"] - .describe( "list all/matching test cases" ) - .bind( &ConfigData::listTests ); - - cli["-t"]["--list-tags"] - .describe( "list all/matching tags" ) - .bind( &ConfigData::listTags ); - - cli["-s"]["--success"] - .describe( "include successful tests in output" ) - .bind( &ConfigData::showSuccessfulTests ); - - cli["-b"]["--break"] - .describe( "break into debugger on failure" ) - .bind( &ConfigData::shouldDebugBreak ); - - cli["-e"]["--nothrow"] - .describe( "skip exception tests" ) - .bind( &ConfigData::noThrow ); - - cli["-i"]["--invisibles"] - .describe( "show invisibles (tabs, newlines)" ) - .bind( &ConfigData::showInvisibles ); - - cli["-o"]["--out"] - .describe( "output filename" ) - .bind( &ConfigData::outputFilename, "filename" ); - - cli["-r"]["--reporter"] -// .placeholder( "name[:filename]" ) - .describe( "reporter to use (defaults to console)" ) - .bind( &addReporterName, "name" ); - - cli["-n"]["--name"] - .describe( "suite name" ) - .bind( &ConfigData::name, "name" ); - - cli["-a"]["--abort"] - .describe( "abort at first failure" ) - .bind( &abortAfterFirst ); - - cli["-x"]["--abortx"] - .describe( "abort after x failures" ) - .bind( &abortAfterX, "no. failures" ); - - cli["-w"]["--warn"] - .describe( "enable warnings" ) - .bind( &addWarning, "warning name" ); - -// - needs updating if reinstated -// cli.into( &setVerbosity ) -// .describe( "level of verbosity (0=no output)" ) -// .shortOpt( "v") -// .longOpt( "verbosity" ) -// .placeholder( "level" ); - - cli[_] - .describe( "which test or tests to use" ) - .bind( &addTestOrTags, "test name, pattern or tags" ); - - cli["-d"]["--durations"] - .describe( "show test durations" ) - .bind( &setShowDurations, "yes|no" ); - - cli["-f"]["--input-file"] - .describe( "load test names to run from a file" ) - .bind( &loadTestNamesFromFile, "filename" ); - - cli["-#"]["--filenames-as-tags"] - .describe( "adds a tag for the filename" ) - .bind( &ConfigData::filenamesAsTags ); - - cli["-c"]["--section"] - .describe( "specify section to run" ) - .bind( &addSectionToRun, "section name" ); - - // Less common commands which don't have a short form - cli["--list-test-names-only"] - .describe( "list all/matching test cases names only" ) - .bind( &ConfigData::listTestNamesOnly ); - - cli["--list-extra-info"] - .describe( "list all/matching test cases with more info" ) - .bind( &ConfigData::listExtraInfo ); - - cli["--list-reporters"] - .describe( "list all reporters" ) - .bind( &ConfigData::listReporters ); - - cli["--order"] - .describe( "test case order (defaults to decl)" ) - .bind( &setOrder, "decl|lex|rand" ); - - cli["--rng-seed"] - .describe( "set a specific seed for random numbers" ) - .bind( &setRngSeed, "'time'|number" ); - - cli["--force-colour"] - .describe( "force colourised output (deprecated)" ) - .bind( &forceColour ); - - cli["--use-colour"] - .describe( "should output be colourised" ) - .bind( &setUseColour, "yes|no" ); - - return cli; - } - -} // end namespace Catch - -// #included from: internal/catch_list.hpp -#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED - -// #included from: catch_text.h -#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED - -#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - -#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch -// #included from: ../external/tbc_text_format.h -// Only use header guard if we are not using an outer namespace -#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED -# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -# endif -# else -# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED -# endif -#endif -#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -#include -#include -#include - -// Use optional outer namespace -#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { -#endif - -namespace Tbc { - -#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH - const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - struct TextAttributes { - TextAttributes() - : initialIndent( std::string::npos ), - indent( 0 ), - width( consoleWidth-1 ) - {} - - TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } - TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } - TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } - - std::size_t initialIndent; // indent of first line, or npos - std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos - std::size_t width; // maximum width of text, including indent. Longer text will wrap - }; - - class Text { - public: - Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) - : attr( _attr ) - { - const std::string wrappableBeforeChars = "[({<\t"; - const std::string wrappableAfterChars = "])}>-,./|\\"; - const std::string wrappableInsteadOfChars = " \n\r"; - std::string indent = _attr.initialIndent != std::string::npos - ? std::string( _attr.initialIndent, ' ' ) - : std::string( _attr.indent, ' ' ); - - typedef std::string::const_iterator iterator; - iterator it = _str.begin(); - const iterator strEnd = _str.end(); - - while( it != strEnd ) { - - if( lines.size() >= 1000 ) { - lines.push_back( "... message truncated due to excessive size" ); - return; - } - - std::string suffix; - std::size_t width = (std::min)( static_cast( strEnd-it ), _attr.width-static_cast( indent.size() ) ); - iterator itEnd = it+width; - iterator itNext = _str.end(); - - iterator itNewLine = std::find( it, itEnd, '\n' ); - if( itNewLine != itEnd ) - itEnd = itNewLine; - - if( itEnd != strEnd ) { - bool foundWrapPoint = false; - iterator findIt = itEnd; - do { - if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) { - itEnd = findIt+1; - itNext = findIt+1; - foundWrapPoint = true; - } - else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) { - itEnd = findIt; - itNext = findIt; - foundWrapPoint = true; - } - else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) { - itNext = findIt+1; - itEnd = findIt; - foundWrapPoint = true; - } - if( findIt == it ) - break; - else - --findIt; - } - while( !foundWrapPoint ); - - if( !foundWrapPoint ) { - // No good wrap char, so we'll break mid word and add a hyphen - --itEnd; - itNext = itEnd; - suffix = "-"; - } - else { - while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos ) - --itEnd; - } - } - lines.push_back( indent + std::string( it, itEnd ) + suffix ); - - if( indent.size() != _attr.indent ) - indent = std::string( _attr.indent, ' ' ); - it = itNext; - } - } - - typedef std::vector::const_iterator const_iterator; - - const_iterator begin() const { return lines.begin(); } - const_iterator end() const { return lines.end(); } - std::string const& last() const { return lines.back(); } - std::size_t size() const { return lines.size(); } - std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } - std::string toString() const { - std::ostringstream oss; - oss << *this; - return oss.str(); - } - - inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { - for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); - it != itEnd; ++it ) { - if( it != _text.begin() ) - _stream << "\n"; - _stream << *it; - } - return _stream; - } - - private: - std::string str; - TextAttributes attr; - std::vector lines; - }; - -} // end namespace Tbc - -#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -} // end outer namespace -#endif - -#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE - -namespace Catch { - using Tbc::Text; - using Tbc::TextAttributes; -} - -// #included from: catch_console_colour.hpp -#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED - -namespace Catch { - - struct Colour { - enum Code { - None = 0, - - White, - Red, - Green, - Blue, - Cyan, - Yellow, - Grey, - - Bright = 0x10, - - BrightRed = Bright | Red, - BrightGreen = Bright | Green, - LightGrey = Bright | Grey, - BrightWhite = Bright | White, - - // By intention - FileName = LightGrey, - Warning = Yellow, - ResultError = BrightRed, - ResultSuccess = BrightGreen, - ResultExpectedFailure = Warning, - - Error = BrightRed, - Success = Green, - - OriginalExpression = Cyan, - ReconstructedExpression = Yellow, - - SecondaryText = LightGrey, - Headers = White - }; - - // Use constructed object for RAII guard - Colour( Code _colourCode ); - Colour( Colour const& other ); - ~Colour(); - - // Use static method for one-shot changes - static void use( Code _colourCode ); - - private: - bool m_moved; - }; - - inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } - -} // end namespace Catch - -// #included from: catch_interfaces_reporter.h -#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED - -#include -#include -#include - -namespace Catch -{ - struct ReporterConfig { - explicit ReporterConfig( Ptr const& _fullConfig ) - : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} - - ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) - : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} - - std::ostream& stream() const { return *m_stream; } - Ptr fullConfig() const { return m_fullConfig; } - - private: - std::ostream* m_stream; - Ptr m_fullConfig; - }; - - struct ReporterPreferences { - ReporterPreferences() - : shouldRedirectStdOut( false ) - {} - - bool shouldRedirectStdOut; - }; - - template - struct LazyStat : Option { - LazyStat() : used( false ) {} - LazyStat& operator=( T const& _value ) { - Option::operator=( _value ); - used = false; - return *this; - } - void reset() { - Option::reset(); - used = false; - } - bool used; - }; - - struct TestRunInfo { - TestRunInfo( std::string const& _name ) : name( _name ) {} - std::string name; - }; - struct GroupInfo { - GroupInfo( std::string const& _name, - std::size_t _groupIndex, - std::size_t _groupsCount ) - : name( _name ), - groupIndex( _groupIndex ), - groupsCounts( _groupsCount ) - {} - - std::string name; - std::size_t groupIndex; - std::size_t groupsCounts; - }; - - struct AssertionStats { - AssertionStats( AssertionResult const& _assertionResult, - std::vector const& _infoMessages, - Totals const& _totals ) - : assertionResult( _assertionResult ), - infoMessages( _infoMessages ), - totals( _totals ) - { - if( assertionResult.hasMessage() ) { - // Copy message into messages list. - // !TBD This should have been done earlier, somewhere - MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); - builder << assertionResult.getMessage(); - builder.m_info.message = builder.m_stream.str(); - - infoMessages.push_back( builder.m_info ); - } - } - virtual ~AssertionStats(); - -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - AssertionStats( AssertionStats const& ) = default; - AssertionStats( AssertionStats && ) = default; - AssertionStats& operator = ( AssertionStats const& ) = default; - AssertionStats& operator = ( AssertionStats && ) = default; -# endif - - AssertionResult assertionResult; - std::vector infoMessages; - Totals totals; - }; - - struct SectionStats { - SectionStats( SectionInfo const& _sectionInfo, - Counts const& _assertions, - double _durationInSeconds, - bool _missingAssertions ) - : sectionInfo( _sectionInfo ), - assertions( _assertions ), - durationInSeconds( _durationInSeconds ), - missingAssertions( _missingAssertions ) - {} - virtual ~SectionStats(); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - SectionStats( SectionStats const& ) = default; - SectionStats( SectionStats && ) = default; - SectionStats& operator = ( SectionStats const& ) = default; - SectionStats& operator = ( SectionStats && ) = default; -# endif - - SectionInfo sectionInfo; - Counts assertions; - double durationInSeconds; - bool missingAssertions; - }; - - struct TestCaseStats { - TestCaseStats( TestCaseInfo const& _testInfo, - Totals const& _totals, - std::string const& _stdOut, - std::string const& _stdErr, - bool _aborting ) - : testInfo( _testInfo ), - totals( _totals ), - stdOut( _stdOut ), - stdErr( _stdErr ), - aborting( _aborting ) - {} - virtual ~TestCaseStats(); - -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - TestCaseStats( TestCaseStats const& ) = default; - TestCaseStats( TestCaseStats && ) = default; - TestCaseStats& operator = ( TestCaseStats const& ) = default; - TestCaseStats& operator = ( TestCaseStats && ) = default; -# endif - - TestCaseInfo testInfo; - Totals totals; - std::string stdOut; - std::string stdErr; - bool aborting; - }; - - struct TestGroupStats { - TestGroupStats( GroupInfo const& _groupInfo, - Totals const& _totals, - bool _aborting ) - : groupInfo( _groupInfo ), - totals( _totals ), - aborting( _aborting ) - {} - TestGroupStats( GroupInfo const& _groupInfo ) - : groupInfo( _groupInfo ), - aborting( false ) - {} - virtual ~TestGroupStats(); - -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - TestGroupStats( TestGroupStats const& ) = default; - TestGroupStats( TestGroupStats && ) = default; - TestGroupStats& operator = ( TestGroupStats const& ) = default; - TestGroupStats& operator = ( TestGroupStats && ) = default; -# endif - - GroupInfo groupInfo; - Totals totals; - bool aborting; - }; - - struct TestRunStats { - TestRunStats( TestRunInfo const& _runInfo, - Totals const& _totals, - bool _aborting ) - : runInfo( _runInfo ), - totals( _totals ), - aborting( _aborting ) - {} - virtual ~TestRunStats(); - -# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS - TestRunStats( TestRunStats const& _other ) - : runInfo( _other.runInfo ), - totals( _other.totals ), - aborting( _other.aborting ) - {} -# else - TestRunStats( TestRunStats const& ) = default; - TestRunStats( TestRunStats && ) = default; - TestRunStats& operator = ( TestRunStats const& ) = default; - TestRunStats& operator = ( TestRunStats && ) = default; -# endif - - TestRunInfo runInfo; - Totals totals; - bool aborting; - }; - - class MultipleReporters; - - struct IStreamingReporter : IShared { - virtual ~IStreamingReporter(); - - // Implementing class must also provide the following static method: - // static std::string getDescription(); - - virtual ReporterPreferences getPreferences() const = 0; - - virtual void noMatchingTestCases( std::string const& spec ) = 0; - - virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; - virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; - - virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; - virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; - - virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; - - // The return value indicates if the messages buffer should be cleared: - virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; - - virtual void sectionEnded( SectionStats const& sectionStats ) = 0; - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; - virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; - - virtual void skipTest( TestCaseInfo const& testInfo ) = 0; - - virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; } - }; - - struct IReporterFactory : IShared { - virtual ~IReporterFactory(); - virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; - virtual std::string getDescription() const = 0; - }; - - struct IReporterRegistry { - typedef std::map > FactoryMap; - typedef std::vector > Listeners; - - virtual ~IReporterRegistry(); - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; - virtual FactoryMap const& getFactories() const = 0; - virtual Listeners const& getListeners() const = 0; - }; - - Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); - -} - -#include -#include - -namespace Catch { - - inline std::size_t listTests( Config const& config ) { - - TestSpec testSpec = config.testSpec(); - if( config.testSpec().hasFilters() ) - Catch::cout() << "Matching test cases:\n"; - else { - Catch::cout() << "All available test cases:\n"; - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); - } - - std::size_t matchedTests = 0; - TextAttributes nameAttr, descAttr, tagsAttr; - nameAttr.setInitialIndent( 2 ).setIndent( 4 ); - descAttr.setIndent( 4 ); - tagsAttr.setIndent( 6 ); - - std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); - it != itEnd; - ++it ) { - matchedTests++; - TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); - Colour::Code colour = testCaseInfo.isHidden() - ? Colour::SecondaryText - : Colour::None; - Colour colourGuard( colour ); - - Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; - if( config.listExtraInfo() ) { - Catch::cout() << " " << testCaseInfo.lineInfo << std::endl; - std::string description = testCaseInfo.description; - if( description.empty() ) - description = "(NO DESCRIPTION)"; - Catch::cout() << Text( description, descAttr ) << std::endl; - } - if( !testCaseInfo.tags.empty() ) - Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; - } - - if( !config.testSpec().hasFilters() ) - Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl; - else - Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl; - return matchedTests; - } - - inline std::size_t listTestsNamesOnly( Config const& config ) { - TestSpec testSpec = config.testSpec(); - if( !config.testSpec().hasFilters() ) - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); - std::size_t matchedTests = 0; - std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); - it != itEnd; - ++it ) { - matchedTests++; - TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); - if( startsWith( testCaseInfo.name, '#' ) ) - Catch::cout() << '"' << testCaseInfo.name << '"'; - else - Catch::cout() << testCaseInfo.name; - if ( config.listExtraInfo() ) - Catch::cout() << "\t@" << testCaseInfo.lineInfo; - Catch::cout() << std::endl; - } - return matchedTests; - } - - struct TagInfo { - TagInfo() : count ( 0 ) {} - void add( std::string const& spelling ) { - ++count; - spellings.insert( spelling ); - } - std::string all() const { - std::string out; - for( std::set::const_iterator it = spellings.begin(), itEnd = spellings.end(); - it != itEnd; - ++it ) - out += "[" + *it + "]"; - return out; - } - std::set spellings; - std::size_t count; - }; - - inline std::size_t listTags( Config const& config ) { - TestSpec testSpec = config.testSpec(); - if( config.testSpec().hasFilters() ) - Catch::cout() << "Tags for matching test cases:\n"; - else { - Catch::cout() << "All available tags:\n"; - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); - } - - std::map tagCounts; - - std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); - it != itEnd; - ++it ) { - for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), - tagItEnd = it->getTestCaseInfo().tags.end(); - tagIt != tagItEnd; - ++tagIt ) { - std::string tagName = *tagIt; - std::string lcaseTagName = toLower( tagName ); - std::map::iterator countIt = tagCounts.find( lcaseTagName ); - if( countIt == tagCounts.end() ) - countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; - countIt->second.add( tagName ); - } - } - - for( std::map::const_iterator countIt = tagCounts.begin(), - countItEnd = tagCounts.end(); - countIt != countItEnd; - ++countIt ) { - std::ostringstream oss; - oss << " " << std::setw(2) << countIt->second.count << " "; - Text wrapper( countIt->second.all(), TextAttributes() - .setInitialIndent( 0 ) - .setIndent( oss.str().size() ) - .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); - Catch::cout() << oss.str() << wrapper << '\n'; - } - Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; - return tagCounts.size(); - } - - inline std::size_t listReporters( Config const& /*config*/ ) { - Catch::cout() << "Available reporters:\n"; - IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); - IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; - std::size_t maxNameLen = 0; - for(it = itBegin; it != itEnd; ++it ) - maxNameLen = (std::max)( maxNameLen, it->first.size() ); - - for(it = itBegin; it != itEnd; ++it ) { - Text wrapper( it->second->getDescription(), TextAttributes() - .setInitialIndent( 0 ) - .setIndent( 7+maxNameLen ) - .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); - Catch::cout() << " " - << it->first - << ':' - << std::string( maxNameLen - it->first.size() + 2, ' ' ) - << wrapper << '\n'; - } - Catch::cout() << std::endl; - return factories.size(); - } - - inline Option list( Config const& config ) { - Option listedCount; - if( config.listTests() || ( config.listExtraInfo() && !config.listTestNamesOnly() ) ) - listedCount = listedCount.valueOr(0) + listTests( config ); - if( config.listTestNamesOnly() ) - listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); - if( config.listTags() ) - listedCount = listedCount.valueOr(0) + listTags( config ); - if( config.listReporters() ) - listedCount = listedCount.valueOr(0) + listReporters( config ); - return listedCount; - } - -} // end namespace Catch - -// #included from: internal/catch_run_context.hpp -#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED - -// #included from: catch_test_case_tracker.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED - -#include -#include -#include -#include -#include - -CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS - -namespace Catch { -namespace TestCaseTracking { - - struct NameAndLocation { - std::string name; - SourceLineInfo location; - - NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) - : name( _name ), - location( _location ) - {} - }; - - struct ITracker : SharedImpl<> { - virtual ~ITracker(); - - // static queries - virtual NameAndLocation const& nameAndLocation() const = 0; - - // dynamic queries - virtual bool isComplete() const = 0; // Successfully completed or failed - virtual bool isSuccessfullyCompleted() const = 0; - virtual bool isOpen() const = 0; // Started but not complete - virtual bool hasChildren() const = 0; - - virtual ITracker& parent() = 0; - - // actions - virtual void close() = 0; // Successfully complete - virtual void fail() = 0; - virtual void markAsNeedingAnotherRun() = 0; - - virtual void addChild( Ptr const& child ) = 0; - virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0; - virtual void openChild() = 0; - - // Debug/ checking - virtual bool isSectionTracker() const = 0; - virtual bool isIndexTracker() const = 0; - }; - - class TrackerContext { - - enum RunState { - NotStarted, - Executing, - CompletedCycle - }; - - Ptr m_rootTracker; - ITracker* m_currentTracker; - RunState m_runState; - - public: - - static TrackerContext& instance() { - static TrackerContext s_instance; - return s_instance; - } - - TrackerContext() - : m_currentTracker( CATCH_NULL ), - m_runState( NotStarted ) - {} - - ITracker& startRun(); - - void endRun() { - m_rootTracker.reset(); - m_currentTracker = CATCH_NULL; - m_runState = NotStarted; - } - - void startCycle() { - m_currentTracker = m_rootTracker.get(); - m_runState = Executing; - } - void completeCycle() { - m_runState = CompletedCycle; - } - - bool completedCycle() const { - return m_runState == CompletedCycle; - } - ITracker& currentTracker() { - return *m_currentTracker; - } - void setCurrentTracker( ITracker* tracker ) { - m_currentTracker = tracker; - } - }; - - class TrackerBase : public ITracker { - protected: - enum CycleState { - NotStarted, - Executing, - ExecutingChildren, - NeedsAnotherRun, - CompletedSuccessfully, - Failed - }; - class TrackerHasName { - NameAndLocation m_nameAndLocation; - public: - TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {} - bool operator ()( Ptr const& tracker ) { - return - tracker->nameAndLocation().name == m_nameAndLocation.name && - tracker->nameAndLocation().location == m_nameAndLocation.location; - } - }; - typedef std::vector > Children; - NameAndLocation m_nameAndLocation; - TrackerContext& m_ctx; - ITracker* m_parent; - Children m_children; - CycleState m_runState; - public: - TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : m_nameAndLocation( nameAndLocation ), - m_ctx( ctx ), - m_parent( parent ), - m_runState( NotStarted ) - {} - virtual ~TrackerBase(); - - virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE { - return m_nameAndLocation; - } - virtual bool isComplete() const CATCH_OVERRIDE { - return m_runState == CompletedSuccessfully || m_runState == Failed; - } - virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { - return m_runState == CompletedSuccessfully; - } - virtual bool isOpen() const CATCH_OVERRIDE { - return m_runState != NotStarted && !isComplete(); - } - virtual bool hasChildren() const CATCH_OVERRIDE { - return !m_children.empty(); - } - - virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { - m_children.push_back( child ); - } - - virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE { - Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); - return( it != m_children.end() ) - ? it->get() - : CATCH_NULL; - } - virtual ITracker& parent() CATCH_OVERRIDE { - assert( m_parent ); // Should always be non-null except for root - return *m_parent; - } - - virtual void openChild() CATCH_OVERRIDE { - if( m_runState != ExecutingChildren ) { - m_runState = ExecutingChildren; - if( m_parent ) - m_parent->openChild(); - } - } - - virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } - virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } - - void open() { - m_runState = Executing; - moveToThis(); - if( m_parent ) - m_parent->openChild(); - } - - virtual void close() CATCH_OVERRIDE { - - // Close any still open children (e.g. generators) - while( &m_ctx.currentTracker() != this ) - m_ctx.currentTracker().close(); - - switch( m_runState ) { - case NotStarted: - case CompletedSuccessfully: - case Failed: - throw std::logic_error( "Illogical state" ); - - case NeedsAnotherRun: - break;; - - case Executing: - m_runState = CompletedSuccessfully; - break; - case ExecutingChildren: - if( m_children.empty() || m_children.back()->isComplete() ) - m_runState = CompletedSuccessfully; - break; - - default: - throw std::logic_error( "Unexpected state" ); - } - moveToParent(); - m_ctx.completeCycle(); - } - virtual void fail() CATCH_OVERRIDE { - m_runState = Failed; - if( m_parent ) - m_parent->markAsNeedingAnotherRun(); - moveToParent(); - m_ctx.completeCycle(); - } - virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { - m_runState = NeedsAnotherRun; - } - private: - void moveToParent() { - assert( m_parent ); - m_ctx.setCurrentTracker( m_parent ); - } - void moveToThis() { - m_ctx.setCurrentTracker( this ); - } - }; - - class SectionTracker : public TrackerBase { - std::vector m_filters; - public: - SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : TrackerBase( nameAndLocation, ctx, parent ) - { - if( parent ) { - while( !parent->isSectionTracker() ) - parent = &parent->parent(); - - SectionTracker& parentSection = static_cast( *parent ); - addNextFilters( parentSection.m_filters ); - } - } - virtual ~SectionTracker(); - - virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } - - static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { - SectionTracker* section = CATCH_NULL; - - ITracker& currentTracker = ctx.currentTracker(); - if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { - assert( childTracker ); - assert( childTracker->isSectionTracker() ); - section = static_cast( childTracker ); - } - else { - section = new SectionTracker( nameAndLocation, ctx, ¤tTracker ); - currentTracker.addChild( section ); - } - if( !ctx.completedCycle() ) - section->tryOpen(); - return *section; - } - - void tryOpen() { - if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) ) - open(); - } - - void addInitialFilters( std::vector const& filters ) { - if( !filters.empty() ) { - m_filters.push_back(""); // Root - should never be consulted - m_filters.push_back(""); // Test Case - not a section filter - m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); - } - } - void addNextFilters( std::vector const& filters ) { - if( filters.size() > 1 ) - m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); - } - }; - - class IndexTracker : public TrackerBase { - int m_size; - int m_index; - public: - IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) - : TrackerBase( nameAndLocation, ctx, parent ), - m_size( size ), - m_index( -1 ) - {} - virtual ~IndexTracker(); - - virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } - - static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { - IndexTracker* tracker = CATCH_NULL; - - ITracker& currentTracker = ctx.currentTracker(); - if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { - assert( childTracker ); - assert( childTracker->isIndexTracker() ); - tracker = static_cast( childTracker ); - } - else { - tracker = new IndexTracker( nameAndLocation, ctx, ¤tTracker, size ); - currentTracker.addChild( tracker ); - } - - if( !ctx.completedCycle() && !tracker->isComplete() ) { - if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) - tracker->moveNext(); - tracker->open(); - } - - return *tracker; - } - - int index() const { return m_index; } - - void moveNext() { - m_index++; - m_children.clear(); - } - - virtual void close() CATCH_OVERRIDE { - TrackerBase::close(); - if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) - m_runState = Executing; - } - }; - - inline ITracker& TrackerContext::startRun() { - m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL ); - m_currentTracker = CATCH_NULL; - m_runState = Executing; - return *m_rootTracker; - } - -} // namespace TestCaseTracking - -using TestCaseTracking::ITracker; -using TestCaseTracking::TrackerContext; -using TestCaseTracking::SectionTracker; -using TestCaseTracking::IndexTracker; - -} // namespace Catch - -CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS - -// #included from: catch_fatal_condition.hpp -#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED - -namespace Catch { - - // Report the error condition - inline void reportFatal( std::string const& message ) { - IContext& context = Catch::getCurrentContext(); - IResultCapture* resultCapture = context.getResultCapture(); - resultCapture->handleFatalErrorCondition( message ); - } - -} // namespace Catch - -#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// -// #included from: catch_windows_h_proxy.h - -#define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED - -#ifdef CATCH_DEFINES_NOMINMAX -# define NOMINMAX -#endif -#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -#endif - -#ifdef __AFXDLL -#include -#else -#include -#endif - -#ifdef CATCH_DEFINES_NOMINMAX -# undef NOMINMAX -#endif -#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN -# undef WIN32_LEAN_AND_MEAN -#endif - - -# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) - -namespace Catch { - struct FatalConditionHandler { - void reset() {} - }; -} - -# else // CATCH_CONFIG_WINDOWS_SEH is defined - -namespace Catch { - - struct SignalDefs { DWORD id; const char* name; }; - extern SignalDefs signalDefs[]; - // There is no 1-1 mapping between signals and windows exceptions. - // Windows can easily distinguish between SO and SigSegV, - // but SigInt, SigTerm, etc are handled differently. - SignalDefs signalDefs[] = { - { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, - { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, - { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, - { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" }, - }; - - struct FatalConditionHandler { - - static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { - for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { - if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { - reportFatal(signalDefs[i].name); - } - } - // If its not an exception we care about, pass it along. - // This stops us from eating debugger breaks etc. - return EXCEPTION_CONTINUE_SEARCH; - } - - FatalConditionHandler() { - isSet = true; - // 32k seems enough for Catch to handle stack overflow, - // but the value was found experimentally, so there is no strong guarantee - guaranteeSize = 32 * 1024; - exceptionHandlerHandle = CATCH_NULL; - // Register as first handler in current chain - exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); - // Pass in guarantee size to be filled - SetThreadStackGuarantee(&guaranteeSize); - } - - static void reset() { - if (isSet) { - // Unregister handler and restore the old guarantee - RemoveVectoredExceptionHandler(exceptionHandlerHandle); - SetThreadStackGuarantee(&guaranteeSize); - exceptionHandlerHandle = CATCH_NULL; - isSet = false; - } - } - - ~FatalConditionHandler() { - reset(); - } - private: - static bool isSet; - static ULONG guaranteeSize; - static PVOID exceptionHandlerHandle; - }; - - bool FatalConditionHandler::isSet = false; - ULONG FatalConditionHandler::guaranteeSize = 0; - PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL; - -} // namespace Catch - -# endif // CATCH_CONFIG_WINDOWS_SEH - -#else // Not Windows - assumed to be POSIX compatible ////////////////////////// - -# if !defined(CATCH_CONFIG_POSIX_SIGNALS) - -namespace Catch { - struct FatalConditionHandler { - void reset() {} - }; -} - -# else // CATCH_CONFIG_POSIX_SIGNALS is defined - -#include - -namespace Catch { - - struct SignalDefs { - int id; - const char* name; - }; - extern SignalDefs signalDefs[]; - SignalDefs signalDefs[] = { - { SIGINT, "SIGINT - Terminal interrupt signal" }, - { SIGILL, "SIGILL - Illegal instruction signal" }, - { SIGFPE, "SIGFPE - Floating point error signal" }, - { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, - { SIGTERM, "SIGTERM - Termination request signal" }, - { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } - }; - - struct FatalConditionHandler { - - static bool isSet; - static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)]; - static stack_t oldSigStack; - static char altStackMem[SIGSTKSZ]; - - static void handleSignal( int sig ) { - std::string name = ""; - for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { - SignalDefs &def = signalDefs[i]; - if (sig == def.id) { - name = def.name; - break; - } - } - reset(); - reportFatal(name); - raise( sig ); - } - - FatalConditionHandler() { - isSet = true; - stack_t sigStack; - sigStack.ss_sp = altStackMem; - sigStack.ss_size = SIGSTKSZ; - sigStack.ss_flags = 0; - sigaltstack(&sigStack, &oldSigStack); - struct sigaction sa = { 0 }; - - sa.sa_handler = handleSignal; - sa.sa_flags = SA_ONSTACK; - for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { - sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); - } - } - - ~FatalConditionHandler() { - reset(); - } - static void reset() { - if( isSet ) { - // Set signals back to previous values -- hopefully nobody overwrote them in the meantime - for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { - sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL); - } - // Return the old stack - sigaltstack(&oldSigStack, CATCH_NULL); - isSet = false; - } - } - }; - - bool FatalConditionHandler::isSet = false; - struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; - stack_t FatalConditionHandler::oldSigStack = {}; - char FatalConditionHandler::altStackMem[SIGSTKSZ] = {}; - -} // namespace Catch - -# endif // CATCH_CONFIG_POSIX_SIGNALS - -#endif // not Windows - -#include -#include - -namespace Catch { - - class StreamRedirect { - - public: - StreamRedirect( std::ostream& stream, std::string& targetString ) - : m_stream( stream ), - m_prevBuf( stream.rdbuf() ), - m_targetString( targetString ) - { - stream.rdbuf( m_oss.rdbuf() ); - } - - ~StreamRedirect() { - m_targetString += m_oss.str(); - m_stream.rdbuf( m_prevBuf ); - } - - private: - std::ostream& m_stream; - std::streambuf* m_prevBuf; - std::ostringstream m_oss; - std::string& m_targetString; - }; - - // StdErr has two constituent streams in C++, std::cerr and std::clog - // This means that we need to redirect 2 streams into 1 to keep proper - // order of writes and cannot use StreamRedirect on its own - class StdErrRedirect { - public: - StdErrRedirect(std::string& targetString) - :m_cerrBuf( cerr().rdbuf() ), m_clogBuf(clog().rdbuf()), - m_targetString(targetString){ - cerr().rdbuf(m_oss.rdbuf()); - clog().rdbuf(m_oss.rdbuf()); - } - ~StdErrRedirect() { - m_targetString += m_oss.str(); - cerr().rdbuf(m_cerrBuf); - clog().rdbuf(m_clogBuf); - } - private: - std::streambuf* m_cerrBuf; - std::streambuf* m_clogBuf; - std::ostringstream m_oss; - std::string& m_targetString; - }; - - /////////////////////////////////////////////////////////////////////////// - - class RunContext : public IResultCapture, public IRunner { - - RunContext( RunContext const& ); - void operator =( RunContext const& ); - - public: - - explicit RunContext( Ptr const& _config, Ptr const& reporter ) - : m_runInfo( _config->name() ), - m_context( getCurrentMutableContext() ), - m_activeTestCase( CATCH_NULL ), - m_config( _config ), - m_reporter( reporter ), - m_shouldReportUnexpected ( true ) - { - m_context.setRunner( this ); - m_context.setConfig( m_config ); - m_context.setResultCapture( this ); - m_reporter->testRunStarting( m_runInfo ); - } - - virtual ~RunContext() { - m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); - } - - void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { - m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); - } - void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { - m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); - } - - Totals runTest( TestCase const& testCase ) { - Totals prevTotals = m_totals; - - std::string redirectedCout; - std::string redirectedCerr; - - TestCaseInfo testInfo = testCase.getTestCaseInfo(); - - m_reporter->testCaseStarting( testInfo ); - - m_activeTestCase = &testCase; - - do { - ITracker& rootTracker = m_trackerContext.startRun(); - assert( rootTracker.isSectionTracker() ); - static_cast( rootTracker ).addInitialFilters( m_config->getSectionsToRun() ); - do { - m_trackerContext.startCycle(); - m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) ); - runCurrentTest( redirectedCout, redirectedCerr ); - } - while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); - } - // !TBD: deprecated - this will be replaced by indexed trackers - while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); - - Totals deltaTotals = m_totals.delta( prevTotals ); - if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) { - deltaTotals.assertions.failed++; - deltaTotals.testCases.passed--; - deltaTotals.testCases.failed++; - } - m_totals.testCases += deltaTotals.testCases; - m_reporter->testCaseEnded( TestCaseStats( testInfo, - deltaTotals, - redirectedCout, - redirectedCerr, - aborting() ) ); - - m_activeTestCase = CATCH_NULL; - m_testCaseTracker = CATCH_NULL; - - return deltaTotals; - } - - Ptr config() const { - return m_config; - } - - private: // IResultCapture - - virtual void assertionEnded( AssertionResult const& result ) { - if( result.getResultType() == ResultWas::Ok ) { - m_totals.assertions.passed++; - } - else if( !result.isOk() ) { - m_totals.assertions.failed++; - } - - // We have no use for the return value (whether messages should be cleared), because messages were made scoped - // and should be let to clear themselves out. - static_cast(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); - - // Reset working state - m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); - m_lastResult = result; - } - - virtual bool lastAssertionPassed() - { - return m_totals.assertions.passed == (m_prevPassed + 1); - } - - virtual void assertionPassed() - { - m_totals.assertions.passed++; - m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"; - m_lastAssertionInfo.macroName = ""; - } - - virtual void assertionRun() - { - m_prevPassed = m_totals.assertions.passed; - } - - virtual bool sectionStarted ( - SectionInfo const& sectionInfo, - Counts& assertions - ) - { - ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) ); - if( !sectionTracker.isOpen() ) - return false; - m_activeSections.push_back( §ionTracker ); - - m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; - - m_reporter->sectionStarting( sectionInfo ); - - assertions = m_totals.assertions; - - return true; - } - bool testForMissingAssertions( Counts& assertions ) { - if( assertions.total() != 0 ) - return false; - if( !m_config->warnAboutMissingAssertions() ) - return false; - if( m_trackerContext.currentTracker().hasChildren() ) - return false; - m_totals.assertions.failed++; - assertions.failed++; - return true; - } - - virtual void sectionEnded( SectionEndInfo const& endInfo ) { - Counts assertions = m_totals.assertions - endInfo.prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); - - if( !m_activeSections.empty() ) { - m_activeSections.back()->close(); - m_activeSections.pop_back(); - } - - m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); - m_messages.clear(); - } - - virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { - if( m_unfinishedSections.empty() ) - m_activeSections.back()->fail(); - else - m_activeSections.back()->close(); - m_activeSections.pop_back(); - - m_unfinishedSections.push_back( endInfo ); - } - - virtual void pushScopedMessage( MessageInfo const& message ) { - m_messages.push_back( message ); - } - - virtual void popScopedMessage( MessageInfo const& message ) { - m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); - } - - virtual std::string getCurrentTestName() const { - return m_activeTestCase - ? m_activeTestCase->getTestCaseInfo().name - : std::string(); - } - - virtual const AssertionResult* getLastResult() const { - return &m_lastResult; - } - - virtual void exceptionEarlyReported() { - m_shouldReportUnexpected = false; - } - - virtual void handleFatalErrorCondition( std::string const& message ) { - // Don't rebuild the result -- the stringification itself can cause more fatal errors - // Instead, fake a result data. - AssertionResultData tempResult; - tempResult.resultType = ResultWas::FatalErrorCondition; - tempResult.message = message; - AssertionResult result(m_lastAssertionInfo, tempResult); - - getResultCapture().assertionEnded(result); - - handleUnfinishedSections(); - - // Recreate section for test case (as we will lose the one that was in scope) - TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); - - Counts assertions; - assertions.failed = 1; - SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); - m_reporter->sectionEnded( testCaseSectionStats ); - - TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); - - Totals deltaTotals; - deltaTotals.testCases.failed = 1; - deltaTotals.assertions.failed = 1; - m_reporter->testCaseEnded( TestCaseStats( testInfo, - deltaTotals, - std::string(), - std::string(), - false ) ); - m_totals.testCases.failed++; - testGroupEnded( std::string(), m_totals, 1, 1 ); - m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); - } - - public: - // !TBD We need to do this another way! - bool aborting() const { - return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); - } - - private: - - void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { - TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); - m_reporter->sectionStarting( testCaseSection ); - Counts prevAssertions = m_totals.assertions; - double duration = 0; - m_shouldReportUnexpected = true; - try { - m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); - - seedRng( *m_config ); - - Timer timer; - timer.start(); - if( m_reporter->getPreferences().shouldRedirectStdOut ) { - StreamRedirect coutRedir( Catch::cout(), redirectedCout ); - StdErrRedirect errRedir( redirectedCerr ); - invokeActiveTestCase(); - } - else { - invokeActiveTestCase(); - } - duration = timer.getElapsedSeconds(); - } - catch( TestFailureException& ) { - // This just means the test was aborted due to failure - } - catch(...) { - // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions - // are reported without translation at the point of origin. - if (m_shouldReportUnexpected) { - makeUnexpectedResultBuilder().useActiveException(); - } - } - m_testCaseTracker->close(); - handleUnfinishedSections(); - m_messages.clear(); - - Counts assertions = m_totals.assertions - prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); - - if( testCaseInfo.okToFail() ) { - std::swap( assertions.failedButOk, assertions.failed ); - m_totals.assertions.failed -= assertions.failedButOk; - m_totals.assertions.failedButOk += assertions.failedButOk; - } - - SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); - m_reporter->sectionEnded( testCaseSectionStats ); - } - - void invokeActiveTestCase() { - FatalConditionHandler fatalConditionHandler; // Handle signals - m_activeTestCase->invoke(); - fatalConditionHandler.reset(); - } - - private: - - ResultBuilder makeUnexpectedResultBuilder() const { - return ResultBuilder( m_lastAssertionInfo.macroName, - m_lastAssertionInfo.lineInfo, - m_lastAssertionInfo.capturedExpression, - m_lastAssertionInfo.resultDisposition ); - } - - void handleUnfinishedSections() { - // If sections ended prematurely due to an exception we stored their - // infos here so we can tear them down outside the unwind process. - for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), - itEnd = m_unfinishedSections.rend(); - it != itEnd; - ++it ) - sectionEnded( *it ); - m_unfinishedSections.clear(); - } - - TestRunInfo m_runInfo; - IMutableContext& m_context; - TestCase const* m_activeTestCase; - ITracker* m_testCaseTracker; - ITracker* m_currentSectionTracker; - AssertionResult m_lastResult; - - Ptr m_config; - Totals m_totals; - Ptr m_reporter; - std::vector m_messages; - AssertionInfo m_lastAssertionInfo; - std::vector m_unfinishedSections; - std::vector m_activeSections; - TrackerContext m_trackerContext; - size_t m_prevPassed; - bool m_shouldReportUnexpected; - }; - - IResultCapture& getResultCapture() { - if( IResultCapture* capture = getCurrentContext().getResultCapture() ) - return *capture; - else - throw std::logic_error( "No result capture instance" ); - } - -} // end namespace Catch - -// #included from: internal/catch_version.h -#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED - -namespace Catch { - - // Versioning information - struct Version { - Version( unsigned int _majorVersion, - unsigned int _minorVersion, - unsigned int _patchNumber, - char const * const _branchName, - unsigned int _buildNumber ); - - unsigned int const majorVersion; - unsigned int const minorVersion; - unsigned int const patchNumber; - - // buildNumber is only used if branchName is not null - char const * const branchName; - unsigned int const buildNumber; - - friend std::ostream& operator << ( std::ostream& os, Version const& version ); - - private: - void operator=( Version const& ); - }; - - inline Version libraryVersion(); -} - -#include -#include -#include - -namespace Catch { - - Ptr createReporter( std::string const& reporterName, Ptr const& config ) { - Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); - if( !reporter ) { - std::ostringstream oss; - oss << "No reporter registered with name: '" << reporterName << "'"; - throw std::domain_error( oss.str() ); - } - return reporter; - } - -#if !defined(CATCH_CONFIG_DEFAULT_REPORTER) -#define CATCH_CONFIG_DEFAULT_REPORTER "console" -#endif - - Ptr makeReporter( Ptr const& config ) { - std::vector reporters = config->getReporterNames(); - if( reporters.empty() ) - reporters.push_back( CATCH_CONFIG_DEFAULT_REPORTER ); - - Ptr reporter; - for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); - it != itEnd; - ++it ) - reporter = addReporter( reporter, createReporter( *it, config ) ); - return reporter; - } - Ptr addListeners( Ptr const& config, Ptr reporters ) { - IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); - for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); - it != itEnd; - ++it ) - reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); - return reporters; - } - - Totals runTests( Ptr const& config ) { - - Ptr iconfig = config.get(); - - Ptr reporter = makeReporter( config ); - reporter = addListeners( iconfig, reporter ); - - RunContext context( iconfig, reporter ); - - Totals totals; - - context.testGroupStarting( config->name(), 1, 1 ); - - TestSpec testSpec = config->testSpec(); - if( !testSpec.hasFilters() ) - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests - - std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); - for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); - it != itEnd; - ++it ) { - if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) - totals += context.runTest( *it ); - else - reporter->skipTest( *it ); - } - - context.testGroupEnded( iconfig->name(), totals, 1, 1 ); - return totals; - } - - void applyFilenamesAsTags( IConfig const& config ) { - std::vector const& tests = getAllTestCasesSorted( config ); - for(std::size_t i = 0; i < tests.size(); ++i ) { - TestCase& test = const_cast( tests[i] ); - std::set tags = test.tags; - - std::string filename = test.lineInfo.file; - std::string::size_type lastSlash = filename.find_last_of( "\\/" ); - if( lastSlash != std::string::npos ) - filename = filename.substr( lastSlash+1 ); - - std::string::size_type lastDot = filename.find_last_of( '.' ); - if( lastDot != std::string::npos ) - filename = filename.substr( 0, lastDot ); - - tags.insert( '#' + filename ); - setTags( test, tags ); - } - } - - class Session : NonCopyable { - static bool alreadyInstantiated; - - public: - - struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; - - Session() - : m_cli( makeCommandLineParser() ) { - if( alreadyInstantiated ) { - std::string msg = "Only one instance of Catch::Session can ever be used"; - Catch::cerr() << msg << std::endl; - throw std::logic_error( msg ); - } - alreadyInstantiated = true; - } - ~Session() { - Catch::cleanUp(); - } - - void showHelp( std::string const& processName ) { - Catch::cout() << "\nCatch v" << libraryVersion() << "\n"; - - m_cli.usage( Catch::cout(), processName ); - Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; - } - - int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { - try { - m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); - m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData ); - if( m_configData.showHelp ) - showHelp( m_configData.processName ); - m_config.reset(); - } - catch( std::exception& ex ) { - { - Colour colourGuard( Colour::Red ); - Catch::cerr() - << "\nError(s) in input:\n" - << Text( ex.what(), TextAttributes().setIndent(2) ) - << "\n\n"; - } - m_cli.usage( Catch::cout(), m_configData.processName ); - return (std::numeric_limits::max)(); - } - return 0; - } - - void useConfigData( ConfigData const& _configData ) { - m_configData = _configData; - m_config.reset(); - } - - int run( int argc, char const* const* const argv ) { - - int returnCode = applyCommandLine( argc, argv ); - if( returnCode == 0 ) - returnCode = run(); - return returnCode; - } - - #if defined(WIN32) && defined(UNICODE) - int run( int argc, wchar_t const* const* const argv ) { - - char **utf8Argv = new char *[ argc ]; - - for ( int i = 0; i < argc; ++i ) { - int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); - - utf8Argv[ i ] = new char[ bufSize ]; - - WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); - } - - int returnCode = applyCommandLine( argc, utf8Argv ); - if( returnCode == 0 ) - returnCode = run(); - - for ( int i = 0; i < argc; ++i ) - delete [] utf8Argv[ i ]; - - delete [] utf8Argv; - - return returnCode; - } - #endif - - int run() { - if( m_configData.showHelp ) - return 0; - - try - { - config(); // Force config to be constructed - - seedRng( *m_config ); - - if( m_configData.filenamesAsTags ) - applyFilenamesAsTags( *m_config ); - - // Handle list request - if( Option listed = list( config() ) ) - return static_cast( *listed ); - - return static_cast( runTests( m_config ).assertions.failed ); - } - catch( std::exception& ex ) { - Catch::cerr() << ex.what() << std::endl; - return (std::numeric_limits::max)(); - } - } - - Clara::CommandLine const& cli() const { - return m_cli; - } - std::vector const& unusedTokens() const { - return m_unusedTokens; - } - ConfigData& configData() { - return m_configData; - } - Config& config() { - if( !m_config ) - m_config = new Config( m_configData ); - return *m_config; - } - private: - Clara::CommandLine m_cli; - std::vector m_unusedTokens; - ConfigData m_configData; - Ptr m_config; - }; - - bool Session::alreadyInstantiated = false; - -} // end namespace Catch - -// #included from: catch_registry_hub.hpp -#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED - -// #included from: catch_test_case_registry_impl.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED - -#include -#include -#include -#include - -namespace Catch { - - struct RandomNumberGenerator { - typedef std::ptrdiff_t result_type; - - result_type operator()( result_type n ) const { return std::rand() % n; } - -#ifdef CATCH_CONFIG_CPP11_SHUFFLE - static constexpr result_type min() { return 0; } - static constexpr result_type max() { return 1000000; } - result_type operator()() const { return std::rand() % max(); } -#endif - template - static void shuffle( V& vector ) { - RandomNumberGenerator rng; -#ifdef CATCH_CONFIG_CPP11_SHUFFLE - std::shuffle( vector.begin(), vector.end(), rng ); -#else - std::random_shuffle( vector.begin(), vector.end(), rng ); -#endif - } - }; - - inline std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { - - std::vector sorted = unsortedTestCases; - - switch( config.runOrder() ) { - case RunTests::InLexicographicalOrder: - std::sort( sorted.begin(), sorted.end() ); - break; - case RunTests::InRandomOrder: - { - seedRng( config ); - RandomNumberGenerator::shuffle( sorted ); - } - break; - case RunTests::InDeclarationOrder: - // already in declaration order - break; - } - return sorted; - } - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { - return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); - } - - void enforceNoDuplicateTestCases( std::vector const& functions ) { - std::set seenFunctions; - for( std::vector::const_iterator it = functions.begin(), itEnd = functions.end(); - it != itEnd; - ++it ) { - std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); - if( !prev.second ) { - std::ostringstream ss; - - ss << Colour( Colour::Red ) - << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n' - << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; - - throw std::runtime_error(ss.str()); - } - } - } - - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { - std::vector filtered; - filtered.reserve( testCases.size() ); - for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); - it != itEnd; - ++it ) - if( matchTest( *it, testSpec, config ) ) - filtered.push_back( *it ); - return filtered; - } - std::vector const& getAllTestCasesSorted( IConfig const& config ) { - return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); - } - - class TestRegistry : public ITestCaseRegistry { - public: - TestRegistry() - : m_currentSortOrder( RunTests::InDeclarationOrder ), - m_unnamedCount( 0 ) - {} - virtual ~TestRegistry(); - - virtual void registerTest( TestCase const& testCase ) { - std::string name = testCase.getTestCaseInfo().name; - if( name.empty() ) { - std::ostringstream oss; - oss << "Anonymous test case " << ++m_unnamedCount; - return registerTest( testCase.withName( oss.str() ) ); - } - m_functions.push_back( testCase ); - } - - virtual std::vector const& getAllTests() const { - return m_functions; - } - virtual std::vector const& getAllTestsSorted( IConfig const& config ) const { - if( m_sortedFunctions.empty() ) - enforceNoDuplicateTestCases( m_functions ); - - if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { - m_sortedFunctions = sortTests( config, m_functions ); - m_currentSortOrder = config.runOrder(); - } - return m_sortedFunctions; - } - - private: - std::vector m_functions; - mutable RunTests::InWhatOrder m_currentSortOrder; - mutable std::vector m_sortedFunctions; - size_t m_unnamedCount; - std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised - }; - - /////////////////////////////////////////////////////////////////////////// - - class FreeFunctionTestCase : public SharedImpl { - public: - - FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} - - virtual void invoke() const { - m_fun(); - } - - private: - virtual ~FreeFunctionTestCase(); - - TestFunction m_fun; - }; - - inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { - std::string className = classOrQualifiedMethodName; - if( startsWith( className, '&' ) ) - { - std::size_t lastColons = className.rfind( "::" ); - std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); - if( penultimateColons == std::string::npos ) - penultimateColons = 1; - className = className.substr( penultimateColons, lastColons-penultimateColons ); - } - return className; - } - - void registerTestCase - ( ITestCase* testCase, - char const* classOrQualifiedMethodName, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - - getMutableRegistryHub().registerTest - ( makeTestCase - ( testCase, - extractClassName( classOrQualifiedMethodName ), - nameAndDesc.name, - nameAndDesc.description, - lineInfo ) ); - } - void registerTestCaseFunction - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ) { - registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); - } - - /////////////////////////////////////////////////////////////////////////// - - AutoReg::AutoReg - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ) { - registerTestCaseFunction( function, lineInfo, nameAndDesc ); - } - - AutoReg::~AutoReg() {} - -} // end namespace Catch - -// #included from: catch_reporter_registry.hpp -#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED - -#include - -namespace Catch { - - class ReporterRegistry : public IReporterRegistry { - - public: - - virtual ~ReporterRegistry() CATCH_OVERRIDE {} - - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { - FactoryMap::const_iterator it = m_factories.find( name ); - if( it == m_factories.end() ) - return CATCH_NULL; - return it->second->create( ReporterConfig( config ) ); - } - - void registerReporter( std::string const& name, Ptr const& factory ) { - m_factories.insert( std::make_pair( name, factory ) ); - } - void registerListener( Ptr const& factory ) { - m_listeners.push_back( factory ); - } - - virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { - return m_factories; - } - virtual Listeners const& getListeners() const CATCH_OVERRIDE { - return m_listeners; - } - - private: - FactoryMap m_factories; - Listeners m_listeners; - }; -} - -// #included from: catch_exception_translator_registry.hpp -#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED - -#ifdef __OBJC__ -#import "Foundation/Foundation.h" -#endif - -namespace Catch { - - class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { - public: - ~ExceptionTranslatorRegistry() { - deleteAll( m_translators ); - } - - virtual void registerTranslator( const IExceptionTranslator* translator ) { - m_translators.push_back( translator ); - } - - virtual std::string translateActiveException() const { - try { -#ifdef __OBJC__ - // In Objective-C try objective-c exceptions first - @try { - return tryTranslators(); - } - @catch (NSException *exception) { - return Catch::toString( [exception description] ); - } -#else - return tryTranslators(); -#endif - } - catch( TestFailureException& ) { - throw; - } - catch( std::exception& ex ) { - return ex.what(); - } - catch( std::string& msg ) { - return msg; - } - catch( const char* msg ) { - return msg; - } - catch(...) { - return "Unknown exception"; - } - } - - std::string tryTranslators() const { - if( m_translators.empty() ) - throw; - else - return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); - } - - private: - std::vector m_translators; - }; -} - -// #included from: catch_tag_alias_registry.h -#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED - -#include - -namespace Catch { - - class TagAliasRegistry : public ITagAliasRegistry { - public: - virtual ~TagAliasRegistry(); - virtual Option find( std::string const& alias ) const; - virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; - void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); - - private: - std::map m_registry; - }; - -} // end namespace Catch - -namespace Catch { - - namespace { - - class RegistryHub : public IRegistryHub, public IMutableRegistryHub { - - RegistryHub( RegistryHub const& ); - void operator=( RegistryHub const& ); - - public: // IRegistryHub - RegistryHub() { - } - virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { - return m_reporterRegistry; - } - virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { - return m_testCaseRegistry; - } - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { - return m_exceptionTranslatorRegistry; - } - virtual ITagAliasRegistry const& getTagAliasRegistry() const CATCH_OVERRIDE { - return m_tagAliasRegistry; - } - - public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, Ptr const& factory ) CATCH_OVERRIDE { - m_reporterRegistry.registerReporter( name, factory ); - } - virtual void registerListener( Ptr const& factory ) CATCH_OVERRIDE { - m_reporterRegistry.registerListener( factory ); - } - virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { - m_testCaseRegistry.registerTest( testInfo ); - } - virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { - m_exceptionTranslatorRegistry.registerTranslator( translator ); - } - virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) CATCH_OVERRIDE { - m_tagAliasRegistry.add( alias, tag, lineInfo ); - } - - private: - TestRegistry m_testCaseRegistry; - ReporterRegistry m_reporterRegistry; - ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; - TagAliasRegistry m_tagAliasRegistry; - }; - - // Single, global, instance - inline RegistryHub*& getTheRegistryHub() { - static RegistryHub* theRegistryHub = CATCH_NULL; - if( !theRegistryHub ) - theRegistryHub = new RegistryHub(); - return theRegistryHub; - } - } - - IRegistryHub& getRegistryHub() { - return *getTheRegistryHub(); - } - IMutableRegistryHub& getMutableRegistryHub() { - return *getTheRegistryHub(); - } - void cleanUp() { - delete getTheRegistryHub(); - getTheRegistryHub() = CATCH_NULL; - cleanUpContext(); - } - std::string translateActiveException() { - return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); - } - -} // end namespace Catch - -// #included from: catch_notimplemented_exception.hpp -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED - -#include - -namespace Catch { - - NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) - : m_lineInfo( lineInfo ) { - std::ostringstream oss; - oss << lineInfo << ": function "; - oss << "not implemented"; - m_what = oss.str(); - } - - const char* NotImplementedException::what() const CATCH_NOEXCEPT { - return m_what.c_str(); - } - -} // end namespace Catch - -// #included from: catch_context_impl.hpp -#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED - -// #included from: catch_stream.hpp -#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED - -#include -#include -#include - -namespace Catch { - - template - class StreamBufImpl : public StreamBufBase { - char data[bufferSize]; - WriterF m_writer; - - public: - StreamBufImpl() { - setp( data, data + sizeof(data) ); - } - - ~StreamBufImpl() CATCH_NOEXCEPT { - sync(); - } - - private: - int overflow( int c ) { - sync(); - - if( c != EOF ) { - if( pbase() == epptr() ) - m_writer( std::string( 1, static_cast( c ) ) ); - else - sputc( static_cast( c ) ); - } - return 0; - } - - int sync() { - if( pbase() != pptr() ) { - m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); - setp( pbase(), epptr() ); - } - return 0; - } - }; - - /////////////////////////////////////////////////////////////////////////// - - FileStream::FileStream( std::string const& filename ) { - m_ofs.open( filename.c_str() ); - if( m_ofs.fail() ) { - std::ostringstream oss; - oss << "Unable to open file: '" << filename << '\''; - throw std::domain_error( oss.str() ); - } - } - - std::ostream& FileStream::stream() const { - return m_ofs; - } - - struct OutputDebugWriter { - - void operator()( std::string const&str ) { - writeToDebugConsole( str ); - } - }; - - DebugOutStream::DebugOutStream() - : m_streamBuf( new StreamBufImpl() ), - m_os( m_streamBuf.get() ) - {} - - std::ostream& DebugOutStream::stream() const { - return m_os; - } - - // Store the streambuf from cout up-front because - // cout may get redirected when running tests - CoutStream::CoutStream() - : m_os( Catch::cout().rdbuf() ) - {} - - std::ostream& CoutStream::stream() const { - return m_os; - } - -#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions - std::ostream& cout() { - return std::cout; - } - std::ostream& cerr() { - return std::cerr; - } - std::ostream& clog() { - return std::clog; - } -#endif -} - -namespace Catch { - - class Context : public IMutableContext { - - Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} - Context( Context const& ); - void operator=( Context const& ); - - public: - virtual ~Context() { - deleteAllValues( m_generatorsByTestName ); - } - - public: // IContext - virtual IResultCapture* getResultCapture() { - return m_resultCapture; - } - virtual IRunner* getRunner() { - return m_runner; - } - virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { - return getGeneratorsForCurrentTest() - .getGeneratorInfo( fileInfo, totalSize ) - .getCurrentIndex(); - } - virtual bool advanceGeneratorsForCurrentTest() { - IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); - return generators && generators->moveNext(); - } - - virtual Ptr getConfig() const { - return m_config; - } - - public: // IMutableContext - virtual void setResultCapture( IResultCapture* resultCapture ) { - m_resultCapture = resultCapture; - } - virtual void setRunner( IRunner* runner ) { - m_runner = runner; - } - virtual void setConfig( Ptr const& config ) { - m_config = config; - } - - friend IMutableContext& getCurrentMutableContext(); - - private: - IGeneratorsForTest* findGeneratorsForCurrentTest() { - std::string testName = getResultCapture()->getCurrentTestName(); - - std::map::const_iterator it = - m_generatorsByTestName.find( testName ); - return it != m_generatorsByTestName.end() - ? it->second - : CATCH_NULL; - } - - IGeneratorsForTest& getGeneratorsForCurrentTest() { - IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); - if( !generators ) { - std::string testName = getResultCapture()->getCurrentTestName(); - generators = createGeneratorsForTest(); - m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); - } - return *generators; - } - - private: - Ptr m_config; - IRunner* m_runner; - IResultCapture* m_resultCapture; - std::map m_generatorsByTestName; - }; - - namespace { - Context* currentContext = CATCH_NULL; - } - IMutableContext& getCurrentMutableContext() { - if( !currentContext ) - currentContext = new Context(); - return *currentContext; - } - IContext& getCurrentContext() { - return getCurrentMutableContext(); - } - - void cleanUpContext() { - delete currentContext; - currentContext = CATCH_NULL; - } -} - -// #included from: catch_console_colour_impl.hpp -#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED - -// #included from: catch_errno_guard.hpp -#define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED - -#include - -namespace Catch { - - class ErrnoGuard { - public: - ErrnoGuard():m_oldErrno(errno){} - ~ErrnoGuard() { errno = m_oldErrno; } - private: - int m_oldErrno; - }; - -} - -namespace Catch { - namespace { - - struct IColourImpl { - virtual ~IColourImpl() {} - virtual void use( Colour::Code _colourCode ) = 0; - }; - - struct NoColourImpl : IColourImpl { - void use( Colour::Code ) {} - - static IColourImpl* instance() { - static NoColourImpl s_instance; - return &s_instance; - } - }; - - } // anon namespace -} // namespace Catch - -#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) -# ifdef CATCH_PLATFORM_WINDOWS -# define CATCH_CONFIG_COLOUR_WINDOWS -# else -# define CATCH_CONFIG_COLOUR_ANSI -# endif -#endif - -#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// - -namespace Catch { -namespace { - - class Win32ColourImpl : public IColourImpl { - public: - Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) - { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); - originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); - originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); - } - - virtual void use( Colour::Code _colourCode ) { - switch( _colourCode ) { - case Colour::None: return setTextAttribute( originalForegroundAttributes ); - case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); - case Colour::Red: return setTextAttribute( FOREGROUND_RED ); - case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); - case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); - case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); - case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); - case Colour::Grey: return setTextAttribute( 0 ); - - case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); - case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); - case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); - case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); - - case Colour::Bright: throw std::logic_error( "not a colour" ); - } - } - - private: - void setTextAttribute( WORD _textAttribute ) { - SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); - } - HANDLE stdoutHandle; - WORD originalForegroundAttributes; - WORD originalBackgroundAttributes; - }; - - IColourImpl* platformColourInstance() { - static Win32ColourImpl s_instance; - - Ptr config = getCurrentContext().getConfig(); - UseColour::YesOrNo colourMode = config - ? config->useColour() - : UseColour::Auto; - if( colourMode == UseColour::Auto ) - colourMode = !isDebuggerActive() - ? UseColour::Yes - : UseColour::No; - return colourMode == UseColour::Yes - ? &s_instance - : NoColourImpl::instance(); - } - -} // end anon namespace -} // end namespace Catch - -#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// - -#include - -namespace Catch { -namespace { - - // use POSIX/ ANSI console terminal codes - // Thanks to Adam Strzelecki for original contribution - // (http://github.com/nanoant) - // https://github.com/philsquared/Catch/pull/131 - class PosixColourImpl : public IColourImpl { - public: - virtual void use( Colour::Code _colourCode ) { - switch( _colourCode ) { - case Colour::None: - case Colour::White: return setColour( "[0m" ); - case Colour::Red: return setColour( "[0;31m" ); - case Colour::Green: return setColour( "[0;32m" ); - case Colour::Blue: return setColour( "[0;34m" ); - case Colour::Cyan: return setColour( "[0;36m" ); - case Colour::Yellow: return setColour( "[0;33m" ); - case Colour::Grey: return setColour( "[1;30m" ); - - case Colour::LightGrey: return setColour( "[0;37m" ); - case Colour::BrightRed: return setColour( "[1;31m" ); - case Colour::BrightGreen: return setColour( "[1;32m" ); - case Colour::BrightWhite: return setColour( "[1;37m" ); - - case Colour::Bright: throw std::logic_error( "not a colour" ); - } - } - static IColourImpl* instance() { - static PosixColourImpl s_instance; - return &s_instance; - } - - private: - void setColour( const char* _escapeCode ) { - Catch::cout() << '\033' << _escapeCode; - } - }; - - IColourImpl* platformColourInstance() { - ErrnoGuard guard; - Ptr config = getCurrentContext().getConfig(); - UseColour::YesOrNo colourMode = config - ? config->useColour() - : UseColour::Auto; - if( colourMode == UseColour::Auto ) - colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) - ? UseColour::Yes - : UseColour::No; - return colourMode == UseColour::Yes - ? PosixColourImpl::instance() - : NoColourImpl::instance(); - } - -} // end anon namespace -} // end namespace Catch - -#else // not Windows or ANSI /////////////////////////////////////////////// - -namespace Catch { - - static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } - -} // end namespace Catch - -#endif // Windows/ ANSI/ None - -namespace Catch { - - Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } - Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } - Colour::~Colour(){ if( !m_moved ) use( None ); } - - void Colour::use( Code _colourCode ) { - static IColourImpl* impl = platformColourInstance(); - impl->use( _colourCode ); - } - -} // end namespace Catch - -// #included from: catch_generators_impl.hpp -#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED - -#include -#include -#include - -namespace Catch { - - struct GeneratorInfo : IGeneratorInfo { - - GeneratorInfo( std::size_t size ) - : m_size( size ), - m_currentIndex( 0 ) - {} - - bool moveNext() { - if( ++m_currentIndex == m_size ) { - m_currentIndex = 0; - return false; - } - return true; - } - - std::size_t getCurrentIndex() const { - return m_currentIndex; - } - - std::size_t m_size; - std::size_t m_currentIndex; - }; - - /////////////////////////////////////////////////////////////////////////// - - class GeneratorsForTest : public IGeneratorsForTest { - - public: - ~GeneratorsForTest() { - deleteAll( m_generatorsInOrder ); - } - - IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { - std::map::const_iterator it = m_generatorsByName.find( fileInfo ); - if( it == m_generatorsByName.end() ) { - IGeneratorInfo* info = new GeneratorInfo( size ); - m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); - m_generatorsInOrder.push_back( info ); - return *info; - } - return *it->second; - } - - bool moveNext() { - std::vector::const_iterator it = m_generatorsInOrder.begin(); - std::vector::const_iterator itEnd = m_generatorsInOrder.end(); - for(; it != itEnd; ++it ) { - if( (*it)->moveNext() ) - return true; - } - return false; - } - - private: - std::map m_generatorsByName; - std::vector m_generatorsInOrder; - }; - - IGeneratorsForTest* createGeneratorsForTest() - { - return new GeneratorsForTest(); - } - -} // end namespace Catch - -// #included from: catch_assertionresult.hpp -#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED - -namespace Catch { - - AssertionInfo::AssertionInfo():macroName(""), capturedExpression(""), resultDisposition(ResultDisposition::Normal), secondArg(""){} - - AssertionInfo::AssertionInfo( char const * _macroName, - SourceLineInfo const& _lineInfo, - char const * _capturedExpression, - ResultDisposition::Flags _resultDisposition, - char const * _secondArg) - : macroName( _macroName ), - lineInfo( _lineInfo ), - capturedExpression( _capturedExpression ), - resultDisposition( _resultDisposition ), - secondArg( _secondArg ) - {} - - AssertionResult::AssertionResult() {} - - AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) - : m_info( info ), - m_resultData( data ) - {} - - AssertionResult::~AssertionResult() {} - - // Result was a success - bool AssertionResult::succeeded() const { - return Catch::isOk( m_resultData.resultType ); - } - - // Result was a success, or failure is suppressed - bool AssertionResult::isOk() const { - return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); - } - - ResultWas::OfType AssertionResult::getResultType() const { - return m_resultData.resultType; - } - - bool AssertionResult::hasExpression() const { - return m_info.capturedExpression[0] != 0; - } - - bool AssertionResult::hasMessage() const { - return !m_resultData.message.empty(); - } - - std::string capturedExpressionWithSecondArgument( char const * capturedExpression, char const * secondArg ) { - return (secondArg[0] == 0 || secondArg[0] == '"' && secondArg[1] == '"') - ? capturedExpression - : std::string(capturedExpression) + ", " + secondArg; - } - - std::string AssertionResult::getExpression() const { - if( isFalseTest( m_info.resultDisposition ) ) - return '!' + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); - else - return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); - } - std::string AssertionResult::getExpressionInMacro() const { - if( m_info.macroName[0] == 0 ) - return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); - else - return std::string(m_info.macroName) + "( " + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + " )"; - } - - bool AssertionResult::hasExpandedExpression() const { - return hasExpression() && getExpandedExpression() != getExpression(); - } - - std::string AssertionResult::getExpandedExpression() const { - return m_resultData.reconstructExpression(); - } - - std::string AssertionResult::getMessage() const { - return m_resultData.message; - } - SourceLineInfo AssertionResult::getSourceInfo() const { - return m_info.lineInfo; - } - - std::string AssertionResult::getTestMacroName() const { - return m_info.macroName; - } - - void AssertionResult::discardDecomposedExpression() const { - m_resultData.decomposedExpression = CATCH_NULL; - } - - void AssertionResult::expandDecomposedExpression() const { - m_resultData.reconstructExpression(); - } - -} // end namespace Catch - -// #included from: catch_test_case_info.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED - -#include - -namespace Catch { - - inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { - if( startsWith( tag, '.' ) || - tag == "hide" || - tag == "!hide" ) - return TestCaseInfo::IsHidden; - else if( tag == "!throws" ) - return TestCaseInfo::Throws; - else if( tag == "!shouldfail" ) - return TestCaseInfo::ShouldFail; - else if( tag == "!mayfail" ) - return TestCaseInfo::MayFail; - else if( tag == "!nonportable" ) - return TestCaseInfo::NonPortable; - else - return TestCaseInfo::None; - } - inline bool isReservedTag( std::string const& tag ) { - return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] ); - } - inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { - if( isReservedTag( tag ) ) { - std::ostringstream ss; - ss << Colour(Colour::Red) - << "Tag name [" << tag << "] not allowed.\n" - << "Tag names starting with non alpha-numeric characters are reserved\n" - << Colour(Colour::FileName) - << _lineInfo << '\n'; - throw std::runtime_error(ss.str()); - } - } - - TestCase makeTestCase( ITestCase* _testCase, - std::string const& _className, - std::string const& _name, - std::string const& _descOrTags, - SourceLineInfo const& _lineInfo ) - { - bool isHidden( startsWith( _name, "./" ) ); // Legacy support - - // Parse out tags - std::set tags; - std::string desc, tag; - bool inTag = false; - for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { - char c = _descOrTags[i]; - if( !inTag ) { - if( c == '[' ) - inTag = true; - else - desc += c; - } - else { - if( c == ']' ) { - TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); - if( prop == TestCaseInfo::IsHidden ) - isHidden = true; - else if( prop == TestCaseInfo::None ) - enforceNotReservedTag( tag, _lineInfo ); - - tags.insert( tag ); - tag.clear(); - inTag = false; - } - else - tag += c; - } - } - if( isHidden ) { - tags.insert( "hide" ); - tags.insert( "." ); - } - - TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); - return TestCase( _testCase, info ); - } - - void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ) - { - testCaseInfo.tags = tags; - testCaseInfo.lcaseTags.clear(); - - std::ostringstream oss; - for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { - oss << '[' << *it << ']'; - std::string lcaseTag = toLower( *it ); - testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); - testCaseInfo.lcaseTags.insert( lcaseTag ); - } - testCaseInfo.tagsAsString = oss.str(); - } - - TestCaseInfo::TestCaseInfo( std::string const& _name, - std::string const& _className, - std::string const& _description, - std::set const& _tags, - SourceLineInfo const& _lineInfo ) - : name( _name ), - className( _className ), - description( _description ), - lineInfo( _lineInfo ), - properties( None ) - { - setTags( *this, _tags ); - } - - TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) - : name( other.name ), - className( other.className ), - description( other.description ), - tags( other.tags ), - lcaseTags( other.lcaseTags ), - tagsAsString( other.tagsAsString ), - lineInfo( other.lineInfo ), - properties( other.properties ) - {} - - bool TestCaseInfo::isHidden() const { - return ( properties & IsHidden ) != 0; - } - bool TestCaseInfo::throws() const { - return ( properties & Throws ) != 0; - } - bool TestCaseInfo::okToFail() const { - return ( properties & (ShouldFail | MayFail ) ) != 0; - } - bool TestCaseInfo::expectedToFail() const { - return ( properties & (ShouldFail ) ) != 0; - } - - TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} - - TestCase::TestCase( TestCase const& other ) - : TestCaseInfo( other ), - test( other.test ) - {} - - TestCase TestCase::withName( std::string const& _newName ) const { - TestCase other( *this ); - other.name = _newName; - return other; - } - - void TestCase::swap( TestCase& other ) { - test.swap( other.test ); - name.swap( other.name ); - className.swap( other.className ); - description.swap( other.description ); - tags.swap( other.tags ); - lcaseTags.swap( other.lcaseTags ); - tagsAsString.swap( other.tagsAsString ); - std::swap( TestCaseInfo::properties, static_cast( other ).properties ); - std::swap( lineInfo, other.lineInfo ); - } - - void TestCase::invoke() const { - test->invoke(); - } - - bool TestCase::operator == ( TestCase const& other ) const { - return test.get() == other.test.get() && - name == other.name && - className == other.className; - } - - bool TestCase::operator < ( TestCase const& other ) const { - return name < other.name; - } - TestCase& TestCase::operator = ( TestCase const& other ) { - TestCase temp( other ); - swap( temp ); - return *this; - } - - TestCaseInfo const& TestCase::getTestCaseInfo() const - { - return *this; - } - -} // end namespace Catch - -// #included from: catch_version.hpp -#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED - -namespace Catch { - - Version::Version - ( unsigned int _majorVersion, - unsigned int _minorVersion, - unsigned int _patchNumber, - char const * const _branchName, - unsigned int _buildNumber ) - : majorVersion( _majorVersion ), - minorVersion( _minorVersion ), - patchNumber( _patchNumber ), - branchName( _branchName ), - buildNumber( _buildNumber ) - {} - - std::ostream& operator << ( std::ostream& os, Version const& version ) { - os << version.majorVersion << '.' - << version.minorVersion << '.' - << version.patchNumber; - // branchName is never null -> 0th char is \0 if it is empty - if (version.branchName[0]) { - os << '-' << version.branchName - << '.' << version.buildNumber; - } - return os; - } - - inline Version libraryVersion() { - static Version version( 1, 9, 7, "", 0 ); - return version; - } - -} - -// #included from: catch_message.hpp -#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED - -namespace Catch { - - MessageInfo::MessageInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ) - : macroName( _macroName ), - lineInfo( _lineInfo ), - type( _type ), - sequence( ++globalCount ) - {} - - // This may need protecting if threading support is added - unsigned int MessageInfo::globalCount = 0; - - //////////////////////////////////////////////////////////////////////////// - - ScopedMessage::ScopedMessage( MessageBuilder const& builder ) - : m_info( builder.m_info ) - { - m_info.message = builder.m_stream.str(); - getResultCapture().pushScopedMessage( m_info ); - } - ScopedMessage::ScopedMessage( ScopedMessage const& other ) - : m_info( other.m_info ) - {} - - ScopedMessage::~ScopedMessage() { - if ( !std::uncaught_exception() ){ - getResultCapture().popScopedMessage(m_info); - } - } - -} // end namespace Catch - -// #included from: catch_legacy_reporter_adapter.hpp -#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED - -// #included from: catch_legacy_reporter_adapter.h -#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED - -namespace Catch -{ - // Deprecated - struct IReporter : IShared { - virtual ~IReporter(); - - virtual bool shouldRedirectStdout() const = 0; - - virtual void StartTesting() = 0; - virtual void EndTesting( Totals const& totals ) = 0; - virtual void StartGroup( std::string const& groupName ) = 0; - virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; - virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; - virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; - virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; - virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; - virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; - virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; - virtual void Aborted() = 0; - virtual void Result( AssertionResult const& result ) = 0; - }; - - class LegacyReporterAdapter : public SharedImpl - { - public: - LegacyReporterAdapter( Ptr const& legacyReporter ); - virtual ~LegacyReporterAdapter(); - - virtual ReporterPreferences getPreferences() const; - virtual void noMatchingTestCases( std::string const& ); - virtual void testRunStarting( TestRunInfo const& ); - virtual void testGroupStarting( GroupInfo const& groupInfo ); - virtual void testCaseStarting( TestCaseInfo const& testInfo ); - virtual void sectionStarting( SectionInfo const& sectionInfo ); - virtual void assertionStarting( AssertionInfo const& ); - virtual bool assertionEnded( AssertionStats const& assertionStats ); - virtual void sectionEnded( SectionStats const& sectionStats ); - virtual void testCaseEnded( TestCaseStats const& testCaseStats ); - virtual void testGroupEnded( TestGroupStats const& testGroupStats ); - virtual void testRunEnded( TestRunStats const& testRunStats ); - virtual void skipTest( TestCaseInfo const& ); - - private: - Ptr m_legacyReporter; - }; -} - -namespace Catch -{ - LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) - : m_legacyReporter( legacyReporter ) - {} - LegacyReporterAdapter::~LegacyReporterAdapter() {} - - ReporterPreferences LegacyReporterAdapter::getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); - return prefs; - } - - void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} - void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { - m_legacyReporter->StartTesting(); - } - void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { - m_legacyReporter->StartGroup( groupInfo.name ); - } - void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { - m_legacyReporter->StartTestCase( testInfo ); - } - void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { - m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); - } - void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { - // Not on legacy interface - } - - bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { - if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { - for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); - it != itEnd; - ++it ) { - if( it->type == ResultWas::Info ) { - ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); - rb << it->message; - rb.setResultType( ResultWas::Info ); - AssertionResult result = rb.build(); - m_legacyReporter->Result( result ); - } - } - } - m_legacyReporter->Result( assertionStats.assertionResult ); - return true; - } - void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { - if( sectionStats.missingAssertions ) - m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); - m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); - } - void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { - m_legacyReporter->EndTestCase - ( testCaseStats.testInfo, - testCaseStats.totals, - testCaseStats.stdOut, - testCaseStats.stdErr ); - } - void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { - if( testGroupStats.aborting ) - m_legacyReporter->Aborted(); - m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); - } - void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { - m_legacyReporter->EndTesting( testRunStats.totals ); - } - void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { - } -} - -// #included from: catch_timer.hpp - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++11-long-long" -#endif - -#ifdef CATCH_PLATFORM_WINDOWS - -#else - -#include - -#endif - -namespace Catch { - - namespace { -#ifdef CATCH_PLATFORM_WINDOWS - UInt64 getCurrentTicks() { - static UInt64 hz=0, hzo=0; - if (!hz) { - QueryPerformanceFrequency( reinterpret_cast( &hz ) ); - QueryPerformanceCounter( reinterpret_cast( &hzo ) ); - } - UInt64 t; - QueryPerformanceCounter( reinterpret_cast( &t ) ); - return ((t-hzo)*1000000)/hz; - } -#else - UInt64 getCurrentTicks() { - timeval t; - gettimeofday(&t,CATCH_NULL); - return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); - } -#endif - } - - void Timer::start() { - m_ticks = getCurrentTicks(); - } - unsigned int Timer::getElapsedMicroseconds() const { - return static_cast(getCurrentTicks() - m_ticks); - } - unsigned int Timer::getElapsedMilliseconds() const { - return static_cast(getElapsedMicroseconds()/1000); - } - double Timer::getElapsedSeconds() const { - return getElapsedMicroseconds()/1000000.0; - } - -} // namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif -// #included from: catch_common.hpp -#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED - -#include -#include - -namespace Catch { - - bool startsWith( std::string const& s, std::string const& prefix ) { - return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); - } - bool startsWith( std::string const& s, char prefix ) { - return !s.empty() && s[0] == prefix; - } - bool endsWith( std::string const& s, std::string const& suffix ) { - return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); - } - bool endsWith( std::string const& s, char suffix ) { - return !s.empty() && s[s.size()-1] == suffix; - } - bool contains( std::string const& s, std::string const& infix ) { - return s.find( infix ) != std::string::npos; - } - char toLowerCh(char c) { - return static_cast( std::tolower( c ) ); - } - void toLowerInPlace( std::string& s ) { - std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); - } - std::string toLower( std::string const& s ) { - std::string lc = s; - toLowerInPlace( lc ); - return lc; - } - std::string trim( std::string const& str ) { - static char const* whitespaceChars = "\n\r\t "; - std::string::size_type start = str.find_first_not_of( whitespaceChars ); - std::string::size_type end = str.find_last_not_of( whitespaceChars ); - - return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); - } - - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { - bool replaced = false; - std::size_t i = str.find( replaceThis ); - while( i != std::string::npos ) { - replaced = true; - str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); - if( i < str.size()-withThis.size() ) - i = str.find( replaceThis, i+withThis.size() ); - else - i = std::string::npos; - } - return replaced; - } - - pluralise::pluralise( std::size_t count, std::string const& label ) - : m_count( count ), - m_label( label ) - {} - - std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { - os << pluraliser.m_count << ' ' << pluraliser.m_label; - if( pluraliser.m_count != 1 ) - os << 's'; - return os; - } - - SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){} - SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) - : file( _file ), - line( _line ) - {} - bool SourceLineInfo::empty() const { - return file[0] == '\0'; - } - bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { - return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); - } - bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { - return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0)); - } - - void seedRng( IConfig const& config ) { - if( config.rngSeed() != 0 ) - std::srand( config.rngSeed() ); - } - unsigned int rngSeed() { - return getCurrentContext().getConfig()->rngSeed(); - } - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { -#ifndef __GNUG__ - os << info.file << '(' << info.line << ')'; -#else - os << info.file << ':' << info.line; -#endif - return os; - } - - void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { - std::ostringstream oss; - oss << locationInfo << ": Internal Catch error: '" << message << '\''; - if( alwaysTrue() ) - throw std::logic_error( oss.str() ); - } -} - -// #included from: catch_section.hpp -#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED - -namespace Catch { - - SectionInfo::SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name, - std::string const& _description ) - : name( _name ), - description( _description ), - lineInfo( _lineInfo ) - {} - - Section::Section( SectionInfo const& info ) - : m_info( info ), - m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) - { - m_timer.start(); - } - -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17 -#endif - Section::~Section() { - if( m_sectionIncluded ) { - SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); - if( std::uncaught_exception() ) - getResultCapture().sectionEndedEarly( endInfo ); - else - getResultCapture().sectionEnded( endInfo ); - } - } -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - - // This indicates whether the section should be executed or not - Section::operator bool() const { - return m_sectionIncluded; - } - -} // end namespace Catch - -// #included from: catch_debugger.hpp -#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED - -#ifdef CATCH_PLATFORM_MAC - - #include - #include - #include - #include - #include - - namespace Catch{ - - // The following function is taken directly from the following technical note: - // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html - - // Returns true if the current process is being debugged (either - // running under the debugger or has a debugger attached post facto). - bool isDebuggerActive(){ - - int mib[4]; - struct kinfo_proc info; - size_t size; - - // Initialize the flags so that, if sysctl fails for some bizarre - // reason, we get a predictable result. - - info.kp_proc.p_flag = 0; - - // Initialize mib, which tells sysctl the info we want, in this case - // we're looking for information about a specific process ID. - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - - // Call sysctl. - - size = sizeof(info); - if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { - Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; - return false; - } - - // We're being debugged if the P_TRACED flag is set. - - return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); - } - } // namespace Catch - -#elif defined(CATCH_PLATFORM_LINUX) - #include - #include - - namespace Catch{ - // The standard POSIX way of detecting a debugger is to attempt to - // ptrace() the process, but this needs to be done from a child and not - // this process itself to still allow attaching to this process later - // if wanted, so is rather heavy. Under Linux we have the PID of the - // "debugger" (which doesn't need to be gdb, of course, it could also - // be strace, for example) in /proc/$PID/status, so just get it from - // there instead. - bool isDebuggerActive(){ - // Libstdc++ has a bug, where std::ifstream sets errno to 0 - // This way our users can properly assert over errno values - ErrnoGuard guard; - std::ifstream in("/proc/self/status"); - for( std::string line; std::getline(in, line); ) { - static const int PREFIX_LEN = 11; - if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) { - // We're traced if the PID is not 0 and no other PID starts - // with 0 digit, so it's enough to check for just a single - // character. - return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; - } - } - - return false; - } - } // namespace Catch -#elif defined(_MSC_VER) - extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); - namespace Catch { - bool isDebuggerActive() { - return IsDebuggerPresent() != 0; - } - } -#elif defined(__MINGW32__) - extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); - namespace Catch { - bool isDebuggerActive() { - return IsDebuggerPresent() != 0; - } - } -#else - namespace Catch { - inline bool isDebuggerActive() { return false; } - } -#endif // Platform - -#ifdef CATCH_PLATFORM_WINDOWS - - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - ::OutputDebugStringA( text.c_str() ); - } - } -#else - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - // !TBD: Need a version for Mac/ XCode and other IDEs - Catch::cout() << text; - } - } -#endif // Platform - -// #included from: catch_tostring.hpp -#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED - -namespace Catch { - -namespace Detail { - - const std::string unprintableString = "{?}"; - - namespace { - const int hexThreshold = 255; - - struct Endianness { - enum Arch { Big, Little }; - - static Arch which() { - union _{ - int asInt; - char asChar[sizeof (int)]; - } u; - - u.asInt = 1; - return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; - } - }; - } - - std::string rawMemoryToString( const void *object, std::size_t size ) - { - // Reverse order for little endian architectures - int i = 0, end = static_cast( size ), inc = 1; - if( Endianness::which() == Endianness::Little ) { - i = end-1; - end = inc = -1; - } - - unsigned char const *bytes = static_cast(object); - std::ostringstream os; - os << "0x" << std::setfill('0') << std::hex; - for( ; i != end; i += inc ) - os << std::setw(2) << static_cast(bytes[i]); - return os.str(); - } -} - -std::string toString( std::string const& value ) { - std::string s = value; - if( getCurrentContext().getConfig()->showInvisibles() ) { - for(size_t i = 0; i < s.size(); ++i ) { - std::string subs; - switch( s[i] ) { - case '\n': subs = "\\n"; break; - case '\t': subs = "\\t"; break; - default: break; - } - if( !subs.empty() ) { - s = s.substr( 0, i ) + subs + s.substr( i+1 ); - ++i; - } - } - } - return '"' + s + '"'; -} -std::string toString( std::wstring const& value ) { - - std::string s; - s.reserve( value.size() ); - for(size_t i = 0; i < value.size(); ++i ) - s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; - return Catch::toString( s ); -} - -std::string toString( const char* const value ) { - return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); -} - -std::string toString( char* const value ) { - return Catch::toString( static_cast( value ) ); -} - -std::string toString( const wchar_t* const value ) -{ - return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); -} - -std::string toString( wchar_t* const value ) -{ - return Catch::toString( static_cast( value ) ); -} - -std::string toString( int value ) { - std::ostringstream oss; - oss << value; - if( value > Detail::hexThreshold ) - oss << " (0x" << std::hex << value << ')'; - return oss.str(); -} - -std::string toString( unsigned long value ) { - std::ostringstream oss; - oss << value; - if( value > Detail::hexThreshold ) - oss << " (0x" << std::hex << value << ')'; - return oss.str(); -} - -std::string toString( unsigned int value ) { - return Catch::toString( static_cast( value ) ); -} - -template -std::string fpToString( T value, int precision ) { - std::ostringstream oss; - oss << std::setprecision( precision ) - << std::fixed - << value; - std::string d = oss.str(); - std::size_t i = d.find_last_not_of( '0' ); - if( i != std::string::npos && i != d.size()-1 ) { - if( d[i] == '.' ) - i++; - d = d.substr( 0, i+1 ); - } - return d; -} - -std::string toString( const double value ) { - return fpToString( value, 10 ); -} -std::string toString( const float value ) { - return fpToString( value, 5 ) + 'f'; -} - -std::string toString( bool value ) { - return value ? "true" : "false"; -} - -std::string toString( char value ) { - if ( value == '\r' ) - return "'\\r'"; - if ( value == '\f' ) - return "'\\f'"; - if ( value == '\n' ) - return "'\\n'"; - if ( value == '\t' ) - return "'\\t'"; - if ( '\0' <= value && value < ' ' ) - return toString( static_cast( value ) ); - char chstr[] = "' '"; - chstr[1] = value; - return chstr; -} - -std::string toString( signed char value ) { - return toString( static_cast( value ) ); -} - -std::string toString( unsigned char value ) { - return toString( static_cast( value ) ); -} - -#ifdef CATCH_CONFIG_CPP11_LONG_LONG -std::string toString( long long value ) { - std::ostringstream oss; - oss << value; - if( value > Detail::hexThreshold ) - oss << " (0x" << std::hex << value << ')'; - return oss.str(); -} -std::string toString( unsigned long long value ) { - std::ostringstream oss; - oss << value; - if( value > Detail::hexThreshold ) - oss << " (0x" << std::hex << value << ')'; - return oss.str(); -} -#endif - -#ifdef CATCH_CONFIG_CPP11_NULLPTR -std::string toString( std::nullptr_t ) { - return "nullptr"; -} -#endif - -#ifdef __OBJC__ - std::string toString( NSString const * const& nsstring ) { - if( !nsstring ) - return "nil"; - return "@" + toString([nsstring UTF8String]); - } - std::string toString( NSString * CATCH_ARC_STRONG & nsstring ) { - if( !nsstring ) - return "nil"; - return "@" + toString([nsstring UTF8String]); - } - std::string toString( NSObject* const& nsObject ) { - return toString( [nsObject description] ); - } -#endif - -} // end namespace Catch - -// #included from: catch_result_builder.hpp -#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED - -namespace Catch { - - ResultBuilder::ResultBuilder( char const* macroName, - SourceLineInfo const& lineInfo, - char const* capturedExpression, - ResultDisposition::Flags resultDisposition, - char const* secondArg ) - : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition, secondArg ), - m_shouldDebugBreak( false ), - m_shouldThrow( false ), - m_guardException( false ), - m_usedStream( false ) - {} - - ResultBuilder::~ResultBuilder() { -#if defined(CATCH_CONFIG_FAST_COMPILE) - if ( m_guardException ) { - stream().oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; - captureResult( ResultWas::ThrewException ); - getCurrentContext().getResultCapture()->exceptionEarlyReported(); - } -#endif - } - - ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { - m_data.resultType = result; - return *this; - } - ResultBuilder& ResultBuilder::setResultType( bool result ) { - m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; - return *this; - } - - void ResultBuilder::endExpression( DecomposedExpression const& expr ) { - // Flip bool results if FalseTest flag is set - if( isFalseTest( m_assertionInfo.resultDisposition ) ) { - m_data.negate( expr.isBinaryExpression() ); - } - - getResultCapture().assertionRun(); - - if(getCurrentContext().getConfig()->includeSuccessfulResults() || m_data.resultType != ResultWas::Ok) - { - AssertionResult result = build( expr ); - handleResult( result ); - } - else - getResultCapture().assertionPassed(); - } - - void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { - m_assertionInfo.resultDisposition = resultDisposition; - stream().oss << Catch::translateActiveException(); - captureResult( ResultWas::ThrewException ); - } - - void ResultBuilder::captureResult( ResultWas::OfType resultType ) { - setResultType( resultType ); - captureExpression(); - } - - void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { - if( expectedMessage.empty() ) - captureExpectedException( Matchers::Impl::MatchAllOf() ); - else - captureExpectedException( Matchers::Equals( expectedMessage ) ); - } - - void ResultBuilder::captureExpectedException( Matchers::Impl::MatcherBase const& matcher ) { - - assert( !isFalseTest( m_assertionInfo.resultDisposition ) ); - AssertionResultData data = m_data; - data.resultType = ResultWas::Ok; - data.reconstructedExpression = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg); - - std::string actualMessage = Catch::translateActiveException(); - if( !matcher.match( actualMessage ) ) { - data.resultType = ResultWas::ExpressionFailed; - data.reconstructedExpression = actualMessage; - } - AssertionResult result( m_assertionInfo, data ); - handleResult( result ); - } - - void ResultBuilder::captureExpression() { - AssertionResult result = build(); - handleResult( result ); - } - - void ResultBuilder::handleResult( AssertionResult const& result ) - { - getResultCapture().assertionEnded( result ); - - if( !result.isOk() ) { - if( getCurrentContext().getConfig()->shouldDebugBreak() ) - m_shouldDebugBreak = true; - if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) - m_shouldThrow = true; - } - } - - void ResultBuilder::react() { -#if defined(CATCH_CONFIG_FAST_COMPILE) - if (m_shouldDebugBreak) { - /////////////////////////////////////////////////////////////////// - // To inspect the state during test, you need to go one level up the callstack - // To go back to the test and change execution, jump over the throw statement - /////////////////////////////////////////////////////////////////// - CATCH_BREAK_INTO_DEBUGGER(); - } -#endif - if( m_shouldThrow ) - throw Catch::TestFailureException(); - } - - bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } - bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } - - AssertionResult ResultBuilder::build() const - { - return build( *this ); - } - - // CAVEAT: The returned AssertionResult stores a pointer to the argument expr, - // a temporary DecomposedExpression, which in turn holds references to - // operands, possibly temporary as well. - // It should immediately be passed to handleResult; if the expression - // needs to be reported, its string expansion must be composed before - // the temporaries are destroyed. - AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const - { - assert( m_data.resultType != ResultWas::Unknown ); - AssertionResultData data = m_data; - - if(m_usedStream) - data.message = m_stream().oss.str(); - data.decomposedExpression = &expr; // for lazy reconstruction - return AssertionResult( m_assertionInfo, data ); - } - - void ResultBuilder::reconstructExpression( std::string& dest ) const { - dest = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg); - } - - void ResultBuilder::setExceptionGuard() { - m_guardException = true; - } - void ResultBuilder::unsetExceptionGuard() { - m_guardException = false; - } - -} // end namespace Catch - -// #included from: catch_tag_alias_registry.hpp -#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED - -namespace Catch { - - TagAliasRegistry::~TagAliasRegistry() {} - - Option TagAliasRegistry::find( std::string const& alias ) const { - std::map::const_iterator it = m_registry.find( alias ); - if( it != m_registry.end() ) - return it->second; - else - return Option(); - } - - std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { - std::string expandedTestSpec = unexpandedTestSpec; - for( std::map::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); - it != itEnd; - ++it ) { - std::size_t pos = expandedTestSpec.find( it->first ); - if( pos != std::string::npos ) { - expandedTestSpec = expandedTestSpec.substr( 0, pos ) + - it->second.tag + - expandedTestSpec.substr( pos + it->first.size() ); - } - } - return expandedTestSpec; - } - - void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { - - if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) { - std::ostringstream oss; - oss << Colour( Colour::Red ) - << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" - << Colour( Colour::FileName ) - << lineInfo << '\n'; - throw std::domain_error( oss.str().c_str() ); - } - if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { - std::ostringstream oss; - oss << Colour( Colour::Red ) - << "error: tag alias, \"" << alias << "\" already registered.\n" - << "\tFirst seen at " - << Colour( Colour::Red ) << find(alias)->lineInfo << '\n' - << Colour( Colour::Red ) << "\tRedefined at " - << Colour( Colour::FileName) << lineInfo << '\n'; - throw std::domain_error( oss.str().c_str() ); - } - } - - ITagAliasRegistry::~ITagAliasRegistry() {} - - ITagAliasRegistry const& ITagAliasRegistry::get() { - return getRegistryHub().getTagAliasRegistry(); - } - - RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { - getMutableRegistryHub().registerTagAlias( alias, tag, lineInfo ); - } - -} // end namespace Catch - -// #included from: catch_matchers_string.hpp - -namespace Catch { -namespace Matchers { - - namespace StdString { - - CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) - : m_caseSensitivity( caseSensitivity ), - m_str( adjustString( str ) ) - {} - std::string CasedString::adjustString( std::string const& str ) const { - return m_caseSensitivity == CaseSensitive::No - ? toLower( str ) - : str; - } - std::string CasedString::caseSensitivitySuffix() const { - return m_caseSensitivity == CaseSensitive::No - ? " (case insensitive)" - : std::string(); - } - - StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator ) - : m_comparator( comparator ), - m_operation( operation ) { - } - - std::string StringMatcherBase::describe() const { - std::string description; - description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + - m_comparator.caseSensitivitySuffix().size()); - description += m_operation; - description += ": \""; - description += m_comparator.m_str; - description += "\""; - description += m_comparator.caseSensitivitySuffix(); - return description; - } - - EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {} - - bool EqualsMatcher::match( std::string const& source ) const { - return m_comparator.adjustString( source ) == m_comparator.m_str; - } - - ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {} - - bool ContainsMatcher::match( std::string const& source ) const { - return contains( m_comparator.adjustString( source ), m_comparator.m_str ); - } - - StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {} - - bool StartsWithMatcher::match( std::string const& source ) const { - return startsWith( m_comparator.adjustString( source ), m_comparator.m_str ); - } - - EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {} - - bool EndsWithMatcher::match( std::string const& source ) const { - return endsWith( m_comparator.adjustString( source ), m_comparator.m_str ); - } - - } // namespace StdString - - StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) { - return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) ); - } - StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) { - return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) ); - } - StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { - return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) ); - } - StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { - return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) ); - } - -} // namespace Matchers -} // namespace Catch -// #included from: ../reporters/catch_reporter_multi.hpp -#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED - -namespace Catch { - -class MultipleReporters : public SharedImpl { - typedef std::vector > Reporters; - Reporters m_reporters; - -public: - void add( Ptr const& reporter ) { - m_reporters.push_back( reporter ); - } - -public: // IStreamingReporter - - virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { - return m_reporters[0]->getPreferences(); - } - - virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->noMatchingTestCases( spec ); - } - - virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testRunStarting( testRunInfo ); - } - - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testGroupStarting( groupInfo ); - } - - virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testCaseStarting( testInfo ); - } - - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->sectionStarting( sectionInfo ); - } - - virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->assertionStarting( assertionInfo ); - } - - // The return value indicates if the messages buffer should be cleared: - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - bool clearBuffer = false; - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - clearBuffer |= (*it)->assertionEnded( assertionStats ); - return clearBuffer; - } - - virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->sectionEnded( sectionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testCaseEnded( testCaseStats ); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testGroupEnded( testGroupStats ); - } - - virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testRunEnded( testRunStats ); - } - - virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->skipTest( testInfo ); - } - - virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE { - return this; - } - -}; - -Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { - Ptr resultingReporter; - - if( existingReporter ) { - MultipleReporters* multi = existingReporter->tryAsMulti(); - if( !multi ) { - multi = new MultipleReporters; - resultingReporter = Ptr( multi ); - if( existingReporter ) - multi->add( existingReporter ); - } - else - resultingReporter = existingReporter; - multi->add( additionalReporter ); - } - else - resultingReporter = additionalReporter; - - return resultingReporter; -} - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_xml.hpp -#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED - -// #included from: catch_reporter_bases.hpp -#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED - -#include -#include -#include -#include - -namespace Catch { - - namespace { - // Because formatting using c++ streams is stateful, drop down to C is required - // Alternatively we could use stringstream, but its performance is... not good. - std::string getFormattedDuration( double duration ) { - // Max exponent + 1 is required to represent the whole part - // + 1 for decimal point - // + 3 for the 3 decimal places - // + 1 for null terminator - const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; - char buffer[maxDoubleSize]; - - // Save previous errno, to prevent sprintf from overwriting it - ErrnoGuard guard; -#ifdef _MSC_VER - sprintf_s(buffer, "%.3f", duration); -#else - sprintf(buffer, "%.3f", duration); -#endif - return std::string(buffer); - } - } - - struct StreamingReporterBase : SharedImpl { - - StreamingReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = false; - } - - virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { - return m_reporterPrefs; - } - - virtual ~StreamingReporterBase() CATCH_OVERRIDE; - - virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} - - virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { - currentTestRunInfo = _testRunInfo; - } - virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { - currentGroupInfo = _groupInfo; - } - - virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { - currentTestCaseInfo = _testInfo; - } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { - m_sectionStack.push_back( _sectionInfo ); - } - - virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { - m_sectionStack.pop_back(); - } - virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { - currentTestCaseInfo.reset(); - } - virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { - currentGroupInfo.reset(); - } - virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { - currentTestCaseInfo.reset(); - currentGroupInfo.reset(); - currentTestRunInfo.reset(); - } - - virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { - // Don't do anything with this by default. - // It can optionally be overridden in the derived class. - } - - Ptr m_config; - std::ostream& stream; - - LazyStat currentTestRunInfo; - LazyStat currentGroupInfo; - LazyStat currentTestCaseInfo; - - std::vector m_sectionStack; - ReporterPreferences m_reporterPrefs; - }; - - struct CumulativeReporterBase : SharedImpl { - template - struct Node : SharedImpl<> { - explicit Node( T const& _value ) : value( _value ) {} - virtual ~Node() {} - - typedef std::vector > ChildNodes; - T value; - ChildNodes children; - }; - struct SectionNode : SharedImpl<> { - explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} - virtual ~SectionNode(); - - bool operator == ( SectionNode const& other ) const { - return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; - } - bool operator == ( Ptr const& other ) const { - return operator==( *other ); - } - - SectionStats stats; - typedef std::vector > ChildSections; - typedef std::vector Assertions; - ChildSections childSections; - Assertions assertions; - std::string stdOut; - std::string stdErr; - }; - - struct BySectionInfo { - BySectionInfo( SectionInfo const& other ) : m_other( other ) {} - BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} - bool operator() ( Ptr const& node ) const { - return ((node->stats.sectionInfo.name == m_other.name) && - (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); - } - private: - void operator=( BySectionInfo const& ); - SectionInfo const& m_other; - }; - - typedef Node TestCaseNode; - typedef Node TestGroupNode; - typedef Node TestRunNode; - - CumulativeReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = false; - } - ~CumulativeReporterBase(); - - virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { - return m_reporterPrefs; - } - - virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} - virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} - - virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} - - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { - SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); - Ptr node; - if( m_sectionStack.empty() ) { - if( !m_rootSection ) - m_rootSection = new SectionNode( incompleteStats ); - node = m_rootSection; - } - else { - SectionNode& parentNode = *m_sectionStack.back(); - SectionNode::ChildSections::const_iterator it = - std::find_if( parentNode.childSections.begin(), - parentNode.childSections.end(), - BySectionInfo( sectionInfo ) ); - if( it == parentNode.childSections.end() ) { - node = new SectionNode( incompleteStats ); - parentNode.childSections.push_back( node ); - } - else - node = *it; - } - m_sectionStack.push_back( node ); - m_deepestSection = node; - } - - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} - - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - assert( !m_sectionStack.empty() ); - SectionNode& sectionNode = *m_sectionStack.back(); - sectionNode.assertions.push_back( assertionStats ); - // AssertionResult holds a pointer to a temporary DecomposedExpression, - // which getExpandedExpression() calls to build the expression string. - // Our section stack copy of the assertionResult will likely outlive the - // temporary, so it must be expanded or discarded now to avoid calling - // a destroyed object later. - prepareExpandedExpression( sectionNode.assertions.back().assertionResult ); - return true; - } - virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { - assert( !m_sectionStack.empty() ); - SectionNode& node = *m_sectionStack.back(); - node.stats = sectionStats; - m_sectionStack.pop_back(); - } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - Ptr node = new TestCaseNode( testCaseStats ); - assert( m_sectionStack.size() == 0 ); - node->children.push_back( m_rootSection ); - m_testCases.push_back( node ); - m_rootSection.reset(); - - assert( m_deepestSection ); - m_deepestSection->stdOut = testCaseStats.stdOut; - m_deepestSection->stdErr = testCaseStats.stdErr; - } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - Ptr node = new TestGroupNode( testGroupStats ); - node->children.swap( m_testCases ); - m_testGroups.push_back( node ); - } - virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { - Ptr node = new TestRunNode( testRunStats ); - node->children.swap( m_testGroups ); - m_testRuns.push_back( node ); - testRunEndedCumulative(); - } - virtual void testRunEndedCumulative() = 0; - - virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} - - virtual void prepareExpandedExpression( AssertionResult& result ) const { - if( result.isOk() ) - result.discardDecomposedExpression(); - else - result.expandDecomposedExpression(); - } - - Ptr m_config; - std::ostream& stream; - std::vector m_assertions; - std::vector > > m_sections; - std::vector > m_testCases; - std::vector > m_testGroups; - - std::vector > m_testRuns; - - Ptr m_rootSection; - Ptr m_deepestSection; - std::vector > m_sectionStack; - ReporterPreferences m_reporterPrefs; - - }; - - template - char const* getLineOfChars() { - static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; - if( !*line ) { - std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); - line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; - } - return line; - } - - struct TestEventListenerBase : StreamingReporterBase { - TestEventListenerBase( ReporterConfig const& _config ) - : StreamingReporterBase( _config ) - {} - - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} - virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { - return false; - } - }; - -} // end namespace Catch - -// #included from: ../internal/catch_reporter_registrars.hpp -#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED - -namespace Catch { - - template - class LegacyReporterRegistrar { - - class ReporterFactory : public IReporterFactory { - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new LegacyReporterAdapter( new T( config ) ); - } - - virtual std::string getDescription() const { - return T::getDescription(); - } - }; - - public: - - LegacyReporterRegistrar( std::string const& name ) { - getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); - } - }; - - template - class ReporterRegistrar { - - class ReporterFactory : public SharedImpl { - - // *** Please Note ***: - // - If you end up here looking at a compiler error because it's trying to register - // your custom reporter class be aware that the native reporter interface has changed - // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via - // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. - // However please consider updating to the new interface as the old one is now - // deprecated and will probably be removed quite soon! - // Please contact me via github if you have any questions at all about this. - // In fact, ideally, please contact me anyway to let me know you've hit this - as I have - // no idea who is actually using custom reporters at all (possibly no-one!). - // The new interface is designed to minimise exposure to interface changes in the future. - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new T( config ); - } - - virtual std::string getDescription() const { - return T::getDescription(); - } - }; - - public: - - ReporterRegistrar( std::string const& name ) { - getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); - } - }; - - template - class ListenerRegistrar { - - class ListenerFactory : public SharedImpl { - - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new T( config ); - } - virtual std::string getDescription() const { - return std::string(); - } - }; - - public: - - ListenerRegistrar() { - getMutableRegistryHub().registerListener( new ListenerFactory() ); - } - }; -} - -#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ - namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } - -#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ - namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } - -// Deprecated - use the form without INTERNAL_ -#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ - namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } - -#define CATCH_REGISTER_LISTENER( listenerType ) \ - namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } - -// #included from: ../internal/catch_xmlwriter.hpp -#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED - -#include -#include -#include -#include - -namespace Catch { - - class XmlEncode { - public: - enum ForWhat { ForTextNodes, ForAttributes }; - - XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) - : m_str( str ), - m_forWhat( forWhat ) - {} - - void encodeTo( std::ostream& os ) const { - - // Apostrophe escaping not necessary if we always use " to write attributes - // (see: http://www.w3.org/TR/xml/#syntax) - - for( std::size_t i = 0; i < m_str.size(); ++ i ) { - char c = m_str[i]; - switch( c ) { - case '<': os << "<"; break; - case '&': os << "&"; break; - - case '>': - // See: http://www.w3.org/TR/xml/#syntax - if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) - os << ">"; - else - os << c; - break; - - case '\"': - if( m_forWhat == ForAttributes ) - os << """; - else - os << c; - break; - - default: - // Escape control chars - based on contribution by @espenalb in PR #465 and - // by @mrpi PR #588 - if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) { - // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 - os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) - << static_cast( c ); - } - else - os << c; - } - } - } - - friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { - xmlEncode.encodeTo( os ); - return os; - } - - private: - std::string m_str; - ForWhat m_forWhat; - }; - - class XmlWriter { - public: - - class ScopedElement { - public: - ScopedElement( XmlWriter* writer ) - : m_writer( writer ) - {} - - ScopedElement( ScopedElement const& other ) - : m_writer( other.m_writer ){ - other.m_writer = CATCH_NULL; - } - - ~ScopedElement() { - if( m_writer ) - m_writer->endElement(); - } - - ScopedElement& writeText( std::string const& text, bool indent = true ) { - m_writer->writeText( text, indent ); - return *this; - } - - template - ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { - m_writer->writeAttribute( name, attribute ); - return *this; - } - - private: - mutable XmlWriter* m_writer; - }; - - XmlWriter() - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( Catch::cout() ) - { - writeDeclaration(); - } - - XmlWriter( std::ostream& os ) - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( os ) - { - writeDeclaration(); - } - - ~XmlWriter() { - while( !m_tags.empty() ) - endElement(); - } - - XmlWriter& startElement( std::string const& name ) { - ensureTagClosed(); - newlineIfNecessary(); - m_os << m_indent << '<' << name; - m_tags.push_back( name ); - m_indent += " "; - m_tagIsOpen = true; - return *this; - } - - ScopedElement scopedElement( std::string const& name ) { - ScopedElement scoped( this ); - startElement( name ); - return scoped; - } - - XmlWriter& endElement() { - newlineIfNecessary(); - m_indent = m_indent.substr( 0, m_indent.size()-2 ); - if( m_tagIsOpen ) { - m_os << "/>"; - m_tagIsOpen = false; - } - else { - m_os << m_indent << ""; - } - m_os << std::endl; - m_tags.pop_back(); - return *this; - } - - XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { - if( !name.empty() && !attribute.empty() ) - m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; - return *this; - } - - XmlWriter& writeAttribute( std::string const& name, bool attribute ) { - m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; - return *this; - } - - template - XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { - std::ostringstream oss; - oss << attribute; - return writeAttribute( name, oss.str() ); - } - - XmlWriter& writeText( std::string const& text, bool indent = true ) { - if( !text.empty() ){ - bool tagWasOpen = m_tagIsOpen; - ensureTagClosed(); - if( tagWasOpen && indent ) - m_os << m_indent; - m_os << XmlEncode( text ); - m_needsNewline = true; - } - return *this; - } - - XmlWriter& writeComment( std::string const& text ) { - ensureTagClosed(); - m_os << m_indent << ""; - m_needsNewline = true; - return *this; - } - - void writeStylesheetRef( std::string const& url ) { - m_os << "\n"; - } - - XmlWriter& writeBlankLine() { - ensureTagClosed(); - m_os << '\n'; - return *this; - } - - void ensureTagClosed() { - if( m_tagIsOpen ) { - m_os << ">" << std::endl; - m_tagIsOpen = false; - } - } - - private: - XmlWriter( XmlWriter const& ); - void operator=( XmlWriter const& ); - - void writeDeclaration() { - m_os << "\n"; - } - - void newlineIfNecessary() { - if( m_needsNewline ) { - m_os << std::endl; - m_needsNewline = false; - } - } - - bool m_tagIsOpen; - bool m_needsNewline; - std::vector m_tags; - std::string m_indent; - std::ostream& m_os; - }; - -} - -namespace Catch { - class XmlReporter : public StreamingReporterBase { - public: - XmlReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - m_xml(_config.stream()), - m_sectionDepth( 0 ) - { - m_reporterPrefs.shouldRedirectStdOut = true; - } - - virtual ~XmlReporter() CATCH_OVERRIDE; - - static std::string getDescription() { - return "Reports test results as an XML document"; - } - - virtual std::string getStylesheetRef() const { - return std::string(); - } - - void writeSourceInfo( SourceLineInfo const& sourceInfo ) { - m_xml - .writeAttribute( "filename", sourceInfo.file ) - .writeAttribute( "line", sourceInfo.line ); - } - - public: // StreamingReporterBase - - virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { - StreamingReporterBase::noMatchingTestCases( s ); - } - - virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { - StreamingReporterBase::testRunStarting( testInfo ); - std::string stylesheetRef = getStylesheetRef(); - if( !stylesheetRef.empty() ) - m_xml.writeStylesheetRef( stylesheetRef ); - m_xml.startElement( "Catch" ); - if( !m_config->name().empty() ) - m_xml.writeAttribute( "name", m_config->name() ); - } - - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { - StreamingReporterBase::testGroupStarting( groupInfo ); - m_xml.startElement( "Group" ) - .writeAttribute( "name", groupInfo.name ); - } - - virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { - StreamingReporterBase::testCaseStarting(testInfo); - m_xml.startElement( "TestCase" ) - .writeAttribute( "name", trim( testInfo.name ) ) - .writeAttribute( "description", testInfo.description ) - .writeAttribute( "tags", testInfo.tagsAsString ); - - writeSourceInfo( testInfo.lineInfo ); - - if ( m_config->showDurations() == ShowDurations::Always ) - m_testCaseTimer.start(); - m_xml.ensureTagClosed(); - } - - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { - StreamingReporterBase::sectionStarting( sectionInfo ); - if( m_sectionDepth++ > 0 ) { - m_xml.startElement( "Section" ) - .writeAttribute( "name", trim( sectionInfo.name ) ) - .writeAttribute( "description", sectionInfo.description ); - writeSourceInfo( sectionInfo.lineInfo ); - m_xml.ensureTagClosed(); - } - } - - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } - - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - - AssertionResult const& result = assertionStats.assertionResult; - - bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); - - if( includeResults ) { - // Print any info messages in tags. - for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); - it != itEnd; - ++it ) { - if( it->type == ResultWas::Info ) { - m_xml.scopedElement( "Info" ) - .writeText( it->message ); - } else if ( it->type == ResultWas::Warning ) { - m_xml.scopedElement( "Warning" ) - .writeText( it->message ); - } - } - } - - // Drop out if result was successful but we're not printing them. - if( !includeResults && result.getResultType() != ResultWas::Warning ) - return true; - - // Print the expression if there is one. - if( result.hasExpression() ) { - m_xml.startElement( "Expression" ) - .writeAttribute( "success", result.succeeded() ) - .writeAttribute( "type", result.getTestMacroName() ); - - writeSourceInfo( result.getSourceInfo() ); - - m_xml.scopedElement( "Original" ) - .writeText( result.getExpression() ); - m_xml.scopedElement( "Expanded" ) - .writeText( result.getExpandedExpression() ); - } - - // And... Print a result applicable to each result type. - switch( result.getResultType() ) { - case ResultWas::ThrewException: - m_xml.startElement( "Exception" ); - writeSourceInfo( result.getSourceInfo() ); - m_xml.writeText( result.getMessage() ); - m_xml.endElement(); - break; - case ResultWas::FatalErrorCondition: - m_xml.startElement( "FatalErrorCondition" ); - writeSourceInfo( result.getSourceInfo() ); - m_xml.writeText( result.getMessage() ); - m_xml.endElement(); - break; - case ResultWas::Info: - m_xml.scopedElement( "Info" ) - .writeText( result.getMessage() ); - break; - case ResultWas::Warning: - // Warning will already have been written - break; - case ResultWas::ExplicitFailure: - m_xml.startElement( "Failure" ); - writeSourceInfo( result.getSourceInfo() ); - m_xml.writeText( result.getMessage() ); - m_xml.endElement(); - break; - default: - break; - } - - if( result.hasExpression() ) - m_xml.endElement(); - - return true; - } - - virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { - StreamingReporterBase::sectionEnded( sectionStats ); - if( --m_sectionDepth > 0 ) { - XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); - e.writeAttribute( "successes", sectionStats.assertions.passed ); - e.writeAttribute( "failures", sectionStats.assertions.failed ); - e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); - - if ( m_config->showDurations() == ShowDurations::Always ) - e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); - - m_xml.endElement(); - } - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - StreamingReporterBase::testCaseEnded( testCaseStats ); - XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); - e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); - - if ( m_config->showDurations() == ShowDurations::Always ) - e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); - - if( !testCaseStats.stdOut.empty() ) - m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false ); - if( !testCaseStats.stdErr.empty() ) - m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false ); - - m_xml.endElement(); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - StreamingReporterBase::testGroupEnded( testGroupStats ); - // TODO: Check testGroupStats.aborting and act accordingly. - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) - .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) - .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); - m_xml.endElement(); - } - - virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { - StreamingReporterBase::testRunEnded( testRunStats ); - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", testRunStats.totals.assertions.passed ) - .writeAttribute( "failures", testRunStats.totals.assertions.failed ) - .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); - m_xml.endElement(); - } - - private: - Timer m_testCaseTimer; - XmlWriter m_xml; - int m_sectionDepth; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_junit.hpp -#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED - -#include - -namespace Catch { - - namespace { - std::string getCurrentTimestamp() { - // Beware, this is not reentrant because of backward compatibility issues - // Also, UTC only, again because of backward compatibility (%z is C++11) - time_t rawtime; - std::time(&rawtime); - const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z"); - -#ifdef _MSC_VER - std::tm timeInfo = {}; - gmtime_s(&timeInfo, &rawtime); -#else - std::tm* timeInfo; - timeInfo = std::gmtime(&rawtime); -#endif - - char timeStamp[timeStampSize]; - const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; - -#ifdef _MSC_VER - std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); -#else - std::strftime(timeStamp, timeStampSize, fmt, timeInfo); -#endif - return std::string(timeStamp); - } - - } - - class JunitReporter : public CumulativeReporterBase { - public: - JunitReporter( ReporterConfig const& _config ) - : CumulativeReporterBase( _config ), - xml( _config.stream() ), - unexpectedExceptions( 0 ), - m_okToFail( false ) - { - m_reporterPrefs.shouldRedirectStdOut = true; - } - - virtual ~JunitReporter() CATCH_OVERRIDE; - - static std::string getDescription() { - return "Reports test results in an XML format that looks like Ant's junitreport target"; - } - - virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} - - virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { - CumulativeReporterBase::testRunStarting( runInfo ); - xml.startElement( "testsuites" ); - } - - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { - suiteTimer.start(); - stdOutForSuite.str(""); - stdErrForSuite.str(""); - unexpectedExceptions = 0; - CumulativeReporterBase::testGroupStarting( groupInfo ); - } - - virtual void testCaseStarting( TestCaseInfo const& testCaseInfo ) CATCH_OVERRIDE { - m_okToFail = testCaseInfo.okToFail(); - } - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) - unexpectedExceptions++; - return CumulativeReporterBase::assertionEnded( assertionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - stdOutForSuite << testCaseStats.stdOut; - stdErrForSuite << testCaseStats.stdErr; - CumulativeReporterBase::testCaseEnded( testCaseStats ); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - double suiteTime = suiteTimer.getElapsedSeconds(); - CumulativeReporterBase::testGroupEnded( testGroupStats ); - writeGroup( *m_testGroups.back(), suiteTime ); - } - - virtual void testRunEndedCumulative() CATCH_OVERRIDE { - xml.endElement(); - } - - void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); - TestGroupStats const& stats = groupNode.value; - xml.writeAttribute( "name", stats.groupInfo.name ); - xml.writeAttribute( "errors", unexpectedExceptions ); - xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); - xml.writeAttribute( "tests", stats.totals.assertions.total() ); - xml.writeAttribute( "hostname", "tbd" ); // !TBD - if( m_config->showDurations() == ShowDurations::Never ) - xml.writeAttribute( "time", "" ); - else - xml.writeAttribute( "time", suiteTime ); - xml.writeAttribute( "timestamp", getCurrentTimestamp() ); - - // Write test cases - for( TestGroupNode::ChildNodes::const_iterator - it = groupNode.children.begin(), itEnd = groupNode.children.end(); - it != itEnd; - ++it ) - writeTestCase( **it ); - - xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); - xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); - } - - void writeTestCase( TestCaseNode const& testCaseNode ) { - TestCaseStats const& stats = testCaseNode.value; - - // All test cases have exactly one section - which represents the - // test case itself. That section may have 0-n nested sections - assert( testCaseNode.children.size() == 1 ); - SectionNode const& rootSection = *testCaseNode.children.front(); - - std::string className = stats.testInfo.className; - - if( className.empty() ) { - if( rootSection.childSections.empty() ) - className = "global"; - } - writeSection( className, "", rootSection ); - } - - void writeSection( std::string const& className, - std::string const& rootName, - SectionNode const& sectionNode ) { - std::string name = trim( sectionNode.stats.sectionInfo.name ); - if( !rootName.empty() ) - name = rootName + '/' + name; - - if( !sectionNode.assertions.empty() || - !sectionNode.stdOut.empty() || - !sectionNode.stdErr.empty() ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); - if( className.empty() ) { - xml.writeAttribute( "classname", name ); - xml.writeAttribute( "name", "root" ); - } - else { - xml.writeAttribute( "classname", className ); - xml.writeAttribute( "name", name ); - } - xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); - - writeAssertions( sectionNode ); - - if( !sectionNode.stdOut.empty() ) - xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); - if( !sectionNode.stdErr.empty() ) - xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); - } - for( SectionNode::ChildSections::const_iterator - it = sectionNode.childSections.begin(), - itEnd = sectionNode.childSections.end(); - it != itEnd; - ++it ) - if( className.empty() ) - writeSection( name, "", **it ); - else - writeSection( className, name, **it ); - } - - void writeAssertions( SectionNode const& sectionNode ) { - for( SectionNode::Assertions::const_iterator - it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); - it != itEnd; - ++it ) - writeAssertion( *it ); - } - void writeAssertion( AssertionStats const& stats ) { - AssertionResult const& result = stats.assertionResult; - if( !result.isOk() ) { - std::string elementName; - switch( result.getResultType() ) { - case ResultWas::ThrewException: - case ResultWas::FatalErrorCondition: - elementName = "error"; - break; - case ResultWas::ExplicitFailure: - elementName = "failure"; - break; - case ResultWas::ExpressionFailed: - elementName = "failure"; - break; - case ResultWas::DidntThrowException: - elementName = "failure"; - break; - - // We should never see these here: - case ResultWas::Info: - case ResultWas::Warning: - case ResultWas::Ok: - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - elementName = "internalError"; - break; - } - - XmlWriter::ScopedElement e = xml.scopedElement( elementName ); - - xml.writeAttribute( "message", result.getExpandedExpression() ); - xml.writeAttribute( "type", result.getTestMacroName() ); - - std::ostringstream oss; - if( !result.getMessage().empty() ) - oss << result.getMessage() << '\n'; - for( std::vector::const_iterator - it = stats.infoMessages.begin(), - itEnd = stats.infoMessages.end(); - it != itEnd; - ++it ) - if( it->type == ResultWas::Info ) - oss << it->message << '\n'; - - oss << "at " << result.getSourceInfo(); - xml.writeText( oss.str(), false ); - } - } - - XmlWriter xml; - Timer suiteTimer; - std::ostringstream stdOutForSuite; - std::ostringstream stdErrForSuite; - unsigned int unexpectedExceptions; - bool m_okToFail; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_console.hpp -#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED - -#include -#include - -namespace Catch { - - struct ConsoleReporter : StreamingReporterBase { - ConsoleReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - m_headerPrinted( false ) - {} - - virtual ~ConsoleReporter() CATCH_OVERRIDE; - static std::string getDescription() { - return "Reports test results as plain lines of text"; - } - - virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { - stream << "No test cases matched '" << spec << '\'' << std::endl; - } - - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { - } - - virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { - AssertionResult const& result = _assertionStats.assertionResult; - - bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); - - // Drop out if result was successful but we're not printing them. - if( !includeResults && result.getResultType() != ResultWas::Warning ) - return false; - - lazyPrint(); - - AssertionPrinter printer( stream, _assertionStats, includeResults ); - printer.print(); - stream << std::endl; - return true; - } - - virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { - m_headerPrinted = false; - StreamingReporterBase::sectionStarting( _sectionInfo ); - } - virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { - if( _sectionStats.missingAssertions ) { - lazyPrint(); - Colour colour( Colour::ResultError ); - if( m_sectionStack.size() > 1 ) - stream << "\nNo assertions in section"; - else - stream << "\nNo assertions in test case"; - stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; - } - if( m_config->showDurations() == ShowDurations::Always ) { - stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; - } - if( m_headerPrinted ) { - m_headerPrinted = false; - } - StreamingReporterBase::sectionEnded( _sectionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { - StreamingReporterBase::testCaseEnded( _testCaseStats ); - m_headerPrinted = false; - } - virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { - if( currentGroupInfo.used ) { - printSummaryDivider(); - stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; - printTotals( _testGroupStats.totals ); - stream << '\n' << std::endl; - } - StreamingReporterBase::testGroupEnded( _testGroupStats ); - } - virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { - printTotalsDivider( _testRunStats.totals ); - printTotals( _testRunStats.totals ); - stream << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); - } - - private: - - class AssertionPrinter { - void operator= ( AssertionPrinter const& ); - public: - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) - : stream( _stream ), - stats( _stats ), - result( _stats.assertionResult ), - colour( Colour::None ), - message( result.getMessage() ), - messages( _stats.infoMessages ), - printInfoMessages( _printInfoMessages ) - { - switch( result.getResultType() ) { - case ResultWas::Ok: - colour = Colour::Success; - passOrFail = "PASSED"; - //if( result.hasMessage() ) - if( _stats.infoMessages.size() == 1 ) - messageLabel = "with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "with messages"; - break; - case ResultWas::ExpressionFailed: - if( result.isOk() ) { - colour = Colour::Success; - passOrFail = "FAILED - but was ok"; - } - else { - colour = Colour::Error; - passOrFail = "FAILED"; - } - if( _stats.infoMessages.size() == 1 ) - messageLabel = "with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "with messages"; - break; - case ResultWas::ThrewException: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "due to unexpected exception with "; - if (_stats.infoMessages.size() == 1) - messageLabel += "message"; - if (_stats.infoMessages.size() > 1) - messageLabel += "messages"; - break; - case ResultWas::FatalErrorCondition: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "due to a fatal error condition"; - break; - case ResultWas::DidntThrowException: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "because no exception was thrown where one was expected"; - break; - case ResultWas::Info: - messageLabel = "info"; - break; - case ResultWas::Warning: - messageLabel = "warning"; - break; - case ResultWas::ExplicitFailure: - passOrFail = "FAILED"; - colour = Colour::Error; - if( _stats.infoMessages.size() == 1 ) - messageLabel = "explicitly with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "explicitly with messages"; - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - passOrFail = "** internal error **"; - colour = Colour::Error; - break; - } - } - - void print() const { - printSourceInfo(); - if( stats.totals.assertions.total() > 0 ) { - if( result.isOk() ) - stream << '\n'; - printResultType(); - printOriginalExpression(); - printReconstructedExpression(); - } - else { - stream << '\n'; - } - printMessage(); - } - - private: - void printResultType() const { - if( !passOrFail.empty() ) { - Colour colourGuard( colour ); - stream << passOrFail << ":\n"; - } - } - void printOriginalExpression() const { - if( result.hasExpression() ) { - Colour colourGuard( Colour::OriginalExpression ); - stream << " "; - stream << result.getExpressionInMacro(); - stream << '\n'; - } - } - void printReconstructedExpression() const { - if( result.hasExpandedExpression() ) { - stream << "with expansion:\n"; - Colour colourGuard( Colour::ReconstructedExpression ); - stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n'; - } - } - void printMessage() const { - if( !messageLabel.empty() ) - stream << messageLabel << ':' << '\n'; - for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); - it != itEnd; - ++it ) { - // If this assertion is a warning ignore any INFO messages - if( printInfoMessages || it->type != ResultWas::Info ) - stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n'; - } - } - void printSourceInfo() const { - Colour colourGuard( Colour::FileName ); - stream << result.getSourceInfo() << ": "; - } - - std::ostream& stream; - AssertionStats const& stats; - AssertionResult const& result; - Colour::Code colour; - std::string passOrFail; - std::string messageLabel; - std::string message; - std::vector messages; - bool printInfoMessages; - }; - - void lazyPrint() { - - if( !currentTestRunInfo.used ) - lazyPrintRunInfo(); - if( !currentGroupInfo.used ) - lazyPrintGroupInfo(); - - if( !m_headerPrinted ) { - printTestCaseAndSectionHeader(); - m_headerPrinted = true; - } - } - void lazyPrintRunInfo() { - stream << '\n' << getLineOfChars<'~'>() << '\n'; - Colour colour( Colour::SecondaryText ); - stream << currentTestRunInfo->name - << " is a Catch v" << libraryVersion() << " host application.\n" - << "Run with -? for options\n\n"; - - if( m_config->rngSeed() != 0 ) - stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; - - currentTestRunInfo.used = true; - } - void lazyPrintGroupInfo() { - if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { - printClosedHeader( "Group: " + currentGroupInfo->name ); - currentGroupInfo.used = true; - } - } - void printTestCaseAndSectionHeader() { - assert( !m_sectionStack.empty() ); - printOpenHeader( currentTestCaseInfo->name ); - - if( m_sectionStack.size() > 1 ) { - Colour colourGuard( Colour::Headers ); - - std::vector::const_iterator - it = m_sectionStack.begin()+1, // Skip first section (test case) - itEnd = m_sectionStack.end(); - for( ; it != itEnd; ++it ) - printHeaderString( it->name, 2 ); - } - - SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; - - if( !lineInfo.empty() ){ - stream << getLineOfChars<'-'>() << '\n'; - Colour colourGuard( Colour::FileName ); - stream << lineInfo << '\n'; - } - stream << getLineOfChars<'.'>() << '\n' << std::endl; - } - - void printClosedHeader( std::string const& _name ) { - printOpenHeader( _name ); - stream << getLineOfChars<'.'>() << '\n'; - } - void printOpenHeader( std::string const& _name ) { - stream << getLineOfChars<'-'>() << '\n'; - { - Colour colourGuard( Colour::Headers ); - printHeaderString( _name ); - } - } - - // if string has a : in first line will set indent to follow it on - // subsequent lines - void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { - std::size_t i = _string.find( ": " ); - if( i != std::string::npos ) - i+=2; - else - i = 0; - stream << Text( _string, TextAttributes() - .setIndent( indent+i) - .setInitialIndent( indent ) ) << '\n'; - } - - struct SummaryColumn { - - SummaryColumn( std::string const& _label, Colour::Code _colour ) - : label( _label ), - colour( _colour ) - {} - SummaryColumn addRow( std::size_t count ) { - std::ostringstream oss; - oss << count; - std::string row = oss.str(); - for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { - while( it->size() < row.size() ) - *it = ' ' + *it; - while( it->size() > row.size() ) - row = ' ' + row; - } - rows.push_back( row ); - return *this; - } - - std::string label; - Colour::Code colour; - std::vector rows; - - }; - - void printTotals( Totals const& totals ) { - if( totals.testCases.total() == 0 ) { - stream << Colour( Colour::Warning ) << "No tests ran\n"; - } - else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { - stream << Colour( Colour::ResultSuccess ) << "All tests passed"; - stream << " (" - << pluralise( totals.assertions.passed, "assertion" ) << " in " - << pluralise( totals.testCases.passed, "test case" ) << ')' - << '\n'; - } - else { - - std::vector columns; - columns.push_back( SummaryColumn( "", Colour::None ) - .addRow( totals.testCases.total() ) - .addRow( totals.assertions.total() ) ); - columns.push_back( SummaryColumn( "passed", Colour::Success ) - .addRow( totals.testCases.passed ) - .addRow( totals.assertions.passed ) ); - columns.push_back( SummaryColumn( "failed", Colour::ResultError ) - .addRow( totals.testCases.failed ) - .addRow( totals.assertions.failed ) ); - columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) - .addRow( totals.testCases.failedButOk ) - .addRow( totals.assertions.failedButOk ) ); - - printSummaryRow( "test cases", columns, 0 ); - printSummaryRow( "assertions", columns, 1 ); - } - } - void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { - for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { - std::string value = it->rows[row]; - if( it->label.empty() ) { - stream << label << ": "; - if( value != "0" ) - stream << value; - else - stream << Colour( Colour::Warning ) << "- none -"; - } - else if( value != "0" ) { - stream << Colour( Colour::LightGrey ) << " | "; - stream << Colour( it->colour ) - << value << ' ' << it->label; - } - } - stream << '\n'; - } - - static std::size_t makeRatio( std::size_t number, std::size_t total ) { - std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; - return ( ratio == 0 && number > 0 ) ? 1 : ratio; - } - static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { - if( i > j && i > k ) - return i; - else if( j > k ) - return j; - else - return k; - } - - void printTotalsDivider( Totals const& totals ) { - if( totals.testCases.total() > 0 ) { - std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); - std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); - std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); - while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) - findMax( failedRatio, failedButOkRatio, passedRatio )++; - while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) - findMax( failedRatio, failedButOkRatio, passedRatio )--; - - stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); - stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); - if( totals.testCases.allPassed() ) - stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); - else - stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); - } - else { - stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); - } - stream << '\n'; - } - void printSummaryDivider() { - stream << getLineOfChars<'-'>() << '\n'; - } - - private: - bool m_headerPrinted; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_compact.hpp -#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED - -namespace Catch { - - struct CompactReporter : StreamingReporterBase { - - CompactReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ) - {} - - virtual ~CompactReporter(); - - static std::string getDescription() { - return "Reports test results on a single line, suitable for IDEs"; - } - - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = false; - return prefs; - } - - virtual void noMatchingTestCases( std::string const& spec ) { - stream << "No test cases matched '" << spec << '\'' << std::endl; - } - - virtual void assertionStarting( AssertionInfo const& ) {} - - virtual bool assertionEnded( AssertionStats const& _assertionStats ) { - AssertionResult const& result = _assertionStats.assertionResult; - - bool printInfoMessages = true; - - // Drop out if result was successful and we're not printing those - if( !m_config->includeSuccessfulResults() && result.isOk() ) { - if( result.getResultType() != ResultWas::Warning ) - return false; - printInfoMessages = false; - } - - AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); - printer.print(); - - stream << std::endl; - return true; - } - - virtual void sectionEnded(SectionStats const& _sectionStats) CATCH_OVERRIDE { - if (m_config->showDurations() == ShowDurations::Always) { - stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; - } - } - - virtual void testRunEnded( TestRunStats const& _testRunStats ) { - printTotals( _testRunStats.totals ); - stream << '\n' << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); - } - - private: - class AssertionPrinter { - void operator= ( AssertionPrinter const& ); - public: - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) - : stream( _stream ) - , stats( _stats ) - , result( _stats.assertionResult ) - , messages( _stats.infoMessages ) - , itMessage( _stats.infoMessages.begin() ) - , printInfoMessages( _printInfoMessages ) - {} - - void print() { - printSourceInfo(); - - itMessage = messages.begin(); - - switch( result.getResultType() ) { - case ResultWas::Ok: - printResultType( Colour::ResultSuccess, passedString() ); - printOriginalExpression(); - printReconstructedExpression(); - if ( ! result.hasExpression() ) - printRemainingMessages( Colour::None ); - else - printRemainingMessages(); - break; - case ResultWas::ExpressionFailed: - if( result.isOk() ) - printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); - else - printResultType( Colour::Error, failedString() ); - printOriginalExpression(); - printReconstructedExpression(); - printRemainingMessages(); - break; - case ResultWas::ThrewException: - printResultType( Colour::Error, failedString() ); - printIssue( "unexpected exception with message:" ); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::FatalErrorCondition: - printResultType( Colour::Error, failedString() ); - printIssue( "fatal error condition with message:" ); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::DidntThrowException: - printResultType( Colour::Error, failedString() ); - printIssue( "expected exception, got none" ); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::Info: - printResultType( Colour::None, "info" ); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::Warning: - printResultType( Colour::None, "warning" ); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::ExplicitFailure: - printResultType( Colour::Error, failedString() ); - printIssue( "explicitly" ); - printRemainingMessages( Colour::None ); - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - printResultType( Colour::Error, "** internal error **" ); - break; - } - } - - private: - // Colour::LightGrey - - static Colour::Code dimColour() { return Colour::FileName; } - -#ifdef CATCH_PLATFORM_MAC - static const char* failedString() { return "FAILED"; } - static const char* passedString() { return "PASSED"; } -#else - static const char* failedString() { return "failed"; } - static const char* passedString() { return "passed"; } -#endif - - void printSourceInfo() const { - Colour colourGuard( Colour::FileName ); - stream << result.getSourceInfo() << ':'; - } - - void printResultType( Colour::Code colour, std::string const& passOrFail ) const { - if( !passOrFail.empty() ) { - { - Colour colourGuard( colour ); - stream << ' ' << passOrFail; - } - stream << ':'; - } - } - - void printIssue( std::string const& issue ) const { - stream << ' ' << issue; - } - - void printExpressionWas() { - if( result.hasExpression() ) { - stream << ';'; - { - Colour colour( dimColour() ); - stream << " expression was:"; - } - printOriginalExpression(); - } - } - - void printOriginalExpression() const { - if( result.hasExpression() ) { - stream << ' ' << result.getExpression(); - } - } - - void printReconstructedExpression() const { - if( result.hasExpandedExpression() ) { - { - Colour colour( dimColour() ); - stream << " for: "; - } - stream << result.getExpandedExpression(); - } - } - - void printMessage() { - if ( itMessage != messages.end() ) { - stream << " '" << itMessage->message << '\''; - ++itMessage; - } - } - - void printRemainingMessages( Colour::Code colour = dimColour() ) { - if ( itMessage == messages.end() ) - return; - - // using messages.end() directly yields compilation error: - std::vector::const_iterator itEnd = messages.end(); - const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); - - { - Colour colourGuard( colour ); - stream << " with " << pluralise( N, "message" ) << ':'; - } - - for(; itMessage != itEnd; ) { - // If this assertion is a warning ignore any INFO messages - if( printInfoMessages || itMessage->type != ResultWas::Info ) { - stream << " '" << itMessage->message << '\''; - if ( ++itMessage != itEnd ) { - Colour colourGuard( dimColour() ); - stream << " and"; - } - } - } - } - - private: - std::ostream& stream; - AssertionStats const& stats; - AssertionResult const& result; - std::vector messages; - std::vector::const_iterator itMessage; - bool printInfoMessages; - }; - - // Colour, message variants: - // - white: No tests ran. - // - red: Failed [both/all] N test cases, failed [both/all] M assertions. - // - white: Passed [both/all] N test cases (no assertions). - // - red: Failed N tests cases, failed M assertions. - // - green: Passed [both/all] N tests cases with M assertions. - - std::string bothOrAll( std::size_t count ) const { - return count == 1 ? std::string() : count == 2 ? "both " : "all " ; - } - - void printTotals( const Totals& totals ) const { - if( totals.testCases.total() == 0 ) { - stream << "No tests ran."; - } - else if( totals.testCases.failed == totals.testCases.total() ) { - Colour colour( Colour::ResultError ); - const std::string qualify_assertions_failed = - totals.assertions.failed == totals.assertions.total() ? - bothOrAll( totals.assertions.failed ) : std::string(); - stream << - "Failed " << bothOrAll( totals.testCases.failed ) - << pluralise( totals.testCases.failed, "test case" ) << ", " - "failed " << qualify_assertions_failed << - pluralise( totals.assertions.failed, "assertion" ) << '.'; - } - else if( totals.assertions.total() == 0 ) { - stream << - "Passed " << bothOrAll( totals.testCases.total() ) - << pluralise( totals.testCases.total(), "test case" ) - << " (no assertions)."; - } - else if( totals.assertions.failed ) { - Colour colour( Colour::ResultError ); - stream << - "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " - "failed " << pluralise( totals.assertions.failed, "assertion" ) << '.'; - } - else { - Colour colour( Colour::ResultSuccess ); - stream << - "Passed " << bothOrAll( totals.testCases.passed ) - << pluralise( totals.testCases.passed, "test case" ) << - " with " << pluralise( totals.assertions.passed, "assertion" ) << '.'; - } - } - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) - -} // end namespace Catch - -namespace Catch { - // These are all here to avoid warnings about not having any out of line - // virtual methods - NonCopyable::~NonCopyable() {} - IShared::~IShared() {} - IStream::~IStream() CATCH_NOEXCEPT {} - FileStream::~FileStream() CATCH_NOEXCEPT {} - CoutStream::~CoutStream() CATCH_NOEXCEPT {} - DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} - StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} - IContext::~IContext() {} - IResultCapture::~IResultCapture() {} - ITestCase::~ITestCase() {} - ITestCaseRegistry::~ITestCaseRegistry() {} - IRegistryHub::~IRegistryHub() {} - IMutableRegistryHub::~IMutableRegistryHub() {} - IExceptionTranslator::~IExceptionTranslator() {} - IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} - IReporter::~IReporter() {} - IReporterFactory::~IReporterFactory() {} - IReporterRegistry::~IReporterRegistry() {} - IStreamingReporter::~IStreamingReporter() {} - AssertionStats::~AssertionStats() {} - SectionStats::~SectionStats() {} - TestCaseStats::~TestCaseStats() {} - TestGroupStats::~TestGroupStats() {} - TestRunStats::~TestRunStats() {} - CumulativeReporterBase::SectionNode::~SectionNode() {} - CumulativeReporterBase::~CumulativeReporterBase() {} - - StreamingReporterBase::~StreamingReporterBase() {} - ConsoleReporter::~ConsoleReporter() {} - CompactReporter::~CompactReporter() {} - IRunner::~IRunner() {} - IMutableContext::~IMutableContext() {} - IConfig::~IConfig() {} - XmlReporter::~XmlReporter() {} - JunitReporter::~JunitReporter() {} - TestRegistry::~TestRegistry() {} - FreeFunctionTestCase::~FreeFunctionTestCase() {} - IGeneratorInfo::~IGeneratorInfo() {} - IGeneratorsForTest::~IGeneratorsForTest() {} - WildcardPattern::~WildcardPattern() {} - TestSpec::Pattern::~Pattern() {} - TestSpec::NamePattern::~NamePattern() {} - TestSpec::TagPattern::~TagPattern() {} - TestSpec::ExcludedPattern::~ExcludedPattern() {} - Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {} - - void Config::dummy() {} - - namespace TestCaseTracking { - ITracker::~ITracker() {} - TrackerBase::~TrackerBase() {} - SectionTracker::~SectionTracker() {} - IndexTracker::~IndexTracker() {} - } -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#endif - -#ifdef CATCH_CONFIG_MAIN -// #included from: internal/catch_default_main.hpp -#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED - -#ifndef __OBJC__ - -#if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) -// Standard C/C++ Win32 Unicode wmain entry point -extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { -#else -// Standard C/C++ main entry point -int main (int argc, char * argv[]) { -#endif - - int result = Catch::Session().run( argc, argv ); - return ( result < 0xff ? result : 0xff ); -} - -#else // __OBJC__ - -// Objective-C entry point -int main (int argc, char * const argv[]) { -#if !CATCH_ARC_ENABLED - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; -#endif - - Catch::registerTestMethods(); - int result = Catch::Session().run( argc, (char* const*)argv ); - -#if !CATCH_ARC_ENABLED - [pool drain]; -#endif - - return ( result < 0xff ? result : 0xff ); -} - -#endif // __OBJC__ - -#endif - -#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED -# undef CLARA_CONFIG_MAIN -#endif - -////// - -// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ -#ifdef CATCH_CONFIG_PREFIX_ALL - -#if defined(CATCH_CONFIG_FAST_COMPILE) -#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) -#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) -#else -#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) -#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) -#endif - -#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) -#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) -#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) -#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) - -#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) -#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) - -#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) -#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) -#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) - -#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) - -#if defined(CATCH_CONFIG_FAST_COMPILE) -#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#else -#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#endif - -#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) -#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) -#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) -#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) -#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) - #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) - #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) - #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) - #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) - #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) - #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) - #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#else - #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) - #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) - #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) - #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) - #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) - #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg ) - #define CATCH_FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg ) - #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg ) -#endif -#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) - -#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) - -#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) - -// "BDD-style" convenience wrappers -#ifdef CATCH_CONFIG_VARIADIC_MACROS -#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) -#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) -#else -#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) -#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) -#endif -#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) -#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) -#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) -#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) -#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) - -// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required -#else - -#if defined(CATCH_CONFIG_FAST_COMPILE) -#define REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE", Catch::ResultDisposition::Normal, expr ) -#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) - -#else -#define REQUIRE( expr ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, expr ) -#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) -#endif - -#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) -#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) -#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) -#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) - -#define CHECK( expr ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) -#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) - -#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) -#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) -#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) - -#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) - -#if defined(CATCH_CONFIG_FAST_COMPILE) -#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#else -#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#endif - -#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) -#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) -#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) -#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) -#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) - -#ifdef CATCH_CONFIG_VARIADIC_MACROS -#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) -#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) -#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) -#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) -#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) -#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) -#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#else -#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) - #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) - #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) - #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) - #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) - #define FAIL( msg ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg ) - #define FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg ) - #define SUCCEED( msg ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg ) -#endif -#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) - -#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) - -#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) - -#endif - -#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) - -// "BDD-style" convenience wrappers -#ifdef CATCH_CONFIG_VARIADIC_MACROS -#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) -#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) -#else -#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) -#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) -#endif -#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) -#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) -#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) -#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) -#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) - -using Catch::Detail::Approx; - -// #included from: internal/catch_reenable_warnings.h - -#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(pop) -# else -# pragma clang diagnostic pop -# endif -#elif defined __GNUC__ -# pragma GCC diagnostic pop -#endif - -#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED - diff --git a/tests/Test_config.h b/tests/Test_config.h index 7cd54c70..329d59b4 100644 --- a/tests/Test_config.h +++ b/tests/Test_config.h @@ -29,7 +29,7 @@ along with this program. If not, see . */ /*-------------------VERSION----------------------*/ -#define OMG_VERSION "0.8" +#define OMG_VERSION "0.9beta" /*-------------CONFIGURE WIFIMANAGER-------------*/ /* @@ -48,7 +48,10 @@ * to the access point with your password (SSID: WifiManager_ssid, password: WifiManager_password) */ -//#define ESPWifiManualSetup true //uncomment to disable WifiManager +#if defined(ESP8266) // for nodemcu, weemos and esp8266 + //#define ESPWifiManualSetup true //uncomment you don't want to use wifimanager for your credential settings on ESP +#endif + #define WifiManager_password "your_password" //this is going to be the WPA2-PSK password for the initial setup access point #define WifiManager_ssid "OpenMQTTGateway" //this is the network name of the initial setup access point @@ -106,7 +109,7 @@ const byte subnet[] = { 255, 255, 255, 0 }; //ip adress /*-------------DEFINE THE MODULES YOU WANT BELOW----------------*/ //Addons and module management, comment the Z line and the config file if you don't use -#ifdef ESP8266 // for nodemcu, weemos and esp8266 +#if defined(ESP8266) // for nodemcu, weemos, esp8266, and Arduino mega #define ZgatewayRF "RF" #define ZgatewayRF315 "RF315" #define ZgatewaySRFB "SRFB" @@ -114,6 +117,7 @@ const byte subnet[] = { 255, 255, 255, 0 }; //ip adress #define ZgatewayIR "IR" #define ZgatewayBT "BT" #define Zgateway2G "2G" + #define ZgatewayPilight "Pilight" #define ZactuatorONOFF "ONOFF" #define ZsensorINA226 "INA226" #define ZsensorHCSR501 "HCSR501" @@ -124,28 +128,55 @@ const byte subnet[] = { 255, 255, 255, 0 }; //ip adress #define ZsensorDHT "DHT"// If you uncomment this you can't use I2C due to the fact that I2C use also D1 #define ZgatewayRFM69 "RFM69"// If you uncomment this you can't use RF and BT due to the fact that RF use also D8 and BT use also D6/D7 #define ZsensorGPIOInput "GPIOInput" - #define ZgatewayPilight "Pilight" + #define ZsensorGPIOKeyCode "GPIOKeyCode" + #define jsonPublishing true + #define simplePublishing true #elif ESP32 #define ZgatewayRF "RF" #define ZgatewayRF "RF315" #define ZgatewayRF2 "RF2" //#define Zgateway2G (not tested yet) - //#define ZgatewayIR + #define ZgatewayIR "IR" #define ZgatewayBT "BT" #define ZactuatorONOFF "ONOFF" - //#define ZsensorINA226 - //#define ZsensorHCSR501 - //#define ZsensorADC - //#define ZsensorBH1750 - //#define ZsensorBME280 + #define ZsensorINA226 "INA226" //ESP8266, Arduino, ESP32 + #define ZsensorHCSR501 "HCSR501" //ESP8266, Arduino, ESP32, Sonoff RF Bridge + #define ZsensorADC "ADC" //ESP8266, Arduino, ESP32 + #define ZsensorBH1750 "BH1750" //ESP8266, Arduino, ESP32 + #define ZsensorBME280 "BME280" //ESP8266, Arduino, ESP32 + #define ZsensorTSL2561 "TSL2561" + #define ZsensorDHT "DHT" + #define ZgatewayRFM69 "RFM69" + #define ZsensorGPIOInput "GPIOInput" + #define ZsensorGPIOKeyCode "GPIOKeyCode" + #define jsonPublishing true + #define simplePublishing true +#elif defined(__AVR_ATmega1280__) + #define ZgatewayRF "RF" + #define ZgatewayRF315 "RF315" + #define ZgatewaySRFB "SRFB" + #define ZgatewayRF2 "RF2" + #define ZgatewayIR "IR" + #define ZgatewayBT "BT" + #define Zgateway2G "2G" + //#define ZgatewayPilight "Pilight" + #define ZactuatorONOFF "ONOFF" + #define ZsensorINA226 "INA226" + #define ZsensorHCSR501 "HCSR501" + #define ZsensorADC "ADC" + #define ZsensorBH1750 "BH1750" + #define ZsensorBME280 "BME280" + #define ZsensorTSL2561 "TSL2561" #define ZsensorDHT "DHT"// If you uncomment this you can't use I2C due to the fact that I2C use also D1 - //#define ZgatewayRFM69 // If you uncomment this you can't use RF and BT due to the fact that RF use also D8 and BT use also D6/D7 - //#define ZsensorGPIOInput "GPIOInput" //untested -#else // for arduino mega + W5100 + #define ZgatewayRFM69 "RFM69"// If you uncomment this you can't use RF and BT due to the fact that RF use also D8 and BT use also D6/D7 + #define ZsensorGPIOInput "GPIOInput" + #define ZsensorGPIOKeyCode "GPIOKeyCode" + #define jsonPublishing true + #define simplePublishing true +#else // for arduino Uno #define ZgatewayRF "RF" //#define Zgateway2G (not tested yet) //#define ZgatewayRF2 // too big for UNO - //#define ZgatewayRFM69 not tested //#define ZgatewayIR //#define ZgatewayBT //#define ZactuatorONOFF @@ -155,8 +186,11 @@ const byte subnet[] = { 255, 255, 255, 0 }; //ip adress //#define ZsensorBME280 //#define ZsensorHCSR501 //#define ZsensorADC - //#define ZgatewayRFM69 not tested + //#define ZgatewayRFM69 //not tested //#define ZsensorGPIOInput //not tested + //#define ZsensorGPIOKeyCode "GPIOKeyCode" //not tested + #define jsonPublishing true + //#define simplePublishing true #endif /*----------------------------OTHER PARAMETERS-----------------------------*/ #ifdef ZgatewaySRFB @@ -170,14 +204,17 @@ const byte subnet[] = { 255, 255, 255, 0 }; //ip adress #define subjectMQTTtoX Base_Topic Gateway_Name "/commands/#" #define subjectMultiGTWKey "toMQTT" +#define valueAsASubject true + //variables to avoid duplicates #define time_avoid_duplicate 3000 // if you want to avoid duplicate mqtt message received set this to > 0, the value is the time in milliseconds during which we don't publish duplicates #ifdef ESP32 //#define multiCore //uncomment to use multicore function of ESP32 for BLE #endif +#define JSON_MSG_BUFFER 256 // Json message max buffer size, don't put 1024 or higher it is causing unexpected behaviour on ESP8266 #define TimeBetweenReadingSYS 30000 // time between system readings (like memory) #define subjectSYStoMQTT Base_Topic Gateway_Name "/SYStoMQTT" /*-------------------ACTIVATE TRACES----------------------*/ -#define TRACE 1 // 0= trace off 1 = trace on +#define TRACE 0 // 0= trace off 1 = trace on