Index: src/libbn/tests/CMakeLists.txt
===================================================================
--- src/libbn/tests/CMakeLists.txt	(revision 58878)
+++ src/libbn/tests/CMakeLists.txt	(working copy)
@@ -10,6 +10,7 @@
 BRLCAD_ADDEXEC(tester_bn_chull bn_chull.c "libbu;libbn" NO_INSTALL)
 BRLCAD_ADDEXEC(tester_bn_plane_pt bn_plane_pt.c "libbu;libbn" NO_INSTALL)
 BRLCAD_ADDEXEC(tester_bn_plane_dist bn_plane_dist.c "libbu;libbn" NO_INSTALL)
+BRLCAD_ADDEXEC(tester_bn_plane_isect bn_plane_isect.c "libbu;libbn" NO_INSTALL)
 CMAKEFILES(bn_chull_test003_bot.asc)
 CMAKEFILES(bn_chull_test004_bot.asc)
 CMAKEFILES(bn_poly_cubic_roots.c bn_poly_quartic_roots.c bn_obr.c)
@@ -222,6 +223,56 @@
 add_test(bn_plane_dist_pt3_pt3_same   tester_bn_plane_dist 3 0,0,0 0,0,0 0)
 add_test(bn_plane_dist_pt3_pt3_1      tester_bn_plane_dist 3 0,0,0 1,1,1 1.732051)
 
+# For tester_bn_plane_isect, the input format is as follows:
+#
+# tester_bn_plane_isect <function number> <args>
+
+# For function #1 (bn_isect_line_lseg), the <args> format is as follows:
+#
+# Px,Py,Pz Dx,Dy,Dz Ax,Ay,Az Bx,By,Bz expected_return expected_t
+#
+# where P and D define the parametric line, and A and B define the
+# line segment. An individual point is three integer or floating point
+# numbers separated by commas.
+
+add_test(bn_plane_isect_line_lseg_case-4_1   tester_bn_plane_isect 1 -5,-5,-5 1,1,1 0,0,0 0,0,0 -4 0)
+# This test fails because it thinks that there is an intersection
+# between a and b, even though the intersection is less than a.
+add_test(bn_plane_isect_line_lseg_case-3_1   tester_bn_plane_isect 1 -5,-5,-5 1,1,1 0,0,1 0,0,5 -3 6)
+# This test fails because it does not return the correct t.
+add_test(bn_plane_isect_line_lseg_case-2_1   tester_bn_plane_isect 1 -5,-5,-5 1,1,1 0,0,-5 0,0,1 -2 6)
+add_test(bn_plane_isect_line_lseg_case-1_1   tester_bn_plane_isect 1 -5,-5,-5 1,1,1 -5,-5,-6 0,0,-1 -1 0)
+# This test fails because it does not return the correct t for a
+add_test(bn_plane_isect_line_lseg_case0_1    tester_bn_plane_isect 1 -5,-5,-5 1,1,1 1,1,1 5,5,5 0 6)
+# This test fails because it thinks that there is an intersection
+# between a and be even though they intersect at a
+add_test(bn_plane_isect_line_lseg_case1_1    tester_bn_plane_isect 1 -5,-5,-5 1,1,1 0,0,0 0,0,5 1 5)
+# This test fails because it thinks that the intersection is past b
+# even though it is at b
+add_test(bn_plane_isect_line_lseg_case2_1    tester_bn_plane_isect 1 -5,-5,-5 1,1,1 0,0,-5 0,0,0 2 5)
+# This test fails because it does not return the correct t for the intersection
+add_test(bn_plane_isect_line_lseg_case3_1    tester_bn_plane_isect 1 -5,-5,-5 1,1,1 0,0,-5 0,0,5 3 5)
+
+# For function #2 (bn_isect_lseg3_lseg3), the <args> format is as follows:
+#
+# Px,Py,Pz PDIRx,PDIRy,PDIRz Qx,Qy,Qz QDIRx,QDIRy,QDIRz expected_return expected_dist_0 expected_dist_1
+#
+# Where P and PDIR define the first segment, and Q and QDIR define the
+# second. expected_dist_0 and expected_dist_1 are the expected values
+# of the two components of the dist[] array output by the function. An
+# individual point is three integer or floating point numbers
+# separated by commas.
+
+add_test(bn_plane_isect_lseg3_lseg3_case-3_1   tester_bn_plane_isect 2 0,0,0 0,1,1 0,0,1 0,-1,1 -3 0.5 -0.5)
+add_test(bn_plane_isect_lseg3_lseg3_case-3_2   tester_bn_plane_isect 2 0,0,0 0,1,1 0,1,0 0,-0.25,0.25 -3 0.5 2)
+add_test(bn_plane_isect_lseg3_lseg3_case-2_1   tester_bn_plane_isect 2 0,0,0 0,1,1 1,1,1 0,1,1 -2 0 0)
+add_test(bn_plane_isect_lseg3_lseg3_case-1_1   tester_bn_plane_isect 2 -5,-5,-5 3,3,3 0,0,0 -1,-1,-1 -1 1.666667 1.333333)
+add_test(bn_plane_isect_lseg3_lseg3_case0_1    tester_bn_plane_isect 2 -5,-5,-5 3,3,3 0,0,0 -2,-2,-2 0 1.666667 1)
+add_test(bn_plane_isect_lseg3_lseg3_case0_2    tester_bn_plane_isect 2 -5,-5,-5 3,3,3 0,0,0 -3,-3,-3 0 1.666667 0.666667)
+add_test(bn_plane_isect_lseg3_lseg3_case0_3    tester_bn_plane_isect 2 -5,-5,-5 5,5,5 -4,-4,-4 2,2,2 0 0.2 0.6)
+add_test(bn_plane_isect_lseg3_lseg3_case1_1    tester_bn_plane_isect 2 0,0,0 0,1,1 0,1,0 0,-1,1 1 0.5 0.5)
+
+
 # Local Variables:
 # tab-width: 8
 # mode: cmake
Index: src/libbn/tests/bn_plane_isect.c
===================================================================
--- src/libbn/tests/bn_plane_isect.c	(revision 0)
+++ src/libbn/tests/bn_plane_isect.c	(working copy)
@@ -0,0 +1,137 @@
+/*                 B N _ P L A N E _ I S E C T . C
+ * BRL-CAD
+ *
+ * Copyright (c) 2013 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; see the file named COPYING for more
+ * information.
+ */
+
+#include "common.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "bu.h"
+#include "bn.h"
+
+
+#define TOL_INIT { BN_TOL_MAGIC, BN_TOL_DIST, BN_TOL_DIST * BN_TOL_DIST, 1e-6, 1.0 - 1e-6 }
+
+
+static int
+test_bn_isect_line_lseg(int argc, char **argv)
+{
+    int expected_return = 0;
+    int actual_return = 0;
+    fastf_t expected_t;
+    fastf_t actual_t;
+    point_t p = VINIT_ZERO;
+    vect_t d = VINIT_ZERO;
+    point_t a = VINIT_ZERO;
+    point_t b = VINIT_ZERO;
+    struct bn_tol tol = TOL_INIT;
+
+    if (argc != 8) {
+	bu_exit(1, "ERROR: input format is Px,Py,Pz Dx,Dy,Dz Ax,Ay,Az Bx,By,Bz expected_return expected_t [%s]\n", argv[0]);
+    }
+
+    sscanf(argv[2], "%lf,%lf,%lf", &p[X], &p[Y], &p[Z]);
+    sscanf(argv[3], "%lf,%lf,%lf", &d[X], &d[Y], &d[Z]);
+    sscanf(argv[4], "%lf,%lf,%lf", &a[X], &a[Y], &a[Z]);
+    sscanf(argv[5], "%lf,%lf,%lf", &b[X], &b[Y], &b[Z]);
+    sscanf(argv[6], "%d", &expected_return);
+    sscanf(argv[7], "%lf", &expected_t);
+
+    actual_return = bn_isect_line_lseg(&actual_t, p, d, a, b, &tol);
+
+    bu_log("return: %d\n", actual_return);
+    bu_log("t: %f\n", actual_t);
+
+    return !(expected_return == actual_return
+	     && NEAR_EQUAL(expected_t, actual_t, BN_TOL_DIST));
+}
+
+
+static int
+test_bn_isect_lseg3_lseg3(int argc, char **argv)
+{
+    int expected_return = 0;
+    int actual_return = 0;
+    fastf_t expected_dist[2] = {0,0, 0.0};
+    fastf_t actual_dist[2] = {0,0, 0.0};
+    point_t p = VINIT_ZERO;
+    vect_t pdir = VINIT_ZERO;
+    point_t q = VINIT_ZERO;
+    vect_t qdir = VINIT_ZERO;
+    struct bn_tol tol = TOL_INIT;
+
+    if (argc != 9) {
+	bu_exit(1, "ERROR: input format is Px,Py,Pz PDIRx,PDIRy,PDIRz Qx,Qy,Qz QDIRx,QDIRy,QDIRz expected_return expected_dist_0 expected_dist_1 [%s]\n", argv[0]);
+    }
+
+    sscanf(argv[2], "%lf,%lf,%lf", &p[X], &p[Y], &p[Z]);
+    sscanf(argv[3], "%lf,%lf,%lf", &pdir[X], &pdir[Y], &pdir[Z]);
+    sscanf(argv[4], "%lf,%lf,%lf", &q[X], &q[Y], &q[Z]);
+    sscanf(argv[5], "%lf,%lf,%lf", &qdir[X], &qdir[Y], &qdir[Z]);
+    sscanf(argv[6], "%d", &expected_return);
+    sscanf(argv[7], "%lf", &expected_dist[0]);
+    sscanf(argv[8], "%lf", &expected_dist[1]);
+
+    actual_return = bn_isect_lseg3_lseg3(actual_dist, p, pdir, q, qdir, &tol);
+
+    bu_log("return: %d\n", actual_return);
+    bu_log("dist[0]: %f\n", actual_dist[0]);
+    bu_log("dist[1]: %f\n", actual_dist[1]);
+
+    return !(expected_return == actual_return
+	     && NEAR_EQUAL(expected_dist[0], actual_dist[0], BN_TOL_DIST)
+	     && NEAR_EQUAL(expected_dist[1], actual_dist[1], BN_TOL_DIST));
+}
+
+
+int
+main(int argc, char *argv[])
+{
+    int function_num = 0;
+
+    if (argc < 3) {
+	bu_exit(1, "ERROR: input format is function_num function_test_args [%s]\n", argv[0]);
+    }
+
+    sscanf(argv[1], "%d", &function_num);
+    if (function_num < 1 || function_num > 5)
+	function_num = 0;
+
+    switch (function_num) {
+        case 1:
+	    return test_bn_isect_line_lseg(argc, argv);
+        case 2:
+	    return test_bn_isect_lseg3_lseg3(argc, argv);
+    }
+    return 1;
+}
+
+
+/** @} */
+/*
+ * Local Variables:
+ * mode: C
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * c-file-style: "stroustrup"
+ * End:
+ * ex: shiftwidth=4 tabstop=8
+ */
