flok 0.0.41 → 0.0.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/kern/pagers/pg_dummy.js +18 -0
- data/app/kern/services/vm.rb +361 -34
- data/docs/services/vm.md +69 -40
- data/docs/services/vm/diff.md +156 -0
- data/docs/services/vm/pagers.md +3 -2
- data/lib/flok/user_compiler.rb +3 -0
- data/lib/flok/version.rb +1 -1
- data/spec/env/kern.rb +19 -0
- data/spec/etc/user_compiler/controller0bg.rb +13 -0
- data/spec/etc/user_compiler_spec.rb +19 -12
- data/spec/kern/assets/global_on_entry5.rb +28 -0
- data/spec/kern/assets/vm/controller0_diff.rb +47 -0
- data/spec/kern/assets/vm/pg_dummy/config.rb +10 -0
- data/spec/kern/assets/vm/pg_mem/write.rb +1 -1
- data/spec/kern/assets/vm/pg_mem/write2.rb +1 -1
- data/spec/kern/assets/vm/vm_commit_pages.js +108 -0
- data/spec/kern/assets/vm/vm_diff_pages.js +140 -0
- data/spec/kern/assets/vm/vm_transaction_diff_pages.js +150 -0
- data/spec/kern/controller_spec.rb +19 -0
- data/spec/kern/vm_service_functional_spec.rb +1111 -0
- data/spec/kern/vm_service_spec.rb +84 -185
- data/spec/kern/vm_transaction_spec.rb +375 -0
- metadata +22 -4
- data/spec/kern/vm_service_spec2.rb +0 -39
@@ -0,0 +1,140 @@
|
|
1
|
+
//Page Factor
|
2
|
+
//////////////////////////////////////////////////////////////////////////////////////////
|
3
|
+
function PageFactory(head, next) {
|
4
|
+
this.head = head;
|
5
|
+
this.next = next;
|
6
|
+
this.entries = [];
|
7
|
+
}
|
8
|
+
|
9
|
+
//Add an entry
|
10
|
+
PageFactory.prototype.addEntry = function(eid, value) {
|
11
|
+
this.entries.push({_id: eid, _sig: value, value: value});
|
12
|
+
}
|
13
|
+
|
14
|
+
//This adds up to four entrys that can be represented as a square:
|
15
|
+
//-------------
|
16
|
+
//| id0 | id1 |
|
17
|
+
//-------------
|
18
|
+
//| id2 | id3 |
|
19
|
+
//-------------
|
20
|
+
//Leaving out parts of the values array will not add those entries, e.g. ["Square", null, null, "Triangle"]
|
21
|
+
//--------------------|
|
22
|
+
//| Square | null |
|
23
|
+
//--------------------|
|
24
|
+
//| null | Triangle |
|
25
|
+
//--------------------|
|
26
|
+
//Where 'Square' is id0 and 'Triangle' is id3
|
27
|
+
PageFactory.prototype.addEntryFourSquare = function(values) {
|
28
|
+
if (values.length != 4) {
|
29
|
+
throw "FourSquare requires for values. Make values null if you don't need them"
|
30
|
+
}
|
31
|
+
|
32
|
+
for (var i = 0; i < values.length; ++i) {
|
33
|
+
if (values[i]) {
|
34
|
+
this.addEntry("id"+i, values[i]);
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
//Same as addEntryFourSquare but takes an index parameter before the
|
40
|
+
//value that sets the id of each element
|
41
|
+
//e.g. addEntryFourSquareCustomIds([["id0, "A"], ["id2, "B"], ["id1, "C"], ["id3, "D"]]).
|
42
|
+
//[
|
43
|
+
// {_id: "id0", value: "A", _sig: "A"},
|
44
|
+
// {_id: "id3", value: "D", _sig: "D"},
|
45
|
+
// {_id: "id2", value: "C", _sig: "C"},
|
46
|
+
// {_id: "id1", value: "B", _sig: "B"},
|
47
|
+
//]
|
48
|
+
PageFactory.prototype.addEntryFourSquareCustomIds = function(values) {
|
49
|
+
for (var i = 0; i < values.length; ++i) {
|
50
|
+
//Get pair
|
51
|
+
var pair = values[i];
|
52
|
+
if (pair.length != 2) {
|
53
|
+
throw "FourSquareShuffle accepts pairs. E.g. ['id0', 'A']"
|
54
|
+
}
|
55
|
+
|
56
|
+
var id = pair[0];
|
57
|
+
var value = pair[1];
|
58
|
+
|
59
|
+
this.addEntry(id, value);
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
//Returns a page
|
64
|
+
PageFactory.prototype.compile = function() {
|
65
|
+
var page = vm_create_page("default");
|
66
|
+
page._head = this.head;
|
67
|
+
page._next = this.next;
|
68
|
+
|
69
|
+
page.entries = this.entries;
|
70
|
+
|
71
|
+
vm_rehash_page(page);
|
72
|
+
vm_reindex_page(page);
|
73
|
+
|
74
|
+
return page;
|
75
|
+
}
|
76
|
+
//////////////////////////////////////////////////////////////////////////////////////////
|
77
|
+
|
78
|
+
var pf = new PageFactory();
|
79
|
+
pf.addEntryFourSquare(["Triangle", "Square", "Z", null]);
|
80
|
+
triangle_square_z_null = pf.compile();
|
81
|
+
|
82
|
+
var pf = new PageFactory();
|
83
|
+
pf.addEntryFourSquare(["Triangle", "Circle", null, "Q"]);
|
84
|
+
triangle_circle_null_q = pf.compile();
|
85
|
+
|
86
|
+
var pf = new PageFactory();
|
87
|
+
pf.addEntryFourSquare(["Triangle", "Circle", null, "Q"]);
|
88
|
+
triangle_circle_null_q = pf.compile();
|
89
|
+
|
90
|
+
var pf = new PageFactory();
|
91
|
+
pf.addEntryFourSquare(["Q", null, "Circle", "Square"]);
|
92
|
+
q_null_circle_square = pf.compile();
|
93
|
+
|
94
|
+
var pf = new PageFactory();
|
95
|
+
pf.addEntryFourSquare(["P", "Circle", null, "Q"]);
|
96
|
+
p_circle_null_q = pf.compile();
|
97
|
+
|
98
|
+
var pf = new PageFactory();
|
99
|
+
pf.addEntryFourSquare(["P", "Circle", null, null]);
|
100
|
+
p_circle_null_null = pf.compile();
|
101
|
+
|
102
|
+
var pf = new PageFactory();
|
103
|
+
pf.addEntryFourSquare(["P", null, null, "Q"]);
|
104
|
+
p_null_null_q = pf.compile();
|
105
|
+
|
106
|
+
var pf = new PageFactory();
|
107
|
+
pf.addEntryFourSquare(["P", "Square", null, null]);
|
108
|
+
p_square_null_null = pf.compile();
|
109
|
+
|
110
|
+
var pf = new PageFactory();
|
111
|
+
pf.addEntryFourSquare(["Triangle", null, "A", "M"]);
|
112
|
+
triangle_null_a_m = pf.compile();
|
113
|
+
|
114
|
+
var pf = new PageFactory();
|
115
|
+
pf.addEntryFourSquare(["Triangle", "Square", null, null]);
|
116
|
+
triangle_square_null_null = pf.compile();
|
117
|
+
|
118
|
+
var pf = new PageFactory();
|
119
|
+
pf.addEntryFourSquare(["Triangle", "Z", "Q", null]);
|
120
|
+
triangle_z_q_null = pf.compile();
|
121
|
+
|
122
|
+
var pf = new PageFactory(null);
|
123
|
+
head_null = pf.compile();
|
124
|
+
|
125
|
+
var pf = new PageFactory("world");
|
126
|
+
head_world = pf.compile();
|
127
|
+
|
128
|
+
var pf = new PageFactory(null);
|
129
|
+
next_null = pf.compile();
|
130
|
+
|
131
|
+
var pf = new PageFactory(null, "world");
|
132
|
+
next_world = pf.compile();
|
133
|
+
|
134
|
+
var pf = new PageFactory();
|
135
|
+
pf.addEntryFourSquareCustomIds([["id1", "Square"], ["id0", "Triangle"], ["id2", "Z"]]);
|
136
|
+
triangle_square_z_null_moved_square_triangle_z = pf.compile();
|
137
|
+
|
138
|
+
var pf = new PageFactory();
|
139
|
+
pf.addEntryFourSquareCustomIds([["id2", "Z"], ["id1", "Square"], ["id0", "Triangle"]]);
|
140
|
+
triangle_square_z_null_moved_z_square_triangle = pf.compile();
|
@@ -0,0 +1,150 @@
|
|
1
|
+
//Page Factor
|
2
|
+
//////////////////////////////////////////////////////////////////////////////////////////
|
3
|
+
function PageFactory(head, next) {
|
4
|
+
this.head = head;
|
5
|
+
this.next = next;
|
6
|
+
this.entries = [];
|
7
|
+
}
|
8
|
+
|
9
|
+
//Add an entry
|
10
|
+
PageFactory.prototype.addEntry = function(eid, value) {
|
11
|
+
this.entries.push({_id: eid, _sig: value, value: value});
|
12
|
+
}
|
13
|
+
|
14
|
+
//This adds up to four entrys that can be represented as a square:
|
15
|
+
//-------------
|
16
|
+
//| id0 | id1 |
|
17
|
+
//-------------
|
18
|
+
//| id2 | id3 |
|
19
|
+
//-------------
|
20
|
+
//Leaving out parts of the values array will not add those entries, e.g. ["Square", null, null, "Triangle"]
|
21
|
+
//--------------------|
|
22
|
+
//| Square | null |
|
23
|
+
//--------------------|
|
24
|
+
//| null | Triangle |
|
25
|
+
//--------------------|
|
26
|
+
//Where 'Square' is id0 and 'Triangle' is id3
|
27
|
+
PageFactory.prototype.addEntryFourSquare = function(values) {
|
28
|
+
if (values.length != 4) {
|
29
|
+
throw "FourSquare requires for values. Make values null if you don't need them"
|
30
|
+
}
|
31
|
+
|
32
|
+
for (var i = 0; i < values.length; ++i) {
|
33
|
+
if (values[i]) {
|
34
|
+
this.addEntry("id"+i, values[i]);
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
//Same as addEntryFourSquare but takes an index parameter before the
|
40
|
+
//value that sets the id of each element
|
41
|
+
//e.g. addEntryFourSquareCustomIds([["id0, "A"], ["id2, "B"], ["id1, "C"], ["id3, "D"]]).
|
42
|
+
//[
|
43
|
+
// {_id: "id0", value: "A", _sig: "A"},
|
44
|
+
// {_id: "id3", value: "D", _sig: "D"},
|
45
|
+
// {_id: "id2", value: "C", _sig: "C"},
|
46
|
+
// {_id: "id1", value: "B", _sig: "B"},
|
47
|
+
//]
|
48
|
+
PageFactory.prototype.addEntryFourSquareCustomIds = function(values) {
|
49
|
+
for (var i = 0; i < values.length; ++i) {
|
50
|
+
//Get pair
|
51
|
+
var pair = values[i];
|
52
|
+
if (pair.length != 2) {
|
53
|
+
throw "FourSquareShuffle accepts pairs. E.g. ['id0', 'A']"
|
54
|
+
}
|
55
|
+
|
56
|
+
var id = pair[0];
|
57
|
+
var value = pair[1];
|
58
|
+
|
59
|
+
this.addEntry(id, value);
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
//Returns a page
|
64
|
+
PageFactory.prototype.compile = function(page_id) {
|
65
|
+
if (page_id === undefined) {
|
66
|
+
var page = vm_create_page("default");
|
67
|
+
} else {
|
68
|
+
var page = vm_create_page(page_id);
|
69
|
+
}
|
70
|
+
|
71
|
+
page._head = this.head;
|
72
|
+
page._next = this.next;
|
73
|
+
|
74
|
+
page.entries = this.entries;
|
75
|
+
|
76
|
+
vm_rehash_page(page);
|
77
|
+
vm_reindex_page(page);
|
78
|
+
|
79
|
+
return page;
|
80
|
+
}
|
81
|
+
//////////////////////////////////////////////////////////////////////////////////////////
|
82
|
+
|
83
|
+
var pf = new PageFactory();
|
84
|
+
pf.addEntryFourSquare(["Triangle", "Square", "Z", null]);
|
85
|
+
triangle_square_z_null = pf.compile();
|
86
|
+
|
87
|
+
var pf = new PageFactory();
|
88
|
+
pf.addEntryFourSquare(["Triangle", "Circle", null, "Q"]);
|
89
|
+
triangle_circle_null_q = pf.compile();
|
90
|
+
|
91
|
+
var pf = new PageFactory();
|
92
|
+
pf.addEntryFourSquare(["Triangle", "Circle", null, "Q"]);
|
93
|
+
triangle_circle_null_q = pf.compile();
|
94
|
+
|
95
|
+
var pf = new PageFactory();
|
96
|
+
pf.addEntryFourSquare(["Q", null, "Circle", "Square"]);
|
97
|
+
q_null_circle_square = pf.compile();
|
98
|
+
|
99
|
+
var pf = new PageFactory();
|
100
|
+
pf.addEntryFourSquare(["P", "Circle", null, "Q"]);
|
101
|
+
p_circle_null_q = pf.compile();
|
102
|
+
|
103
|
+
var pf = new PageFactory();
|
104
|
+
pf.addEntryFourSquare(["P", "Circle", null, null]);
|
105
|
+
p_circle_null_null = pf.compile();
|
106
|
+
|
107
|
+
var pf = new PageFactory();
|
108
|
+
pf.addEntryFourSquare(["P", null, null, "Q"]);
|
109
|
+
p_null_null_q = pf.compile();
|
110
|
+
|
111
|
+
var pf = new PageFactory();
|
112
|
+
pf.addEntryFourSquare(["P", "Square", null, null]);
|
113
|
+
p_square_null_null = pf.compile();
|
114
|
+
|
115
|
+
var pf = new PageFactory();
|
116
|
+
pf.addEntryFourSquare(["Triangle", null, "A", "M"]);
|
117
|
+
triangle_null_a_m = pf.compile();
|
118
|
+
|
119
|
+
var pf = new PageFactory();
|
120
|
+
pf.addEntryFourSquare(["Triangle", "Square", null, null]);
|
121
|
+
triangle_square_null_null = pf.compile();
|
122
|
+
|
123
|
+
var pf = new PageFactory();
|
124
|
+
pf.addEntryFourSquare(["Triangle", "Z", "Q", null]);
|
125
|
+
triangle_z_q_null = pf.compile();
|
126
|
+
|
127
|
+
var pf = new PageFactory(null);
|
128
|
+
head_null = pf.compile();
|
129
|
+
|
130
|
+
var pf = new PageFactory("world");
|
131
|
+
head_world = pf.compile();
|
132
|
+
|
133
|
+
var pf = new PageFactory(null);
|
134
|
+
next_null = pf.compile();
|
135
|
+
|
136
|
+
var pf = new PageFactory(null, "world");
|
137
|
+
next_world = pf.compile();
|
138
|
+
|
139
|
+
var pf = new PageFactory();
|
140
|
+
pf.addEntryFourSquareCustomIds([["id1", "Square"], ["id0", "Triangle"], ["id2", "Z"]]);
|
141
|
+
triangle_square_z_null_moved_square_triangle_z = pf.compile();
|
142
|
+
|
143
|
+
var pf = new PageFactory();
|
144
|
+
pf.addEntryFourSquareCustomIds([["id2", "Z"], ["id1", "Square"], ["id0", "Triangle"]]);
|
145
|
+
triangle_square_z_null_moved_z_square_triangle = pf.compile();
|
146
|
+
|
147
|
+
//Seperate page
|
148
|
+
var pf = new PageFactory();
|
149
|
+
pf.addEntryFourSquare(["P", "Square", null, null]);
|
150
|
+
default2_square_null_null = pf.compile("default2");
|
@@ -596,6 +596,25 @@ RSpec.describe "kern:controller_spec" do
|
|
596
596
|
@driver.mexpect("if_event", [base, "context", {"base" => base, "secret" => "foo"}])
|
597
597
|
end
|
598
598
|
|
599
|
+
it "Does allow service macros in the global on_entry function" do
|
600
|
+
#Compile the controller
|
601
|
+
ctx = flok_new_user File.read('./spec/kern/assets/global_on_entry5.rb'), File.read("./spec/kern/assets/vm/config5.rb")
|
602
|
+
|
603
|
+
#Run the embed function
|
604
|
+
secret = SecureRandom.hex
|
605
|
+
ctx.eval %{
|
606
|
+
global_on_entry_called_count = 0;
|
607
|
+
|
608
|
+
//Call embed on main root view
|
609
|
+
base = _embed("my_controller", 0, {}, null);
|
610
|
+
|
611
|
+
int_dispatch([]);
|
612
|
+
}
|
613
|
+
|
614
|
+
expect(ctx.eval("read_res_called")).to eq(true)
|
615
|
+
end
|
616
|
+
|
617
|
+
|
599
618
|
it "Does allow interval (every) events" do
|
600
619
|
#Compile the controller
|
601
620
|
ctx = flok_new_user File.read('./spec/kern/assets/interval.rb')
|
@@ -0,0 +1,1111 @@
|
|
1
|
+
#This contains tests for the 'functions' of the vm service system
|
2
|
+
|
3
|
+
Dir.chdir File.join File.dirname(__FILE__), '../../'
|
4
|
+
require './spec/env/kern.rb'
|
5
|
+
require './spec/lib/helpers.rb'
|
6
|
+
require './spec/lib/io_extensions.rb'
|
7
|
+
require './spec/lib/rspec_extensions.rb'
|
8
|
+
require 'zlib'
|
9
|
+
|
10
|
+
#Evaluates the
|
11
|
+
def eval_and_dump str
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
RSpec.describe "kern:vm_service_functional" do
|
16
|
+
include Zlib
|
17
|
+
include_context "kern"
|
18
|
+
|
19
|
+
it "Can can use vm_create_page" do
|
20
|
+
ctx = flok_new_user File.read('./spec/kern/assets/vm/controller0.rb'), File.read("./spec/kern/assets/vm/config5.rb")
|
21
|
+
dump = ctx.evald %{
|
22
|
+
dump.new_page = vm_create_page("my_id")
|
23
|
+
dump.new_anon_page = vm_create_page();
|
24
|
+
}
|
25
|
+
|
26
|
+
expect(dump["new_page"]).to eq({
|
27
|
+
"_head" => nil,
|
28
|
+
"_next" => nil,
|
29
|
+
"_id" => "my_id",
|
30
|
+
"entries" => [],
|
31
|
+
"__index" => {},
|
32
|
+
"_hash" => nil,
|
33
|
+
})
|
34
|
+
|
35
|
+
expect(dump["new_anon_page"]["_id"]).not_to eq nil
|
36
|
+
expect(dump["new_anon_page"]["entries"]).to eq []
|
37
|
+
end
|
38
|
+
|
39
|
+
it "Can can use vm_copy_page" do
|
40
|
+
ctx = flok_new_user File.read('./spec/kern/assets/vm/controller0.rb'), File.read("./spec/kern/assets/vm/config5.rb")
|
41
|
+
dump = ctx.evald %{
|
42
|
+
dump.new_page = vm_create_page("Q")
|
43
|
+
dump.no_head_no_next_no_entry = vm_copy_page(dump.new_page);
|
44
|
+
|
45
|
+
//Modify the new_page with a head, next, and entry; then create a copy
|
46
|
+
dump.new_page._head = "Z";
|
47
|
+
dump.new_page._next = "Triangle";
|
48
|
+
dump.new_page.entries.push({"_id": "id0", "_sig": "Square", "value": "Square"});
|
49
|
+
dump.head_z_next_triangle_entry_square = vm_copy_page(dump.new_page);
|
50
|
+
|
51
|
+
//Modify the new_page's entry in-place and make a copy
|
52
|
+
dump.new_page.entries[0]["_sig"] = "Circle";
|
53
|
+
dump.new_page.entries[0]["value"] = "Circle";
|
54
|
+
dump.head_z_next_triangle_entry_circle = vm_copy_page(dump.new_page);
|
55
|
+
|
56
|
+
//Modify the new_page's entry again in-place
|
57
|
+
dump.new_page.entries[0]["_sig"] = "Triangle"
|
58
|
+
dump.new_page.entries[0]["value"] = "Triangle"
|
59
|
+
}
|
60
|
+
|
61
|
+
expect(dump["no_head_no_next_no_entry"]).to eq({
|
62
|
+
"_head" => nil,
|
63
|
+
"_next" => nil,
|
64
|
+
"_id" => "Q",
|
65
|
+
"_hash" => nil,
|
66
|
+
"entries" => [],
|
67
|
+
})
|
68
|
+
|
69
|
+
expect(dump["head_z_next_triangle_entry_square"]).to eq({
|
70
|
+
"_head" => "Z",
|
71
|
+
"_next" => "Triangle",
|
72
|
+
"_id" => "Q",
|
73
|
+
"_hash" => nil,
|
74
|
+
"entries" => [
|
75
|
+
{"_id" => "id0", "_sig" => "Square", "value" => "Square"},
|
76
|
+
],
|
77
|
+
})
|
78
|
+
|
79
|
+
expect(dump["head_z_next_triangle_entry_circle"]).to eq({
|
80
|
+
"_head" => "Z",
|
81
|
+
"_next" => "Triangle",
|
82
|
+
"_id" => "Q",
|
83
|
+
"_hash" => nil,
|
84
|
+
"entries" => [
|
85
|
+
{"_id" => "id0", "_sig" => "Circle", "value" => "Circle"},
|
86
|
+
],
|
87
|
+
})
|
88
|
+
|
89
|
+
expect(dump["new_page"]).to eq({
|
90
|
+
"_head" => "Z",
|
91
|
+
"_next" => "Triangle",
|
92
|
+
"_id" => "Q",
|
93
|
+
"_hash" => nil,
|
94
|
+
"entries" => [
|
95
|
+
{"_id" => "id0", "_sig" => "Triangle", "value" => "Triangle"},
|
96
|
+
],
|
97
|
+
"__index" => {}
|
98
|
+
})
|
99
|
+
end
|
100
|
+
|
101
|
+
#vm_rehash_page
|
102
|
+
###########################################################################
|
103
|
+
it "vm_rehash_page can calculate the hash correctly" do
|
104
|
+
ctx = flok_new_user File.read('./spec/kern/assets/vm/controller0.rb'), File.read("./spec/kern/assets/vm/config3.rb")
|
105
|
+
|
106
|
+
#Run the check
|
107
|
+
res = ctx.eval %{
|
108
|
+
//Manually construct a page
|
109
|
+
var page = {
|
110
|
+
_head: null,
|
111
|
+
_next: null,
|
112
|
+
_id: "hello",
|
113
|
+
entries: [
|
114
|
+
{_id: "hello2", _sig: "nohteunth"},
|
115
|
+
]
|
116
|
+
}
|
117
|
+
|
118
|
+
vm_rehash_page(page);
|
119
|
+
}
|
120
|
+
|
121
|
+
#Calculate hash ourselves
|
122
|
+
hash = crc32("hello")
|
123
|
+
hash = crc32("nohteunth", hash)
|
124
|
+
page = JSON.parse(ctx.eval("JSON.stringify(page)"))
|
125
|
+
page = JSON.parse(ctx.eval("JSON.stringify(page)"))
|
126
|
+
|
127
|
+
#Expect the same hash
|
128
|
+
expect(page).to eq({
|
129
|
+
"_head" => nil,
|
130
|
+
"_next" => nil,
|
131
|
+
"_id" => "hello",
|
132
|
+
"entries" => [
|
133
|
+
{"_id" => "hello2", "_sig" => "nohteunth"}
|
134
|
+
],
|
135
|
+
"_hash" => hash.to_s
|
136
|
+
})
|
137
|
+
end
|
138
|
+
|
139
|
+
it "vm_rehash_page can calculate the hash correctly with head and next" do
|
140
|
+
ctx = flok_new_user File.read('./spec/kern/assets/vm/controller0.rb'), File.read("./spec/kern/assets/vm/config3.rb")
|
141
|
+
|
142
|
+
#Run the check
|
143
|
+
res = ctx.eval %{
|
144
|
+
//Manually construct a page
|
145
|
+
var page = {
|
146
|
+
_head: "a",
|
147
|
+
_next: "b",
|
148
|
+
_id: "hello",
|
149
|
+
entries: [
|
150
|
+
{_id: "hello2", _sig: "nohteunth"},
|
151
|
+
]
|
152
|
+
}
|
153
|
+
|
154
|
+
vm_rehash_page(page);
|
155
|
+
}
|
156
|
+
|
157
|
+
#Calculate hash ourselves
|
158
|
+
hash = crc32("a")
|
159
|
+
hash = crc32("b", hash)
|
160
|
+
hash = crc32("hello", hash)
|
161
|
+
hash = crc32("nohteunth", hash)
|
162
|
+
page = JSON.parse(ctx.eval("JSON.stringify(page)"))
|
163
|
+
|
164
|
+
#Expect the same hash
|
165
|
+
expect(page).to eq({
|
166
|
+
"_head" => "a",
|
167
|
+
"_next" => "b",
|
168
|
+
"_id" => "hello",
|
169
|
+
"entries" => [
|
170
|
+
{"_id" => "hello2", "_sig" => "nohteunth"}
|
171
|
+
],
|
172
|
+
"_hash" => hash.to_s
|
173
|
+
})
|
174
|
+
end
|
175
|
+
###########################################################################
|
176
|
+
|
177
|
+
#vm_reindex_page
|
178
|
+
###########################################################################
|
179
|
+
it "vm_reindex_page can calculate the __index correctly" do
|
180
|
+
ctx = flok_new_user File.read('./spec/kern/assets/vm/controller0.rb'), File.read("./spec/kern/assets/vm/config3.rb")
|
181
|
+
|
182
|
+
#Run the check
|
183
|
+
res = ctx.eval %{
|
184
|
+
//Manually construct a page
|
185
|
+
var page = {
|
186
|
+
_head: null,
|
187
|
+
_next: null,
|
188
|
+
_id: "hello",
|
189
|
+
entries: [
|
190
|
+
{_id: "hello2", _sig: "nohteunth"},
|
191
|
+
{_id: "hello3", _sig: "nohteunth2"},
|
192
|
+
]
|
193
|
+
}
|
194
|
+
|
195
|
+
vm_reindex_page(page);
|
196
|
+
}
|
197
|
+
|
198
|
+
#Expect the same hash
|
199
|
+
page = ctx.dump("page")
|
200
|
+
expect(page.keys).to include("__index")
|
201
|
+
expect(page["__index"]).to eq({
|
202
|
+
"hello2" => 0,
|
203
|
+
"hello3" => 1
|
204
|
+
})
|
205
|
+
end
|
206
|
+
###########################################################################
|
207
|
+
|
208
|
+
#vm_diff
|
209
|
+
###########################################################################
|
210
|
+
|
211
|
+
#################################################################################################################
|
212
|
+
#Each vm_diff_entry is any array in the format of [type, *args] and each matcher is a hash
|
213
|
+
#in the format of {:type => "*", :args => [...]}. In order for a matcher to match a vm_diff_entry
|
214
|
+
#the matcher's :type must be equal to the vm_diff_entry's type, and the matcher's :args must be
|
215
|
+
#equal to the vm_diff_entry's *args. Equivalency for type is defined as absolutely equal. Equivalency
|
216
|
+
#for args is defined per element; in order for args to be equivalent, all elements of the args must
|
217
|
+
#be equivalent. Each element must be absolutely equal to be equivalent with the exception of argument
|
218
|
+
#elements where the matcher element is of type hash. In the hash case, equivalency is true if the vm_diff_entry
|
219
|
+
#sibling argument element is of type hash *and* the sibling element contains at-least all the key-value pairs
|
220
|
+
#in the forementioned matcher's arg element.
|
221
|
+
#e.g.
|
222
|
+
#################################################################################################################
|
223
|
+
#1. Match without a matcher's args element of type hash.
|
224
|
+
# ["foo", "bar", 3] <=> {:type => "foo", :args => ["bar", 3]}
|
225
|
+
#2. Match with a matcher's args element of type hash.
|
226
|
+
# ["foo", "bar", {"hello" => "world", "goodbye" => "world} <=> {:type => "foo", :args => [{"hello" => "world"}]}
|
227
|
+
#################################################################################################################
|
228
|
+
def verify_vm_diff vm_diff, matchers
|
229
|
+
winning_candidates = []
|
230
|
+
|
231
|
+
_vm_diff = JSON.parse(vm_diff.to_json)
|
232
|
+
|
233
|
+
_vm_diff.each do |vm_diff_entry|
|
234
|
+
#Get the vm_diff_entry in the format of [type, *args]
|
235
|
+
type = vm_diff_entry.shift
|
236
|
+
args = vm_diff_entry
|
237
|
+
|
238
|
+
#Find candidate matchers that have the same type as the vm_diff_entry
|
239
|
+
candidates = matchers.select{|e| e[:type] == type}
|
240
|
+
raise "verify_vm_diff failed. The given vm_diff contained a type, #{type.inspect} that was not even mentioned in the matchers. \nvm_diff = #{vm_diff.inspect}, \nmatchers = #{matchers.inspect}" unless candidates.length > 0
|
241
|
+
|
242
|
+
#Find a candidate that matches the args rules listed in the comments
|
243
|
+
winning_candidate = nil
|
244
|
+
candidates.each do |c|
|
245
|
+
catch(:candidate_failed) do
|
246
|
+
raise "verify_vm_diff failed. A given matcher with type, \n#{c[:type]}, \ncontained no :args array" unless c[:args]
|
247
|
+
next unless c[:args].length == args.length
|
248
|
+
|
249
|
+
c[:args].each_with_index do |a, i|
|
250
|
+
if a.class == Hash
|
251
|
+
throw :candidate_failed if args[i].class != Hash
|
252
|
+
a.each do |k, v|
|
253
|
+
throw :candidate_failed if args[i][k] != v
|
254
|
+
end
|
255
|
+
else
|
256
|
+
#Everything else is exactly equal to be equivalent
|
257
|
+
throw :candidate_failed if a != args[i]
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
winning_candidate = c
|
262
|
+
break
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
if winning_candidate
|
267
|
+
winning_candidates << winning_candidate
|
268
|
+
else
|
269
|
+
raise "verify_vm_diff failed. Could not find a candidate to match the vm_diff_entry of: #{[type, *args]} with the matchers of #{matchers.inspect}"
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
#Make sure all matchers were used
|
274
|
+
left_matchers = matchers - winning_candidates
|
275
|
+
raise "verify_vm_diff failed. Matchers did not all match a vm_diff_entry. \nRemaining matchers include \n#{left_matchers.inspect} \nand matched matchers include \n#{winning_candidates.inspect}\n for the vm_diff of\n#{vm_diff.inspect}" if left_matchers.length > 0
|
276
|
+
end
|
277
|
+
|
278
|
+
#Each vm_page["entries"] is an array, this helper function allows you to define a set
|
279
|
+
#of matchers which will check the entries array to verify that all matchers are equal to
|
280
|
+
#one unique element of the vm_page["entries"]. If all matchers are not exahusted, or all
|
281
|
+
#vm_page["entries"] do not have a paired matcher, then this verify function fails. Equivalency
|
282
|
+
#for entry matcher implies that all key-value pairs of the matcher are present in a vm_page["entries"] entry.
|
283
|
+
#e.g.
|
284
|
+
#############################################################################################################
|
285
|
+
#Matching entry & matcher pair
|
286
|
+
#entry = {"_id" => "my_id", "value" => 4}
|
287
|
+
#matcher = {"_id" => "my_id"} or {"value" => 4} or {"_id => "my_id", "value" => 4}
|
288
|
+
#############################################################################################################
|
289
|
+
def verify_vm_page_entries page, matchers
|
290
|
+
matching_matchers = []
|
291
|
+
page["entries"].each do |entry|
|
292
|
+
#Find matching matcher from matchers
|
293
|
+
matching_matcher = nil
|
294
|
+
matchers.each do |matcher|
|
295
|
+
catch(:matcher_does_not_match) do
|
296
|
+
#For all key value pairs in matcher
|
297
|
+
matcher.each do |k, v|
|
298
|
+
throw :matcher_does_not_match if entry[k] != v
|
299
|
+
end
|
300
|
+
|
301
|
+
matching_matcher = matcher
|
302
|
+
break
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
if matching_matcher
|
307
|
+
matching_matchers << matching_matcher
|
308
|
+
else
|
309
|
+
raise "verify_vm_page_entries failed: The entry: #{entry.inspect} had no matchers that would fit the bill, given matchers include: #{matchers.inspect}. The page was: #{page.inspect}"
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
left_matchers = matchers - matching_matchers
|
314
|
+
raise "verify_vm_page_entries failed: Matchers did not all match an entry. \nRemaining matchers include\n#{left_matchers.inspect}\n and matched matchers include \n#{matching_matchers.inspect}\n for the page of #{page.inspect}" if left_matchers.length > 0
|
315
|
+
end
|
316
|
+
|
317
|
+
#Same as verify_vm_page_entries, but the order of the matchers is taken into account
|
318
|
+
def verify_vm_page_entries_with_order page, matchers
|
319
|
+
page["entries"].each_with_index do |entry, i|
|
320
|
+
matcher = matchers[i]
|
321
|
+
|
322
|
+
#Matcher should match all k, v pairs
|
323
|
+
matcher.each do |k, v|
|
324
|
+
raise "Matcher #{matcher.inspect} did not match entry: #{entry.inspect}\n The order was taken into consideration for entries:\n#{page["entries"].inspect}\nWith Matchers\n#{matchers.inspect}" if entry[k] != v
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
|
330
|
+
#Reload the vm_diff_pages.js. Needed because vm_diff functions
|
331
|
+
#are often destructive and multiple tests need to have a fresh
|
332
|
+
#copy of the pages
|
333
|
+
def reload_vm_diff_pages(ctx)
|
334
|
+
pages_src = File.read("./spec/kern/assets/vm/vm_diff_pages.js")
|
335
|
+
ctx.eval pages_src
|
336
|
+
end
|
337
|
+
|
338
|
+
it "can use vm_diff" do
|
339
|
+
ctx = flok_new_user File.read('./spec/kern/assets/vm/controller22.rb'), File.read("./spec/kern/assets/vm/config5.rb")
|
340
|
+
|
341
|
+
#diff of vm_commit:0, 1
|
342
|
+
#| Triangle | Square | -> | Triangle | Circle |
|
343
|
+
#| K | | -> | | Q |
|
344
|
+
#from to
|
345
|
+
reload_vm_diff_pages(ctx)
|
346
|
+
dump = ctx.evald %{
|
347
|
+
var from = triangle_square_z_null;
|
348
|
+
var to = triangle_circle_null_q;
|
349
|
+
dump.diff = vm_diff(from, to)
|
350
|
+
vm_diff_replay(from, dump.diff);
|
351
|
+
dump.replay = from;
|
352
|
+
vm_rehash_page(dump.replay);
|
353
|
+
vm_reindex_page(dump.replay);
|
354
|
+
}
|
355
|
+
verify_vm_diff(dump["diff"], [
|
356
|
+
{type: "M", args: [{"_id" => "id1", "value" => "Circle"}]},
|
357
|
+
{type: "-", args: ["id2"]},
|
358
|
+
{type: "+", args: [2, {"_id" => "id3", "value" => "Q"}]}
|
359
|
+
])
|
360
|
+
verify_vm_page_entries(dump["replay"], [
|
361
|
+
{"_id" => "id0", "value" => "Triangle"},
|
362
|
+
{"_id" => "id1", "value" => "Circle"},
|
363
|
+
{"_id" => "id3", "value" => "Q"},
|
364
|
+
])
|
365
|
+
|
366
|
+
#vm_commit:2
|
367
|
+
#| Triangle | Square | -> | Q | |
|
368
|
+
#| K | | -> | Circle | Square |
|
369
|
+
#from to
|
370
|
+
reload_vm_diff_pages(ctx)
|
371
|
+
dump = ctx.evald %{
|
372
|
+
var from = triangle_square_z_null;
|
373
|
+
var to = q_null_circle_square;
|
374
|
+
dump.diff = vm_diff(from, to)
|
375
|
+
vm_diff_replay(from, dump.diff);
|
376
|
+
dump.replay = from;
|
377
|
+
vm_rehash_page(dump.replay);
|
378
|
+
vm_reindex_page(dump.replay);
|
379
|
+
}
|
380
|
+
verify_vm_diff(dump["diff"], [
|
381
|
+
{type: "M", args: [{"_id" => "id0", "value" => "Q"}]},
|
382
|
+
{type: "-", args: ["id1"]},
|
383
|
+
{type: "M", args: [{"_id" => "id2", "value" => "Circle"}]},
|
384
|
+
{type: "+", args: [2, {"_id" => "id3", "value" => "Square"}]}
|
385
|
+
])
|
386
|
+
verify_vm_page_entries(dump["replay"], [
|
387
|
+
{"_id" => "id0", "value" => "Q"},
|
388
|
+
{"_id" => "id2", "value" => "Circle"},
|
389
|
+
{"_id" => "id3", "value" => "Square"},
|
390
|
+
])
|
391
|
+
|
392
|
+
#vm_rebase:1 (diff only)
|
393
|
+
#| P | Circle | -> | P | Circle |
|
394
|
+
#| | Q | -> | | |
|
395
|
+
#from to
|
396
|
+
reload_vm_diff_pages(ctx)
|
397
|
+
dump = ctx.evald %{
|
398
|
+
var from = p_circle_null_q;
|
399
|
+
dump.diff = [
|
400
|
+
["+", 0, {"_id": "id1", "_sig": "Square", "value": "Square"}],
|
401
|
+
["M", {"_id": "id2", "_sig": "Z", "value": "Z"}],
|
402
|
+
["-", "id3"],
|
403
|
+
]
|
404
|
+
vm_diff_replay(from, dump.diff);
|
405
|
+
dump.replay = from;
|
406
|
+
vm_rehash_page(dump.replay);
|
407
|
+
vm_reindex_page(dump.replay);
|
408
|
+
}
|
409
|
+
verify_vm_page_entries(dump["replay"], [
|
410
|
+
{"_id" => "id0", "value" => "P"},
|
411
|
+
{"_id" => "id1", "value" => "Circle"},
|
412
|
+
])
|
413
|
+
|
414
|
+
#vm_rebase:2a (diff only)
|
415
|
+
#| P | Circle | -> | P | |
|
416
|
+
#| | Q | -> | | Q |
|
417
|
+
#from to
|
418
|
+
reload_vm_diff_pages(ctx)
|
419
|
+
dump = ctx.evald %{
|
420
|
+
var from = p_circle_null_q;
|
421
|
+
dump.diff = [
|
422
|
+
["-", "id1"],
|
423
|
+
["M", {"_id": "id2", "_sig": "A", "value": "A"}],
|
424
|
+
["+", 2, {"_id":"id3", "_sig": "M", "value": "M"}],
|
425
|
+
]
|
426
|
+
vm_diff_replay(from, dump.diff);
|
427
|
+
dump.replay = from;
|
428
|
+
vm_rehash_page(dump.replay);
|
429
|
+
vm_reindex_page(dump.replay);
|
430
|
+
}
|
431
|
+
verify_vm_page_entries(dump["replay"], [
|
432
|
+
{"_id" => "id0", "value" => "P"},
|
433
|
+
{"_id" => "id3", "value" => "Q"},
|
434
|
+
])
|
435
|
+
|
436
|
+
#vm_rebase:2b (diff only)
|
437
|
+
#| P | | -> | P | Square |
|
438
|
+
#| | Q | -> | | |
|
439
|
+
#from to
|
440
|
+
reload_vm_diff_pages(ctx)
|
441
|
+
dump = ctx.evald %{
|
442
|
+
var from = p_null_null_q;
|
443
|
+
dump.diff = [
|
444
|
+
["+", 1, {"_id":"id1", "_sig": "Square", "value": "Square"}],
|
445
|
+
["M", {"_id": "id2", "_sig": "Z", "value": "Z"}],
|
446
|
+
["-", "id3"],
|
447
|
+
]
|
448
|
+
vm_diff_replay(from, dump.diff);
|
449
|
+
dump.replay = from;
|
450
|
+
vm_rehash_page(dump.replay);
|
451
|
+
vm_reindex_page(dump.replay);
|
452
|
+
}
|
453
|
+
verify_vm_page_entries(dump["replay"], [
|
454
|
+
{"_id" => "id0", "value" => "P"},
|
455
|
+
{"_id" => "id1", "value" => "Square"},
|
456
|
+
])
|
457
|
+
|
458
|
+
#vm_rebase:2c
|
459
|
+
#| P | | -> | P | Square |
|
460
|
+
#| | Q | -> | | |
|
461
|
+
#from to
|
462
|
+
reload_vm_diff_pages(ctx)
|
463
|
+
dump = ctx.evald %{
|
464
|
+
var from = p_null_null_q;
|
465
|
+
var to = p_square_null_null;
|
466
|
+
dump.diff = vm_diff(from, to)
|
467
|
+
vm_diff_replay(from, dump.diff);
|
468
|
+
dump.replay = from;
|
469
|
+
vm_rehash_page(dump.replay);
|
470
|
+
vm_reindex_page(dump.replay);
|
471
|
+
}
|
472
|
+
verify_vm_diff(dump["diff"], [
|
473
|
+
{type: "+", args: [1, {"_id" => "id1", "value" => "Square"}]},
|
474
|
+
{type: "-", args: ["id3"]},
|
475
|
+
])
|
476
|
+
verify_vm_page_entries(dump["replay"], [
|
477
|
+
{"_id" => "id0", "value" => "P"},
|
478
|
+
{"_id" => "id1", "value" => "Square"},
|
479
|
+
])
|
480
|
+
|
481
|
+
#vm_rebase:2d
|
482
|
+
#| Triangle | | -> | Triangle | Square |
|
483
|
+
#| A | M | -> | Z | |
|
484
|
+
#from to
|
485
|
+
reload_vm_diff_pages(ctx)
|
486
|
+
dump = ctx.evald %{
|
487
|
+
var from = triangle_null_a_m;
|
488
|
+
var to = triangle_square_z_null;
|
489
|
+
dump.diff = vm_diff(from, to)
|
490
|
+
vm_diff_replay(from, dump.diff);
|
491
|
+
dump.replay = from;
|
492
|
+
vm_rehash_page(dump.replay);
|
493
|
+
vm_reindex_page(dump.replay);
|
494
|
+
}
|
495
|
+
verify_vm_diff(dump["diff"], [
|
496
|
+
{type: "+", args: [1, {"_id" => "id1", "value" => "Square"}]},
|
497
|
+
{type: "M", args: [{"_id" => "id2", "value" => "Z"}]},
|
498
|
+
{type: "-", args: ["id3"]},
|
499
|
+
])
|
500
|
+
verify_vm_page_entries(dump["replay"], [
|
501
|
+
{"_id" => "id0", "value" => "Triangle"},
|
502
|
+
{"_id" => "id1", "value" => "Square"},
|
503
|
+
{"_id" => "id2", "value" => "Z"},
|
504
|
+
])
|
505
|
+
|
506
|
+
#vm_addendum:2a (diff only)
|
507
|
+
#| Triangle | Square | -> | Triangle | Z |
|
508
|
+
#| | | -> | Q | |
|
509
|
+
#from to
|
510
|
+
reload_vm_diff_pages(ctx)
|
511
|
+
dump = ctx.evald %{
|
512
|
+
var from = triangle_square_null_null;
|
513
|
+
dump.diff = [
|
514
|
+
["M", {"_id": "id1", "_sig": "Z", "value": "Z"}],
|
515
|
+
["+", 2, {"_id":"id2", "_sig": "Q", "value": "Q"}],
|
516
|
+
["-", "id3"],
|
517
|
+
]
|
518
|
+
vm_diff_replay(from, dump.diff);
|
519
|
+
dump.replay = from;
|
520
|
+
vm_rehash_page(dump.replay);
|
521
|
+
vm_reindex_page(dump.replay);
|
522
|
+
}
|
523
|
+
verify_vm_page_entries(dump["replay"], [
|
524
|
+
{"_id" => "id0", "value" => "Triangle"},
|
525
|
+
{"_id" => "id1", "value" => "Z"},
|
526
|
+
{"_id" => "id2", "value" => "Q"},
|
527
|
+
])
|
528
|
+
|
529
|
+
#vm_addendum:2b (diff only)
|
530
|
+
#| Triangle | Square | -> | Triangle | Z |
|
531
|
+
#| | | -> | Q | |
|
532
|
+
#from to
|
533
|
+
reload_vm_diff_pages(ctx)
|
534
|
+
dump = ctx.evald %{
|
535
|
+
var from = triangle_square_null_null;
|
536
|
+
dump.diff = [
|
537
|
+
["M", {"_id": "id1", "_sig": "Z", "value": "Z"}],
|
538
|
+
["+", 2, {"_id":"id2", "_sig": "Q", "value": "Q"}],
|
539
|
+
["-", "id3"],
|
540
|
+
]
|
541
|
+
vm_diff_replay(from, dump.diff);
|
542
|
+
dump.replay = from;
|
543
|
+
vm_rehash_page(dump.replay);
|
544
|
+
vm_reindex_page(dump.replay);
|
545
|
+
}
|
546
|
+
verify_vm_page_entries(dump["replay"], [
|
547
|
+
{"_id" => "id0", "value" => "Triangle"},
|
548
|
+
{"_id" => "id1", "value" => "Z"},
|
549
|
+
{"_id" => "id2", "value" => "Q"},
|
550
|
+
])
|
551
|
+
|
552
|
+
#vm_addendum:2c
|
553
|
+
#head:null head:world
|
554
|
+
#from to
|
555
|
+
reload_vm_diff_pages(ctx)
|
556
|
+
dump = ctx.evald %{
|
557
|
+
var from = head_null;
|
558
|
+
var to = head_world;
|
559
|
+
dump.diff = vm_diff(from, to)
|
560
|
+
vm_diff_replay(from, dump.diff);
|
561
|
+
dump.replay = from;
|
562
|
+
vm_rehash_page(dump.replay);
|
563
|
+
vm_reindex_page(dump.replay);
|
564
|
+
}
|
565
|
+
verify_vm_diff(dump["diff"], [
|
566
|
+
{type: "HEAD_M", args: ["world"]}
|
567
|
+
])
|
568
|
+
expect(dump["replay"]["_head"]).to eq("world")
|
569
|
+
|
570
|
+
#vm_addendum:2d
|
571
|
+
#head:world head:null
|
572
|
+
#from to
|
573
|
+
reload_vm_diff_pages(ctx)
|
574
|
+
dump = ctx.evald %{
|
575
|
+
var from = head_world;
|
576
|
+
var to = head_null;
|
577
|
+
dump.diff = vm_diff(from, to)
|
578
|
+
vm_diff_replay(from, dump.diff);
|
579
|
+
dump.replay = from;
|
580
|
+
vm_rehash_page(dump.replay);
|
581
|
+
vm_reindex_page(dump.replay);
|
582
|
+
}
|
583
|
+
verify_vm_diff(dump["diff"], [
|
584
|
+
{type: "HEAD_M", args: [nil]}
|
585
|
+
])
|
586
|
+
expect(dump["replay"]["_head"]).to eq(nil)
|
587
|
+
|
588
|
+
#vm_addendum:2e
|
589
|
+
#next:null next:world
|
590
|
+
#from to
|
591
|
+
reload_vm_diff_pages(ctx)
|
592
|
+
dump = ctx.evald %{
|
593
|
+
var from = next_null;
|
594
|
+
var to = next_world;
|
595
|
+
dump.diff = vm_diff(from, to)
|
596
|
+
vm_diff_replay(from, dump.diff);
|
597
|
+
dump.replay = from;
|
598
|
+
vm_rehash_page(dump.replay);
|
599
|
+
vm_reindex_page(dump.replay);
|
600
|
+
}
|
601
|
+
verify_vm_diff(dump["diff"], [
|
602
|
+
{type: "NEXT_M", args: ["world"]}
|
603
|
+
])
|
604
|
+
expect(dump["replay"]["_next"]).to eq("world")
|
605
|
+
|
606
|
+
#vm_addendum:2f
|
607
|
+
#next:world next:null
|
608
|
+
#from to
|
609
|
+
reload_vm_diff_pages(ctx)
|
610
|
+
dump = ctx.evald %{
|
611
|
+
var from = next_world;
|
612
|
+
var to = next_null;
|
613
|
+
dump.diff = vm_diff(from, to)
|
614
|
+
vm_diff_replay(from, dump.diff);
|
615
|
+
dump.replay = from;
|
616
|
+
vm_rehash_page(dump.replay);
|
617
|
+
vm_reindex_page(dump.replay);
|
618
|
+
}
|
619
|
+
verify_vm_diff(dump["diff"], [
|
620
|
+
{type: "NEXT_M", args: [nil]}
|
621
|
+
])
|
622
|
+
expect(dump["replay"]["_next"]).to eq(nil)
|
623
|
+
|
624
|
+
#continued... moved, XXXXXXX(N) is the new index
|
625
|
+
#| Triangle(0) | Square(1)| -> | Triangle(1)| Square(0)|
|
626
|
+
#| Z(2) | | -> | Z(2) | |
|
627
|
+
#from to
|
628
|
+
reload_vm_diff_pages(ctx)
|
629
|
+
dump = ctx.evald %{
|
630
|
+
var from = triangle_square_z_null;
|
631
|
+
var to = triangle_square_z_null_moved_square_triangle_z;
|
632
|
+
dump.diff = vm_diff(from, to)
|
633
|
+
vm_diff_replay(from, dump.diff);
|
634
|
+
dump.replay = from;
|
635
|
+
vm_rehash_page(dump.replay);
|
636
|
+
vm_reindex_page(dump.replay);
|
637
|
+
}
|
638
|
+
verify_vm_diff(dump["diff"], [
|
639
|
+
{type: ">", args: [1, "id0"]}
|
640
|
+
])
|
641
|
+
verify_vm_page_entries_with_order(dump["replay"], [
|
642
|
+
{"_id" => "id1", "value" => "Square"},
|
643
|
+
{"_id" => "id0", "value" => "Triangle"},
|
644
|
+
{"_id" => "id2", "value" => "Z"},
|
645
|
+
])
|
646
|
+
|
647
|
+
#moved(2)
|
648
|
+
#| Triangle(0) | Square(1)| -> | Triangle(2)| Square(1)|
|
649
|
+
#| Z(2) | | -> | Z(0) | |
|
650
|
+
#from to
|
651
|
+
reload_vm_diff_pages(ctx)
|
652
|
+
dump = ctx.evald %{
|
653
|
+
var from = triangle_square_z_null;
|
654
|
+
var to = triangle_square_z_null_moved_z_square_triangle;
|
655
|
+
dump.diff = vm_diff(from, to)
|
656
|
+
vm_diff_replay(from, dump.diff);
|
657
|
+
dump.replay = from;
|
658
|
+
vm_rehash_page(dump.replay);
|
659
|
+
vm_reindex_page(dump.replay);
|
660
|
+
}
|
661
|
+
verify_vm_diff(dump["diff"], [
|
662
|
+
{type: ">", args: [2, "id0"]},
|
663
|
+
{type: ">", args: [1, "id1"]}
|
664
|
+
])
|
665
|
+
verify_vm_page_entries_with_order(dump["replay"], [
|
666
|
+
{"_id" => "id2", "value" => "Z"},
|
667
|
+
{"_id" => "id1", "value" => "Square"},
|
668
|
+
{"_id" => "id0", "value" => "Triangle"},
|
669
|
+
])
|
670
|
+
|
671
|
+
#moved(3) Not taking a diff, presenting an illegal move diff
|
672
|
+
#to use on Q (Which dosen't exist)
|
673
|
+
#| Triangle(0) | Square(1)| -> | Triangle(2)| Square(1)|
|
674
|
+
#| Z(2) | | -> | Z(0) | |
|
675
|
+
#from to
|
676
|
+
reload_vm_diff_pages(ctx)
|
677
|
+
dump = ctx.evald %{
|
678
|
+
var from = triangle_square_z_null;
|
679
|
+
dump.diff = [
|
680
|
+
[">", 3, "id3"],
|
681
|
+
[">", 2, "id0"],
|
682
|
+
[">", 1, "id1"],
|
683
|
+
]
|
684
|
+
vm_diff_replay(from, dump.diff);
|
685
|
+
dump.replay = from;
|
686
|
+
vm_rehash_page(dump.replay);
|
687
|
+
vm_reindex_page(dump.replay);
|
688
|
+
}
|
689
|
+
verify_vm_page_entries_with_order(dump["replay"], [
|
690
|
+
{"_id" => "id2", "value" => "Z"},
|
691
|
+
{"_id" => "id1", "value" => "Square"},
|
692
|
+
{"_id" => "id0", "value" => "Triangle"},
|
693
|
+
])
|
694
|
+
end
|
695
|
+
###########################################################################
|
696
|
+
|
697
|
+
#vm commit helpers
|
698
|
+
###########################################################################
|
699
|
+
def reload_vm_commit_pages(ctx)
|
700
|
+
pages_src = File.read("./spec/kern/assets/vm/vm_commit_pages.js")
|
701
|
+
ctx.eval pages_src
|
702
|
+
end
|
703
|
+
|
704
|
+
it "can use vm_commit" do
|
705
|
+
ctx = flok_new_user File.read('./spec/kern/assets/vm/controller22.rb'), File.read("./spec/kern/assets/vm/config5.rb")
|
706
|
+
|
707
|
+
#vm_commit:0
|
708
|
+
#| Triangle | Circle | -> | Triangle | Square |
|
709
|
+
#| | Q | -> | Z | |
|
710
|
+
#newer older
|
711
|
+
reload_vm_commit_pages(ctx)
|
712
|
+
dump = ctx.evald %{
|
713
|
+
dump.newer = triangle_circle_null_q;
|
714
|
+
dump.older = triangle_square_z_null;
|
715
|
+
vm_commit(dump.older, dump.newer);
|
716
|
+
}
|
717
|
+
|
718
|
+
verify_vm_page_entries(dump["newer"], [
|
719
|
+
{"_id" => "id0", "value" => "Triangle"},
|
720
|
+
{"_id" => "id1", "value" => "Circle"},
|
721
|
+
{"_id" => "id3", "value" => "Q"},
|
722
|
+
])
|
723
|
+
|
724
|
+
#Changes match
|
725
|
+
verify_vm_diff(dump["newer"]["__changes"], [
|
726
|
+
{type: "M", args: [{"_id" => "id1", "value" => "Circle"}]},
|
727
|
+
{type: "-", args: ["id2"]},
|
728
|
+
{type: "+", args: [2, {"_id" => "id3", "value" => "Q"}]},
|
729
|
+
])
|
730
|
+
|
731
|
+
#No base but does include changes
|
732
|
+
expect(dump["newer"]["__changes_id"]).not_to eq(nil)
|
733
|
+
expect(dump["newer"]["__base"]).to eq(nil)
|
734
|
+
|
735
|
+
#vm_commit:1 older[nobase, changes]
|
736
|
+
#| Triangle | Circle | -> | Triangle | Square | --__changes-- | ----- |
|
737
|
+
#| | Q | -> | Z | | | |x| | Add (+) |
|
738
|
+
#newer older | ----- Triangle |
|
739
|
+
# | | | | |
|
740
|
+
# | ----- |
|
741
|
+
# | ----- |
|
742
|
+
# | | | | Modify (M) |
|
743
|
+
# | ----- Z |
|
744
|
+
# | |x| | |
|
745
|
+
# | ----- |
|
746
|
+
# | ----- |
|
747
|
+
# | | | | Remove (-) |
|
748
|
+
# | ----- |
|
749
|
+
# | | |x| |
|
750
|
+
# | ----- |
|
751
|
+
reload_vm_commit_pages(ctx)
|
752
|
+
dump = ctx.evald %{
|
753
|
+
dump.newer = triangle_circle_null_q;
|
754
|
+
dump.older = triangle_square_z_null;
|
755
|
+
dump.older.__changes_id = "XXXXX";
|
756
|
+
dump.older.__changes = [
|
757
|
+
["+", 0, {"_id": "id0", "_sig": "Triangle", "value": "Triangle"}],
|
758
|
+
["M", {"_id": "id2", "_sig": "Z", "value": "Z"}],
|
759
|
+
["-", "id3"],
|
760
|
+
|
761
|
+
]
|
762
|
+
vm_commit(dump.older, dump.newer);
|
763
|
+
}
|
764
|
+
|
765
|
+
verify_vm_page_entries(dump["newer"], [
|
766
|
+
{"_id" => "id0", "value" => "Triangle"},
|
767
|
+
{"_id" => "id1", "value" => "Circle"},
|
768
|
+
{"_id" => "id3", "value" => "Q"},
|
769
|
+
])
|
770
|
+
|
771
|
+
#Changes match
|
772
|
+
verify_vm_diff(dump["newer"]["__changes"], [
|
773
|
+
{type: "M", args: [{"_id" => "id1", "value" => "Circle"}]},
|
774
|
+
{type: "-", args: ["id2"]},
|
775
|
+
{type: "+", args: [2, {"_id" => "id3", "value" => "Q"}]},
|
776
|
+
])
|
777
|
+
expect(dump["newer"]["__changes_id"]).not_to eq(nil)
|
778
|
+
|
779
|
+
#Base with changes
|
780
|
+
verify_vm_page_entries(dump["newer"]["__base"], [
|
781
|
+
{"_id" => "id0", "value" => "Triangle"},
|
782
|
+
{"_id" => "id1", "value" => "Square"},
|
783
|
+
{"_id" => "id2", "value" => "Z"},
|
784
|
+
])
|
785
|
+
verify_vm_diff(dump["newer"]["__base"]["__changes"], [
|
786
|
+
{type: "+", args: [0, {"_id" => "id0", "value" => "Triangle"}]},
|
787
|
+
{type: "-", args: ["id3"]},
|
788
|
+
{type: "M", args: [{"_id" => "id2", "value" => "Z"}]},
|
789
|
+
])
|
790
|
+
expect(dump["newer"]["__base"]["__changes_id"]).not_to eq(nil)
|
791
|
+
expect(dump["newer"]["__base"]["__base"]).to eq(nil)
|
792
|
+
|
793
|
+
#vm_commit:2 older[base[nobase, changes], changes]
|
794
|
+
#| Q | | -> | Triangle | Circle | --__changes-- | ----- |
|
795
|
+
#| Circle | Square | -> | | Q | | | |x| Modify (M) |
|
796
|
+
#newer ----------------------- | ----- Circle |
|
797
|
+
# | __base | | | | | |
|
798
|
+
# ----------------------- | ----- |
|
799
|
+
# | Triangle | Square | | ----- |
|
800
|
+
# | Z | | --__changes- | | | | Remove (-) |
|
801
|
+
# older | | ----- |
|
802
|
+
# | | |x| | |
|
803
|
+
# | | ----- |
|
804
|
+
# | | ----- |
|
805
|
+
# | | | | | Insert (+) |
|
806
|
+
# | | ----- Q |
|
807
|
+
# | | | |x| |
|
808
|
+
# | | ----- |
|
809
|
+
# | --------------------
|
810
|
+
# |
|
811
|
+
# |- | ----- |
|
812
|
+
# | |x| | Add (+) |
|
813
|
+
# | ----- Triangle |
|
814
|
+
# | | | | |
|
815
|
+
# | ----- |
|
816
|
+
# | ----- |
|
817
|
+
# | | | | Modify (M) |
|
818
|
+
# | ----- Z |
|
819
|
+
# | |x| | |
|
820
|
+
# | ----- |
|
821
|
+
# | ----- |
|
822
|
+
# | | | | Remove (-) |
|
823
|
+
# | ----- |
|
824
|
+
# | | |x| |
|
825
|
+
# | ----- |
|
826
|
+
reload_vm_commit_pages(ctx)
|
827
|
+
dump = ctx.evald %{
|
828
|
+
dump.newer = q_null_circle_square;
|
829
|
+
dump.older = triangle_circle_null_q;
|
830
|
+
dump.older.__changes_id = "XXXXX";
|
831
|
+
dump.older.__changes = [
|
832
|
+
["M", {"_id": "id0", "_sig": "Circle", "value": "Circle"}],
|
833
|
+
["-", "id2"],
|
834
|
+
["+", 2, {"_id": "id3", "_sig": "Q", "value": "Q"}],
|
835
|
+
]
|
836
|
+
|
837
|
+
//Also, base on older
|
838
|
+
dump.older.__base = triangle_square_z_null;
|
839
|
+
dump.older.__base.__changes = [
|
840
|
+
["+", 0, {"_id": "id0", "_sig": "Triangle", "value": "Triangle"}],
|
841
|
+
["M", {"_id": "id2", "_sig": "Z", "value": "Z"}],
|
842
|
+
["-", "id3"],
|
843
|
+
]
|
844
|
+
dump.older.__base.__changes_id = "YYYYYYY";
|
845
|
+
vm_commit(dump.older, dump.newer);
|
846
|
+
}
|
847
|
+
|
848
|
+
verify_vm_page_entries(dump["newer"], [
|
849
|
+
{"_id" => "id0", "value" => "Q"},
|
850
|
+
{"_id" => "id2", "value" => "Circle"},
|
851
|
+
{"_id" => "id3", "value" => "Square"},
|
852
|
+
])
|
853
|
+
|
854
|
+
#Changes match
|
855
|
+
verify_vm_diff(dump["newer"]["__changes"], [
|
856
|
+
{type: "M", args: [{"_id" => "id0", "value" => "Q"}]},
|
857
|
+
{type: "-", args: ["id1"]},
|
858
|
+
{type: "M", args: [{"_id" => "id2", "value" => "Circle"}]},
|
859
|
+
{type: "+", args: [2, {"_id" => "id3", "value" => "Square"}]},
|
860
|
+
])
|
861
|
+
expect(dump["newer"]["__changes_id"]).not_to eq(nil)
|
862
|
+
|
863
|
+
#Base with changes
|
864
|
+
verify_vm_page_entries(dump["newer"]["__base"], [
|
865
|
+
{"_id" => "id0", "value" => "Triangle"},
|
866
|
+
{"_id" => "id1", "value" => "Square"},
|
867
|
+
{"_id" => "id2", "value" => "Z"},
|
868
|
+
])
|
869
|
+
verify_vm_diff(dump["newer"]["__base"]["__changes"], [
|
870
|
+
{type: "+", args: [0, {"_id" => "id0", "value" => "Triangle"}]},
|
871
|
+
{type: "M", args: [{"_id" => "id2", "value" => "Z"}]},
|
872
|
+
{type: "-", args: ["id3"]},
|
873
|
+
])
|
874
|
+
expect(dump["newer"]["__base"]["__changes_id"]).not_to eq(nil)
|
875
|
+
expect(dump["newer"]["__base"]["__base"]).to eq(nil)
|
876
|
+
end
|
877
|
+
|
878
|
+
it "can use vm_rebase" do
|
879
|
+
ctx = flok_new_user File.read('./spec/kern/assets/vm/controller22.rb'), File.read("./spec/kern/assets/vm/config5.rb")
|
880
|
+
|
881
|
+
#vm_rebase:0 newer[nobase, nochange]
|
882
|
+
#| Triangle | Circle | -> | Triangle | Square |
|
883
|
+
#| | Q | -> | Z | |
|
884
|
+
#older newer
|
885
|
+
reload_vm_commit_pages(ctx)
|
886
|
+
dump = ctx.evald %{
|
887
|
+
dump.older = triangle_circle_null_q;
|
888
|
+
dump.newer = triangle_square_z_null;
|
889
|
+
vm_rebase(dump.newer, dump.older);
|
890
|
+
}
|
891
|
+
|
892
|
+
verify_vm_page_entries(dump["older"], [
|
893
|
+
{"_id" => "id0", "value" => "Triangle"},
|
894
|
+
{"_id" => "id1", "value" => "Circle"},
|
895
|
+
{"_id" => "id3", "value" => "Q"},
|
896
|
+
])
|
897
|
+
|
898
|
+
#No base & No changes
|
899
|
+
expect(dump["older"]["__changes"]).to eq(nil)
|
900
|
+
expect(dump["older"]["__changes_id"]).to eq(nil)
|
901
|
+
expect(dump["older"]["__base"]).to eq(nil)
|
902
|
+
|
903
|
+
#vm_rebase:1 newer[nobase, changes]
|
904
|
+
#| P | Circle | -> | Triangle | Square | --__changes-- | ----- |
|
905
|
+
#| | Q | -> | Z | | | | |x| Add (+) |
|
906
|
+
#older newer | ----- Square |
|
907
|
+
# | | | | |
|
908
|
+
# | ----- |
|
909
|
+
# | ----- |
|
910
|
+
# | | | | Modify (M) |
|
911
|
+
# | ----- Z |
|
912
|
+
# | |x| | |
|
913
|
+
# | ----- |
|
914
|
+
# | ----- |
|
915
|
+
# | | | | Remove (-) |
|
916
|
+
# | ----- |
|
917
|
+
# | | |x| |
|
918
|
+
# | ----- |
|
919
|
+
reload_vm_commit_pages(ctx)
|
920
|
+
dump = ctx.evald %{
|
921
|
+
dump.older = p_circle_null_q;
|
922
|
+
dump.newer = triangle_square_z_null;
|
923
|
+
dump.newer.__changes = [
|
924
|
+
["+", 0, {"_id": "id1", "_sig": "Square", "value": "Square"}],
|
925
|
+
["M", {"_id": "id2", "_sig": "Z", "value": "Z"}],
|
926
|
+
["-", "id3"],
|
927
|
+
]
|
928
|
+
dump.newer.__changes_id = "XXXXXXXXXXX";
|
929
|
+
vm_rebase(dump.newer, dump.older);
|
930
|
+
}
|
931
|
+
|
932
|
+
verify_vm_page_entries(dump["older"], [
|
933
|
+
{"_id" => "id0", "value" => "P"},
|
934
|
+
{"_id" => "id1", "value" => "Circle"},
|
935
|
+
])
|
936
|
+
|
937
|
+
#Changes match
|
938
|
+
verify_vm_diff(dump["older"]["__changes"], [
|
939
|
+
{type: "+", args: [0, {"_id" => "id1", "value" => "Square"}]},
|
940
|
+
{type: "M", args: [{"_id" => "id2", "value" => "Z"}]},
|
941
|
+
{type: "-", args: ["id3"]},
|
942
|
+
])
|
943
|
+
expect(dump["older"]["__changes_id"]).not_to eq(nil)
|
944
|
+
|
945
|
+
#No base
|
946
|
+
expect(dump["older"]["__base"]).to eq(nil)
|
947
|
+
|
948
|
+
#vm_rebase:2 newer[base[nobase, changes], changes]
|
949
|
+
#| P | Circle | -> | Triangle | Square | --__changes-- | ----- |
|
950
|
+
#| | Q | -> | K | | | | |x| Add (+) |
|
951
|
+
#older ----------------------- | ----- Square |
|
952
|
+
# | __base | | | | | |
|
953
|
+
# ----------------------- | ----- |
|
954
|
+
# | Triangle | | | ----- |
|
955
|
+
# | A | M | --__changes- | | | | Modify (M) |
|
956
|
+
# newer | | ----- Z |
|
957
|
+
# | | |x| | |
|
958
|
+
# | | ----- |
|
959
|
+
# | | ----- |
|
960
|
+
# | | | | | Remove (-) |
|
961
|
+
# | | ----- |
|
962
|
+
# | | | |x| |
|
963
|
+
# | | ----- |
|
964
|
+
# | --------------------
|
965
|
+
# |
|
966
|
+
# |- | ----- |
|
967
|
+
# | | |x| Remove (-) |
|
968
|
+
# | ----- |
|
969
|
+
# | | | | |
|
970
|
+
# | ----- |
|
971
|
+
# | ----- |
|
972
|
+
# | | | | Modify (M) |
|
973
|
+
# | ----- A |
|
974
|
+
# | |x| | |
|
975
|
+
# | ----- |
|
976
|
+
# | ----- |
|
977
|
+
# | | | | Add (+) |
|
978
|
+
# | ----- M |
|
979
|
+
# | | |x| |
|
980
|
+
# | ----- |
|
981
|
+
reload_vm_commit_pages(ctx)
|
982
|
+
dump = ctx.evald %{
|
983
|
+
dump.older = p_circle_null_q;
|
984
|
+
dump.newer = triangle_square_z_null;
|
985
|
+
dump.newer.__changes_id = "XXXXX";
|
986
|
+
dump.newer.__changes = [
|
987
|
+
["+", 0, {"_id": "id1", "_sig": "Square", "value": "Square"}],
|
988
|
+
["M", {"_id": "id2", "_sig": "Z", "value": "Z"}],
|
989
|
+
["-", "id3"],
|
990
|
+
]
|
991
|
+
|
992
|
+
//Also, base on older
|
993
|
+
dump.newer.__base = triangle_null_a_m;
|
994
|
+
dump.newer.__base.__changes = [
|
995
|
+
["-", "id1"],
|
996
|
+
["M", {"_id": "id2", "_sig": "A", "value": "A"}],
|
997
|
+
["+", 2, {"_id": "id3", "_sig": "+", "value": "M"}],
|
998
|
+
]
|
999
|
+
dump.newer.__base.__changes_id = "YYYYYYY";
|
1000
|
+
vm_rebase(dump.newer, dump.older);
|
1001
|
+
}
|
1002
|
+
|
1003
|
+
verify_vm_page_entries(dump["older"], [
|
1004
|
+
{"_id" => "id0", "value" => "P"},
|
1005
|
+
{"_id" => "id1", "value" => "Square"},
|
1006
|
+
])
|
1007
|
+
|
1008
|
+
#Changes match
|
1009
|
+
verify_vm_diff(dump["older"]["__changes"], [
|
1010
|
+
{type: "+", args: [0, {"_id" => "id1", "value" => "Square"}]},
|
1011
|
+
{type: "-", args: ["id3"]},
|
1012
|
+
])
|
1013
|
+
expect(dump["older"]["__changes_id"]).not_to eq(nil)
|
1014
|
+
expect(dump["older"]["__changes_id"]).not_to eq("XXXXX")
|
1015
|
+
|
1016
|
+
#Base with changes
|
1017
|
+
verify_vm_page_entries(dump["older"]["__base"], [
|
1018
|
+
{"_id" => "id0", "value" => "P"},
|
1019
|
+
{"_id" => "id3", "value" => "Q"},
|
1020
|
+
])
|
1021
|
+
verify_vm_diff(dump["older"]["__base"]["__changes"], [
|
1022
|
+
{type: "-", args: ["id1"]},
|
1023
|
+
{type: "M", args: [{"_id" => "id2", "value" => "A"}]},
|
1024
|
+
{type: "+", args: [2, {"_id" => "id3", "value" => "M"}]},
|
1025
|
+
])
|
1026
|
+
expect(dump["older"]["__base"]["__changes_id"]).to eq("YYYYYYY")
|
1027
|
+
expect(dump["older"]["__base"]["__base"]).to eq(nil)
|
1028
|
+
end
|
1029
|
+
|
1030
|
+
it "can use vm_mark_changes_synced" do
|
1031
|
+
ctx = flok_new_user File.read('./spec/kern/assets/vm/controller22.rb'), File.read("./spec/kern/assets/vm/config5.rb")
|
1032
|
+
|
1033
|
+
#Case A
|
1034
|
+
#Page with no changes. (Nothing happends)
|
1035
|
+
dump = ctx.evald %{
|
1036
|
+
dump.page = vm_create_page();
|
1037
|
+
vm_mark_changes_synced(dump.page, "changes_id");
|
1038
|
+
|
1039
|
+
dump.__changes_id_is_undefined = (dump.page.__changes_id === undefined)
|
1040
|
+
dump.__changes_is_undefined = (dump.page.__changes === undefined)
|
1041
|
+
}
|
1042
|
+
expect(dump["__changes_id_is_undefined"]).to eq(true)
|
1043
|
+
expect(dump["__changes_is_undefined"]).to eq(true)
|
1044
|
+
|
1045
|
+
#Case B
|
1046
|
+
#Page with changes, but changes_id given to vm_mark_changes_synced does not match (Nothing happends).
|
1047
|
+
dump = ctx.evald %{
|
1048
|
+
dump.page = vm_create_page();
|
1049
|
+
dump.page.__changes_id = "foo";
|
1050
|
+
dump.page.__changes = ["A"]
|
1051
|
+
vm_mark_changes_synced(dump.page, "bar");
|
1052
|
+
}
|
1053
|
+
expect(dump["page"]["__changes"]).to eq(["A"])
|
1054
|
+
expect(dump["page"]["__changes_id"]).to eq("foo")
|
1055
|
+
|
1056
|
+
#Case C
|
1057
|
+
#Page with changes but no base, and changes_id given to vm_mark_changes_synced does match __changes_id of page.
|
1058
|
+
#The __changes and __changes_id of the page will be removed.
|
1059
|
+
dump = ctx.evald %{
|
1060
|
+
dump.page = vm_create_page();
|
1061
|
+
dump.page.__changes_id = "foo";
|
1062
|
+
dump.page.__changes = ["A"]
|
1063
|
+
vm_mark_changes_synced(dump.page, "foo");
|
1064
|
+
|
1065
|
+
dump.__changes_id_is_undefined = (dump.page.__changes_id === undefined)
|
1066
|
+
dump.__changes_is_undefined = (dump.page.__changes === undefined)
|
1067
|
+
}
|
1068
|
+
expect(dump["__changes_id_is_undefined"]).to eq(true)
|
1069
|
+
expect(dump["__changes_is_undefined"]).to eq(true)
|
1070
|
+
|
1071
|
+
#Case D
|
1072
|
+
#Page with changes and a base[changes, nobase], and changes_id given to vm_mark_changes_synced does not match __base.__changes_id of page.
|
1073
|
+
#Nothing happends
|
1074
|
+
dump = ctx.evald %{
|
1075
|
+
dump.page = vm_create_page();
|
1076
|
+
dump.page.__changes_id = "foo";
|
1077
|
+
dump.page.__changes = ["A"]
|
1078
|
+
|
1079
|
+
//Attach base [unbased, changes]
|
1080
|
+
dump.page.__base = vm_create_page();
|
1081
|
+
dump.page.__base.__changes_id = "bar";
|
1082
|
+
dump.page.__base.__changes = ["B"]
|
1083
|
+
|
1084
|
+
vm_mark_changes_synced(dump.page, "foo");
|
1085
|
+
}
|
1086
|
+
expect(dump["page"]["__changes"]).to eq(["A"])
|
1087
|
+
expect(dump["page"]["__changes_id"]).to eq("foo")
|
1088
|
+
|
1089
|
+
#Case E
|
1090
|
+
#Page with changes and a base[changes, nobase], and changes_id given to vm_mark_changes_synced does match __base.__changes_id of page.
|
1091
|
+
#The base will be removed, but the page's __changes and __changes_id will remain.
|
1092
|
+
dump = ctx.evald %{
|
1093
|
+
dump.page = vm_create_page();
|
1094
|
+
dump.page.__changes_id = "foo";
|
1095
|
+
dump.page.__changes = ["A"]
|
1096
|
+
|
1097
|
+
//Attach base [unbased, changes]
|
1098
|
+
dump.page.__base = vm_create_page();
|
1099
|
+
dump.page.__base.__changes_id = "bar";
|
1100
|
+
dump.page.__base.__changes = ["B"]
|
1101
|
+
|
1102
|
+
vm_mark_changes_synced(dump.page, "bar");
|
1103
|
+
|
1104
|
+
dump.__base_is_undefined = (dump.page.__base === undefined)
|
1105
|
+
}
|
1106
|
+
expect(dump["__base_is_undefined"]).to eq(true)
|
1107
|
+
expect(dump["page"]["__changes"]).to eq(["A"])
|
1108
|
+
expect(dump["page"]["__changes_id"]).to eq("foo")
|
1109
|
+
end
|
1110
|
+
###########################################################################
|
1111
|
+
end
|