OXYGENHUB
# 02f1b14af1e2 oxygen / crates / oxy-server / tests / http.rs
3.5 KiB · Rust · last changed HTTP integration test compiles without Debug on Repo 1 month ago source blame history raw
1
//! End-to-end: a real server on a loopback port, clients over HTTP.
2
3
use oxy_core::repo::{Repo, SignatureStatus};
4
use std::fs;
5
use std::net::TcpListener;
6
use std::path::Path;
7
8
fn write(root: &Path, rel: &str, content: &[u8]) {
9
    let p = root.join(rel);
10
    fs::create_dir_all(p.parent().unwrap()).unwrap();
11
    fs::write(p, content).unwrap();
12
}
13
14
fn start(root: &Path, tokens: Vec<String>) -> String {
15
    let listener = TcpListener::bind("127.0.0.1:0").unwrap();
16
    let port = listener.local_addr().unwrap().port();
17
    let cfg = oxy_server::ServerConfig { root: root.to_path_buf(), tokens };
18
    std::thread::spawn(move || oxy_server::run_blocking(listener, cfg).unwrap());
19
    format!("http://127.0.0.1:{port}")
20
}
21
22
#[test]
23
fn clone_push_pull_over_http() {
24
    let dir = tempfile::tempdir().unwrap();
25
    let root = dir.path();
26
    let served = root.join("served");
27
    Repo::init(&served.join("origin")).unwrap();
28
    let base = start(&served, vec![]);
29
    let url = format!("{base}/origin");
30
31
    let mut a = Repo::clone(&url, &root.join("a")).unwrap().with_keys_dir(root.join("keys"));
32
    let (key, _) = a.create_identity("Ada", "[email protected]").unwrap();
33
    write(&root.join("a"), "f.txt", b"hello\n");
34
    let h1 = a.commit("hello", &[]).unwrap();
35
    let r = a.push("origin", false).unwrap();
36
    assert!(r[0].ok, "{}", r[0].reason);
37
38
    let origin = Repo::open(&served.join("origin")).unwrap();
39
    assert_eq!(origin.bookmark_heads().unwrap(), vec![h1]);
40
    assert!(matches!(origin.authenticate_change(&h1).unwrap(), SignatureStatus::Valid { key: k, sealed: true, .. } if k == key));
41
42
    let b = Repo::clone(&url, &root.join("b")).unwrap();
43
    assert_eq!(fs::read(root.join("b/f.txt")).unwrap(), b"hello\n");
44
    write(&root.join("b"), "g.txt", b"g\n");
45
    let h2 = b.commit("g", &[]).unwrap();
46
    assert!(b.push("origin", false).unwrap()[0].ok);
47
48
    let pr = a.pull("origin").unwrap();
49
    assert!(pr.changed && pr.checked_out);
50
    assert_eq!(fs::read(root.join("a/g.txt")).unwrap(), b"g\n");
51
    let mut heads = a.bookmark_heads().unwrap();
52
    heads.sort();
53
    let mut want = vec![h1, h2];
54
    want.sort();
55
    assert_eq!(heads, want);
56
57
    // Unknown repositories and names the server refuses are surfaced as errors.
58
    let err = Repo::clone(&format!("{base}/nope"), &root.join("c")).err().unwrap().to_string();
59
    assert!(err.contains("404"), "{err}");
60
    fs::create_dir_all(served.join(".hidden/.oxy")).unwrap();
61
    assert!(Repo::clone(&format!("{base}/.hidden"), &root.join("d")).err().unwrap().to_string().contains("404"));
62
}
63
64
#[test]
65
fn push_requires_a_token_when_configured() {
66
    let dir = tempfile::tempdir().unwrap();
67
    let root = dir.path();
68
    let served = root.join("served");
69
    Repo::init(&served.join("origin")).unwrap();
70
    let base = start(&served, vec!["s3cret".into()]);
71
    let url = format!("{base}/origin");
72
73
    // Reads are open.
74
    let mut a = Repo::clone(&url, &root.join("a")).unwrap();
75
    write(&root.join("a"), "f.txt", b"x\n");
76
    a.commit("x", &[]).unwrap();
77
    let err = a.push("origin", false).err().unwrap().to_string();
78
    assert!(err.contains("401"), "{err}");
79
80
    a.config.set("remote.origin.token", "wrong").unwrap();
81
    a.save_config().unwrap();
82
    assert!(a.push("origin", false).err().unwrap().to_string().contains("401"));
83
84
    a.config.set("remote.origin.token", "s3cret").unwrap();
85
    a.save_config().unwrap();
86
    assert!(a.push("origin", false).unwrap()[0].ok);
87
    let origin = Repo::open(&served.join("origin")).unwrap();
88
    assert_eq!(origin.bookmark_heads().unwrap().len(), 1);
89
}