构造一组 store,使其内容与一份 xray JSON 完全等价。两侧分别走 server hash 与 node hash 路径,结果必须字节一致。
(t *testing.T)
| 15 | // 构造一组 store,使其内容与一份 xray JSON 完全等价。两侧分别走 server hash |
| 16 | // 与 node hash 路径,结果必须字节一致。 |
| 17 | func TestComputeNodeConfigHash_MatchesNodeSide(t *testing.T) { |
| 18 | userStore := users.NewMemoryStore() |
| 19 | ibStore := inbounds.NewMemoryStore() |
| 20 | |
| 21 | // inbound:vless 一个,trojan 一个(不同 protocol,确保 token 取值分支被覆盖) |
| 22 | ibVless, _ := ibStore.UpsertInbound(inbounds.Inbound{ |
| 23 | ID: "ib-v", NodeID: "n1", Protocol: "vless", |
| 24 | Tag: "vless-1", Port: 443, TrafficRate: 0, |
| 25 | }) |
| 26 | ibTrojan, _ := ibStore.UpsertInbound(inbounds.Inbound{ |
| 27 | ID: "ib-t", NodeID: "n1", Protocol: "trojan", |
| 28 | Tag: "trojan-1", Port: 8443, TrafficRate: 0, |
| 29 | }) |
| 30 | |
| 31 | // 两个用户,都 active;user 级 UUID/Secret 优先 |
| 32 | _, _ = userStore.UpsertUser(users.User{ |
| 33 | ID: "ua", Username: "alice", Status: users.StatusActive, |
| 34 | UUID: "uuid-alice", Secret: "secret-alice", |
| 35 | }) |
| 36 | _, _ = userStore.UpsertUser(users.User{ |
| 37 | ID: "ub", Username: "bob", Status: users.StatusActive, |
| 38 | UUID: "uuid-bob", Secret: "secret-bob", |
| 39 | }) |
| 40 | |
| 41 | // alice 同时拥有 vless / trojan;bob 只有 vless |
| 42 | _, _ = userStore.UpsertUserInbound(users.UserInbound{ |
| 43 | ID: "a-v", UserID: "ua", InboundID: ibVless.ID, NodeID: "n1", |
| 44 | }) |
| 45 | _, _ = userStore.UpsertUserInbound(users.UserInbound{ |
| 46 | ID: "a-t", UserID: "ua", InboundID: ibTrojan.ID, NodeID: "n1", |
| 47 | }) |
| 48 | _, _ = userStore.UpsertUserInbound(users.UserInbound{ |
| 49 | ID: "b-v", UserID: "ub", InboundID: ibVless.ID, NodeID: "n1", |
| 50 | }) |
| 51 | |
| 52 | got, err := ComputeNodeConfigHash(context.Background(), "n1", userStore, ibStore, nil) |
| 53 | if err != nil { |
| 54 | t.Fatalf("ComputeNodeConfigHash error = %v", err) |
| 55 | } |
| 56 | |
| 57 | // 模拟 node 侧从 xray 配置 JSON 算 hash 的等价输入: |
| 58 | // proxycfg 生成的 client.email = "<username>@<tag>",UUID 走 id;trojan 走 password。 |
| 59 | xray := `{"inbounds":[ |
| 60 | {"tag":"vless-1","settings":{"clients":[ |
| 61 | {"id":"uuid-alice","email":"alice@vless-1"}, |
| 62 | {"id":"uuid-bob","email":"bob@vless-1"} |
| 63 | ]}}, |
| 64 | {"tag":"trojan-1","settings":{"clients":[ |
| 65 | {"password":"secret-alice","email":"alice@trojan-1"} |
| 66 | ]}} |
| 67 | ]}` |
| 68 | want := confighash.HashFromXrayJSON(xray) |
| 69 | |
| 70 | if got != want { |
| 71 | t.Fatalf("server vs node hash mismatch:\n server = %s\n node = %s", got, want) |
| 72 | } |
| 73 | if len(got) != 64 { |
| 74 | t.Fatalf("expected 64-hex sha256, got %q", got) |
nothing calls this directly
no test coverage detected