예제 #1
0
def test_large_course_insert(db_test_client):
    from application import db
    teachers = []
    for _ in range(random.randint(18,23)):
        username = get_random_unicode(35)
        password = get_random_unicode(30)
        first = get_random_unicode(15)
        last = get_random_unicode(25)

        db.insert_user(username, password, first, last, role="TEACHER")
        acc = db.get_user(username, password)
        assert acc.name == username
        assert acc.role == "TEACHER"
        teachers.append(acc)
    teach_courses = {}
    for t in teachers:
        teach_courses[t.id]=[]
        for _ in range(random.randint(12,20)):
            course = Course(get_random_unicode(20), get_random_unicode(40), random_datetime())
            id, code = db.insert_course(course, t.id)
            course.id = id
            course.code = code
            teach_courses[t.id].append(course)
    random.shuffle(teachers)
    for t in teachers:
        db_courses = db.select_courses_teacher(t.id)
        assert len(db_courses)>=12
        case = unittest.TestCase()
        case.assertCountEqual(db_courses, teach_courses[t.id])
    return teachers
예제 #2
0
def create_dummy(db:data, user_id=None, course=None, task=None, assignment=None, submit=None, answer=None):
    s = "useless"
    d = datetime.datetime.now()
    results = {}
    if not user_id:
        username = get_random_unicode(30)
        db.insert_user(username, s,s,s,role="TEACHER")
        user_id = db.get_user(username,s)
        results["teacher_id"]=user_id
    if not course:
        course, _ = db.insert_course(Course(s,s,d),user_id)
        results["course_id"]=course
    if not assignment:
        assignment = db.insert_assignment(user_id, course, s, d, d, [])
        results["assignment_id"]=assignment
    if not task:
        task = db.insert_task(user_id, assignment, s , 2, [])
        results["task_id"]=task
    if not answer:
        answer = db.update_answer(user_id, task, [], s, d)
        results["answer_id"]=answer
    if not submit:
        submit = db.update_submit(user_id, task, assignment, [])
        results["submit_id"]=submit

    return results
예제 #3
0
def select_course_details(self,
                          course_id: int,
                          user_id: int,
                          is_student: bool = True) -> Course:
    """Return the course object for the given id. For student doesn't matter, but is here cause I'm lazy (used to check if student has rights)

    Arguments:
        course_id {int} -- [description]
        user_id {int} -- [description]

    Keyword Arguments:
        is_student {bool} -- [doesn't matter] (default: {True})

    Returns:
        Course -- [course object with all simple fields set, including teacher id Assignments not set]
    """

    sql = select([self.course]).where(self.course.c.id == course_id)

    with self.engine.connect() as conn:
        rs = conn.execute(sql)
        self.logger.info("Fetching course %s for user %s", course_id, user_id)
        row = rs.fetchone()
        if row is None:
            rs.close()
            self.logger.warning("found no course matching parameters")
            return None
        c = Course(row[self.course.c.name],
                   row[self.course.c.description],
                   row[self.course.c.end_date],
                   id=row[self.course.c.id],
                   code=row[self.course.c.code],
                   teacher_id=row[self.course.c.teacher_id])
        rs.close()
    return c
예제 #4
0
def test_course_insert(db_test_client):
    from application import db
    from .user_test import test_user_insert
    test_user_insert(db_test_client)
    student = db.get_user_by_id(1)
    teacher = db.get_user_by_id(2)
    assert student is not None
    assert teacher is not None
    name = "'öäasöä1ÅÄÖÅÄÅÖÄÅÖö23å231äl23ölasäösä"
    desc = "äöääöäpläplpä21äl.masalöas"
    c = Course(name, desc, datetime.date.today())
    id, code = db.insert_course(c, teacher.id)

    assert id > 0 
    assert code is not None
    with db.engine.connect() as conn:
        sql = select([db.course]).where(db.course.c.teacher_id == teacher.id)
        rs = conn.execute(sql)
        row = rs.first()
        assert row[db.course.c.id] == id
        assert row[db.course.c.description] == desc
        assert row[db.course.c.name] == name

    

    return id, code
예제 #5
0
def select_courses_teacher(self, teacher_id: int) -> list:
    """Returns a list of course objects for the given id (meaning courses the teacher owns), only simple details are added

    Arguments:
        teacher_id {int} -- [description]

    Returns:
        list -- [list of Course objects]
    """
    self.logger.info("Fetching all courses for user (teacher) %s", teacher_id)
    sql = select([self.course]).where(self.course.c.teacher_id == teacher_id)
    with self.engine.connect() as conn:
        rs = conn.execute(sql)
        courses = []
        i = 0
        for row in rs:
            i += 1
            courses.append(
                Course(row[self.course.c.name],
                       row[self.course.c.description],
                       row[self.course.c.end_date],
                       code=row[self.course.c.code],
                       id=row[self.course.c.id],
                       teacher_id=row[self.course.c.teacher_id]))
            j = self.assignment.outerjoin(self.course)
            sql = select([func.min(self.assignment.c.deadline)]).select_from(
                j).where((self.course.c.id == row[self.course.c.id])
                         & (self.assignment.c.deadline > func.now()))
            rs = conn.execute(sql)
            min = rs.first()[0]
            courses[len(courses) - 1].min = min
        self.logger.info("Found %s courses", i)
    return courses
예제 #6
0
def set_assignments(self, course: Course, for_student=True):
    """Set Assignment fields for the given course. If for:student is provided, only assignment where reveal date is past will be added

    Arguments:
        course {Course} -- [course object to modify. Needs to have id field set]

    Keyword Arguments:
        for_student {bool} -- [wheather query is for student or teacher, students can't see assignment before their reveal date] (default: {True})
    """

    if course is None:
        self.logger.warning("Null course?")
        return
    self.logger.info("Seting assignments for course: %s (for student %s)",
                     str(course.id), for_student)
    j = self.assignment.join(self.task)
    sql = select([
        self.assignment, self.task
    ]).select_from(j).where(self.assignment.c.course_id == course.id).order_by(
        self.assignment.c.deadline, self.task.c.number)
    if for_student:
        sql = sql.where(self.assignment.c.reveal < func.now())

    with self.engine.connect() as conn:

        rs = conn.execute(sql)

        a = {}

        for row in rs:
            self.logger.debug(str(row))

            if row is None:
                self.logger.info("found no assignments matching parameters")
                continue
            assig_id = row[self.assignment.c.id]

            if a.get(assig_id) is None:
                assig = Assignment(
                    row[self.assignment.c.id], row[self.assignment.c.name],
                    row[self.assignment.c.reveal],
                    row[self.assignment.c.deadline], [
                        Task(row[self.task.c.id],
                             row[self.task.c.number],
                             row[self.task.c.points],
                             row[self.task.c.description],
                             assignment_id=row[self.assignment.c.id])
                    ])
                a[assig_id] = assig
            else:
                a[assig_id].tasks.append(
                    Task(row[self.task.c.id],
                         row[self.task.c.number],
                         row[self.task.c.points],
                         row[self.task.c.description],
                         assignment_id=row[self.assignment.c.id]))

    course.assignments = list(a.values())
예제 #7
0
def insert_random_courses(teacher_id, db, n=random.randint(1, 5)):
    ids = []
    for _ in range(n):
        name = get_random_unicode(random.randint(12, 18))
        desc = get_random_unicode(random.randint(9, 18))
        c = Course(name, desc, datetime.date.today(), teacher_id=teacher_id)
        id, _ = db.insert_course(c, teacher_id)
        ids.append(id)
    return ids
예제 #8
0
def test_select_file_details_multiple(db_test_client):
    from application import db
    db.insert_user("turha", "turha", "turha", "turha", role="TEACHER")
    user_id = db.get_user("turha","turha").id
    case = unittest.TestCase()
    case.maxDiff = None
    c_id, _ =db.insert_course(Course("something","somthing", datetime.datetime.now()),user_id)
    for _ in range(20):

        id_dic = create_dummy(db, user_id=user_id, course=c_id)
        correct_files= []
        for i in range(20):
            rand_bytes= os.urandom(20)
            name = "task"+str(id_dic["task_id"])+str(i)
            id = file_insert_helper(db,binary_file=rand_bytes, task_id=id_dic["task_id"], name=name, user_id=user_id)
            correct_files.append(File(id, name, datetime.datetime.now()))
        files = db.select_file_details(task_id=id_dic["task_id"])
        assert len(files) == 20
        
        case.assertCountEqual(files, correct_files)
        
        correct_bytes, _ = db.get_file(id)
        assert rand_bytes == correct_bytes

        rand_bytes= os.urandom(20)
        id = file_insert_helper(db,binary_file=rand_bytes,submit_id=id_dic["submit_id"], name="submit_id"+str(id_dic["submit_id"]), user_id=user_id)
        sub_id = id_dic["submit_id"]
        files = db.select_file_details(submit_id=sub_id)
        assert len(files) == 1
        assert files[0].name == "submit_id"+str(id_dic["submit_id"])
        assert files[0].id == id
        correct_bytes, _ = db.get_file(id)
        assert rand_bytes == correct_bytes


        rand_bytes= os.urandom(20)
        id = file_insert_helper(db,binary_file=rand_bytes,assignment_id=id_dic["assignment_id"], name="assignment_id"+str(id_dic["task_id"]), user_id=user_id)
        files = db.select_file_details(assignment_id=id_dic["assignment_id"])
        assert len(files) == 1
        assert files[0].name == "assignment_id"+str(id_dic["assignment_id"])
        assert files[0].id == id
        correct_bytes, _ = db.get_file(id)
        assert rand_bytes == correct_bytes

        rand_bytes= os.urandom(20)
        id = file_insert_helper(db,binary_file=rand_bytes,answer_id=id_dic["answer_id"], name="answer_id"+str(id_dic["task_id"]), user_id=user_id)
        files = db.select_file_details(answer_id=id_dic["answer_id"])
        assert len(files) == 1
        assert files[0].name == "answer_id"+str(id_dic["answer_id"])
        assert files[0].id == id
        correct_bytes, _ = db.get_file(id)
        assert rand_bytes == correct_bytes
예제 #9
0
def test_invalid_signup(db_test_client):
    from application import db
    
    description = get_random_unicode(100)
    reveal = pytz.utc.localize(datetime.datetime.utcnow()) - datetime.timedelta(minutes=1)
    teacher = insert_users(db, 1, roles=["TEACHER"])[0]
    student = insert_users(db, 1, roles=["USER"])[0]
    id, code = db.insert_course(Course("something", "something",reveal), teacher.id)
    db.enlist_student(code, student.id)
    with pytest.raises(IntegrityError):
        db.enlist_student(code, student.id)
    
    with pytest.raises(ValueError):
        db.enlist_student("something", student.id)
예제 #10
0
def test_select_file_details_single(db_test_client):
    from application import db
    db.insert_user("turha", "turha", "turha", "turha", role="TEACHER")
    user_id = db.get_user("turha","turha").id
    c_id, _ =db.insert_course(Course("something","somthing", datetime.datetime.now()),user_id)
    for _ in range(20):

        id_dic = create_dummy(db, user_id=user_id, course=c_id)
        rand_bytes= os.urandom(20)
        id = file_insert_helper(db,binary_file=rand_bytes, task_id=id_dic["task_id"], name="task"+str(id_dic["task_id"]), user_id=user_id)
        files = db.select_file_details(task_id=id_dic["task_id"])
        assert len(files) == 1
        assert files[0].name == "task"+str(id_dic["task_id"])
        assert files[0].id == id
        assert rand_bytes, _ == db.get_file(id)

        rand_bytes= os.urandom(20)
        id = file_insert_helper(db,binary_file=rand_bytes,submit_id=id_dic["submit_id"], name="submit_id"+str(id_dic["submit_id"]), user_id=user_id)
        sub_id = id_dic["submit_id"]
        files = db.select_file_details(submit_id=sub_id)
        assert len(files) == 1
        assert files[0].name == "submit_id"+str(id_dic["submit_id"])
        assert files[0].id == id
        assert rand_bytes, _ == db.get_file(id)


        rand_bytes= os.urandom(20)
        id = file_insert_helper(db,binary_file=rand_bytes,assignment_id=id_dic["assignment_id"], name="assignment_id"+str(id_dic["task_id"]), user_id=user_id)
        files = db.select_file_details(assignment_id=id_dic["assignment_id"])
        assert len(files) == 1
        assert files[0].name == "assignment_id"+str(id_dic["assignment_id"])
        assert files[0].id == id
        db_bytes, name = db.get_file(id)
        
        assert rand_bytes == db_bytes

        rand_bytes= os.urandom(20)
        id = file_insert_helper(db,binary_file=rand_bytes,answer_id=id_dic["answer_id"], name="answer_id"+str(id_dic["task_id"]), user_id=user_id)
        files = db.select_file_details(answer_id=id_dic["answer_id"])
        assert len(files) == 1
        assert files[0].name == "answer_id"+str(id_dic["answer_id"])
        assert files[0].id == id
        assert rand_bytes, _ == db.get_file(id)
예제 #11
0
def new_course():
    if current_user.role != "TEACHER":
        app.logger.info("non-teacher attempted insert")
        return redirect(url_for("index"))

    if request.method == "GET":
        return render_template("/teacher/new_course.html", form = CourseForm())
    
    form = CourseForm(request.form)
    if not form.validate():
        app.logger.info("form validation failed")
        render_template("/teacher/new_course.html", form = form)

    date = form.end_date.data
    if not date:
        date = datetime.date.today()
    
    id = db.insert_course(Course(form.name.data, form.description.data, form.end_date.data, time_zone="Europe/Helsinki"), current_user.get_id())
    
    return redirect(url_for("courses"))
예제 #12
0
def insert_courses(db, teacher_id, n):
    for _ in range(n):
        name = get_random_unicode(45)
        desc = get_random_unicode(23)
        c = Course(name, desc, random_datetime())
        id, code = db.insert_course(c, teacher_id)
예제 #13
0
def test_large_course_signup(db_test_client):
    from application import db
    from .user_test import test_weird_chars_large_set
    ids = test_weird_chars_large_set(db_test_client, random_roles=False)
    
    
    now = datetime.datetime.now()
    courses = []
    teacher_courses = {}
    accs = []
    for id in ids:
        acc = db.get_user_by_id(id)
        assert acc.id == id
        assert acc.role == "TEACHER" or acc.role=="USER"

        accs.append(acc)
        if acc.role == "TEACHER":
            teacher_courses[id] = []
            for _ in range(random.randint(14,16)):
                
                name = get_random_unicode(10)
                description = get_random_unicode(20)
                random_time = now + datetime.timedelta(days=random.randint(0, 30))
                c = Course(name, description, random_time, teacher_id=id)
                course_id, code = db.insert_course(c, id)
                c.id = course_id
                c.code = code
                assert c.teacher_id is not None
                courses.append(c)
                teacher_courses[id].append(c)
    student_enlists = {}
    for acc in accs:
        if acc.role == "USER":
            student_enlists[acc.id]=[]
            enlists = random.sample(courses, k=random.randint( len(courses)//2, len(courses)-1 ))
            for c in enlists:
                student_enlists[acc.id].append(c)
                db.enlist_student(c.code, acc.id)

    for acc in accs:
        if acc.role =="TEACHER":
            courses = db.select_courses_teacher(acc.id)
            real = teacher_courses[acc.id]
            assert len(real) == len(courses)
            assert len(real) > 10
            case = unittest.TestCase()
            case.assertCountEqual(courses, real)
            for c in courses:
                assert c.teacher_id == acc.id
                assert c in real, str(c)+" not found in"+", ".join(str(a) for a in real)
            
            for c in real:
                assert c in courses, str(c)+" not found in"+", ".join(str(c) for c in real)
        else:
            courses = db.select_courses_student(acc.id)
            real = student_enlists[acc.id]

            assert len(real) == len(courses)
            assert len(real) > 6
            case = unittest.TestCase()
            case.assertCountEqual(courses, real)
            for c in courses:
                assert c.teacher_id is not None
                assert c in real, str(c)+"not found in"+", ".join(str(c) for c in real)
            for c in real:
                assert c in courses, str(c)+"not found in"+", ".join(str(c) for c in real)
예제 #14
0
def test_large_answer_insert_and_update(db_test_client):
    from application import db
    visible_reveal = pytz.utc.localize(
        datetime.datetime.utcnow()) - datetime.timedelta(minutes=1)
    teacher = insert_users(db, 1, roles=["TEACHER"])[0]
    course_id, _ = db.insert_course(
        Course("something", "somthing", visible_reveal, visible_reveal),
        teacher.id)
    f = generate_random_file()
    file_name = secure_filename(get_random_unicode(30))
    werk_file = FileStorage(f, file_name)
    assignment_id = db.insert_assignment(teacher.id, course_id, "somthing",
                                         random_datetime(), visible_reveal,
                                         [werk_file])
    werk_file.close()
    all_answers = []
    visible_answers = []
    visible_tasks = []
    correct_files = FileMultiDict()
    for _ in range(100):
        task_id = db.insert_task(teacher.id, assignment_id,
                                 get_random_unicode(20), 20, [])
        hidden = random.randint(0, 1)
        if not hidden:
            visible_tasks.append(task_id)
            reveal = visible_reveal
        else:
            reveal = random_datetime()
        files = []
        for i in range(3):
            f = generate_random_file(length=10)
            file_name = str(task_id) + "t" + str(i)
            werk_file = FileStorage(f, file_name)
            files.append(werk_file)
            correct_files.add_file(task_id, werk_file, werk_file.filename)
        desc = get_random_unicode(30)
        id = db.update_answer(teacher.id, task_id, files, desc, reveal=reveal)

        answer = Answer(id, desc, reveal.replace(tzinfo=None),
                        db.select_file_details(answer_id=id))
        all_answers.append(answer)
        if not hidden:
            visible_answers.append(answer)

    for f in files:
        f.close()
    assignment = db.select_assignment(assignment_id, for_student=False)
    all_db_answers = []
    case = unittest.TestCase()
    assert len(assignment.tasks) == 100
    for t in assignment.tasks:
        assert isinstance(t, Task)
        db.set_task_answer(t, for_student=False)
        assert t.answer is not None
        a = t.answer
        assert isinstance(a, Answer)
        assert len(a.files) == 3
        correct_filenames = [
            file.filename for file in correct_files.getlist(t.id)
        ]
        assert len(correct_filenames) == 3
        db_filenames = [file.name for file in a.files]

        case.assertCountEqual(db_filenames, correct_filenames)
        all_db_answers.append(a)

    assert len(all_answers) == len(all_db_answers)
    case.maxDiff = None
    case.assertCountEqual(all_answers, all_db_answers)
    assignment = db.select_assignment(assignment_id, for_student=True)
    assert len(assignment.tasks) == 100

    db_visibles = []
    for t in assignment.tasks:
        assert isinstance(t, Task)
        db.set_task_answer(t, for_student=True)
        if t.id not in visible_tasks:
            assert t.answer is None
            continue
        assert t.answer is not None
        db_visibles.append(t.answer)
        a = t.answer
        assert isinstance(a, Answer)
        assert len(a.files) == 3
        correct_filenames = [
            file.filename for file in correct_files.getlist(t.id)
        ]
        assert len(correct_filenames) == 3
        db_filenames = [file.name for file in a.files]

        case.assertCountEqual(db_filenames, correct_filenames)

    case.assertCountEqual(db_visibles, visible_answers)
예제 #15
0
def test_simple_answer(db_test_client):
    from application import db

    reveal = pytz.utc.localize(
        datetime.datetime.utcnow()) - datetime.timedelta(minutes=1)
    teacher = insert_users(db, 1, roles=["TEACHER"])[0]
    student = insert_users(db, 1, roles=["USER"])[0]
    c_id, code = db.insert_course(Course("something", "something", reveal),
                                  teacher.id)
    db.enlist_student(code, student.id)
    f = generate_random_file()
    file_name = secure_filename(get_random_unicode(30))
    werk_file = FileStorage(f, file_name)
    a_id = db.insert_assignment(teacher.id, c_id, "ksakas", reveal, reveal,
                                [werk_file])
    t_id = db.insert_task(teacher.id, a_id, "something", 3, [werk_file])
    werk_file.close()
    files = []
    correct_files = FileMultiDict()
    for _ in range(5):
        f = generate_random_file()
        file_name = secure_filename(get_random_unicode(30))
        werk_file = FileStorage(f, file_name)
        files.append(werk_file)
        correct_files.add_file(file_name, werk_file)

    description = get_random_unicode(100)
    db.update_answer(teacher.id,
                     t_id,
                     files,
                     description,
                     reveal=random_datetime())

    assignment = db.select_assignment(a_id, task_id=t_id)

    assert assignment.name == "ksakas"

    assert len(assignment.tasks) == 1
    t = assignment.tasks[0]
    assert isinstance(t, Task)
    db.set_task_answer(assignment.tasks[0], for_student=False)

    assert t.answer is not None
    assert isinstance(t.answer, Answer)
    assert t.answer.description == description

    assert len(t.answer.files) == 5

    for db_f in t.answer.files:
        assert isinstance(db_f, File)
        c_f = correct_files.get(db_f.name)

        bin_file, name = db.get_file(db_f.id)
        assert name == db_f.name, "shouldn't fail... " + str(
            type(name)) + "  " + str(type(db_f.name))
        c_f.seek(0)
        assert bin_file == c_f.read()
        c_f.close()

    db.set_task_answer(t, for_student=True)
    assert t.answer is None