add: foreign key support in database
add: more tests fix: bad tag handling when finding 0 in column
This commit is contained in:
		
							parent
							
								
									7f3182ee96
								
							
						
					
					
						commit
						1475f605aa
					
				
					 14 changed files with 214 additions and 276 deletions
				
			
		| 
						 | 
					@ -1,52 +0,0 @@
 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <netdb.h>
 | 
					 | 
				
			||||||
#include <sys/socket.h>
 | 
					 | 
				
			||||||
#include <sys/types.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <logger.h>
 | 
					 | 
				
			||||||
#include <helpers.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
helper_bind_tcp_server(char* addr, uint16_t port, int max_client_backlog)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    char port_str[6];
 | 
					 | 
				
			||||||
    sprintf(port_str, "%d", port);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    struct addrinfo hints, *res;
 | 
					 | 
				
			||||||
    int fd;
 | 
					 | 
				
			||||||
    int status;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    memset(&hints, 0, sizeof hints);
 | 
					 | 
				
			||||||
    hints.ai_family = AF_UNSPEC;
 | 
					 | 
				
			||||||
    hints.ai_socktype = SOCK_STREAM;
 | 
					 | 
				
			||||||
    hints.ai_flags = AI_PASSIVE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if ((status = getaddrinfo(addr, port_str, &hints, &res)) != 0)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        LOG_ERROR("getaddrinfo: %s\n", gai_strerror(status));
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if ((status = bind(fd, res->ai_addr, res->ai_addrlen)) == -1)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        LOG_ERROR("error binding socket: %s\n", strerror(errno));
 | 
					 | 
				
			||||||
        freeaddrinfo(res);
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if ((status = listen(fd, max_client_backlog)) == -1)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        LOG_ERROR("error setting up listener: %s\n", strerror(errno));
 | 
					 | 
				
			||||||
        freeaddrinfo(res);
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    freeaddrinfo(res);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return fd;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,24 +0,0 @@
 | 
				
			||||||
#include <sys/socket.h>
 | 
					 | 
				
			||||||
#include <arpa/inet.h>
 | 
					 | 
				
			||||||
#include <stdint.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <helpers.h>
 | 
					 | 
				
			||||||
#include <logger.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
uint16_t
 | 
					 | 
				
			||||||
helper_get_port(int sock)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    struct sockaddr_in sin;
 | 
					 | 
				
			||||||
    socklen_t len = sizeof(sin);
 | 
					 | 
				
			||||||
    if (getsockname(sock, (struct sockaddr *)&sin, &len) == -1)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        LOG_ERROR("could not get socket name for port: %s\n", strerror(errno));
 | 
					 | 
				
			||||||
        return 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return ntohs(sin.sin_port);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,57 +0,0 @@
 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <netdb.h>
 | 
					 | 
				
			||||||
#include <sys/socket.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <logger.h>
 | 
					 | 
				
			||||||
#include <helpers.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
helper_open_discovery_socket(uint16_t discovery_port)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    struct addrinfo hints, *res;
 | 
					 | 
				
			||||||
    int fd, status;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    memset(&hints, 0, sizeof hints);
 | 
					 | 
				
			||||||
    hints.ai_family = AF_INET; // use ipv4
 | 
					 | 
				
			||||||
    hints.ai_socktype = SOCK_DGRAM; //set socket flag
 | 
					 | 
				
			||||||
    hints.ai_flags = AI_PASSIVE; // get my IP
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    char discovery_port_str[6];
 | 
					 | 
				
			||||||
    sprintf(discovery_port_str, "%u", discovery_port);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //get connection info for our computer
 | 
					 | 
				
			||||||
    if ((status = getaddrinfo(NULL, discovery_port_str, &hints, &res)) != 0)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        LOG_FATAL("getaddrinfo: %s\n", gai_strerror(status));
 | 
					 | 
				
			||||||
        freeaddrinfo(res);
 | 
					 | 
				
			||||||
        exit(EXIT_FAILURE);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //creating socket
 | 
					 | 
				
			||||||
    fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
 | 
					 | 
				
			||||||
    int yes = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // lose the pesky "Address already in use" error message
 | 
					 | 
				
			||||||
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        LOG_FATAL("setsockopt: %s\n", strerror(errno));
 | 
					 | 
				
			||||||
        freeaddrinfo(res);
 | 
					 | 
				
			||||||
        exit(EXIT_FAILURE);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (bind(fd, res->ai_addr, res->ai_addrlen) == -1)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        LOG_FATAL("bind: %s\n", strerror(errno));
 | 
					 | 
				
			||||||
        freeaddrinfo(res);
 | 
					 | 
				
			||||||
        exit(EXIT_FAILURE);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    freeaddrinfo(res);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    LOG_INFO("opened discovery socket on port %u\n", discovery_port);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return fd;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -8,24 +8,6 @@
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
helper_connect_tcp_server(char* host, uint16_t port);
 | 
					helper_connect_tcp_server(char* host, uint16_t port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					 | 
				
			||||||
helper_bind_tcp_server(char* addr, uint16_t port, int max_client_backlog);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
uint16_t
 | 
					 | 
				
			||||||
helper_get_port(int sock);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief Open socket for discovery
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Will exit program when unable to open socket.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param discovery_port Port number to listen on for discovery broadcasts
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return Open socket to accept discovery broadcasts on
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
helper_open_discovery_socket(uint16_t discovery_port);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
helper_parse_cli(int argc, const char **argv, config_t *config);
 | 
					helper_parse_cli(int argc, const char **argv, config_t *config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								main.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								main.c
									
										
									
									
									
								
							| 
						 | 
					@ -84,6 +84,8 @@ main(int argc, const char** argv)
 | 
				
			||||||
        terminate(1);
 | 
					        terminate(1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sqlite3_exec(global_database, "PRAGMA foreign_keys = ON", 0, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /******************** INIT ROUTER ********************/
 | 
					    /******************** INIT ROUTER ********************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,8 +15,24 @@ junction_tag_insert(int tag_id, int relay_id, int schedule_id)
 | 
				
			||||||
    sqlite3_prepare_v2(global_database, "INSERT INTO junction_tag(tag_id, schedule_id, relay_id) values (?1, ?2, ?3);", -1, &stmt, NULL);
 | 
					    sqlite3_prepare_v2(global_database, "INSERT INTO junction_tag(tag_id, schedule_id, relay_id) values (?1, ?2, ?3);", -1, &stmt, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sqlite3_bind_int(stmt, 1, tag_id);
 | 
					    sqlite3_bind_int(stmt, 1, tag_id);
 | 
				
			||||||
    sqlite3_bind_int(stmt, 2, schedule_id);
 | 
					
 | 
				
			||||||
    sqlite3_bind_int(stmt, 3, relay_id);
 | 
					    if(schedule_id)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        sqlite3_bind_int(stmt, 2, schedule_id);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        sqlite3_bind_null(stmt, 2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(relay_id)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        sqlite3_bind_int(stmt, 3, relay_id);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        sqlite3_bind_null(stmt, 3);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rc = sqlite3_step(stmt);
 | 
					    rc = sqlite3_step(stmt);
 | 
				
			||||||
    if (rc != SQLITE_DONE)
 | 
					    if (rc != SQLITE_DONE)
 | 
				
			||||||
| 
						 | 
					@ -46,10 +62,13 @@ get_ids(sqlite3_stmt *stmt)
 | 
				
			||||||
        if (s == SQLITE_ROW)
 | 
					        if (s == SQLITE_ROW)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            new_id = sqlite3_column_int(stmt, 0);
 | 
					            new_id = sqlite3_column_int(stmt, 0);
 | 
				
			||||||
            row++;
 | 
					            if(new_id != 0) // found row for other target (relay <> schedule)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                row++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ids = (int*)realloc(ids, sizeof(int) * (row + 1));
 | 
					                ids = (int*)realloc(ids, sizeof(int) * (row + 1));
 | 
				
			||||||
            ids[row - 1] = new_id;
 | 
					                ids[row - 1] = new_id;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -236,7 +236,7 @@ relay_to_json(relay_t *relay)
 | 
				
			||||||
    controller_t *controller = controller_get_by_id(relay->controller_id);
 | 
					    controller_t *controller = controller_get_by_id(relay->controller_id);
 | 
				
			||||||
    if(!controller)
 | 
					    if(!controller)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        LOG_DEBUG("failed to get controller\n");
 | 
					        LOG_WARN("failed to get controller\n");
 | 
				
			||||||
        cJSON_Delete(json);
 | 
					        cJSON_Delete(json);
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,7 @@ create table relays
 | 
				
			||||||
    controller_id   INTEGER
 | 
					    controller_id   INTEGER
 | 
				
			||||||
                    NOT NULL
 | 
					                    NOT NULL
 | 
				
			||||||
                    REFERENCES controllers (id)
 | 
					                    REFERENCES controllers (id)
 | 
				
			||||||
 | 
					                    ON DELETE CASCADE
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
create table schedules
 | 
					create table schedules
 | 
				
			||||||
| 
						 | 
					@ -59,11 +60,14 @@ create table junction_tag
 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
    tag_id          INTEGER
 | 
					    tag_id          INTEGER
 | 
				
			||||||
                    NOT NULL
 | 
					                    NOT NULL
 | 
				
			||||||
                    REFERENCES tags (id),
 | 
					                    REFERENCES tags (id)
 | 
				
			||||||
 | 
					                    ON DELETE CASCADE,
 | 
				
			||||||
    relay_id        INTEGER
 | 
					    relay_id        INTEGER
 | 
				
			||||||
                    REFERENCES relays (id),
 | 
					                    REFERENCES relays (id)
 | 
				
			||||||
 | 
					                    ON DELETE CASCADE,
 | 
				
			||||||
    schedule_id     INTEGER
 | 
					    schedule_id     INTEGER
 | 
				
			||||||
                    REFERENCES schedules (id)
 | 
					                    REFERENCES schedules (id)
 | 
				
			||||||
 | 
					                    ON DELETE CASCADE
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
create table junction_relay_schedule
 | 
					create table junction_relay_schedule
 | 
				
			||||||
| 
						 | 
					@ -71,11 +75,12 @@ create table junction_relay_schedule
 | 
				
			||||||
    weekday         SMALLINT
 | 
					    weekday         SMALLINT
 | 
				
			||||||
                    NOT NULL,
 | 
					                    NOT NULL,
 | 
				
			||||||
    relay_id        INTEGER
 | 
					    relay_id        INTEGER
 | 
				
			||||||
                    NOT NULL
 | 
					                    REFERENCES relays (id)
 | 
				
			||||||
                    REFERENCES relays (id),
 | 
					                    ON DELETE CASCADE,
 | 
				
			||||||
    schedule_id     INTEGER
 | 
					    schedule_id     INTEGER
 | 
				
			||||||
                    NOT NULL
 | 
					                    DEFAULT 1
 | 
				
			||||||
                    REFERENCES schedules (id)
 | 
					                    REFERENCES schedules (id)
 | 
				
			||||||
 | 
					                    ON DELETE SET DEFAULT
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
INSERT INTO schedules (uid, name, periods) VALUES (x'6f666600000000000000000000000000', 'off', x'00');
 | 
					INSERT INTO schedules (uid, name, periods) VALUES (x'6f666600000000000000000000000000', 'off', x'00');
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,18 +7,12 @@ stages:
 | 
				
			||||||
    url: "http://localhost:5000/api/v1/controllers/discover/"
 | 
					    url: "http://localhost:5000/api/v1/controllers/discover/"
 | 
				
			||||||
  response:
 | 
					  response:
 | 
				
			||||||
    status_code: 200
 | 
					    status_code: 200
 | 
				
			||||||
    json:
 | 
					    verify_response_with:
 | 
				
			||||||
    - id: !anystr
 | 
					      function: validate_controller:multiple
 | 
				
			||||||
      name: !anystr
 | 
					 | 
				
			||||||
      relay_count: !anyint
 | 
					 | 
				
			||||||
      relays: !anystr
 | 
					 | 
				
			||||||
      active: !anybool
 | 
					 | 
				
			||||||
      port: !anyint
 | 
					 | 
				
			||||||
      ip: !anystr
 | 
					 | 
				
			||||||
      relays: !anylist
 | 
					 | 
				
			||||||
    save:
 | 
					    save:
 | 
				
			||||||
      json:
 | 
					      json:
 | 
				
			||||||
        returned_id: "[0].id"
 | 
					        returned_id: "[0].id"
 | 
				
			||||||
 | 
					        returned_relay_count: "[0].relay_count"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- name: "[controller_relays_basic] get controller relays, check length"
 | 
					- name: "[controller_relays_basic] get controller relays, check length"
 | 
				
			||||||
  request:
 | 
					  request:
 | 
				
			||||||
| 
						 | 
					@ -26,71 +20,11 @@ stages:
 | 
				
			||||||
    url: "http://localhost:5000/api/v1/controllers/{returned_id}/relays"
 | 
					    url: "http://localhost:5000/api/v1/controllers/{returned_id}/relays"
 | 
				
			||||||
  response:
 | 
					  response:
 | 
				
			||||||
    status_code: 200
 | 
					    status_code: 200
 | 
				
			||||||
    json:
 | 
					    verify_response_with:
 | 
				
			||||||
    - name: !anystr
 | 
					      function: validate_relay:multiple
 | 
				
			||||||
      number: 0
 | 
					      function: validate_relay:relay_count
 | 
				
			||||||
      controller_id: "{returned_id}"
 | 
					      extra_kwargs:
 | 
				
			||||||
      active_schedule:
 | 
					        relay_count: !int "{returned_relay_count:d}"
 | 
				
			||||||
        id: !anystr
 | 
					 | 
				
			||||||
        name: !anystr
 | 
					 | 
				
			||||||
        periods: !anylist
 | 
					 | 
				
			||||||
        tags: !anylist
 | 
					 | 
				
			||||||
      schedules: !anylist
 | 
					 | 
				
			||||||
      tags: !anylist
 | 
					 | 
				
			||||||
    - name: !anystr
 | 
					 | 
				
			||||||
      number: 1
 | 
					 | 
				
			||||||
      controller_id: "{returned_id}"
 | 
					 | 
				
			||||||
      active_schedule: !anydict
 | 
					 | 
				
			||||||
      schedules: !anylist
 | 
					 | 
				
			||||||
      tags: !anylist
 | 
					 | 
				
			||||||
    - name: !anystr
 | 
					 | 
				
			||||||
      number: 2
 | 
					 | 
				
			||||||
      controller_id: "{returned_id}"
 | 
					 | 
				
			||||||
      active_schedule: !anydict
 | 
					 | 
				
			||||||
      schedules: !anylist
 | 
					 | 
				
			||||||
      tags: !anylist
 | 
					 | 
				
			||||||
    - name: !anystr
 | 
					 | 
				
			||||||
      number: 3
 | 
					 | 
				
			||||||
      controller_id: "{returned_id}"
 | 
					 | 
				
			||||||
      active_schedule: !anydict
 | 
					 | 
				
			||||||
      schedules: !anylist
 | 
					 | 
				
			||||||
      tags: !anylist
 | 
					 | 
				
			||||||
    - name: !anystr
 | 
					 | 
				
			||||||
      number: 4
 | 
					 | 
				
			||||||
      controller_id: "{returned_id}"
 | 
					 | 
				
			||||||
      active_schedule: !anydict
 | 
					 | 
				
			||||||
      schedules: !anylist
 | 
					 | 
				
			||||||
      tags: !anylist
 | 
					 | 
				
			||||||
    - name: !anystr
 | 
					 | 
				
			||||||
      number: 5
 | 
					 | 
				
			||||||
      controller_id: "{returned_id}"
 | 
					 | 
				
			||||||
      active_schedule: !anydict
 | 
					 | 
				
			||||||
      schedules: !anylist
 | 
					 | 
				
			||||||
      tags: !anylist
 | 
					 | 
				
			||||||
    - name: !anystr
 | 
					 | 
				
			||||||
      number: 6
 | 
					 | 
				
			||||||
      controller_id: "{returned_id}"
 | 
					 | 
				
			||||||
      active_schedule: !anydict
 | 
					 | 
				
			||||||
      schedules: !anylist
 | 
					 | 
				
			||||||
      tags: !anylist
 | 
					 | 
				
			||||||
    - name: !anystr
 | 
					 | 
				
			||||||
      number: 7
 | 
					 | 
				
			||||||
      controller_id: "{returned_id}"
 | 
					 | 
				
			||||||
      active_schedule: !anydict
 | 
					 | 
				
			||||||
      schedules: !anylist
 | 
					 | 
				
			||||||
      tags: !anylist
 | 
					 | 
				
			||||||
    - name: !anystr
 | 
					 | 
				
			||||||
      number: 8
 | 
					 | 
				
			||||||
      controller_id: "{returned_id}"
 | 
					 | 
				
			||||||
      active_schedule: !anydict
 | 
					 | 
				
			||||||
      schedules: !anylist
 | 
					 | 
				
			||||||
      tags: !anylist
 | 
					 | 
				
			||||||
    - name: !anystr
 | 
					 | 
				
			||||||
      number: 9
 | 
					 | 
				
			||||||
      controller_id: "{returned_id}"
 | 
					 | 
				
			||||||
      active_schedule: !anydict
 | 
					 | 
				
			||||||
      schedules: !anylist
 | 
					 | 
				
			||||||
      tags: !anylist
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
- name: "[controller_relays_basic] get controller relays, check length"
 | 
					- name: "[controller_relays_basic] get controller relays, check length"
 | 
				
			||||||
  request:
 | 
					  request:
 | 
				
			||||||
| 
						 | 
					@ -98,42 +32,11 @@ stages:
 | 
				
			||||||
    url: "http://localhost:5000/api/v1/controllers/{returned_id}/relays/5"
 | 
					    url: "http://localhost:5000/api/v1/controllers/{returned_id}/relays/5"
 | 
				
			||||||
  response:
 | 
					  response:
 | 
				
			||||||
    status_code: 200
 | 
					    status_code: 200
 | 
				
			||||||
    json:
 | 
					    verify_response_with:
 | 
				
			||||||
      name: !anystr
 | 
					      function: validate_relay:single
 | 
				
			||||||
      number: 5
 | 
					      function: validate_relay:check_controller_id
 | 
				
			||||||
      controller_id: "{returned_id}"
 | 
					      extra_kwargs:
 | 
				
			||||||
      active_schedule:
 | 
					        name: "{returned_id}"
 | 
				
			||||||
        id: !anystr
 | 
					      function: validate_relay:check_number
 | 
				
			||||||
        name: !anystr
 | 
					      extra_kwargs:
 | 
				
			||||||
        periods: !anylist
 | 
					        number: 5
 | 
				
			||||||
        tags: !anylist
 | 
					 | 
				
			||||||
      schedules: 
 | 
					 | 
				
			||||||
      - id: !anystr
 | 
					 | 
				
			||||||
        name: !anystr
 | 
					 | 
				
			||||||
        periods: !anylist
 | 
					 | 
				
			||||||
        tags: !anylist
 | 
					 | 
				
			||||||
      - id: !anystr
 | 
					 | 
				
			||||||
        name: !anystr
 | 
					 | 
				
			||||||
        periods: !anylist
 | 
					 | 
				
			||||||
        tags: !anylist
 | 
					 | 
				
			||||||
      - id: !anystr
 | 
					 | 
				
			||||||
        name: !anystr
 | 
					 | 
				
			||||||
        periods: !anylist
 | 
					 | 
				
			||||||
        tags: !anylist
 | 
					 | 
				
			||||||
      - id: !anystr
 | 
					 | 
				
			||||||
        name: !anystr
 | 
					 | 
				
			||||||
        periods: !anylist
 | 
					 | 
				
			||||||
        tags: !anylist
 | 
					 | 
				
			||||||
      - id: !anystr
 | 
					 | 
				
			||||||
        name: !anystr
 | 
					 | 
				
			||||||
        periods: !anylist
 | 
					 | 
				
			||||||
        tags: !anylist
 | 
					 | 
				
			||||||
      - id: !anystr
 | 
					 | 
				
			||||||
        name: !anystr
 | 
					 | 
				
			||||||
        periods: !anylist
 | 
					 | 
				
			||||||
        tags: !anylist
 | 
					 | 
				
			||||||
      - id: !anystr
 | 
					 | 
				
			||||||
        name: !anystr
 | 
					 | 
				
			||||||
        periods: !anylist
 | 
					 | 
				
			||||||
        tags: !anylist
 | 
					 | 
				
			||||||
      tags: !anylist
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,3 +44,56 @@ stages:
 | 
				
			||||||
        id: "{returned_id}"
 | 
					        id: "{returned_id}"
 | 
				
			||||||
        name: "{returned_name}"
 | 
					        name: "{returned_name}"
 | 
				
			||||||
        periods: "{returned_periods}"
 | 
					        periods: "{returned_periods}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- name: "[tags] discover controllers"
 | 
				
			||||||
 | 
					  request:
 | 
				
			||||||
 | 
					    method: POST
 | 
				
			||||||
 | 
					    url: "http://localhost:5000/api/v1/controllers/discover/"
 | 
				
			||||||
 | 
					  response:
 | 
				
			||||||
 | 
					    status_code: 200
 | 
				
			||||||
 | 
					    verify_response_with:
 | 
				
			||||||
 | 
					      function: validate_controller:multiple
 | 
				
			||||||
 | 
					    save:
 | 
				
			||||||
 | 
					      json:
 | 
				
			||||||
 | 
					        returned_id: "[0].id"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- name: "[tags] set relay tag"
 | 
				
			||||||
 | 
					  request:
 | 
				
			||||||
 | 
					    method: PUT
 | 
				
			||||||
 | 
					    url: "http://localhost:5000/api/v1/controllers/{returned_id}/relays/3"
 | 
				
			||||||
 | 
					    json:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					      - "test_tag_1"
 | 
				
			||||||
 | 
					  response:
 | 
				
			||||||
 | 
					    status_code: 200
 | 
				
			||||||
 | 
					    verify_response_with:
 | 
				
			||||||
 | 
					      function: validate_relay:single
 | 
				
			||||||
 | 
					      function: validate_relay:check_controller_id
 | 
				
			||||||
 | 
					      extra_kwargs:
 | 
				
			||||||
 | 
					        name: "{returned_id}"
 | 
				
			||||||
 | 
					      function: validate_relay:check_number
 | 
				
			||||||
 | 
					      extra_kwargs:
 | 
				
			||||||
 | 
					        number: 3
 | 
				
			||||||
 | 
					      function: validate_relay:check_tag
 | 
				
			||||||
 | 
					      extra_kwargs:
 | 
				
			||||||
 | 
					        tag: "{tavern.request_vars.json.tags[0]}"
 | 
				
			||||||
 | 
					    save:
 | 
				
			||||||
 | 
					      json:
 | 
				
			||||||
 | 
					        returned_name: "name"
 | 
				
			||||||
 | 
					        returned_number: "number"
 | 
				
			||||||
 | 
					        returned_tag: "tags[0]"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- name: "[tags] get relay, check name and number"
 | 
				
			||||||
 | 
					  request:
 | 
				
			||||||
 | 
					    method: GET
 | 
				
			||||||
 | 
					    url: "http://localhost:5000/api/v1/relays/tag/{returned_tag}"
 | 
				
			||||||
 | 
					  response:
 | 
				
			||||||
 | 
					    status_code: 200
 | 
				
			||||||
 | 
					    verify_response_with:
 | 
				
			||||||
 | 
					      function: validate_relay:multiple
 | 
				
			||||||
 | 
					      function: validate_relay:find
 | 
				
			||||||
 | 
					      extra_kwargs:
 | 
				
			||||||
 | 
					        name: "{returned_name}"
 | 
				
			||||||
 | 
					        number: !int "{returned_number:d}"
 | 
				
			||||||
 | 
					        controller_id: "{returned_id}"
 | 
				
			||||||
 | 
					        tag: "{returned_tag}"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/tavern_utils/__pycache__/validate_relay.cpython-38.pyc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/tavern_utils/__pycache__/validate_relay.cpython-38.pyc
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										41
									
								
								tests/tavern_utils/validate_controller.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								tests/tavern_utils/validate_controller.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,41 @@
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					import validate_relay
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _verify_single(controller):
 | 
				
			||||||
 | 
					    assert isinstance(controller.get("id"), str), "controller id is not a string"
 | 
				
			||||||
 | 
					    assert isinstance(controller.get("name"), str), "controller name is not a string"
 | 
				
			||||||
 | 
					    assert isinstance(controller.get("relay_count"), int), "controller relay_count is not an integer"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert isinstance(controller.get("relays"), list), "controller relays is not a list"
 | 
				
			||||||
 | 
					    assert len(controller.get("relays")) == controller.get("relay_count"), "controller relay have a length unequal to relay_count"
 | 
				
			||||||
 | 
					    for relay in controller.get("relays"):
 | 
				
			||||||
 | 
					        assert isinstance(relay, dict), "controller relays contain a relay which is not a dict"
 | 
				
			||||||
 | 
					        validate_relay._verify_single(relay)
 | 
				
			||||||
 | 
					        assert relay.get("controller_id") == controller.get("id")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def single(response):
 | 
				
			||||||
 | 
					    _verify_single(response.json())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def multiple(response):
 | 
				
			||||||
 | 
					    assert isinstance(response.json(), list), "response is not a list"
 | 
				
			||||||
 | 
					    for controller in response.json():
 | 
				
			||||||
 | 
					        _verify_single(controller)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def check_id(response, id):
 | 
				
			||||||
 | 
					    assert response.json().get("id") == id, "controller id check failed"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def check_name(response, name):
 | 
				
			||||||
 | 
					    assert response.json().get("name") == name, "controller name check failed"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def find(response, id=None, name=None):
 | 
				
			||||||
 | 
					    for controller in response.json():
 | 
				
			||||||
 | 
					        if id != None and id != schedule.get("id"):
 | 
				
			||||||
 | 
					            print(schedule.get("id"))
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if name != None and name != schedule.get("name"):
 | 
				
			||||||
 | 
					            print(schedule.get("name"))
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    assert False, "controller not found in list"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,2 +1,68 @@
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					import validate_schedule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _verify_single(relay):
 | 
				
			||||||
 | 
					    assert isinstance(relay.get("number"), int), "relay number is not an integer"
 | 
				
			||||||
 | 
					    assert isinstance(relay.get("name"), str), "relay name is not a string"
 | 
				
			||||||
 | 
					    assert isinstance(relay.get("controller_id"), str), "relay controller_id is not a string"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert isinstance(relay.get("active_schedule"), dict), "relay active_schedule is not a dict"
 | 
				
			||||||
 | 
					    validate_schedule._verify_single(relay.get("active_schedule"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert isinstance(relay.get("schedules"), list), "relay schedules is not a list"
 | 
				
			||||||
 | 
					    assert len(relay.get("schedules")) == 7, "relay schedule have a length unequal to 7"
 | 
				
			||||||
 | 
					    for schedule in relay.get("schedules"):
 | 
				
			||||||
 | 
					        assert isinstance(relay, dict), "relay schedules contain a schedule which is not a dict"
 | 
				
			||||||
 | 
					        validate_schedule._verify_single(schedule)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert isinstance(relay.get("tags"), list), "relay tags is not a list"
 | 
				
			||||||
 | 
					    for tag in relay.get("tags"):
 | 
				
			||||||
 | 
					        assert isinstance(tag, str), "relay tags contain a tag which is not a string"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def single(response):
 | 
					def single(response):
 | 
				
			||||||
    assert response.json().get("number") >= 0
 | 
					    _verify_single(response.json())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def multiple(response):
 | 
				
			||||||
 | 
					    assert isinstance(response.json(), list), "response is not a list"
 | 
				
			||||||
 | 
					    for relay in response.json():
 | 
				
			||||||
 | 
					        _verify_single(relay)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def relay_count(response, relay_count):
 | 
				
			||||||
 | 
					    assert len(response.json()) == relay_count, "response has invalid length"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def check_number(response, number):
 | 
				
			||||||
 | 
					    assert response.json().get("number") == number, "relay number check failed"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def check_name(response, name):
 | 
				
			||||||
 | 
					    assert response.json().get("name") == name, "relay name check failed"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def check_controller_id(response, controller_id):
 | 
				
			||||||
 | 
					    assert response.json().get("controller_id") == controller_id, "relay controller_id check failed"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def check_tag(response, tag):
 | 
				
			||||||
 | 
					    for response_tag in response.json().get("tags"):
 | 
				
			||||||
 | 
					        if response_tag == tag:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					    assert False, "tag not found in relay,"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def find(response, name=None, number=None, controller_id=None, tag=None):
 | 
				
			||||||
 | 
					    print(response.json())
 | 
				
			||||||
 | 
					    for relay in response.json():
 | 
				
			||||||
 | 
					        if number != None and number != relay.get("number"):
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if name != None and name != relay.get("name"):
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if controller_id != None and controller_id != relay.get("controller_id"):
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if tag != None:
 | 
				
			||||||
 | 
					            found_in_response = False
 | 
				
			||||||
 | 
					            for response_tag in relay.get("tags"):
 | 
				
			||||||
 | 
					                if response_tag == tag:
 | 
				
			||||||
 | 
					                    found_in_response = True
 | 
				
			||||||
 | 
					            if not found_in_response:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    assert False, "relay not found in list"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue