added a mechanism to bump the version

added a test that checks for JSONRPC api changes and enforces a version bump
pull/1/head
Michael Zanetti 2014-05-03 17:22:44 +02:00
parent 7fe317666d
commit c54e289403
7 changed files with 445 additions and 1 deletions

10
guh.pri
View File

@ -1,6 +1,16 @@
guh_version_major = 0
guh_version_minor = 0
guh_version_patch = 1
coverage {
message("Building coverage.")
QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -O0
LIBS += -lgcov
QMAKE_LFLAGS += -fprofile-arcs
}
message("fooooooooo $${guh_version_major} $${MYVAR}")
DEFINES += GUH_VERSION_MAJOR=$$guh_version_major
DEFINES += GUH_VERSION_MINOR=$$guh_version_minor
DEFINES += GUH_VERSION_PATCH=$$guh_version_patch
DEFINES += GUH_VERSION_STRING=\\\"$${guh_version_major}.$${guh_version_minor}.$${guh_version_patch}\\\"

View File

@ -70,6 +70,9 @@ RuleEngine *GuhCore::ruleEngine() const
GuhCore::GuhCore(QObject *parent) :
QObject(parent)
{
qDebug() << "*****************************************";
qDebug() << "* GUH version:" << GUH_VERSION_STRING << "starting up. *";
qDebug() << "*****************************************";
qDebug() << "*****************************************";
qDebug() << "* Creating Device Manager *";

View File

@ -116,7 +116,7 @@ JsonReply* JsonRPCServer::Version(const QVariantMap &params) const
Q_UNUSED(params)
QVariantMap data;
data.insert("version", "0.0.0");
data.insert("version", GUH_VERSION_STRING);
return createReply(data);
}

View File

@ -136,6 +136,7 @@ void JsonTypes::init()
s_device.insert("deviceClassId", "uuid");
s_device.insert("name", "string");
s_device.insert("params", QVariantList() << paramRef());
s_device.insert("setupComplete", "bool");
// DeviceDescription
s_deviceDescriptor.insert("id", "uuid");
@ -346,6 +347,7 @@ QVariantMap JsonTypes::packDevice(Device *device)
params.append(packParam(param));
}
variant.insert("params", params);
variant.insert("setupComplete", device->setupComplete());
return variant;
}

377
tests/auto/api.json Normal file
View File

@ -0,0 +1,377 @@
0.0.1
{
"methods": {
"Actions.ExecuteAction": {
"description": "Execute a single action.",
"params": {
"actionTypeId": "uuid",
"deviceId": "uuid",
"o:params": [
"$ref:Param"
]
},
"returns": {
"errorMessage": "string",
"success": "bool"
}
},
"Devices.AddConfiguredDevice": {
"description": "Add a configured device. Use deviceDescriptorId or deviceParams, depending on the createMethod of the device class.",
"params": {
"deviceClassId": "uuid",
"o:deviceDescriptorId": "uuid",
"o:deviceParams": [
"$ref:Param"
]
},
"returns": {
"errorMessage": "string",
"o:deviceId": "uuid",
"success": "bool"
}
},
"Devices.GetActionTypes": {
"description": "Get action types for a specified deviceClassId.",
"params": {
"deviceClassId": "uuid"
},
"returns": {
"actionTypes": [
"$ref:ActionType"
]
}
},
"Devices.GetConfiguredDevices": {
"description": "Returns a list of configured devices.",
"params": {
},
"returns": {
"devices": [
"$ref:Device"
]
}
},
"Devices.GetDiscoveredDevices": {
"description": "Performs a device discovery and returns the results. This function may take a while to return.",
"params": {
"deviceClassId": "uuid",
"o:discoveryParams": [
"$ref:Param"
]
},
"returns": {
"errorMessage": "string",
"o:deviceDescriptors": [
"$ref:DeviceDescriptor"
],
"success": "bool"
}
},
"Devices.GetEventTypes": {
"description": "Get event types for a specified deviceClassId.",
"params": {
"deviceClassId": "uuid"
},
"returns": {
"eventTypes": [
"$ref:EventType"
]
}
},
"Devices.GetPlugins": {
"description": "Returns a list of loaded plugins.",
"params": {
},
"returns": {
"plugins": [
"$ref:Plugin"
]
}
},
"Devices.GetStateTypes": {
"description": "Get state types for a specified deviceClassId.",
"params": {
"deviceClassId": "uuid"
},
"returns": {
"stateTypes": [
"$ref:StateType"
]
}
},
"Devices.GetStateValue": {
"description": "Get the value of the given device and the given stateType",
"params": {
"deviceId": "uuid",
"stateTypeId": "uuid"
},
"returns": {
"errorMessage": "string",
"o:value": "variant",
"success": "bool"
}
},
"Devices.GetSupportedDevices": {
"description": "Returns a list of supported Device classes, optionally filtered by vendorId.",
"params": {
"o:vendorId": "uuid"
},
"returns": {
"deviceClasses": [
"$ref:DeviceClass"
]
}
},
"Devices.GetSupportedVendors": {
"description": "Returns a list of supported Vendors.",
"params": {
},
"returns": {
"vendors": [
"$ref:Vendor"
]
}
},
"Devices.RemoveConfiguredDevice": {
"description": "Remove a device from the system.",
"params": {
"deviceId": "uuid"
},
"returns": {
"errorMessage": "string",
"success": "bool"
}
},
"Devices.SetPluginConfiguration": {
"description": "Set a plugin's params.",
"params": {
"pluginId": "uuid",
"pluginParams": [
"$ref:ParamType"
]
},
"returns": {
}
},
"JSONRPC.Introspect": {
"description": "Introspect this API.",
"params": {
},
"returns": {
"methods": "object",
"types": "object"
}
},
"JSONRPC.SetNotificationStatus": {
"description": "Enable/Disable notifications for this connections.",
"params": {
"enabled": "bool"
},
"returns": {
"enabled": "bool",
"errorMessage": "string",
"success": "bool"
}
},
"JSONRPC.Version": {
"description": "Version of this Guh/JSONRPC interface.",
"params": {
},
"returns": {
"version": "string"
}
},
"Rules.AddRule": {
"description": "Add a rule",
"params": {
"actions": [
"$ref:Action"
],
"eventDescriptor": "$ref:EventDescriptor"
},
"returns": {
"errorMessage": "string",
"success": "bool"
}
},
"Rules.GetRules": {
"description": "Get all configured rules",
"params": {
},
"returns": {
"rules": [
"$ref:Rule"
]
}
},
"Rules.RemoveRule": {
"description": "Remove a rule",
"params": {
"ruleId": "uuid"
},
"returns": {
}
}
},
"notifications": {
"Devices.StateChanged": {
"description": "Emitted whenever a State of a device changes.",
"params": {
"deviceId": "uuid",
"stateTypeId": "uuid",
"variant": "value"
}
}
},
"types": {
"Action": {
"actionTypeId": "uuid",
"deviceId": "uuid",
"o:params": [
"$ref:Param"
]
},
"ActionType": {
"id": "uuid",
"name": "string",
"params": [
"$ref:ParamType"
]
},
"BasicType": [
"uuid",
"string",
"integer",
"double",
"bool"
],
"CreateMethodType": [
"CreateMethodUser",
"CreateMethodAuto",
"CreateMethodDiscovery"
],
"Device": {
"deviceClassId": "uuid",
"id": "uuid",
"name": "string",
"params": [
"$ref:Param"
],
"setupComplete": "bool"
},
"DeviceClass": {
"actions": [
"$ref:ActionType"
],
"createMethod": "$ref:CreateMethodType",
"events": [
"$ref:EventType"
],
"id": "uuid",
"name": "string",
"params": [
"$ref:ParamType"
],
"setupMethod": "$ref:SetupMethodType",
"states": [
"$ref:StateType"
],
"vendorId": "uuid"
},
"DeviceDescriptor": {
"description": "string",
"id": "uuid",
"title": "string"
},
"Event": {
"deviceId": "uuid",
"eventTypeId": "uuid",
"o:params": [
"$ref:Param"
]
},
"EventDescriptor": {
"deviceId": "uuid",
"eventTypeId": "uuid",
"o:paramDescriptors": [
"$ref:ParamDescriptor"
]
},
"EventType": {
"id": "uuid",
"name": "string",
"params": [
"$ref:ParamType"
]
},
"OperandType": [
"OperandTypeEquals",
"OperandTypeNotEquals",
"OperandTypeLess",
"OperandTypeGreater",
"OperandTypeLessThan",
"OperandTypeGreaterThan"
],
"Param": {
"name": "string",
"value": "$ref:BasicType"
},
"ParamDescriptor": {
"name": "string",
"operand": "$ref:OperandType",
"value": "$ref:BasicType"
},
"ParamType": {
"name": "string",
"o:defaultValue": "variant",
"o:maxValue": "variant",
"o:minValue": "variant",
"type": "$ref:BasicType"
},
"Plugin": {
"id": "uuid",
"name": "string",
"params": [
"$ref:ParamType"
]
},
"Rule": {
"actions": [
"$ref:Action"
],
"eventDescriptors": [
"$ref:EventDescriptor"
],
"id": "uuid",
"ruleType": "$ref:RuleType",
"states": [
"$ref:State"
]
},
"RuleType": [
"RuleTypeMatchAll",
"RuleTypeMatchAny"
],
"SetupMethodType": [
"SetupMethodJustAdd",
"SetupMethodDisplayPin",
"SetupMethodEnterPin",
"SetupMethodPushButton"
],
"State": {
"deviceId": "uuid",
"stateTypeId": "uuid",
"value": "variant"
},
"StateType": {
"defaultValue": "variant",
"id": "uuid",
"name": "string",
"type": "$ref:BasicType"
},
"Vendor": {
"id": "uuid",
"name": "string"
}
}
}

View File

@ -4,6 +4,7 @@ TARGET = guhtests
QT += testlib network
CONFIG += testcase c++11
DEFINES += TESTING_ENABLED
DEFINES += TESTS_SOURCE_DIR=\\\"$$top_srcdir/tests/auto/\\\"
INCLUDEPATH += $$top_srcdir/server/ $$top_srcdir/server/jsonrpc $$top_srcdir/libguh $$top_srcdir/tests/auto/
LIBS += -L$$top_builddir/libguh/ -lguh

View File

@ -26,6 +26,7 @@
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QCoreApplication>
Q_IMPORT_PLUGIN(DevicePluginMock)
@ -83,6 +84,8 @@ private slots:
void getRules();
void apiChangeBumpsVersion();
private:
QVariant injectAndWait(const QString &method, const QVariantMap &params);
QStringList extractRefs(const QVariant &variant);
@ -601,5 +604,53 @@ void TestJSONRPC::getRules()
qDebug() << "got rules response" << response;
}
void TestJSONRPC::apiChangeBumpsVersion()
{
QString oldFilePath = QString(TESTS_SOURCE_DIR) + "/api.json";
QString newFilePath = QString(TESTS_SOURCE_DIR) + "/api.json.new";
QVariant response = injectAndWait("JSONRPC.Version", QVariantMap());
QByteArray newVersion = response.toMap().value("params").toMap().value("version").toByteArray();
response = injectAndWait("JSONRPC.Introspect", QVariantMap());
QJsonDocument jsonDoc = QJsonDocument::fromVariant(response.toMap().value("params"));
QByteArray newApi = jsonDoc.toJson();
QFile oldApiFile(oldFilePath);
QVERIFY(oldApiFile.exists() && oldApiFile.open(QIODevice::ReadOnly));
QByteArray oldVersion = oldApiFile.readLine().trimmed();
QByteArray oldApi = oldApiFile.readAll();
qDebug() << "version" << oldVersion << newVersion;
if (oldVersion == newVersion && oldApi == newApi) {
// All fine. no changes
return;
}
if (oldVersion == newVersion && oldApi != newApi) {
QVERIFY2(false, "JSONRPC API has changed but version is still the same. You need to bump the API version.");
}
QFile newApiFile(newFilePath);
QVERIFY(newApiFile.open(QIODevice::ReadWrite));
if (newApiFile.size() > 0) {
newApiFile.resize(0);
}
newApiFile.write(newVersion + '\n');
newApiFile.write(newApi);
newApiFile.flush();
QProcess p;
p.execute("diff", QStringList() << "-u" << oldFilePath << newFilePath);
p.waitForFinished();
qDebug() << p.readAll();
QVERIFY2(false, QString("JSONRPC API has changed. Update %1.").arg(oldFilePath).toLatin1().data());
}
QTEST_MAIN(TestJSONRPC)
#include "testjsonrpc.moc"