Put in new allwiplib-2018 and packaged the large files

added new allwpilib

added ntcore

Added new wpiutil

Change-Id: I5bbb966a69ac2fbdce056e4c092a13f246dbaa6a
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/README.html b/third_party/allwpilib_2018/wpilibjIntegrationTests/README.html
new file mode 100644
index 0000000..dc9d154
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/README.html
@@ -0,0 +1,389 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <style>/* Fonts */
+@font-face{
+  font-family: octicons-anchor;
+  src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAYcAA0AAAAACjQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABMAAAABwAAAAca8vGTk9TLzIAAAFMAAAARAAAAFZG1VHVY21hcAAAAZAAAAA+AAABQgAP9AdjdnQgAAAB0AAAAAQAAAAEACICiGdhc3AAAAHUAAAACAAAAAj//wADZ2x5ZgAAAdwAAADRAAABEKyikaNoZWFkAAACsAAAAC0AAAA2AtXoA2hoZWEAAALgAAAAHAAAACQHngNFaG10eAAAAvwAAAAQAAAAEAwAACJsb2NhAAADDAAAAAoAAAAKALIAVG1heHAAAAMYAAAAHwAAACABEAB2bmFtZQAAAzgAAALBAAAFu3I9x/Nwb3N0AAAF/AAAAB0AAAAvaoFvbwAAAAEAAAAAzBdyYwAAAADP2IQvAAAAAM/bz7t4nGNgZGFgnMDAysDB1Ml0hoGBoR9CM75mMGLkYGBgYmBlZsAKAtJcUxgcPsR8iGF2+O/AEMPsznAYKMwIkgMA5REMOXicY2BgYGaAYBkGRgYQsAHyGMF8FgYFIM0ChED+h5j//yEk/3KoSgZGNgYYk4GRCUgwMaACRoZhDwCs7QgGAAAAIgKIAAAAAf//AAJ4nHWMMQrCQBBF/0zWrCCIKUQsTDCL2EXMohYGSSmorScInsRGL2DOYJe0Ntp7BK+gJ1BxF1stZvjz/v8DRghQzEc4kIgKwiAppcA9LtzKLSkdNhKFY3HF4lK69ExKslx7Xa+vPRVS43G98vG1DnkDMIBUgFN0MDXflU8tbaZOUkXUH0+U27RoRpOIyCKjbMCVejwypzJJG4jIwb43rfl6wbwanocrJm9XFYfskuVC5K/TPyczNU7b84CXcbxks1Un6H6tLH9vf2LRnn8Ax7A5WQAAAHicY2BkYGAA4teL1+yI57f5ysDNwgAC529f0kOmWRiYVgEpDgYmEA8AUzEKsQAAAHicY2BkYGB2+O/AEMPCAAJAkpEBFbAAADgKAe0EAAAiAAAAAAQAAAAEAAAAAAAAKgAqACoAiAAAeJxjYGRgYGBhsGFgYgABEMkFhAwM/xn0QAIAD6YBhwB4nI1Ty07cMBS9QwKlQapQW3VXySvEqDCZGbGaHULiIQ1FKgjWMxknMfLEke2A+IJu+wntrt/QbVf9gG75jK577Lg8K1qQPCfnnnt8fX1NRC/pmjrk/zprC+8D7tBy9DHgBXoWfQ44Av8t4Bj4Z8CLtBL9CniJluPXASf0Lm4CXqFX8Q84dOLnMB17N4c7tBo1AS/Qi+hTwBH4rwHHwN8DXqQ30XXAS7QaLwSc0Gn8NuAVWou/gFmnjLrEaEh9GmDdDGgL3B4JsrRPDU2hTOiMSuJUIdKQQayiAth69r6akSSFqIJuA19TrzCIaY8sIoxyrNIrL//pw7A2iMygkX5vDj+G+kuoLdX4GlGK/8Lnlz6/h9MpmoO9rafrz7ILXEHHaAx95s9lsI7AHNMBWEZHULnfAXwG9/ZqdzLI08iuwRloXE8kfhXYAvE23+23DU3t626rbs8/8adv+9DWknsHp3E17oCf+Z48rvEQNZ78paYM38qfk3v/u3l3u3GXN2Dmvmvpf1Srwk3pB/VSsp512bA/GG5i2WJ7wu430yQ5K3nFGiOqgtmSB5pJVSizwaacmUZzZhXLlZTq8qGGFY2YcSkqbth6aW1tRmlaCFs2016m5qn36SbJrqosG4uMV4aP2PHBmB3tjtmgN2izkGQyLWprekbIntJFing32a5rKWCN/SdSoga45EJykyQ7asZvHQ8PTm6cslIpwyeyjbVltNikc2HTR7YKh9LBl9DADC0U/jLcBZDKrMhUBfQBvXRzLtFtjU9eNHKin0x5InTqb8lNpfKv1s1xHzTXRqgKzek/mb7nB8RZTCDhGEX3kK/8Q75AmUM/eLkfA+0Hi908Kx4eNsMgudg5GLdRD7a84npi+YxNr5i5KIbW5izXas7cHXIMAau1OueZhfj+cOcP3P8MNIWLyYOBuxL6DRylJ4cAAAB4nGNgYoAALjDJyIAOWMCiTIxMLDmZedkABtIBygAAAA==) format('woff');
+}
+
+@font-face{
+  font-family: fontawesome-mini;
+  src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAzUABAAAAAAFNgAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABbAAAABwAAAAcZMzaOEdERUYAAAGIAAAAHQAAACAAOQAET1MvMgAAAagAAAA+AAAAYHqhde9jbWFwAAAB6AAAAFIAAAFa4azkLWN2dCAAAAI8AAAAKAAAACgFgwioZnBnbQAAAmQAAAGxAAACZVO0L6dnYXNwAAAEGAAAAAgAAAAIAAAAEGdseWYAAAQgAAAFDgAACMz7eroHaGVhZAAACTAAAAAwAAAANgWEOEloaGVhAAAJYAAAAB0AAAAkDGEGa2htdHgAAAmAAAAAEwAAADBEgAAQbG9jYQAACZQAAAAaAAAAGgsICJBtYXhwAAAJsAAAACAAAAAgASgBD25hbWUAAAnQAAACZwAABOD4no+3cG9zdAAADDgAAABsAAAAmF+yXM9wcmVwAAAMpAAAAC4AAAAusPIrFAAAAAEAAAAAyYlvMQAAAADLVHQgAAAAAM/u9uZ4nGNgZGBg4ANiCQYQYGJgBEJuIGYB8xgABMMAPgAAAHicY2Bm42OcwMDKwMLSw2LMwMDQBqGZihmiwHycoKCyqJjB4YPDh4NsDP+BfNb3DIuAFCOSEgUGRgAKDgt4AAB4nGNgYGBmgGAZBkYGEAgB8hjBfBYGCyDNxcDBwMTA9MHhQ9SHrA8H//9nYACyQyFs/sP86/kX8HtB9UIBIxsDXICRCUgwMaACRoZhDwA3fxKSAAAAAAHyAHABJQB/AIEAdAFGAOsBIwC/ALgAxACGAGYAugBNACcA/wCIeJxdUbtOW0EQ3Q0PA4HE2CA52hSzmZDGe6EFCcTVjWJkO4XlCGk3cpGLcQEfQIFEDdqvGaChpEibBiEXSHxCPiESM2uIojQ7O7NzzpkzS8qRqnfpa89T5ySQwt0GzTb9Tki1swD3pOvrjYy0gwdabGb0ynX7/gsGm9GUO2oA5T1vKQ8ZTTuBWrSn/tH8Cob7/B/zOxi0NNP01DoJ6SEE5ptxS4PvGc26yw/6gtXhYjAwpJim4i4/plL+tzTnasuwtZHRvIMzEfnJNEBTa20Emv7UIdXzcRRLkMumsTaYmLL+JBPBhcl0VVO1zPjawV2ys+hggyrNgQfYw1Z5DB4ODyYU0rckyiwNEfZiq8QIEZMcCjnl3Mn+pED5SBLGvElKO+OGtQbGkdfAoDZPs/88m01tbx3C+FkcwXe/GUs6+MiG2hgRYjtiKYAJREJGVfmGGs+9LAbkUvvPQJSA5fGPf50ItO7YRDyXtXUOMVYIen7b3PLLirtWuc6LQndvqmqo0inN+17OvscDnh4Lw0FjwZvP+/5Kgfo8LK40aA4EQ3o3ev+iteqIq7wXPrIn07+xWgAAAAABAAH//wAPeJyFlctvG1UUh+/12DPN1B7P3JnYjj2Ox4/MuDHxJH5N3UdaEUQLqBIkfQQioJWQ6AMEQkIqsPGCPwA1otuWSmTBhjtps2ADWbJg3EpIXbGouqSbCraJw7kzNo2dRN1cnXN1ZvT7zuuiMEI7ncizyA0URofRBJpCdbQuIFShYY+GZRrxMDVtih5TwQPHtXDFFSIKoWIbuREBjLH27Ny4MsbVx+uOJThavebgVrNRLAiYx06rXsvhxLgWx9xpfHdrs/ekc2Pl2cpPCVEITQpwbj8VQhfXSq2m+Wxqaq2D73Kne5e3NjHqQNj3CRYlJlgUl/jRNP+2Gs2pNYRQiOnmUaQDqm30KqKiTTWPWjboxnTWpvgxjXo0KrtZXAHt7hwIz0YVcj88JnKlJKi3NPAwLyDwZudSmJSMMJFDYaOkaol6XtESx3Gt1VTytdZJ3DCLeaVhVnCBH1fycHTxFXwPX+l2e3d6H/TufGGmMTLTnbSJUdo00zuBswMO/nl3YLeL/wnu9/limCuD3vC54h5NBVz6Li414AI8Vx3iiosKcQXUbrvhFFiYb++HN4DaF4XzFW0fIN4XDWJ3a3XQoq9V8WiyRmdsatV9xUcHims1JloH0YUa090G3Tro3mC6c01f+YwCPquINr1PTaCP6rVTOOmf0GE2dBc7zWIhji3/5MchSuBHgDbU99RMWt3YUNMZMJmx92YP6NsHx/5/M1yvInpnkIOM3Z8fA3JQ2lW1RFC1KaBPDFXNAHYYvGy73aYZZZ3HifbeuiVZCpwA3oQBs0wGPYJbJfg60xrKEbKiNtTe1adwrpBRwlAuQ3q3VRaX0QmQ9a49BTSCuF1MLfQ6+tinOubRBZuWPNoMevGMT+V41KitO1is3D/tpMcq1JHZqDHGs8DoYGDkxJgKjHROeTCmhZvzPm9pod+ltKm4PN7Dyvvldlpsg8D+4AUJZ3F/JBstZz7cbFRxsaAGV6yX/dkcycWf8eS3QlQea+YLjdm3yrOnrhFpUyKVvFE4lpv4bO3Svx/6F/4xmiDu/RT5iI++lko18mY1oX+5UGKR6kmVjM/Zb76yfHtxy+h/SyQ0lLdpdKy/lWB6szatetQJ8nZ80A2Qt6ift6gJeavU3BO4gtxs/KCtNPVibCtYCWY3SIlSBPKXZALXiIR9oZeJ1AuMyxLpHIy/yO7vSiSE+kZvk0ihJ30HgHfzZtEMmvV58x6dtqns0XTAW7Vdm4HJ04OCp/crOO7rd9SGxQAE/mVA9xRN+kVSMRFF6S9JFGUtthkjBA5tFCWc2l4V43Ex9GmUP3SI37Jjmir9KqlaDJ4S4JB3vuM/jzyH1+8MuoZ+QGzfnvPoJb96cZlWjMcKLfgDwB7E634JTY+asjsPzS5CiVnEWY+KsrsIN5rn3mAPjqmQBxGjcGKB9f9ZxY3mYC2L85CJ2FXIxKKyHk+dg0FHbuEc7D5NzWUX32WxFcWNGRAbvwSx0RmIXVDuYySafluQBmzA/ssqJAMLnli+WIC90Gw4lm85wcp0qjArEDPJJV/sSx4P9ungTpgMw5gVC1XO4uULq0s3v1rqLi0vX/z65vlH50f8T/RHmSPTk5xxWBWOluMT6WiOy+tdvWxlV/XQb3o3c6Ssr+r6I708GsX9/nzp1tKFh0s3v7m4vAy/Hnb/KMOvc1wump6Il48K6mGDy02X9Yd65pa+nQIjk76lWxCkG8NBCP0HQS9IpAAAeJxjYGRgYGBhcCrq214Qz2/zlUGenQEEzr/77oug/zewFbB+AHI5GJhAogBwKQ0qeJxjYGRgYH3/P46BgZ0BBNgKGBgZUAEPAE/7At0AAAB4nGNngAB2IGYjhBsYBAAIYADVAAAAAAAAAAAAAFwAyAEeAaACCgKmAx4DggRmAAAAAQAAAAwAagAEAAAAAAACAAEAAgAWAAABAAChAAAAAHiclZI7bxQxFIWPd/JkUYQChEhIyAVKgdBMskm1QkKrRETpQiLRUczueB/K7HhlOxttg8LvoKPgP9DxFxANDR0tHRWi4NjrPIBEgh1p/dm+vufcawNYFWsQmP6e4jSyQB2fI9cwj++RE9wTjyPP4LYoI89iWbyLPIe6+Bh5Hs9rryMv4GbtW+RF3EhuRa7jbrIbeQkPkjdUETOLnL0Kip4FVvAhco1RXyMnSPEz8gzWxE7kWTwUp5HnsCLeR57HW/El8gJWa58iL+JO7UfkOh4l9yMv4UnyEtvQGGECgwF66MNBooF1bGCL1ELB/TYU+ZBRlvsKQ44Se6jQ4a7hef+fh72Crv25kp+8lNWGmeKoOI5jJLb1aGIGvb6TjfWNLdkqdFvJw4l1amjlXtXRZqRN7lSRylZZyhBqpVFWmTEXgWfUrpi/hZOQXdOd4rKuXOtEWT3k5IArPRzTUU5tHKjecZkTpnVbNOnt6jzN8240GD4xtikvZW56043rPMg/dS+dlOceXoR+WPbJ55Dsekq1lJpnypsMUsYOdCW30o103Ytu/lvh+5RWFLfBjm9/N8hJntPhvx92rnoE/kyHdGasGy754kw36vsVf/lFeBi+0COu+cfgQr42G3CRpeLoZ53gmfe3X6rcKt5oVxnptHR9JS8ehVUd5wvvahN2uqxOOpMXapibI5k7Zwbt4xBSaTfoKBufhAnO/uqNcfK8OTs0OQ6l7JIqFjDhYj5WcjevCnI/1DDiI8j4ndWb/5YzDZWh79yomWXeXj7Nnw70/2TIeFPTrlSh89k1ObOSRVZWZfgF0r/zJQB4nG2JUQuCQBCEd07TTg36fb2IyBaLd3vWaUh/vmSJnvpgmG8YcmS8X3Shf3R7QA4OBUocUKHGER5NNbOOEvwc1txnuWkTRb/aPjimJ5vXabI+3VfOiyS15UWvyezM2xiGOPyuMohOH8O8JiO4Af+FsAGNAEuwCFBYsQEBjlmxRgYrWCGwEFlLsBRSWCGwgFkdsAYrXFhZsBQrAAA=) format('woff');
+}
+
+/* Body */
+html { font-size: 100%; overflow-y: scroll; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
+
+body{
+  color:#4d4d4c;
+  font-family:Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman',
+              "Hiragino Sans GB", "STXihei", "微软雅黑", serif;
+  font-size:12px;
+  line-height:1.5em;
+  background:#fefefe;
+  width: 45em;
+  margin: 10px auto;
+  padding: 30px;
+  border: 1px solid #ddd;
+  outline: 1300px solid #f8f8f8;
+}
+
+/* Links */
+a{ color: #06d; text-decoration:none; }
+a:hover{ color: #06e; text-decoration: underline; }
+a:active{ color:#faa700; }
+a:focus{ outline: thin dotted; }
+a:hover, a:active{ outline: 0; }
+
+::-moz-selection { background:#a8d1ff; color:#000 }
+::selection { background:#a8d1ff; color:#000 }
+
+a::-moz-selection { background:#a8d1ff; color:#0645ad }
+a::selection { background:#a8d1ff; color:#0645ad }
+
+/* Header Anchor Links*/
+.headeranchor-link {
+  color:#111;
+  border: 0;
+  margin-left: -20px;
+  padding-right: 6px;
+  cursor: pointer;
+  position: absolute;
+  display: block;
+  top: 0;
+  left: 0;
+  bottom: 0;
+}
+
+.headeranchor {
+  font: normal normal 16px octicons-anchor;
+  line-height: 1;
+  -moz-osx-font-smoothing: grayscale;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+
+.headeranchor-link:hover,
+.headeranchor-link:visited,
+.headeranchor-link:active
+{ text-decoration: none; color:#4d4d4c; }
+.headeranchor-link:hover .headeranchor:before,
+h1:hover .headeranchor:before,
+h2:hover .headeranchor:before,
+h3:hover .headeranchor:before,
+h4:hover .headeranchor:before,
+h5:hover .headeranchor:before,
+h6:hover .headeranchor:before
+{ content: '\f05c'; }
+
+abbr { cursor: pointer; }
+
+/* Paragraphs */
+p { margin:1em 0; }
+
+/* Images */
+img {
+  max-width:100%;
+  border: 0;
+  -ms-interpolation-mode: bicubic;
+  vertical-align: middle;
+}
+
+/* Headers */
+h1,h2,h3,h4,h5,h6 {
+  font-weight:normal;
+  color:#111;
+  line-height: 1.7;
+  position: relative;
+}
+h4,h5,h6{ font-weight: bold; }
+h1 { font-size:2.5em; border-bottom: 1px solid #ddd;}
+h2 { font-size:2em; border-bottom:1px solid #eee; padding-bottom: 5px; }
+h3 { font-size:1.5em; }
+h4 { font-size:1.2em; }
+h5 { font-size:1em; }
+h6 { font-size:0.9em; }
+
+/* Block Quotes */
+blockquote {
+  color:#666666;
+  margin:0;
+  padding-left: 3em;
+  border-left: 0.5em #EEE solid;
+}
+hr { display: block; height: 2px; border: 0; border-top: 1px solid #aaa;border-bottom: 1px solid #eee; margin: 1em 0; padding: 0; }
+
+/* Raw Blocks */
+pre, code, kbd, samp {
+  color: #000;
+  font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  border-radius: 3px;
+  font-size: 0.88em;
+  background-color: #F8F8F8;
+  border: 1px solid #CCC;
+}
+
+pre {
+  padding: 10px;
+  overflow: auto;
+}
+
+code { padding: 0 3px 0 3px; }
+pre code { border: 0; padding: 0; }
+
+/* Admonition */
+.admonition {
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  border-radius: 3px;
+  font-size: 0.88em;
+  padding: 0.5em 1em 0.5em 1em;
+  margin: 10px auto;
+  color: #888888;
+  background-color: #F8F8F8;
+  border: 1px solid #888888;
+}
+
+.admonition p { padding: 0; margin: 0; }
+.admonition-title { font-weight: bold; margin: 0; }
+
+.admonition-icon {
+  font: normal normal 16px fontawesome-mini;
+  line-height: 1.5;
+  -moz-osx-font-smoothing: grayscale;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  float: left;
+}
+
+.admonition.attention { color: #4F8A10; background-color: #DFF2BF; border: 1px solid #4F8A10; }
+.admonition.caution { color: #D63301; background-color: #FFCCBA; border: 1px solid #D63301; }
+.admonition.hint { color: #00529B; background-color: #BDE5F8; border: 1px solid #00529B; }
+.admonition.danger { color: #D8000C; background-color: #FFBABA; border: 1px solid #D8000C; }
+.admonition.question { color: #00049b; background-color: #BDC8F8; border: 1px solid #00049b; }
+.admonition.note { color: #9F6000; background-color: #FEEFB3; border: 1px solid #9F6000; }
+
+.attention > .admonition-icon:before { content: "\f058\00a0"; }
+.caution > .admonition-icon:before { content: "\f06a\00a0"; }
+.hint > .admonition-icon:before { content: "\f05a\00a0"; }
+.danger > .admonition-icon:before { content: "\f056\00a0"; }
+.question > .admonition-icon:before { content: "\f059\00a0"; }
+.note > .admonition-icon:before { content: "\f040\00a0"; }
+
+/* progress bar*/
+.progress {
+  display: block;
+  width: 300px;
+  margin: 10px 0;
+  height: 24px;
+  border: 1px solid #ccc;
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  border-radius: 3px;
+  background-color: #F8F8F8;
+  position: relative;
+  box-shadow: inset -1px 1px 3px rgba(0, 0, 0, .1);
+}
+
+.progress-label {
+  position: absolute;
+  text-align: center;
+  font-weight: bold;
+  width: 100%; margin: 0;
+  line-height: 24px;
+  color: #333;
+  text-shadow:
+    1px 1px 0px #fefefe,
+    -1px -1px 0px #fefefe,
+    -1px 1px 0px #fefefe,
+    1px -1px 0px #fefefe,
+    0px 1px 0px #fefefe,
+    0px -1px 0px #fefefe,
+    1px 0px 0px #fefefe,
+    -1px 0px 0px #fefefe,
+    1px 1px 2px #000;
+  -webkit-font-smoothing: antialiased !important;
+  white-space: nowrap;
+  overflow: hidden;
+}
+
+.progress-bar {
+  height: 24px;
+  float: left;
+  border-right: 1px solid #ccc;
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  border-radius: 3px;
+  background-color: #34c2e3;
+  box-shadow: inset 0 1px 0px rgba(255, 255, 255, .5);
+  background-size: 30px 30px;
+  background-image: -webkit-linear-gradient(
+    135deg,
+    rgba(255, 255, 255, .4) 27%, transparent 27%,
+    transparent 53%, rgba(255, 255, 255, .4) 53%,
+    rgba(255, 255, 255, .4) 77%, transparent 77%,
+    transparent
+  );
+  background-image: -moz-linear-gradient(
+    135deg,
+    rgba(255, 255, 255, .4) 27%, transparent 27%,
+    transparent 53%, rgba(255, 255, 255, .4) 53%,
+    rgba(255, 255, 255, .4) 77%, transparent 77%,
+    transparent
+  );
+  background-image: -ms-linear-gradient(
+    135deg,
+    rgba(255, 255, 255, .4) 27%, transparent 27%,
+    transparent 53%, rgba(255, 255, 255, .4) 53%,
+    rgba(255, 255, 255, .4) 77%, transparent 77%,
+    transparent
+  );
+  background-image: -o-linear-gradient(
+    135deg,
+    rgba(255, 255, 255, .4) 27%, transparent 27%,
+    transparent 53%, rgba(255, 255, 255, .4) 53%,
+    rgba(255, 255, 255, .4) 77%, transparent 77%,
+    transparent
+  );
+  background-image: linear-gradient(
+    135deg,
+    rgba(255, 255, 255, .4) 27%, transparent 27%,
+    transparent 53%, rgba(255, 255, 255, .4) 53%,
+    rgba(255, 255, 255, .4) 77%, transparent 77%,
+    transparent
+  );
+}
+
+.progress-100plus .progress-bar { background-color: #1ee038; }
+.progress-80plus .progress-bar { background-color: #86e01e; }
+.progress-60plus .progress-bar { background-color: #f2d31b; }
+.progress-40plus .progress-bar { background-color: #f2b01e; }
+.progress-20plus .progress-bar { background-color: #f27011; }
+.progress-0plus .progress-bar { background-color: #f63a0f; }
+
+.gloss .progress-bar {
+  box-shadow:
+    inset -1px 1px 0px rgba(255, 255, 255, .5),
+    inset 0 -4px 12px rgba(255, 255, 255, .7),
+    inset 0 4px 12px rgba(255, 255, 255, .7),
+    inset 0 -12px 0px rgba(0, 0, 0, .05),
+    inset 1px -1px 0px rgba(255, 255, 255, .2);
+}
+
+.candystripe-animate .progress-bar{
+  -webkit-animation: animate-stripes 3s linear infinite;
+  -moz-animation: animate-stripes 3s linear infinite;
+  animation: animate-stripes 3s linear infinite;
+}
+
+@-webkit-keyframes animate-stripes { 0% { background-position: 0 0; } 100% { background-position: 60px 0; } }
+@-moz-keyframes animate-stripes { 0% { background-position: 0 0; } 100% { background-position: 60px 0; } }
+@keyframes animate-stripes { 0% { background-position: 0 0; } 100% { background-position: 60px 0; } }
+
+/* Inlines */
+b, strong { font-weight: bold; }
+
+mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; }
+
+sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
+sup { top: -0.5em; }
+sub { bottom: -0.25em; }
+
+dfn { font-style: italic; }
+
+/* Lists */
+ul, ol { padding-left: 30px; }
+li p:last-child { margin:0 }
+.task-list-item { list-style-type: none; }
+.task-list-item input { float:left; margin-left: -20px; margin-top: 6px; }
+dt { font-weight: bold; font-style: italic;}
+dd { margin: 0 0 0 2em; }
+
+/* Tables */
+table { width: 100%; border-collapse: collapse; overflow-x: auto; overflow-y: hidden; display: block;}
+table tr { background-color: #fefefe; }
+table tr:nth-child(2n) { background-color: #f8f8f8; }
+td, th { border: 1px solid #ddd; padding: 6px 13px; }
+
+/* Codehilite Tables */
+.codehilitetable { border: 0; border-spacing: 0; }
+.linenos, .code, .codehilitetable td { border: 0; padding: 0; }
+td:not(.linenos) .linenodiv { padding: 0 !important; }
+.code { width: 100%; }
+.linenos div pre, .linenodiv pre {
+  border: 0;
+  border-top: 1px solid #CCC;
+  border-left: 1px solid #CCC;
+  border-right: 1px solid #CCC;
+  border-bottom: 1px solid #CCC;
+  -webkit-border-radius: 0;
+  -moz-border-radius: 0;
+  border-radius: 0;
+  -webkit-border-top-left-radius: 3px;
+  -webkit-border-bottom-left-radius: 3px;
+  -moz-border-radius-topleft: 3px;
+  -moz-border-radius-bottomleft: 3px;
+  border-top-left-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+
+.code div pre {
+  border: 0;
+  border-top: 1px solid #CCC;
+  border-right: 1px solid #CCC;
+  border-bottom: 1px solid #CCC;
+  -webkit-border-radius: 0;
+  -moz-border-radius: 0;
+  border-radius: 0;
+  -webkit-border-top-right-radius: 3px;
+  -webkit-border-bottom-right-radius: 3px;
+  -moz-border-radius-topright: 3px;
+  -moz-border-radius-bottomright: 3px;
+  border-top-right-radius: 3px;
+  border-bottom-right-radius: 3px;
+}
+
+/* Media */
+@media only screen and (min-width: 480px) {
+  body{ font-size:14px; }
+}
+
+@media only screen and (min-width: 768px) {
+  body{ font-size:16px; }
+}
+
+@media print {
+  * { background: transparent !important; color: black !important; filter:none !important; -ms-filter: none !important; }
+  body{ font-size:12pt; max-width:100%; outline:none; border: 0;}
+  a, a:visited { text-decoration: underline; }
+  .headeranchor-link { display: none; }
+  hr { height: 1px; border:0; border-bottom:1px solid black; }
+  a[href]:after { content: " (" attr(href) ")"; }
+  abbr[title]:after { content: " (" attr(title) ")"; }
+  .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; }
+  pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; }
+  pre, blockquote { border: 1px solid #999; padding-right: 1em; page-break-inside: avoid; }
+  .progress, .progress-bar { box-shadow: none; }
+  tr, img { page-break-inside: avoid; }
+  img { max-width: 100% !important; }
+  p, h2, h3 { orphans: 3; widows: 3; }
+  h2, h3 { page-break-after: avoid; }
+}
+
+
+    </style>
+    <title>README</title></head>
+<body><h2 id="to-load-run-integration-tests"><a name="user-content-to-load-run-integration-tests"
+                                                href="#to-load-run-integration-tests"
+                                                class="headeranchor-link" aria-hidden="true"><span
+        class="headeranchor"></span></a>TO LOAD &amp; RUN INTEGRATION TESTS</h2>
+<p>See: allwpilib/test-scripts</p></body>
+</html>
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/README.md b/third_party/allwpilib_2018/wpilibjIntegrationTests/README.md
new file mode 100644
index 0000000..5aa567a
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/README.md
@@ -0,0 +1,3 @@
+## TO LOAD & RUN INTEGRATION TESTS
+
+See: allwpilib/test-scripts
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/build.gradle b/third_party/allwpilib_2018/wpilibjIntegrationTests/build.gradle
new file mode 100644
index 0000000..865b801
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/build.gradle
@@ -0,0 +1,39 @@
+plugins {
+    id 'java'
+    id 'application'
+    id 'com.github.johnrengelman.shadow' version '1.2.3'
+}
+
+repositories {
+    mavenCentral()
+}
+
+mainClassName = 'edu.wpi.first.wpilibj.test.AntJunitLanucher'
+
+dependencies {
+    compile project(':wpilibj')
+    compile files(project(':wpilibj').sourceSets.test.output)
+    compile 'edu.wpi.first.wpiutil:wpiutil-java:3.+'
+    compile 'edu.wpi.first.ntcore:ntcore-java:4.+'
+    compile 'org.opencv:opencv-java:3.2.0'
+    compile 'edu.wpi.first.cscore:cscore-java:1.+'
+    compile 'junit:junit:4.11'
+    compile 'com.googlecode.junit-toolbox:junit-toolbox:2.0'
+    compile 'org.apache.ant:ant:1.9.4'
+    compile 'org.apache.ant:ant-junit:1.9.4'
+}
+
+build.dependsOn shadowJar
+
+def testOutputFolder = file("${project(':').buildDir}/integrationTestFiles")
+
+task copyWpilibJIntegrationTestJarToOutput(type: Copy) {
+    destinationDir testOutputFolder
+    dependsOn shadowJar
+    inputs.file shadowJar
+    from (shadowJar) {
+        into 'java'
+    }
+}
+
+build.dependsOn copyWpilibJIntegrationTestJarToOutput
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/runintegrationjavaprogram b/third_party/allwpilib_2018/wpilibjIntegrationTests/runintegrationjavaprogram
new file mode 100644
index 0000000..dc80c8d
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/runintegrationjavaprogram
@@ -0,0 +1,5 @@
+#. ./.profile
+killall java
+killall FRCUserProgram
+sleep 1
+/usr/local/frc/JRE/bin/java -ea -jar wpilibJavaIntegrationTests-0.1.0-SNAPSHOT.jar $@
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/AbstractInterruptTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/AbstractInterruptTest.java
new file mode 100644
index 0000000..a53bd21
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/AbstractInterruptTest.java
@@ -0,0 +1,311 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.After;
+import org.junit.Test;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+
+import static org.hamcrest.Matchers.both;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.lessThan;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
+
+/**
+ * This class should not be run as a test explicitly. Instead it should be extended by tests that
+ * use the InterruptableSensorBase.
+ */
+public abstract class AbstractInterruptTest extends AbstractComsSetup {
+  private InterruptableSensorBase m_interruptable = null;
+
+  private InterruptableSensorBase getInterruptable() {
+    if (m_interruptable == null) {
+      m_interruptable = giveInterruptableSensorBase();
+    }
+    return m_interruptable;
+  }
+
+
+  @After
+  public void interruptTeardown() {
+    if (m_interruptable != null) {
+      freeInterruptableSensorBase();
+      m_interruptable = null;
+    }
+  }
+
+  /**
+   * Give the interruptable sensor base that interrupts can be attached to.
+   */
+  abstract InterruptableSensorBase giveInterruptableSensorBase();
+
+  /**
+   * Cleans up the interruptable sensor base. This is only called if {@link
+   * #giveInterruptableSensorBase()} is called.
+   */
+  abstract void freeInterruptableSensorBase();
+
+  /**
+   * Perform whatever action is required to set the interrupt high.
+   */
+  abstract void setInterruptHigh();
+
+  /**
+   * Perform whatever action is required to set the interrupt low.
+   */
+  abstract void setInterruptLow();
+
+
+  private class InterruptCounter {
+    private final AtomicInteger m_count = new AtomicInteger();
+
+    void increment() {
+      m_count.addAndGet(1);
+    }
+
+    int getCount() {
+      return m_count.get();
+    }
+  }
+
+  private class TestInterruptHandlerFunction extends InterruptHandlerFunction<InterruptCounter> {
+    protected final AtomicBoolean m_exceptionThrown = new AtomicBoolean(false);
+    /**
+     * Stores the time that the interrupt fires.
+     */
+    final AtomicLong m_interruptFireTime = new AtomicLong();
+    /**
+     * Stores if the interrupt has completed at least once.
+     */
+    final AtomicBoolean m_interruptComplete = new AtomicBoolean(false);
+    protected Exception m_ex;
+    final InterruptCounter m_counter;
+
+    TestInterruptHandlerFunction(InterruptCounter counter) {
+      m_counter = counter;
+    }
+
+    @Override
+    public void interruptFired(int interruptAssertedMask, InterruptCounter param) {
+      m_interruptFireTime.set(RobotController.getFPGATime());
+      m_counter.increment();
+      try {
+        // This won't cause the test to fail
+        assertSame(m_counter, param);
+      } catch (Exception ex) {
+        // So we must throw the exception within the test
+        m_exceptionThrown.set(true);
+        m_ex = ex;
+      }
+      m_interruptComplete.set(true);
+    }
+
+    @Override
+    public InterruptCounter overridableParameter() {
+      return m_counter;
+    }
+  }
+
+  @Test(timeout = 1000)
+  public void testSingleInterruptsTriggering() throws Exception {
+    // Given
+    final InterruptCounter counter = new InterruptCounter();
+    TestInterruptHandlerFunction function = new TestInterruptHandlerFunction(counter);
+
+    // When
+    getInterruptable().requestInterrupts(function);
+    getInterruptable().enableInterrupts();
+
+    setInterruptLow();
+    Timer.delay(0.01);
+    // Note: Utility.getFPGATime() is used because double values can turn over
+    // after the robot has been running for a long time
+    final long interruptTriggerTime = RobotController.getFPGATime();
+    setInterruptHigh();
+
+    // Delay until the interrupt is complete
+    while (!function.m_interruptComplete.get()) {
+      Timer.delay(.005);
+    }
+
+
+    // Then
+    assertEquals("The interrupt did not fire the expected number of times", 1, counter.getCount());
+    // If the test within the interrupt failed
+    if (function.m_exceptionThrown.get()) {
+      throw function.m_ex;
+    }
+    final long range = 10000; // in microseconds
+    assertThat(
+        "The interrupt did not fire within the expected time period (values in milliseconds)",
+        function.m_interruptFireTime.get(),
+        both(greaterThan(interruptTriggerTime - range)).and(lessThan(interruptTriggerTime
+            + range)));
+    assertThat(
+        "The readRisingTimestamp() did not return the correct value (values in seconds)",
+        getInterruptable().readRisingTimestamp(),
+        both(greaterThan((interruptTriggerTime - range) / 1e6)).and(
+            lessThan((interruptTriggerTime + range) / 1e6)));
+  }
+
+  @Test(timeout = 2000)
+  public void testMultipleInterruptsTriggering() throws Exception {
+    // Given
+    final InterruptCounter counter = new InterruptCounter();
+    TestInterruptHandlerFunction function = new TestInterruptHandlerFunction(counter);
+
+    // When
+    getInterruptable().requestInterrupts(function);
+    getInterruptable().enableInterrupts();
+
+    final int fireCount = 50;
+    for (int i = 0; i < fireCount; i++) {
+      setInterruptLow();
+      setInterruptHigh();
+      // Wait for the interrupt to complete before moving on
+      while (!function.m_interruptComplete.getAndSet(false)) {
+        Timer.delay(.005);
+      }
+    }
+    // Then
+    assertEquals("The interrupt did not fire the expected number of times", fireCount,
+        counter.getCount());
+  }
+
+  /**
+   * The timeout length for this test in seconds.
+   */
+  private static final int synchronousTimeout = 5;
+
+  @Test(timeout = (long) (synchronousTimeout * 1e3))
+  public void testSynchronousInterruptsTriggering() {
+    // Given
+    getInterruptable().requestInterrupts();
+
+    final double synchronousDelay = synchronousTimeout / 2.;
+    final Runnable runnable = () -> {
+      Timer.delay(synchronousDelay);
+      setInterruptLow();
+      setInterruptHigh();
+    };
+
+    // When
+
+    // Note: the long time value is used because doubles can flip if the robot
+    // is left running for long enough
+    final long startTimeStamp = RobotController.getFPGATime();
+    new Thread(runnable).start();
+    // Delay for twice as long as the timeout so the test should fail first
+    getInterruptable().waitForInterrupt(synchronousTimeout * 2);
+    final long stopTimeStamp = RobotController.getFPGATime();
+
+    // Then
+    // The test will not have timed out and:
+    final double interruptRunTime = (stopTimeStamp - startTimeStamp) * 1e-6;
+    assertEquals("The interrupt did not run for the expected amount of time (units in seconds)",
+        synchronousDelay, interruptRunTime, .1);
+  }
+
+  @Test(timeout = (long) (synchronousTimeout * 1e3))
+  public void testSynchronousInterruptsWaitResultTimeout() {
+    // Given
+    getInterruptable().requestInterrupts();
+
+    //Don't fire interrupt. Expect it to timeout.
+    InterruptableSensorBase.WaitResult result = getInterruptable()
+        .waitForInterrupt(synchronousTimeout / 2);
+
+    assertEquals("The interrupt did not time out correctly.", result, InterruptableSensorBase
+        .WaitResult.kTimeout);
+  }
+
+  @Test(timeout = (long) (synchronousTimeout * 1e3))
+  public void testSynchronousInterruptsWaitResultRisingEdge() {
+    // Given
+    getInterruptable().requestInterrupts();
+
+    final double synchronousDelay = synchronousTimeout / 2.;
+    final Runnable runnable = () -> {
+      Timer.delay(synchronousDelay);
+      setInterruptLow();
+      setInterruptHigh();
+    };
+
+    new Thread(runnable).start();
+    // Delay for twice as long as the timeout so the test should fail first
+    InterruptableSensorBase.WaitResult result = getInterruptable()
+        .waitForInterrupt(synchronousTimeout * 2);
+
+    assertEquals("The interrupt did not fire on the rising edge.", result,
+        InterruptableSensorBase.WaitResult.kRisingEdge);
+  }
+
+  @Test(timeout = (long) (synchronousTimeout * 1e3))
+  public void testSynchronousInterruptsWaitResultFallingEdge() {
+    // Given
+    getInterruptable().requestInterrupts();
+    getInterruptable().setUpSourceEdge(false, true);
+
+    final double synchronousDelay = synchronousTimeout / 2.;
+    final Runnable runnable = () -> {
+      Timer.delay(synchronousDelay);
+      setInterruptHigh();
+      setInterruptLow();
+    };
+
+    new Thread(runnable).start();
+    // Delay for twice as long as the timeout so the test should fail first
+    InterruptableSensorBase.WaitResult result = getInterruptable()
+        .waitForInterrupt(synchronousTimeout * 2);
+
+    assertEquals("The interrupt did not fire on the falling edge.", result,
+        InterruptableSensorBase.WaitResult.kFallingEdge);
+  }
+
+
+  @Test(timeout = 4000)
+  public void testDisableStopsInterruptFiring() {
+    final InterruptCounter counter = new InterruptCounter();
+    TestInterruptHandlerFunction function = new TestInterruptHandlerFunction(counter);
+
+    // When
+    getInterruptable().requestInterrupts(function);
+    getInterruptable().enableInterrupts();
+
+    final int fireCount = 50;
+    for (int i = 0; i < fireCount; i++) {
+      setInterruptLow();
+      setInterruptHigh();
+      // Wait for the interrupt to complete before moving on
+      while (!function.m_interruptComplete.getAndSet(false)) {
+        Timer.delay(.005);
+      }
+    }
+    getInterruptable().disableInterrupts();
+    // TestBench.out().println("Finished disabling the robot");
+
+    for (int i = 0; i < fireCount; i++) {
+      setInterruptLow();
+      setInterruptHigh();
+      // Just wait because the interrupt should not fire
+      Timer.delay(.005);
+    }
+
+    // Then
+    assertEquals("The interrupt did not fire the expected number of times", fireCount,
+        counter.getCount());
+  }
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/AnalogCrossConnectTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/AnalogCrossConnectTest.java
new file mode 100644
index 0000000..6ccff8c
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/AnalogCrossConnectTest.java
@@ -0,0 +1,198 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.AnalogTriggerOutput.AnalogTriggerType;
+import edu.wpi.first.wpilibj.fixtures.AnalogCrossConnectFixture;
+import edu.wpi.first.wpilibj.test.TestBench;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test that covers the {@link AnalogCrossConnectFixture}.
+ */
+public class AnalogCrossConnectTest extends AbstractInterruptTest {
+  private static final Logger logger = Logger.getLogger(AnalogCrossConnectTest.class.getName());
+
+  private static AnalogCrossConnectFixture analogIO;
+
+  static final double kDelayTime = 0.01;
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+
+  @BeforeClass
+  public static void setUpBeforeClass() throws Exception {
+    analogIO = TestBench.getAnalogCrossConnectFixture();
+  }
+
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {
+    analogIO.teardown();
+    analogIO = null;
+  }
+
+  @Before
+  public void setUp() throws Exception {
+    analogIO.setup();
+  }
+
+
+  @Test
+  public void testAnalogOuput() {
+    for (int i = 0; i < 50; i++) {
+      analogIO.getOutput().setVoltage(i / 10.0);
+      Timer.delay(kDelayTime);
+      assertEquals(analogIO.getOutput().getVoltage(), analogIO.getInput().getVoltage(), 0.01);
+    }
+  }
+
+  @Test
+  public void testAnalogTriggerBelowWindow() {
+    // Given
+    AnalogTrigger trigger = new AnalogTrigger(analogIO.getInput());
+    trigger.setLimitsVoltage(2.0, 3.0);
+
+    // When the output voltage is than less the lower limit
+    analogIO.getOutput().setVoltage(1.0);
+    Timer.delay(kDelayTime);
+
+    // Then the analog trigger is not in the window and the trigger state is off
+    assertFalse("Analog trigger is in the window (2V, 3V)", trigger.getInWindow());
+    assertFalse("Analog trigger is on", trigger.getTriggerState());
+
+    trigger.free();
+  }
+
+  @Test
+  public void testAnalogTriggerInWindow() {
+    // Given
+    AnalogTrigger trigger = new AnalogTrigger(analogIO.getInput());
+    trigger.setLimitsVoltage(2.0, 3.0);
+
+    // When the output voltage is within the lower and upper limits
+    analogIO.getOutput().setVoltage(2.5f);
+    Timer.delay(kDelayTime);
+
+    // Then the analog trigger is in the window and the trigger state is off
+    assertTrue("Analog trigger is not in the window (2V, 3V)", trigger.getInWindow());
+    assertFalse("Analog trigger is on", trigger.getTriggerState());
+
+    trigger.free();
+  }
+
+  @Test
+  public void testAnalogTriggerAboveWindow() {
+    // Given
+    AnalogTrigger trigger = new AnalogTrigger(analogIO.getInput());
+    trigger.setLimitsVoltage(2.0, 3.0);
+
+    // When the output voltage is greater than the upper limit
+    analogIO.getOutput().setVoltage(4.0);
+    Timer.delay(kDelayTime);
+
+    // Then the analog trigger is not in the window and the trigger state is on
+    assertFalse("Analog trigger is in the window (2V, 3V)", trigger.getInWindow());
+    assertTrue("Analog trigger is not on", trigger.getTriggerState());
+
+    trigger.free();
+  }
+
+  @Test
+  public void testAnalogTriggerCounter() {
+    // Given
+    AnalogTrigger trigger = new AnalogTrigger(analogIO.getInput());
+    trigger.setLimitsVoltage(2.0, 3.0);
+    Counter counter = new Counter(trigger);
+
+    // When the analog output is turned low and high 50 times
+    for (int i = 0; i < 50; i++) {
+      analogIO.getOutput().setVoltage(1.0);
+      Timer.delay(kDelayTime);
+      analogIO.getOutput().setVoltage(4.0);
+      Timer.delay(kDelayTime);
+    }
+
+    // Then the counter should be at 50
+    assertEquals("Analog trigger counter did not count 50 ticks", 50, counter.get());
+  }
+
+  @Test(expected = RuntimeException.class)
+  public void testRuntimeExceptionOnInvalidAccumulatorPort() {
+    analogIO.getInput().getAccumulatorCount();
+  }
+
+  private AnalogTrigger m_interruptTrigger;
+  private AnalogTriggerOutput m_interruptTriggerOutput;
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see
+   * edu.wpi.first.wpilibj.AbstractInterruptTest#giveInterruptableSensorBase()
+   */
+  @Override
+  InterruptableSensorBase giveInterruptableSensorBase() {
+    m_interruptTrigger = new AnalogTrigger(analogIO.getInput());
+    m_interruptTrigger.setLimitsVoltage(2.0, 3.0);
+    m_interruptTriggerOutput = new AnalogTriggerOutput(m_interruptTrigger,
+        AnalogTriggerType.kState);
+    return m_interruptTriggerOutput;
+  }
+
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see
+   * edu.wpi.first.wpilibj.AbstractInterruptTest#freeInterruptableSensorBase()
+   */
+  @Override
+  void freeInterruptableSensorBase() {
+    m_interruptTriggerOutput.cancelInterrupts();
+    m_interruptTriggerOutput.free();
+    m_interruptTriggerOutput = null;
+    m_interruptTrigger.free();
+    m_interruptTrigger = null;
+  }
+
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.AbstractInterruptTest#setInterruptHigh()
+   */
+  @Override
+  void setInterruptHigh() {
+    analogIO.getOutput().setVoltage(4.0);
+    Timer.delay(kDelayTime);
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.AbstractInterruptTest#setInterruptLow()
+   */
+  @Override
+  void setInterruptLow() {
+    analogIO.getOutput().setVoltage(1.0);
+    Timer.delay(kDelayTime);
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/AnalogPotentiometerTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/AnalogPotentiometerTest.java
new file mode 100644
index 0000000..dce2ac8
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/AnalogPotentiometerTest.java
@@ -0,0 +1,70 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.fixtures.AnalogCrossConnectFixture;
+import edu.wpi.first.wpilibj.mockhardware.FakePotentiometerSource;
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+import edu.wpi.first.wpilibj.test.TestBench;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests the {@link AnalogPotentiometer}.
+ */
+public class AnalogPotentiometerTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(AnalogPotentiometerTest.class.getName());
+  private AnalogCrossConnectFixture m_analogIO;
+  private FakePotentiometerSource m_potSource;
+  private AnalogPotentiometer m_pot;
+
+  private static final double DOUBLE_COMPARISON_DELTA = 2.0;
+
+  @Before
+  public void setUp() throws Exception {
+    m_analogIO = TestBench.getAnalogCrossConnectFixture();
+    m_potSource = new FakePotentiometerSource(m_analogIO.getOutput(), 360);
+    m_pot = new AnalogPotentiometer(m_analogIO.getInput(), 360.0, 0);
+
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    m_potSource.reset();
+    m_pot.free();
+    m_analogIO.teardown();
+  }
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+  @Test
+  public void testInitialSettings() {
+    assertEquals(0, m_pot.get(), DOUBLE_COMPARISON_DELTA);
+  }
+
+  @Test
+  public void testRangeValues() {
+    for (double i = 0.0; i < 360.0; i = i + 1.0) {
+      m_potSource.setAngle(i);
+      m_potSource.setMaxVoltage(ControllerPower.getVoltage5V());
+      Timer.delay(.02);
+      assertEquals(i, m_pot.get(), DOUBLE_COMPARISON_DELTA);
+    }
+  }
+
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/BuiltInAccelerometerTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/BuiltInAccelerometerTest.java
new file mode 100644
index 0000000..8256444
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/BuiltInAccelerometerTest.java
@@ -0,0 +1,69 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2014-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.interfaces.Accelerometer;
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Parameterized.class)
+public class BuiltInAccelerometerTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(BuiltInAccelerometerTest.class.getName());
+  private static final double kAccelerationTolerance = 0.1;
+  private final BuiltInAccelerometer m_accelerometer;
+
+  public BuiltInAccelerometerTest(Accelerometer.Range range) {
+    m_accelerometer = new BuiltInAccelerometer(range);
+  }
+
+  @BeforeClass
+  public static void waitASecond() {
+    /*
+     * The testbench sometimes shakes a little from a previous test. Give it
+     * some time.
+     */
+    Timer.delay(1.0);
+  }
+
+  /**
+   * Test with all valid ranges to make sure unpacking is always done correctly.
+   */
+  @Parameters
+  public static Collection<Accelerometer.Range[]> generateData() {
+    return Arrays.asList(new Accelerometer.Range[][]{{Accelerometer.Range.k2G},
+        {Accelerometer.Range.k4G}, {Accelerometer.Range.k8G}});
+  }
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+  /**
+   * There's not much we can automatically test with the on-board accelerometer, but checking for
+   * gravity is probably good enough to tell that it's working.
+   */
+  @Test
+  public void testAccelerometer() {
+    assertEquals(0.0, m_accelerometer.getX(), kAccelerationTolerance);
+    assertEquals(1.0, m_accelerometer.getY(), kAccelerationTolerance);
+    assertEquals(0.0, m_accelerometer.getZ(), kAccelerationTolerance);
+  }
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/ConstantsPortsTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/ConstantsPortsTest.java
new file mode 100644
index 0000000..c181e8d
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/ConstantsPortsTest.java
@@ -0,0 +1,99 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.Test;
+
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for checking our constant and port values.
+ */
+public class ConstantsPortsTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(ConstantsPortsTest.class.getName());
+
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+  /**
+   * kDigitalChannels.
+   */
+  @Test
+  public void testDigitalChannels() {
+    assertEquals(31, SensorBase.kDigitalChannels);
+  }
+
+  /**
+   * kAnalogInputChannels.
+   */
+  @Test
+  public void testAnalogInputChannels() {
+    assertEquals(8, SensorBase.kAnalogInputChannels);
+  }
+
+  /**
+   * kAnalogOutputChannels.
+   */
+  @Test
+  public void testAnalogOutputChannels() {
+    assertEquals(2, SensorBase.kAnalogOutputChannels);
+  }
+
+  /**
+   * kSolenoidChannels.
+   */
+  @Test
+  public void testSolenoidChannels() {
+    assertEquals(8, SensorBase.kSolenoidChannels);
+  }
+
+  /**
+   * kPwmChannels.
+   */
+  @Test
+  public void testPwmChannels() {
+    assertEquals(20, SensorBase.kPwmChannels);
+  }
+
+  /**
+   * kRelayChannels.
+   */
+  @Test
+  public void testRelayChannels() {
+    assertEquals(4, SensorBase.kRelayChannels);
+  }
+
+  /**
+   * kPDPChannels.
+   */
+  @Test
+  public void testPDPChannels() {
+    assertEquals(16, SensorBase.kPDPChannels);
+  }
+
+  /**
+   * kPDPModules.
+   */
+  @Test
+  public void testPDPModules() {
+    assertEquals(63, SensorBase.kPDPModules);
+  }
+
+  /**
+   * kPCMModules.
+   */
+  @Test
+  public void testPCMModules() {
+    assertEquals(63, SensorBase.kPCMModules);
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/CounterTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/CounterTest.java
new file mode 100644
index 0000000..4ad00d7
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/CounterTest.java
@@ -0,0 +1,115 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Collection;
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.fixtures.FakeCounterFixture;
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+import edu.wpi.first.wpilibj.test.TestBench;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests to see if the Counter is working properly.
+ */
+@RunWith(Parameterized.class)
+public class CounterTest extends AbstractComsSetup {
+  private static FakeCounterFixture counter = null;
+  private static final Logger logger = Logger.getLogger(CounterTest.class.getName());
+
+  Integer m_input;
+  Integer m_output;
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+  /**
+   * Constructs a Counter Test with the given inputs.
+   *
+   * @param input  The input Port
+   * @param output The output Port
+   */
+  public CounterTest(Integer input, Integer output) {
+    assert input != null;
+    assert output != null;
+
+    m_input = input;
+    m_output = output;
+    // System.out.println("Counter Test: Input: " + input + " Output: " +
+    // output);
+    if (counter != null) {
+      counter.teardown();
+    }
+    counter = new FakeCounterFixture(input, output);
+  }
+
+  /**
+   * Test data generator. This method is called the the JUnit parameterized test runner and returns
+   * a Collection of Arrays. For each Array in the Collection, each array element corresponds to a
+   * parameter in the constructor.
+   */
+  @Parameters
+  public static Collection<Integer[]> generateData() {
+    // In this example, the parameter generator returns a List of
+    // arrays. Each array has two elements: { Digital input port, Digital output
+    // port}.
+    // These data are hard-coded into the class, but they could be
+    // generated or loaded in any way you like.
+    return TestBench.getInstance().getDIOCrossConnectCollection();
+  }
+
+
+  @BeforeClass
+  public static void setUpBeforeClass() throws Exception {
+  }
+
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {
+    counter.teardown();
+    counter = null;
+  }
+
+  @Before
+  public void setUp() throws Exception {
+    counter.setup();
+  }
+
+  /**
+   * Tests the default state of the counter immediately after reset.
+   */
+  @Test
+  public void testDefault() {
+    assertEquals("Counter did not reset to 0", 0, counter.getCounter().get());
+  }
+
+  @Test(timeout = 5000)
+  public void testCount() {
+    final int goal = 100;
+    counter.getFakeCounterSource().setCount(goal);
+    counter.getFakeCounterSource().execute();
+
+    final int count = counter.getCounter().get();
+
+    assertTrue("Fake Counter, Input: " + m_input + ", Output: " + m_output + ", did not return "
+        + goal + " instead got: " + count, count == goal);
+  }
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/DIOCrossConnectTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/DIOCrossConnectTest.java
new file mode 100644
index 0000000..ff776a0
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/DIOCrossConnectTest.java
@@ -0,0 +1,196 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Collection;
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.fixtures.DIOCrossConnectFixture;
+import edu.wpi.first.wpilibj.test.TestBench;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests to see if the Digital ports are working properly.
+ */
+@RunWith(Parameterized.class)
+public class DIOCrossConnectTest extends AbstractInterruptTest {
+  private static final Logger logger = Logger.getLogger(DIOCrossConnectTest.class.getName());
+
+  private static DIOCrossConnectFixture dio = null;
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+  /**
+   * Default constructor for the DIOCrossConnectTest This test is parameterized in order to allow it
+   * to be tested using a variety of different input/output pairs without duplicate code.<br> This
+   * class takes Integer port values instead of DigitalClasses because it would force them to be
+   * instantiated at the same time which could (untested) cause port binding errors.
+   *
+   * @param input  The port for the input wire
+   * @param output The port for the output wire
+   */
+  public DIOCrossConnectTest(Integer input, Integer output) {
+    if (dio != null) {
+      dio.teardown();
+    }
+    dio = new DIOCrossConnectFixture(input, output);
+  }
+
+
+  /**
+   * Test data generator. This method is called the the JUnit parameterized test runner and returns
+   * a Collection of Arrays. For each Array in the Collection, each array element corresponds to a
+   * parameter in the constructor.
+   */
+  @Parameters(name = "{index}: Input Port: {0} Output Port: {1}")
+  public static Collection<Integer[]> generateData() {
+    // In this example, the parameter generator returns a List of
+    // arrays. Each array has two elements: { Digital input port, Digital output
+    // port}.
+    // These data are hard-coded into the class, but they could be
+    // generated or loaded in any way you like.
+    return TestBench.getInstance().getDIOCrossConnectCollection();
+  }
+
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {
+    dio.teardown();
+    dio = null;
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dio.reset();
+  }
+
+  /**
+   * Tests to see if the DIO can create and recognize a high value.
+   */
+  @Test
+  public void testSetHigh() {
+    dio.getOutput().set(true);
+    assertTrue("DIO Not High after no delay", dio.getInput().get());
+    Timer.delay(.02);
+    assertTrue("DIO Not High after .05s delay", dio.getInput().get());
+  }
+
+  /**
+   * Tests to see if the DIO can create and recognize a low value.
+   */
+  @Test
+  public void testSetLow() {
+    dio.getOutput().set(false);
+    assertFalse("DIO Not Low after no delay", dio.getInput().get());
+    Timer.delay(.02);
+    assertFalse("DIO Not Low after .05s delay", dio.getInput().get());
+  }
+
+  /**
+   * Tests to see if the DIO PWM functionality works.
+   */
+  @Test
+  public void testDIOpulseWidthModulation() {
+    dio.getOutput().set(false);
+    assertFalse("DIO Not Low after no delay", dio.getInput().get());
+    //Set frequency to 2.0 Hz
+    dio.getOutput().setPWMRate(2.0);
+    //Enable PWM, but leave it off.
+    dio.getOutput().enablePWM(0.0);
+    Timer.delay(0.5);
+    dio.getOutput().updateDutyCycle(0.5);
+    dio.getInput().requestInterrupts();
+    dio.getInput().setUpSourceEdge(false, true);
+    //TODO: Add return value from WaitForInterrupt
+    dio.getInput().waitForInterrupt(3.0, true);
+    Timer.delay(0.5);
+    final boolean firstCycle = dio.getInput().get();
+    Timer.delay(0.5);
+    final boolean secondCycle = dio.getInput().get();
+    Timer.delay(0.5);
+    final boolean thirdCycle = dio.getInput().get();
+    Timer.delay(0.5);
+    final boolean forthCycle = dio.getInput().get();
+    Timer.delay(0.5);
+    final boolean fifthCycle = dio.getInput().get();
+    Timer.delay(0.5);
+    final boolean sixthCycle = dio.getInput().get();
+    Timer.delay(0.5);
+    final boolean seventhCycle = dio.getInput().get();
+    dio.getOutput().disablePWM();
+    Timer.delay(0.5);
+    final boolean firstAfterStop = dio.getInput().get();
+    Timer.delay(0.5);
+    final boolean secondAfterStop = dio.getInput().get();
+
+    assertFalse("DIO Not Low after first delay", firstCycle);
+    assertTrue("DIO Not High after second delay", secondCycle);
+    assertFalse("DIO Not Low after third delay", thirdCycle);
+    assertTrue("DIO Not High after forth delay", forthCycle);
+    assertFalse("DIO Not Low after fifth delay", fifthCycle);
+    assertTrue("DIO Not High after sixth delay", sixthCycle);
+    assertFalse("DIO Not Low after seventh delay", seventhCycle);
+    assertFalse("DIO Not Low after stopping first read", firstAfterStop);
+    assertFalse("DIO Not Low after stopping second read", secondAfterStop);
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see
+   * edu.wpi.first.wpilibj.AbstractInterruptTest#giveInterruptableSensorBase()
+   */
+  @Override
+  InterruptableSensorBase giveInterruptableSensorBase() {
+    return dio.getInput();
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see
+   * edu.wpi.first.wpilibj.AbstractInterruptTest#freeInterruptableSensorBase()
+   */
+  @Override
+  void freeInterruptableSensorBase() {
+    // Handled in the fixture
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.AbstractInterruptTest#setInterruptHigh()
+   */
+  @Override
+  void setInterruptHigh() {
+    dio.getOutput().set(true);
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.AbstractInterruptTest#setInterruptLow()
+   */
+  @Override
+  void setInterruptLow() {
+    dio.getOutput().set(false);
+
+  }
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/DigitalGlitchFilterTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/DigitalGlitchFilterTest.java
new file mode 100644
index 0000000..e3e1569
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/DigitalGlitchFilterTest.java
@@ -0,0 +1,82 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.Test;
+
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test for the DigitalGlitchFilter class.
+ */
+public class DigitalGlitchFilterTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(
+      DigitalGlitchFilterTest.class.getName());
+
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+  /**
+   * This is a test to make sure that filters can be created and are consistent. This assumes that
+   * the FPGA implementation to actually implement the filter has been tested.  It does validate
+   * that we are successfully able to set and get the active filters for ports and makes sure that
+   * the FPGA filter is changed correctly, and does the same for the period.
+   */
+  @Test
+  public void testDigitalGlitchFilterBasic() {
+    final DigitalInput input1 = new DigitalInput(1);
+    final DigitalInput input2 = new DigitalInput(2);
+    final DigitalInput input3 = new DigitalInput(3);
+    final DigitalInput input4 = new DigitalInput(4);
+    final Encoder encoder5 = new Encoder(5, 6);
+    final Counter counter7 = new Counter(7);
+
+    final DigitalGlitchFilter filter1 = new DigitalGlitchFilter();
+    filter1.add(input1);
+    filter1.setPeriodNanoSeconds(4200);
+
+    final DigitalGlitchFilter filter2 = new DigitalGlitchFilter();
+    filter2.add(input2);
+    filter2.add(input3);
+    filter2.setPeriodNanoSeconds(97100);
+
+    final DigitalGlitchFilter filter3 = new DigitalGlitchFilter();
+    filter3.add(input4);
+    filter3.add(encoder5);
+    filter3.add(counter7);
+    filter3.setPeriodNanoSeconds(167800);
+
+    assertEquals(4200, filter1.getPeriodNanoSeconds());
+    assertEquals(97100, filter2.getPeriodNanoSeconds());
+    assertEquals(167800, filter3.getPeriodNanoSeconds());
+
+    filter1.remove(input1);
+
+    filter2.remove(input2);
+    filter2.remove(input3);
+
+    filter3.remove(input4);
+    filter3.remove(encoder5);
+    filter3.remove(counter7);
+
+    input1.free();
+    input2.free();
+    input3.free();
+    input4.free();
+    encoder5.free();
+    counter7.free();
+    filter1.free();
+    filter2.free();
+    filter3.free();
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/DriverStationTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/DriverStationTest.java
new file mode 100644
index 0000000..094b3a3
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/DriverStationTest.java
@@ -0,0 +1,44 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.Test;
+
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+
+import static org.junit.Assert.assertEquals;
+
+
+public class DriverStationTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(TimerTest.class.getName());
+  private static final double TIMER_TOLERANCE = 0.2;
+  private static final long TIMER_RUNTIME = 1000000; // 1 second
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+  @Test
+  public void waitForDataTest() {
+    long startTime = RobotController.getFPGATime();
+
+    // Wait for data 50 times
+    for (int i = 0; i < 50; i++) {
+      DriverStation.getInstance().waitForData();
+    }
+    long endTime = RobotController.getFPGATime();
+    long difference = endTime - startTime;
+
+    assertEquals("DriverStation waitForData did not wait long enough", TIMER_RUNTIME, difference,
+        TIMER_TOLERANCE * TIMER_RUNTIME);
+  }
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/EncoderTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/EncoderTest.java
new file mode 100644
index 0000000..cb78b99
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/EncoderTest.java
@@ -0,0 +1,149 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Collection;
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.fixtures.FakeEncoderFixture;
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+import edu.wpi.first.wpilibj.test.TestBench;
+
+import static org.junit.Assert.assertTrue;
+
+
+/**
+ * Test to see if the FPGA properly recognizes a mock Encoder input.
+ */
+@RunWith(Parameterized.class)
+public class EncoderTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(EncoderTest.class.getName());
+  private static FakeEncoderFixture encoder = null;
+
+  private final boolean m_flip; // Does this test need to flip the inputs
+  private final int m_inputA;
+  private final int m_inputB;
+  private final int m_outputA;
+  private final int m_outputB;
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+  /**
+   * Test data generator. This method is called the the JUnit parametrized test runner and returns
+   * a Collection of Arrays. For each Array in the Collection, each array element corresponds to a
+   * parameter in the constructor.
+   */
+  @Parameters
+  public static Collection<Integer[]> generateData() {
+    return TestBench.getInstance().getEncoderDIOCrossConnectCollection();
+  }
+
+  /**
+   * Constructs a parametrized Encoder Test.
+   *
+   * @param inputA  The port number for inputA
+   * @param outputA The port number for outputA
+   * @param inputB  The port number for inputB
+   * @param outputB The port number for outputB
+   * @param flip    whether or not these set of values require the encoder to be reversed (0 or 1)
+   */
+  public EncoderTest(int inputA, int outputA, int inputB, int outputB, int flip) {
+    m_inputA = inputA;
+    m_inputB = inputB;
+    m_outputA = outputA;
+    m_outputB = outputB;
+
+    // If the encoder from a previous test is allocated then we must free its
+    // members
+    if (encoder != null) {
+      encoder.teardown();
+    }
+    m_flip = flip == 0;
+    encoder = new FakeEncoderFixture(inputA, outputA, inputB, outputB);
+  }
+
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {
+    encoder.teardown();
+    encoder = null;
+  }
+
+  /**
+   * Sets up the test and verifies that the test was reset to the default state.
+   */
+  @Before
+  public void setUp() throws Exception {
+    encoder.setup();
+    testDefaultState();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    encoder.reset();
+  }
+
+  /**
+   * Tests to see if Encoders initialize to zero.
+   */
+  @Test
+  public void testDefaultState() {
+    int value = encoder.getEncoder().get();
+    assertTrue(errorMessage(0, value), value == 0);
+  }
+
+  /**
+   * Tests to see if Encoders can count up successfully.
+   */
+  @Test
+  public void testCountUp() {
+    int goal = 100;
+    encoder.getFakeEncoderSource().setCount(goal);
+    encoder.getFakeEncoderSource().setForward(m_flip);
+    encoder.getFakeEncoderSource().execute();
+    int value = encoder.getEncoder().get();
+    assertTrue(errorMessage(goal, value), value == goal);
+
+  }
+
+  /**
+   * Tests to see if Encoders can count down successfully.
+   */
+  @Test
+  public void testCountDown() {
+    int goal = -100;
+    encoder.getFakeEncoderSource().setCount(goal); // Goal has to be positive
+    encoder.getFakeEncoderSource().setForward(!m_flip);
+    encoder.getFakeEncoderSource().execute();
+    int value = encoder.getEncoder().get();
+    assertTrue(errorMessage(goal, value), value == goal);
+
+  }
+
+  /**
+   * Creates a simple message with the error that was encountered for the Encoders.
+   *
+   * @param goal      The goal that was trying to be reached
+   * @param trueValue The actual value that was reached by the test
+   * @return A fully constructed message with data about where and why the the test failed.
+   */
+  private String errorMessage(int goal, int trueValue) {
+    return "Encoder ({In,Out}): {" + m_inputA + ", " + m_outputA + "},{" + m_inputB + ", "
+        + m_outputB + "} Returned: " + trueValue + ", Wanted: " + goal;
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/FilterNoiseTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/FilterNoiseTest.java
new file mode 100644
index 0000000..14a6bc9
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/FilterNoiseTest.java
@@ -0,0 +1,97 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.fixtures.FilterNoiseFixture;
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+import edu.wpi.first.wpilibj.test.TestBench;
+
+import static org.junit.Assert.assertTrue;
+
+
+@RunWith(Parameterized.class)
+public class FilterNoiseTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(FilterNoiseTest.class.getName());
+
+  private static FilterNoiseFixture<?> me = null;
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+  /**
+   * Constructs the FilterNoiseTest.
+   *
+   * @param mef The fixture under test.
+   */
+  public FilterNoiseTest(FilterNoiseFixture<?> mef) {
+    logger.fine("Constructor with: " + mef.getType());
+    if (me != null && !me.equals(mef)) {
+      me.teardown();
+    }
+    me = mef;
+  }
+
+  @Parameters(name = "{index}: {0}")
+  public static Collection<FilterNoiseFixture<?>[]> generateData() {
+    return Arrays.asList(new FilterNoiseFixture<?>[][]{
+        {TestBench.getInstance().getSinglePoleIIRNoiseFixture()},
+        {TestBench.getInstance().getMovAvgNoiseFixture()}});
+  }
+
+  @Before
+  public void setUp() {
+    me.setup();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    me.reset();
+  }
+
+  @AfterClass
+  public static void tearDownAfterClass() {
+    // Clean up the fixture after the test
+    me.teardown();
+    me = null;
+  }
+
+  /**
+   * Test if the filter reduces the noise produced by a signal generator.
+   */
+  @Test
+  public void testNoiseReduce() {
+    double noiseGenError = 0.0;
+    double filterError = 0.0;
+
+    FilterNoiseFixture.NoiseGenerator noise = me.getNoiseGenerator();
+
+    noise.reset();
+    for (double t = 0; t < TestBench.kFilterTime; t += TestBench.kFilterStep) {
+      final double theoryData = noise.getData(t);
+      filterError += Math.abs(me.getFilter().pidGet() - theoryData);
+      noiseGenError += Math.abs(noise.get() - theoryData);
+    }
+
+    assertTrue(me.getType() + " should have reduced noise accumulation from " + noiseGenError
+        + " but failed. The filter error was " + filterError, noiseGenError > filterError);
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/FilterOutputTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/FilterOutputTest.java
new file mode 100644
index 0000000..30a46f1
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/FilterOutputTest.java
@@ -0,0 +1,96 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2015-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.fixtures.FilterOutputFixture;
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+import edu.wpi.first.wpilibj.test.TestBench;
+
+import static org.junit.Assert.assertEquals;
+
+
+@RunWith(Parameterized.class)
+public class FilterOutputTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(FilterOutputTest.class.getName());
+
+  private double m_expectedOutput;
+
+  private static FilterOutputFixture<?> me = null;
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+  /**
+   * Constructs a filter output test.
+   *
+   * @param mef The fixture under test.
+   */
+  public FilterOutputTest(FilterOutputFixture<?> mef) {
+    logger.fine("Constructor with: " + mef.getType());
+    if (me != null && !me.equals(mef)) {
+      me.teardown();
+    }
+    me = mef;
+    m_expectedOutput = me.getExpectedOutput();
+  }
+
+  @Parameters(name = "{index}: {0}")
+  public static Collection<FilterOutputFixture<?>[]> generateData() {
+    return Arrays.asList(new FilterOutputFixture<?>[][]{
+        {TestBench.getInstance().getSinglePoleIIROutputFixture()},
+        {TestBench.getInstance().getHighPassOutputFixture()},
+        {TestBench.getInstance().getMovAvgOutputFixture()},
+        {TestBench.getInstance().getPulseFixture()}});
+  }
+
+  @Before
+  public void setUp() {
+    me.setup();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    me.reset();
+  }
+
+  @AfterClass
+  public static void tearDownAfterClass() {
+    // Clean up the fixture after the test
+    me.teardown();
+    me = null;
+  }
+
+  /**
+   * Test if the filter produces consistent output for a given data set.
+   */
+  @Test
+  public void testOutput() {
+    me.reset();
+
+    double filterOutput = 0.0;
+    for (double t = 0.0; t < TestBench.kFilterTime; t += TestBench.kFilterStep) {
+      filterOutput = me.getFilter().pidGet();
+    }
+
+    assertEquals(me.getType() + " output was incorrect.", m_expectedOutput, filterOutput, 0.00005);
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/GyroTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/GyroTest.java
new file mode 100644
index 0000000..fad1155
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/GyroTest.java
@@ -0,0 +1,129 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.fixtures.TiltPanCameraFixture;
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+import edu.wpi.first.wpilibj.test.TestBench;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests that the {@link TiltPanCameraFixture}.
+ */
+public class GyroTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(GyroTest.class.getName());
+
+  public static final double TEST_ANGLE = 90.0;
+
+  private TiltPanCameraFixture m_tpcam;
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+  @Before
+  public void setUp() throws Exception {
+    logger.fine("Setup: TiltPan camera");
+    m_tpcam = TestBench.getInstance().getTiltPanCam();
+    m_tpcam.setup();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    m_tpcam.teardown();
+  }
+
+  @Test
+  public void testAllGyroTests() {
+    testInitial(m_tpcam.getGyro());
+    testDeviationOverTime(m_tpcam.getGyro());
+    testGyroAngle(m_tpcam.getGyro());
+    testGyroAngleCalibratedParameters();
+  }
+
+  public void testInitial(AnalogGyro gyro) {
+    double angle = gyro.getAngle();
+    assertEquals(errorMessage(angle, 0), 0, angle, .5);
+  }
+
+  /**
+   * Test to see if the Servo and the gyroscope is turning 90 degrees Note servo on TestBench is not
+   * the same type of servo that servo class was designed for so setAngle is significantly off. This
+   * has been calibrated for the servo on the rig.
+   */
+  public void testGyroAngle(AnalogGyro gyro) {
+    // Set angle
+    for (int i = 0; i < 5; i++) {
+      m_tpcam.getPan().set(0);
+      Timer.delay(.1);
+    }
+
+    Timer.delay(0.5);
+    // Reset for setup
+    gyro.reset();
+    Timer.delay(0.5);
+
+    // Perform test
+    for (int i = 0; i < 53; i++) {
+      m_tpcam.getPan().set(i / 100.0);
+      Timer.delay(0.05);
+    }
+    Timer.delay(1.2);
+
+    double angle = gyro.getAngle();
+
+    double difference = TEST_ANGLE - angle;
+
+    double diff = Math.abs(difference);
+
+    assertEquals(errorMessage(diff, TEST_ANGLE), TEST_ANGLE, angle, 10);
+  }
+
+
+  protected void testDeviationOverTime(AnalogGyro gyro) {
+    // Make sure that the test isn't influenced by any previous motions.
+    Timer.delay(0.5);
+    gyro.reset();
+    Timer.delay(0.25);
+    double angle = gyro.getAngle();
+    assertEquals(errorMessage(angle, 0), 0, angle, .5);
+    Timer.delay(5);
+    angle = gyro.getAngle();
+    assertEquals("After 5 seconds " + errorMessage(angle, 0), 0, angle, 2.0);
+  }
+
+  /**
+   * Gets calibrated parameters from already calibrated gyro, allocates a new gyro with the center
+   * and offset parameters, and re-runs the test.
+   */
+  public void testGyroAngleCalibratedParameters() {
+    // Get calibrated parameters to make new Gyro with parameters
+    final double calibratedOffset = m_tpcam.getGyro().getOffset();
+    final int calibratedCenter = m_tpcam.getGyro().getCenter();
+    m_tpcam.freeGyro();
+    m_tpcam.setupGyroParam(calibratedCenter, calibratedOffset);
+    Timer.delay(TiltPanCameraFixture.RESET_TIME);
+    // Repeat tests
+    testInitial(m_tpcam.getGyroParam());
+    testDeviationOverTime(m_tpcam.getGyroParam());
+    testGyroAngle(m_tpcam.getGyroParam());
+  }
+
+  private String errorMessage(double difference, double target) {
+    return "Gyro angle skewed " + difference + " deg away from target " + target;
+  }
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/MockDS.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/MockDS.java
new file mode 100644
index 0000000..155b5d7
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/MockDS.java
@@ -0,0 +1,85 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetSocketAddress;
+import java.net.SocketException;
+
+public class MockDS {
+  private Thread m_thread;
+
+  private void generateEnabledDsPacket(byte[] data, short sendCount) {
+    data[0] = (byte) (sendCount >> 8);
+    data[1] = (byte) sendCount;
+    data[2] = 0x01; // general data tag
+    data[3] = 0x04; // teleop enabled
+    data[4] = 0x10; // normal data request
+    data[5] = 0x00; // red 1 station
+  }
+
+  @SuppressWarnings("JavadocMethod")
+  public void start() {
+
+    m_thread = new Thread(() -> {
+      DatagramSocket socket;
+      try {
+        socket = new DatagramSocket();
+      } catch (SocketException e1) {
+        // TODO Auto-generated catch block
+        e1.printStackTrace();
+        return;
+      }
+      InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 1110);
+      byte[] sendData = new byte[6];
+      DatagramPacket packet = new DatagramPacket(sendData, 0, 6, addr);
+      short sendCount = 0;
+      int initCount = 0;
+      while (!Thread.currentThread().isInterrupted()) {
+        try {
+          Thread.sleep(20);
+          generateEnabledDsPacket(sendData, sendCount++);
+          // ~50 disabled packets are required to make the robot actually enable
+          // 1 is definitely not enough.
+          if (initCount < 50) {
+            initCount++;
+            sendData[3] = 0;
+          }
+          packet.setData(sendData);
+          socket.send(packet);
+        } catch (InterruptedException ex) {
+          Thread.currentThread().interrupt();
+        } catch (IOException ex) {
+          // TODO Auto-generated catch block
+          ex.printStackTrace();
+        }
+      }
+      socket.close();
+    });
+    // Because of the test setup in Java, this thread will not be stopped
+    // So it must be a daemon thread
+    m_thread.setDaemon(true);
+    m_thread.start();
+  }
+
+  @SuppressWarnings("JavadocMethod")
+  public void stop() {
+    if (m_thread == null) {
+      return;
+    }
+    m_thread.interrupt();
+    try {
+      m_thread.join(1000);
+    } catch (InterruptedException ex) {
+      // TODO Auto-generated catch block
+      ex.printStackTrace();
+    }
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/MotorEncoderTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/MotorEncoderTest.java
new file mode 100644
index 0000000..fa1b586
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/MotorEncoderTest.java
@@ -0,0 +1,236 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.filters.LinearDigitalFilter;
+import edu.wpi.first.wpilibj.fixtures.MotorEncoderFixture;
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+import edu.wpi.first.wpilibj.test.TestBench;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+
+@RunWith(Parameterized.class)
+public class MotorEncoderTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(MotorEncoderTest.class.getName());
+
+  private static final double MOTOR_RUNTIME = .25;
+
+  // private static final List<MotorEncoderFixture> pairs = new
+  // ArrayList<MotorEncoderFixture>();
+  private static MotorEncoderFixture<?> me = null;
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+  /**
+   * Constructs the test.
+   *
+   * @param mef The fixture under test.
+   */
+  public MotorEncoderTest(MotorEncoderFixture<?> mef) {
+    logger.fine("Constructor with: " + mef.getType());
+    if (me != null && !me.equals(mef)) {
+      me.teardown();
+    }
+    me = mef;
+  }
+
+  @Parameters(name = "{index}: {0}")
+  public static Collection<MotorEncoderFixture<?>[]> generateData() {
+    // logger.fine("Loading the MotorList");
+    return Arrays.asList(new MotorEncoderFixture<?>[][]{{TestBench.getInstance().getTalonPair()},
+        {TestBench.getInstance().getVictorPair()}, {TestBench.getInstance().getJaguarPair()}});
+  }
+
+  @Before
+  public void setUp() {
+    double initialSpeed = me.getMotor().get();
+    assertTrue(me.getType() + " Did not start with an initial speed of 0 instead got: "
+        + initialSpeed, Math.abs(initialSpeed) < 0.001);
+    me.setup();
+
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    me.reset();
+    encodersResetCheck(me);
+  }
+
+  @AfterClass
+  public static void tearDownAfterClass() {
+    // Clean up the fixture after the test
+    me.teardown();
+    me = null;
+  }
+
+  /**
+   * Test to ensure that the isMotorWithinRange method is functioning properly. Really only needs to
+   * run on one MotorEncoderFixture to ensure that it is working correctly.
+   */
+  @Test
+  public void testIsMotorWithinRange() {
+    double range = 0.01;
+    assertTrue(me.getType() + " 1", me.isMotorSpeedWithinRange(0.0, range));
+    assertTrue(me.getType() + " 2", me.isMotorSpeedWithinRange(0.0, -range));
+    assertFalse(me.getType() + " 3", me.isMotorSpeedWithinRange(1.0, range));
+    assertFalse(me.getType() + " 4", me.isMotorSpeedWithinRange(-1.0, range));
+  }
+
+  /**
+   * This test is designed to see if the values of different motors will increment when spun
+   * forward.
+   */
+  @Test
+  public void testIncrement() {
+    int startValue = me.getEncoder().get();
+
+    me.getMotor().set(.2);
+    Timer.delay(MOTOR_RUNTIME);
+    int currentValue = me.getEncoder().get();
+    assertTrue(me.getType() + " Encoder not incremented: start: " + startValue + "; current: "
+        + currentValue, startValue < currentValue);
+
+  }
+
+  /**
+   * This test is designed to see if the values of different motors will decrement when spun in
+   * reverse.
+   */
+  @Test
+  public void testDecrement() {
+    int startValue = me.getEncoder().get();
+
+    me.getMotor().set(-.2);
+    Timer.delay(MOTOR_RUNTIME);
+    int currentValue = me.getEncoder().get();
+    assertTrue(me.getType() + " Encoder not decremented: start: " + startValue + "; current: "
+        + currentValue, startValue > currentValue);
+  }
+
+  /**
+   * This method test if the counters count when the motors rotate.
+   */
+  @Test
+  public void testCounter() {
+    final int counter1Start = me.getCounters()[0].get();
+    final int counter2Start = me.getCounters()[1].get();
+
+    me.getMotor().set(.75);
+    Timer.delay(MOTOR_RUNTIME);
+    int counter1End = me.getCounters()[0].get();
+    int counter2End = me.getCounters()[1].get();
+    assertTrue(me.getType() + " Counter not incremented: start: " + counter1Start + "; current: "
+        + counter1End, counter1Start < counter1End);
+    assertTrue(me.getType() + " Counter not incremented: start: " + counter1Start + "; current: "
+        + counter2End, counter2Start < counter2End);
+    me.reset();
+    encodersResetCheck(me);
+  }
+
+  /**
+   * Tests to see if you set the speed to something not {@literal <=} 1.0 if the code appropriately
+   * throttles the value.
+   */
+  @Test
+  public void testSetHighForwardSpeed() {
+    me.getMotor().set(15);
+    assertTrue(me.getType() + " Motor speed was not close to 1.0, was: " + me.getMotor().get(),
+        me.isMotorSpeedWithinRange(1.0, 0.001));
+  }
+
+  /**
+   * Tests to see if you set the speed to something not {@literal >=} -1.0 if the code appropriately
+   * throttles the value.
+   */
+  @Test
+  public void testSetHighReverseSpeed() {
+    me.getMotor().set(-15);
+    assertTrue(me.getType() + " Motor speed was not close to 1.0, was: " + me.getMotor().get(),
+        me.isMotorSpeedWithinRange(-1.0, 0.001));
+  }
+
+
+  @Test
+  public void testPositionPIDController() {
+    me.getEncoder().setPIDSourceType(PIDSourceType.kDisplacement);
+    PIDController pid = new PIDController(0.001, 0.0005, 0, me.getEncoder(), me.getMotor());
+    pid.setAbsoluteTolerance(50.0);
+    pid.setOutputRange(-0.2, 0.2);
+    pid.setSetpoint(1000);
+
+    pid.enable();
+    Timer.delay(10.0);
+    pid.disable();
+
+    assertTrue(
+        "PID loop did not reach setpoint within 10 seconds. The current error was" + pid
+            .getError(), pid.onTarget());
+
+    pid.free();
+  }
+
+  @Test
+  public void testVelocityPIDController() {
+    me.getEncoder().setPIDSourceType(PIDSourceType.kRate);
+    LinearDigitalFilter filter = LinearDigitalFilter.movingAverage(me.getEncoder(), 50);
+    PIDController pid =
+        new PIDController(1e-5, 0.0, 3e-5, 8e-5, filter, me.getMotor());
+    pid.setAbsoluteTolerance(200);
+    pid.setOutputRange(-0.3, 0.3);
+    pid.setSetpoint(600);
+
+    pid.enable();
+    Timer.delay(10.0);
+    pid.disable();
+
+    assertTrue(
+        "PID loop did not reach setpoint within 10 seconds. The error was: " + pid.getError(),
+        pid.onTarget());
+
+    pid.free();
+  }
+
+  /**
+   * Checks to see if the encoders and counters are appropriately reset to zero when reset.
+   *
+   * @param me The MotorEncoderFixture under test
+   */
+  private void encodersResetCheck(MotorEncoderFixture<?> me) {
+    assertEquals(me.getType() + " Encoder value was incorrect after reset.", me.getEncoder().get(),
+        0);
+    assertEquals(me.getType() + " Motor value was incorrect after reset.", me.getMotor().get(), 0,
+        0);
+    assertEquals(me.getType() + " Counter1 value was incorrect after reset.",
+        me.getCounters()[0].get(), 0);
+    assertEquals(me.getType() + " Counter2 value was incorrect after reset.",
+        me.getCounters()[1].get(), 0);
+    Timer.delay(0.5); // so this doesn't fail with the 0.5 second default
+    // timeout on the encoders
+    assertTrue(me.getType() + " Encoder.getStopped() returned false after the motor was reset.", me
+        .getEncoder().getStopped());
+  }
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/MotorInvertingTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/MotorInvertingTest.java
new file mode 100644
index 0000000..13daf64
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/MotorInvertingTest.java
@@ -0,0 +1,134 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.fixtures.MotorEncoderFixture;
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+import edu.wpi.first.wpilibj.test.TestBench;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests Inversion of motors using the SpeedController setInverted.
+ */
+@RunWith(Parameterized.class)
+public class MotorInvertingTest extends AbstractComsSetup {
+  static MotorEncoderFixture<?> fixture = null;
+  private static final double motorspeed = 0.2;
+  private static final double delaytime = 0.3;
+
+
+  /**
+   * Constructs the test.
+   *
+   * @param afixture The fixture under test.
+   */
+  public MotorInvertingTest(MotorEncoderFixture<?> afixture) {
+    logger.fine("Constructor with: " + afixture.getType());
+    if (fixture != null && !fixture.equals(afixture)) {
+      fixture.teardown();
+    }
+    fixture = afixture;
+    fixture.setup();
+  }
+
+  @Parameters(name = "{index}: {0}")
+  public static Collection<MotorEncoderFixture<?>[]> generateData() {
+    // logger.fine("Loading the MotorList");
+    return Arrays.asList(new MotorEncoderFixture<?>[][]{{TestBench.getInstance().getTalonPair()},
+        {TestBench.getInstance().getVictorPair()}, {TestBench.getInstance().getJaguarPair()}});
+  }
+
+  private static final Logger logger = Logger.getLogger(MotorInvertingTest.class.getName());
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+  @Before
+  public void setUp() {
+    // Reset the fixture elements before every test
+    fixture.reset();
+  }
+
+  @AfterClass
+  public static void tearDown() {
+    fixture.getMotor().setInverted(false);
+    // Clean up the fixture after the test
+    fixture.teardown();
+  }
+
+  @Test
+  public void testInvertingPositive() {
+    fixture.getMotor().setInverted(false);
+    fixture.getMotor().set(motorspeed);
+    Timer.delay(delaytime);
+    final boolean initDirection = fixture.getEncoder().getDirection();
+    fixture.getMotor().setInverted(true);
+    fixture.getMotor().set(motorspeed);
+    Timer.delay(delaytime);
+    assertFalse("Inverting with Positive value does not change direction", fixture.getEncoder()
+        .getDirection() == initDirection);
+    fixture.getMotor().set(0);
+  }
+
+  @Test
+  public void testInvertingNegative() {
+    fixture.getMotor().setInverted(false);
+    fixture.getMotor().set(-motorspeed);
+    Timer.delay(delaytime);
+    final boolean initDirection = fixture.getEncoder().getDirection();
+    fixture.getMotor().setInverted(true);
+    fixture.getMotor().set(-motorspeed);
+    Timer.delay(delaytime);
+    assertFalse("Inverting with Negative value does not change direction", fixture.getEncoder()
+        .getDirection() == initDirection);
+    fixture.getMotor().set(0);
+  }
+
+  @Test
+  public void testInvertingSwitchingPosToNeg() {
+    fixture.getMotor().setInverted(false);
+    fixture.getMotor().set(motorspeed);
+    Timer.delay(delaytime);
+    final boolean initDirection = fixture.getEncoder().getDirection();
+    fixture.getMotor().setInverted(true);
+    fixture.getMotor().set(-motorspeed);
+    Timer.delay(delaytime);
+    assertTrue("Inverting with Switching value does change direction", fixture.getEncoder()
+        .getDirection() == initDirection);
+    fixture.getMotor().set(0);
+  }
+
+  @Test
+  public void testInvertingSwitchingNegToPos() {
+    fixture.getMotor().setInverted(false);
+    fixture.getMotor().set(-motorspeed);
+    Timer.delay(delaytime);
+    final boolean initDirection = fixture.getEncoder().getDirection();
+    fixture.getMotor().setInverted(true);
+    fixture.getMotor().set(motorspeed);
+    Timer.delay(delaytime);
+    assertTrue("Inverting with Switching value does change direction", fixture.getEncoder()
+        .getDirection() == initDirection);
+    fixture.getMotor().set(0);
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/PCMTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/PCMTest.java
new file mode 100644
index 0000000..4a0eae0
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/PCMTest.java
@@ -0,0 +1,275 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2014-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test that covers the {@link Compressor}.
+ */
+
+public class PCMTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(PCMTest.class.getName());
+  /*
+   * The PCM switches the compressor up to 2 seconds after the pressure switch
+   * changes.
+   */
+  protected static final double kCompressorDelayTime = 2.0;
+
+  /* Solenoids should change much more quickly */
+  protected static final double kSolenoidDelayTime = 1.0;
+
+  /*
+   * The voltage divider on the test bench should bring the compressor output to
+   * around these values.
+   */
+  protected static final double kCompressorOnVoltage = 5.00;
+  protected static final double kCompressorOffVoltage = 1.68;
+
+  private static Compressor compressor;
+
+  private static DigitalOutput fakePressureSwitch;
+  private static AnalogInput fakeCompressor;
+
+  private static DigitalInput fakeSolenoid1;
+  private static DigitalInput fakeSolenoid2;
+
+  @BeforeClass
+  public static void setUpBeforeClass() throws Exception {
+    compressor = new Compressor();
+
+    fakePressureSwitch = new DigitalOutput(11);
+    fakeCompressor = new AnalogInput(1);
+
+    fakeSolenoid1 = new DigitalInput(12);
+    fakeSolenoid2 = new DigitalInput(13);
+  }
+
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {
+    compressor.free();
+
+    fakePressureSwitch.free();
+    fakeCompressor.free();
+
+    fakeSolenoid1.free();
+    fakeSolenoid2.free();
+  }
+
+  @Before
+  public void reset() throws Exception {
+    compressor.stop();
+    fakePressureSwitch.set(false);
+  }
+
+  /**
+   * Test if the compressor turns on and off when the pressure switch is toggled.
+   */
+  @Test
+  public void testPressureSwitch() throws Exception {
+    final double range = 0.5;
+    reset();
+    compressor.setClosedLoopControl(true);
+
+    // Turn on the compressor
+    fakePressureSwitch.set(true);
+    Timer.delay(kCompressorDelayTime);
+    assertEquals("Compressor did not turn on when the pressure switch turned on.",
+        kCompressorOnVoltage, fakeCompressor.getVoltage(), range);
+
+    // Turn off the compressor
+    fakePressureSwitch.set(false);
+    Timer.delay(kCompressorDelayTime);
+    assertEquals("Compressor did not turn off when the pressure switch turned off.",
+        kCompressorOffVoltage, fakeCompressor.getVoltage(), range);
+  }
+
+  /**
+   * Test if the correct solenoids turn on and off when they should.
+   */
+  @Test
+  public void testSolenoid() throws Exception {
+    reset();
+
+    Solenoid solenoid1 = new Solenoid(0);
+    Solenoid solenoid2 = new Solenoid(1);
+
+    solenoid1.set(false);
+    solenoid2.set(false);
+    Timer.delay(kSolenoidDelayTime);
+    assertTrue("Solenoid #1 did not turn off", fakeSolenoid1.get());
+    assertTrue("Solenoid #2 did not turn off", fakeSolenoid2.get());
+    assertFalse("Solenoid #1 did not report off", solenoid1.get());
+    assertFalse("Solenoid #2 did not report off", solenoid2.get());
+
+    // Turn Solenoid #1 on, and turn Solenoid #2 off
+    solenoid1.set(true);
+    solenoid2.set(false);
+    Timer.delay(kSolenoidDelayTime);
+    assertFalse("Solenoid #1 did not turn on", fakeSolenoid1.get());
+    assertTrue("Solenoid #2 did not turn off", fakeSolenoid2.get());
+    assertTrue("Solenoid #1 did not report on", solenoid1.get());
+    assertFalse("Solenoid #2 did not report off", solenoid2.get());
+
+    // Turn Solenoid #1 off, and turn Solenoid #2 on
+    solenoid1.set(false);
+    solenoid2.set(true);
+    Timer.delay(kSolenoidDelayTime);
+    assertTrue("Solenoid #1 did not turn off", fakeSolenoid1.get());
+    assertFalse("Solenoid #2 did not turn on", fakeSolenoid2.get());
+    assertFalse("Solenoid #1 did not report off", solenoid1.get());
+    assertTrue("Solenoid #2 did not report on", solenoid2.get());
+
+    // Turn both Solenoids on
+    solenoid1.set(true);
+    solenoid2.set(true);
+    Timer.delay(kSolenoidDelayTime);
+    assertFalse("Solenoid #1 did not turn on", fakeSolenoid1.get());
+    assertFalse("Solenoid #2 did not turn on", fakeSolenoid2.get());
+    assertTrue("Solenoid #1 did not report on", solenoid1.get());
+    assertTrue("Solenoid #2 did not report on", solenoid2.get());
+
+    solenoid1.free();
+    solenoid2.free();
+  }
+
+  /**
+   * Test if the correct solenoids turn on and off when they should when used with the
+   * DoubleSolenoid class.
+   */
+  @Test
+  public void doubleSolenoid() {
+    DoubleSolenoid solenoid = new DoubleSolenoid(0, 1);
+
+    solenoid.set(DoubleSolenoid.Value.kOff);
+    Timer.delay(kSolenoidDelayTime);
+    assertTrue("Solenoid #1 did not turn off", fakeSolenoid1.get());
+    assertTrue("Solenoid #2 did not turn off", fakeSolenoid2.get());
+    assertTrue("DoubleSolenoid did not report off", solenoid.get() == DoubleSolenoid.Value.kOff);
+
+    solenoid.set(DoubleSolenoid.Value.kForward);
+    Timer.delay(kSolenoidDelayTime);
+    assertFalse("Solenoid #1 did not turn on", fakeSolenoid1.get());
+    assertTrue("Solenoid #2 did not turn off", fakeSolenoid2.get());
+    assertTrue("DoubleSolenoid did not report Forward", solenoid.get() == DoubleSolenoid.Value
+        .kForward);
+
+    solenoid.set(DoubleSolenoid.Value.kReverse);
+    Timer.delay(kSolenoidDelayTime);
+    assertTrue("Solenoid #1 did not turn off", fakeSolenoid1.get());
+    assertFalse("Solenoid #2 did not turn on", fakeSolenoid2.get());
+    assertTrue("DoubleSolenoid did not report Reverse", solenoid.get() == DoubleSolenoid.Value
+        .kReverse);
+
+    solenoid.free();
+  }
+
+  /**
+   * Test if the correct solenoids turn on and off when they should.
+   */
+  @Test
+  public void testOneShot() throws Exception {
+    reset();
+
+    Solenoid solenoid1 = new Solenoid(0);
+    Solenoid solenoid2 = new Solenoid(1);
+
+    solenoid1.set(false);
+    solenoid2.set(false);
+    Timer.delay(kSolenoidDelayTime);
+    assertTrue("Solenoid #1 did not turn off", fakeSolenoid1.get());
+    assertTrue("Solenoid #2 did not turn off", fakeSolenoid2.get());
+    assertFalse("Solenoid #1 did not report off", solenoid1.get());
+    assertFalse("Solenoid #2 did not report off", solenoid2.get());
+
+    // Pulse Solenoid #1 on, and turn Solenoid #2 off
+    solenoid1.setPulseDuration(2 * kSolenoidDelayTime);
+    solenoid1.startPulse();
+    solenoid2.set(false);
+    Timer.delay(kSolenoidDelayTime);
+    assertFalse("Solenoid #1 did not turn on", fakeSolenoid1.get());
+    assertTrue("Solenoid #2 did not turn off", fakeSolenoid2.get());
+    assertTrue("Solenoid #1 did not report on", solenoid1.get());
+    assertFalse("Solenoid #2 did not report off", solenoid2.get());
+    Timer.delay(2 * kSolenoidDelayTime);
+    assertTrue("Solenoid #1 did not turn off", fakeSolenoid1.get());
+    assertTrue("Solenoid #2 did not turn off", fakeSolenoid2.get());
+    assertFalse("Solenoid #1 did not report off", solenoid1.get());
+    assertFalse("Solenoid #2 did not report off", solenoid2.get());
+
+    // Turn Solenoid #1 off, and pulse Solenoid #2 on
+    solenoid1.set(false);
+    solenoid2.setPulseDuration(2 * kSolenoidDelayTime);
+    solenoid2.startPulse();
+    Timer.delay(kSolenoidDelayTime);
+    assertTrue("Solenoid #1 did not turn off", fakeSolenoid1.get());
+    assertFalse("Solenoid #2 did not turn on", fakeSolenoid2.get());
+    assertFalse("Solenoid #1 did not report off", solenoid1.get());
+    assertTrue("Solenoid #2 did not report on", solenoid2.get());
+    Timer.delay(2 * kSolenoidDelayTime);
+    assertTrue("Solenoid #1 did not turn off", fakeSolenoid1.get());
+    assertTrue("Solenoid #2 did not turn off", fakeSolenoid2.get());
+    assertFalse("Solenoid #1 did not report off", solenoid1.get());
+    assertFalse("Solenoid #2 did not report off", solenoid2.get());
+
+    // Pulse both Solenoids on
+    solenoid1.setPulseDuration(2 * kSolenoidDelayTime);
+    solenoid2.setPulseDuration(2 * kSolenoidDelayTime);
+    solenoid1.startPulse();
+    solenoid2.startPulse();
+    Timer.delay(kSolenoidDelayTime);
+    assertFalse("Solenoid #1 did not turn on", fakeSolenoid1.get());
+    assertFalse("Solenoid #2 did not turn on", fakeSolenoid2.get());
+    assertTrue("Solenoid #1 did not report on", solenoid1.get());
+    assertTrue("Solenoid #2 did not report on", solenoid2.get());
+    Timer.delay(2 * kSolenoidDelayTime);
+    assertTrue("Solenoid #1 did not turn off", fakeSolenoid1.get());
+    assertTrue("Solenoid #2 did not turn off", fakeSolenoid2.get());
+    assertFalse("Solenoid #1 did not report off", solenoid1.get());
+    assertFalse("Solenoid #2 did not report off", solenoid2.get());
+
+    // Pulse both Solenoids on with different durations
+    solenoid1.setPulseDuration(1.5 * kSolenoidDelayTime);
+    solenoid2.setPulseDuration(2.5 * kSolenoidDelayTime);
+    solenoid1.startPulse();
+    solenoid2.startPulse();
+    Timer.delay(kSolenoidDelayTime);
+    assertFalse("Solenoid #1 did not turn on", fakeSolenoid1.get());
+    assertFalse("Solenoid #2 did not turn on", fakeSolenoid2.get());
+    assertTrue("Solenoid #1 did not report on", solenoid1.get());
+    assertTrue("Solenoid #2 did not report on", solenoid2.get());
+    Timer.delay(kSolenoidDelayTime);
+    assertTrue("Solenoid #1 did not turn off", fakeSolenoid1.get());
+    assertFalse("Solenoid #2 did not turn on", fakeSolenoid2.get());
+    assertFalse("Solenoid #1 did not report off", solenoid1.get());
+    assertTrue("Solenoid #2 did not report on", solenoid2.get());
+    Timer.delay(kSolenoidDelayTime);
+    assertTrue("Solenoid #1 did not turn off", fakeSolenoid1.get());
+    assertTrue("Solenoid #2 did not turn off", fakeSolenoid2.get());
+    assertFalse("Solenoid #1 did not report off", solenoid1.get());
+    assertFalse("Solenoid #2 did not report off", solenoid2.get());
+
+    solenoid1.free();
+    solenoid2.free();
+  }
+
+  protected Logger getClassLogger() {
+    return logger;
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/PDPTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/PDPTest.java
new file mode 100644
index 0000000..d7acb94
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/PDPTest.java
@@ -0,0 +1,113 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.can.CANMessageNotFoundException;
+import edu.wpi.first.wpilibj.fixtures.MotorEncoderFixture;
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+import edu.wpi.first.wpilibj.test.TestBench;
+
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test that covers the {@link PowerDistributionPanel}.
+ */
+@RunWith(Parameterized.class)
+public class PDPTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(PCMTest.class.getName());
+
+  private static PowerDistributionPanel pdp;
+  private static MotorEncoderFixture<?> me;
+  private final double m_expectedStoppedCurrentDraw;
+
+  @BeforeClass
+  public static void setUpBeforeClass() throws Exception {
+    pdp = new PowerDistributionPanel();
+  }
+
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {
+    pdp.free();
+    pdp = null;
+    me.teardown();
+    me = null;
+  }
+
+
+  @SuppressWarnings("JavadocMethod")
+  public PDPTest(MotorEncoderFixture<?> mef, Double expectedCurrentDraw) {
+    logger.fine("Constructor with: " + mef.getType());
+    if (me != null && !me.equals(mef)) {
+      me.teardown();
+    }
+    me = mef;
+    me.setup();
+
+    m_expectedStoppedCurrentDraw = expectedCurrentDraw;
+  }
+
+  @Parameters(name = "{index}: {0}, Expected Stopped Current Draw: {1}")
+  public static Collection<Object[]> generateData() {
+    // logger.fine("Loading the MotorList");
+    return Arrays.asList(new Object[][]{
+        {TestBench.getInstance().getTalonPair(), new Double(0.0)}});
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    me.reset();
+  }
+
+
+  /**
+   * Test if the current changes when the motor is driven using a talon.
+   */
+  @Test
+  public void checkStoppedCurrentForSpeedController() throws CANMessageNotFoundException {
+    Timer.delay(0.25);
+
+    /* The Current should be 0 */
+    assertEquals("The low current was not within the expected range.", m_expectedStoppedCurrentDraw,
+        pdp.getCurrent(me.getPDPChannel()), 0.001);
+  }
+
+  /**
+   * Test if the current changes when the motor is driven using a talon.
+   */
+  @Test
+  public void checkRunningCurrentForSpeedController() throws CANMessageNotFoundException {
+
+    /* Set the motor to full forward */
+    me.getMotor().set(1.0);
+    Timer.delay(2);
+
+    /* The current should now be greater than the low current */
+    assertThat("The driven current is not greater than the resting current.",
+        pdp.getCurrent(me.getPDPChannel()), is(greaterThan(m_expectedStoppedCurrentDraw)));
+  }
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/PIDTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/PIDTest.java
new file mode 100644
index 0000000..f9120b4
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/PIDTest.java
@@ -0,0 +1,206 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.logging.Logger;
+
+import edu.wpi.first.networktables.NetworkTable;
+import edu.wpi.first.networktables.NetworkTableInstance;
+import edu.wpi.first.wpilibj.fixtures.MotorEncoderFixture;
+import edu.wpi.first.wpilibj.smartdashboard.SendableBuilderImpl;
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+import edu.wpi.first.wpilibj.test.TestBench;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+
+/**
+ * Test that covers the {@link PIDController}.
+ */
+
+@RunWith(Parameterized.class)
+public class PIDTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(PIDTest.class.getName());
+  private NetworkTable m_table;
+  private SendableBuilderImpl m_builder;
+
+  private static final double absoluteTolerance = 50;
+  private static final double outputRange = 0.25;
+
+  private PIDController m_controller = null;
+  private static MotorEncoderFixture me = null;
+
+  @SuppressWarnings({"MemberName", "EmptyLineSeparator", "MultipleVariableDeclarations"})
+  private final Double k_p, k_i, k_d;
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+
+  @SuppressWarnings({"ParameterName", "JavadocMethod"})
+  public PIDTest(Double p, Double i, Double d, MotorEncoderFixture mef) {
+    logger.fine("Constructor with: " + mef.getType());
+    if (PIDTest.me != null && !PIDTest.me.equals(mef)) {
+      PIDTest.me.teardown();
+    }
+    PIDTest.me = mef;
+    this.k_p = p;
+    this.k_i = i;
+    this.k_d = d;
+  }
+
+
+  @Parameters
+  public static Collection<Object[]> generateData() {
+    // logger.fine("Loading the MotorList");
+    Collection<Object[]> data = new ArrayList<Object[]>();
+    double kp = 0.001;
+    double ki = 0.0005;
+    double kd = 0.0;
+    for (int i = 0; i < 1; i++) {
+      data.addAll(Arrays.asList(new Object[][]{
+          {kp, ki, kd, TestBench.getInstance().getTalonPair()},
+          {kp, ki, kd, TestBench.getInstance().getVictorPair()},
+          {kp, ki, kd, TestBench.getInstance().getJaguarPair()}}));
+    }
+    return data;
+  }
+
+  @BeforeClass
+  public static void setUpBeforeClass() throws Exception {
+  }
+
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {
+    logger.fine("TearDownAfterClass: " + me.getType());
+    me.teardown();
+    me = null;
+  }
+
+  @Before
+  public void setUp() throws Exception {
+    logger.fine("Setup: " + me.getType());
+    me.setup();
+    m_table = NetworkTableInstance.getDefault().getTable("TEST_PID");
+    m_builder = new SendableBuilderImpl();
+    m_builder.setTable(m_table);
+    m_controller = new PIDController(k_p, k_i, k_d, me.getEncoder(), me.getMotor());
+    m_controller.initSendable(m_builder);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    logger.fine("Teardown: " + me.getType());
+    m_controller.disable();
+    m_controller.free();
+    m_controller = null;
+    me.reset();
+  }
+
+  private void setupAbsoluteTolerance() {
+    m_controller.setAbsoluteTolerance(absoluteTolerance);
+  }
+
+  private void setupOutputRange() {
+    m_controller.setOutputRange(-outputRange, outputRange);
+  }
+
+  @Test
+  public void testInitialSettings() {
+    setupAbsoluteTolerance();
+    setupOutputRange();
+    double setpoint = 2500.0;
+    m_controller.setSetpoint(setpoint);
+    assertFalse("PID did not begin disabled", m_controller.isEnabled());
+    assertEquals("PID.getError() did not start at " + setpoint, setpoint,
+        m_controller.getError(), 0);
+    m_builder.updateTable();
+    assertEquals(k_p, m_table.getEntry("p").getDouble(9999999), 0);
+    assertEquals(k_i, m_table.getEntry("i").getDouble(9999999), 0);
+    assertEquals(k_d, m_table.getEntry("d").getDouble(9999999), 0);
+    assertEquals(setpoint, m_table.getEntry("setpoint").getDouble(9999999), 0);
+    assertFalse(m_table.getEntry("enabled").getBoolean(true));
+  }
+
+  @Test
+  public void testRestartAfterEnable() {
+    setupAbsoluteTolerance();
+    setupOutputRange();
+    double setpoint = 2500.0;
+    m_controller.setSetpoint(setpoint);
+    m_controller.enable();
+    m_builder.updateTable();
+    assertTrue(m_table.getEntry("enabled").getBoolean(false));
+    assertTrue(m_controller.isEnabled());
+    assertThat(0.0, is(not(me.getMotor().get())));
+    m_controller.reset();
+    m_builder.updateTable();
+    assertFalse(m_table.getEntry("enabled").getBoolean(true));
+    assertFalse(m_controller.isEnabled());
+    assertEquals(0, me.getMotor().get(), 0);
+  }
+
+  @Test
+  public void testSetSetpoint() {
+    setupAbsoluteTolerance();
+    setupOutputRange();
+    Double setpoint = 2500.0;
+    m_controller.disable();
+    m_controller.setSetpoint(setpoint);
+    m_controller.enable();
+    assertEquals("Did not correctly set set-point", setpoint, new Double(m_controller
+        .getSetpoint()));
+  }
+
+  @Test(timeout = 10000)
+  public void testRotateToTarget() {
+    setupAbsoluteTolerance();
+    setupOutputRange();
+    double setpoint = 1000.0;
+    assertEquals(pidData() + "did not start at 0", 0, m_controller.get(), 0);
+    m_controller.setSetpoint(setpoint);
+    assertEquals(pidData() + "did not have an error of " + setpoint, setpoint,
+        m_controller.getError(), 0);
+    m_controller.enable();
+    Timer.delay(5);
+    m_controller.disable();
+    assertTrue(pidData() + "Was not on Target. Controller Error: " + m_controller.getError(),
+        m_controller.onTarget());
+  }
+
+  private String pidData() {
+    return me.getType() + " PID {P:" + m_controller.getP() + " I:" + m_controller.getI() + " D:"
+        + m_controller.getD() + "} ";
+  }
+
+
+  @Test(expected = RuntimeException.class)
+  public void testOnTargetNoToleranceSet() {
+    setupOutputRange();
+    m_controller.onTarget();
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/PreferencesTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/PreferencesTest.java
new file mode 100644
index 0000000..c63f4b3
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/PreferencesTest.java
@@ -0,0 +1,124 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.networktables.NetworkTable;
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests the {@link Preferences}.
+ */
+public class PreferencesTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(PreferencesTest.class.getName());
+
+  private NetworkTable m_prefTable;
+  private Preferences m_pref;
+  private long m_check;
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+
+  @Before
+  public void setUp() throws Exception {
+    NetworkTable.shutdown();
+    try {
+      File file = new File("networktables.ini");
+      file.mkdirs();
+      if (file.exists()) {
+        file.delete();
+      }
+      file.createNewFile();
+      OutputStream output = new FileOutputStream(file);
+      output
+          .write(("[NetworkTables Storage 3.0]\ndouble \"/Preferences/checkedValueInt\"=2\ndouble "
+              + "\"/Preferences/checkedValueDouble\"=.2\ndouble "
+              + "\"/Preferences/checkedValueFloat\"=3.14\ndouble "
+              + "\"/Preferences/checkedValueLong\"=172\nstring "
+              + "\"/Preferences/checkedValueString\"=\"hello \\nHow are you ?\"\nboolean "
+              + "\"/Preferences/checkedValueBoolean\"=false\n")
+              .getBytes());
+
+    } catch (IOException ex) {
+      ex.printStackTrace();
+    }
+    NetworkTable.initialize();
+
+    m_pref = Preferences.getInstance();
+    m_prefTable = NetworkTable.getTable("Preferences");
+    m_check = System.currentTimeMillis();
+  }
+
+
+  protected void remove() {
+    m_pref.remove("checkedValueLong");
+    m_pref.remove("checkedValueDouble");
+    m_pref.remove("checkedValueString");
+    m_pref.remove("checkedValueInt");
+    m_pref.remove("checkedValueFloat");
+    m_pref.remove("checkedValueBoolean");
+  }
+
+  protected void addCheckedValue() {
+    m_pref.putLong("checkedValueLong", m_check);
+    m_pref.putDouble("checkedValueDouble", 1);
+    m_pref.putString("checkedValueString", "checked");
+    m_pref.putInt("checkedValueInt", 1);
+    m_pref.putFloat("checkedValueFloat", 1);
+    m_pref.putBoolean("checkedValueBoolean", true);
+  }
+
+  @Test
+  public void testAddRemoveSave() {
+    assertEquals(m_pref.getLong("checkedValueLong", 0), 172L);
+    assertEquals(m_pref.getDouble("checkedValueDouble", 0), .2, 0);
+    assertEquals(m_pref.getString("checkedValueString", ""), "hello \nHow are you ?");
+    assertEquals(m_pref.getInt("checkedValueInt", 0), 2);
+    assertEquals(m_pref.getFloat("checkedValueFloat", 0), 3.14, .001);
+    assertFalse(m_pref.getBoolean("checkedValueBoolean", true));
+    remove();
+    assertEquals(m_pref.getLong("checkedValueLong", 0), 0);
+    assertEquals(m_pref.getDouble("checkedValueDouble", 0), 0, 0);
+    assertEquals(m_pref.getString("checkedValueString", ""), "");
+    assertEquals(m_pref.getInt("checkedValueInt", 0), 0);
+    assertEquals(m_pref.getFloat("checkedValueFloat", 0), 0, 0);
+    assertFalse(m_pref.getBoolean("checkedValueBoolean", false));
+    addCheckedValue();
+    assertEquals(m_check, m_pref.getLong("checkedValueLong", 0));
+    assertEquals(m_pref.getDouble("checkedValueDouble", 0), 1, 0);
+    assertEquals(m_pref.getString("checkedValueString", ""), "checked");
+    assertEquals(m_pref.getInt("checkedValueInt", 0), 1);
+    assertEquals(m_pref.getFloat("checkedValueFloat", 0), 1, 0);
+    assertTrue(m_pref.getBoolean("checkedValueBoolean", false));
+  }
+
+  @Test
+  public void testPreferencesToNetworkTables() {
+    String networkedNumber = "networkCheckedValue";
+    int networkNumberValue = 100;
+    m_pref.putInt(networkedNumber, networkNumberValue);
+    assertEquals(networkNumberValue, (int) (m_prefTable.getNumber(networkedNumber, 9999999)));
+    m_pref.remove(networkedNumber);
+  }
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/RelayCrossConnectTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/RelayCrossConnectTest.java
new file mode 100644
index 0000000..0cec277
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/RelayCrossConnectTest.java
@@ -0,0 +1,150 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.logging.Logger;
+
+import edu.wpi.first.networktables.NetworkTable;
+import edu.wpi.first.networktables.NetworkTableInstance;
+import edu.wpi.first.wpilibj.Relay.Direction;
+import edu.wpi.first.wpilibj.Relay.InvalidValueException;
+import edu.wpi.first.wpilibj.Relay.Value;
+import edu.wpi.first.wpilibj.fixtures.RelayCrossConnectFixture;
+import edu.wpi.first.wpilibj.smartdashboard.SendableBuilderImpl;
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+import edu.wpi.first.wpilibj.test.TestBench;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests the {@link RelayCrossConnectFixture}.
+ */
+public class RelayCrossConnectTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(RelayCrossConnectTest.class.getName());
+  private static final NetworkTable table =
+      NetworkTableInstance.getDefault().getTable("_RELAY_CROSS_CONNECT_TEST_");
+  private RelayCrossConnectFixture m_relayFixture;
+  private SendableBuilderImpl m_builder;
+
+
+  @Before
+  public void setUp() throws Exception {
+    m_relayFixture = TestBench.getRelayCrossConnectFixture();
+    m_relayFixture.setup();
+    m_builder = new SendableBuilderImpl();
+    m_builder.setTable(table);
+    m_relayFixture.getRelay().initSendable(m_builder);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    m_relayFixture.reset();
+    m_relayFixture.teardown();
+  }
+
+  @Test
+  public void testBothHigh() {
+    m_relayFixture.getRelay().setDirection(Direction.kBoth);
+    m_relayFixture.getRelay().set(Value.kOn);
+    m_builder.updateTable();
+    assertTrue("Input one was not high when relay set both high", m_relayFixture.getInputOne()
+        .get());
+    assertTrue("Input two was not high when relay set both high", m_relayFixture.getInputTwo()
+        .get());
+    assertEquals(Value.kOn, m_relayFixture.getRelay().get());
+    assertEquals("On", table.getEntry("Value").getString(""));
+  }
+
+  @Test
+  public void testFirstHigh() {
+    m_relayFixture.getRelay().setDirection(Direction.kBoth);
+    m_relayFixture.getRelay().set(Value.kForward);
+    m_builder.updateTable();
+    assertFalse("Input one was not low when relay set Value.kForward", m_relayFixture.getInputOne()
+        .get());
+    assertTrue("Input two was not high when relay set Value.kForward", m_relayFixture
+        .getInputTwo()
+        .get());
+    assertEquals(Value.kForward, m_relayFixture.getRelay().get());
+    assertEquals("Forward", table.getEntry("Value").getString(""));
+  }
+
+  @Test
+  public void testSecondHigh() {
+    m_relayFixture.getRelay().setDirection(Direction.kBoth);
+    m_relayFixture.getRelay().set(Value.kReverse);
+    m_builder.updateTable();
+    assertTrue("Input one was not high when relay set Value.kReverse", m_relayFixture.getInputOne()
+        .get());
+    assertFalse("Input two was not low when relay set Value.kReverse", m_relayFixture
+        .getInputTwo()
+        .get());
+    assertEquals(Value.kReverse, m_relayFixture.getRelay().get());
+    assertEquals("Reverse", table.getEntry("Value").getString(""));
+  }
+
+  @Test
+  public void testForwardDirection() {
+    m_relayFixture.getRelay().setDirection(Direction.kForward);
+    m_relayFixture.getRelay().set(Value.kOn);
+    m_builder.updateTable();
+    assertFalse("Input one was not low when relay set Value.kOn in kForward Direction",
+        m_relayFixture.getInputOne().get());
+    assertTrue("Input two was not high when relay set Value.kOn in kForward Direction",
+        m_relayFixture.getInputTwo().get());
+    assertEquals(Value.kOn, m_relayFixture.getRelay().get());
+    assertEquals("On", table.getEntry("Value").getString(""));
+  }
+
+  @Test
+  public void testReverseDirection() {
+    m_relayFixture.getRelay().setDirection(Direction.kReverse);
+    m_relayFixture.getRelay().set(Value.kOn);
+    m_builder.updateTable();
+    assertTrue("Input one was not high when relay set Value.kOn in kReverse Direction",
+        m_relayFixture.getInputOne().get());
+    assertFalse("Input two was not low when relay set Value.kOn in kReverse Direction",
+        m_relayFixture.getInputTwo().get());
+    assertEquals(Value.kOn, m_relayFixture.getRelay().get());
+    assertEquals("On", table.getEntry("Value").getString(""));
+  }
+
+  @Test(expected = InvalidValueException.class)
+  public void testSetValueForwardWithDirectionReverseThrowingException() {
+    m_relayFixture.getRelay().setDirection(Direction.kForward);
+    m_relayFixture.getRelay().set(Value.kReverse);
+  }
+
+  @Test(expected = InvalidValueException.class)
+  public void testSetValueReverseWithDirectionForwardThrowingException() {
+    m_relayFixture.getRelay().setDirection(Direction.kReverse);
+    m_relayFixture.getRelay().set(Value.kForward);
+  }
+
+  @Test
+  public void testInitialSettings() {
+    m_builder.updateTable();
+    assertEquals(Value.kOff, m_relayFixture.getRelay().get());
+    // Initially both outputs should be off
+    assertFalse(m_relayFixture.getInputOne().get());
+    assertFalse(m_relayFixture.getInputTwo().get());
+    assertEquals("Off", table.getEntry("Value").getString(""));
+  }
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/RobotDriveTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/RobotDriveTest.java
new file mode 100644
index 0000000..e0715d5
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/RobotDriveTest.java
@@ -0,0 +1,183 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import edu.wpi.first.wpilibj.drive.DifferentialDrive;
+import edu.wpi.first.wpilibj.drive.MecanumDrive;
+
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+
+import java.util.logging.Logger;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests the eqivilance of RobotDrive and DifferentialDrive/MecanumDrive.
+ */
+public class RobotDriveTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(RobotDriveTest.class.getName());
+
+  private static MockSpeedController m_rdFrontLeft = new MockSpeedController();
+  private static MockSpeedController m_rdRearLeft = new MockSpeedController();
+  private static MockSpeedController m_rdFrontRight = new MockSpeedController();
+  private static MockSpeedController m_rdRearRight = new MockSpeedController();
+  private static MockSpeedController m_frontLeft = new MockSpeedController();
+  private static MockSpeedController m_rearLeft = new MockSpeedController();
+  private static MockSpeedController m_frontRight = new MockSpeedController();
+  private static MockSpeedController m_rearRight = new MockSpeedController();
+  private static RobotDrive m_robotDrive =
+      new RobotDrive(m_rdFrontLeft, m_rdRearLeft, m_rdFrontRight, m_rdRearRight);
+  private static DifferentialDrive m_differentialDrive =
+      new DifferentialDrive(m_frontLeft, m_frontRight);
+  private static MecanumDrive m_mecanumDrive =
+      new MecanumDrive(m_frontLeft, m_rearLeft, m_frontRight, m_rearRight);
+
+  private final double[] m_testJoystickValues = {1.0, 0.9, 0.5, 0.01, 0.0, -0.01, -0.5, -0.9,
+                                                 -1.0};
+  private final double[] m_testGyroValues = {0, 30, 45, 90, 135, 180, 225, 270, 305, 360, 540,
+                                             -45, -90, -135, -180, -225, -270, -305, -360, -540};
+
+  @BeforeClass
+  public static void before() {
+    m_differentialDrive.setDeadband(0.0);
+    m_differentialDrive.setSafetyEnabled(false);
+    m_mecanumDrive.setDeadband(0.0);
+    m_mecanumDrive.setSafetyEnabled(false);
+    m_robotDrive.setSafetyEnabled(false);
+  }
+
+  @Test
+  public void testTankDriveSquared() {
+    for (double leftJoystick : m_testJoystickValues) {
+      for (double rightJoystick : m_testJoystickValues) {
+        m_robotDrive.tankDrive(leftJoystick, rightJoystick);
+        m_differentialDrive.tankDrive(leftJoystick, rightJoystick);
+        assertEquals("Left Motor squared didn't match. Left Joystick: " + leftJoystick
+            + " Right Joystick: " + rightJoystick + " ", m_rdFrontLeft.get(), m_frontLeft.get(),
+            0.01);
+        assertEquals("Right Motor squared didn't match. Left Joystick: " + leftJoystick
+            + " Right Joystick: " + rightJoystick + " ", m_rdFrontRight.get(), m_frontRight.get(),
+            0.01);
+      }
+    }
+  }
+
+  @Test
+  public void testTankDrive() {
+    for (double leftJoystick : m_testJoystickValues) {
+      for (double rightJoystick : m_testJoystickValues) {
+        m_robotDrive.tankDrive(leftJoystick, rightJoystick, false);
+        m_differentialDrive.tankDrive(leftJoystick, rightJoystick, false);
+        assertEquals("Left Motor didn't match. Left Joystick: " + leftJoystick
+            + " Right Joystick: " + rightJoystick + " ", m_rdFrontLeft.get(), m_frontLeft.get(),
+            0.01);
+        assertEquals("Right Motor didn't match. Left Joystick: " + leftJoystick
+            + " Right Joystick: " + rightJoystick + " ", m_rdFrontRight.get(), m_frontRight.get(),
+            0.01);
+      }
+    }
+  }
+
+  @Test
+  public void testArcadeDriveSquared() {
+    for (double moveJoystick : m_testJoystickValues) {
+      for (double rotateJoystick : m_testJoystickValues) {
+        m_robotDrive.arcadeDrive(moveJoystick, rotateJoystick);
+        m_differentialDrive.arcadeDrive(moveJoystick, -rotateJoystick);
+        assertEquals("Left Motor squared didn't match. Move Joystick: " + moveJoystick
+            + " Rotate Joystick: " + rotateJoystick + " ", m_rdFrontLeft.get(), m_frontLeft.get(),
+            0.01);
+        assertEquals("Right Motor squared didn't match. Move Joystick: " + moveJoystick
+            + " Rotate Joystick: " + rotateJoystick + " ", m_rdFrontRight.get(),
+            m_frontRight.get(), 0.01);
+      }
+    }
+  }
+
+  @Test
+  public void testArcadeDrive() {
+    for (double moveJoystick : m_testJoystickValues) {
+      for (double rotateJoystick : m_testJoystickValues) {
+        m_robotDrive.arcadeDrive(moveJoystick, rotateJoystick, false);
+        m_differentialDrive.arcadeDrive(moveJoystick, -rotateJoystick, false);
+        assertEquals("Left Motor didn't match. Move Joystick: " + moveJoystick
+            + " Rotate Joystick: " + rotateJoystick + " ", m_rdFrontLeft.get(), m_frontLeft.get(),
+            0.01);
+        assertEquals("Right Motor didn't match. Move Joystick: " + moveJoystick
+            + " Rotate Joystick: " + rotateJoystick + " ", m_rdFrontRight.get(),
+            m_frontRight.get(), 0.01);
+      }
+    }
+  }
+
+  @Test
+  public void testMecanumPolar() {
+    System.out.println("magnitudeJoystick, directionJoystick , rotationJoystick, "
+        + "m_rdFrontLeft, m_frontLeft, m_rdFrontRight, m_frontRight, m_rdRearLeft, "
+        + "m_rearLeft, m_rdRearRight, m_rearRight");
+    for (double magnitudeJoystick : m_testJoystickValues) {
+      for (double directionJoystick : m_testGyroValues) {
+        for (double rotationJoystick : m_testJoystickValues) {
+          m_robotDrive.mecanumDrive_Polar(magnitudeJoystick, directionJoystick, rotationJoystick);
+          m_mecanumDrive.drivePolar(magnitudeJoystick, directionJoystick, rotationJoystick);
+          assertEquals("Left Front Motor didn't match. Magnitude Joystick: " + magnitudeJoystick
+              + " Direction Joystick: " + directionJoystick + " RotationJoystick: "
+              + rotationJoystick, m_rdFrontLeft.get(), m_frontLeft.get(), 0.01);
+          assertEquals("Right Front Motor didn't match. Magnitude Joystick: " + magnitudeJoystick
+              + " Direction Joystick: " + directionJoystick + " RotationJoystick: "
+              + rotationJoystick, m_rdFrontRight.get(), -m_frontRight.get(), 0.01);
+          assertEquals("Left Rear Motor didn't match. Magnitude Joystick: " + magnitudeJoystick
+              + " Direction Joystick: " + directionJoystick + " RotationJoystick: "
+              + rotationJoystick, m_rdRearLeft.get(), m_rearLeft.get(), 0.01);
+          assertEquals("Right Rear Motor didn't match. Magnitude Joystick: " + magnitudeJoystick
+              + " Direction Joystick: " + directionJoystick + " RotationJoystick: "
+              + rotationJoystick, m_rdRearRight.get(), -m_rearRight.get(), 0.01);
+        }
+      }
+    }
+  }
+
+  @Test
+  @SuppressWarnings("checkstyle:LocalVariableName")
+  public void testMecanumCartesian() {
+    for (double x_Joystick : m_testJoystickValues) {
+      for (double y_Joystick : m_testJoystickValues) {
+        for (double rotationJoystick : m_testJoystickValues) {
+          for (double gyroValue : m_testGyroValues) {
+            m_robotDrive.mecanumDrive_Cartesian(x_Joystick, y_Joystick, rotationJoystick,
+                                                gyroValue);
+            m_mecanumDrive.driveCartesian(x_Joystick, -y_Joystick, rotationJoystick, -gyroValue);
+            assertEquals("Left Front Motor didn't match. X Joystick: " + x_Joystick
+                + " Y Joystick: " + y_Joystick + " RotationJoystick: "
+                + rotationJoystick + " Gyro: " + gyroValue, m_rdFrontLeft.get(),
+                m_frontLeft.get(), 0.01);
+            assertEquals("Right Front Motor didn't match. X Joystick: " + x_Joystick
+                + " Y Joystick: " + y_Joystick + " RotationJoystick: "
+                + rotationJoystick + " Gyro: " + gyroValue, m_rdFrontRight.get(),
+                -m_frontRight.get(), 0.01);
+            assertEquals("Left Rear Motor didn't match. X Joystick: " + x_Joystick
+                + " Y Joystick: " + y_Joystick + " RotationJoystick: "
+                + rotationJoystick + " Gyro: " + gyroValue, m_rdRearLeft.get(),
+                m_rearLeft.get(), 0.01);
+            assertEquals("Right Rear Motor didn't match. X Joystick: " + x_Joystick
+                + " Y Joystick: " + y_Joystick + " RotationJoystick: "
+                + rotationJoystick + " Gyro: " + gyroValue, m_rdRearRight.get(),
+                -m_rearRight.get(), 0.01);
+          }
+        }
+      }
+    }
+  }
+
+  protected Logger getClassLogger() {
+    return logger;
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/SampleTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/SampleTest.java
new file mode 100644
index 0000000..e98575f
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/SampleTest.java
@@ -0,0 +1,65 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.fixtures.SampleFixture;
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Sample test for a sample PID controller. This demonstrates the general pattern of how to create a
+ * test and use testing fixtures and categories. All tests must extend from {@link
+ * AbstractComsSetup} in order to ensure that Network Communications are set up before the tests are
+ * run.
+ */
+public class SampleTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(SampleTest.class.getName());
+
+  static SampleFixture fixture = new SampleFixture();
+
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+  @BeforeClass
+  public static void classSetup() {
+    // Set up the fixture before the test is created
+    fixture.setup();
+  }
+
+  @Before
+  public void setUp() {
+    // Reset the fixture elements before every test
+    fixture.reset();
+  }
+
+  @AfterClass
+  public static void tearDown() {
+    // Clean up the fixture after the test
+    fixture.teardown();
+  }
+
+  /**
+   * This is just a sample test that asserts true. Any traditional junit code can be used, these are
+   * ordinary junit tests!
+   */
+  @Test
+  public void test() {
+    Timer.delay(0.5);
+    assertTrue(true);
+  }
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/TimerTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/TimerTest.java
new file mode 100644
index 0000000..745daaf
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/TimerTest.java
@@ -0,0 +1,45 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.Test;
+
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+
+import static org.junit.Assert.assertEquals;
+
+
+public class TimerTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(TimerTest.class.getName());
+  private static final long TIMER_TOLERANCE = (long) (2.5 * 1000);
+  private static final long TIMER_RUNTIME = 5 * 1000000;
+
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+  @Test
+  public void delayTest() {
+    // Given
+    long startTime = RobotController.getFPGATime();
+
+    // When
+    Timer.delay(TIMER_RUNTIME / 1000000);
+    long endTime = RobotController.getFPGATime();
+    long difference = endTime - startTime;
+
+    // Then
+    long offset = difference - TIMER_RUNTIME;
+    assertEquals("Timer.delay ran " + offset + " microseconds too long", TIMER_RUNTIME, difference,
+        TIMER_TOLERANCE);
+  }
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/WpiLibJTestSuite.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/WpiLibJTestSuite.java
new file mode 100644
index 0000000..6d5fff0
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/WpiLibJTestSuite.java
@@ -0,0 +1,30 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+import edu.wpi.first.wpilibj.test.AbstractTestSuite;
+
+/**
+ * Holds all of the tests in the root wpilibj directory. Please list alphabetically so that it is
+ * easy to determine if a test is missing from the list.
+ */
+@RunWith(Suite.class)
+@SuiteClasses({AnalogCrossConnectTest.class, AnalogPotentiometerTest.class,
+    BuiltInAccelerometerTest.class,
+    CircularBufferTest.class, ConstantsPortsTest.class, CounterTest.class,
+    DigitalGlitchFilterTest.class, DIOCrossConnectTest.class, DriverStationTest.class,
+    EncoderTest.class, FilterNoiseTest.class, FilterOutputTest.class, GyroTest.class,
+    MotorEncoderTest.class, MotorInvertingTest.class, PCMTest.class, PDPTest.class,
+    PIDTest.class, PIDToleranceTest.class, PreferencesTest.class, RelayCrossConnectTest.class,
+    RobotDriveTest.class, SampleTest.class, TimerTest.class})
+public class WpiLibJTestSuite extends AbstractTestSuite {
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/can/CANStatusTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/can/CANStatusTest.java
new file mode 100644
index 0000000..c501ebc
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/can/CANStatusTest.java
@@ -0,0 +1,19 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2017-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.can;
+
+import org.junit.Test;
+
+public class CANStatusTest {
+  @Test
+  public void canStatusGetDoesntThrow() {
+    CANStatus status = new CANStatus();
+    CANJNI.GetCANStatus(status);
+    // Nothing we can assert, so just make sure it didn't throw.
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/command/CommandTestSuite.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/command/CommandTestSuite.java
new file mode 100644
index 0000000..ea34c69
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/command/CommandTestSuite.java
@@ -0,0 +1,24 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.command;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+import edu.wpi.first.wpilibj.test.AbstractTestSuite;
+
+/**
+ * Contains a listing of all of the {@link Command} tests.
+ */
+@RunWith(Suite.class)
+@SuiteClasses({ButtonTest.class, CommandParallelGroupTest.class, CommandScheduleTest.class,
+    CommandSequentialGroupTest.class, CommandSupersedeTest.class, CommandTimeoutTest.class,
+    ConditionalCommandTest.class, DefaultCommandTest.class})
+public class CommandTestSuite extends AbstractTestSuite {
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/AnalogCrossConnectFixture.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/AnalogCrossConnectFixture.java
new file mode 100644
index 0000000..f14ceaa
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/AnalogCrossConnectFixture.java
@@ -0,0 +1,86 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.fixtures;
+
+import edu.wpi.first.wpilibj.AnalogInput;
+import edu.wpi.first.wpilibj.AnalogOutput;
+
+/**
+ * A fixture that connects an {@link AnalogInput} and an {@link AnalogOutput}.
+ */
+public abstract class AnalogCrossConnectFixture implements ITestFixture {
+  private boolean m_initialized = false;
+
+  private AnalogInput m_input;
+  private AnalogOutput m_output;
+
+  protected abstract AnalogInput giveAnalogInput();
+
+  protected abstract AnalogOutput giveAnalogOutput();
+
+
+  private void initialize() {
+    synchronized (this) {
+      if (!m_initialized) {
+        m_input = giveAnalogInput();
+        m_output = giveAnalogOutput();
+        m_initialized = true;
+      }
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.fixtures.ITestFixture#setup()
+   */
+  @Override
+  public boolean setup() {
+    initialize();
+    m_output.setVoltage(0);
+    return true;
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.fixtures.ITestFixture#reset()
+   */
+  @Override
+  public boolean reset() {
+    initialize();
+    return true;
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.fixtures.ITestFixture#teardown()
+   */
+  @Override
+  public boolean teardown() {
+    m_input.free();
+    m_output.free();
+    return true;
+  }
+
+  /**
+   * Analog Output.
+   */
+  public final AnalogOutput getOutput() {
+    initialize();
+    return m_output;
+  }
+
+  public final AnalogInput getInput() {
+    initialize();
+    return m_input;
+  }
+
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/DIOCrossConnectFixture.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/DIOCrossConnectFixture.java
new file mode 100644
index 0000000..de77fb9
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/DIOCrossConnectFixture.java
@@ -0,0 +1,90 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.fixtures;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.DigitalInput;
+import edu.wpi.first.wpilibj.DigitalOutput;
+
+/**
+ * Connects a digital input to a digital output.
+ */
+public class DIOCrossConnectFixture implements ITestFixture {
+  private static final Logger logger = Logger.getLogger(DIOCrossConnectFixture.class.getName());
+
+  private final DigitalInput m_input;
+  private final DigitalOutput m_output;
+  private boolean m_allocated;
+
+  /**
+   * Constructs using two pre-allocated digital objects.
+   *
+   * @param input  The input
+   * @param output The output.
+   */
+  public DIOCrossConnectFixture(DigitalInput input, DigitalOutput output) {
+    assert input != null;
+    assert output != null;
+    m_input = input;
+    m_output = output;
+    m_allocated = false;
+  }
+
+  /**
+   * Constructs a {@link DIOCrossConnectFixture} using the ports of the digital objects.
+   *
+   * @param input  The port of the {@link DigitalInput}
+   * @param output The port of the {@link DigitalOutput}
+   */
+  public DIOCrossConnectFixture(Integer input, Integer output) {
+    assert input != null;
+    assert output != null;
+    assert !input.equals(output);
+    m_input = new DigitalInput(input);
+    m_output = new DigitalOutput(output);
+    m_allocated = true;
+  }
+
+  public DigitalInput getInput() {
+    return m_input;
+  }
+
+  public DigitalOutput getOutput() {
+    return m_output;
+  }
+
+  @Override
+  public boolean setup() {
+    return true;
+  }
+
+  @Override
+  public boolean reset() {
+    try {
+      m_input.cancelInterrupts();
+    } catch (IllegalStateException ex) {
+      // This will happen if the interrupt has not been allocated for this test.
+    }
+    m_output.set(false);
+    return true;
+  }
+
+  @Override
+  public boolean teardown() {
+    logger.log(Level.FINE, "Begining teardown");
+    if (m_allocated) {
+      m_input.free();
+      m_output.free();
+      m_allocated = false;
+    }
+    return true;
+  }
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/FakeCounterFixture.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/FakeCounterFixture.java
new file mode 100644
index 0000000..bff0e4c
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/FakeCounterFixture.java
@@ -0,0 +1,112 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.fixtures;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.Counter;
+import edu.wpi.first.wpilibj.mockhardware.FakeCounterSource;
+
+/**
+ * A fixture that can test the {@link Counter} using a {@link DIOCrossConnectFixture}.
+ */
+public class FakeCounterFixture implements ITestFixture {
+  private static final Logger logger = Logger.getLogger(FakeEncoderFixture.class.getName());
+
+  private final DIOCrossConnectFixture m_dio;
+  private boolean m_allocated;
+  private final FakeCounterSource m_source;
+  private final Counter m_counter;
+
+  /**
+   * Constructs a FakeCounterFixture.
+   *
+   * @param dio A previously allocated DIOCrossConnectFixture (must be freed outside this class)
+   */
+  public FakeCounterFixture(DIOCrossConnectFixture dio) {
+    m_dio = dio;
+    m_allocated = false;
+    m_source = new FakeCounterSource(dio.getOutput());
+    m_counter = new Counter(dio.getInput());
+  }
+
+
+  /**
+   * Constructs a FakeCounterFixture using two port numbers.
+   *
+   * @param input  the input port
+   * @param output the output port
+   */
+  public FakeCounterFixture(int input, int output) {
+    m_dio = new DIOCrossConnectFixture(input, output);
+    m_allocated = true;
+    m_source = new FakeCounterSource(m_dio.getOutput());
+    m_counter = new Counter(m_dio.getInput());
+  }
+
+  /**
+   * Retrieves the FakeCouterSource for use.
+   *
+   * @return the FakeCounterSource
+   */
+  public FakeCounterSource getFakeCounterSource() {
+    return m_source;
+  }
+
+  /**
+   * Gets the Counter for use.
+   *
+   * @return the Counter
+   */
+  public Counter getCounter() {
+    return m_counter;
+  }
+
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.fixtures.ITestFixture#setup()
+   */
+  @Override
+  public boolean setup() {
+    return true;
+
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.fixtures.ITestFixture#reset()
+   */
+  @Override
+  public boolean reset() {
+    m_counter.reset();
+    return true;
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.fixtures.ITestFixture#teardown()
+   */
+  @Override
+  public boolean teardown() {
+    logger.log(Level.FINE, "Begining teardown");
+    m_counter.free();
+    m_source.free();
+    if (m_allocated) { // Only tear down the dio if this class allocated it
+      m_dio.teardown();
+      m_allocated = false;
+    }
+    return true;
+  }
+
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/FakeEncoderFixture.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/FakeEncoderFixture.java
new file mode 100644
index 0000000..372b2d8
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/FakeEncoderFixture.java
@@ -0,0 +1,116 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.fixtures;
+
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.Encoder;
+import edu.wpi.first.wpilibj.mockhardware.FakeEncoderSource;
+
+/**
+ * An encoder that uses two {@link DIOCrossConnectFixture DIOCrossConnectFixtures} to test the
+ * {@link Encoder}.
+ */
+public class FakeEncoderFixture implements ITestFixture {
+  private static final Logger logger = Logger.getLogger(FakeEncoderFixture.class.getName());
+
+  private final DIOCrossConnectFixture m_dio1;
+  private final DIOCrossConnectFixture m_dio2;
+  private boolean m_allocated;
+
+  private final FakeEncoderSource m_source;
+  private int[] m_sourcePort = new int[2];
+  private final Encoder m_encoder;
+  private int[] m_encoderPort = new int[2];
+
+  /**
+   * Constructs a FakeEncoderFixture from two DIOCrossConnectFixture.
+   */
+  public FakeEncoderFixture(DIOCrossConnectFixture dio1, DIOCrossConnectFixture dio2) {
+    assert dio1 != null;
+    assert dio2 != null;
+    m_dio1 = dio1;
+    m_dio2 = dio2;
+    m_allocated = false;
+    m_source = new FakeEncoderSource(dio1.getOutput(), dio2.getOutput());
+    m_encoder = new Encoder(dio1.getInput(), dio2.getInput());
+  }
+
+  /**
+   * Construcst a FakeEncoderFixture from a set of Digital I/O ports.
+   */
+  public FakeEncoderFixture(int inputA, int outputA, int inputB, int outputB) {
+    assert outputA != outputB;
+    assert outputA != inputA;
+    assert outputA != inputB;
+    assert outputB != inputA;
+    assert outputB != inputB;
+    assert inputA != inputB;
+    m_dio1 = new DIOCrossConnectFixture(inputA, outputA);
+    m_dio2 = new DIOCrossConnectFixture(inputB, outputB);
+    m_allocated = true;
+    m_sourcePort[0] = outputA;
+    m_sourcePort[1] = outputB;
+    m_encoderPort[0] = inputA;
+    m_encoderPort[1] = inputB;
+    m_source = new FakeEncoderSource(m_dio1.getOutput(), m_dio2.getOutput());
+    m_encoder = new Encoder(m_dio1.getInput(), m_dio2.getInput());
+  }
+
+  public FakeEncoderSource getFakeEncoderSource() {
+    return m_source;
+  }
+
+  public Encoder getEncoder() {
+    return m_encoder;
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.fixtures.ITestFixture#setup()
+   */
+  @Override
+  public boolean setup() {
+    return true;
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.fixtures.ITestFixture#reset()
+   */
+  @Override
+  public boolean reset() {
+    m_dio1.reset();
+    m_dio2.reset();
+    m_encoder.reset();
+    return true;
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.fixtures.ITestFixture#teardown()
+   */
+  @Override
+  public boolean teardown() {
+    logger.fine("Begining teardown");
+    m_source.free();
+    logger.finer("Source freed " + m_sourcePort[0] + ",  " + m_sourcePort[1]);
+    m_encoder.free();
+    logger.finer("Encoder freed " + m_encoderPort[0] + ", " + m_encoderPort[1]);
+    if (m_allocated) {
+      m_dio1.teardown();
+      m_dio2.teardown();
+    }
+    return true;
+  }
+
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/FilterNoiseFixture.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/FilterNoiseFixture.java
new file mode 100644
index 0000000..ee899b3
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/FilterNoiseFixture.java
@@ -0,0 +1,159 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.fixtures;
+
+import java.lang.reflect.ParameterizedType;
+import java.util.Random;
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.PIDSource;
+import edu.wpi.first.wpilibj.PIDSourceType;
+import edu.wpi.first.wpilibj.test.TestBench;
+
+/**
+ * Represents a physically connected Motor and Encoder to allow for unit tests on these different
+ * pairs<br> Designed to allow the user to easily setup and tear down the fixture to allow for
+ * reuse. This class should be explicitly instantiated in the TestBed class to allow any test to
+ * access this fixture. This allows tests to be mailable so that you can easily reconfigure the
+ * physical testbed without breaking the tests.
+ */
+public abstract class FilterNoiseFixture<T extends PIDSource> implements ITestFixture {
+  private static final Logger logger = Logger.getLogger(FilterNoiseFixture.class.getName());
+  private boolean m_initialized = false;
+  private boolean m_tornDown = false;
+  protected T m_filter;
+  private NoiseGenerator m_data;
+
+  /**
+   * Where the implementer of this class should pass the filter constructor.
+   */
+  protected abstract T giveFilter(PIDSource source);
+
+  private void initialize() {
+    synchronized (this) {
+      if (!m_initialized) {
+        m_initialized = true; // This ensures it is only initialized once
+
+        m_data = new NoiseGenerator(TestBench.kStdDev) {
+          @Override
+          @SuppressWarnings("ParameterName")
+          public double getData(double t) {
+            return 100.0 * Math.sin(2.0 * Math.PI * t);
+          }
+        };
+        m_filter = giveFilter(m_data);
+      }
+    }
+  }
+
+  @Override
+  public boolean setup() {
+    initialize();
+    return true;
+  }
+
+  /**
+   * Gets the filter for this Object.
+   *
+   * @return the filter this object refers too
+   */
+  public T getFilter() {
+    initialize();
+    return m_filter;
+  }
+
+  /**
+   * Gets the noise generator for this object.
+   *
+   * @return the noise generator that this object refers too
+   */
+  public NoiseGenerator getNoiseGenerator() {
+    initialize();
+    return m_data;
+  }
+
+  /**
+   * Retrieves the name of the filter that this object refers to.
+   *
+   * @return The simple name of the filter {@link Class#getSimpleName()}
+   */
+  public String getType() {
+    initialize();
+    return m_filter.getClass().getSimpleName();
+  }
+
+  // test here?
+
+  @Override
+  public boolean reset() {
+    return true;
+  }
+
+  @Override
+  public boolean teardown() {
+    return true;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder string = new StringBuilder("FilterNoiseFixture<");
+    // Get the generic type as a class
+    @SuppressWarnings("unchecked")
+    Class<T> class1 =
+        (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
+            .getActualTypeArguments()[0];
+    string.append(class1.getSimpleName());
+    string.append(">");
+    return string.toString();
+  }
+
+  /**
+   * Adds Gaussian white noise to a function returning data. The noise will have the standard
+   * deviation provided in the constructor.
+   */
+  public abstract class NoiseGenerator implements PIDSource {
+    private double m_noise = 0.0;
+
+    // Make sure first call to pidGet() uses count == 0
+    private double m_count = -TestBench.kFilterStep;
+
+    private double m_stdDev;
+    private Random m_gen = new Random();
+
+    NoiseGenerator(double stdDev) {
+      m_stdDev = stdDev;
+    }
+
+    @SuppressWarnings("ParameterName")
+    public abstract double getData(double t);
+
+    @Override
+    public void setPIDSourceType(PIDSourceType pidSource) {
+    }
+
+    @Override
+    public PIDSourceType getPIDSourceType() {
+      return PIDSourceType.kDisplacement;
+    }
+
+    public double get() {
+      return getData(m_count) + m_noise;
+    }
+
+    @Override
+    public double pidGet() {
+      m_noise = m_gen.nextGaussian() * m_stdDev;
+      m_count += TestBench.kFilterStep;
+      return getData(m_count) + m_noise;
+    }
+
+    public void reset() {
+      m_count = -TestBench.kFilterStep;
+    }
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/FilterOutputFixture.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/FilterOutputFixture.java
new file mode 100644
index 0000000..3c31982
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/FilterOutputFixture.java
@@ -0,0 +1,159 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.fixtures;
+
+import java.lang.reflect.ParameterizedType;
+import java.util.function.DoubleFunction;
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.PIDSource;
+import edu.wpi.first.wpilibj.PIDSourceType;
+import edu.wpi.first.wpilibj.test.TestBench;
+
+/**
+ * Represents a filter to allow for unit tests on them<br> Designed to allow the user to easily
+ * setup and tear down the fixture to allow for reuse. This class should be explicitly instantiated
+ * in the TestBed class to allow any test to access this fixture. This allows tests to be mailable
+ * so that you can easily reconfigure the physical testbed without breaking the tests.
+ */
+public abstract class FilterOutputFixture<T extends PIDSource> implements ITestFixture {
+  private static final Logger logger = Logger.getLogger(FilterOutputFixture.class.getName());
+  private boolean m_initialized = false;
+  private boolean m_tornDown = false;
+  protected T m_filter;
+  protected DataWrapper m_data;
+  private double m_expectedOutput;
+
+  public FilterOutputFixture(double expectedOutput) {
+    m_expectedOutput = expectedOutput;
+  }
+
+  /**
+   * Get expected output of fixture.
+   */
+  public double getExpectedOutput() {
+    return m_expectedOutput;
+  }
+
+  public static DoubleFunction<Double> getData = new DoubleFunction<Double>() {
+    @Override
+    @SuppressWarnings("ParameterName")
+    public Double apply(double t) {
+      return 100.0 * Math.sin(2.0 * Math.PI * t) + 20.0 * Math.cos(50.0 * Math.PI * t);
+    }
+  };
+
+  public static DoubleFunction<Double> getPulseData = new DoubleFunction<Double>() {
+    @Override
+    @SuppressWarnings("ParameterName")
+    public Double apply(double t) {
+      if (Math.abs(t - 1.0) < 0.001) {
+        return 1.0;
+      } else {
+        return 0.0;
+      }
+    }
+  };
+
+  /**
+   * Where the implementer of this class should pass the filter constructor.
+   */
+  protected abstract T giveFilter();
+
+  private void initialize() {
+    synchronized (this) {
+      if (!m_initialized) {
+        m_initialized = true; // This ensures it is only initialized once
+
+        m_filter = giveFilter();
+      }
+    }
+  }
+
+  @Override
+  public boolean setup() {
+    initialize();
+    return true;
+  }
+
+  /**
+   * Gets the filter for this Object.
+   *
+   * @return the filter this object refers too
+   */
+  public T getFilter() {
+    initialize();
+    return m_filter;
+  }
+
+  /**
+   * Retrieves the name of the filter that this object refers to.
+   *
+   * @return The simple name of the filter {@link Class#getSimpleName()}
+   */
+  public String getType() {
+    initialize();
+    return m_filter.getClass().getSimpleName();
+  }
+
+  @Override
+  public boolean reset() {
+    m_data.reset();
+    return true;
+  }
+
+  @Override
+  public boolean teardown() {
+    return true;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder string = new StringBuilder("FilterOutputFixture<");
+    // Get the generic type as a class
+    @SuppressWarnings("unchecked")
+    Class<T> class1 =
+        (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
+            .getActualTypeArguments()[0];
+    string.append(class1.getSimpleName());
+    string.append(">");
+    return string.toString();
+  }
+
+  public class DataWrapper implements PIDSource {
+    // Make sure first call to pidGet() uses count == 0
+    private double m_count = -TestBench.kFilterStep;
+
+    private DoubleFunction<Double> m_func;
+
+    public DataWrapper(DoubleFunction<Double> func) {
+      m_func = func;
+    }
+
+    @Override
+    public void setPIDSourceType(PIDSourceType pidSource) {
+    }
+
+
+    @Override
+    public PIDSourceType getPIDSourceType() {
+      return PIDSourceType.kDisplacement;
+    }
+
+
+    @Override
+    public double pidGet() {
+      m_count += TestBench.kFilterStep;
+      return m_func.apply(m_count);
+    }
+
+    public void reset() {
+      m_count = -TestBench.kFilterStep;
+    }
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/ITestFixture.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/ITestFixture.java
new file mode 100644
index 0000000..ea2b91f
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/ITestFixture.java
@@ -0,0 +1,48 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.fixtures;
+
+import edu.wpi.first.wpilibj.test.TestBench;
+
+/**
+ * Master interface for all test fixtures. This ensures that all test fixtures have setup and
+ * teardown methods, to ensure that the tests run properly. Test fixtures should be modeled around
+ * the content of a test, rather than the actual physical layout of the testing board. They should
+ * obtain references to hardware from the {@link TestBench} class, which is a singleton. Testing
+ * Fixtures are responsible for ensuring that the hardware is in an appropriate state for the start
+ * of a test, and ensuring that future tests will not be affected by the results of a test.
+ */
+public interface ITestFixture {
+
+  /**
+   * Performs any required setup for this fixture, ensuring that all fixture elements are ready for
+   * testing.
+   *
+   * @return True if the fixture is ready for testing
+   */
+  boolean setup();
+
+  /**
+   * Resets the fixture back to test start state. This should be called by the test class in the
+   * test setup method to ensure that the hardware is in the default state. This differs from {@link
+   * ITestFixture#setup()} as that is called once, before the class is constructed, so it may need
+   * to start sensors. This method should not have to start anything, just reset sensors and ensure
+   * that motors are stopped.
+   *
+   * @return True if the fixture is ready for testing
+   */
+  boolean reset();
+
+  /**
+   * Performs any required teardown after use of the fixture, ensuring that future tests will not
+   * run into conflicts.
+   *
+   * @return True if the teardown succeeded
+   */
+  boolean teardown();
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/MotorEncoderFixture.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/MotorEncoderFixture.java
new file mode 100644
index 0000000..0a78583
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/MotorEncoderFixture.java
@@ -0,0 +1,245 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.fixtures;
+
+import java.lang.reflect.ParameterizedType;
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.Counter;
+import edu.wpi.first.wpilibj.DigitalInput;
+import edu.wpi.first.wpilibj.Encoder;
+import edu.wpi.first.wpilibj.PWM;
+import edu.wpi.first.wpilibj.SpeedController;
+import edu.wpi.first.wpilibj.Timer;
+import edu.wpi.first.wpilibj.test.TestBench;
+
+/**
+ * Represents a physically connected Motor and Encoder to allow for unit tests on these different
+ * pairs<br> Designed to allow the user to easily setup and tear down the fixture to allow for
+ * reuse. This class should be explicitly instantiated in the TestBed class to allow any test to
+ * access this fixture. This allows tests to be mailable so that you can easily reconfigure the
+ * physical testbed without breaking the tests.
+ */
+public abstract class MotorEncoderFixture<T extends SpeedController> implements ITestFixture {
+  private static final Logger logger = Logger.getLogger(MotorEncoderFixture.class.getName());
+  private boolean m_initialized = false;
+  private boolean m_tornDown = false;
+  protected T m_motor;
+  private Encoder m_encoder;
+  private final Counter[] m_counters = new Counter[2];
+  protected DigitalInput m_alphaSource; // Stored so it can be freed at tear down
+  protected DigitalInput m_betaSource;
+
+  /**
+   * Default constructor for a MotorEncoderFixture.
+   */
+  public MotorEncoderFixture() {
+  }
+
+  public abstract int getPDPChannel();
+
+  /**
+   * Where the implementer of this class should pass the speed controller Constructor should only be
+   * called from outside this class if the Speed controller is not also an implementation of PWM
+   * interface.
+   *
+   * @return SpeedController
+   */
+  protected abstract T giveSpeedController();
+
+  /**
+   * Where the implementer of this class should pass one of the digital inputs.
+   *
+   * <p>CONSTRUCTOR SHOULD NOT BE CALLED FROM OUTSIDE THIS CLASS!
+   *
+   * @return DigitalInput
+   */
+  protected abstract DigitalInput giveDigitalInputA();
+
+  /**
+   * Where the implementer fo this class should pass the other digital input.
+   *
+   * <p>CONSTRUCTOR SHOULD NOT BE CALLED FROM OUTSIDE THIS CLASS!
+   *
+   * @return Input B to be used when this class is instantiated
+   */
+  protected abstract DigitalInput giveDigitalInputB();
+
+  private void initialize() {
+    synchronized (this) {
+      if (!m_initialized) {
+        m_initialized = true; // This ensures it is only initialized once
+
+        m_alphaSource = giveDigitalInputA();
+        m_betaSource = giveDigitalInputB();
+
+
+        m_encoder = new Encoder(m_alphaSource, m_betaSource);
+        m_counters[0] = new Counter(m_alphaSource);
+        m_counters[1] = new Counter(m_betaSource);
+        logger.fine("Creating the speed controller!");
+        m_motor = giveSpeedController();
+      }
+    }
+  }
+
+  @Override
+  public boolean setup() {
+    initialize();
+    return true;
+  }
+
+  /**
+   * Gets the motor for this Object.
+   *
+   * @return the motor this object refers too
+   */
+  public T getMotor() {
+    initialize();
+    return m_motor;
+  }
+
+  /**
+   * Gets the encoder for this object.
+   *
+   * @return the encoder that this object refers too
+   */
+  public Encoder getEncoder() {
+    initialize();
+    return m_encoder;
+  }
+
+  public Counter[] getCounters() {
+    initialize();
+    return m_counters;
+  }
+
+  /**
+   * Retrieves the name of the motor that this object refers to.
+   *
+   * @return The simple name of the motor {@link Class#getSimpleName()}
+   */
+  public String getType() {
+    initialize();
+    return m_motor.getClass().getSimpleName();
+  }
+
+  /**
+   * Checks to see if the speed of the motor is within some range of a given value. This is used
+   * instead of equals() because doubles can have inaccuracies.
+   *
+   * @param value    The value to compare against
+   * @param accuracy The accuracy range to check against to see if the
+   * @return true if the range of values between motors speed accuracy contains the 'value'.
+   */
+  public boolean isMotorSpeedWithinRange(double value, double accuracy) {
+    initialize();
+    return Math.abs(Math.abs(m_motor.get()) - Math.abs(value)) < Math.abs(accuracy);
+  }
+
+  @Override
+  public boolean reset() {
+    initialize();
+    m_motor.setInverted(false);
+    m_motor.set(0);
+    Timer.delay(TestBench.MOTOR_STOP_TIME); // DEFINED IN THE TestBench
+    m_encoder.reset();
+    for (Counter c : m_counters) {
+      c.reset();
+    }
+
+    boolean wasReset = true;
+    wasReset = wasReset && m_motor.get() == 0;
+    wasReset = wasReset && m_encoder.get() == 0;
+    for (Counter c : m_counters) {
+      wasReset = wasReset && c.get() == 0;
+    }
+
+    return wasReset;
+  }
+
+
+  /**
+   * Safely tears down the MotorEncoder Fixture in a way that makes sure that even if an object
+   * fails to initialize the rest of the fixture can still be torn down and the resources
+   * deallocated.
+   */
+  @Override
+  @SuppressWarnings("Regexp")
+  public boolean teardown() {
+    String type;
+    if (m_motor != null) {
+      type = getType();
+    } else {
+      type = "null";
+    }
+    if (!m_tornDown) {
+      boolean wasNull = false;
+      if (m_motor instanceof PWM && m_motor != null) {
+        ((PWM) m_motor).free();
+        m_motor = null;
+      } else if (m_motor == null) {
+        wasNull = true;
+      }
+      if (m_encoder != null) {
+        m_encoder.free();
+        m_encoder = null;
+      } else {
+        wasNull = true;
+      }
+      if (m_counters[0] != null) {
+        m_counters[0].free();
+        m_counters[0] = null;
+      } else {
+        wasNull = true;
+      }
+      if (m_counters[1] != null) {
+        m_counters[1].free();
+        m_counters[1] = null;
+      } else {
+        wasNull = true;
+      }
+      if (m_alphaSource != null) {
+        m_alphaSource.free();
+        m_alphaSource = null;
+      } else {
+        wasNull = true;
+      }
+      if (m_betaSource != null) {
+        m_betaSource.free();
+        m_betaSource = null;
+      } else {
+        wasNull = true;
+      }
+
+      m_tornDown = true;
+
+      if (wasNull) {
+        throw new NullPointerException("MotorEncoderFixture had null params at teardown");
+      }
+    } else {
+      throw new RuntimeException(type + " Motor Encoder torn down multiple times");
+    }
+
+    return true;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder string = new StringBuilder("MotorEncoderFixture<");
+    // Get the generic type as a class
+    @SuppressWarnings("unchecked")
+    Class<T> class1 =
+        (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
+            .getActualTypeArguments()[0];
+    string.append(class1.getSimpleName());
+    string.append(">");
+    return string.toString();
+  }
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/RelayCrossConnectFixture.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/RelayCrossConnectFixture.java
new file mode 100644
index 0000000..ee19c9a
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/RelayCrossConnectFixture.java
@@ -0,0 +1,97 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.fixtures;
+
+import edu.wpi.first.wpilibj.DigitalInput;
+import edu.wpi.first.wpilibj.Relay;
+
+/**
+ * A connection between a {@link Relay} and two {@link DigitalInput DigitalInputs}.
+ */
+public abstract class RelayCrossConnectFixture implements ITestFixture {
+  private DigitalInput m_inputOne;
+  private DigitalInput m_inputTwo;
+  private Relay m_relay;
+
+  private boolean m_initialized = false;
+  private boolean m_freed = false;
+
+
+  protected abstract Relay giveRelay();
+
+  protected abstract DigitalInput giveInputOne();
+
+  protected abstract DigitalInput giveInputTwo();
+
+  private void initialize() {
+    synchronized (this) {
+      if (!m_initialized) {
+        m_relay = giveRelay();
+        m_inputOne = giveInputOne();
+        m_inputTwo = giveInputTwo();
+        m_initialized = true;
+      }
+    }
+  }
+
+  public Relay getRelay() {
+    initialize();
+    return m_relay;
+  }
+
+  public DigitalInput getInputOne() {
+    initialize();
+    return m_inputOne;
+  }
+
+  public DigitalInput getInputTwo() {
+    initialize();
+    return m_inputTwo;
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.fixtures.ITestFixture#setup()
+   */
+  @Override
+  public boolean setup() {
+    initialize();
+    return true;
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.fixtures.ITestFixture#reset()
+   */
+  @Override
+  public boolean reset() {
+    initialize();
+    return true;
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.fixtures.ITestFixture#teardown()
+   */
+  @Override
+  public boolean teardown() {
+    if (!m_freed) {
+      m_relay.free();
+      m_inputOne.free();
+      m_inputTwo.free();
+      m_freed = true;
+    } else {
+      throw new RuntimeException("You attempted to free the "
+          + RelayCrossConnectFixture.class.getSimpleName() + " multiple times");
+    }
+    return true;
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/SampleFixture.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/SampleFixture.java
new file mode 100644
index 0000000..994c6ee
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/SampleFixture.java
@@ -0,0 +1,48 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.fixtures;
+
+
+/**
+ * This is an example of how to use the {@link ITestFixture} interface to create test fixtures for a
+ * test.
+ */
+public class SampleFixture implements ITestFixture {
+  @Override
+  public boolean setup() {
+    /*
+     * If this fixture actually accessed the hardware, here is where it would
+     * set up the starting state of the test bench. For example, reseting
+     * encoders, ensuring motors are stopped, reseting any serial communication
+     * if necessary, etc.
+     */
+    return true;
+  }
+
+  @Override
+  public boolean reset() {
+    /*
+     * This is where the fixture would reset any sensors or motors used by the
+     * fixture to test default state. This method should not worry about whether
+     * or not the sensors have been allocated correctly, that is the job of the
+     * setup function.
+     */
+    return false;
+  }
+
+  @Override
+  public boolean teardown() {
+    /*
+     * This is where the fixture would deallocate and reset back to normal
+     * conditions any necessary hardware. This includes ensuring motors are
+     * stopped, stoppable sensors are actually stopped, ensuring serial
+     * communications are ready for the next test, etc.
+     */
+    return true;
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/TiltPanCameraFixture.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/TiltPanCameraFixture.java
new file mode 100644
index 0000000..096c559
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/fixtures/TiltPanCameraFixture.java
@@ -0,0 +1,116 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.fixtures;
+
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.AnalogGyro;
+import edu.wpi.first.wpilibj.Servo;
+import edu.wpi.first.wpilibj.Timer;
+
+/**
+ * A class to represent the a physical Camera with two servos (tilt and pan) designed to test to see
+ * if the gyroscope is operating normally.
+ */
+public abstract class TiltPanCameraFixture implements ITestFixture {
+  public static final Logger logger = Logger.getLogger(TiltPanCameraFixture.class.getName());
+
+  public static final double RESET_TIME = 2.0;
+  private AnalogGyro m_gyro;
+  private AnalogGyro m_gyroParam;
+  private Servo m_tilt;
+  private Servo m_pan;
+  private boolean m_initialized = false;
+
+
+  protected abstract AnalogGyro giveGyro();
+
+  protected abstract AnalogGyro giveGyroParam(int center, double offset);
+
+  protected abstract Servo giveTilt();
+
+  protected abstract Servo givePan();
+
+  /**
+   * Constructs the TiltPanCamera.
+   */
+  public TiltPanCameraFixture() {
+  }
+
+  @Override
+  public boolean setup() {
+    boolean wasSetup = false;
+    if (!m_initialized) {
+      m_initialized = true;
+      m_tilt = giveTilt();
+      m_tilt.set(0);
+      m_pan = givePan();
+      m_pan.set(0);
+      Timer.delay(RESET_TIME);
+
+      logger.fine("Initializing the gyro");
+      m_gyro = giveGyro();
+      m_gyro.reset();
+      wasSetup = true;
+    }
+    return wasSetup;
+  }
+
+  @Override
+  public boolean reset() {
+    if (m_gyro != null) {
+      m_gyro.reset();
+    }
+    return true;
+  }
+
+  public Servo getTilt() {
+    return m_tilt;
+  }
+
+  public Servo getPan() {
+    return m_pan;
+  }
+
+  public AnalogGyro getGyro() {
+    return m_gyro;
+  }
+
+  public AnalogGyro getGyroParam() {
+    return m_gyroParam;
+  }
+
+  // Do not call unless all other instances of Gyro have been deallocated
+  public void setupGyroParam(int center, double offset) {
+    m_gyroParam = giveGyroParam(center, offset);
+    m_gyroParam.reset();
+  }
+
+  public void freeGyro() {
+    m_gyro.free();
+    m_gyro = null;
+  }
+
+  @Override
+  public boolean teardown() {
+    m_tilt.free();
+    m_tilt = null;
+    m_pan.free();
+    m_pan = null;
+    if (m_gyro != null) { //in case not freed during gyro tests
+      m_gyro.free();
+      m_gyro = null;
+    }
+    if (m_gyroParam != null) { //in case gyro tests failed before getting to this point
+      m_gyroParam.free();
+      m_gyroParam = null;
+    }
+    return true;
+  }
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/mockhardware/FakeCounterSource.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/mockhardware/FakeCounterSource.java
new file mode 100644
index 0000000..a3fc938
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/mockhardware/FakeCounterSource.java
@@ -0,0 +1,136 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2014-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.mockhardware;
+
+import edu.wpi.first.wpilibj.DigitalOutput;
+import edu.wpi.first.wpilibj.Timer;
+
+/**
+ * Simulates an encoder for testing purposes.
+ */
+public class FakeCounterSource {
+  private Thread m_task;
+  private int m_count;
+  private int m_milliSec;
+  private DigitalOutput m_output;
+  private boolean m_allocated;
+
+  /**
+   * Thread object that allows emulation of an encoder.
+   */
+  private class EncoderThread extends Thread {
+    FakeCounterSource m_encoder;
+
+    EncoderThread(FakeCounterSource encode) {
+      m_encoder = encode;
+    }
+
+    public void run() {
+      m_encoder.m_output.set(false);
+      try {
+        for (int i = 0; i < m_encoder.m_count; i++) {
+          Thread.sleep(m_encoder.m_milliSec);
+          m_encoder.m_output.set(true);
+          Thread.sleep(m_encoder.m_milliSec);
+          m_encoder.m_output.set(false);
+        }
+      } catch (InterruptedException ex) {
+        Thread.currentThread().interrupt();
+      }
+    }
+  }
+
+  /**
+   * Create a fake encoder on a given port.
+   *
+   * @param output the port to output the given signal to
+   */
+  public FakeCounterSource(DigitalOutput output) {
+    m_output = output;
+    m_allocated = false;
+    initEncoder();
+  }
+
+  /**
+   * Create a fake encoder on a given port.
+   *
+   * @param port The port the encoder is supposed to be on
+   */
+  public FakeCounterSource(int port) {
+    m_output = new DigitalOutput(port);
+    m_allocated = true;
+    initEncoder();
+  }
+
+  /**
+   * Destroy Object with minimum memory leak.
+   */
+  public void free() {
+    m_task = null;
+    if (m_allocated) {
+      m_output.free();
+      m_output = null;
+      m_allocated = false;
+    }
+  }
+
+  /**
+   * Common initailization code.
+   */
+  private void initEncoder() {
+    m_milliSec = 1;
+    m_task = new EncoderThread(this);
+    m_output.set(false);
+  }
+
+  /**
+   * Starts the thread execution task.
+   */
+  public void start() {
+    m_task.start();
+  }
+
+  /**
+   * Waits for the thread to complete.
+   */
+  public void complete() {
+    try {
+      m_task.join();
+    } catch (InterruptedException ex) {
+      Thread.currentThread().interrupt();
+    }
+    m_task = new EncoderThread(this);
+    Timer.delay(.01);
+  }
+
+  /**
+   * Starts and completes a task set - does not return until thred has finished its operations.
+   */
+  public void execute() {
+    start();
+    complete();
+  }
+
+  /**
+   * Sets the count to run encoder.
+   *
+   * @param count The count to emulate to the controller
+   */
+  public void setCount(int count) {
+    m_count = count;
+  }
+
+  /**
+   * Specify the rate to send pulses.
+   *
+   * @param milliSec The rate to send out pulses at
+   */
+  public void setRate(int milliSec) {
+    m_milliSec = milliSec;
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/mockhardware/FakeEncoderSource.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/mockhardware/FakeEncoderSource.java
new file mode 100644
index 0000000..742bdac
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/mockhardware/FakeEncoderSource.java
@@ -0,0 +1,179 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2014-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.mockhardware;
+
+import edu.wpi.first.wpilibj.DigitalOutput;
+import edu.wpi.first.wpilibj.Timer;
+
+/**
+ * Emulates a quadrature encoder.
+ */
+public class FakeEncoderSource {
+  private Thread m_task;
+  private int m_count;
+  private int m_milliSec;
+  private boolean m_forward;
+  private final DigitalOutput m_outputA;
+  private final DigitalOutput m_outputB;
+  private final boolean m_allocatedOutputs;
+
+  /**
+   * Thread object that allows emulation of a quadrature encoder.
+   */
+  private class QuadEncoderThread extends Thread {
+    FakeEncoderSource m_encoder;
+
+    QuadEncoderThread(FakeEncoderSource encode) {
+      m_encoder = encode;
+    }
+
+    public void run() {
+
+      final DigitalOutput lead;
+      final DigitalOutput lag;
+
+      m_encoder.m_outputA.set(false);
+      m_encoder.m_outputB.set(false);
+
+      if (m_encoder.isForward()) {
+        lead = m_encoder.m_outputA;
+        lag = m_encoder.m_outputB;
+      } else {
+        lead = m_encoder.m_outputB;
+        lag = m_encoder.m_outputA;
+      }
+
+      try {
+        for (int i = 0; i < m_encoder.m_count; i++) {
+          lead.set(true);
+          Thread.sleep(m_encoder.m_milliSec);
+          lag.set(true);
+          Thread.sleep(m_encoder.m_milliSec);
+          lead.set(false);
+          Thread.sleep(m_encoder.m_milliSec);
+          lag.set(false);
+          Thread.sleep(m_encoder.m_milliSec);
+        }
+      } catch (InterruptedException ex) {
+        Thread.currentThread().interrupt();
+      }
+    }
+  }
+
+  /**
+   * Creates an encoder source using two ports.
+   *
+   * @param portA The A port
+   * @param portB The B port
+   */
+  public FakeEncoderSource(int portA, int portB) {
+    m_outputA = new DigitalOutput(portA);
+    m_outputB = new DigitalOutput(portB);
+    m_allocatedOutputs = true;
+    initQuadEncoder();
+  }
+
+  /**
+   * Creates the fake encoder using two digital outputs.
+   *
+   * @param outputA The A digital output
+   * @param outputB The B digital output
+   */
+  public FakeEncoderSource(DigitalOutput outputA, DigitalOutput outputB) {
+    m_outputA = outputA;
+    m_outputB = outputB;
+    m_allocatedOutputs = false;
+    initQuadEncoder();
+  }
+
+  /**
+   * Frees the resource.
+   */
+  public void free() {
+    m_task = null;
+    if (m_allocatedOutputs) {
+      m_outputA.free();
+      m_outputB.free();
+    }
+  }
+
+  /**
+   * Common initialization code.
+   */
+  private void initQuadEncoder() {
+    m_milliSec = 1;
+    m_forward = true;
+    m_task = new QuadEncoderThread(this);
+    m_outputA.set(false);
+    m_outputB.set(false);
+  }
+
+  /**
+   * Starts the thread.
+   */
+  public void start() {
+    m_task.start();
+  }
+
+  /**
+   * Waits for thread to end.
+   */
+  public void complete() {
+    try {
+      m_task.join();
+    } catch (InterruptedException ex) {
+      Thread.currentThread().interrupt();
+    }
+    m_task = new QuadEncoderThread(this);
+    Timer.delay(.01);
+  }
+
+  /**
+   * Runs and waits for thread to end before returning.
+   */
+  public void execute() {
+    start();
+    complete();
+  }
+
+  /**
+   * Rate of pulses to send.
+   *
+   * @param milliSec Pulse Rate
+   */
+  public void setRate(int milliSec) {
+    m_milliSec = milliSec;
+  }
+
+  /**
+   * Set the number of pulses to simulate.
+   *
+   * @param count Pulse count
+   */
+  public void setCount(int count) {
+    m_count = Math.abs(count);
+  }
+
+  /**
+   * Set which direction the encoder simulates motion in.
+   *
+   * @param isForward Whether to simulate forward motion
+   */
+  public void setForward(boolean isForward) {
+    m_forward = isForward;
+  }
+
+  /**
+   * Accesses whether the encoder is simulating forward motion.
+   *
+   * @return Whether the simulated motion is in the forward direction
+   */
+  public boolean isForward() {
+    return m_forward;
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/mockhardware/FakePotentiometerSource.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/mockhardware/FakePotentiometerSource.java
new file mode 100644
index 0000000..397baa8
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/mockhardware/FakePotentiometerSource.java
@@ -0,0 +1,93 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.mockhardware;
+
+import edu.wpi.first.wpilibj.AnalogOutput;
+
+/**
+ * A fake source to provide output to a {@link edu.wpi.first.wpilibj.interfaces.Potentiometer}.
+ */
+public class FakePotentiometerSource {
+  private AnalogOutput m_output;
+  private boolean m_initOutput;
+  private double m_potMaxAngle;
+  private double m_potMaxVoltage = 5.0;
+  private final double m_defaultPotMaxAngle;
+
+  /**
+   * Constructs the fake source.
+   *
+   * @param output             The analog port to output the signal on
+   * @param defaultPotMaxAngle The default maximum angle the pot supports.
+   */
+  public FakePotentiometerSource(AnalogOutput output, double defaultPotMaxAngle) {
+    m_defaultPotMaxAngle = defaultPotMaxAngle;
+    m_potMaxAngle = defaultPotMaxAngle;
+    m_output = output;
+    m_initOutput = false;
+  }
+
+  public FakePotentiometerSource(int port, double defaultPotMaxAngle) {
+    this(new AnalogOutput(port), defaultPotMaxAngle);
+    m_initOutput = true;
+  }
+
+  /**
+   * Sets the maximum voltage output. If not the default is 5.0V.
+   *
+   * @param voltage The voltage that indicates that the pot is at the max value.
+   */
+  public void setMaxVoltage(double voltage) {
+    m_potMaxVoltage = voltage;
+  }
+
+  public void setRange(double range) {
+    m_potMaxAngle = range;
+  }
+
+  public void reset() {
+    m_potMaxAngle = m_defaultPotMaxAngle;
+    m_output.setVoltage(0.0);
+  }
+
+  public void setAngle(double angle) {
+    m_output.setVoltage((m_potMaxVoltage / m_potMaxAngle) * angle);
+  }
+
+  public void setVoltage(double voltage) {
+    m_output.setVoltage(voltage);
+  }
+
+  public double getVoltage() {
+    return m_output.getVoltage();
+  }
+
+  /**
+   * Returns the currently set angle.
+   *
+   * @return the current angle
+   */
+  public double getAngle() {
+    double voltage = m_output.getVoltage();
+    if (voltage == 0) { // Removes divide by zero error
+      return 0;
+    }
+    return voltage * (m_potMaxAngle / m_potMaxVoltage);
+  }
+
+  /**
+   * Frees the resouce.
+   */
+  public void free() {
+    if (m_initOutput) {
+      m_output.free();
+      m_output = null;
+      m_initOutput = false;
+    }
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/smartdashboard/SmartDashboardTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/smartdashboard/SmartDashboardTest.java
new file mode 100644
index 0000000..af58e6a
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/smartdashboard/SmartDashboardTest.java
@@ -0,0 +1,88 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.smartdashboard;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.networktables.NetworkTable;
+import edu.wpi.first.wpilibj.test.AbstractComsSetup;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test that covers {@link SmartDashboard}.
+ */
+public class SmartDashboardTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(SmartDashboardTest.class.getName());
+  private static final NetworkTable table = NetworkTable.getTable("SmartDashboard");
+
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+  @Test
+  public void testGetBadValue() {
+    assertEquals("", SmartDashboard.getString("_404_STRING_KEY_SHOULD_NOT_BE_FOUND_", ""));
+  }
+
+  @Test
+  public void testPutString() {
+    String key = "testPutString";
+    String value = "thisIsAValue";
+    SmartDashboard.putString(key, value);
+    assertEquals(value, SmartDashboard.getString(key, ""));
+    assertEquals(value, table.getString(key, ""));
+  }
+
+  @Test
+  public void testPutNumber() {
+    String key = "testPutNumber";
+    int value = 2147483647;
+    SmartDashboard.putNumber(key, value);
+    assertEquals(value, SmartDashboard.getNumber(key, 0), 0.01);
+    assertEquals(value, table.getNumber(key, 0), 0.01);
+  }
+
+  @Test
+  public void testPutBoolean() {
+    String key = "testPutBoolean";
+    boolean value = true;
+    SmartDashboard.putBoolean(key, value);
+    assertEquals(value, SmartDashboard.getBoolean(key, !value));
+    assertEquals(value, table.getBoolean(key, false));
+  }
+
+  @Test
+  public void testReplaceString() {
+    String key = "testReplaceString";
+    String valueOld = "oldValue";
+    SmartDashboard.putString(key, valueOld);
+    assertEquals(valueOld, SmartDashboard.getString(key, ""));
+    assertEquals(valueOld, table.getString(key, ""));
+
+    String valueNew = "newValue";
+    SmartDashboard.putString(key, valueNew);
+    assertEquals(valueNew, SmartDashboard.getString(key, ""));
+    assertEquals(valueNew, table.getString(key, ""));
+  }
+
+  @Ignore
+  @Test(expected = IllegalArgumentException.class)
+  public void testPutStringNullKey() {
+    SmartDashboard.putString(null, "This should not work");
+  }
+
+  @Ignore
+  @Test(expected = IllegalArgumentException.class)
+  public void testPutStringNullValue() {
+    SmartDashboard.putString("KEY_SHOULD_NOT_BE_STORED", null);
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/smartdashboard/SmartDashboardTestSuite.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/smartdashboard/SmartDashboardTestSuite.java
new file mode 100644
index 0000000..d3e475e
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/smartdashboard/SmartDashboardTestSuite.java
@@ -0,0 +1,22 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.smartdashboard;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+import edu.wpi.first.wpilibj.test.AbstractTestSuite;
+
+/**
+ * All tests pertaining to {@link SmartDashboard}.
+ */
+@RunWith(Suite.class)
+@SuiteClasses({SmartDashboardTest.class})
+public class SmartDashboardTestSuite extends AbstractTestSuite {
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/AbstractComsSetup.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/AbstractComsSetup.java
new file mode 100644
index 0000000..d999df7
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/AbstractComsSetup.java
@@ -0,0 +1,246 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.test;
+
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+import org.junit.runners.model.MultipleFailureException;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import edu.wpi.first.wpilibj.DriverStation;
+import edu.wpi.first.wpilibj.MockDS;
+import edu.wpi.first.wpilibj.RobotBase;
+import edu.wpi.first.wpilibj.Timer;
+import edu.wpi.first.wpilibj.hal.HAL;
+import edu.wpi.first.wpilibj.livewindow.LiveWindow;
+
+/**
+ * This class serves as a superclass for all tests that involve the hardware on the roboRIO. It uses
+ * an {@link BeforeClass} statement to initialize network communications. Any test that needs to use
+ * the hardware <b>MUST</b> extend from this class, to ensure that all of the hardware will be able
+ * to run.
+ */
+public abstract class AbstractComsSetup {
+  /**
+   * Stores whether network coms have been initialized.
+   */
+  private static boolean initialized = false;
+
+  // We have no way to stop the MockDS, so its thread is daemon.
+  private static  MockDS ds;
+
+  /**
+   * This sets up the network communications library to enable the driver
+   * station. After starting network coms, it will loop until the driver station
+   * returns that the robot is enabled, to ensure that tests will be able to run
+   * on the hardware.
+   */
+  static {
+    if (!initialized) {
+      try {
+        // Set some implementations so that the static methods work properly
+        RobotBase.initializeHardwareConfiguration();
+        HAL.observeUserProgramStarting();
+        DriverStation.getInstance().getAlliance();
+
+        ds = new MockDS();
+        ds.start();
+
+        LiveWindow.setEnabled(false);
+        TestBench.out().println("Started coms");
+      } catch (Exception ex) {
+        TestBench.out().println("Exception during AbstractComsSetup initialization: " + ex);
+        ex.printStackTrace(TestBench.out());
+        throw ex;
+      }
+
+      // Wait until the robot is enabled before starting the tests
+      int enableCounter = 0;
+      while (!DriverStation.getInstance().isEnabled()) {
+        if (enableCounter > 50) {
+          // Robot did not enable properly after 5 seconds.
+          // Force exit
+          TestBench.err().println("Failed to enable. Aborting");
+          System.exit(1);
+        }
+        try {
+          Thread.sleep(100);
+        } catch (InterruptedException ex) {
+          ex.printStackTrace();
+        }
+        TestBench.out().println("Waiting for enable: " + enableCounter++);
+      }
+      TestBench.out().println();
+
+      // Ready to go!
+      initialized = true;
+      TestBench.out().println("Running!");
+    }
+  }
+
+
+  protected abstract Logger getClassLogger();
+
+  /**
+   * This causes a stack trace to be printed as the test is running as well as at the end.
+   */
+  @Rule
+  public final TestWatcher getTestWatcher() {
+    return getOverridenTestWatcher();
+  }
+
+  /**
+   * Given as a way to provide a custom test watcher for a test or set of tests.
+   *
+   * @return the test watcher to use
+   */
+  protected TestWatcher getOverridenTestWatcher() {
+    return new DefaultTestWatcher();
+  }
+
+  protected class DefaultTestWatcher extends TestWatcher {
+    /**
+     * Allows a failure to supply a custom status message to be displayed along with the stack
+     * trace.
+     */
+    protected void failed(Throwable throwable, Description description, String status) {
+      TestBench.out().println();
+      // Instance of is the best way I know to retrieve this data.
+      if (throwable instanceof MultipleFailureException) {
+        /*
+         * MultipleFailureExceptions hold multiple exceptions in one exception.
+         * In order to properly display these stack traces we have to cast the
+         * throwable and work with the list of thrown exceptions stored within
+         * it.
+         */
+        int exceptionCount = 1; // Running exception count
+        int failureCount = ((MultipleFailureException) throwable).getFailures().size();
+        for (Throwable singleThrown : ((MultipleFailureException) throwable).getFailures()) {
+          getClassLogger().logp(
+              Level.SEVERE,
+              description.getClassName(),
+              description.getMethodName(),
+              (exceptionCount++) + "/" + failureCount + " " + description.getDisplayName() + " "
+                  + "failed " + singleThrown.getMessage() + "\n" + status, singleThrown);
+        }
+
+      } else {
+        getClassLogger().logp(Level.SEVERE, description.getClassName(),
+            description.getMethodName(),
+            description.getDisplayName() + " failed " + throwable.getMessage() + "\n" + status,
+            throwable);
+      }
+      super.failed(throwable, description);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.junit.rules.TestWatcher#failed(java.lang.Throwable,
+     * org.junit.runner.Description)
+     */
+    @Override
+    protected void failed(Throwable exception, Description description) {
+      failed(exception, description, "");
+    }
+
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.junit.rules.TestWatcher#starting(org.junit.runner.Description)
+     */
+    @Override
+    protected void starting(Description description) {
+      TestBench.out().println();
+      // Wait until the robot is enabled before starting the next tests
+      int enableCounter = 0;
+      while (!DriverStation.getInstance().isEnabled()) {
+        try {
+          Thread.sleep(100);
+        } catch (InterruptedException ex) {
+          ex.printStackTrace();
+        }
+        // Prints the message on one line overwriting itself each time
+        TestBench.out().print("\rWaiting for enable: " + enableCounter++);
+      }
+      getClassLogger().logp(Level.INFO, description.getClassName(), description.getMethodName(),
+          "Starting");
+      super.starting(description);
+    }
+
+    @Override
+    protected void succeeded(Description description) {
+      simpleLog(Level.INFO, "TEST PASSED!");
+      super.succeeded(description);
+    }
+
+  }
+
+  /**
+   * Logs a simple message without the logger formatting associated with it.
+   *
+   * @param level   The level to log the message at
+   * @param message The message to log
+   */
+  protected void simpleLog(Level level, String message) {
+    if (getClassLogger().isLoggable(level)) {
+      TestBench.out().println(message);
+    }
+  }
+
+  /**
+   * Provided as a replacement to lambda functions to allow for repeatable checks to see if a
+   * correct state is reached.
+   */
+  public abstract class BooleanCheck {
+    public BooleanCheck() {
+    }
+
+    /**
+     * Runs the enclosed code and evaluates it to determine what state it should return.
+     *
+     * @return true if the code provided within the method returns true
+     */
+    public abstract boolean getAsBoolean();
+  }
+
+  /**
+   * Delays until either the correct state is reached or we reach the timeout.
+   *
+   * @param level        The level to log the message at.
+   * @param timeout      How long the delay should run before it should timeout and allow the test
+   *                     to continue
+   * @param message      The message to accompany the delay. The message will display 'message' took
+   *                     'timeout' seconds if it passed.
+   * @param correctState A method to determine if the test has reached a state where it is valid to
+   *                     continue
+   * @return a double representing how long the delay took to run in seconds.
+   */
+  public double delayTillInCorrectStateWithMessage(Level level, double timeout, String message,
+                                                   BooleanCheck correctState) {
+    int timeoutIndex;
+    // As long as we are not in the correct state and the timeout has not been
+    // reached then continue to run this loop
+    for (timeoutIndex = 0; timeoutIndex < (timeout * 100) && !correctState.getAsBoolean();
+         timeoutIndex++) {
+      Timer.delay(.01);
+    }
+    if (correctState.getAsBoolean()) {
+      simpleLog(level, message + " took " + (timeoutIndex * .01) + " seconds");
+    } else {
+      simpleLog(level, message + " timed out after " + (timeoutIndex * .01) + " seconds");
+    }
+    return timeoutIndex * .01;
+  }
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/AbstractTestSuite.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/AbstractTestSuite.java
new file mode 100644
index 0000000..794d0e4
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/AbstractTestSuite.java
@@ -0,0 +1,257 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.test;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.Request;
+import org.junit.runners.Suite.SuiteClasses;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+/**
+ * Allows tests suites and tests to be run selectively from the command line using a regex text
+ * pattern.
+ */
+public abstract class AbstractTestSuite {
+  private static final Logger logger = Logger.getLogger(AbstractTestSuite.class.getName());
+
+  /**
+   * Gets all of the classes listed within the SuiteClasses annotation. To use it, annotate a class
+   * with <code>@RunWith(Suite.class)</code> and <code>@SuiteClasses({TestClass1.class,
+   * ...})</code>. When you run this class, it will run all the tests in all the suite classes. When
+   * loading the tests using regex the test list will be generated from this annotation.
+   *
+   * @return the list of classes listed in the <code>@SuiteClasses({TestClass1.class, ...})</code>.
+   * @throws RuntimeException If the <code>@SuiteClasses</code> annotation is missing.
+   */
+  protected List<Class<?>> getAnnotatedTestClasses() {
+    SuiteClasses annotation = getClass().getAnnotation(SuiteClasses.class);
+    List<Class<?>> classes = new Vector<Class<?>>();
+    if (annotation == null) {
+      throw new RuntimeException(String.format("class '%s' must have a SuiteClasses annotation",
+          getClass().getName()));
+    }
+    for (Class<?> c : annotation.value()) {
+      classes.add(c);
+    }
+    return classes;
+  }
+
+  private boolean areAnySuperClassesOfTypeAbstractTestSuite(Class<?> check) {
+    while (check != null) {
+      if (check.equals(AbstractTestSuite.class)) {
+        return true;
+      }
+      check = check.getSuperclass();
+    }
+    return false;
+  }
+
+  /**
+   * Stores a method name and method class pair. Used when searching for methods matching a given
+   * regex text.
+   */
+  protected class ClassMethodPair {
+    public final Class<?> m_methodClass;
+    public final String m_methodName;
+
+    public ClassMethodPair(Class<?> klass, Method method) {
+      m_methodClass = klass;
+      m_methodName = method.getName();
+    }
+
+    public Request getMethodRunRequest() {
+      return Request.method(m_methodClass, m_methodName);
+    }
+  }
+
+  protected List<ClassMethodPair> getMethodMatching(final String regex) {
+    List<ClassMethodPair> classMethodPairs = new Vector<ClassMethodPair>();
+    // Get all of the test classes
+    for (Class<?> c : getAllContainedBaseTests()) {
+      for (Method m : c.getMethods()) {
+        // If this is a test method that is not trying to be ignored and it
+        // matches the regex
+        if (m.getAnnotation(Test.class) != null && m.getAnnotation(Ignore.class) == null
+            && Pattern.matches(regex, m.getName())) {
+          ClassMethodPair pair = new ClassMethodPair(c, m);
+          classMethodPairs.add(pair);
+        }
+      }
+    }
+    return classMethodPairs;
+  }
+
+
+  /**
+   * Gets all of the test classes listed in this suite. Does not include any of the test suites. All
+   * of these classes contain tests.
+   *
+   * @param runningList the running list of classes to prevent recursion.
+   * @return The list of base test classes.
+   */
+  private List<Class<?>> getAllContainedBaseTests(List<Class<?>> runningList) {
+    for (Class<?> c : getAnnotatedTestClasses()) {
+      // Check to see if this is a test class or a suite
+      if (areAnySuperClassesOfTypeAbstractTestSuite(c)) {
+        // Create a new instance of this class so that we can retrieve its data
+        try {
+          AbstractTestSuite suite = (AbstractTestSuite) c.newInstance();
+          // Add the tests from this suite that match the regex to the list of
+          // tests to run
+          runningList = suite.getAllContainedBaseTests(runningList);
+        } catch (InstantiationException | IllegalAccessException ex) {
+          // This shouldn't happen unless the constructor is changed in some
+          // way.
+          logger.log(Level.SEVERE, "Test suites can not take paramaters in their constructors.",
+              ex);
+        }
+      } else if (c.getAnnotation(SuiteClasses.class) != null) {
+        logger.log(Level.SEVERE,
+            String.format("class '%s' must extend %s to be searchable using regex.",
+                c.getName(), AbstractTestSuite.class.getName()));
+      } else { // This is a class containing tests
+        // so add it to the list
+        runningList.add(c);
+      }
+    }
+    return runningList;
+  }
+
+  /**
+   * Gets all of the test classes listed in this suite. Does not include any of the test suites. All
+   * of these classes contain tests.
+   *
+   * @return The list of base test classes.
+   */
+  public List<Class<?>> getAllContainedBaseTests() {
+    List<Class<?>> runningBaseTests = new Vector<Class<?>>();
+    return getAllContainedBaseTests(runningBaseTests);
+  }
+
+
+  /**
+   * Retrieves all of the classes listed in the <code>@SuiteClasses</code> annotation that match the
+   * given regex text.
+   *
+   * @param regex       the text pattern to retrieve.
+   * @param runningList the running list of classes to prevent recursion
+   * @return The list of classes matching the regex pattern
+   */
+  private List<Class<?>> getAllClassMatching(final String regex, final List<Class<?>> runningList) {
+    for (Class<?> c : getAnnotatedTestClasses()) {
+      // Compare the regex against the simple name of the class
+      if (Pattern.matches(regex, c.getName()) && !runningList.contains(c)) {
+        runningList.add(c);
+      }
+    }
+    return runningList;
+  }
+
+  /**
+   * Retrieves all of the classes listed in the <code>@SuiteClasses</code> annotation that match the
+   * given regex text.
+   *
+   * @param regex the text pattern to retrieve.
+   * @return The list of classes matching the regex pattern
+   */
+  public List<Class<?>> getAllClassMatching(final String regex) {
+    final List<Class<?>> matchingClasses = new Vector<Class<?>>();
+    return getAllClassMatching(regex, matchingClasses);
+  }
+
+  /**
+   * Searches through all of the suites and tests and loads only the test or test suites matching
+   * the regex text. This method also prevents a single test from being loaded multiple times by
+   * loading the suite first then loading tests from all non loaded suites.
+   *
+   * @param regex the regex text to search for
+   * @return the list of suite and/or test classes matching the regex.
+   */
+  private List<Class<?>> getSuiteOrTestMatchingRegex(final String regex, List<Class<?>>
+      runningList) {
+    // Get any test suites matching the regex using the superclass methods
+    runningList = getAllClassMatching(regex, runningList);
+
+
+    // Then search any test suites not retrieved already for test classes
+    // matching the regex.
+    List<Class<?>> unCollectedSuites = getAllClasses();
+    // If we already have a test suite then we don't want to load the test twice
+    // so remove the suite from the list
+    unCollectedSuites.removeAll(runningList);
+    for (Class<?> c : unCollectedSuites) {
+      // Prevents recursively adding tests/suites that have already been added
+      if (!runningList.contains(c)) {
+        try {
+          final AbstractTestSuite suite;
+          // Check the class to make sure that it is not a test class
+          if (areAnySuperClassesOfTypeAbstractTestSuite(c)) {
+            // Create a new instance of this class so that we can retrieve its
+            // data.
+            suite = (AbstractTestSuite) c.newInstance();
+            // Add the tests from this suite that match the regex to the list of
+            // tests to run
+            runningList = suite.getSuiteOrTestMatchingRegex(regex, runningList);
+          }
+
+        } catch (InstantiationException | IllegalAccessException ex) {
+          // This shouldn't happen unless the constructor is changed in some
+          // way.
+          logger.log(Level.SEVERE, "Test suites can not take paramaters in their constructors.",
+              ex);
+        }
+      }
+    }
+    return runningList;
+  }
+
+  /**
+   * Searches through all of the suites and tests and loads only the test or test suites matching
+   * the regex text. This method also prevents a single test from being loaded multiple times by
+   * loading the suite first then loading tests from all non loaded suites.
+   *
+   * @param regex the regex text to search for
+   * @return the list of suite and/or test classes matching the regex.
+   */
+  protected List<Class<?>> getSuiteOrTestMatchingRegex(final String regex) {
+    final List<Class<?>> matchingClasses = new Vector<Class<?>>();
+    return getSuiteOrTestMatchingRegex(regex, matchingClasses);
+  }
+
+
+  /**
+   * Retrieves all of the classes listed in the <code>@SuiteClasses</code> annotation.
+   *
+   * @return List of SuiteClasses
+   * @throws RuntimeException If the <code>@SuiteClasses</code> annotation is missing.
+   */
+  public List<Class<?>> getAllClasses() {
+    return getAnnotatedTestClasses();
+  }
+
+  /**
+   * Gets the name of all of the classes listed within the <code>@SuiteClasses</code> annotation.
+   *
+   * @return the list of classes.
+   * @throws RuntimeException If the <code>@SuiteClasses</code> annotation is missing.
+   */
+  public List<String> getAllClassName() {
+    List<String> classNames = new Vector<String>();
+    for (Class<?> c : getAnnotatedTestClasses()) {
+      classNames.add(c.getName());
+    }
+    return classNames;
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/AbstractTestSuiteTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/AbstractTestSuiteTest.java
new file mode 100644
index 0000000..d3ece6e
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/AbstractTestSuiteTest.java
@@ -0,0 +1,155 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.test;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+import org.junit.runners.model.InitializationError;
+
+import java.util.List;
+
+import edu.wpi.first.wpilibj.test.AbstractTestSuite.ClassMethodPair;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasItems;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Yes, this is the test system testing itself. Functionally, this is making sure that all tests get
+ * run correctly when you use parametrized arguments.
+ */
+@SuppressWarnings("MultipleTopLevelClasses")
+public class AbstractTestSuiteTest {
+  @Ignore("Prevents ANT from trying to run these as tests")
+  @RunWith(Suite.class)
+  @SuiteClasses({FirstSampleTest.class, SecondSampleTest.class, ThirdSampleTest.class,
+      FourthSampleTest.class, UnusualTest.class, ExampleSubSuite.class, EmptySuite.class})
+  class TestForAbstractTestSuite extends AbstractTestSuite {
+  }
+
+  TestForAbstractTestSuite m_testSuite;
+
+  @Before
+  public void setUp() throws Exception {
+    m_testSuite = new TestForAbstractTestSuite();
+  }
+
+  @Test
+  public void testGetTestsMatchingAll() throws InitializationError {
+    // when
+    List<Class<?>> collectedTests = m_testSuite.getAllClassMatching(".*");
+    // then
+    assertEquals(7, collectedTests.size());
+  }
+
+  @Test
+  public void testGetTestsMatchingSample() throws InitializationError {
+    // when
+    List<Class<?>> collectedTests = m_testSuite.getAllClassMatching(".*Sample.*");
+    // then
+    assertEquals(4, collectedTests.size());
+  }
+
+  @Test
+  public void testGetTestsMatchingUnusual() throws InitializationError {
+    // when
+    List<Class<?>> collectedTests = m_testSuite.getAllClassMatching(".*Unusual.*");
+    // then
+    assertEquals(1, collectedTests.size());
+    assertEquals(UnusualTest.class, collectedTests.get(0));
+  }
+
+  @Test
+  public void testGetTestsFromSuiteMatchingAll() throws InitializationError {
+    // when
+    List<Class<?>> collectedTests = m_testSuite.getSuiteOrTestMatchingRegex(".*");
+    // then
+    assertEquals(7, collectedTests.size());
+  }
+
+  @Test
+  public void testGetTestsFromSuiteMatchingTest() throws InitializationError {
+    // when
+    List<Class<?>> collectedTests = m_testSuite.getSuiteOrTestMatchingRegex(".*Test.*");
+    // then
+    assertEquals(7, collectedTests.size());
+    assertThat(collectedTests, hasItems(FirstSubSuiteTest.class,
+        SecondSubSuiteTest.class, UnusualTest.class));
+    assertThat(collectedTests,
+        not(hasItems(new Class<?>[]{ExampleSubSuite.class, EmptySuite.class})));
+  }
+
+  @Test
+  public void testGetMethodFromTest() {
+    // when
+    List<ClassMethodPair> pairs = m_testSuite.getMethodMatching(".*Method.*");
+    // then
+    assertEquals(1, pairs.size());
+    assertEquals(FirstSubSuiteTest.class, pairs.get(0).m_methodClass);
+    assertEquals(FirstSubSuiteTest.METHODNAME, pairs.get(0).m_methodName);
+
+  }
+
+}
+
+@SuppressWarnings("OneTopLevelClass")
+class FirstSampleTest {
+}
+
+@SuppressWarnings("OneTopLevelClass")
+class SecondSampleTest {
+}
+
+@SuppressWarnings("OneTopLevelClass")
+class ThirdSampleTest {
+}
+
+@SuppressWarnings("OneTopLevelClass")
+class FourthSampleTest {
+}
+
+@SuppressWarnings("OneTopLevelClass")
+class UnusualTest {
+} // This is a member of both suites
+
+
+@Ignore("Prevents ANT from trying to run these as tests")
+@SuppressWarnings("OneTopLevelClass")
+class FirstSubSuiteTest {
+  public static final String METHODNAME = "aTestMethod";
+
+  @Test
+  @SuppressWarnings("MethodName")
+  public void aTestMethod() {
+  }
+}
+
+@SuppressWarnings("OneTopLevelClass")
+class SecondSubSuiteTest {
+}
+
+
+@RunWith(Suite.class)
+@SuiteClasses({FirstSubSuiteTest.class, SecondSubSuiteTest.class, UnusualTest.class})
+@Ignore("Prevents ANT from trying to run these as tests")
+@SuppressWarnings("OneTopLevelClass")
+class ExampleSubSuite extends AbstractTestSuite {
+}
+
+
+@Ignore("Prevents ANT from trying to run these as tests")
+@RunWith(Suite.class)
+@SuiteClasses({})
+@SuppressWarnings("OneTopLevelClass")
+class EmptySuite extends AbstractTestSuite {
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/AntJunitLanucher.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/AntJunitLanucher.java
new file mode 100644
index 0000000..77ed801
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/AntJunitLanucher.java
@@ -0,0 +1,91 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.test;
+
+import org.apache.tools.ant.BuildLogger;
+import org.apache.tools.ant.DefaultLogger;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.optional.junit.FormatterElement;
+import org.apache.tools.ant.taskdefs.optional.junit.JUnitTask;
+import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest;
+
+import java.io.File;
+
+/**
+ * Provides an entry point for tests to run with ANT. This allows ant to output JUnit XML test
+ * results for Jenkins.
+ */
+public class AntJunitLanucher {
+  /**
+   * Main entry point for jenkins.
+   *
+   * @param args Arguments passed to java.
+   */
+  public static void main(String... args) {
+    if (args.length == 0) {
+      String path =
+          String.format("%s/%s", System.getProperty("user.dir"), "/testResults/AntReports");
+      String pathToReports = path;
+      Project project = new Project();
+
+      try {
+        // Create the file to store the test output
+        new File(pathToReports).mkdirs();
+
+        project.setProperty("java.io.tmpdir", pathToReports);
+
+        /* Output to screen */
+        FormatterElement.TypeAttribute typeScreen = new FormatterElement.TypeAttribute();
+        typeScreen.setValue("plain");
+        FormatterElement formatToScreen = new FormatterElement();
+        formatToScreen.setType(typeScreen);
+        formatToScreen.setUseFile(false);
+        formatToScreen.setOutput(System.out);
+
+        JUnitTask task = new JUnitTask();
+        task.addFormatter(formatToScreen);
+
+        // add a build listener to the project
+        BuildLogger logger = new DefaultLogger();
+        logger.setOutputPrintStream(System.out);
+        logger.setErrorPrintStream(System.err);
+        logger.setMessageOutputLevel(Project.MSG_INFO);
+        logger.setEmacsMode(true);
+        project.addBuildListener(logger);
+
+        task.setProject(project);
+
+        // Set the output to the XML file
+        FormatterElement.TypeAttribute type = new FormatterElement.TypeAttribute();
+        type.setValue("xml");
+
+        FormatterElement formater = new FormatterElement();
+        formater.setType(type);
+        task.addFormatter(formater);
+
+        // Create the JUnitTest
+        JUnitTest test = new JUnitTest(TestSuite.class.getName());
+        test.setTodir(new File(pathToReports));
+        task.addTest(test);
+
+        TestBench.out().println("Beginning Test Execution With ANT");
+        task.execute();
+      } catch (Exception ex) {
+        ex.printStackTrace();
+      }
+    } else {
+      TestBench.out().println(
+          "Run will not output XML for Jenkins because " + "tests are not being run with ANT");
+      // This should never return as it makes its own call to
+      // System.exit();
+      TestSuite.main(args);
+    }
+    System.exit(0);
+  }
+
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/QuickTest.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/QuickTest.java
new file mode 100644
index 0000000..05953be
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/QuickTest.java
@@ -0,0 +1,38 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.test;
+
+import org.junit.Test;
+
+import java.util.logging.Logger;
+
+/**
+ * This class is designated to allow for simple testing of the library without the overlying testing
+ * framework. This test is NOT run as a normal part of the testing process and must be explicitly
+ * selected at runtime by using the 'quick' argument. This test should never be committed with
+ * changes to it but can be used during development to aid in feature testing.
+ */
+public class QuickTest extends AbstractComsSetup {
+  private static final Logger logger = Logger.getLogger(QuickTest.class.getName());
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see edu.wpi.first.wpilibj.test.AbstractComsSetup#getClassLogger()
+   */
+  @Override
+  protected Logger getClassLogger() {
+    return logger;
+  }
+
+
+  @Test
+  public void test() {
+
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/RepeatRule.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/RepeatRule.java
new file mode 100644
index 0000000..5e987d6
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/RepeatRule.java
@@ -0,0 +1,65 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.test;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This JUnit Rule allows you to apply this rule to any test to allow it to run multiple times. This
+ * is important if you have a test that fails only "sometimes" and needs to be rerun to find the
+ * issue.
+ *
+ * <p>This code was originally found here:
+ * <a href="http://www.codeaffine.com/2013/04/10/running-junit-tests-repeatedly-without-loops/">
+ * Running JUnit Tests Repeatedly Without Loops</a>
+ */
+public class RepeatRule implements TestRule {
+  @Retention(RetentionPolicy.RUNTIME)
+  @Target({java.lang.annotation.ElementType.METHOD})
+  public @interface Repeat {
+    /**
+     * The number of times to repeat the test.
+     */
+    int times();
+  }
+
+
+  private static class RepeatStatement extends Statement {
+    private final int m_times;
+    private final Statement m_statement;
+
+    private RepeatStatement(int times, Statement statement) {
+      m_times = times;
+      m_statement = statement;
+    }
+
+    @Override
+    public void evaluate() throws Throwable {
+      for (int i = 0; i < m_times; i++) {
+        m_statement.evaluate();
+      }
+    }
+  }
+
+  @Override
+  public Statement apply(Statement statement, Description description) {
+    Statement result = statement;
+    Repeat repeat = description.getAnnotation(Repeat.class);
+    if (repeat != null) {
+      int times = repeat.times();
+      result = new RepeatStatement(times, statement);
+    }
+    return result;
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/TestBench.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/TestBench.java
new file mode 100644
index 0000000..0f63b0c
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/TestBench.java
@@ -0,0 +1,480 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.test;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import edu.wpi.first.wpilibj.AnalogGyro;
+import edu.wpi.first.wpilibj.AnalogInput;
+import edu.wpi.first.wpilibj.AnalogOutput;
+import edu.wpi.first.wpilibj.DigitalInput;
+import edu.wpi.first.wpilibj.Jaguar;
+import edu.wpi.first.wpilibj.PIDSource;
+import edu.wpi.first.wpilibj.Relay;
+import edu.wpi.first.wpilibj.Servo;
+import edu.wpi.first.wpilibj.Talon;
+import edu.wpi.first.wpilibj.Victor;
+import edu.wpi.first.wpilibj.filters.LinearDigitalFilter;
+import edu.wpi.first.wpilibj.fixtures.AnalogCrossConnectFixture;
+import edu.wpi.first.wpilibj.fixtures.DIOCrossConnectFixture;
+import edu.wpi.first.wpilibj.fixtures.FilterNoiseFixture;
+import edu.wpi.first.wpilibj.fixtures.FilterOutputFixture;
+import edu.wpi.first.wpilibj.fixtures.MotorEncoderFixture;
+import edu.wpi.first.wpilibj.fixtures.RelayCrossConnectFixture;
+import edu.wpi.first.wpilibj.fixtures.TiltPanCameraFixture;
+
+/**
+ * This class provides access to all of the elements on the test bench, for use in fixtures. This
+ * class is a singleton, you should use {@link #getInstance()} to obtain a reference to the {@code
+ * TestBench}.
+ */
+public final class TestBench {
+  /**
+   * The time that it takes to have a motor go from rotating at full speed to completely stopped.
+   */
+  public static final double MOTOR_STOP_TIME = 0.25;
+
+  public static final int kTalonChannel = 10;
+  public static final int kVictorChannel = 1;
+  public static final int kJaguarChannel = 2;
+
+  /* TiltPanCamera Channels */
+  public static final int kGyroChannel = 0;
+  public static final double kGyroSensitivity = 0.013;
+  public static final int kTiltServoChannel = 9;
+  public static final int kPanServoChannel = 8;
+
+
+  /* PowerDistributionPanel channels */
+  public static final int kJaguarPDPChannel = 6;
+  public static final int kVictorPDPChannel = 8;
+  public static final int kTalonPDPChannel = 10;
+
+  // THESE MUST BE IN INCREMENTING ORDER
+  public static final int DIOCrossConnectB2 = 9;
+  public static final int DIOCrossConnectB1 = 8;
+  public static final int DIOCrossConnectA2 = 7;
+  public static final int DIOCrossConnectA1 = 6;
+
+  // Filter constants
+  public static final double kStdDev = 10.0;
+  public static final double kFilterStep = 0.005;
+  public static final double kFilterTime = 2.0;
+  public static final double kSinglePoleIIRTimeConstant = 0.015915;
+  public static final double kSinglePoleIIRExpectedOutput = -3.2172003;
+  public static final double kHighPassTimeConstant = 0.006631;
+  public static final double kHighPassExpectedOutput = 10.074717;
+  public static final int kMovAvgTaps = 6;
+  public static final double kMovAvgExpectedOutput = -10.191644;
+
+  /**
+   * The Singleton instance of the Test Bench.
+   */
+  private static TestBench instance = null;
+
+  /**
+   * The single constructor for the TestBench. This method is private in order to prevent multiple
+   * TestBench objects from being allocated.
+   */
+  protected TestBench() {
+  }
+
+  /**
+   * Constructs a new set of objects representing a connected set of Talon controlled Motors and an
+   * encoder.
+   *
+   * @return a freshly allocated Talon, Encoder pair
+   */
+  public MotorEncoderFixture<Talon> getTalonPair() {
+
+    MotorEncoderFixture<Talon> talonPair = new MotorEncoderFixture<Talon>() {
+      @Override
+      protected Talon giveSpeedController() {
+        return new Talon(kTalonChannel);
+      }
+
+      @Override
+      protected DigitalInput giveDigitalInputA() {
+        return new DigitalInput(0);
+      }
+
+      @Override
+      protected DigitalInput giveDigitalInputB() {
+        return new DigitalInput(1);
+      }
+
+      @Override
+      public int getPDPChannel() {
+        return kTalonPDPChannel;
+      }
+    };
+    return talonPair;
+  }
+
+  /**
+   * Constructs a new set of objects representing a connected set of Victor controlled Motors and an
+   * encoder.
+   *
+   * @return a freshly allocated Victor, Encoder pair
+   */
+  public MotorEncoderFixture<Victor> getVictorPair() {
+
+    MotorEncoderFixture<Victor> vicPair = new MotorEncoderFixture<Victor>() {
+      @Override
+      protected Victor giveSpeedController() {
+        return new Victor(kVictorChannel);
+      }
+
+      @Override
+      protected DigitalInput giveDigitalInputA() {
+        return new DigitalInput(2);
+      }
+
+      @Override
+      protected DigitalInput giveDigitalInputB() {
+        return new DigitalInput(3);
+      }
+
+      @Override
+      public int getPDPChannel() {
+        return kVictorPDPChannel;
+      }
+    };
+    return vicPair;
+  }
+
+  /**
+   * Constructs a new set of objects representing a connected set of Jaguar controlled Motors and an
+   * encoder.
+   *
+   * @return a freshly allocated Jaguar, Encoder pair
+   */
+  public MotorEncoderFixture<Jaguar> getJaguarPair() {
+    MotorEncoderFixture<Jaguar> jagPair = new MotorEncoderFixture<Jaguar>() {
+      @Override
+      protected Jaguar giveSpeedController() {
+        return new Jaguar(kJaguarChannel);
+      }
+
+      @Override
+      protected DigitalInput giveDigitalInputA() {
+        return new DigitalInput(4);
+      }
+
+      @Override
+      protected DigitalInput giveDigitalInputB() {
+        return new DigitalInput(5);
+      }
+
+      @Override
+      public int getPDPChannel() {
+        return kJaguarPDPChannel;
+      }
+    };
+    return jagPair;
+  }
+
+  /**
+   * Constructs a new set of two Servo's and a Gyroscope.
+   *
+   * @return a freshly allocated Servo's and a freshly allocated Gyroscope
+   */
+  public TiltPanCameraFixture getTiltPanCam() {
+    TiltPanCameraFixture tpcam = new TiltPanCameraFixture() {
+      @Override
+      protected AnalogGyro giveGyro() {
+        AnalogGyro gyro = new AnalogGyro(kGyroChannel);
+        gyro.setSensitivity(kGyroSensitivity);
+        return gyro;
+      }
+
+      @Override
+      protected AnalogGyro giveGyroParam(int center, double offset) {
+        AnalogGyro gyro = new AnalogGyro(kGyroChannel, center, offset);
+        gyro.setSensitivity(kGyroSensitivity);
+        return gyro;
+      }
+
+      @Override
+      protected Servo giveTilt() {
+        return new Servo(kTiltServoChannel);
+      }
+
+      @Override
+      protected Servo givePan() {
+        return new Servo(kPanServoChannel);
+      }
+    };
+
+    return tpcam;
+  }
+
+  public DIOCrossConnectFixture getDIOCrossConnectFixture(int inputPort, int outputPort) {
+    DIOCrossConnectFixture dio = new DIOCrossConnectFixture(inputPort, outputPort);
+    return dio;
+  }
+
+  /**
+   * Gets two lists of possible DIO pairs for the two pairs.
+   */
+  private List<List<Integer[]>> getDIOCrossConnect() {
+    List<List<Integer[]>> pairs = new ArrayList<List<Integer[]>>();
+    List<Integer[]> setA =
+        Arrays.asList(new Integer[][]{
+            {new Integer(DIOCrossConnectA1), new Integer(DIOCrossConnectA2)},
+            {new Integer(DIOCrossConnectA2), new Integer(DIOCrossConnectA1)}});
+    pairs.add(setA);
+
+    List<Integer[]> setB =
+        Arrays.asList(new Integer[][]{
+            {new Integer(DIOCrossConnectB1), new Integer(DIOCrossConnectB2)},
+            {new Integer(DIOCrossConnectB2), new Integer(DIOCrossConnectB1)}});
+    pairs.add(setB);
+    // NOTE: IF MORE DIOCROSSCONNECT PAIRS ARE ADDED ADD THEM HERE
+    return pairs;
+  }
+
+  @SuppressWarnings("JavadocMethod")
+  public static AnalogCrossConnectFixture getAnalogCrossConnectFixture() {
+    AnalogCrossConnectFixture analogIO = new AnalogCrossConnectFixture() {
+      @Override
+      protected AnalogOutput giveAnalogOutput() {
+        return new AnalogOutput(0);
+      }
+
+      @Override
+      protected AnalogInput giveAnalogInput() {
+        return new AnalogInput(2);
+      }
+    };
+    return analogIO;
+  }
+
+  @SuppressWarnings("JavadocMethod")
+  public static RelayCrossConnectFixture getRelayCrossConnectFixture() {
+    RelayCrossConnectFixture relay = new RelayCrossConnectFixture() {
+
+      @Override
+      protected Relay giveRelay() {
+        return new Relay(0);
+      }
+
+      @Override
+      protected DigitalInput giveInputTwo() {
+        return new DigitalInput(18);
+      }
+
+      @Override
+      protected DigitalInput giveInputOne() {
+        return new DigitalInput(19);
+      }
+    };
+    return relay;
+  }
+
+  /**
+   * Return a single Collection containing all of the DIOCrossConnectFixtures in all two pair
+   * combinations.
+   *
+   * @return pairs of DIOCrossConnectFixtures
+   */
+  public Collection<Integer[]> getDIOCrossConnectCollection() {
+    Collection<Integer[]> pairs = new ArrayList<Integer[]>();
+    for (Collection<Integer[]> collection : getDIOCrossConnect()) {
+      pairs.addAll(collection);
+    }
+    return pairs;
+  }
+
+  /**
+   * Gets an array of pairs for the encoder to use using two different lists.
+   *
+   * @param flip whether this encoder needs to be flipped
+   * @return A list of different inputs to use for the tests
+   */
+  private Collection<Integer[]> getPairArray(List<Integer[]> listA, List<Integer[]> listB,
+                                             boolean flip) {
+    Collection<Integer[]> encoderPortPairs = new ArrayList<Integer[]>();
+    for (Integer[] portPairsA : listA) {
+      Integer[] inputs = new Integer[5];
+      inputs[0] = portPairsA[0]; // InputA
+      inputs[1] = portPairsA[1]; // InputB
+
+      for (Integer[] portPairsB : listB) {
+        inputs[2] = portPairsB[0]; // OutputA
+        inputs[3] = portPairsB[1]; // OutputB
+        inputs[4] = flip ? 0 : 1; // The flip bit
+      }
+
+      ArrayList<Integer[]> construtorInput = new ArrayList<Integer[]>();
+      construtorInput.add(inputs);
+
+      inputs = inputs.clone();
+      for (Integer[] portPairsB : listB) {
+        inputs[2] = portPairsB[1]; // OutputA
+        inputs[3] = portPairsB[0]; // OutputB
+        inputs[4] = flip ? 0 : 1; // The flip bit
+      }
+      construtorInput.add(inputs);
+      encoderPortPairs.addAll(construtorInput);
+    }
+    return encoderPortPairs;
+  }
+
+  /**
+   * Constructs the list of inputs to be used for the encoder test.
+   *
+   * @return A collection of different input pairs to use for the encoder
+   */
+  public Collection<Integer[]> getEncoderDIOCrossConnectCollection() {
+    Collection<Integer[]> encoderPortPairs = new ArrayList<Integer[]>();
+    assert getDIOCrossConnect().size() == 2;
+    encoderPortPairs.addAll(getPairArray(getDIOCrossConnect().get(0), getDIOCrossConnect().get(1),
+        false));
+    encoderPortPairs.addAll(getPairArray(getDIOCrossConnect().get(1), getDIOCrossConnect().get(0),
+        false));
+    assert encoderPortPairs.size() == 8;
+    return encoderPortPairs;
+  }
+
+  /**
+   * Constructs a new set of objects representing a single-pole IIR filter with a noisy data source.
+   *
+   * @return a single-pole IIR filter with a noisy data source
+   */
+  public FilterNoiseFixture<LinearDigitalFilter> getSinglePoleIIRNoiseFixture() {
+    return new FilterNoiseFixture<LinearDigitalFilter>() {
+      @Override
+      protected LinearDigitalFilter giveFilter(PIDSource source) {
+        return LinearDigitalFilter.singlePoleIIR(source,
+            kSinglePoleIIRTimeConstant,
+            kFilterStep);
+      }
+    };
+  }
+
+  /**
+   * Constructs a new set of objects representing a moving average filter with a noisy data source
+   * using a linear digital filter.
+   *
+   * @return a moving average filter with a noisy data source
+   */
+  public FilterNoiseFixture<LinearDigitalFilter> getMovAvgNoiseFixture() {
+    return new FilterNoiseFixture<LinearDigitalFilter>() {
+      @Override
+      protected LinearDigitalFilter giveFilter(PIDSource source) {
+        return LinearDigitalFilter.movingAverage(source, kMovAvgTaps);
+      }
+    };
+  }
+
+  /**
+   * Constructs a new set of objects representing a single-pole IIR filter with a repeatable data
+   * source.
+   *
+   * @return a single-pole IIR filter with a repeatable data source
+   */
+  public FilterOutputFixture<LinearDigitalFilter> getSinglePoleIIROutputFixture() {
+    return new FilterOutputFixture<LinearDigitalFilter>(kSinglePoleIIRExpectedOutput) {
+      @Override
+      protected LinearDigitalFilter giveFilter() {
+        m_data = new DataWrapper(getData);
+        return LinearDigitalFilter.singlePoleIIR(m_data,
+            kSinglePoleIIRTimeConstant,
+            kFilterStep);
+      }
+    };
+  }
+
+  /**
+   * Constructs a new set of objects representing a high-pass filter with a repeatable data source.
+   *
+   * @return a high-pass filter with a repeatable data source
+   */
+  public FilterOutputFixture<LinearDigitalFilter> getHighPassOutputFixture() {
+    return new FilterOutputFixture<LinearDigitalFilter>(kHighPassExpectedOutput) {
+      @Override
+      protected LinearDigitalFilter giveFilter() {
+        m_data = new DataWrapper(getData);
+        return LinearDigitalFilter.highPass(m_data, kHighPassTimeConstant,
+            kFilterStep);
+      }
+    };
+  }
+
+  /**
+   * Constructs a new set of objects representing a moving average filter with a repeatable data
+   * source using a linear digital filter.
+   *
+   * @return a moving average filter with a repeatable data source
+   */
+  public FilterOutputFixture<LinearDigitalFilter> getMovAvgOutputFixture() {
+    return new FilterOutputFixture<LinearDigitalFilter>(kMovAvgExpectedOutput) {
+      @Override
+      protected LinearDigitalFilter giveFilter() {
+        m_data = new DataWrapper(getData);
+        return LinearDigitalFilter.movingAverage(m_data, kMovAvgTaps);
+      }
+    };
+  }
+
+  /**
+   * Constructs a new set of objects representing a moving average filter with a repeatable data
+   * source using a linear digital filter.
+   *
+   * @return a moving average filter with a repeatable data source
+   */
+  public FilterOutputFixture<LinearDigitalFilter> getPulseFixture() {
+    return new FilterOutputFixture<LinearDigitalFilter>(0.0) {
+      @Override
+      protected LinearDigitalFilter giveFilter() {
+        m_data = new DataWrapper(getPulseData);
+        return LinearDigitalFilter.movingAverage(m_data, kMovAvgTaps);
+      }
+    };
+  }
+
+  /**
+   * Gets the singleton of the TestBench. If the TestBench is not already allocated in constructs an
+   * new instance of it. Otherwise it returns the existing instance.
+   *
+   * @return The Singleton instance of the TestBench
+   */
+  public static TestBench getInstance() {
+    if (instance == null) {
+      instance = new TestBench();
+    }
+    return instance;
+  }
+
+  /**
+   * Provides access to the output stream for the test system. This should be used instead of
+   * System.out This is gives us a way to implement changes to where the output text of this test
+   * system is sent.
+   *
+   * @return The test bench global print stream.
+   */
+  public static PrintStream out() {
+    return System.out;
+  }
+
+  /**
+   * Provides access to the error stream for the test system. This should be used instead of
+   * System.err This is gives us a way to implement changes to where the output text of this test
+   * system is sent.
+   *
+   * @return The test bench global print stream.
+   */
+  public static PrintStream err() {
+    return System.err;
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/TestSuite.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/TestSuite.java
new file mode 100644
index 0000000..72f6703
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/TestSuite.java
@@ -0,0 +1,381 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+package edu.wpi.first.wpilibj.test;
+
+import junit.framework.JUnit4TestAdapter;
+import junit.runner.Version;
+
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.RunWith;
+import org.junit.runner.notification.Failure;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+import edu.wpi.first.wpilibj.WpiLibJTestSuite;
+import edu.wpi.first.wpilibj.command.CommandTestSuite;
+import edu.wpi.first.wpilibj.smartdashboard.SmartDashboardTestSuite;
+
+/**
+ * The WPILibJ Integeration Test Suite collects all of the tests to be run by junit. In order for a
+ * test to be run, it must be added the list of suite classes below. The tests will be run in the
+ * order they are listed in the suite classes annotation.
+ */
+@RunWith(Suite.class)
+// These are listed on separate lines to prevent merge conflicts
+@SuiteClasses({WpiLibJTestSuite.class, CommandTestSuite.class, SmartDashboardTestSuite.class})
+public class TestSuite extends AbstractTestSuite {
+  static {
+    // Sets up the logging output
+    final InputStream inputStream = TestSuite.class.getResourceAsStream("/logging.properties");
+    try {
+      Objects.requireNonNull(inputStream, "./logging.properties was not loaded");
+      LogManager.getLogManager().readConfiguration(inputStream);
+      Logger.getAnonymousLogger().info("Loaded");
+    } catch (final IOException | NullPointerException ex) {
+      Logger.getAnonymousLogger().severe("Could not load default logging.properties file");
+      Logger.getAnonymousLogger().severe(ex.getMessage());
+    }
+
+    TestBench.out().println("Starting Tests");
+  }
+
+  private static final Logger WPILIBJ_ROOT_LOGGER = Logger.getLogger("edu.wpi.first.wpilibj");
+  private static final Logger WPILIBJ_COMMAND_ROOT_LOGGER = Logger
+      .getLogger("edu.wpi.first.wpilibj.command");
+
+
+  private static final Class<?> QUICK_TEST = QuickTest.class;
+  private static final String QUICK_TEST_FLAG = "--quick";
+  private static final String HELP_FLAG = "--help";
+  private static final String METHOD_NAME_FILTER = "--methodFilter=";
+  private static final String METHOD_REPEAT_FILTER = "--repeat=";
+  private static final String CLASS_NAME_FILTER = "--filter=";
+
+  private static TestSuite instance = null;
+
+  /**
+   * Get the singleton instance of the test suite.
+   */
+  public static TestSuite getInstance() {
+    if (instance == null) {
+      instance = new TestSuite();
+    }
+    return instance;
+  }
+
+  /**
+   * This has to be public so that the JUnit4.
+   */
+  public TestSuite() {
+  }
+
+  /**
+   * Displays a help message for the user when they use the --help flag at runtime.
+   */
+  protected static void displayHelp() {
+    StringBuilder helpMessage = new StringBuilder("Test Parameters help: \n");
+    helpMessage.append("\t" + QUICK_TEST_FLAG
+        + " will cause the quick test to be run. Ignores other flags except for "
+        + METHOD_REPEAT_FILTER + "\n");
+    helpMessage.append("\t" + CLASS_NAME_FILTER
+        + " will use the supplied regex text to search for suite/test class names "
+        + "matching the regex and run them.\n");
+    helpMessage.append("\t" + METHOD_NAME_FILTER
+        + " will use the supplied regex text to search for test methods (excluding methods "
+        + "with the @Ignore annotation) and run only those methods. Can be paired with "
+        + METHOD_REPEAT_FILTER + " to " + "repeat the selected tests multiple times.\n");
+    helpMessage.append("\t" + METHOD_REPEAT_FILTER + " will repeat the tests selected with either "
+        + QUICK_TEST_FLAG + " or " + CLASS_NAME_FILTER
+        + " and run them the given number of times.\n");
+    helpMessage
+        .append("[NOTE] All regex uses the syntax defined by java.util.regex.Pattern. This "
+            + "documentation can be found at "
+            + "http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html\n");
+    helpMessage.append("\n");
+    helpMessage.append("\n");
+
+    TestBench.out().println(helpMessage);
+  }
+
+  /**
+   * Lets the user know that they used the TestSuite improperly and gives details about how to use
+   * it correctly in the future.
+   */
+  protected static void displayInvalidUsage(String message, String... args) {
+    StringBuilder invalidMessage = new StringBuilder("Invalid Usage: " + message + "\n");
+    invalidMessage.append("Params received: ");
+    for (String a : args) {
+      invalidMessage.append(a + " ");
+    }
+    invalidMessage.append("\n");
+    invalidMessage
+        .append("For details on proper usage of the runtime flags please run again with the "
+            + HELP_FLAG + " flag.\n\n");
+
+    TestBench.out().println(invalidMessage);
+
+  }
+
+  /**
+   * Prints the loaded tests before they are run.
+   *
+   * @param classes the classes that were loaded.
+   */
+  protected static void printLoadedTests(final Class<?>... classes) {
+    StringBuilder loadedTestsMessage = new StringBuilder("The following tests were loaded:\n");
+    Package packagE = null;
+    for (Class<?> c : classes) {
+      if (c.getPackage().equals(packagE)) {
+        packagE = c.getPackage();
+        loadedTestsMessage.append(packagE.getName() + "\n");
+      }
+      loadedTestsMessage.append("\t" + c.getSimpleName() + "\n");
+    }
+    TestBench.out().println(loadedTestsMessage);
+  }
+
+
+  /**
+   * Parses the arguments passed at runtime and runs the appropriate tests based upon these
+   * arguments.
+   *
+   * @param args the args passed into the program at runtime
+   * @return the restults of the tests that have run. If no tests were run then null is returned.
+   */
+  protected static Result parseArgsRunAndGetResult(final String[] args) {
+    if (args.length == 0) { // If there are no args passed at runtime then just
+      // run all of the tests.
+      printLoadedTests(TestSuite.class);
+      return JUnitCore.runClasses(TestSuite.class);
+    }
+
+    // The method filter was passed
+    boolean methodFilter = false;
+    String methodRegex = "";
+    // The class filter was passed
+    boolean classFilter = false;
+    String classRegex = "";
+    int repeatCount = 1;
+
+    for (String s : args) {
+      if (Pattern.matches(METHOD_NAME_FILTER + ".*", s)) {
+        methodFilter = true;
+        methodRegex = new String(s).replace(METHOD_NAME_FILTER, "");
+      }
+      if (Pattern.matches(METHOD_REPEAT_FILTER + ".*", s)) {
+        try {
+          repeatCount = Integer.parseInt(new String(s).replace(METHOD_REPEAT_FILTER, ""));
+        } catch (NumberFormatException ex) {
+          displayInvalidUsage("The argument passed to the repeat rule was not a valid integer.",
+              args);
+        }
+      }
+      if (Pattern.matches(CLASS_NAME_FILTER + ".*", s)) {
+        classFilter = true;
+        classRegex = s.replace(CLASS_NAME_FILTER, "");
+      }
+    }
+
+
+    ArrayList<String> argsParsed = new ArrayList<String>(Arrays.asList(args));
+    if (argsParsed.contains(HELP_FLAG)) {
+      // If the user inputs the help flag then return the help message and exit
+      // without running any tests
+      displayHelp();
+      return null;
+    }
+    if (argsParsed.contains(QUICK_TEST_FLAG)) {
+      printLoadedTests(QUICK_TEST);
+      return JUnitCore.runClasses(QUICK_TEST);
+    }
+
+    /**
+     * Stores the data from multiple {@link Result}s in one class that can be
+     * returned to display the results.
+     */
+    class MultipleResult extends Result {
+      private static final long serialVersionUID = 1L;
+      private final List<Failure> m_failures = new ArrayList<>();
+      private int m_runCount = 0;
+      private int m_ignoreCount = 0;
+      private long m_runTime = 0;
+
+      @Override
+      public int getRunCount() {
+        return m_runCount;
+      }
+
+      @Override
+      public int getFailureCount() {
+        return m_failures.size();
+      }
+
+      @Override
+      public long getRunTime() {
+        return m_runTime;
+      }
+
+      @Override
+      public List<Failure> getFailures() {
+        return m_failures;
+      }
+
+      @Override
+      public int getIgnoreCount() {
+        return m_ignoreCount;
+      }
+
+      /**
+       * Adds the given result's data to this result.
+       *
+       * @param result the result to add to this result
+       */
+      void addResult(Result result) {
+        m_failures.addAll(result.getFailures());
+        m_runCount += result.getRunCount();
+        m_ignoreCount += result.getIgnoreCount();
+        m_runTime += result.getRunTime();
+      }
+    }
+
+    // If a specific method has been requested
+    if (methodFilter) {
+      List<ClassMethodPair> pairs = (new TestSuite()).getMethodMatching(methodRegex);
+      if (pairs.size() == 0) {
+        displayInvalidUsage("None of the arguments passed to the method name filter matched.",
+            args);
+        return null;
+      }
+      // Print out the list of tests before we run them
+      TestBench.out().println("Running the following tests:");
+      Class<?> classListing = null;
+      for (ClassMethodPair p : pairs) {
+        if (!p.m_methodClass.equals(classListing)) {
+          // Only display the class name every time it changes
+          classListing = p.m_methodClass;
+          TestBench.out().println(classListing);
+        }
+        TestBench.out().println("\t" + p.m_methodName);
+      }
+
+
+      // The test results will be saved here
+      MultipleResult results = new MultipleResult();
+      // Runs tests multiple times if the repeat rule is used
+      for (int i = 0; i < repeatCount; i++) {
+        // Now run all of the tests
+        for (ClassMethodPair p : pairs) {
+          Result result = (new JUnitCore()).run(p.getMethodRunRequest());
+          // Store the given results in one cohesive result
+          results.addResult(result);
+        }
+      }
+
+      return results;
+    }
+
+    // If a specific class has been requested
+    if (classFilter) {
+      List<Class<?>> testClasses = (new TestSuite()).getSuiteOrTestMatchingRegex(classRegex);
+      if (testClasses.size() == 0) {
+        displayInvalidUsage("None of the arguments passed to the filter matched.", args);
+        return null;
+      }
+      printLoadedTests(testClasses.toArray(new Class[0]));
+      MultipleResult results = new MultipleResult();
+      // Runs tests multiple times if the repeat rule is used
+      for (int i = 0; i < repeatCount; i++) {
+        Result result = (new JUnitCore()).run(testClasses.toArray(new Class[0]));
+        // Store the given results in one cohesive result
+        results.addResult(result);
+      }
+      return results;
+    }
+    displayInvalidUsage(
+        "None of the parameters that you passed matched any of the accepted flags.", args);
+
+    return null;
+  }
+
+  protected static void displayResults(Result result) {
+    // Results are collected and displayed here
+    TestBench.out().println("\n");
+    if (!result.wasSuccessful()) {
+      // Prints out a list of stack traces for the failed tests
+      TestBench.out().println("Failure List: ");
+      for (Failure f : result.getFailures()) {
+        TestBench.out().println(f.getDescription());
+        TestBench.out().println(f.getTrace());
+      }
+      TestBench.out().println();
+      TestBench.out().println("FAILURES!!!");
+      // Print the test statistics
+      TestBench.out().println(
+          "Tests run: " + result.getRunCount() + ", Failures: " + result.getFailureCount()
+              + ", Ignored: " + result.getIgnoreCount() + ", In " + result.getRunTime() + "ms");
+
+      // Prints out a list of test that failed
+      TestBench.out().println("Failure List (short):");
+      String failureClass = result.getFailures().get(0).getDescription().getClassName();
+      TestBench.out().println(failureClass);
+      for (Failure f : result.getFailures()) {
+        if (!failureClass.equals(f.getDescription().getClassName())) {
+          failureClass = f.getDescription().getClassName();
+          TestBench.out().println(failureClass);
+        }
+        TestBench.err().println("\t" + f.getDescription());
+      }
+    } else {
+      TestBench.out().println("SUCCESS!");
+      TestBench.out().println(
+          "Tests run: " + result.getRunCount() + ", Ignored: " + result.getIgnoreCount() + ", In "
+              + result.getRunTime() + "ms");
+    }
+    TestBench.out().println();
+  }
+
+  /**
+   * This is used by ant to get the Junit tests. This is required because the tests try to load
+   * using a JUnit 3 framework. JUnit4 uses annotations to load tests. This method allows JUnit3 to
+   * load JUnit4 tests.
+   */
+  public static junit.framework.Test suite() {
+    return new JUnit4TestAdapter(TestSuite.class);
+  }
+
+
+  /**
+   * The method called at runtime.
+   *
+   * @param args The test suites to run
+   */
+  public static void main(String[] args) {
+    TestBench.out().println("JUnit version " + Version.id());
+
+    // Tests are run here
+    Result result = parseArgsRunAndGetResult(args);
+    if (result != null) {
+      // Results are collected and displayed here
+      displayResults(result);
+
+      System.exit(result.wasSuccessful() ? 0 : 1);
+    }
+    System.exit(1);
+  }
+}
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/package-info.java b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/package-info.java
new file mode 100644
index 0000000..481cb08
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/java/edu/wpi/first/wpilibj/test/package-info.java
@@ -0,0 +1,18 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2018 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+/**
+ * This is the starting point for the integration testing framework. This package should contain
+ * classes that are not explicitly for testing the library but instead provide the framework that
+ * the tests can extend from. Every test should extend from
+ * {@link edu.wpi.first.wpilibj.test.AbstractComsSetup}
+ * to ensure that Network Communications is properly instantiated before the test is run. The
+ * {@link edu.wpi.first.wpilibj.test.TestBench} should contain the port numbers for all of the
+ * hardware and these values should not be explicitly defined anywhere else in the testing
+ * framework.
+ */
+package edu.wpi.first.wpilibj.test;
diff --git a/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/resources/logging.properties b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/resources/logging.properties
new file mode 100644
index 0000000..b15c534
--- /dev/null
+++ b/third_party/allwpilib_2018/wpilibjIntegrationTests/src/main/resources/logging.properties
@@ -0,0 +1,25 @@
+# "handlers" specifies a comma separated list of log Handler
+# classes.  These handlers will be installed during VM startup.
+# By default we only configure a ConsoleHandler, which will only
+# show messages at the INFO and above levels.
+handlers=java.util.logging.ConsoleHandler
+# Default global logging level.
+# This specifies which kinds of events are logged across
+# all loggers.  For any given facility this global level
+# can be overriden by a facility specific level
+# Note that the ConsoleHandler also has a separate level
+# setting to limit messages printed to the console.
+#.level= INFO
+.level=INFO
+############################################################
+# Handler specific properties.
+# Describes specific configuration info for Handlers.
+############################################################
+java.util.logging.ConsoleHandler.level=FINER
+java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
+############################################################
+# Facility specific properties.
+# Provides extra control for each logger.
+############################################################
+edu.wpi.first.wpilibj.level=INFO
+edu.wpi.first.wpilibj.command.level=INFO