Add tests for connection logic

This commit is contained in:
Rachel Fenichel 2016-02-25 15:16:32 -08:00
parent c2f879ad14
commit 9263e28263
4 changed files with 318 additions and 70 deletions

View file

@ -200,6 +200,8 @@ Blockly.Connection.prototype.checkConnection_ = function(target) {
throw 'Source connection already connected.';
case Blockly.Connection.REASON_TARGET_NULL:
throw 'Target connection is null.';
case Blockly.Connection.REASON_CHECKS_FAILED:
throw 'Connection checks failed.';
default:
throw 'Unknown connection failure: this should never happen!';
}
@ -293,8 +295,7 @@ Blockly.Connection.prototype.connect = function(otherConnection) {
}
// Establish the connections.
this.targetConnection = otherConnection;
otherConnection.targetConnection = this;
Blockly.Connection.connectReciprocally(this, otherConnection);
// Demote the inferior block so that one is a child of the superior one.
childBlock.setParent(parentBlock);
@ -319,6 +320,19 @@ Blockly.Connection.prototype.connect = function(otherConnection) {
}
};
/**
* Update two connections to target each other.
* @param {Blockly.Connection} first The first connection to update.
* @param {Blockly.Connection} second The second conneciton to update.
*/
Blockly.Connection.connectReciprocally = function(first, second) {
if (!first || !second) {
throw 'Cannot connect null connections.';
}
first.targetConnection = second;
second.targetConnection = first;
}
/**
* Does the given block have one and only one connection point that will accept
* an orphaned block?

View file

@ -0,0 +1,95 @@
/**
* @license
* Blockly Tests
*
* Copyright 2015 Google Inc.
* https://developers.google.com/blockly/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
function verify_DB_(msg, expected, db) {
var equal = (expected.length == db.length);
if (equal) {
for (var x = 0; x < expected.length; x++) {
if (expected[x] != db[x]) {
equal = false;
break;
}
}
}
if (equal) {
assertTrue(msg, true);
} else {
assertEquals(msg, expected, db);
}
}
function test_DB_addConnection() {
var db = new Blockly.ConnectionDB();
var o2 = {y_: 2, sourceBlock_: {}};
db.addConnection_(o2);
verify_DB_('Adding connection #2', [o2], db);
var o4 = {y_: 4, sourceBlock_: {}};
db.addConnection_(o4);
verify_DB_('Adding connection #4', [o2, o4], db);
var o1 = {y_: 1, sourceBlock_: {}};
db.addConnection_(o1);
verify_DB_('Adding connection #1', [o1, o2, o4], db);
var o3a = {y_: 3, sourceBlock_: {}};
db.addConnection_(o3a);
verify_DB_('Adding connection #3a', [o1, o2, o3a, o4], db);
var o3b = {y_: 3, sourceBlock_: {}};
db.addConnection_(o3b);
verify_DB_('Adding connection #3b', [o1, o2, o3b, o3a, o4], db);
}
function test_DB_removeConnection() {
var db = new Blockly.ConnectionDB();
var o1 = {y_: 1, sourceBlock_: {}};
var o2 = {y_: 2, sourceBlock_: {}};
var o3a = {y_: 3, sourceBlock_: {}};
var o3b = {y_: 3, sourceBlock_: {}};
var o3c = {y_: 3, sourceBlock_: {}};
var o4 = {y_: 4, sourceBlock_: {}};
db.addConnection_(o1);
db.addConnection_(o2);
db.addConnection_(o3c);
db.addConnection_(o3b);
db.addConnection_(o3a);
db.addConnection_(o4);
verify_DB_('Adding connections 1-4', [o1, o2, o3a, o3b, o3c, o4], db);
db.removeConnection_(o2);
verify_DB_('Removing connection #2', [o1, o3a, o3b, o3c, o4], db);
db.removeConnection_(o4);
verify_DB_('Removing connection #4', [o1, o3a, o3b, o3c], db);
db.removeConnection_(o1);
verify_DB_('Removing connection #1', [o3a, o3b, o3c], db);
db.removeConnection_(o3a);
verify_DB_('Removing connection #3a', [o3b, o3c], db);
db.removeConnection_(o3c);
verify_DB_('Removing connection #3c', [o3b], db);
db.removeConnection_(o3b);
verify_DB_('Removing connection #3b', [], db);
}

View file

@ -2,7 +2,7 @@
* @license
* Blockly Tests
*
* Copyright 2015 Google Inc.
* Copyright 2016 Google Inc.
* https://developers.google.com/blockly/
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -17,79 +17,217 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Tests for connection logic.
* @author fenichel@google.com (Rachel Fenichel)
*/
'use strict';
function verify_DB_(msg, expected, db) {
var equal = (expected.length == db.length);
if (equal) {
for (var x = 0; x < expected.length; x++) {
if (expected[x] != db[x]) {
equal = false;
break;
}
}
}
if (equal) {
assertTrue(msg, true);
} else {
assertEquals(msg, expected, db);
}
var input;
var output;
var previous;
var next;
var dummyWorkspace;
function connectionTest_setUp() {
dummyWorkspace = {};
input = new Blockly.Connection({workspace: dummyWorkspace}, Blockly.INPUT_VALUE);
output = new Blockly.Connection({workspace: dummyWorkspace}, Blockly.OUTPUT_VALUE);
previous = new Blockly.Connection({workspace: dummyWorkspace}, Blockly.PREVIOUS_STATEMENT);
next = new Blockly.Connection({workspace: dummyWorkspace}, Blockly.NEXT_STATEMENT);
}
function test_DB_addConnection() {
var db = new Blockly.ConnectionDB();
var o2 = {y_: 2, sourceBlock_: {}};
db.addConnection_(o2);
verify_DB_('Adding connection #2', [o2], db);
var o4 = {y_: 4, sourceBlock_: {}};
db.addConnection_(o4);
verify_DB_('Adding connection #4', [o2, o4], db);
var o1 = {y_: 1, sourceBlock_: {}};
db.addConnection_(o1);
verify_DB_('Adding connection #1', [o1, o2, o4], db);
var o3a = {y_: 3, sourceBlock_: {}};
db.addConnection_(o3a);
verify_DB_('Adding connection #3a', [o1, o2, o3a, o4], db);
var o3b = {y_: 3, sourceBlock_: {}};
db.addConnection_(o3b);
verify_DB_('Adding connection #3b', [o1, o2, o3b, o3a, o4], db);
function connectionTest_tearDown() {
input = null;
output = null;
previous = null;
next = null;
dummyWorkspace = null;
}
function test_DB_removeConnection() {
var db = new Blockly.ConnectionDB();
var o1 = {y_: 1, sourceBlock_: {}};
var o2 = {y_: 2, sourceBlock_: {}};
var o3a = {y_: 3, sourceBlock_: {}};
var o3b = {y_: 3, sourceBlock_: {}};
var o3c = {y_: 3, sourceBlock_: {}};
var o4 = {y_: 4, sourceBlock_: {}};
db.addConnection_(o1);
db.addConnection_(o2);
db.addConnection_(o3c);
db.addConnection_(o3b);
db.addConnection_(o3a);
db.addConnection_(o4);
verify_DB_('Adding connections 1-4', [o1, o2, o3a, o3b, o3c, o4], db);
/**
* These tests check that the reasons for failures to connect are consistent (internal view of
* error states).
*/
function testCanConnectWithReason_TargetNull() {
connectionTest_setUp();
db.removeConnection_(o2);
verify_DB_('Removing connection #2', [o1, o3a, o3b, o3c, o4], db);
assertEquals(Blockly.Connection.REASON_TARGET_NULL, input.canConnectWithReason_(null));
db.removeConnection_(o4);
verify_DB_('Removing connection #4', [o1, o3a, o3b, o3c], db);
db.removeConnection_(o1);
verify_DB_('Removing connection #1', [o3a, o3b, o3c], db);
db.removeConnection_(o3a);
verify_DB_('Removing connection #3a', [o3b, o3c], db);
db.removeConnection_(o3c);
verify_DB_('Removing connection #3c', [o3b], db);
db.removeConnection_(o3b);
verify_DB_('Removing connection #3b', [], db);
connectionTest_tearDown();
}
function testCanConnectWithReason_Disconnect() {
connectionTest_setUp();
var tempConnection = new Blockly.Connection({workspace: dummyWorkspace}, Blockly.OUTPUT_VALUE);
Blockly.Connection.connectReciprocally(input, tempConnection);
assertEquals(Blockly.Connection.REASON_MUST_DISCONNECT, input.canConnectWithReason_(output));
connectionTest_tearDown();
}
function testCanConnectWithReason_DifferentWorkspaces() {
connectionTest_setUp();
input = new Blockly.Connection({workspace: {}}, Blockly.INPUT_VALUE);
output = new Blockly.Connection({workspace: dummyWorkspace}, Blockly.OUTPUT_VALUE);
assertEquals(Blockly.Connection.REASON_DIFFERENT_WORKSPACES, input.canConnectWithReason_(output));
connectionTest_tearDown();
}
function testCanConnectWithReason_Self() {
connectionTest_setUp();
var block = {type_: "test block"};
input.sourceBlock_ = block;
assertEquals(Blockly.Connection.REASON_SELF_CONNECTION, input.canConnectWithReason_(input));
connectionTest_tearDown();
}
function testCanConnectWithReason_Type() {
connectionTest_setUp();
assertEquals(Blockly.Connection.REASON_WRONG_TYPE, input.canConnectWithReason_(previous));
assertEquals(Blockly.Connection.REASON_WRONG_TYPE, input.canConnectWithReason_(next));
assertEquals(Blockly.Connection.REASON_WRONG_TYPE, output.canConnectWithReason_(previous));
assertEquals(Blockly.Connection.REASON_WRONG_TYPE, output.canConnectWithReason_(next));
assertEquals(Blockly.Connection.REASON_WRONG_TYPE, previous.canConnectWithReason_(input));
assertEquals(Blockly.Connection.REASON_WRONG_TYPE, previous.canConnectWithReason_(output));
assertEquals(Blockly.Connection.REASON_WRONG_TYPE, next.canConnectWithReason_(input));
assertEquals(Blockly.Connection.REASON_WRONG_TYPE, next.canConnectWithReason_(output));
connectionTest_tearDown();
}
function testCanConnectWithReason_CanConnect() {
connectionTest_setUp();
assertEquals(Blockly.Connection.CAN_CONNECT, previous.canConnectWithReason_(next));
assertEquals(Blockly.Connection.CAN_CONNECT, next.canConnectWithReason_(previous));
assertEquals(Blockly.Connection.CAN_CONNECT, input.canConnectWithReason_(output));
assertEquals(Blockly.Connection.CAN_CONNECT, output.canConnectWithReason_(input));
connectionTest_tearDown();
}
/**
* The next set of tests checks that exceptions are being thrown at the correct times (external
* view of errors).
*/
function testCheckConnection_Self() {
connectionTest_setUp();
var block = {type_: "test block"};
input.sourceBlock_ = block;
try {
input.checkConnection_(input);
fail();
} catch (e) {
// expected
}
connectionTest_tearDown();
}
function testCheckConnection_TypeInputPrev() {
connectionTest_setUp();
try {
input.checkConnection_(previous);
fail();
} catch (e) {
// expected
}
connectionTest_tearDown();
}
function testCheckConnection_TypeInputNext() {
connectionTest_setUp();
try {
input.checkConnection_(next);
fail();
} catch (e) {
// expected
}
connectionTest_tearDown();
}
function testCheckConnection_TypeOutputPrev() {
connectionTest_setUp();
try {
output.checkConnection_(previous);
fail();
} catch (e) {
// expected
}
connectionTest_tearDown();
}
function testCheckConnection_TypePrevInput() {
connectionTest_setUp();
try {
previous.checkConnection_(input);
fail();
} catch (e) {
// expected
}
connectionTest_tearDown();
}
function testCheckConnection_TypePrevOutput() {
connectionTest_setUp();
try {
previous.checkConnection_(output);
fail();
} catch (e) {
// expected
}
connectionTest_tearDown();
}
function testCheckConnection_TypeNextInput() {
connectionTest_setUp();
try {
next.checkConnection_(input);
fail();
} catch (e) {
// expected
}
connectionTest_tearDown();
}
function testCheckConnection_TypeNextOutput() {
connectionTest_setUp();
try {
next.checkConnection_(output);
fail();
} catch (e) {
// expected
}
connectionTest_tearDown();
}
function testCheckConnection_Okay() {
connectionTest_setUp();
previous.checkConnection_(next);
next.checkConnection_(previous);
input.checkConnection_(output);
output.checkConnection_(input);
connectionTest_tearDown();
}

View file

@ -10,6 +10,7 @@
<script src="blockly_test.js"></script>
<script src="block_test.js"></script>
<script src="connection_test.js"></script>
<script src="connection_db_test.js"></script>
<script src="generator_test.js"></script>
<script src="names_test.js"></script>
<script src="workspace_test.js"></script>