Improve REST API testing system (#4403)

main
Kirill Sizov 4 years ago committed by GitHub
parent be334fdee9
commit 6dd73b0576
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -532,6 +532,8 @@ class FloatArrayField(models.TextField):
def from_db_value(self, value, expression, connection):
if not value:
return value
if value.startswith('[') and value.endswith(']'):
value = value[1:-1]
return [float(v) for v in value.split(self.separator)]
def to_python(self, value):

@ -40,8 +40,8 @@ procedure to add them:
1. Backup DB and data volume using commands below
1. Don't forget to dump new objects into corresponding json files inside
assets directory
1. Commit cvat_data.tar.bz2 and cvat_db.sql into git. Be sure that they are
small enough: ~200K-400K together.
1. Commit cvat_data.tar.bz2 and data.json into git. Be sure that they are
small enough: ~300K together.
It is recommended to use dummy and tiny images. You can generate them using
Pillow library. See a sample code below:
@ -63,10 +63,13 @@ for i, color in enumerate(colormap):
To backup DB and data volume, please use commands below.
```console
docker exec cvat_db pg_dump -c -Fp -U root -d cvat > assets/cvat_db/cvat_db.sql
docker run --rm --volumes-from cvat ubuntu tar -cjv /home/django/data > assets/cvat_data.tar.bz2
docker exec cvat python manage.py dumpdata --indent 2 > assets/cvat_db/data.json
docker exec cvat tar -cjv /home/django/data > assets/cvat_db/cvat_data.tar.bz2
```
> Note: if you won't be use --indent options or will be use with other value
> it potentially will lead to problems with merging of this file with other branch.
## How to update *.json files in the assets directory?
If you have updated the test database and want to update the assets/*.json
@ -81,19 +84,38 @@ python utils/dump_objects.py
To restore DB and data volume, please use commands below.
```console
cat assets/cvat_db/cvat_db.sql | docker exec -i cvat_db psql -U root -d cvat
cat assets/cvat_data.tar.bz2 | docker run --rm -i --volumes-from cvat ubuntu tar -xj --strip 3 -C /home/django/data
cat assets/cvat_db/data.json | docker exec -i cvat python manage.py --format=json loaddata -
cat assets/cvat_db/cvat_data.tar.bz2 | docker exec -i cvat tar --strip 3 -C /home/django/data/ -xj
```
## Assets directory structure
Assets directory has two parts:
- `cvat_db` directory --- this directory contains all necessary files for
successful restoring of test db
- `cvat_data.tar.bz2` --- archieve with data volumes;
- `data.json` --- file required for DB restoring.
Contains all information about test db;
- `restore.sql` --- SQL script for creating copy of database and
killing connection for `cvat` database.
Script should be run with varialbe declaration:
```
# create database <new> with template <existing>
psql -U root -d postgres -v from=<existing> -v to=<new> restore.sql
```
- `*.json` files --- these file contains all necessary data for getting
expected results from HTTP responses
## FAQ
1. How to merge two DB dumps?
It can be critical if several developers add new tests in parallel. But if
you have json description of all objects together with cvat_db.sql, it will
be possible to recreate them manually.
In common case it should be easy just to merge two JSON files.
But in the case when a simple merge fails, you have to first merge
the branches, then re-create the changes that you made.
1. How to upgrade cvat_data.tar.bz2 and cvat_db.sql?
1. How to upgrade cvat_data.tar.bz2 and data.json?
After every commit which changes the layout of DB and data directory it is
possible to break these files. But failed tests should be a clear indicator
@ -111,3 +133,63 @@ cat assets/cvat_data.tar.bz2 | docker run --rm -i --volumes-from cvat ubuntu tar
Since some tests change the database, these tests may be dependent on each
other, so in current implementation we avoid such problem by restoring
the database after each test function (see `conftest.py`)
1. Which user should be selected to create new resources in test DB?
If for your test it's no matter what user should send a request,
then better to choose `admin1` user for creating new resource.
## Troubleshooting
1. If your test session was exit with message:
```
_pytest.outcomes.Exit: Command failed: ... Add `-s` option to see more details.
```
Rerun tests to see error messages:
```
pytest ./tests/rest_api -s
```
1. If your tests was failed due to date field incompatibility and you have
error message like this:
```
assert {'values_chan...34.908528Z'}}} == {}
E Left contains 1 more item:
E {'values_changed': {"root['results'][0]['updated_date']": {'new_value': '2022-03-05T08:52:34.908000Z',
E 'old_value': '2022-03-05T08:52:34.908528Z'}}}
E Use -v to get the full diff
```
Just dump JSON assets with:
```
python3 tests/rest_api/utils/dump_objests.py
```
1. If your test infrastructure has been corrupted and you have errors during db restoring.
You should to create (or recreate) `cvat` database:
```
docker exec cvat_db dropdb --if-exists cvat
docker exec cvat_db createdb cvat
docker exec cvat python manage.py migrate
```
1. Perform migrate when some relation does not exists. Example of error message:
```
django.db.utils.ProgrammingError: Problem installing fixture '/data.json': Could not load admin.LogEntry(pk=1): relation "django_admin_log" does not exist`
```
Solution:
```
docker exec cvat python manage.py migrate
```
1. If for some reason you need to recreate cvat database, but using `dropdb`
you have error message:
```
ERROR: database "cvat" is being accessed by other users
DETAIL: There are 1 other session(s) using the database.
```
In this case you should terminate all existent connections for cvat database,
you can perform it with command:
```
docker exec cvat_db psql -U root -d postgres -v from=cvat -v to=test_db -f restore.sql
```

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

@ -2,6 +2,7 @@ SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'cvat' AND pid <> pg_backend_pid();
DROP DATABASE cvat;
DROP DATABASE IF EXISTS :to;
CREATE DATABASE :to WITH TEMPLATE :from;
CREATE DATABASE cvat WITH TEMPLATE test_db;

@ -4,7 +4,7 @@
"previous": null,
"results": [
{
"created_date": "2022-02-24T21:29:21.978055Z",
"created_date": "2022-02-24T21:29:21.978000Z",
"key": "Fi3WRUhFxTWpMiVpdwNR2CGyhgcIXSCUYgPCugPq72QUOgHz9NSMOGiKS3PfJ7Ql",
"organization": 2,
"owner": {
@ -24,7 +24,7 @@
}
},
{
"created_date": "2022-01-19T13:54:42.015131Z",
"created_date": "2022-01-19T13:54:42.015000Z",
"key": "BrwoDmMNQQ1v9WXOukp9DwQVuqB3RDPjpUECCEq6QcAuG0Pi8k1IYtQ9uz9jg0Bv",
"organization": 2,
"owner": {
@ -44,7 +44,7 @@
}
},
{
"created_date": "2022-01-19T13:54:42.005381Z",
"created_date": "2022-01-19T13:54:42.005000Z",
"key": "5FjIXya6fTGvlRpauFvi2QN1wDOqo1V9REB5rJinDR8FZO9gr0qmtWpghsCte8Y1",
"organization": 2,
"owner": {
@ -64,7 +64,7 @@
}
},
{
"created_date": "2021-12-14T19:55:13.745912Z",
"created_date": "2021-12-14T19:55:13.745000Z",
"key": "h43G28di7vfs4Jv5VrKZ26xvGAfm6Yc2FFv14z9EKhiuIEDQ22pEnzmSCab8MnK1",
"organization": 2,
"owner": {
@ -84,7 +84,7 @@
}
},
{
"created_date": "2021-12-14T19:54:56.431899Z",
"created_date": "2021-12-14T19:54:56.431000Z",
"key": "mFpVV2Yh39uUdU8IpigSxvuPegqi8sjxFi6P9Jdy6fBE8Ky9Juzi1KjeGDQsizSS",
"organization": 2,
"owner": {
@ -104,7 +104,7 @@
}
},
{
"created_date": "2021-12-14T19:54:46.172754Z",
"created_date": "2021-12-14T19:54:46.172000Z",
"key": "62HplmGPJuzpTXSyzPWiAlREkq8smCjK30GdtYze3q03J9X5ghQe3oMhlAyQ0WBH",
"organization": 2,
"owner": {
@ -124,7 +124,7 @@
}
},
{
"created_date": "2021-12-14T19:54:33.591399Z",
"created_date": "2021-12-14T19:54:33.591000Z",
"key": "Y1I4FFU27WRqq2rWQLtKjDztMqpvqW7gJgg7q73F7oE4H5kukvXugWjiTLHclPDu",
"organization": 2,
"owner": {
@ -144,7 +144,7 @@
}
},
{
"created_date": "2021-12-14T18:48:46.579536Z",
"created_date": "2021-12-14T18:48:46.579000Z",
"key": "cbmm587Z05WQUYvesIZUCtbTl7CEL4thv1Au6Nr51psflITn9X6BsvNFXcNEkoYn",
"organization": 1,
"owner": {
@ -164,7 +164,7 @@
}
},
{
"created_date": "2021-12-14T18:47:49.322807Z",
"created_date": "2021-12-14T18:47:49.322000Z",
"key": "aViZkw9TaieLoZaswEnkMy8tTet1yYDRof3eKZDtZaHf1BItgCNNM6y6fnjrkrej",
"organization": 1,
"owner": {
@ -184,7 +184,7 @@
}
},
{
"created_date": "2021-12-14T18:47:39.935203Z",
"created_date": "2021-12-14T18:47:39.935000Z",
"key": "Lzyzgo161I7Fej1vC5RXPdyUgCBfbuxsEEhHYeYOJqvbeJe5clPDnqCm7pKOC9tr",
"organization": 1,
"owner": {

@ -1,131 +1,88 @@
{
"count": 9,
"count": 10,
"next": null,
"previous": null,
"results": [
{
"assignee": null,
"bug_tracker": null,
"assignee": {
"first_name": "Worker",
"id": 7,
"last_name": "Second",
"url": "http://localhost:8080/api/users/7",
"username": "worker2"
},
"bug_tracker": "",
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"dimension": "2d",
"id": 9,
"id": 16,
"labels": [
{
"attributes": [],
"color": "#6080c0",
"id": 11,
"id": 7,
"name": "cat"
},
{
"attributes": [],
"color": "#406040",
"id": 12,
"id": 8,
"name": "dog"
}
],
"mode": "annotation",
"project_id": null,
"project_id": 2,
"stage": "annotation",
"start_frame": 0,
"state": "in progress",
"status": "annotation",
"stop_frame": 10,
"task_id": 7,
"url": "http://localhost:8080/api/jobs/9"
"task_id": 11,
"url": "http://localhost:8080/api/jobs/16"
},
{
"assignee": null,
"bug_tracker": null,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"dimension": "3d",
"id": 8,
"labels": [
{
"attributes": [],
"color": "#2080c0",
"id": 10,
"name": "car"
}
],
"mode": "annotation",
"project_id": null,
"stage": "annotation",
"start_frame": 0,
"state": "new",
"status": "annotation",
"stop_frame": 0,
"task_id": 6,
"url": "http://localhost:8080/api/jobs/8"
},
{
"assignee": {
"first_name": "Worker",
"id": 9,
"last_name": "Fourth",
"url": "http://localhost:8080/api/users/9",
"username": "worker4"
},
"bug_tracker": null,
"bug_tracker": "",
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"dimension": "2d",
"id": 7,
"id": 14,
"labels": [
{
"attributes": [],
"attributes": [
{
"default_value": "mazda",
"id": 1,
"input_type": "select",
"mutable": false,
"name": "model",
"values": [
"mazda",
"volvo",
"bmw"
]
}
],
"color": "#2080c0",
"id": 9,
"id": 5,
"name": "car"
}
],
"mode": "interpolation",
"project_id": null,
"stage": "annotation",
"start_frame": 0,
"state": "in progress",
"status": "annotation",
"stop_frame": 24,
"task_id": 5,
"url": "http://localhost:8080/api/jobs/7"
},
{
"assignee": {
"first_name": "Worker",
"id": 7,
"last_name": "Second",
"url": "http://localhost:8080/api/users/7",
"username": "worker2"
},
"bug_tracker": "",
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"dimension": "2d",
"id": 6,
"labels": [
{
"attributes": [],
"color": "#6080c0",
"id": 7,
"name": "cat"
},
{
"attributes": [],
"color": "#406040",
"id": 8,
"name": "dog"
"color": "#c06060",
"id": 6,
"name": "person"
}
],
"mode": "annotation",
"project_id": 2,
"project_id": 1,
"stage": "annotation",
"start_frame": 0,
"start_frame": 15,
"state": "new",
"status": "annotation",
"stop_frame": 57,
"task_id": 4,
"url": "http://localhost:8080/api/jobs/6"
"stop_frame": 19,
"task_id": 9,
"url": "http://localhost:8080/api/jobs/14"
},
{
"assignee": null,
@ -133,7 +90,7 @@
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"dimension": "2d",
"id": 5,
"id": 13,
"labels": [
{
"attributes": [
@ -164,12 +121,12 @@
"mode": "annotation",
"project_id": 1,
"stage": "acceptance",
"start_frame": 100,
"start_frame": 10,
"state": "new",
"status": "validation",
"stop_frame": 147,
"task_id": 3,
"url": "http://localhost:8080/api/jobs/5"
"stop_frame": 14,
"task_id": 9,
"url": "http://localhost:8080/api/jobs/13"
},
{
"assignee": null,
@ -177,7 +134,7 @@
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"dimension": "2d",
"id": 4,
"id": 12,
"labels": [
{
"attributes": [
@ -208,12 +165,12 @@
"mode": "annotation",
"project_id": 1,
"stage": "validation",
"start_frame": 50,
"start_frame": 5,
"state": "new",
"status": "validation",
"stop_frame": 99,
"task_id": 3,
"url": "http://localhost:8080/api/jobs/4"
"stop_frame": 9,
"task_id": 9,
"url": "http://localhost:8080/api/jobs/12"
},
{
"assignee": null,
@ -221,7 +178,7 @@
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"dimension": "2d",
"id": 3,
"id": 11,
"labels": [
{
"attributes": [
@ -255,71 +212,65 @@
"start_frame": 0,
"state": "in progress",
"status": "annotation",
"stop_frame": 49,
"task_id": 3,
"url": "http://localhost:8080/api/jobs/3"
"stop_frame": 4,
"task_id": 9,
"url": "http://localhost:8080/api/jobs/11"
},
{
"assignee": {
"first_name": "Worker",
"id": 6,
"first_name": "Admin",
"id": 1,
"last_name": "First",
"url": "http://localhost:8080/api/users/6",
"username": "worker1"
"url": "http://localhost:8080/api/users/1",
"username": "admin1"
},
"bug_tracker": null,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"dimension": "2d",
"id": 2,
"id": 10,
"labels": [
{
"attributes": [],
"color": "#2080c0",
"id": 3,
"name": "car"
"color": "#6080c0",
"id": 13,
"name": "cat"
},
{
"attributes": [],
"color": "#c06060",
"id": 4,
"name": "person"
"color": "#406040",
"id": 14,
"name": "dog"
}
],
"mode": "annotation",
"project_id": null,
"stage": "annotation",
"start_frame": 0,
"state": "new",
"state": "in progress",
"status": "annotation",
"stop_frame": 22,
"task_id": 2,
"url": "http://localhost:8080/api/jobs/2"
"stop_frame": 13,
"task_id": 8,
"url": "http://localhost:8080/api/jobs/10"
},
{
"assignee": {
"first_name": "Admin",
"id": 1,
"last_name": "First",
"url": "http://localhost:8080/api/users/1",
"username": "admin1"
},
"assignee": null,
"bug_tracker": null,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"dimension": "2d",
"id": 1,
"id": 9,
"labels": [
{
"attributes": [],
"color": "#6080c0",
"id": 1,
"id": 11,
"name": "cat"
},
{
"attributes": [],
"color": "#406040",
"id": 2,
"id": 12,
"name": "dog"
}
],
@ -327,11 +278,104 @@
"project_id": null,
"stage": "annotation",
"start_frame": 0,
"state": "in progress",
"status": "annotation",
"stop_frame": 10,
"task_id": 7,
"url": "http://localhost:8080/api/jobs/9"
},
{
"assignee": null,
"bug_tracker": null,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"dimension": "3d",
"id": 8,
"labels": [
{
"attributes": [],
"color": "#2080c0",
"id": 10,
"name": "car"
}
],
"mode": "annotation",
"project_id": null,
"stage": "annotation",
"start_frame": 0,
"state": "new",
"status": "annotation",
"stop_frame": 0,
"task_id": 6,
"url": "http://localhost:8080/api/jobs/8"
},
{
"assignee": {
"first_name": "Worker",
"id": 9,
"last_name": "Fourth",
"url": "http://localhost:8080/api/users/9",
"username": "worker4"
},
"bug_tracker": null,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"dimension": "2d",
"id": 7,
"labels": [
{
"attributes": [],
"color": "#2080c0",
"id": 9,
"name": "car"
}
],
"mode": "interpolation",
"project_id": null,
"stage": "annotation",
"start_frame": 0,
"state": "in progress",
"status": "annotation",
"stop_frame": 24,
"task_id": 5,
"url": "http://localhost:8080/api/jobs/7"
},
{
"assignee": {
"first_name": "Worker",
"id": 6,
"last_name": "First",
"url": "http://localhost:8080/api/users/6",
"username": "worker1"
},
"bug_tracker": null,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"dimension": "2d",
"id": 2,
"labels": [
{
"attributes": [],
"color": "#2080c0",
"id": 3,
"name": "car"
},
{
"attributes": [],
"color": "#c06060",
"id": 4,
"name": "person"
}
],
"mode": "annotation",
"project_id": null,
"stage": "annotation",
"start_frame": 0,
"state": "new",
"status": "annotation",
"stop_frame": 129,
"task_id": 1,
"url": "http://localhost:8080/api/jobs/1"
"stop_frame": 22,
"task_id": 2,
"url": "http://localhost:8080/api/jobs/2"
}
]
}

@ -7,7 +7,7 @@
"id": 12,
"invitation": "Fi3WRUhFxTWpMiVpdwNR2CGyhgcIXSCUYgPCugPq72QUOgHz9NSMOGiKS3PfJ7Ql",
"is_active": true,
"joined_date": "2022-02-24T21:29:21.978055Z",
"joined_date": "2022-02-24T21:29:21.978000Z",
"organization": 2,
"role": "worker",
"user": {
@ -22,7 +22,7 @@
"id": 11,
"invitation": "BrwoDmMNQQ1v9WXOukp9DwQVuqB3RDPjpUECCEq6QcAuG0Pi8k1IYtQ9uz9jg0Bv",
"is_active": true,
"joined_date": "2022-01-19T13:54:42.015131Z",
"joined_date": "2022-01-19T13:54:42.015000Z",
"organization": 2,
"role": "maintainer",
"user": {
@ -37,7 +37,7 @@
"id": 10,
"invitation": "5FjIXya6fTGvlRpauFvi2QN1wDOqo1V9REB5rJinDR8FZO9gr0qmtWpghsCte8Y1",
"is_active": true,
"joined_date": "2022-01-19T13:54:42.005381Z",
"joined_date": "2022-01-19T13:54:42.005000Z",
"organization": 2,
"role": "supervisor",
"user": {
@ -52,7 +52,7 @@
"id": 9,
"invitation": "h43G28di7vfs4Jv5VrKZ26xvGAfm6Yc2FFv14z9EKhiuIEDQ22pEnzmSCab8MnK1",
"is_active": true,
"joined_date": "2021-12-14T19:55:13.745912Z",
"joined_date": "2021-12-14T19:55:13.745000Z",
"organization": 2,
"role": "supervisor",
"user": {
@ -67,7 +67,7 @@
"id": 8,
"invitation": "mFpVV2Yh39uUdU8IpigSxvuPegqi8sjxFi6P9Jdy6fBE8Ky9Juzi1KjeGDQsizSS",
"is_active": true,
"joined_date": "2021-12-14T19:54:56.431899Z",
"joined_date": "2021-12-14T19:54:56.431000Z",
"organization": 2,
"role": "worker",
"user": {
@ -82,7 +82,7 @@
"id": 7,
"invitation": "62HplmGPJuzpTXSyzPWiAlREkq8smCjK30GdtYze3q03J9X5ghQe3oMhlAyQ0WBH",
"is_active": true,
"joined_date": "2021-12-14T19:54:46.172754Z",
"joined_date": "2021-12-14T19:54:46.172000Z",
"organization": 2,
"role": "worker",
"user": {
@ -97,7 +97,7 @@
"id": 6,
"invitation": "Y1I4FFU27WRqq2rWQLtKjDztMqpvqW7gJgg7q73F7oE4H5kukvXugWjiTLHclPDu",
"is_active": true,
"joined_date": "2021-12-14T19:54:33.591399Z",
"joined_date": "2021-12-14T19:54:33.591000Z",
"organization": 2,
"role": "maintainer",
"user": {
@ -112,7 +112,7 @@
"id": 5,
"invitation": null,
"is_active": true,
"joined_date": "2021-12-14T19:51:38.667522Z",
"joined_date": "2021-12-14T19:51:38.667000Z",
"organization": 2,
"role": "owner",
"user": {
@ -127,7 +127,7 @@
"id": 4,
"invitation": "cbmm587Z05WQUYvesIZUCtbTl7CEL4thv1Au6Nr51psflITn9X6BsvNFXcNEkoYn",
"is_active": true,
"joined_date": "2021-12-14T18:48:46.579536Z",
"joined_date": "2021-12-14T18:48:46.579000Z",
"organization": 1,
"role": "maintainer",
"user": {
@ -142,7 +142,7 @@
"id": 3,
"invitation": "aViZkw9TaieLoZaswEnkMy8tTet1yYDRof3eKZDtZaHf1BItgCNNM6y6fnjrkrej",
"is_active": true,
"joined_date": "2021-12-14T18:47:49.322807Z",
"joined_date": "2021-12-14T18:47:49.322000Z",
"organization": 1,
"role": "worker",
"user": {
@ -157,7 +157,7 @@
"id": 2,
"invitation": "Lzyzgo161I7Fej1vC5RXPdyUgCBfbuxsEEhHYeYOJqvbeJe5clPDnqCm7pKOC9tr",
"is_active": true,
"joined_date": "2021-12-14T18:47:39.935203Z",
"joined_date": "2021-12-14T18:47:39.935000Z",
"organization": 1,
"role": "worker",
"user": {
@ -172,7 +172,7 @@
"id": 1,
"invitation": null,
"is_active": true,
"joined_date": "2021-12-14T18:45:40.172529Z",
"joined_date": "2021-12-14T18:45:40.172000Z",
"organization": 1,
"role": "owner",
"user": {

@ -3,7 +3,7 @@
"contact": {
"email": "org2@cvat.org"
},
"created_date": "2021-12-14T19:51:38.667522Z",
"created_date": "2021-12-14T19:51:38.667000Z",
"description": "",
"id": 2,
"name": "Organization #2",
@ -15,13 +15,13 @@
"username": "business1"
},
"slug": "org2",
"updated_date": "2021-12-14T19:51:38.667536Z"
"updated_date": "2021-12-14T19:51:38.667000Z"
},
{
"contact": {
"email": "org1@cvat.org"
},
"created_date": "2021-12-14T18:45:40.172529Z",
"created_date": "2021-12-14T18:45:40.172000Z",
"description": "",
"id": 1,
"name": "organization #1",
@ -33,6 +33,6 @@
"username": "user1"
},
"slug": "org1",
"updated_date": "2021-12-14T18:45:40.172542Z"
"updated_date": "2021-12-14T18:45:40.172000Z"
}
]

@ -12,7 +12,7 @@
"username": "user2"
},
"bug_tracker": "",
"created_date": "2021-12-14T19:52:37.278149Z",
"created_date": "2021-12-14T19:52:37.278000Z",
"dimension": "2d",
"id": 2,
"labels": [
@ -40,12 +40,12 @@
},
"status": "annotation",
"task_subsets": [
"train"
"Train"
],
"tasks": [
4
11
],
"updated_date": "2022-02-24T21:32:36.197153Z",
"updated_date": "2022-03-05T10:32:23.813000Z",
"url": "http://localhost:8080/api/projects/2"
},
{
@ -57,7 +57,7 @@
"username": "user6"
},
"bug_tracker": "",
"created_date": "2021-12-14T19:46:37.969497Z",
"created_date": "2021-12-14T19:46:37.969000Z",
"dimension": "2d",
"id": 1,
"labels": [
@ -97,13 +97,11 @@
"username": "business1"
},
"status": "annotation",
"task_subsets": [
"Train"
],
"task_subsets": [],
"tasks": [
3
9
],
"updated_date": "2022-02-24T21:33:48.037024Z",
"updated_date": "2022-03-05T09:47:49.679000Z",
"url": "http://localhost:8080/api/projects/1"
}
]

@ -6,14 +6,14 @@
{
"assignee": null,
"bug_tracker": "",
"created_date": "2022-03-11T11:18:43.991247Z",
"created_date": "2022-03-14T13:24:05.852000Z",
"dimension": "2d",
"id": 8,
"id": 12,
"labels": [
{
"attributes": [],
"color": "#2080c0",
"id": 13,
"id": 15,
"name": "Car"
}
],
@ -33,63 +33,69 @@
"segments": [],
"status": "annotation",
"subset": "",
"updated_date": "2022-03-11T11:18:44.076719Z",
"url": "http://localhost:8080/api/tasks/8"
"updated_date": "2022-03-14T13:24:05.861000Z",
"url": "http://localhost:8080/api/tasks/12"
},
{
"assignee": {
"first_name": "Worker",
"id": 7,
"last_name": "Second",
"url": "http://localhost:8080/api/users/7",
"username": "worker2"
"first_name": "User",
"id": 19,
"last_name": "Fifth",
"url": "http://localhost:8080/api/users/19",
"username": "user5"
},
"bug_tracker": "",
"created_date": "2022-02-21T10:31:52.429478Z",
"data": 7,
"created_date": "2022-03-05T10:32:19.149000Z",
"data": 11,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"data_original_chunk_type": "imageset",
"dimension": "2d",
"id": 7,
"id": 11,
"image_quality": 70,
"labels": [
{
"attributes": [],
"color": "#6080c0",
"id": 11,
"id": 7,
"name": "cat"
},
{
"attributes": [],
"color": "#406040",
"id": 12,
"id": 8,
"name": "dog"
}
],
"mode": "annotation",
"name": "task_2_org2",
"name": "task1_in_project2",
"organization": 2,
"overlap": 0,
"owner": {
"first_name": "Business",
"id": 11,
"last_name": "Second",
"url": "http://localhost:8080/api/users/11",
"username": "business2"
"id": 10,
"last_name": "First",
"url": "http://localhost:8080/api/users/10",
"username": "business1"
},
"project_id": null,
"project_id": 2,
"segment_size": 11,
"segments": [
{
"jobs": [
{
"assignee": null,
"id": 9,
"assignee": {
"first_name": "Worker",
"id": 7,
"last_name": "Second",
"url": "http://localhost:8080/api/users/7",
"username": "worker2"
},
"id": 16,
"stage": "annotation",
"state": "in progress",
"status": "annotation",
"url": "http://localhost:8080/api/jobs/9"
"url": "http://localhost:8080/api/jobs/16"
}
],
"start_frame": 0,
@ -98,87 +104,160 @@
],
"size": 11,
"status": "annotation",
"subset": "",
"updated_date": "2022-02-21T10:41:38.540427Z",
"url": "http://localhost:8080/api/tasks/7"
"subset": "Train",
"updated_date": "2022-03-05T10:32:35.568000Z",
"url": "http://localhost:8080/api/tasks/11"
},
{
"assignee": null,
"assignee": {
"first_name": "User",
"id": 20,
"last_name": "Sixth",
"url": "http://localhost:8080/api/users/20",
"username": "user6"
},
"bug_tracker": "",
"created_date": "2022-02-16T06:26:54.631217Z",
"data": 6,
"created_date": "2022-03-05T09:33:10.420000Z",
"data": 9,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"data_original_chunk_type": "imageset",
"dimension": "3d",
"id": 6,
"dimension": "2d",
"id": 9,
"image_quality": 70,
"labels": [
{
"attributes": [],
"attributes": [
{
"default_value": "mazda",
"id": 1,
"input_type": "select",
"mutable": false,
"name": "model",
"values": [
"mazda",
"volvo",
"bmw"
]
}
],
"color": "#2080c0",
"id": 10,
"id": 5,
"name": "car"
},
{
"attributes": [],
"color": "#c06060",
"id": 6,
"name": "person"
}
],
"mode": "annotation",
"name": "task3",
"name": "task1_in_project1",
"organization": null,
"overlap": 0,
"owner": {
"first_name": "User",
"id": 2,
"first_name": "Business",
"id": 10,
"last_name": "First",
"url": "http://localhost:8080/api/users/2",
"username": "user1"
"url": "http://localhost:8080/api/users/10",
"username": "business1"
},
"project_id": null,
"segment_size": 1,
"project_id": 1,
"segment_size": 5,
"segments": [
{
"jobs": [
{
"assignee": null,
"id": 8,
"id": 11,
"stage": "annotation",
"state": "new",
"state": "in progress",
"status": "annotation",
"url": "http://localhost:8080/api/jobs/8"
"url": "http://localhost:8080/api/jobs/11"
}
],
"start_frame": 0,
"stop_frame": 0
"stop_frame": 4
},
{
"jobs": [
{
"assignee": null,
"id": 12,
"stage": "validation",
"state": "new",
"status": "validation",
"url": "http://localhost:8080/api/jobs/12"
}
],
"start_frame": 5,
"stop_frame": 9
},
{
"jobs": [
{
"assignee": null,
"id": 13,
"stage": "acceptance",
"state": "new",
"status": "validation",
"url": "http://localhost:8080/api/jobs/13"
}
],
"start_frame": 10,
"stop_frame": 14
},
{
"jobs": [
{
"assignee": null,
"id": 14,
"stage": "annotation",
"state": "new",
"status": "annotation",
"url": "http://localhost:8080/api/jobs/14"
}
],
"start_frame": 15,
"stop_frame": 19
}
],
"size": 1,
"size": 20,
"status": "annotation",
"subset": "",
"updated_date": "2022-02-16T06:26:54.836403Z",
"url": "http://localhost:8080/api/tasks/6"
"updated_date": "2022-03-05T09:47:49.667000Z",
"url": "http://localhost:8080/api/tasks/9"
},
{
"assignee": null,
"bug_tracker": "",
"created_date": "2022-02-16T06:25:48.168612Z",
"data": 5,
"created_date": "2022-03-05T08:30:48.612000Z",
"data": 8,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"data_original_chunk_type": "video",
"data_original_chunk_type": "imageset",
"dimension": "2d",
"id": 5,
"id": 8,
"image_quality": 70,
"labels": [
{
"attributes": [],
"color": "#2080c0",
"id": 9,
"name": "car"
"color": "#6080c0",
"id": 13,
"name": "cat"
},
{
"attributes": [],
"color": "#406040",
"id": 14,
"name": "dog"
}
],
"mode": "interpolation",
"name": "task2",
"mode": "annotation",
"name": "task1",
"organization": null,
"overlap": 5,
"overlap": 0,
"owner": {
"first_name": "User",
"id": 2,
@ -187,243 +266,178 @@
"username": "user1"
},
"project_id": null,
"segment_size": 25,
"segment_size": 14,
"segments": [
{
"jobs": [
{
"assignee": {
"first_name": "Worker",
"id": 9,
"last_name": "Fourth",
"url": "http://localhost:8080/api/users/9",
"username": "worker4"
"first_name": "Admin",
"id": 1,
"last_name": "First",
"url": "http://localhost:8080/api/users/1",
"username": "admin1"
},
"id": 7,
"id": 10,
"stage": "annotation",
"state": "in progress",
"status": "annotation",
"url": "http://localhost:8080/api/jobs/7"
"url": "http://localhost:8080/api/jobs/10"
}
],
"start_frame": 0,
"stop_frame": 24
"stop_frame": 13
}
],
"size": 25,
"size": 14,
"status": "annotation",
"subset": "",
"updated_date": "2022-02-21T10:40:21.257604Z",
"url": "http://localhost:8080/api/tasks/5"
"updated_date": "2022-03-05T08:52:34.908000Z",
"url": "http://localhost:8080/api/tasks/8"
},
{
"assignee": {
"first_name": "User",
"id": 19,
"last_name": "Fifth",
"url": "http://localhost:8080/api/users/19",
"username": "user5"
"first_name": "Worker",
"id": 7,
"last_name": "Second",
"url": "http://localhost:8080/api/users/7",
"username": "worker2"
},
"bug_tracker": "",
"created_date": "2021-12-14T19:55:57.475273Z",
"data": 4,
"created_date": "2022-02-21T10:31:52.429000Z",
"data": 7,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"data_original_chunk_type": "imageset",
"dimension": "2d",
"id": 4,
"id": 7,
"image_quality": 70,
"labels": [
{
"attributes": [],
"color": "#6080c0",
"id": 7,
"id": 11,
"name": "cat"
},
{
"attributes": [],
"color": "#406040",
"id": 8,
"id": 12,
"name": "dog"
}
],
"mode": "annotation",
"name": "task1_in_project2",
"name": "task_2_org2",
"organization": 2,
"overlap": 0,
"owner": {
"first_name": "Business",
"id": 10,
"last_name": "First",
"url": "http://localhost:8080/api/users/10",
"username": "business1"
"id": 11,
"last_name": "Second",
"url": "http://localhost:8080/api/users/11",
"username": "business2"
},
"project_id": 2,
"segment_size": 58,
"project_id": null,
"segment_size": 11,
"segments": [
{
"jobs": [
{
"assignee": {
"first_name": "Worker",
"id": 7,
"last_name": "Second",
"url": "http://localhost:8080/api/users/7",
"username": "worker2"
},
"id": 6,
"assignee": null,
"id": 9,
"stage": "annotation",
"state": "new",
"state": "in progress",
"status": "annotation",
"url": "http://localhost:8080/api/jobs/6"
"url": "http://localhost:8080/api/jobs/9"
}
],
"start_frame": 0,
"stop_frame": 57
"stop_frame": 10
}
],
"size": 58,
"size": 11,
"status": "annotation",
"subset": "train",
"updated_date": "2022-02-24T21:32:36.190676Z",
"url": "http://localhost:8080/api/tasks/4"
"subset": "",
"updated_date": "2022-02-21T10:41:38.540000Z",
"url": "http://localhost:8080/api/tasks/7"
},
{
"assignee": {
"first_name": "User",
"id": 19,
"last_name": "Fifth",
"url": "http://localhost:8080/api/users/19",
"username": "user5"
},
"assignee": null,
"bug_tracker": "",
"created_date": "2021-12-14T19:48:33.089778Z",
"data": 3,
"created_date": "2022-02-16T06:26:54.631000Z",
"data": 6,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"data_original_chunk_type": "imageset",
"dimension": "2d",
"id": 3,
"dimension": "3d",
"id": 6,
"image_quality": 70,
"labels": [
{
"attributes": [
{
"default_value": "mazda",
"id": 1,
"input_type": "select",
"mutable": false,
"name": "model",
"values": [
"mazda",
"volvo",
"bmw"
]
}
],
"attributes": [],
"color": "#2080c0",
"id": 5,
"id": 10,
"name": "car"
},
{
"attributes": [],
"color": "#c06060",
"id": 6,
"name": "person"
}
],
"mode": "annotation",
"name": "task1_in_project1",
"name": "task3",
"organization": null,
"overlap": 0,
"owner": {
"first_name": "Business",
"id": 10,
"first_name": "User",
"id": 2,
"last_name": "First",
"url": "http://localhost:8080/api/users/10",
"username": "business1"
"url": "http://localhost:8080/api/users/2",
"username": "user1"
},
"project_id": 1,
"segment_size": 50,
"project_id": null,
"segment_size": 1,
"segments": [
{
"jobs": [
{
"assignee": null,
"id": 3,
"id": 8,
"stage": "annotation",
"state": "in progress",
"state": "new",
"status": "annotation",
"url": "http://localhost:8080/api/jobs/3"
"url": "http://localhost:8080/api/jobs/8"
}
],
"start_frame": 0,
"stop_frame": 49
},
{
"jobs": [
{
"assignee": null,
"id": 4,
"stage": "validation",
"state": "new",
"status": "validation",
"url": "http://localhost:8080/api/jobs/4"
}
],
"start_frame": 50,
"stop_frame": 99
},
{
"jobs": [
{
"assignee": null,
"id": 5,
"stage": "acceptance",
"state": "new",
"status": "validation",
"url": "http://localhost:8080/api/jobs/5"
}
],
"start_frame": 100,
"stop_frame": 147
"stop_frame": 0
}
],
"size": 148,
"size": 1,
"status": "annotation",
"subset": "Train",
"updated_date": "2022-02-24T21:25:10.697341Z",
"url": "http://localhost:8080/api/tasks/3"
"subset": "",
"updated_date": "2022-02-16T06:26:54.836000Z",
"url": "http://localhost:8080/api/tasks/6"
},
{
"assignee": null,
"bug_tracker": "",
"created_date": "2021-12-14T18:50:29.458488Z",
"data": 2,
"created_date": "2022-02-16T06:25:48.168000Z",
"data": 5,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"data_original_chunk_type": "imageset",
"data_original_chunk_type": "video",
"dimension": "2d",
"id": 2,
"id": 5,
"image_quality": 70,
"labels": [
{
"attributes": [],
"color": "#2080c0",
"id": 3,
"id": 9,
"name": "car"
},
{
"attributes": [],
"color": "#c06060",
"id": 4,
"name": "person"
}
],
"mode": "annotation",
"mode": "interpolation",
"name": "task2",
"organization": 1,
"overlap": 0,
"organization": null,
"overlap": 5,
"owner": {
"first_name": "User",
"id": 2,
@ -432,63 +446,63 @@
"username": "user1"
},
"project_id": null,
"segment_size": 23,
"segment_size": 25,
"segments": [
{
"jobs": [
{
"assignee": {
"first_name": "Worker",
"id": 6,
"last_name": "First",
"url": "http://localhost:8080/api/users/6",
"username": "worker1"
"id": 9,
"last_name": "Fourth",
"url": "http://localhost:8080/api/users/9",
"username": "worker4"
},
"id": 2,
"id": 7,
"stage": "annotation",
"state": "new",
"state": "in progress",
"status": "annotation",
"url": "http://localhost:8080/api/jobs/2"
"url": "http://localhost:8080/api/jobs/7"
}
],
"start_frame": 0,
"stop_frame": 22
"stop_frame": 24
}
],
"size": 23,
"size": 25,
"status": "annotation",
"subset": "",
"updated_date": "2021-12-22T07:14:15.234748Z",
"url": "http://localhost:8080/api/tasks/2"
"updated_date": "2022-02-21T10:40:21.257000Z",
"url": "http://localhost:8080/api/tasks/5"
},
{
"assignee": null,
"bug_tracker": "",
"created_date": "2021-12-14T18:43:47.601289Z",
"data": 1,
"created_date": "2021-12-14T18:50:29.458000Z",
"data": 2,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"data_original_chunk_type": "imageset",
"dimension": "2d",
"id": 1,
"id": 2,
"image_quality": 70,
"labels": [
{
"attributes": [],
"color": "#6080c0",
"id": 1,
"name": "cat"
"color": "#2080c0",
"id": 3,
"name": "car"
},
{
"attributes": [],
"color": "#406040",
"id": 2,
"name": "dog"
"color": "#c06060",
"id": 4,
"name": "person"
}
],
"mode": "annotation",
"name": "task1",
"organization": null,
"name": "task2",
"organization": 1,
"overlap": 0,
"owner": {
"first_name": "User",
@ -498,34 +512,34 @@
"username": "user1"
},
"project_id": null,
"segment_size": 130,
"segment_size": 23,
"segments": [
{
"jobs": [
{
"assignee": {
"first_name": "Admin",
"id": 1,
"first_name": "Worker",
"id": 6,
"last_name": "First",
"url": "http://localhost:8080/api/users/1",
"username": "admin1"
"url": "http://localhost:8080/api/users/6",
"username": "worker1"
},
"id": 1,
"id": 2,
"stage": "annotation",
"state": "new",
"status": "annotation",
"url": "http://localhost:8080/api/jobs/1"
"url": "http://localhost:8080/api/jobs/2"
}
],
"start_frame": 0,
"stop_frame": 129
"stop_frame": 22
}
],
"size": 130,
"size": 23,
"status": "annotation",
"subset": "",
"updated_date": "2021-12-22T07:15:22.942484Z",
"url": "http://localhost:8080/api/tasks/1"
"updated_date": "2021-12-22T07:14:15.234000Z",
"url": "http://localhost:8080/api/tasks/2"
}
]
}

@ -46,7 +46,7 @@
"is_active": true,
"is_staff": true,
"is_superuser": true,
"last_login": null,
"last_login": "2022-03-05T09:37:01.636000Z",
"last_name": "Second",
"url": "http://localhost:8080/api/users/18",
"username": "admin2"
@ -150,7 +150,7 @@
"is_active": true,
"is_staff": false,
"is_superuser": false,
"last_login": "2022-02-21T10:29:16.518442Z",
"last_login": "2022-02-21T10:29:16.518000Z",
"last_name": "Second",
"url": "http://localhost:8080/api/users/11",
"username": "business2"
@ -166,7 +166,7 @@
"is_active": true,
"is_staff": false,
"is_superuser": false,
"last_login": "2022-01-19T13:52:59.477881Z",
"last_login": "2022-03-05T10:31:48.850000Z",
"last_name": "First",
"url": "http://localhost:8080/api/users/10",
"username": "business1"
@ -230,7 +230,7 @@
"is_active": true,
"is_staff": false,
"is_superuser": false,
"last_login": "2021-12-14T19:11:21.048740Z",
"last_login": "2021-12-14T19:11:21.048000Z",
"last_name": "First",
"url": "http://localhost:8080/api/users/6",
"username": "worker1"
@ -294,7 +294,7 @@
"is_active": true,
"is_staff": false,
"is_superuser": false,
"last_login": "2022-02-16T06:24:53.910205Z",
"last_login": "2022-03-05T08:52:22.036000Z",
"last_name": "First",
"url": "http://localhost:8080/api/users/2",
"username": "user1"
@ -310,7 +310,7 @@
"is_active": true,
"is_staff": true,
"is_superuser": true,
"last_login": "2022-03-11T11:18:43.931009Z",
"last_login": "2022-03-05T09:34:33.293000Z",
"last_name": "First",
"url": "http://localhost:8080/api/users/1",
"username": "admin1"

@ -1,54 +1,43 @@
# Copyright (C) 2021 Intel Corporation
#
# SPDX-License-Identifier: MIT
from subprocess import run, CalledProcessError
import pytest
import json
import os.path as osp
from .utils.config import ASSETS_DIR
def cvat_db_container(command):
run(('docker exec cvat_db ' + command).split(), check=True) #nosec
CVAT_DB_DIR = osp.join(ASSETS_DIR, 'cvat_db')
def docker_cp(source, target):
run(' '.join(['docker container cp', source, target]).split(), check=True) #nosec
def _run(command):
try:
run(command.split(), check=True) #nosec
except CalledProcessError:
pytest.exit(f'Command failed: {command}. Add `-s` option to see more details')
def restore_data_volume():
command = 'docker run --rm --volumes-from cvat --mount ' \
f'type=bind,source={ASSETS_DIR},target=/mnt/ ubuntu tar ' \
'--strip 3 -C /home/django/data -xjf /mnt/cvat_data.tar.bz2'
run(command.split(), check=True) #nosec
def restore_cvat_db():
cvat_db_container('psql -U root -d postgres -f /cvat_db/restore_db.sql')
def drop_test_db():
restore_cvat_db()
cvat_db_container('rm -rf /cvat_db')
cvat_db_container('dropdb test_db')
_run(f"docker container cp {osp.join(ASSETS_DIR, 'cvat_db', 'cvat_data.tar.bz2')} cvat:cvat_data.tar.bz2")
_run(f"docker exec -i cvat tar --strip 3 -xjf /cvat_data.tar.bz2 -C /home/django/data/")
def create_test_db():
docker_cp(source=osp.join(ASSETS_DIR, 'cvat_db'), target='cvat_db:/')
cvat_db_container('createdb test_db')
cvat_db_container('psql -U root -q -d test_db -f /cvat_db/cvat_db.sql')
_run(f"docker container cp {osp.join(CVAT_DB_DIR, 'restore.sql')} cvat_db:restore.sql")
_run(f"docker container cp {osp.join(CVAT_DB_DIR, 'data.json')} cvat:data.json")
_run('docker exec cvat python manage.py loaddata /data.json')
_run('docker exec cvat_db psql -U root -d postgres -v from=cvat -v to=test_db -f restore.sql')
@pytest.fixture(scope='session', autouse=True)
def init_test_db():
try:
restore_data_volume()
create_test_db()
except CalledProcessError:
drop_test_db()
pytest.exit(f"Cannot to initialize test DB")
restore_data_volume()
create_test_db()
yield
drop_test_db()
_run('docker exec cvat_db psql -U root -d postgres -v from=test_db -v to=cvat -f restore.sql')
_run('docker exec cvat_db dropdb test_db')
@pytest.fixture(scope='function', autouse=True)
def restore():
restore_cvat_db()
_run('docker exec cvat_db psql -U root -d postgres -v from=test_db -v to=cvat -f restore.sql')
class Container:
def __init__(self, data, key='id'):

@ -25,4 +25,4 @@ def test_check_objects_integrity(path):
resp_objs = response.json()
assert DeepDiff(json_objs, resp_objs, ignore_order=True,
exclude_regex_paths=r"root\['results'\]\[d+\]\['last_login'\]") == {}
exclude_regex_paths=r"root\['results'\]\[\d+\]\['last_login'\]") == {}

@ -114,8 +114,11 @@ class TestGetAnnotations:
def _test_get_job_annotations_200(self, user, jid, data, **kwargs):
response = get_method(user, f'jobs/{jid}/annotations', **kwargs)
response_data = response.json()
response_data['shapes'] = sorted(response_data['shapes'], key=lambda a: a['id'])
assert response.status_code == HTTPStatus.OK
assert DeepDiff(data, response.json(),
assert DeepDiff(data, response_data,
exclude_paths="root['version']") == {}
def _test_get_job_annotations_403(self, user, jid, **kwargs):
@ -155,8 +158,9 @@ class TestGetAnnotations:
username, jid = find_job_staff_user(jobs, users, job_staff)
if is_allow:
self._test_get_job_annotations_200(username,
jid, annotations['job'][str(jid)], **kwargs)
data = annotations['job'][str(jid)]
data['shapes'] = sorted(data['shapes'], key=lambda a: a['id'])
self._test_get_job_annotations_200(username, jid, data, **kwargs)
else:
self._test_get_job_annotations_403(username, jid, **kwargs)

@ -27,7 +27,7 @@ def _wait_until_task_is_created(username, task_id):
class TestGetAnalytics:
task_id = 8
task_id = 12
def _test_can_create(self, user, task_id, resources):
response = _post_task_remote_data(user, task_id, resources)
assert response.status_code == HTTPStatus.ACCEPTED

@ -147,7 +147,7 @@ class TestGetData:
_USERNAME = 'user1'
@pytest.mark.parametrize('content_type, task_id', [
('image/png', 1),
('image/png', 8),
('image/png', 5),
('image/x.point-cloud-data', 6),
])

Loading…
Cancel
Save