exercism/go/robot-simulator/robot_simulator_step2_test.go

95 lines
3.4 KiB
Go

// +build step2 !step1,!step3
package robot
import (
"fmt"
"testing"
)
// For step 1 you implement robot movements, but it's not much of a simulation.
// For example where in the source code is "the robot"? Where is "the grid"?
// Where are the computations that turn robot actions into grid positions,
// in the robot or in the grid? The physical world is different.
//
// Step 2 introduces a "room." It seems a small addition, but we'll make
// big changes to clarify the rolls of "room", "robot", and "test program"
// and begin to clarify the physics of the simulation. You will define Room
// and Robot as functions which the test program "brings into existence" by
// launching them as goroutines. Information moves between test program,
// robot, and room over Go channels.
//
// Think of Room as a "physics engine," something that models and simulates
// a physical room with walls and a robot. It should somehow model the
// coordinate space of the room, the location of the robot and the walls,
// and ensure for example that the robot doesn't walk through walls.
// We want Robot to be an agent that performs actions, but we want Room to
// maintain a coherent truth.
//
// Step 2 API:
//
// StartRobot(chan Command, chan Action)
// Room(extent Rect, robot Step2Robot, act chan Action, rep chan Step2Robot)
//
// You get to define Action; see defs.go for other definitions.
//
// The test program creates the channels and starts both Room and Robot.
// The test program then sends commands to Robot. When it is done sending
// commands, it closes the command channel. Robot must accept commands and
// inform Room of actions it is attempting. When it senses the command channel
// closing, it must shut down itself. The room must interpret the physical
// consequences of the robot actions. When it senses the robot shutting down,
// it sends a final report back to the test program, telling the robot's final
// position and direction.
var test2 = []struct {
Command
Step2Robot
}{
0: {' ', Step2Robot{N, Pos{1, 1}}}, // no command, this is the start DirAt
1: {'A', Step2Robot{N, Pos{1, 2}}},
2: {'R', Step2Robot{E, Pos{1, 2}}},
3: {'A', Step2Robot{E, Pos{2, 2}}},
4: {'L', Step2Robot{N, Pos{2, 2}}},
5: {'L', Step2Robot{W, Pos{2, 2}}},
6: {'L', Step2Robot{S, Pos{2, 2}}},
7: {'A', Step2Robot{S, Pos{2, 1}}},
8: {'R', Step2Robot{W, Pos{2, 1}}},
9: {'A', Step2Robot{W, Pos{1, 1}}},
10: {'A', Step2Robot{W, Pos{1, 1}}}, // bump W wall
11: {'L', Step2Robot{S, Pos{1, 1}}},
12: {'A', Step2Robot{S, Pos{1, 1}}}, // bump S wall
13: {'L', Step2Robot{E, Pos{1, 1}}},
14: {'A', Step2Robot{E, Pos{2, 1}}},
15: {'A', Step2Robot{E, Pos{2, 1}}}, // bump E wall
16: {'L', Step2Robot{N, Pos{2, 1}}},
17: {'A', Step2Robot{N, Pos{2, 2}}},
18: {'A', Step2Robot{N, Pos{2, 2}}}, // bump N wall
}
func TestStep2(t *testing.T) {
// run incrementally longer tests
for i := 1; i <= len(test2); i++ {
cmd := make(chan Command)
act := make(chan Action)
rep := make(chan Step2Robot)
go StartRobot(cmd, act)
go Room(Rect{Pos{1, 1}, Pos{2, 2}}, test2[0].Step2Robot, act, rep)
fmt.Println("Starting Tests")
for j := 1; j < i; j++ {
fmt.Println("Channeling: ", test2[j])
cmd <- test2[j].Command
}
close(cmd)
da := <-rep
last := i - 1
want := test2[last].Step2Robot
if da.Pos != want.Pos {
t.Fatalf("Command #%d, Pos = %v, want %v", last, da.Pos, want.Pos)
}
if da.Dir != want.Dir {
t.Fatalf("Command #%d, Dir = %v, want %v", last, da.Dir, want.Dir)
}
}
}