---
title: "Examples and use-cases"
author: "Rich FitzJohn"
date: "2018-11-08"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Examples and use-cases}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---



## Using a database in testing

This example requires the `redux` package, which is available on
CRAN and can be installed with

```r
install.packages("redux")
```

```r
docker <- stevedore::docker_client()

redis <- docker$container$run("redis", name = "redis", ports = "6379",
                              detach = TRUE, rm = TRUE)
```

We now have a Redis server running on 32775

```r
redis$ports()
```

```
##   container_port protocol host_ip host_port
## 1           6379      tcp 0.0.0.0     32775
```

Make a connection to the Redis server:

```r
con <- redux::hiredis(port = redis$ports()$host_port)
```

and we can communicate with the Redis server:

```r
con$PING()
```

```
## [Redis: PONG]
```

Because this is a brand new container we can write data without
worrying about clobbering data that already exists:

```r
con$SET("key", "hello redis")
```

```
## [Redis: OK]
```

```r
con$GET("key")
```

```
## [1] "hello redis"
```

And we can get a fresh copy of Redis by simply starting a new copy
of redis

```r
redis$kill()
```

```
## NULL
```

```r
redis <- docker$container$run("redis", name = "redis", ports = "6379",
                              detach = TRUE, rm = TRUE)
con <- redux::hiredis(port = redis$ports()$host_port)
con$KEYS("*")
```

```
## list()
```

```r
redis$kill()
```

```
## NULL
```

The same approach works for other database that might be large or
awkward to install, such as Postgres or MySQL.

## Testing shiny apps

(this section is not actually run because doing anything with it
requires looking in a web browser)

The rocker project has a shiny container that provides an easy to
use version of the shiny server.  If we have a directory `app`
that contains a shiny application we can map this with:

```r
volumes <- sprintf("%s:%s", normalizePath("app"), "/srv/shiny-server/")
```

(see the [shiny docker image
documentation](https://hub.docker.com/r/rocker/shiny) for the
destination path.

We can start this with

```r
shiny <- docker$container$run("rocker/shiny", name = "shiny", ports = "3838",
                              volumes = volumes,
                              detach = TRUE, rm = TRUE)
```

In an interactive session, you can visit the shiny server:

```r
browseURL(sprintf("http://localhost:%s", shiny$ports()$host_port))
```

## Package testing

You can build an image that contains all the bits required to test
your package and then run tests using that image.  This ensures
that you're running in a totally clean environment (and that you
really know what all the dependencies of your package are)


For this we have a Dockerfile, which contains
```plain
FROM r-base

RUN apt-get update && \
        apt-get install -yy \
                git \
                libcurl4-openssl-dev \
                libssl-dev \
                qpdf

RUN install2.r --error \
        curl \
        knitr \
        openssl \
        rcmdcheck \
        rmarkdown \
        rcorpora \
        testthat \
        uuid

COPY tester.sh /usr/local/bin
RUN chmod +x /usr/local/bin/tester.sh

ENTRYPOINT ["/usr/local/bin/tester.sh"]
```

And the script `tester.sh` (copied into the docker image above)
which contains:

```r
lang_output(readLines("tester/tester.sh"), "shell")
```

```
## ```shell
## #!/usr/bin/env bash
## set -e
##
## if [[ "$#" -ne 1 ]]; then
##     echo "Expected one argument"
##     exit 1
## fi
## SRC=$1
##
## if echo $SRC | grep -q "^https://"; then
##     DEST=$(mktemp -d)
##     git clone $SRC $DEST
##     SRC=$DEST
## fi
##
## if [ ! -f "$SRC/DESCRIPTION" ]; then
##     echo "Did not find a DESCRIPTION" file
##     exit 1
## fi
##
## PACKAGE=$(grep '^Package:' "$SRC/DESCRIPTION" | \
##                  sed -E 's/^Package:[[:space:]]+//')
## R CMD build $SRC
## PACKAGE_TGZ=$(ls -1tr ${PACKAGE}*gz | tail -n1)
##
## export _R_CHECK_CRAN_INCOMING_=FALSE
## Rscript -e "rcmdcheck::rcmdcheck('$PACKAGE_TGZ', args = c('--as-cran', '--no-manual'))"
## ```
```

```r
img <- docker$image$build("tester", tag = "richfitz/tester")
```

```
## Step 1/6 : FROM r-base
##  ---> e4a158184cc5
## Step 2/6 : RUN apt-get update &&         apt-get install -yy                 git                 libcurl4-openssl-dev                 libssl-dev                 qpdf
##  ---> Using cache
##  ---> ef239ce55ffe
## Step 3/6 : RUN install2.r --error         curl         knitr         openssl         rcmdcheck         rmarkdown         rcorpora         testthat         uuid
##  ---> Using cache
##  ---> 412ea6a1c8a4
## Step 4/6 : COPY tester.sh /usr/local/bin
##  ---> Using cache
##  ---> 079439ae1bae
## Step 5/6 : RUN chmod +x /usr/local/bin/tester.sh
##  ---> Using cache
##  ---> 9d56dca452f9
## Step 6/6 : ENTRYPOINT ["/usr/local/bin/tester.sh"]
##  ---> Using cache
##  ---> 68e1b48c1b2c
## Successfully built 68e1b48c1b2c
## Successfully tagged richfitz/tester:latest
```

With this image we can then test packages off github:

```r
invisible(docker$container$run(img, "https://github.com/richfitz/ids",
                               rm = TRUE, stream = stdout()))
```

```
## E> Cloning into '/tmp/tmp.3r6OVHu5N6'...
## O> * checking for file ‘/tmp/tmp.3r6OVHu5N6/DESCRIPTION’ ... OK
## O> * preparing ‘ids’:
## O> * checking DESCRIPTION meta-information ... OK
## O> * installing the package to build vignettes
## O> * creating vignettes ... OK
## O> * checking for LF line-endings in source and make files and shell scripts
## O> * checking for empty or unneeded directories
## O> * looking to see if a ‘data/datalist’ file should be added
## O> * building ‘ids_1.0.1.tar.gz’
## E>
## O> ── R CMD check ─────────────────────────────────────────────────────────────────
## O>   
─  using log directory ‘/tmp/Rtmp9phSht/file3f69a6c616/ids.Rcheck’
## O> ─  using R version 3.5.1 (2018-07-02)
## O> 
  
─  using platform: x86_64-pc-linux-gnu (64-bit)
## O> ─  using session charset: UTF-8
## O> 
  
─  using options ‘--no-manual --as-cran’
## O> 
  
✔  checking for file ‘ids/DESCRIPTION’
## O> ─  this is package ‘ids’ version ‘1.0.1’
## O>    checking package namespace information ...
  
✔  checking package namespace information
## O>    checking package dependencies ...
  
✔  checking package dependencies (1.2s)
## O>    checking if this is a source package ...
  
✔  checking if this is a source package
## O> ✔  checking if there is a namespace
## O> 
  
✔  checking for .dll and .exe files
## O> ✔  checking for hidden files and directories
## O>    checking for portable file names ...
  
✔  checking for portable file names
## O> ✔  checking for sufficient/correct file permissions
## O> ✔  checking serialization versions
## O>    checking whether package ‘ids’ can be installed ...
  
✔  checking whether package ‘ids’ can be installed (854ms)
## O> 
  
✔  checking installed package size
## O> 
  
   checking package directory ...
  
✔  checking package directory
## O> ✔  checking ‘build’ directory
## O>    checking DESCRIPTION meta-information ...
  
✔  checking DESCRIPTION meta-information
## O> 
  
✔  checking top-level files
## O> ✔  checking for left-over files
## O>    checking index information ...
  
✔  checking index information
## O> 
  
   checking package subdirectories ...
  
✔  checking package subdirectories
## O> 
  
   checking R files for non-ASCII characters ...
  
✔  checking R files for non-ASCII characters
## O> 
  
   checking R files for syntax errors ...
  
✔  checking R files for syntax errors
## O> 
  
   checking whether the package can be loaded ...
  
✔  checking whether the package can be loaded
## O> 
  
   checking whether the package can be loaded with stated dependencies ...
  
✔  checking whether the package can be loaded with stated dependencies
## O> 
  
   checking whether the package can be unloaded cleanly ...
  
✔  checking whether the package can be unloaded cleanly
## O> 
  
   checking whether the namespace can be loaded with stated dependencies ...
  
✔  checking whether the namespace can be loaded with stated dependencies
## O> 
  
   checking whether the namespace can be unloaded cleanly ...
  
✔  checking whether the namespace can be unloaded cleanly
## O> 
  
   checking loading without being on the library search path ...
  
✔  checking loading without being on the library search path
## O> 
  
   checking dependencies in R code ...
  
✔  checking dependencies in R code
## O> 
  
   checking S3 generic/method consistency ...
  
✔  checking S3 generic/method consistency (416ms)
## O> 
  
   checking replacement functions ...
  
✔  checking replacement functions
## O> 
  
   checking foreign function calls ...
  
✔  checking foreign function calls
## O> 
  
   checking R code for possible problems ...
  
✔  checking R code for possible problems (2s)
## O> 
  
   checking Rd files ...
  
✔  checking Rd files
## O> 
  
   checking Rd metadata ...
  
✔  checking Rd metadata
## O> 
  
   checking Rd line widths ...
  
✔  checking Rd line widths
## O> 
  
   checking Rd cross-references ...
  
✔  checking Rd cross-references
## O> 
  
   checking for missing documentation entries ...
  
✔  checking for missing documentation entries
## O> 
  
   checking for code/documentation mismatches ...
  
✔  checking for code/documentation mismatches (347ms)
## O> 
  
   checking Rd \usage sections ...
  
✔  checking Rd \usage sections (541ms)
## O> 
  
   checking Rd contents ...
  
✔  checking Rd contents
## O> 
  
   checking for unstated dependencies in examples ...
  
✔  checking for unstated dependencies in examples
## O> 
  
   checking R/sysdata.rda ...
  
✔  checking R/sysdata.rda
## O> 
  
   checking installed files from ‘inst/doc’ ...
  
✔  checking installed files from ‘inst/doc’
## O> 
  
   checking files in ‘vignettes’ ...
  
   checking files in ‘vignettes’ ... 
  
✔  checking files in ‘vignettes’
## O>    checking examples ...
  
   checking examples ... 
  
✔  checking examples (732ms)
## O> 
  
   checking for unstated dependencies in ‘tests’ ...
  
✔  checking for unstated dependencies in ‘tests’
## O> 
  
   checking tests ...
  
─  checking tests ...
## O> 
  
   Running ‘testthat.R’
  

  
✔  Running ‘testthat.R’
## O> 
  
   checking for unstated dependencies in vignettes ...
  
✔  checking for unstated dependencies in vignettes
## O> 
  
✔  checking package vignettes in ‘inst/doc’
## O> 
  
   checking re-building of vignette outputs ...
  
✔  checking re-building of vignette outputs (1.1s)
## O>
## O>
## O> 
  

── R CMD check results ────────────────────────────────────────── ids 1.0.1 ────
## O> Duration: 12.4s
## O>
## O> 0 errors ✔ | 0 warnings ✔ | 0 notes ✔
```



(I have cheated here and put all of the dependencies of `ids` into
the docker image via the Dockerfile).

The same approach would work by mounting the package source
directory into the container and passing the path (within the
container) to `$run()`.
