def update(dataset_id, dictionary, author_id):
    # TODO(roman): Make author_id argument optional (keep old author if None).
    dataset_validator.validate(dictionary)

    with db.engine.begin() as connection:
        if "description" not in dictionary:
            dictionary["description"] = None

        connection.execute("""UPDATE dataset
                          SET (name, description, public, author, last_edited) = (%s, %s, %s, %s, now())
                          WHERE id = %s""",
                           (dictionary["name"], dictionary["description"], dictionary["public"], author_id, dataset_id))

        # Replacing old classes with new ones
        connection.execute("""DELETE FROM dataset_class WHERE dataset = %s""", (dataset_id,))

        for cls in dictionary["classes"]:
            if "description" not in cls:
                cls["description"] = None
            result = connection.execute("""INSERT INTO dataset_class (name, description, dataset)
                              VALUES (%s, %s, %s) RETURNING id""",
                                        (cls["name"], cls["description"], dataset_id))
            cls_id = result.fetchone()[0]

            for recording_mbid in cls["recordings"]:
                connection.execute("INSERT INTO dataset_class_member (class, mbid) VALUES (%s, %s)",
                                   (cls_id, recording_mbid))
def create_from_dict(dictionary, author_id):
    """Creates a new dataset from a dictionary.

    Returns:
        Tuple with two values: new dataset ID and error. If error occurs first
        will be None and second is an exception. If there are no errors, second
        value will be None.
    """
    dataset_validator.validate(dictionary)

    with db.engine.begin() as connection:
        if "description" not in dictionary:
            dictionary["description"] = None

        result = connection.execute("""INSERT INTO dataset (id, name, description, public, author)
                          VALUES (uuid_generate_v4(), %s, %s, %s, %s) RETURNING id""",
                       (dictionary["name"], dictionary["description"], dictionary["public"], author_id))
        dataset_id = result.fetchone()[0]

        for cls in dictionary["classes"]:
            if "description" not in cls:
                cls["description"] = None
            result = connection.execute("""INSERT INTO dataset_class (name, description, dataset)
                              VALUES (%s, %s, %s) RETURNING id""",
                           (cls["name"], cls["description"], dataset_id))
            cls_id = result.fetchone()[0]

            # Removing duplicate recordings
            cls["recordings"] = list(set(cls["recordings"]))

            for recording_mbid in cls["recordings"]:
                connection.execute("INSERT INTO dataset_class_member (class, mbid) VALUES (%s, %s)",
                               (cls_id, recording_mbid))

    return dataset_id
Esempio n. 3
0
def update(dataset_id, dictionary, author_id):
    # TODO(roman): Make author_id argument optional (keep old author if None).
    dataset_validator.validate(dictionary)

    with db.engine.begin() as connection:
        if "description" not in dictionary or dictionary["description"] is None:
            dictionary["description"] = ""

        connection.execute(
            """UPDATE dataset
                          SET (name, description, public, author, last_edited) = (%s, %s, %s, %s, now())
                          WHERE id = %s""",
            (dictionary["name"], dictionary["description"],
             dictionary["public"], author_id, dataset_id))

        # Replacing old classes with new ones
        connection.execute("""DELETE FROM dataset_class WHERE dataset = %s""",
                           (dataset_id, ))

        for cls in dictionary["classes"]:
            if "description" not in cls or cls["description"] is None:
                cls["description"] = ""
            result = connection.execute(
                """INSERT INTO dataset_class (name, description, dataset)
                              VALUES (%s, %s, %s) RETURNING id""",
                (cls["name"], cls["description"], dataset_id))
            cls_id = result.fetchone()[0]

            for recording_mbid in cls["recordings"]:
                connection.execute(
                    "INSERT INTO dataset_class_member (class, mbid) VALUES (%s, %s)",
                    (cls_id, recording_mbid))
    def test_dataset_item_lengths(self):
        # Incorrect lengths
        with self.assertRaises(dataset_validator.ValidationException) as ar:
            dataset_validator.validate({
                "name": "",  # Smaller than Min Len
                "classes": [],
                "public": False,
            })
        self.assertEqual(str(ar.exception), "Dataset name must be between 1 and 100 characters")

        with self.assertRaises(dataset_validator.ValidationException) as ar:
            dataset_validator.validate({
                "name": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuv \
                wxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghj",  # Greater than Max Len
                "classes": [],
                "public": False,
            })
        self.assertEqual(str(ar.exception), "Dataset name must be between 1 and 100 characters")

        with self.assertRaises(dataset_validator.ValidationException) as ar:
            dataset_validator.validate({
                "name": "this dataset",
                "classes": [
                    {
                        "name": "",  # Smaller than Min Len
                        "recordings": [],
                    },
                ],
                "public": False,
            })
        self.assertEqual(str(ar.exception), "Length of the `name` field in class number 0 doesn't fit the limits. Class name must be between 1 and 100 characters")

        with self.assertRaises(dataset_validator.ValidationException) as ar:
            dataset_validator.validate({
                "name": "this dataset",
                "classes": [
                    {
                        "name": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl \
                mnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghj", #Greater than Max Len
                        "recordings": [],
                    },
                ],
                "public": False,
            })
        self.assertEqual(str(ar.exception), "Length of the `name` field in class number 0 doesn't fit the limits. Class name must be between 1 and 100 characters")

        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    {
                        "name": "Not Rock",
                        "why": "Because",  # this item shouldn't be there
                        "recordings": [],
                    },
                ],
                "public": False,
            })
 def test_dataset_unexpected_items(self):
     # Unexpected items
     with self.assertRaises(dataset_validator.ValidationException):
         dataset_validator.validate({
             "i_like": "to test",
         })
     with self.assertRaises(dataset_validator.ValidationException):
         dataset_validator.validate({
             "i": "don't",
         })
     with self.assertRaises(dataset_validator.ValidationException):
         dataset_validator.validate({
             "name": "Dataset",
             "surname": "For Testing",  # this item shouldn't be there
             "classes": [
                 {
                     "name": "Not Rock",
                     "recordings": [],
                 },
             ],
             "public": False,
         })
     with self.assertRaises(dataset_validator.ValidationException):
         dataset_validator.validate({
             "name": "Dataset",
             "classes": [
                 {
                     "name": "Rock",
                     "why": "Because",  # this item shouldn't be there
                     "recordings": [],
                 },
             ],
             "public": True,
         })
 def test_dataset_missing_values(self):
     # Missing values
     with self.assertRaises(dataset_validator.ValidationException):
         # Dataset name is missing
         dataset_validator.validate({
             "classes": [
                 {
                     "name": "the one and only",
                     "recordings": [],
                 },
             ],
             "public":
             False,
         })
     with self.assertRaises(dataset_validator.ValidationException):
         # List of classes is missing
         dataset_validator.validate({
             "name": "test",
             "public": False,
         })
     with self.assertRaises(dataset_validator.ValidationException):
         # Publicity value is missing
         dataset_validator.validate({
             "name": "test",
             "classes": [],
         })
     with self.assertRaises(dataset_validator.ValidationException):
         # Class name is missing
         dataset_validator.validate({
             "name": "test",
             "classes": [
                 {
                     "recordings": [],
                 },
             ],
             "public": False,
         })
     with self.assertRaises(dataset_validator.ValidationException):
         # List of recordings in a class is missing
         dataset_validator.validate({
             "name": "test",
             "classes": [
                 {
                     "name": "this",
                 },
             ],
             "public": False,
         })
 def test_dataset_missing_values(self):
     # Missing values
     with self.assertRaises(dataset_validator.ValidationException):
         # Dataset name is missing
         dataset_validator.validate({
             "classes": [
                 {
                     "name": "the one and only",
                     "recordings": [],
                 },
             ],
             "public": False,
         })
     with self.assertRaises(dataset_validator.ValidationException):
         # List of classes is missing
         dataset_validator.validate({
             "name": "test",
             "public": False,
         })
     with self.assertRaises(dataset_validator.ValidationException):
         # Publicity value is missing
         dataset_validator.validate({
             "name": "test",
             "classes": [],
         })
     with self.assertRaises(dataset_validator.ValidationException):
         # Class name is missing
         dataset_validator.validate({
             "name": "test",
             "classes": [
                 {
                     "recordings": [],
                 },
             ],
             "public": False,
         })
     with self.assertRaises(dataset_validator.ValidationException):
         # List of recordings in a class is missing
         dataset_validator.validate({
             "name": "test",
             "classes": [
                 {
                     "name": "this",
                 },
             ],
             "public": False,
         })
 def test_dataset_item_lengths(self):
     # Incorrect lengths
     with self.assertRaises(dataset_validator.ValidationException):
         dataset_validator.validate({
             "name": "",  # incorrect
             "classes": [],
             "public": False,
         })
     with self.assertRaises(dataset_validator.ValidationException):
         dataset_validator.validate({
             "name":
             "this dataset",
             "classes": [
                 {
                     "name": "",  # incorrect
                     "recordings": [],
                 },
             ],
             "public":
             False,
         })
     with self.assertRaises(dataset_validator.ValidationException):
         dataset_validator.validate({
             "name":
             "test",
             "classes": [
                 {
                     "name": "Not Rock",
                     "why": "Because",  # this item shouldn't be there
                     "recordings": [],
                 },
             ],
             "public":
             False,
         })
def create_from_dict(dictionary, author_id):
    """Creates a new dataset from a dictionary.

    Returns:
        Tuple with two values: new dataset ID and error. If error occurs first
        will be None and second is an exception. If there are no errors, second
        value will be None.
    """
    dataset_validator.validate(dictionary)

    with db.engine.begin() as connection:
        if "description" not in dictionary:
            dictionary["description"] = None

        result = connection.execute("""INSERT INTO dataset (id, name, description, public, author)
                          VALUES (uuid_generate_v4(), %s, %s, %s, %s) RETURNING id""",
                                    (dictionary["name"], dictionary["description"], dictionary["public"], author_id))
        dataset_id = result.fetchone()[0]

        for cls in dictionary["classes"]:
            if "description" not in cls:
                cls["description"] = None
            result = connection.execute("""INSERT INTO dataset_class (name, description, dataset)
                              VALUES (%s, %s, %s) RETURNING id""",
                                        (cls["name"], cls["description"], dataset_id))
            cls_id = result.fetchone()[0]

            # Remove duplicate recordings, preserving order
            seen = set()
            cls["recordings"] = [r for r in cls["recordings"] if not (r in seen or seen.add(r))]

            for recording_mbid in cls["recordings"]:
                connection.execute("INSERT INTO dataset_class_member (class, mbid) VALUES (%s, %s)",
                                   (cls_id, recording_mbid))

    return dataset_id
 def test_dataset_unexpected_items(self):
     # Unexpected items
     with self.assertRaises(dataset_validator.ValidationException):
         dataset_validator.validate({
             "i_like": "to test",
         })
     with self.assertRaises(dataset_validator.ValidationException):
         dataset_validator.validate({
             "i": "don't",
         })
     with self.assertRaises(dataset_validator.ValidationException):
         dataset_validator.validate({
             "name":
             "Dataset",
             "surname":
             "For Testing",  # this item shouldn't be there
             "classes": [
                 {
                     "name": "Not Rock",
                     "recordings": [],
                 },
             ],
             "public":
             False,
         })
     with self.assertRaises(dataset_validator.ValidationException):
         dataset_validator.validate({
             "name":
             "Dataset",
             "classes": [
                 {
                     "name": "Rock",
                     "why": "Because",  # this item shouldn't be there
                     "recordings": [],
                 },
             ],
             "public":
             True,
         })
    def test_dataset_incorrect_types(self):
        # Incorrect types

        # String, not dict
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate("dataset")

        # Name should be string
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": ["This", "is", "my", "cool", "dataset"],
                "classes": [],
                "public":
                False,
            })

        # Desc should be string
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "description": False,
                "classes": [],
                "public": False,
            })

        # Classes should be list
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "description": "",
                "classes": None,
                "public": False,
            })

        # public should be bool
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "description": "",
                "classes": [],
                "public": "Nope",
            })

        # class name should be string
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name":
                "test",
                "classes": [
                    {
                        "name": ("this", "is", "a", "name"),
                        "recordings": [],
                    },
                ],
                "public":
                False,
            })

        # class elements should be dict
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    "first",
                    "second",
                ],
                "public": False,
            })

        # Class desc should be string
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name":
                "test",
                "classes": [
                    {
                        "name": "first",
                        "description": False,
                        "recordings": [],
                    },
                ],
                "public":
                False,
            })

        # class recordings should be list
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name":
                "test",
                "classes": [
                    {
                        "name": "first",
                        "recordings": "I don't have any :(",
                    },
                ],
                "public":
                False,
            })

        # Class recordings should be uuids
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name":
                "test",
                "classes": [
                    {
                        "name": "first",
                        "recordings": ["my favourite"],
                    },
                ],
                "public":
                False,
            })
    def test_dataset_item_lengths(self):
        # Incorrect lengths
        with self.assertRaises(dataset_validator.ValidationException) as ar:
            dataset_validator.validate({
                "name": "",  # Smaller than Min Len
                "classes": [],
                "public": False,
            })
        self.assertEqual(six.ensure_text(ar.exception.error),
                         "Dataset name must be between 1 and 100 characters")

        with self.assertRaises(dataset_validator.ValidationException) as ar:
            dataset_validator.validate({
                "name":
                "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuv \
                wxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghj",  # Greater than Max Len
                "classes": [],
                "public": False,
            })
        self.assertEqual(six.ensure_text(ar.exception.error),
                         "Dataset name must be between 1 and 100 characters")

        with self.assertRaises(dataset_validator.ValidationException) as ar:
            dataset_validator.validate({
                "name":
                "this dataset",
                "classes": [
                    {
                        "name": "",  # Smaller than Min Len
                        "recordings": [],
                    },
                ],
                "public":
                False,
            })
        self.assertEqual(
            six.ensure_text(ar.exception.error),
            "Length of the `name` field in class number 0 doesn't fit the limits. Class name must be between 1 and 100 characters"
        )

        with self.assertRaises(dataset_validator.ValidationException) as ar:
            dataset_validator.validate({
                "name":
                "this dataset",
                "classes": [
                    {
                        "name":
                        "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl \
                mnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghj",  #Greater than Max Len
                        "recordings": [],
                    },
                ],
                "public":
                False,
            })
        self.assertEqual(
            six.ensure_text(ar.exception.error),
            "Length of the `name` field in class number 0 doesn't fit the limits. Class name must be between 1 and 100 characters"
        )

        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name":
                "test",
                "classes": [
                    {
                        "name": "Not Rock",
                        "why": "Because",  # this item shouldn't be there
                        "recordings": [],
                    },
                ],
                "public":
                False,
            })
Esempio n. 13
0
    def test_malformed_datasets(self):
        # Unexpected items
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "i_like": "to test",
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "i": "don't",
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name":
                "Dataset",
                "surname":
                "For Testing",  # this item shouldn't be there
                "classes": [
                    {
                        "name": "Not Rock",
                        "recordings": [],
                    },
                ],
                "public":
                False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name":
                "Dataset",
                "classes": [
                    {
                        "name": "Rock",
                        "why": "Because",  # this item shouldn't be there
                        "recordings": [],
                    },
                ],
                "public":
                True,
            })

        # Missing values
        with self.assertRaises(dataset_validator.ValidationException):
            # Dataset name is missing
            dataset_validator.validate({
                "classes": [
                    {
                        "name": "the one and only",
                        "recordings": [],
                    },
                ],
                "public":
                False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            # List of classes is missing
            dataset_validator.validate({
                "name": "test",
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            # Publicity value is missing
            dataset_validator.validate({
                "name": "test",
                "classes": [],
            })
        with self.assertRaises(dataset_validator.ValidationException):
            # Class name is missing
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    {
                        "recordings": [],
                    },
                ],
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            # List of recordings in a class is missing
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    {
                        "name": "this",
                    },
                ],
                "public": False,
            })

        # Incorrect types
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate("dataset")
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": ["This", "is", "my", "cool", "dataset"],
                "classes": [],
                "public":
                False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "description": False,
                "classes": [],
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "description": "",
                "classes": None,
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "description": "",
                "classes": [],
                "public": "Nope",
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name":
                "test",
                "classes": [
                    {
                        "name": ("this", "is", "a", "name"),
                        "recordings": [],
                    },
                ],
                "public":
                False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    "first",
                    "second",
                ],
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name":
                "test",
                "classes": [
                    {
                        "name": "first",
                        "description": False,
                        "recordings": [],
                    },
                ],
                "public":
                False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name":
                "test",
                "classes": [
                    {
                        "name": "first",
                        "recordings": "I don't have any :(",
                    },
                ],
                "public":
                False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name":
                "test",
                "classes": [
                    {
                        "name": "first",
                        "recordings": ["my favourite"],
                    },
                ],
                "public":
                False,
            })

        # Incorrect lengths
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "",  # incorrect
                "classes": [],
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name":
                "this dataset",
                "classes": [
                    {
                        "name": "",  # incorrect
                        "recordings": [],
                    },
                ],
                "public":
                False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name":
                "test",
                "classes": [
                    {
                        "name": "Not Rock",
                        "why": "Because",  # this item shouldn't be there
                        "recordings": [],
                    },
                ],
                "public":
                False,
            })
    def test_dataset_incorrect_types(self):
        # Incorrect types

        # String, not dict
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate("dataset")

        # Name should be string
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": ["This", "is", "my", "cool", "dataset"],
                "classes": [],
                "public": False,
            })

        # Desc should be string
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "description": False,
                "classes": [],
                "public": False,
            })

        # Classes should be list
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "description": "",
                "classes": None,
                "public": False,
            })

        # public should be bool
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "description": "",
                "classes": [],
                "public": "Nope",
            })

        # class name should be string
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    {
                        "name": ("this", "is", "a", "name"),
                        "recordings": [],
                    },
                ],
                "public": False,
            })

        # class elements should be dict
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    "first",
                    "second",
                ],
                "public": False,
            })

        # Class desc should be string
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    {
                        "name": "first",
                        "description": False,
                        "recordings": [],
                    },
                ],
                "public": False,
            })

        # class recordings should be list
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    {
                        "name": "first",
                        "recordings": "I don't have any :(",
                    },
                ],
                "public": False,
            })

        # Class recordings should be uuids
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    {
                        "name": "first",
                        "recordings": [
                            "my favourite"
                        ],
                    },
                ],
                "public": False,
            })
    def test_malformed_datasets(self):
        # Unexpected items
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "i_like": "to test",
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "i": "don't",
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "Dataset",
                "surname": "For Testing",  # this item shouldn't be there
                "classes": [
                    {
                        "name": "Not Rock",
                        "recordings": [],
                    },
                ],
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "Dataset",
                "classes": [
                    {
                        "name": "Rock",
                        "why": "Because",  # this item shouldn't be there
                        "recordings": [],
                    },
                ],
                "public": True,
            })

        # Missing values
        with self.assertRaises(dataset_validator.ValidationException):
            # Dataset name is missing
            dataset_validator.validate({
                "classes": [
                    {
                        "name": "the one and only",
                        "recordings": [],
                    },
                ],
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            # List of classes is missing
            dataset_validator.validate({
                "name": "test",
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            # Publicity value is missing
            dataset_validator.validate({
                "name": "test",
                "classes": [],
            })
        with self.assertRaises(dataset_validator.ValidationException):
            # Class name is missing
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    {
                        "recordings": [],
                    },
                ],
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            # List of recordings in a class is missing
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    {
                        "name": "this",
                    },
                ],
                "public": False,
            })

        # Incorrect types
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate("dataset")
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": ["This", "is", "my", "cool", "dataset"],
                "classes": [],
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "description": False,
                "classes": [],
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "description": "",
                "classes": None,
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "description": "",
                "classes": [],
                "public": "Nope",
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    {
                        "name": ("this", "is", "a", "name"),
                        "recordings": [],
                    },
                ],
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    "first",
                    "second",
                ],
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    {
                        "name": "first",
                        "description": False,
                        "recordings": [],
                    },
                ],
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    {
                        "name": "first",
                        "recordings": "I don't have any :(",
                    },
                ],
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    {
                        "name": "first",
                        "recordings": [
                            "my favourite"
                        ],
                    },
                ],
                "public": False,
            })

        # Incorrect lengths
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "",  # incorrect
                "classes": [],
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "this dataset",
                "classes": [
                    {
                        "name": "",  # incorrect
                        "recordings": [],
                    },
                ],
                "public": False,
            })
        with self.assertRaises(dataset_validator.ValidationException):
            dataset_validator.validate({
                "name": "test",
                "classes": [
                    {
                        "name": "Not Rock",
                        "why": "Because",  # this item shouldn't be there
                        "recordings": [],
                    },
                ],
                "public": False,
            })