o
    ?h[                     @   s  d Z ddlZddlm  mZ ddlZddlZddl	Z	ddl
Z
ddlmZ dadd Zejjdd Zejjdd	 Zejjd
d Zejjdd Zejjdd Zejjdd Zejjdd Zejjdd Zejjdd Zejjdd Zejjdd Zejjdd ZdS )ag  
test_cameras.py

Purpose:
  Comprehensive test suite for camera management functionality including CRUD
  operations, data validation, API endpoint testing, and database consistency.
  Tests camera adding, renaming, deleting, listing, and user permission boundaries.
  
  This module implements red-team level security testing with comprehensive input
  validation and follows modular, well-organized patterns for production Apache2
  deployment scenarios. Each test ensures proper authentication, CSRF protection,
  and database state verification.

Test Categories:
  - Camera CRUD operations (add, rename, delete, list)
  - Data validation for camera IDs and names
  - API endpoint testing and responses
  - Database consistency verification
  - User permission boundaries and data isolation
  - Camera ID uniqueness validation
  - Authentication and CSRF protection
    N)get_dbc                  C   sR   t d7 a tt d d } t d }tdd}| d|d|d}|d	d
 S )z1Generate a unique 12-digit camera ID for testing.   i  i d   
   c   08d02dN   )_test_counterinttimerandomrandint)	timestampcounter_partrandom_part	unique_id r   ./var/www/html/tests/functional/test_cameras.pyget_unique_camera_id!   s   r   c                 C   s  |d }|d }t  }| jd|d |d dd}|j}d}||k}	|	sXtd	|	fd
||fdt v s9t|r>t|ndt|t|d }
dd|
i }t	t
|d } }	}| d |  T}|dd}|d}d}||u}|std|fd||fdt v st|rt|ndt|d }tdd d|i }
t	t
|
d }}W d   n1 sw   Y  | jd| ||d ddd}|j}d}||k}	|	std	|	fd
||fd t v st|rt|nd t|t|d }
dd|
i }t	t
|d } }	}t|j}|d! }d"}	||	u }|sOtd#|fd$||	ft|t|	d% }d&d'|i }t	t
|d } }}	| j  t }|d(||d f }d}||u}|std|fd||fd)t v st|rt|nd)t|d }d*d|i }
t	t
|
d }}|d+ }t|}||k}|std	|fd,||ft|d-t v sttrttnd-d.t v st|rt|nd.t|d/ }d0d1|i }t	t
|d } }}|d }|d }	||	k}|s9td	|fd2||	ft|t|	d% }d&d'|i }t	t
|d } }}	W d   dS 1 sKw   Y  dS )3zETest adding cameras with valid 12-digit IDs via POST /api/kamere/add.regularvalid/loginusernamepasswordr   r   data.  ==z3%(py2)s
{%(py2)s = %(py0)s.status_code
} == %(py5)slogin_responsepy0py2py5assert %(py7)spy7N/
csrf_token user_idis notz%(py0)s is not %(py3)sr$   py3zUser should be logged inz
>assert %(py5)sr&   /api/kamere/add?csrf_token=camera_name	camera_idr3   application/jsonjsoncontent_type   responsesuccessTisz%(py1)s is %(py4)spy1py4assert %(py6)spy6z=SELECT * FROM cameras WHERE camera_id = ? AND camera_name = ?cameraassert %(py5)sr5   )z0%(py1)s == %(py6)s
{%(py6)s = %(py3)s(%(py4)s)
}r   unique_camera_id)rA   r1   rB   rD   assert %(py8)spy8z%(py1)s == %(py4)s)r   poststatus_code
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationgetsession_transaction_format_assertmsgr8   loadsr   applicationapp_contextr   executefetchoner   )client
test_userssample_camera_datausercamera_datarG   r"   @py_assert1@py_assert4@py_assert3@py_format6@py_format8sessr*   r,   @py_assert2@py_format4r;   r   @py_assert0@py_format5@py_format7dbrE   @py_assert5@py_format9r   r   r   test_add_camera_valid_data-   sF   



l
~r$rp   c                 C   sR  |d }|d }| j d|d |d dd}|j}d}||k}|sUtd	|fd
||fdt v s6t|r;t|ndt|t|d }	dd|	i }
tt	|
d } }}| 
d |  }|
dd}W d   n1 suw   Y  | j d| |d |d ddd}|j}d}||k}|std	|fd
||fdt v st|rt|ndt|t|d }	dd|	i }
tt	|
d } }}t|j}|d }d}||u }|std|fd||ft|t|d }d d!|i }tt	|d } }}d"}|d# }||v }|s=td$|fd%||ft|t|d }d d!|i }tt	|d } }}| j V t }|d&|d f }d}||u }|std|fd'||fd(t v swt|r|t|nd(t|d) }d*d+|i }	tt	|	d }}W d   dS 1 sw   Y  dS ),zFTest adding cameras with invalid short IDs returns appropriate errors.r   invalid_short_idr   r   r   r   r   r   r   r!   r"   r#   r'   r(   Nr)   r*   r+   r2   r5   r3   r4   r6   r7     r;   r<   Fr=   r?   r@   rC   rD   znamenkimessageinz%(py1)s in %(py4)s)SELECT * FROM cameras WHERE camera_id = ?z%(py0)s is %(py3)srE   r0   rF   r&   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   rU   rV   r8   rX   r   rY   rZ   r   r[   r\   r]   r^   r_   r`   ra   r"   rb   rc   rd   re   rf   rg   r*   r;   r   rj   rh   rk   rl   rm   rE   ri   r   r   r    test_add_camera_invalid_short_id^   s>   


ll$r|   c                 C   s  |d }|d }| j d|d |d dd}|j}d}||k}|sUtd	|fd
||fdt v s6t|r;t|ndt|t|d }	dd|	i }
tt	|
d } }}| 
d |  }|
dd}W d   n1 suw   Y  | j d| |d |d ddd}|j}d}||k}|std	|fd
||fdt v st|rt|ndt|t|d }	dd|	i }
tt	|
d } }}t|j}|d }d}||u }|std|fd||ft|t|d }d d!|i }tt	|d } }}| j V t }|d"|d f }d}||u }|s\td|fd#||fd$t v sAt|rFt|nd$t|d% }d&d'|i }	tt	|	d }}W d   dS 1 slw   Y  dS )(zLTest adding cameras with invalid non-numeric IDs returns appropriate errors.r   invalid_non_numericr   r   r   r   r   r   r   r!   r"   r#   r'   r(   Nr)   r*   r+   r2   r5   r3   r4   r6   r7   rr   r;   r<   Fr=   r?   r@   rC   rD   z+SELECT * FROM cameras WHERE camera_name = ?ry   rE   r0   rF   r&   rz   r{   r   r   r   &test_add_camera_invalid_non_numeric_id   s<   


l$r~   c                 C   sP  |d }|d }t  }| jd|d |d dd}|j}d}||k}	|	sXtd	|	fd
||fdt v s9t|r>t|ndt|t|d }
dd|
i }t	t
|d } }	}| d |  }|dd}W d   n1 sxw   Y  | jd| ||d ddd}|j}d}||k}	|	std	|	fd
||fdt v st|rt|ndt|t|d }
dd|
i }t	t
|d } }	}t|j}|d }d}	||	u }|std|fd||	ft|t|	d }dd |i }t	t
|d } }}	d!}|d" }	||	v }|s>td#|fd$||	ft|t|	d }dd |i }t	t
|d } }}	| j T t }|d%|f }d}||u }|std|fd&||fd't v svt|r{t|nd't|d( }d)d*|i }
t	t
|
d }}W d   dS 1 sw   Y  dS )+z@Test adding cameras with empty names returns appropriate errors.r   invalid_empty_namer   r   r   r   r   r   r   r!   r"   r#   r'   r(   Nr)   r*   r+   r2   r3   r4   r6   r7   rr   r;   r<   Fr=   r?   r@   rC   rD   obaveznort   ru   rw   rx   ry   rE   r0   rF   r&   )r   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   rU   rV   r8   rX   r   rY   rZ   r   r[   r\   r]   r^   r_   r`   ra   rG   r"   rb   rc   rd   re   rf   rg   r*   r;   r   rj   rh   rk   rl   rm   rE   ri   r   r   r   test_add_camera_empty_name   s@   


ll$r   c                 C   sZ  |d }t  }|d }| jd|d |d dd}|j}d}||k}	|	sXtd	|	fd
||fdt v s9t|r>t|ndt|t|d }
dd|
i }t	t
|d } }	}|  I}|d}d}||u}|std|fd||fdt v st|rt|ndt|d }dd|i }
t	t
|
d }}W d   n1 sw   Y  | j  t }|d|t||d f |  W d   n1 sw   Y  | d}|j}d}||k}	|	s#td	|	fd
||fdt v st|r	t|ndt|t|d }
dd|
i }t	t
|d } }	}t|j}d}||v }|sjtd|fd||ft|dt v sSt|rXt|ndd }dd|i }
t	t
|
d }}|d }t|t}	|	sd d!t v sttrttnd!dt v st|rt|ndd"t v sttrttnd"t|	d# }t	t
|d}	t|}d$}||k}|std%|fd&||fd't v sttrttnd'dt v st|rt|ndt|t|d( }d)d*|i }t	t
|d } }}d}|D ]}|d+ |kr2|} nq%d}||u}|sotd|fd||fd,t v sTt|rYt|nd,t|d }dd|i }
t	t
|
d }}|d }|d }	||	k}|std	|fd-||	ft|t|	d. }d/d0|i }t	t
|d } }}	dS )1z:Test retrieving camera lists via GET /api/kamere endpoint.r   r   r   r   r   r   r   r   r   r!   r"   r#   r'   r(   Nr,   r-   r/   r0   rF   r&   FINSERT INTO cameras (user_id, camera_id, camera_name) VALUES (?, ?, ?)r3   /api/kamerer:   r;   camerasru   )z%(py1)s in %(py3)sr   rA   r1   z5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstancelist)r$   rA   r%   rB   r   )>)z/%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} > %(py6)slenr$   rA   r1   rD   rH   rI   r5   
our_camerarJ   r@   rC   rD   )r   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   rV   rU   rY   rZ   r   r[   r   commitr8   rX   r   r   r   r   )r]   r^   r_   r`   rG   ra   r"   rb   rc   rd   re   rf   rg   r,   rh   ri   rm   r;   r   rj   r   rk   rn   rl   ro   r   rE   r   r   r   test_retrieve_camera_list_api   sF   


z

	~~tr   c                 C   sl  |d }|d }d}t  }| jd|d |d dd}|j}d	}	||	k}
|
sZtd
|
fd||	fdt v s;t|r@t|ndt|t|	d }dd|i }t	t
|d } }
}	|  I}|d}d}||u}|std|fd||fdt v st|rt|ndt|d }dd|i }t	t
|d }}W d   n1 sw   Y  | j  t }|d|t||d f |  W d   n1 sw   Y  | d |  }|dd}W d   n1 sw   Y  | jd| ||ddd}|j}d }	||	k}
|
sMtd
|
fd||	fd!t v s.t|r3t|nd!t|t|	d }dd|i }t	t
|d } }
}	t|j}|d" }d#}
||
u }|std$|fd%||
ft|t|
d& }d'd(|i }t	t
|d } }}
| j  t }|d)t|f }d}||u}|std|fd||fd*t v st|rt|nd*t|d }dd|i }t	t
|d }}|d }||k}|std
|fd+||ft|d,t v st|rt|nd,d- }dd|i }t	t
|d }}W d   dS 1 s/w   Y  dS ).z;Test renaming existing cameras via POST /api/kamere/rename.r   r   zRenamed Test Camerar   r   r   r   r   r   r   r!   r"   r#   r'   r(   Nr,   r-   r/   r0   rF   r&   r   r3   r)   r*   r+   /api/kamere/rename?csrf_token=r4   r6   r7   r:   r;   r<   Tr=   r?   r@   rC   rD   rx   rE   )z%(py1)s == %(py3)snew_namer   r   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   rV   rU   rY   rZ   r   r[   r   r   r8   rX   r   r\   )r]   r^   r_   r`   ra   r   rG   r"   rb   rc   rd   re   rf   rg   r,   rh   ri   rm   r*   r;   r   rj   rk   rl   rE   r   r   r   test_rename_existing_camera  sZ   


z

	
l~$r   c                 C   s  |d }|d }t  }| jd|d |d dd}|j}d}||k}	|	sXtd	|	fd
||fdt v s9t|r>t|ndt|t|d }
dd|
i }t	t
|d } }	}|  I}|d}d}||u}|std|fd||fdt v st|rt|ndt|d }dd|i }
t	t
|
d }}W d   n1 sw   Y  | j  t }|d|t||d f |  W d   n1 sw   Y  | d |  }|dd}W d   n1 sw   Y  | jd| d|idd}|j}d}||k}	|	sJtd	|	fd
||fd t v s+t|r0t|nd t|t|d }
dd|
i }t	t
|d } }	}t|j}|d! }d"}	||	u }|std#|fd$||	ft|t|	d% }d&d'|i }t	t
|d } }}	| j V t }|d(t|f }d}||u }|std#|fd)||fd*t v st|rt|nd*t|d }dd|i }
t	t
|
d }}W d   dS 1 sw   Y  dS )+z2Test deleting cameras via POST /api/kamere/delete.r   r   r   r   r   r   r   r   r   r!   r"   r#   r'   r(   Nr,   r-   r/   r0   rF   r&   r   r3   r)   r*   r+   z/api/kamere/delete?csrf_token=r5   r6   r7   r:   r;   r<   Tr=   r?   r@   rC   rD   rx   ry   rE   r   )r]   r^   r_   r`   ra   rG   r"   rb   rc   rd   re   rf   rg   r,   rh   ri   rm   r*   r;   r   rj   rk   rl   rE   r   r   r   test_delete_existing_cameraJ  sT   


z

	
l$r   c           "   
   C   s8  |d }t  }t  }| jd|d |d dd}|j}d}||k}	|	sWtd|	fd	||fd
t v s8t|r=t|nd
t|t|d }
dd|
i }t	t
|d } }	}|  I}|d}d}||u}|std|fd||fdt v st|rt|ndt|d }dd|i }
t	t
|
d }}W d   n1 sw   Y  g }| j G t }t||d f||d fgD ])\}\}}|d|t||d  d| f |t||d  d| d q|  W d   n	1 sw   Y  | d}|j}d}||k}	|	sPtd|	fd	||fdt v s1t|r6t|ndt|t|d }
dd|
i }t	t
|d } }	}t|j}|d }| j  t }|d|f }W d   n	1 s}w   Y  t|}t|}||k}|s td|fd ||fd!t v sttrttnd!d"t v st|rt|nd"t|d!t v sttrttnd!d#t v st|rt|nd#t|d$ }d%d&|i }t	t
|d } }}|D ]}d}|D ]}|d' t|d' kr|} nqd}||u}|s\td|fd||fd(t v sAt|rFt|nd(t|d }dd|i }
t	t
|
d }}|d }|d }	||	k}|std|fd)||	ft|t|	d* } d+d,| i }!t	t
|!d } }}	qdS )-z6Test database cameras match API responses consistency.r   r   r   r   r   r   r   r   r!   r"   r#   r'   r(   Nr,   r-   r/   r0   rF   r&   r   valid_2r   r3    r4   r   r:   r;   r   z'SELECT * FROM cameras WHERE user_id = ?)zN%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py8)s
{%(py8)s = %(py5)s(%(py6)s)
}r   api_cameras
db_cameras)r$   rA   r1   r&   rD   rI   zassert %(py10)spy10r5   
api_camerarJ   r@   rC   rD   )r   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   rV   rU   rY   rZ   r   	enumerater[   r   appendr   r8   rX   r   fetchallr   str)"r]   r^   r_   r`   unique_camera_id_1unique_camera_id_2r"   rb   rc   rd   re   rf   rg   r,   rh   ri   cameras_addedrm   ir5   ra   r;   api_datar   r   @py_assert7ro   @py_format11	db_camerar   camrj   rk   rl   r   r   r   )test_database_cameras_match_api_responses  sl   


z





 ~tr   c                 C   sZ  |d }|d }|d }t  }| jd|d |d dd}|j}d	}	||	k}
|
s\td
|
fd||	fdt v s=t|rBt|ndt|t|	d }dd|i }t	t
|d } }
}	|  I}|d}d}||u}|std|fd||fdt v st|rt|ndt|d }dd|i }t	t
|d }}W d   n1 sw   Y  | j  t }|d|t||d f |  W d   n1 sw   Y  | jdddid | jd|d |d dd}|j}d	}	||	k}
|
s9td
|
fd||	fdt v st|rt|ndt|t|	d }dd|i }t	t
|d } }
}	| d}|j}d}	||	k}
|
std
|
fd||	fdt v sgt|rlt|ndt|t|	d }dd|i }t	t
|d } }
}	t|j}|d }|D ]D}|d  }||k}|std!|fd"||ft|d#t v st|rt|nd#d$ }dd|i }t	t
|d }}q| d% |  }|dd}W d   n	1 sw   Y  | jd&| |d'd(d)d*}|j}d+}	||	k}
|
sMtd
|
fd||	fdt v s.t|r3t|ndt|t|	d }dd|i }t	t
|d } }
}	t|j}|d, }d-}
||
u }|std.|fd/||
ft|t|
d0 }d1d2|i }t	t
|d } }}
| j  t }|d3t|f }d}||u}|std|fd||fd4t v st|rt|nd4t|d }dd|i }t	t
|d }}|d }|d }
||
k}|std
|fd5||
ft|t|
d0 }d1d2|i }t	t
|d } }}
W d   dS 1 s&w   Y  dS )6z-Test users can only manage their own cameras.r   limitedr   r   r   r   r   r   r   r   r!   r"   r#   r'   r(   Nr,   r-   r/   r0   rF   r&   r   r3   z/logoutr*   r+   r   r:   r;   r   r5   )!=)z%(py1)s != %(py3)srG   r   r)   r   zHacked Camera Namer4   r6   r7   i  r<   Fr=   r?   r@   rC   rD   rx   rE   rJ   r   )r]   r^   r_   user_regularuser_limitedra   rG   r"   rb   rc   rd   re   rf   rg   r,   rh   ri   rm   r;   limited_datalimited_camerasrE   rj   r*   r   rk   rl   r   r   r   test_user_isolation_cameras  sr   


z
	



l~r$r   c                 C   s:  |d }|d }t  }| jd|d |d dd}|j}d}||k}	|	sXtd	|	fd
||fdt v s9t|r>t|ndt|t|d }
dd|
i }t	t
|d } }	}| d |  }|dd}W d   n1 sxw   Y  | jd| ||d ddd}|j}d}||k}	|	std	|	fd
||fdt v st|rt|ndt|t|d }
dd|
i }t	t
|d } }	}| jd| |dddd}|j}d}||k}	|	s"td	|	fd
||fdt v st|rt|ndt|t|d }
dd|
i }t	t
|d } }	}t|j}|d }d}	||	u }|s^td|fd||	ft|t|	d  }d!d"|i }t	t
|d } }}	d#}|d$ }	||	v }|std%|fd&||	ft|t|	d  }d!d"|i }t	t
|d } }}	| j s t }|d't|f }t|}d(}||k}|std	|fd)||fd*t v sttrttnd*d+t v st|rt|nd+t|t|d, }d-d.|i }t	t
|d } }}W d   dS 1 sw   Y  dS )/z%Test camera ID uniqueness validation.r   r   r   r   r   r   r   r   r   r!   r"   r#   r'   r(   Nr)   r*   r+   r2   r3   r4   r6   r7   r:   r;   zDifferent Camera Namei  r<   Fr=   r?   r@   rC   rD   u   već postojirt   ru   rw   rx   r   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)sr   r   r   rH   rI   )r   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   rU   rV   r8   rX   r   rY   rZ   r   r[   r   r   r   )r]   r^   r_   r`   ra   rG   r"   rb   rc   rd   re   rf   rg   r*   r;   r   rj   rh   rk   rl   rm   r   rn   ro   r   r   r   $test_camera_id_uniqueness_validation  sN   


ll$r   c                 C   s(  g d}|D ]
\}}|dkr|  |}n| j|i d}|j}g d}||v }|s]td|fd||fdt v s>t|rCt|ndt|t|d }d	d
|i }	t	t
|	d } }}|jdkrg }d}
|j}|
|v }|}|sd}|j}||v }|}|std|fd|
|ft|
dt v st|rt|ndt|d }	dd|	i }|| |std|fd||ft|dt v st|rt|ndt|d }dd|i }|| t|di  }dd|i }t	t
|d } } }
 } } } }}qdS )z.Test camera operations require authentication.))r   GET)z/api/kamere/addPOST)z/api/kamere/renamer   )z/api/kamere/deleter   r   )r8   )r   i  i  ru   )z3%(py2)s
{%(py2)s = %(py0)s.status_code
} in %(py5)sr;   r#   r'   r(   Nr   r)   login)z0%(py3)s in %(py7)s
{%(py7)s = %(py5)s.location
})r1   r&   r(   z%(py9)spy9)z4%(py12)s in %(py16)s
{%(py16)s = %(py14)s.location
})py12py14py16z%(py18)spy18r   zassert %(py21)spy21)rU   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   locationr   _format_boolop)r]   endpoints_to_testendpointmethodr;   rb   rc   rd   re   rf   rh   @py_assert6rj   @py_assert11@py_assert15@py_assert13@py_format10@py_format17@py_format19@py_format20@py_format22r   r   r   -test_camera_operations_require_authenticationK  s   R r   c                 C   s  |d }|d }t  }| jd|d |d dd}|j}d}||k}	|	sXtd	|	fd
||fdt v s9t|r>t|ndt|t|d }
dd|
i }t	t
|d } }	}| d |  }|dd}W d   n1 sxw   Y  | jd| ||d ddd}|j}d}||k}	|	std	|	fd
||fdt v st|rt|ndt|t|d }
dd|
i }t	t
|d } }	}t|j}|d }d}	||	u }|std|fd||	ft|t|	d }dd |i }t	t
|d } }}	| j V t }|d!t|f }d}||u}|s]td"|fd#||fd$t v sBt|rGt|nd$t|d% }d&d'|i }
t	t
|
d }}W d   dS 1 smw   Y  dS )(z1Test camera operations work with CSRF protection.r   r   r   r   r   r   r   r   r   r!   r"   r#   r'   r(   Nr)   r*   r+   r2   r3   r4   r6   r7   r:   r;   r<   Tr=   r?   r@   rC   rD   rx   r-   r/   rE   r0   rF   r&   )r   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   rU   rV   r8   rX   r   rY   rZ   r   r[   r   r\   r   r   r   r   $test_camera_add_with_csrf_protectione  s>   


l$r   )__doc__builtinsrO   _pytest.assertion.rewrite	assertionrewriterM   pytestr8   r   r   app_modules.dbr   r
   r   markr   rp   r|   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s@    "
0
(
'
+
3
:
7
C
N
5
