Ejemplo n.º 1
0
void test_random_4x4() {
    test_initiated("a random 4x4x4 scramble");
    CuboidDimensions dim = {4, 4, 4};
    
    Algorithm * algo = algorithm_for_string("F U Uw R E' L2 Fw2 3Rw'");
    Cuboid * testCuboid = algorithm_to_cuboid(algo, dim);
    algorithm_free(algo);
    
    if (!testCuboid) {
        puts("Error: failed to read cuboid.");
    }
    
    StickerMap * testMap = stickermap_create(dim);
    convert_cb_to_sm(testMap, testCuboid);
    cuboid_free(testCuboid);
    
    //  U Uw R E' L2 Fw2 3Rw'
    const char * stickerData = "4662633564435556" "1441644543354332" "5226466621112113" "1111125132543222" "6424262255163316" "4655412345635533";
    
    int i;
    for (i = 0; i < 16 * 6; i++) {
        int value = stickerData[i] - '1' + 1;
        if (testMap->stickers[i] != value) {
            printf("Error: invalid sticker at index %d, %d != %d.\n", i, value, testMap->stickers[i]);
        }
    }
    
    stickermap_free(testMap);
    test_completed();
}
Ejemplo n.º 2
0
void test_save_data_list() {
    test_initiated("save_data_list");
    
    DataList * list = generate_data_list();
    FILE * temp = tmpfile();
    assert(temp != NULL);
    save_data_list(list, temp);
    fseek(temp, 0, SEEK_SET);
    DataList * loaded = load_data_list(temp);
    fclose(temp);
    
    if (loaded) {
        test_data_list_node_equality(loaded->rootNode, list->rootNode);
        if (loaded->dataSize != list->dataSize) {
            puts("Error: dataSize disagrees");
        }
        if (loaded->headerLen != list->headerLen) {
            puts("Error: headerLen disagrees");
        }
        if (loaded->depth != list->depth) {
            puts("Error: depth disagrees");
        }
    } else {
        puts("Error: failed to load data list.");
    }
    
    data_list_free(loaded);
    data_list_free(list);
    
    test_completed();
}
Ejemplo n.º 3
0
void test_superflip() {
    test_initiated("edge orientations on superflip");
    
    CuboidDimensions dims = {3, 3, 3};
    Algorithm * algo = algorithm_for_string("(M U' M U' M U' M U' y z')3");
    Cuboid * cuboid = algorithm_to_cuboid(algo, dims);
    algorithm_free(algo);
    
    int i;
    for (i = 0; i < 12; i++) {
        CuboidEdge edge = cuboid->edges[i];
        int orX = cuboid_edge_orientation(edge, i, 0);
        int orY = cuboid_edge_orientation(edge, i, 0);
        int orZ = cuboid_edge_orientation(edge, i, 0);
        if (orX) {
            printf("Error: edge %d claims to be oriented on the X axis.\n", i);
        }
        if (orY) {
            printf("Error: edge %d claims to be oriented on the Y axis.\n", i);
        }
        if (orZ) {
            printf("Error: edge %d claims to be oriented on the Z axis.\n", i);
        }
    }
    
    cuboid_free(cuboid);
    test_completed();
}
Ejemplo n.º 4
0
void test_superflip() {
    test_initiated("the superflip on a 3x3x3");
    
    CuboidDimensions dims = {3, 3, 3};
    Algorithm * algo = algorithm_for_string("(M U' M U' M U' M U' y z')3");
    Cuboid * cuboid = algorithm_to_cuboid(algo, dims);
    algorithm_free(algo);
    
    // ensure corner identity
    int i;
    for (i = 0; i < 8; i++) {
        CuboidCorner c = cuboid->corners[i];
        if (c.index != i || c.symmetry != 0) {
            printf("Error: invalid corner at index %d.\n", i);
        }
    }
    // ensure center identity
    for (i = 0; i < 6; i++) {
        CuboidCenter c = cuboid->centers[i];
        if (c.side != i + 1 || c.index != 0) {
            printf("Error: invalid center at index %d.\n", i);
        }
    }
    // ensure edge psuedo-identity
    for (i = 0; i < 12; i++) {
        CuboidEdge edge = cuboid->edges[i];
        if (edge.dedgeIndex != i || edge.symmetry == 0) {
            printf("Error: invalid edge at index %d.\n", i);
        }
    }
    
    cuboid_free(cuboid);
    test_completed();
}
Ejemplo n.º 5
0
void test_save_cuboid() {
    test_initiated("save_cuboid");
    
    CuboidDimensions dims = {10, 20, 10};
    Algorithm * algo = algorithm_for_string("R2 2Bw2 3Dw L2 5Bw2 F2 4Rw2 L2 Fw2 2Uw'");
    Cuboid * cuboid = algorithm_to_cuboid(algo, dims);
    algorithm_free(algo);
    
    FILE * temp = tmpfile();
    assert(temp != NULL);
    save_cuboid(cuboid, temp);
    fseek(temp, 0, SEEK_SET);
    Cuboid * cb = load_cuboid(temp);
    fclose(temp);
    
    if (!cb) {
        puts("Error: failed to load cuboid at all!");
    }
    
    test_cuboid_equality(cb, cuboid);
    
    cuboid_free(cb);
    cuboid_free(cuboid);
    test_completed();
}
Ejemplo n.º 6
0
void test_save_algorithm() {
    test_initiated("save_algorithm");
    
    Algorithm * algo = algorithm_for_string("R Uw 2Fw3 D' M2 x L2 y' z2");
    
    FILE * temp = tmpfile();
    assert(temp != NULL);
    
    save_algorithm(algo, temp);
    fseek(temp, 0, SEEK_SET);
    Algorithm * loaded = load_algorithm(temp);
    
    if (!loaded) {
        puts("Error: failed to load algorithm at all!");
    }
    if (loaded->type != AlgorithmTypeContainer) {
        puts("Error: invalid type for loaded algorithm.");
    }
    
    test_algorithm_equality(algo, loaded);
    
    fclose(temp);
    
    algorithm_free(algo);
    algorithm_free(loaded);
    test_completed();
}
Ejemplo n.º 7
0
void test_save_cuboid_search() {
    test_initiated("save_cuboid_search");
    
    FILE * temp = tmpfile();
    assert(temp != NULL);
    BSSearchState * bsState = generate_bs_search_state();
    CSSearchState * state = (CSSearchState *)malloc(sizeof(CSSearchState));
    state->bsState = bsState;
    
    CuboidDimensions dims = {5, 6, 6};
    Algorithm * testAlgo = algorithm_for_string("Lw R2 U2 3Dw2 L'");
    state->settings.rootNode = algorithm_to_cuboid(testAlgo, dims);
    algorithm_free(testAlgo);
    state->settings.algorithms = alg_list_parse("R,L,Uw2,Dw2,Fw2,Bw2", dims);
    
    save_cuboid_search(state, temp);
    fseek(temp, 0, SEEK_SET);
    CSSearchState * loaded = load_cuboid_search(temp);
    if (loaded) {
        test_cuboid_state_equality(loaded, state);
        cs_search_state_free(loaded);
    } else {
        puts("Error: failed to load search state.");
    }
    
    cs_search_state_free(state);
    fclose(temp);
    test_completed();
}
Ejemplo n.º 8
0
void test_generate_division() {
    test_initiated("sboundary_generate_division()");
    SBoundary boundary;
    sboundary_initialize(&boundary, 5, 10);
    sboundary_generate_division(&boundary, 33);
    
    int digits1[] = {0, 3, 0, 3, 0};
    if (memcmp(boundary.sequence, digits1, sizeof(int) * 5) != 0) {
        puts("Error: failed to compute 10^5 / 33.");
    }
    
    sboundary_generate_division(&boundary, 100000 - 1);
    int digits2[] = {0, 0, 0, 0, 1};
    if (memcmp(boundary.sequence, digits2, sizeof(int) * 5) != 0) {
        puts("Error: failed to compute 10^5 / (10^5 - 1).");
    }
    
    sboundary_generate_division(&boundary, 100000);
    if (memcmp(boundary.sequence, digits2, sizeof(int) * 5) != 0) {
        puts("Error: failed to compute 10^5 / 10^5.");
    }
    
    int digits3[] = {0, 0, 0, 0, 0};
    sboundary_generate_division(&boundary, 100001);
    if (memcmp(boundary.sequence, digits3, sizeof(int) * 5) != 0) {
        puts("Error: failed to computer 10^6 / (10^6 + 1).");
    }
    
    sboundary_destroy(boundary);
    test_completed();
}
Ejemplo n.º 9
0
void test_equivalent_4x4() {
    test_initiated("Rw equivalency on a 4x4x4.");
    
    CuboidDimensions dim = {4, 4, 4};
    
    Algorithm * algo = algorithm_for_string("Rw2");
    Cuboid * testCuboid = algorithm_to_cuboid(algo, dim);
    algorithm_free(algo);
        
    Cuboid * control = cuboid_half_face_turn(dim, CuboidMovesAxisX, 1);
    Cuboid * slice = cuboid_half_slice(dim, CuboidMovesAxisX, 1);
    cuboid_multiply_to(slice, control);
    cuboid_free(slice);
    
    // test edge equivalency
    int i, j;
    for (i = 0; i < 12; i++) {
        for (j = 0; j < 2; j++) {
            int index = j + (i * 2);
            CuboidEdge e1 = control->edges[index];
            CuboidEdge e2 = testCuboid->edges[index];
            if (e1.edgeIndex != e2.edgeIndex || e1.symmetry != e2.symmetry ||
                e1.dedgeIndex != e2.dedgeIndex) {
                printf("Error: differnce in edge (%d, %d).\n", i, j);
            }
        }
    }
    // test corner equivalency
    for (i = 0; i < 8; i++) {
        CuboidCorner c1 = control->corners[i];
        CuboidCorner c2 = testCuboid->corners[i];
        if (c1.index != c2.index || c1.symmetry != c2.symmetry) {
            printf("Error: difference in corner %d.\n", i);
        }
    }
    // test center equivalency
    for (i = 1; i <= 6; i++) {
        for (j = 0; j < 4; j++) {
            int index = 4 * (i - 1) + j;
            CuboidCenter c1 = control->centers[index];
            CuboidCenter c2 = testCuboid->centers[index];
            if (c1.side != c2.side || c1.index != c2.index) {
                printf("Error: difference in center (%d, %d).\n", i, j);
            }
        }
    }
        
    cuboid_free(control);
    cuboid_free(testCuboid);
    
    test_completed();
}
Ejemplo n.º 10
0
void test_redbull_algorithm() {
    test_initiated("redbull on a 4x4x4");
    
    CuboidDimensions dims = {4, 4, 4};
    Algorithm * algo = algorithm_for_string("Rw2 R2 B2 U2 Lw L' U2 Rw' R U2 Rw R' U2 F2 Rw R' F2 Lw' L B2 Rw2 R2");
    Cuboid * cuboid = algorithm_to_cuboid(algo, dims);
    algorithm_free(algo);
    
    // verify corner identity
    int i, j;
    for (i = 0; i < 8; i++) {
        CuboidCorner c = cuboid->corners[i];
        if (c.index != i || c.symmetry != 0) {
            printf("Error: invalid corner at index %d.\n", i);
        }
    }
    
    // verify center identity
    for (i = 1; i <= 6; i++) {
        for (j = 0; j < 4; j++) {
            int index = cuboid_center_index(cuboid, i, j);
            CuboidCenter c = cuboid->centers[index];
            if (c.side != i) {
                printf("Error: invalid center at (%d, %d).\n", i, j);
            }
        }
    }
    
    // verify edges
    for (i = 0; i < 12; i++) {
        int edgeCount = cuboid_count_edges_for_dedge(cuboid, i);
        for (j = 0; j < edgeCount; j++) {
            int index = cuboid_edge_index(cuboid, i, j);
            CuboidEdge edge = cuboid->edges[index];
            if (i == 0) {
                if (edge.symmetry != 2 || edge.dedgeIndex != i || edge.edgeIndex != 1 - j) {
                    printf("Error: invaild edge (%d, %d).\n", i, j);
                }
            } else {
                if (edge.symmetry != 0 || edge.dedgeIndex != i || edge.edgeIndex != j) {
                    printf("Error: invalid edge (%d, %d).\n", i, j);
                }
            }
        }
    }
    
    cuboid_free(cuboid);
    test_completed();
}
Ejemplo n.º 11
0
void test_3x4x3_line() {
    test_initiated("3x4x3 \"line\" algorithm");
    
    CuboidDimensions dims = {3, 4, 3};
    const char * data = "212212212212" "121121121121" "333333333" "444444444" "666666666666" "555555555555";
    StickerMap * map = stickermap_create(dims);
    int i;
    for (i = 0; i < 3*3*2 + 3*4*4; i++) {
        map->stickers[i] = data[i] - '1' + 1;
    }
    Cuboid * cuboid = cuboid_create(dims);
    if (!convert_sm_to_cb(cuboid, map)) {
        puts("Error: failed to read stickermap :'(");
    }
    stickermap_free(map);
    
    Algorithm * algo = algorithm_for_string("R2 L2 Uw2 R2 L2 Uw2");
    Cuboid * compare = algorithm_to_cuboid(algo, dims);
    algorithm_free(algo);
    
    for (i = 0; i < 8; i++) {
        CuboidCorner c1 = compare->corners[i];
        CuboidCorner c2 = cuboid->corners[i];
        if (c1.index != c2.index || c1.symmetry != c2.symmetry) {
            printf("Error: corners differ at index %d.\n", i);
            printf("(expected %d, found %d)\n", c2.index, c1.index);
        }
    }
    for (i = 0; i < cuboid_count_edges(cuboid); i++) {
        CuboidEdge e1 = compare->edges[i];
        CuboidEdge e2 = cuboid->edges[i];
        if (e1.dedgeIndex != e2.dedgeIndex || 
            e1.symmetry != e2.symmetry) {
                printf("Error: edges differ at index %d.\n", i);
        }
    }
    for (i = 0; i < cuboid_count_centers(cuboid); i++) {
        CuboidCenter c1 = compare->centers[i];
        CuboidCenter c2 = cuboid->centers[i];
        if (c1.side != c2.side) {
            printf("Error: centers differ at index %d.\n", i);
        }
    }
    
    cuboid_free(compare);
    cuboid_free(cuboid);
    test_completed();
}
Ejemplo n.º 12
0
void test_evil_eyes() {
    test_initiated("evil eyes on an 11x11x11");
    
    CuboidDimensions dims = {11, 11, 11};
    Algorithm * algo = algorithm_for_string("R2 U2 R2 U2 R2 U2");
    Cuboid * evilEyes = algorithm_to_cuboid(algo, dims);
    algorithm_free(algo);
    
    int i, j;
    // verify solved centers
    for (i = 1; i <= 6; i++) {
        for (j = 0; j < 9*9; j++) {
            int centIndex = cuboid_center_index(evilEyes, i, j);
            CuboidCenter c = evilEyes->centers[centIndex];
            if (c.side != i) {
                printf("Error: invalid center at (%d, %d).\n", i, j);
            }
        }
    }
    // verify solved corners
    for (i = 0; i < 8; i++) {
        CuboidCorner c = evilEyes->corners[i];
        if (c.index != i || c.symmetry != 0) {
            printf("Error: invalid corner at index %d.\n", i);
        }
    }
    for (i = 0; i < 12; i++) {
        int expectedDedge = i;
        if (i == 0) expectedDedge = 6;
        if (i == 6) expectedDedge = 0;
        if (i == 1) expectedDedge = 7;
        if (i == 7) expectedDedge = 1;
        int dedgeCount = cuboid_count_edges_for_dedge(evilEyes, i);
        for (j = 0; j < dedgeCount; j++) {
            int index = cuboid_edge_index(evilEyes, i, j);
            CuboidEdge edge = evilEyes->edges[index];
            if (edge.symmetry != 0 || edge.dedgeIndex != expectedDedge) {
                printf("Error: invalid edge at (%d, %d).\n", i, j);
            }
        }
    }
    
    cuboid_free(evilEyes);
    test_completed();
}
Ejemplo n.º 13
0
void test_rl_orientation() {
    test_initiated("R & L edge orientation");
    
    CuboidDimensions dims = {3, 3, 3};
    Algorithm * algo = algorithm_for_string("R U2 D' F' U2 L' B2 D' F");
    Cuboid * cuboid = algorithm_to_cuboid(algo, dims);
    uint8_t eoMap[12] = {0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0};
    int i;
    
    for (i = 0; i < 12; i++) {
        CuboidEdge edge = cuboid->edges[i];
        uint8_t flag = cuboid_edge_orientation(edge, i, 0);
        if (flag != eoMap[i]) {
            printf("Error: invalid EO at %d.\n", i);
        }
    }
    
    cuboid_free(cuboid);
    test_completed();
}
Ejemplo n.º 14
0
void test_fb_orientation() {
    test_initiated("F & B edge orientation");
    
    CuboidDimensions dims = {3, 3, 3};
    Algorithm * algo = algorithm_for_string("R D2 F L' U2 D' F2 L' B");
    Cuboid * cuboid = algorithm_to_cuboid(algo, dims);
    uint8_t eoMap[12] = {1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1}; // I entered this SO fast
    int i;
    
    for (i = 0; i < 12; i++) {
        CuboidEdge edge = cuboid->edges[i];
        uint8_t flag = cuboid_edge_orientation(edge, i, 2);
        if (flag != eoMap[i]) {
            printf("Error: invalid EO at %d.\n", i);
        }
    }
    
    cuboid_free(cuboid);
    test_completed();
}
Ejemplo n.º 15
0
void test_5x5x5_turns() {
    test_initiated("5x5x5 half-turns");
    CuboidDimensions dims = {5, 5, 5};
    
    Cuboid * turnR = cuboid_half_face_turn(dims, CuboidMovesAxisX, 1);
    
    uint8_t rightCenter[] = {8, 7, 6, 5, 4, 3, 2, 1, 0};
    int i;
    for (i = 0; i < 9; i++) {
        CuboidCenter c = turnR->centers[cuboid_center_index(turnR, 5, i)];
        if (c.index != rightCenter[i]) {
            printf("Error: invalid right center at index %d.\n", i);
        }
        int j;
        for (j = 1; j <= 6; j++) {
            if (j == 5) continue;
            CuboidCenter cent = turnR->centers[cuboid_center_index(turnR, j, i)];
            if (cent.index != i || cent.side != j) {
                printf("Error: invalid center piece (%d, %d).\n", j, i);
            }
        }
    }
    
    // check the right dedges
    uint8_t checkEdges[4] = {1, 5, 7, 11};
    for (i = 0; i < 4; i++) {
        int j, dedgeIndex = checkEdges[i];
        int complementDedge = (i < 2 ? checkEdges[i + 2] : checkEdges[i - 2]);
        for (j = 0; j < 3; j++) {
            CuboidEdge edge = turnR->edges[cuboid_edge_index(turnR, dedgeIndex, j)];
            if (edge.edgeIndex != 3 - j - 1 ||
                edge.dedgeIndex != complementDedge) {
                printf("Error: invalid edge at (%d, %d), got (%d, %d).\n", 
                    dedgeIndex, j, edge.dedgeIndex, edge.dedgeIndex);
            }
        }
    }
    
    cuboid_free(turnR);
    test_completed();
}
Ejemplo n.º 16
0
void test_save_base_search() {
    test_initiated("save_base_search");
    
    BSSearchState * state = generate_bs_search_state();
    FILE * temp = tmpfile();
    assert(temp != NULL);
    
    save_base_search(state, temp);
    fseek(temp, 0, SEEK_SET);
    BSSearchState * loaded = load_base_search(temp);
    
    if (loaded) {
        test_base_state_equality(state, loaded);
        bs_search_state_free(loaded);
    } else {
        puts("Error: failed to load!");
    }
    
    fclose(temp);
    bs_search_state_free(state);
    test_completed();
}
Ejemplo n.º 17
0
void test_maximum_minimum() {
    test_initiated("srange_minimum/maximum_digit()");
    
    SBoundary lower, upper;
    sboundary_initialize(&lower, 9, 12);
    sboundary_initialize(&upper, 9, 12);
    int lowerData[9] = {4, 5, 8, 6, 10, 9, 0, 0, 0};
    int upperData[9] = {10, 7, 2, 1, 3, 4, 7, 0, 0};
    memcpy(lower.sequence, lowerData, 9 * sizeof(int));
    memcpy(upper.sequence, upperData, 9 * sizeof(int));
    
    SRange range = {lower, upper};
    
    int test = srange_minimum_digit(range, 3, int_list("\x04\x05\x08"));
    if (test != 6) {
        puts("Error: minimum 3 digits failed.");
    }
    test = srange_minimum_digit(range, 4, int_list("\x05\x00\x00\x00"));
    if (test != 0) {
        puts("Error: going above minimum failed.");
    }
    test = srange_maximum_digit(range, 2, int_list("\x10\x07"));
    if (test != 2) {
        puts("Error: maximum 2 digits failed.");
    }
    test = srange_maximum_digit(range, 6, int_list("\x10\x07\x02\x01\x03\x04"));
    if (test != 6) {
        puts("Error: maximum value blocking failed.");
    }
    test = srange_maximum_digit(range, 7, int_list("\x10\x07\x02\x01\x03\x04\x06"));
    if (test != 11) {
        puts("Error: going below maximum failed.");
    }
    
    sboundary_destroy(lower);
    sboundary_destroy(upper);
    test_completed();
}
Ejemplo n.º 18
0
void test_random_3x3() {
    test_initiated("a random 3x3x3 scramble");
    CuboidDimensions dim = {3, 3, 3};
    
    Algorithm * algo = algorithm_for_string("D L2 D2 R2 B2 D' F2 R' F2 L' R' U' R2 U2 L2 U2 B D' U2 L' D2 B U'");
    Cuboid * testCuboid = algorithm_to_cuboid(algo, dim);
    algorithm_free(algo);
    StickerMap * testMap = stickermap_create(dim);
    convert_cb_to_sm(testMap, testCuboid);
    cuboid_free(testCuboid);
    
    // scrambled with D L2 D2 R2 B2 D' F2 R' F2 L' R' U' R2 U2 L2 U2 B D' U2 L' D2 B U' (23 HTM)
    const char * stickerData = "321312451" "166126216" "445436546" "524542453" "313653536" "212365142";
    int i;
    for (i = 0; i < 9 * 6; i++) {
        int value = stickerData[i] - '1' + 1;
        if (testMap->stickers[i] != value) {
            printf("Error: invalid sticker at index %d, %d != %d.\n", i, value, testMap->stickers[i]);
        }
    }
    
    stickermap_free(testMap);
    test_completed();
}
Ejemplo n.º 19
0
void test_range_division() {
    test_initiated("Testing srange_division()");
    SRange * ranges = (SRange *)malloc(sizeof(SRange) * 50);
    
    int count = srange_division(2, 5, 50, ranges);
    if (count != 25) {
        puts("Error: dividing 25 into 50 pieces should yield 25 pieces!");
    }
    srange_destroy_list(ranges, count);
    
    count = srange_division(2, 10, 50, ranges);
    if (count != 50) {
        puts("Error: dividing 100 by 50 should yield 50 pieces!");
    }
    
    SRange r1 = ranges[0];
    if (!sboundary_is_zero(r1.lower)) {
        puts("Error: first boundary should be zero.");
    }
    if (r1.upper.sequence[0] != 0 || r1.upper.sequence[1] != 2) {
        puts("Error: second boundary should be (0, 2).");
    }
    
    r1 = ranges[count - 1];
    if (r1.lower.sequence[0] != 9 || r1.lower.sequence[1] != 8) {
        puts("Error: invalid second to last boundary.");
    }
    if (r1.upper.sequence[0] != 10 || r1.upper.sequence[1] != 0) {
        puts("Error: invalid last boundary.");
    }
    
    srange_destroy_list(ranges, count);
    
    free(ranges);
    test_completed();
}
Ejemplo n.º 20
0
/*
 * Callback upon request completion.
 */
static void on_request_complete(pj_stun_session *stun_sess,
			        pj_status_t status,
				void *token,
			        pj_stun_tx_data *tdata,
			        const pj_stun_msg *response,
				const pj_sockaddr_t *src_addr,
				unsigned src_addr_len)
{
    nat_detect_session *sess;
    pj_stun_sockaddr_attr *mattr = NULL;
    pj_stun_changed_addr_attr *ca = NULL;
    pj_uint32_t *tsx_id;
    int cmp;
    unsigned test_id;

    PJ_UNUSED_ARG(token);
    PJ_UNUSED_ARG(tdata);
    PJ_UNUSED_ARG(src_addr);
    PJ_UNUSED_ARG(src_addr_len);

    sess = (nat_detect_session*) pj_stun_session_get_user_data(stun_sess);

    pj_grp_lock_acquire(sess->grp_lock);

    /* Find errors in the response */
    if (status == PJ_SUCCESS) {

	/* Check error message */
	if (PJ_STUN_IS_ERROR_RESPONSE(response->hdr.type)) {
	    pj_stun_errcode_attr *eattr;
	    int err_code;

	    eattr = (pj_stun_errcode_attr*)
		    pj_stun_msg_find_attr(response, PJ_STUN_ATTR_ERROR_CODE, 0);

	    if (eattr != NULL)
		err_code = eattr->err_code;
	    else
		err_code = PJ_STUN_SC_SERVER_ERROR;

	    status = PJ_STATUS_FROM_STUN_CODE(err_code);


	} else {

	    /* Get MAPPED-ADDRESS or XOR-MAPPED-ADDRESS */
	    mattr = (pj_stun_sockaddr_attr*)
		    pj_stun_msg_find_attr(response, PJ_STUN_ATTR_XOR_MAPPED_ADDR, 0);
	    if (mattr == NULL) {
		mattr = (pj_stun_sockaddr_attr*)
			pj_stun_msg_find_attr(response, PJ_STUN_ATTR_MAPPED_ADDR, 0);
	    }

	    if (mattr == NULL) {
		status = PJNATH_ESTUNNOMAPPEDADDR;
	    }

	    /* Get CHANGED-ADDRESS attribute */
	    ca = (pj_stun_changed_addr_attr*)
		 pj_stun_msg_find_attr(response, PJ_STUN_ATTR_CHANGED_ADDR, 0);

	    if (ca == NULL) {
		status = PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_SERVER_ERROR);
	    }

	}
    }

    /* Save the result */
    tsx_id = (pj_uint32_t*) tdata->msg->hdr.tsx_id;
    test_id = tsx_id[2];

    if (test_id >= ST_MAX) {
	PJ_LOG(4,(sess->pool->obj_name, "Invalid transaction ID %u in response",
		  test_id));
	end_session(sess, PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_SERVER_ERROR),
		    PJ_STUN_NAT_TYPE_ERR_UNKNOWN);
	goto on_return;
    }

    PJ_LOG(5,(sess->pool->obj_name, "Completed %s, status=%d",
	      test_names[test_id], status));

    sess->result[test_id].complete = PJ_TRUE;
    sess->result[test_id].status = status;
    if (status == PJ_SUCCESS) {
	pj_memcpy(&sess->result[test_id].ma, &mattr->sockaddr.ipv4,
		  sizeof(pj_sockaddr_in));
	pj_memcpy(&sess->result[test_id].ca, &ca->sockaddr.ipv4,
		  sizeof(pj_sockaddr_in));
    }

    /* Send Test 1B only when Test 2 completes. Must not send Test 1B
     * before Test 2 completes to avoid creating mapping on the NAT.
     */
    if (!sess->result[ST_TEST_1B].executed && 
	sess->result[ST_TEST_2].complete &&
	sess->result[ST_TEST_2].status != PJ_SUCCESS &&
	sess->result[ST_TEST_1].complete &&
	sess->result[ST_TEST_1].status == PJ_SUCCESS) 
    {
	cmp = pj_memcmp(&sess->local_addr, &sess->result[ST_TEST_1].ma,
			sizeof(pj_sockaddr_in));
	if (cmp != 0)
	    send_test(sess, ST_TEST_1B, &sess->result[ST_TEST_1].ca, 0);
    }

    if (test_completed(sess)<3 || test_completed(sess)!=test_executed(sess))
	goto on_return;

    /* Handle the test result according to RFC 3489 page 22:


                        +--------+
                        |  Test  |
                        |   1    |
                        +--------+
                             |
                             |
                             V
                            /\              /\
                         N /  \ Y          /  \ Y             +--------+
          UDP     <-------/Resp\--------->/ IP \------------->|  Test  |
          Blocked         \ ?  /          \Same/              |   2    |
                           \  /            \? /               +--------+
                            \/              \/                    |
                                             | N                  |
                                             |                    V
                                             V                    /\
                                         +--------+  Sym.      N /  \
                                         |  Test  |  UDP    <---/Resp\
                                         |   2    |  Firewall   \ ?  /
                                         +--------+              \  /
                                             |                    \/
                                             V                     |Y
                  /\                         /\                    |
   Symmetric  N  /  \       +--------+   N  /  \                   V
      NAT  <--- / IP \<-----|  Test  |<--- /Resp\               Open
                \Same/      |   1B   |     \ ?  /               Internet
                 \? /       +--------+      \  /
                  \/                         \/
                  |                           |Y
                  |                           |
                  |                           V
                  |                           Full
                  |                           Cone
                  V              /\
              +--------+        /  \ Y
              |  Test  |------>/Resp\---->Restricted
              |   3    |       \ ?  /
              +--------+        \  /
                                 \/
                                  |N
                                  |       Port
                                  +------>Restricted

                 Figure 2: Flow for type discovery process
     */

    switch (sess->result[ST_TEST_1].status) {
    case PJNATH_ESTUNTIMEDOUT:
	/*
	 * Test 1 has timed-out. Conclude with NAT_TYPE_BLOCKED. 
	 */
	end_session(sess, PJ_SUCCESS, PJ_STUN_NAT_TYPE_BLOCKED);
	break;
    case PJ_SUCCESS:
	/*
	 * Test 1 is successful. Further tests are needed to detect
	 * NAT type. Compare the MAPPED-ADDRESS with the local address.
	 */
	cmp = pj_memcmp(&sess->local_addr, &sess->result[ST_TEST_1].ma,
			sizeof(pj_sockaddr_in));
	if (cmp==0) {
	    /*
	     * MAPPED-ADDRESS and local address is equal. Need one more
	     * test to determine NAT type.
	     */
	    switch (sess->result[ST_TEST_2].status) {
	    case PJ_SUCCESS:
		/*
		 * Test 2 is also successful. We're in the open.
		 */
		end_session(sess, PJ_SUCCESS, PJ_STUN_NAT_TYPE_OPEN);
		break;
	    case PJNATH_ESTUNTIMEDOUT:
		/*
		 * Test 2 has timed out. We're behind somekind of UDP
		 * firewall.
		 */
		end_session(sess, PJ_SUCCESS, PJ_STUN_NAT_TYPE_SYMMETRIC_UDP);
		break;
	    default:
		/*
		 * We've got other error with Test 2.
		 */
		end_session(sess, sess->result[ST_TEST_2].status, 
			    PJ_STUN_NAT_TYPE_ERR_UNKNOWN);
		break;
	    }
	} else {
	    /*
	     * MAPPED-ADDRESS is different than local address.
	     * We're behind NAT.
	     */
	    switch (sess->result[ST_TEST_2].status) {
	    case PJ_SUCCESS:
		/*
		 * Test 2 is successful. We're behind a full-cone NAT.
		 */
		end_session(sess, PJ_SUCCESS, PJ_STUN_NAT_TYPE_FULL_CONE);
		break;
	    case PJNATH_ESTUNTIMEDOUT:
		/*
		 * Test 2 has timed-out Check result of test 1B..
		 */
		switch (sess->result[ST_TEST_1B].status) {
		case PJ_SUCCESS:
		    /*
		     * Compare the MAPPED-ADDRESS of test 1B with the
		     * MAPPED-ADDRESS returned in test 1..
		     */
		    cmp = pj_memcmp(&sess->result[ST_TEST_1].ma,
				    &sess->result[ST_TEST_1B].ma,
				    sizeof(pj_sockaddr_in));
		    if (cmp != 0) {
			/*
			 * MAPPED-ADDRESS is different, we're behind a
			 * symmetric NAT.
			 */
			end_session(sess, PJ_SUCCESS,
				    PJ_STUN_NAT_TYPE_SYMMETRIC);
		    } else {
			/*
			 * MAPPED-ADDRESS is equal. We're behind a restricted
			 * or port-restricted NAT, depending on the result of
			 * test 3.
			 */
			switch (sess->result[ST_TEST_3].status) {
			case PJ_SUCCESS:
			    /*
			     * Test 3 is successful, we're behind a restricted
			     * NAT.
			     */
			    end_session(sess, PJ_SUCCESS,
					PJ_STUN_NAT_TYPE_RESTRICTED);
			    break;
			case PJNATH_ESTUNTIMEDOUT:
			    /*
			     * Test 3 failed, we're behind a port restricted
			     * NAT.
			     */
			    end_session(sess, PJ_SUCCESS,
					PJ_STUN_NAT_TYPE_PORT_RESTRICTED);
			    break;
			default:
			    /*
			     * Got other error with test 3.
			     */
			    end_session(sess, sess->result[ST_TEST_3].status,
					PJ_STUN_NAT_TYPE_ERR_UNKNOWN);
			    break;
			}
		    }
		    break;
		case PJNATH_ESTUNTIMEDOUT:
		    /*
		     * Strangely test 1B has failed. Maybe connectivity was
		     * lost? Or perhaps port 3489 (the usual port number in
		     * CHANGED-ADDRESS) is blocked?
		     */
		    switch (sess->result[ST_TEST_3].status) {
		    case PJ_SUCCESS:
			/* Although test 1B failed, test 3 was successful.
			 * It could be that port 3489 is blocked, while the
			 * NAT itself looks to be a Restricted one.
			 */
			end_session(sess, PJ_SUCCESS, 
				    PJ_STUN_NAT_TYPE_RESTRICTED);
			break;
		    default:
			/* Can't distinguish between Symmetric and Port
			 * Restricted, so set the type to Unknown
			 */
			end_session(sess, PJ_SUCCESS, 
				    PJ_STUN_NAT_TYPE_ERR_UNKNOWN);
			break;
		    }
		    break;
		default:
		    /*
		     * Got other error with test 1B.
		     */
		    end_session(sess, sess->result[ST_TEST_1B].status,
				PJ_STUN_NAT_TYPE_ERR_UNKNOWN);
		    break;
		}
		break;
	    default:
		/*
		 * We've got other error with Test 2.
		 */
		end_session(sess, sess->result[ST_TEST_2].status, 
			    PJ_STUN_NAT_TYPE_ERR_UNKNOWN);
		break;
	    }
	}
	break;
    default:
	/*
	 * We've got other error with Test 1.
	 */
	end_session(sess, sess->result[ST_TEST_1].status, 
		    PJ_STUN_NAT_TYPE_ERR_UNKNOWN);
	break;
    }

on_return:
    pj_grp_lock_release(sess->grp_lock);
}
Ejemplo n.º 21
0
void test_3x2x3_turns() {
    test_initiated("3x2x3 half-turns");
    CuboidDimensions dims = {3, 2, 3};
    
    Cuboid * turnR = cuboid_half_face_turn(dims, CuboidMovesAxisX, 1);
    Cuboid * turnU = cuboid_half_face_turn(dims, CuboidMovesAxisY, 1);
    
    // validate R turn edges
    CuboidEdge edge1 = turnR->edges[cuboid_edge_index(turnR, 5, 0)];
    CuboidEdge edge2 = turnR->edges[cuboid_edge_index(turnR, 11, 0)];
    if (edge1.symmetry != 0 || edge1.dedgeIndex != 11) {
        puts("Error: dedge 5 is incorrect.\n");
    }
    if (edge2.symmetry != 0 || edge2.dedgeIndex != 5) {
        puts("Error: dedge 11 is incorrect.\n");
    }
    int i;
    for (i = 0; i < 12; i++) {
        if (i == 5 || i == 11) continue;
        if (cuboid_count_edges_for_dedge(turnR, i) != 1) {
            if (i == 1 || i == 3 || i == 7 || i == 9) continue;
            printf("Error: representation does not see edge at %d\n", i);
            continue;
        }
        CuboidEdge edge = turnR->edges[cuboid_edge_index(turnR, i, 0)];
        if (edge.dedgeIndex != i) {
            printf("Error: edge at %d is incorrect.\n", i);
        }
    }
    
    // validate R turn corners
    uint8_t expectedCorners[8] = {0, 1, 2, 3, 7, 6, 5, 4};
    for (i = 0; i < 8; i++) {
        if (turnR->corners[i].index != expectedCorners[i]) {
            printf("Error: wrong corner at index %d, got %d.\n", i, turnR->corners[i].index);
        }
    }
    
    // perform evil eyes and ensure proper swap
    Cuboid * cuboid = cuboid_create(dims);
    for (i = 0; i < 3; i++) {
        cuboid_multiply_to(turnR, cuboid);
        cuboid_multiply_to(turnU, cuboid);
    }
    
    edge1 = cuboid->edges[cuboid_edge_index(cuboid, 0, 0)];
    edge2 = cuboid->edges[cuboid_edge_index(cuboid, 6, 0)];
    if (edge1.dedgeIndex != 6) {
        printf("Error: invalid evil eyes dedge at index 0, actual is %d\n", edge1.dedgeIndex);
    }
    if (edge2.dedgeIndex != 0) {
        puts("Error: invalid evil eyes dedge at index 6");
    }
    
    for (i = 0; i < 12; i++) {
        if (i == 6 || i == 0) continue;
        if (cuboid_count_edges_for_dedge(turnR, i) != 1) continue;
        CuboidEdge edge = cuboid->edges[cuboid_edge_index(cuboid, i, 0)];
        if (edge.dedgeIndex != i) {
            printf("Error: wrong edge at index %d.\n", i);
        }
    }
    
    cuboid_free(cuboid);
    cuboid_free(turnR);
    cuboid_free(turnU);
    
    test_completed();
}
Ejemplo n.º 22
0
void test_3x4x3_slices() {
    test_initiated("3x4x3 double slices");
    CuboidDimensions dims = {3, 4, 3};
    
    Cuboid * htSlice = cuboid_half_slice(dims, CuboidMovesAxisY, 0);
    
    uint8_t dedges[4] = {1, 3, 7, 9};
    uint8_t newEdges[4] = {9, 7, 3, 1};
    
    // verify edges of HT
    int i, j;
    for (i = 0; i < 4; i++) {
        CuboidEdge edge = htSlice->edges[cuboid_edge_index(htSlice, dedges[i], 0)];
        if (edge.dedgeIndex != newEdges[i] || edge.edgeIndex != 0) {
            printf("Error: invalid dedge %d.\n", dedges[i]);
        }
    }
    for (i = 0; i < 12; i++) {
        int edgeCount = cuboid_count_edges_for_dedge(htSlice, i);
        for (j = 0; j < edgeCount; j++) {
            if (i == 1 || i == 3 || i == 7 || i == 9) {
                if (j == 0) continue;
            }
            CuboidEdge edge = htSlice->edges[cuboid_edge_index(htSlice, i, j)];
            if (edge.edgeIndex != j || edge.dedgeIndex != i) {
                printf("Error: invalid edge (%d, %d).\n", i, j);
            }
        }
    }
    
    // verify centers of HT
    uint8_t centers[4] = {1, 2, 5, 6};
    uint8_t newCenters[4] = {2, 1, 6, 5};
    for (i = 0; i < 4; i++) {
        CuboidCenter c = htSlice->centers[cuboid_center_index(htSlice, centers[i], 0)];
        if (c.index != 0 || c.side != newCenters[i]) {
            printf("Error: invalid center on face %d.\n", centers[i]);
        }
    }
    for (i = 1; i <= 6; i++) {
        int centCount = cuboid_count_centers_for_face(htSlice, i);
        for (j = 0; j < centCount; j++) {
            if (i != 3 && i != 4) {
                if (j == 0) continue;
            }
            CuboidCenter c = htSlice->centers[cuboid_center_index(htSlice, i, j)];
            if (c.index != j || c.side != i) {
                printf("Error: invalid center at (%d, %d).\n", i, j);
            }
        }
    }
    
    Cuboid * shouldEqual = cuboid_create(dims);
    Cuboid * qtSlice = cuboid_quarter_slice(dims, CuboidMovesAxisY, 0);
    cuboid_multiply_to(qtSlice, shouldEqual);
    cuboid_multiply_to(qtSlice, shouldEqual);
    cuboid_free(qtSlice);
    
    // ensure that shouldEqual = htSlice
    for (i = 0; i < cuboid_count_centers(htSlice); i++) {
        CuboidCenter c1 = htSlice->centers[i];
        CuboidCenter c2 = shouldEqual->centers[i];
        if (c1.index != c2.index || c1.side != c2.side) {
            printf("Error: different center at index %d.\n", i);
        }
    }
    for (i = 0; i < cuboid_count_edges(htSlice); i++) {
        CuboidEdge e1 = htSlice->edges[i];
        CuboidEdge e2 = shouldEqual->edges[i];
        if (e1.dedgeIndex != e2.dedgeIndex || e1.edgeIndex != e2.edgeIndex
            || e1.symmetry != e2.symmetry) {
            printf("Error: different edges at index %d.\n", i);
        }
    }
    
    cuboid_free(shouldEqual);
    cuboid_free(htSlice);
    
    test_completed();
}
Ejemplo n.º 23
0
void test_tokens() {
    test_initiated("individual tokens");
    
    
    // test Rw
    Algorithm * wideRight = algorithm_for_token("Rw");
    
    if (wideRight->type != AlgorithmTypeWideTurn)
        puts("Error: Rw processed invalid type.");
    if (wideRight->contents.wideTurn.face != 'R')
        puts("Error: Rw processed invalid face.");
    if (wideRight->contents.wideTurn.numLayers != 2)
        puts("Error: Rw processed invalid layer count.");
    if (wideRight->inverseFlag)
        puts("Error: Rw processed an inverse.");
    if (wideRight->power != 1)
        puts("Error: Rw processed the wrong power.");
    
    algorithm_free(wideRight);
    
    Algorithm * shouldBeNull = algorithm_for_token("2M");
    if (shouldBeNull != NULL) {
        puts("Error: failed to detect that 2M is invalid.");
        algorithm_free(shouldBeNull);
    }
    
    Algorithm * mPrime = algorithm_for_token("M'");
    if (mPrime->type != AlgorithmTypeSlice)
        puts("Error: M' processed invalid type.");
    if (mPrime->contents.slice.layer != 'M')
        puts("Error: M' processed invalid slice.");
    if (!mPrime->inverseFlag)
        puts("Error: M' did not process the inverse.");
    if (mPrime->power != 1)
        puts("Error: M' processed the wrong power.");
    algorithm_free(mPrime);
    
    // test 3Uw2
    Algorithm * upWide = algorithm_for_token("13Uw2");
    if (upWide->type != AlgorithmTypeWideTurn)
        puts("Error: 13Uw2 processed invalid type.");
    if (upWide->contents.wideTurn.face != 'U')
        puts("Error: 13Uw2 processed invalid face.");
    if (upWide->contents.wideTurn.numLayers != 13)
        puts("Error: 13Uw2 processed invalid layer count.");
    if (upWide->inverseFlag)
        puts("Error: 13Uw2 processed an inverse.");
    if (upWide->power != 2)
        puts("Error: 13Uw2 processed the wrong power.");
    algorithm_free(upWide);
    
    Algorithm * rotation = algorithm_for_token("x'3");
    if (rotation->type != AlgorithmTypeRotation)
        puts("Error: x'3 processed invalid type.");
    if (rotation->contents.rotation.axis != 'x')
        puts("Error: x'3 processed invalid axis.");
    if (!rotation->inverseFlag)
        puts("Error: x'3 processed invalid inverse flag.");
    if (rotation->power != 3)
        puts("Error: x'3 processed invalid power.");
    algorithm_free(rotation);
    
    test_completed();
}
Ejemplo n.º 24
0
void test_algorithm() {
    test_initiated("algorithm parser");
    
    Algorithm * algo = algorithm_for_string("R2 U' 12Rw15 (R z2)2 R' S'");
    if (algorithm_container_count(algo) != 6) {
        puts("Error: invalid algorithm token count.");
    }
    
    Algorithm * algo1 = algorithm_container_get(algo, 0);
    if (algo1->type != AlgorithmTypeWideTurn ||
        algo1->contents.wideTurn.face != 'R' ||
        algo1->contents.wideTurn.numLayers != 1 ||
        algo1->inverseFlag != 0 ||
        algo1->power != 2) {
        puts("Error: invalid token at index 0.");
    }
    algo1 = algorithm_container_get(algo, 1);
    if (algo1->type != AlgorithmTypeWideTurn ||
        algo1->contents.wideTurn.face != 'U' ||
        algo1->contents.wideTurn.numLayers != 1 ||
        algo1->inverseFlag != 1 ||
        algo1->power != 1) {
        puts("Error: invalid token at index 1.");
    }
    algo1 = algorithm_container_get(algo, 2);
    if (algo1->type != AlgorithmTypeWideTurn ||
        algo1->contents.wideTurn.face != 'R' ||
        algo1->contents.wideTurn.numLayers != 12 ||
        algo1->inverseFlag != 0 ||
        algo1->power != 15) {
        puts("Error: invalid token at index 2.");
    }
    algo1 = algorithm_container_get(algo, 4);
    if (algo1->type != AlgorithmTypeWideTurn ||
        algo1->contents.wideTurn.face != 'R' ||
        algo1->contents.wideTurn.numLayers != 1 ||
        algo1->inverseFlag != 1 ||
        algo1->power != 1) {
        puts("Error: invalid token at index 4.");
    }
    algo1 = algorithm_container_get(algo, 5);
    if (algo1->type != AlgorithmTypeSlice ||
        algo1->contents.slice.layer != 'S' ||
        algo1->inverseFlag != 1 ||
        algo1->power != 1) {
        puts("Error: invalid token at index 5.");
    }
    
    Algorithm * nested = algorithm_container_get(algo, 3);
    if (nested->type != AlgorithmTypeContainer) {
        puts("Error: invalid type for nested subexpression at index 3.");
    }
    if (algorithm_container_count(nested) != 2) {
        puts("Error: invalid count for nested subexpression.");
    }
    if (nested->power != 2) {
        puts("Error: invalid power on nested subexpression.");
    }
    algo1 = algorithm_container_get(nested, 0);
    if (algo1->type != AlgorithmTypeWideTurn ||
        algo1->contents.wideTurn.face != 'R' ||
        algo1->contents.wideTurn.numLayers != 1 ||
        algo1->inverseFlag != 0 ||
        algo1->power != 1) {
        puts("Error: invalid token at subexpression index 0.");
    }
    
    algo1 = algorithm_container_get(nested, 1);
    if (algo1->type != AlgorithmTypeRotation ||
        algo1->contents.rotation.axis != 'z' ||
        algo1->inverseFlag != 0 ||
        algo1->power != 2) {
        puts("Error: invalid token at subexpression index 1.");
    }
    
    algorithm_free(algo);
    
    test_completed();
}