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 & 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