phuochungus commited on
Commit
2cf679a
2 Parent(s): a5c51fb 62dfa61

Merge branch 'main' of https://github.com/phuochungus/SE113.O12_KCPM into DA1

Browse files
.coverage CHANGED
Binary files a/.coverage and b/.coverage differ
 
.gitignore CHANGED
@@ -7,4 +7,5 @@ demo
7
  **/*.mp4
8
  **/*.jpg
9
  .pytest_cache
10
- !demo.jpg
 
 
7
  **/*.mp4
8
  **/*.jpg
9
  .pytest_cache
10
+ !demo.jpg
11
+ /htmlcov
app/routers/friend_request.py CHANGED
@@ -8,6 +8,8 @@ from app.dependencies import get_current_user
8
  from app import db, logger
9
  from enum import Enum
10
  from app.graphdb.main import insert2PersonAndSetFriend
 
 
11
 
12
  router = APIRouter(prefix="/friend_request", tags=["friend_request"])
13
 
@@ -66,29 +68,41 @@ async def acceptRequest(RequestId: str, user=Depends(get_current_user)):
66
  fr = fr_ref.get()
67
 
68
  if not fr.exists:
69
- raise HTTPException(status_code=404, detail="Friend request not found")
 
 
70
 
71
  fr = fr.to_dict()
72
 
73
  if isRequestExpired(fr):
74
- raise HTTPException(status_code=400, detail="Friend request expired")
 
 
75
 
76
  if isRequestDone(fr):
77
- raise HTTPException(status_code=400, detail="Friend request already done")
 
 
78
 
79
  if isInviter(user, fr):
80
  if isInviteeEmpty(fr):
81
- raise HTTPException(status_code=400, detail="Invitee is empty")
 
 
82
  fr_ref.update({"status": RequestStatus.COMPLETE.value})
83
  await makeFriend(fr["invitee"], fr["inviter"])
84
  return {"status": "OK"}
85
-
86
- if isInviteeEmpty(fr) and not isInviter(user, fr):
87
- fr_ref.update(
88
- {"invitee": user["sub"], "status": RequestStatus.WAITING_INVITER.value}
89
- )
90
- sendNotificationToInviter(fr["inviter"], user)
91
- return {"status": "OK"}
 
 
 
 
92
 
93
 
94
  def sendNotificationToInviter(inviterId: str, invitee):
@@ -101,20 +115,21 @@ async def makeFriend(inviteeId: str, inviterId: str):
101
 
102
  @router.delete("/{RequestId}")
103
  def deleteRequest(RequestId: str, user=Depends(get_current_user)):
104
- if user.sub is None:
105
- raise HTTPException(status_code=400, detail="User not found")
106
-
107
  Request_ref = db.collection(COLLECTION_NAME).document(RequestId)
108
- Request = Request_ref.get().to_dict()
109
 
110
  if not Request.exists:
111
- raise HTTPException(status_code=404, detail="Friend request not found")
112
-
 
 
113
  if isInviter(user, Request):
114
  Request_ref.delete()
115
  return {"status": "OK"}
116
  else:
117
- raise HTTPException(status_code=400, detail="You are not inviter")
 
 
118
 
119
 
120
  def isRequestExpired(request):
 
8
  from app import db, logger
9
  from enum import Enum
10
  from app.graphdb.main import insert2PersonAndSetFriend
11
+ from fastapi import status
12
+
13
 
14
  router = APIRouter(prefix="/friend_request", tags=["friend_request"])
15
 
 
68
  fr = fr_ref.get()
69
 
70
  if not fr.exists:
71
+ raise HTTPException(
72
+ status_code=status.HTTP_404_NOT_FOUND, detail="Friend request not found"
73
+ )
74
 
75
  fr = fr.to_dict()
76
 
77
  if isRequestExpired(fr):
78
+ raise HTTPException(
79
+ status_code=status.HTTP_409_CONFLICT, detail="Friend request expired"
80
+ )
81
 
82
  if isRequestDone(fr):
83
+ raise HTTPException(
84
+ status_code=status.HTTP_409_CONFLICT, detail="Friend request already done"
85
+ )
86
 
87
  if isInviter(user, fr):
88
  if isInviteeEmpty(fr):
89
+ raise HTTPException(
90
+ status_code=status.HTTP_409_CONFLICT, detail="Invitee is empty"
91
+ )
92
  fr_ref.update({"status": RequestStatus.COMPLETE.value})
93
  await makeFriend(fr["invitee"], fr["inviter"])
94
  return {"status": "OK"}
95
+ else:
96
+ if isInviteeEmpty(fr):
97
+ fr_ref.update(
98
+ {"invitee": user["sub"], "status": RequestStatus.WAITING_INVITER.value}
99
+ )
100
+ sendNotificationToInviter(fr["inviter"], user)
101
+ return {"status": "OK"}
102
+ else:
103
+ raise HTTPException(
104
+ status_code=status.HTTP_409_CONFLICT, detail="Invitee is not empty"
105
+ )
106
 
107
 
108
  def sendNotificationToInviter(inviterId: str, invitee):
 
115
 
116
  @router.delete("/{RequestId}")
117
  def deleteRequest(RequestId: str, user=Depends(get_current_user)):
 
 
 
118
  Request_ref = db.collection(COLLECTION_NAME).document(RequestId)
119
+ Request = Request_ref.get()
120
 
121
  if not Request.exists:
122
+ raise HTTPException(
123
+ status_code=status.HTTP_404_NOT_FOUND, detail="Friend request not found"
124
+ )
125
+ Request = Request.to_dict()
126
  if isInviter(user, Request):
127
  Request_ref.delete()
128
  return {"status": "OK"}
129
  else:
130
+ raise HTTPException(
131
+ status_code=status.HTTP_403_FORBIDDEN, detail="You are not inviter"
132
+ )
133
 
134
 
135
  def isRequestExpired(request):
app/routers/me.py CHANGED
@@ -9,8 +9,3 @@ router = APIRouter(prefix="/me", tags=["Me"])
9
  @router.get("")
10
  def getProfile(current_user=Depends(get_current_user)):
11
  return current_user
12
-
13
-
14
- @router.get("/friends")
15
- def getFriends(current_user=Depends(get_current_user)):
16
- raise NotImplementedError()
 
9
  @router.get("")
10
  def getProfile(current_user=Depends(get_current_user)):
11
  return current_user
 
 
 
 
 
app/routers/video.py CHANGED
@@ -12,6 +12,7 @@ from fastapi import (
12
  Depends,
13
  HTTPException,
14
  Request,
 
15
  UploadFile,
16
  BackgroundTasks,
17
  status,
 
12
  Depends,
13
  HTTPException,
14
  Request,
15
+ Request,
16
  UploadFile,
17
  BackgroundTasks,
18
  status,
tests/test_friend_request.py CHANGED
@@ -141,11 +141,21 @@ class TestFriendRequest:
141
  assert result.shape[2] == 3
142
  # Write image for later read
143
  mmcv.imwrite(result, "qrcode.jpg")
 
 
 
 
 
 
 
 
 
 
 
144
  # Now test for the invitee aka the one that scan QR code
145
  # Delete invitee user (if existed)
146
  user_ref.document(invitee["id"]).delete()
147
  # Test when the invitee is unknow user (no user entity in database)
148
- request_id = read_qr_code("qrcode.jpg")
149
  payload = ""
150
  headers = {
151
  "Content-Type": "application/json",
@@ -159,6 +169,28 @@ class TestFriendRequest:
159
  # Create invitee user
160
  user_ref.document(invitee["id"]).set({"deviceId": deviceId})
161
  # Send request
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  request_id = read_qr_code("qrcode.jpg")
163
  payload = ""
164
  headers = {
@@ -168,7 +200,95 @@ class TestFriendRequest:
168
  response = client.request(
169
  "PATCH", "friend_request/" + request_id, headers=headers, data=payload
170
  )
 
 
 
 
 
 
 
 
 
 
 
171
  assert response.status_code == 200
172
  # Delete entity for next time test
173
  user_ref.document(inviter["id"]).delete()
174
  user_ref.document(invitee["id"]).delete()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  assert result.shape[2] == 3
142
  # Write image for later read
143
  mmcv.imwrite(result, "qrcode.jpg")
144
+ request_id = read_qr_code("qrcode.jpg")
145
+ ## Send request again (accept friend request when no invitee)
146
+ payload = ""
147
+ headers = {
148
+ "Content-Type": "application/json",
149
+ "Authorization": "Bearer " + inviter["token"],
150
+ }
151
+ response = client.request(
152
+ "PATCH", "friend_request/" + request_id, headers=headers, data=payload
153
+ )
154
+ assert response.status_code == 409
155
  # Now test for the invitee aka the one that scan QR code
156
  # Delete invitee user (if existed)
157
  user_ref.document(invitee["id"]).delete()
158
  # Test when the invitee is unknow user (no user entity in database)
 
159
  payload = ""
160
  headers = {
161
  "Content-Type": "application/json",
 
169
  # Create invitee user
170
  user_ref.document(invitee["id"]).set({"deviceId": deviceId})
171
  # Send request
172
+ ## Send request with false token
173
+ payload = ""
174
+ headers = {
175
+ "Content-Type": "application/json",
176
+ "Authorization": "Bearer " + "xxxxxx",
177
+ }
178
+ response = client.request(
179
+ "PATCH", "friend_request/" + request_id, headers=headers, data=payload
180
+ )
181
+ assert response.status_code == 401
182
+ ## Send request
183
+ request_id = read_qr_code("qrcode.jpg")
184
+ payload = ""
185
+ headers = {
186
+ "Content-Type": "application/json",
187
+ "Authorization": "Bearer " + invitee["token"],
188
+ }
189
+ response = client.request(
190
+ "PATCH", "friend_request/" + request_id, headers=headers, data=payload
191
+ )
192
+ assert response.status_code == 200
193
+ ## Send request again (false)
194
  request_id = read_qr_code("qrcode.jpg")
195
  payload = ""
196
  headers = {
 
200
  response = client.request(
201
  "PATCH", "friend_request/" + request_id, headers=headers, data=payload
202
  )
203
+ assert response.status_code == 409
204
+ ## Send request again (accept friend request from invitee)
205
+ request_id = read_qr_code("qrcode.jpg")
206
+ payload = ""
207
+ headers = {
208
+ "Content-Type": "application/json",
209
+ "Authorization": "Bearer " + inviter["token"],
210
+ }
211
+ response = client.request(
212
+ "PATCH", "friend_request/" + request_id, headers=headers, data=payload
213
+ )
214
  assert response.status_code == 200
215
  # Delete entity for next time test
216
  user_ref.document(inviter["id"]).delete()
217
  user_ref.document(invitee["id"]).delete()
218
+ def test_delete_requestF(self, client, inviter, invitee):
219
+ # Call the firebase database
220
+ friend_request_ref = db.collection("friend_request")
221
+ # Remove all the friend_request use for testing in the past
222
+ query = friend_request_ref.where(
223
+ filter=FieldFilter("inviter", "==", inviter["id"])
224
+ )
225
+ docs = query.stream()
226
+ for doc in docs:
227
+ doc.reference.delete()
228
+ # Delete the user for safety-check
229
+ user_ref = db.collection("user")
230
+ user_ref.document(inviter["id"]).delete()
231
+ # Create request and re-send
232
+ user_ref.document(inviter["id"]).set({"deviceId": deviceId})
233
+ payload = ""
234
+ headers = {
235
+ "Content-Type": "application/json",
236
+ "Authorization": "Bearer " + inviter["token"],
237
+ }
238
+ response = client.request(
239
+ "POST", "friend_request", headers=headers, data=payload
240
+ )
241
+ assert response.status_code == 200
242
+ result = mmcv.imfrombytes(response.read())
243
+ # Check returned QR image
244
+ assert result.shape[2] == 3
245
+ # Write image for later read
246
+ mmcv.imwrite(result, "qrcode.jpg")
247
+ request_id = read_qr_code("qrcode.jpg")
248
+ #Check with unknowed invitee
249
+ payload = ""
250
+ headers = {
251
+ "Content-Type": "application/json",
252
+ "Authorization": "Bearer " + invitee["token"],
253
+ }
254
+ response = client.request(
255
+ "DELETE", "friend_request/" + request_id, headers=headers, data=payload
256
+ )
257
+ assert response.status_code == 403
258
+ #Delete invitee for safety check
259
+ user_ref.document(invitee["id"]).delete()
260
+ # Create invitee user
261
+ user_ref.document(invitee["id"]).set({"deviceId": deviceId})
262
+ # check DELETE route
263
+ payload = ""
264
+ headers = {
265
+ "Content-Type": "application/json",
266
+ "Authorization": "Bearer " + inviter["token"],
267
+ }
268
+ response = client.request(
269
+ "DELETE", "friend_request/" + "xxxx", headers=headers, data=payload
270
+ )
271
+ assert response.status_code == 404
272
+ payload = ""
273
+ headers = {
274
+ "Content-Type": "application/json",
275
+ "Authorization": "Bearer " + invitee["token"],
276
+ }
277
+ response = client.request(
278
+ "DELETE", "friend_request/" + request_id, headers=headers, data=payload
279
+ )
280
+ assert response.status_code == 403
281
+ #Correct Request
282
+ payload = ""
283
+ headers = {
284
+ "Content-Type": "application/json",
285
+ "Authorization": "Bearer " + inviter["token"],
286
+ }
287
+ response = client.request(
288
+ "DELETE", "friend_request/" + request_id, headers=headers, data=payload
289
+ )
290
+ assert response.status_code == 200
291
+
292
+ # Delete entity for next time test
293
+ user_ref.document(inviter["id"]).delete()
294
+ user_ref.document(invitee["id"]).delete()
tests/test_video.py CHANGED
@@ -1,10 +1,9 @@
1
  from fastapi.testclient import TestClient
2
  from fastapi.routing import APIRoute
3
- from app.routers.video import update_artifact, createThumbnail, inference_frame
4
  from app.main import app
5
  from app.constants import deviceId
6
  from app import db
7
- import platform
8
  import mmcv
9
  import os
10
  import pytest
@@ -14,120 +13,137 @@ import cv2
14
  import shutil
15
  from google.cloud.firestore_v1.base_query import FieldFilter
16
 
 
17
  def endpoints():
18
  endpoints = []
19
  for route in app.routes:
20
  if isinstance(route, APIRoute):
21
  endpoints.append(route.path)
22
  return endpoints
 
 
23
  @pytest.fixture
24
  def client():
25
  client = TestClient(app, "http://0.0.0.0:3000")
26
  yield client
 
 
27
  @pytest.fixture
28
  def user():
29
- url = "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=" + os.environ.get("FIREBASE_API_KEY")
30
-
31
- payload = json.dumps({
32
- "email": "test_video@gmail.com",
33
- "password": "testing",
34
- "returnSecureToken": True
35
- })
36
- headers = {
37
- 'Content-Type': 'application/json'
38
- }
 
 
 
39
  response = requests.request("POST", url, headers=headers, data=payload)
40
  data = response.json()
41
- user = {"id": data['localId'], "token": data["idToken"]}
42
- db.collection("user").document(user['id']).set({"deviceId": deviceId})
43
  yield user
44
- db.collection("user").document(user['id']).delete()
 
 
45
  class TestVideoAPI:
46
- @pytest.mark.skipif("/video" not in endpoints(),reason="Route not defined")
47
  def test_video_API(self, user, client):
48
  # Test when no token is pass to route
49
  payload = {}
50
- files=[
51
- ('file',('demo.mp4',open('demo.mp4','rb'),'video/mp4'))
52
- ]
53
- headers = {
54
- }
55
- response = client.request("POST", 'video', headers=headers, data=payload, files=files)
56
  assert response.status_code == 403
57
  # Test when a dummy (not valid) token passed
58
  payload = {}
59
- files=[
60
- ('file',('demo.mp4',open('demo.mp4','rb'),'video/mp4'))
61
- ]
62
- headers = {
63
- 'Authorization': "Bearer saikoljncaskljnfckjnasckjna"
64
- }
65
- response = client.request("POST", 'video', headers=headers, data=payload, files=files)
66
  assert response.status_code == 401
67
  # Test when sent file is not a video
68
  payload = {}
69
- files=[
70
- ('file',('demo.jpg',open('demo.jpg','rb'),'application/octet-stream'))
71
  ]
72
- headers = {
73
- 'Authorization': "Bearer " + user['token']
74
- }
75
  while True:
76
- response = client.request("POST", 'video', headers=headers, data=payload, files=files)
 
 
77
  if response.status_code != 401:
78
  break
79
  assert response.status_code == 400
80
  # Test when all requirements have been fulfilled
81
  payload = {}
82
- files=[
83
- ('file',('demo.mp4',open('demo.mp4','rb'),'video/mp4'))
84
- ]
85
- headers = {
86
- 'Authorization': "Bearer " + user['token']
87
- }
88
- response = client.request("POST", 'video', headers=headers, data=payload, files=files)
89
  assert response.status_code == 200
90
  artifactName = response.text
91
- docs = db.collection("artifacts").where(filter = FieldFilter("name", '==', artifactName)).stream()
 
 
 
 
92
  index = 0
93
  for doc in docs:
94
  # For each document in docs. Verify name and status of the artifact
95
  index += 1
96
  data = doc.get().to_dict()
97
- assert data['name'] == artifactName
98
- assert data['status'] == 'pending'
99
  assert index == 1
100
  doc.delete()
 
101
  def test_update_artifact(self):
102
  # Check and preprocess test data before testing
103
- test_artifact = db.collection("artifacts").document('test')
104
  if not test_artifact.get().exists:
105
- db.collection("artifacts").document('test').set({"name": "test", "path": "", "status": "testing", "thumbnailURL":""})
106
- test_artifact = db.collection("artifacts").document('test')
 
 
107
  else:
108
- test_artifact.update({"status": "testing", 'path': '', "thumbnailURL":""})
109
  # Testing update on each field
110
- update_artifact(test_artifact.id,{"status": "test_done"})
111
- assert db.collection("artifacts").document('test').get().to_dict()['status'] == 'test_done'
112
- #Delete data for next time test
 
 
 
113
  test_artifact.delete()
 
114
  def test_inference_frame(self):
115
- if not os.path.exists('test_vid'):
116
- os.mkdir('test_vid')
117
- shutil.copyfile('demo.mp4', 'test_vid/input.mp4')
118
- thumbnail = inference_frame('test_vid')
119
- assert os.path.exists("test_vid/out.mp4") and os.path.isfile('test_vid/out.mp4')
120
- vidcap = cv2.VideoCapture('test_vid/input.mp4')
121
  success, image = vidcap.read()
122
  if success:
123
- assert (image.shape == thumbnail.shape)
124
  vidcap.release()
125
  del vidcap
126
- shutil.rmtree('test_vid')
 
127
  def test_create_thumbnal(self):
128
- vidcap = cv2.VideoCapture('demo.mp4')
129
  success, image = vidcap.read()
130
  if success:
131
  createThumbnail(image, "")
132
- result = mmcv.imread('thumbnail.jpg', channel_order='rgb')
133
- assert (result.shape == (160, 160, 3))
 
1
  from fastapi.testclient import TestClient
2
  from fastapi.routing import APIRoute
3
+ from app.routers.video import updateArtifact, createThumbnail, inferenceFrame
4
  from app.main import app
5
  from app.constants import deviceId
6
  from app import db
 
7
  import mmcv
8
  import os
9
  import pytest
 
13
  import shutil
14
  from google.cloud.firestore_v1.base_query import FieldFilter
15
 
16
+
17
  def endpoints():
18
  endpoints = []
19
  for route in app.routes:
20
  if isinstance(route, APIRoute):
21
  endpoints.append(route.path)
22
  return endpoints
23
+
24
+
25
  @pytest.fixture
26
  def client():
27
  client = TestClient(app, "http://0.0.0.0:3000")
28
  yield client
29
+
30
+
31
  @pytest.fixture
32
  def user():
33
+ url = (
34
+ "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key="
35
+ + os.environ.get("FIREBASE_API_KEY")
36
+ )
37
+
38
+ payload = json.dumps(
39
+ {
40
+ "email": "test_video@gmail.com",
41
+ "password": "testing",
42
+ "returnSecureToken": True,
43
+ }
44
+ )
45
+ headers = {"Content-Type": "application/json"}
46
  response = requests.request("POST", url, headers=headers, data=payload)
47
  data = response.json()
48
+ user = {"id": data["localId"], "token": data["idToken"]}
49
+ db.collection("user").document(user["id"]).set({"deviceId": deviceId})
50
  yield user
51
+ db.collection("user").document(user["id"]).delete()
52
+
53
+
54
  class TestVideoAPI:
55
+ @pytest.mark.skipif("/video" not in endpoints(), reason="Route not defined")
56
  def test_video_API(self, user, client):
57
  # Test when no token is pass to route
58
  payload = {}
59
+ files = [("file", ("demo.mp4", open("demo.mp4", "rb"), "video/mp4"))]
60
+ headers = {}
61
+ response = client.request(
62
+ "POST", "video", headers=headers, data=payload, files=files
63
+ )
 
64
  assert response.status_code == 403
65
  # Test when a dummy (not valid) token passed
66
  payload = {}
67
+ files = [("file", ("demo.mp4", open("demo.mp4", "rb"), "video/mp4"))]
68
+ headers = {"Authorization": "Bearer saikoljncaskljnfckjnasckjna"}
69
+ response = client.request(
70
+ "POST", "video", headers=headers, data=payload, files=files
71
+ )
 
 
72
  assert response.status_code == 401
73
  # Test when sent file is not a video
74
  payload = {}
75
+ files = [
76
+ ("file", ("demo.jpg", open("demo.jpg", "rb"), "application/octet-stream"))
77
  ]
78
+ headers = {"Authorization": "Bearer " + user["token"]}
 
 
79
  while True:
80
+ response = client.request(
81
+ "POST", "video", headers=headers, data=payload, files=files
82
+ )
83
  if response.status_code != 401:
84
  break
85
  assert response.status_code == 400
86
  # Test when all requirements have been fulfilled
87
  payload = {}
88
+ files = [("file", ("demo.mp4", open("demo.mp4", "rb"), "video/mp4"))]
89
+ headers = {"Authorization": "Bearer " + user["token"]}
90
+ response = client.request(
91
+ "POST", "video", headers=headers, data=payload, files=files
92
+ )
 
 
93
  assert response.status_code == 200
94
  artifactName = response.text
95
+ docs = (
96
+ db.collection("artifacts")
97
+ .where(filter=FieldFilter("name", "==", artifactName))
98
+ .stream()
99
+ )
100
  index = 0
101
  for doc in docs:
102
  # For each document in docs. Verify name and status of the artifact
103
  index += 1
104
  data = doc.get().to_dict()
105
+ assert data["name"] == artifactName
106
+ assert data["status"] == "pending"
107
  assert index == 1
108
  doc.delete()
109
+
110
  def test_update_artifact(self):
111
  # Check and preprocess test data before testing
112
+ test_artifact = db.collection("artifacts").document("test")
113
  if not test_artifact.get().exists:
114
+ db.collection("artifacts").document("test").set(
115
+ {"name": "test", "path": "", "status": "testing", "thumbnailURL": ""}
116
+ )
117
+ test_artifact = db.collection("artifacts").document("test")
118
  else:
119
+ test_artifact.update({"status": "testing", "path": "", "thumbnailURL": ""})
120
  # Testing update on each field
121
+ updateArtifact(test_artifact.id, {"status": "test_done"})
122
+ assert (
123
+ db.collection("artifacts").document("test").get().to_dict()["status"]
124
+ == "test_done"
125
+ )
126
+ # Delete data for next time test
127
  test_artifact.delete()
128
+
129
  def test_inference_frame(self):
130
+ if not os.path.exists("test_vid"):
131
+ os.mkdir("test_vid")
132
+ shutil.copyfile("demo.mp4", "test_vid/input.mp4")
133
+ thumbnail = inferenceFrame("test_vid")
134
+ assert os.path.exists("test_vid/out.mp4") and os.path.isfile("test_vid/out.mp4")
135
+ vidcap = cv2.VideoCapture("test_vid/input.mp4")
136
  success, image = vidcap.read()
137
  if success:
138
+ assert image.shape == thumbnail.shape
139
  vidcap.release()
140
  del vidcap
141
+ shutil.rmtree("test_vid")
142
+
143
  def test_create_thumbnal(self):
144
+ vidcap = cv2.VideoCapture("demo.mp4")
145
  success, image = vidcap.read()
146
  if success:
147
  createThumbnail(image, "")
148
+ result = mmcv.imread("thumbnail.jpg", channel_order="rgb")
149
+ assert result.shape == (160, 160, 3)