File size: 5,410 Bytes
3ce1a40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
using Repoverse.Core.Generation;
using Repoverse.Core.Voxels;
using static Repoverse.Core.WorldConstants;

namespace Repoverse.Core.Tests;

public class InteriorTests
{
    [Fact]
    public void Ignored_directories_never_become_rooms()
    {
        var files = new[] { "src/a.js", "src/b.js" }
            .Concat(Enumerable.Range(0, 5000).Select(i => $"node_modules/pkg{i}/index.js"))
            .Concat(["target/debug/app", "build/out.o"]);
        var graph = RoomGraphBuilder.Build(TestRepos.Make("web", files: files), 6);
        Assert.DoesNotContain(graph.Rooms, r => r.Directories.Any(d => d.StartsWith("node_modules") || d.StartsWith("target") || d.StartsWith("build")));
        Assert.Contains(graph.Rooms, r => r.Name == "src");
    }

    [Fact]
    public void Huge_repositories_are_compressed_to_the_room_budget()
    {
        var files = Enumerable.Range(0, 200).SelectMany(d => Enumerable.Range(0, 3).Select(f => $"pkg{d:000}/file{f}.c"));
        var graph = RoomGraphBuilder.Build(TestRepos.Make("mono", files: files), 10);
        var work = graph.Rooms.Where(BuildingRasterizer.IsWorkRoom).ToList();
        Assert.True(work.Count <= MaxRoomsPerBuilding);
        Assert.Equal(600, work.Sum(r => r.FileCount)); // nothing lost, only folded into Commons
        Assert.Contains(work, r => r.Name == "Commons");
    }

    [Fact]
    public void Room_purpose_comes_from_directory_meaning()
    {
        var graph = RoomGraphBuilder.Build(TestRepos.Make("r", files: ["tests/a.py", "tests/b.py", "docs/x.md", "docs/y.md", "proofs/p.lean", "proofs/q.lean"]), 6);
        Assert.Equal(RoomPurpose.InspectionLab, graph.Rooms.Single(r => r.Name == "tests").Purpose);
        Assert.Equal(RoomPurpose.Archive, graph.Rooms.Single(r => r.Name == "docs").Purpose);
        Assert.Equal(RoomPurpose.ProofVault, graph.Rooms.Single(r => r.Name == "proofs").Purpose);
    }

    [Fact]
    public void Every_room_graph_in_the_slice_is_connected()
    {
        foreach (var b in ManifestBuilder.Build(TestRepos.Slice(), new Seed(1)).Buildings)
            Assert.Empty(b.Interior.Unreachable());
    }

    /// <summary>
    /// §89 against real geometry: flood-fill walkable air from the entrance (2 voxels of
    /// headroom, one-step climbs, ladders vertical) and require every room to be reached.
    /// </summary>
    [Theory]
    [InlineData(4)]
    [InlineData(40)]
    [InlineData(120)]
    public void Every_rasterized_room_is_reachable_on_foot(int directories)
    {
        var files = Enumerable.Range(0, directories).SelectMany(d => new[] { $"m{d:000}/a.rs", $"m{d:000}/b.rs" });
        var b = ManifestBuilder.Build([TestRepos.Make("walk", "kernel", "Rust", files)], new Seed(7)).Buildings[0];

        var grid = new Dictionary<(int, int, int), Voxel>();
        BuildingRasterizer.Rasterize(b, (x, y, z, v) => grid[(x, y, z)] = v);
        Voxel At(int x, int y, int z) => grid.TryGetValue((x, y, z), out var v) ? v : Voxel.Air;
        bool Standable(int x, int y, int z) => At(x, y, z).IsPassable && At(x, y + 1, z).IsPassable && (!At(x, y - 1, z).IsPassable || At(x, y, z).Type == BlockType.Ladder || At(x, y - 1, z).Type == BlockType.Ladder);

        var layout = BuildingRasterizer.Plan(b);
        var f = b.Footprint;
        var start = layout.Entrance;
        var seen = new HashSet<(int, int, int)> { start };
        var queue = new Queue<(int X, int Y, int Z)>(seen);
        while (queue.Count > 0)
        {
            var (x, y, z) = queue.Dequeue();
            foreach (var (dx, dz) in new[] { (1, 0), (-1, 0), (0, 1), (0, -1) })
                foreach (var dy in new[] { 0, 1, -1 })
                {
                    var n = (x + dx, y + dy, z + dz);
                    if (n.Item1 < f.X || n.Item1 > f.MaxX || n.Item3 < f.Z || n.Item3 > f.MaxZ) continue;
                    if (Standable(n.Item1, n.Item2, n.Item3) && seen.Add(n)) queue.Enqueue(n);
                }
            if (At(x, y, z).Type == BlockType.Ladder || At(x, y + 1, z).Type == BlockType.Ladder || At(x, y - 1, z).Type == BlockType.Ladder)
                foreach (var dy in new[] { 1, -1 })
                {
                    var n = (x, y + dy, z);
                    if (At(n.Item1, n.Item2, n.Item3).IsPassable && seen.Add(n)) queue.Enqueue(n);
                }
        }

        Assert.NotEmpty(layout.Rooms);
        Assert.Equal(b.Interior.Rooms.Count(BuildingRasterizer.IsWorkRoom), layout.Rooms.Count);
        foreach (var room in layout.Rooms)
        {
            var c = ((room.MinX + room.MaxX) / 2, room.FloorY + 1, (room.MinZ + room.MaxZ) / 2);
            Assert.True(seen.Contains(c), $"room {room.RoomId} on floor {room.Floor} is sealed");
        }
    }

    [Fact]
    public void Artifacts_become_interactive_objects_inside_their_rooms()
    {
        var b = ManifestBuilder.Build(TestRepos.Slice(), new Seed(1)).Buildings.Single(x => x.Repo.Name == "wasmc");
        var objects = BuildingRasterizer.Objects(b).ToList();
        var placements = BuildingRasterizer.Plan(b).Rooms.ToDictionary(r => r.RoomId);
        Assert.Contains(objects, o => o.SourcePath == "tests/lower.rs" && o.Kind == ArtifactKind.TestBench && o.Actions.Contains("test"));
        Assert.All(objects, o =>
        {
            var p = placements[o.RoomId];
            Assert.InRange(o.X, p.MinX, p.MaxX);
            Assert.InRange(o.Z, p.MinZ, p.MaxZ);
        });
    }
}