aboutsummaryrefslogtreecommitdiff
path: root/comp1511/cs_beats/test_beats.c
blob: d1eb7938423a52234a0ede0fd8775950d85bc92d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// Assignment 2 20T1 COMP1511: CS bEats
// test_beats.c
//
// This program was written by YOUR-NAME-HERE (z5555555)
// on INSERT-DATE-HERE
//
// Version 1.0.0: Assignment released.
#include <stdio.h>
#include <stdlib.h>

#include "beats.h"
#include "test_beats.h"

// Test function for `add_note_to_beat`
int test_add_note_to_beat(void) {
    // Test 1: Rejecting negative inputs.
    Beat test_beat = create_beat();
    if (add_note_to_beat(test_beat, -1, -1) != INVALID_OCTAVE) {
        return DOES_NOT_MEET_SPEC;
    }
    if (add_note_to_beat(test_beat, -1, 0) != INVALID_OCTAVE) {
        return DOES_NOT_MEET_SPEC;
    }
    if (add_note_to_beat(test_beat, 1, -1) != INVALID_KEY) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 2: Rejecting invalid pitch notes.
    if (add_note_to_beat(test_beat, 1, 1) != VALID_NOTE) {
        return DOES_NOT_MEET_SPEC;
    }
    if (add_note_to_beat(test_beat, 1, 0) != NOT_HIGHEST_NOTE) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 3: Accepting valid inputs.
    if (add_note_to_beat(test_beat, 1, 2) != VALID_NOTE) {
        return DOES_NOT_MEET_SPEC;
    }
    return MEETS_SPEC;
}

// Test function for `count_notes_in_octave` this is broken
int test_count_notes_in_octave(void) {
    // Test 1: Counting invalid octaves.
    Beat test_beat = create_beat();
    add_note_to_beat(test_beat, 1, 1);
    if (count_notes_in_octave(test_beat, -1) != 0) {
        return DOES_NOT_MEET_SPEC;
    }
    if (count_notes_in_octave(test_beat, 11) != 0) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 2: Counting valid octaves.
    if (count_notes_in_octave(test_beat, 1) != 1) {
        return DOES_NOT_MEET_SPEC;
    }
    if (count_notes_in_octave(test_beat, 1) == 0) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 3: Counting without any notes
    struct beat *empty_beat = create_beat();
    if (count_notes_in_octave(empty_beat, 0) != 0) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 4: Counting the correct amount
    add_note_to_beat(test_beat, 2, 1);
    add_note_to_beat(test_beat, 2, 2);
    if (count_notes_in_octave(test_beat, 2) != 2) {
        return DOES_NOT_MEET_SPEC;
    }
    add_note_to_beat(test_beat, 2, 3);
    if (count_notes_in_octave(test_beat, 2) != 3) {
        return DOES_NOT_MEET_SPEC;
    }
    return MEETS_SPEC;
}

// These struct definitions are required for the following tests.
// They access the fields directly instead of using other functions as tests,
// which could be considered unsafe as they are not guaranteed to be correct.
// We only want to test a single function, not other functions indirectly.
struct track {
    struct beat *head;
    struct beat *cur;
};

struct beat {
    struct note *notes;
    struct beat *next;
};

// Test function for `add_beat_to_track`
int test_add_beat_to_track(void) {
    // Test 1: Test if the beat gets added correctly.
    struct track *test_track = create_track();
    struct beat *test_beat = create_beat();
    add_beat_to_track(test_track, test_beat);
    if (test_track->head == NULL) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 2: Ensure the beat is a shallow copy.
    if (test_track->head != test_beat) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 3: Test if the expected fields are NULL.
    if (test_track->cur != NULL) {
        return DOES_NOT_MEET_SPEC;
    }
    if (test_track->head->notes != NULL) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 4: Ensure adding muliple beats works correctly.
    struct beat *test_beat2 = create_beat();
    add_beat_to_track(test_track, test_beat2);
    if (test_track->head != test_beat2) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 5: Ensure the last field is still NULL.
    if (test_track->head->next->next != NULL) {
        return DOES_NOT_MEET_SPEC;
    }
    return MEETS_SPEC;
}

// Test function for `remove_selected_beat`
int test_remove_selected_beat(void) {
    // Test 1: Ensure the correct return type on a track with no selected beat.
    struct track *test_track = create_track();
    struct beat *test_beat = create_beat();
    add_beat_to_track(test_track, test_beat);
    if (remove_selected_beat(test_track) != TRACK_STOPPED) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 2: Ensure that no beat has been deleted after the previous test.
    if (test_track->head == NULL) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 3: Ensure the track is still playing after the attempted removal.
    if (test_track->cur != NULL) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 4: Ensure the correct return type on a track with a selected beat.
    select_next_beat(test_track);
    if (remove_selected_beat(test_track) != TRACK_STOPPED) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 5: Ensure the beat has been deleted correct after the previous test.
    if (test_track->head != NULL) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 6: Ensure the track is not playing after beat removal.
    if (test_track->cur != NULL) {
        return DOES_NOT_MEET_SPEC;
    }
    return MEETS_SPEC;
}

// Another struct definition which is required for testing below.
// This can probably be considered bad practice as struct defintions should not
// be simply copied across multiple files, but compared to the alternative
// of invoking potentially broken functions, this is preferable.
struct note {
    int oct;
    int key;
    struct note *next;
};

// Test function for `add_musical_note_to_beat`
int test_add_musical_note_to_beat(void) {
    // Test 1: Ensure the beat is added to an empty beat.
    struct beat *test_beat = create_beat();
    add_musical_note_to_beat(test_beat, "2C#");
    if (test_beat->notes == NULL) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 2: Ensure the beat has the correct pitch.
    if (test_beat->notes->oct != 2 || test_beat->notes->key != 4) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 3: Ensure a higher beat is added when appropriate.
    add_musical_note_to_beat(test_beat, "2C##");
    if (test_beat->notes->next == NULL) {
        return DOES_NOT_MEET_SPEC;
    }
    // Test 4: Ensure that a lower beat is added when appropriate.
    add_musical_note_to_beat(test_beat, "2C");
    if (test_beat->notes->oct != 2 || test_beat->notes->key != 3) {
        return DOES_NOT_MEET_SPEC;
    }
    return MEETS_SPEC;
}