1#!/bin/bash
2# Copyright 2010 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5#
6# Simple functional test harness for rootdev
7# TODO(wad) rootdev should be rewritten in C++ and gmocked.
8
9set -u
10
11warn () {
12  echo "WARN: $@" 1>&2
13}
14
15error () {
16  echo "ERROR: $@" 1>&2
17  exit 1
18}
19
20PASS_COUNT=0
21pass () {
22  echo "PASS:$1" 1>&2
23  PASS_COUNT=$((PASS_COUNT + 1))
24  return 0
25}
26
27FAIL_COUNT=0
28fail () {
29  echo "FAIL:$1" 1>&2
30  FAIL_COUNT=$((FAIL_COUNT + 1))
31  return 0
32}
33
34WORKDIR=
35cleanup () {
36  if [ -n "$WORKDIR" ]; then
37    rm -rf "$WORKDIR"
38  fi
39  trap - EXIT
40}
41
42setup () {
43  WORKDIR=$(mktemp -d rootdev_test.XXXXXXX)
44  if [ ! -d "$WORKDIR" ]; then
45    error "Failed to create temporary work dir"
46  fi
47  trap cleanup EXIT
48}
49
50run_test () {
51  setup
52  echo "RUN:$1" 1>&2
53  eval $1
54  ret=$?
55  cleanup
56  if [ $ret -eq 0 ]; then
57    pass $1
58  else
59    fail $1
60  fi
61}
62
63expect () {
64  cond="$1"
65  eval test $1
66  if [ $? -ne 0 ]; then
67    warn "expect: $1"
68    return 1
69  fi
70  return 0
71}
72
73ROOTDEV=${1:-./rootdev}
74if [[ ! -e ${ROOTDEV} ]]; then
75  error "could not find rootdev '${ROOTDEV}'"
76fi
77
78if [ "${USER:-}" != "root" ]; then
79  error "Must be run as root to use mknod (${USER:-})"
80fi
81
82t00_bad_sys_dir () {
83  out=$("${ROOTDEV}" --block $WORKDIR 2>/dev/null)
84  expect "$? -ne 0" || return 1
85  expect "-z '$out'" || return 1
86}
87run_test t00_bad_sys_dir
88
89h00_setup_sda_tree() {
90  local block=$1
91  local dev=$2
92  mkdir -p $block
93  mkdir -p $dev
94  mkdir -p $block/sda/sda1
95  mkdir -p $block/sda/sda2
96  echo "10:0" > $block/sda/dev
97  echo "10:1" > $block/sda/sda1/dev
98  echo "10:2" > $block/sda/sda2/dev
99  mknod $dev/sda1 b 10 1
100  mknod $dev/sda2 b 10 2
101  mknod $dev/sda b 10 0
102}
103
104t01_sys_dev_match () {
105  local block=$WORKDIR/sys/block
106  local dev=$WORKDIR/dev
107  h00_setup_sda_tree $block $dev
108
109  out=$("${ROOTDEV}" --dev $dev --block $block --major 10 --minor 1 2>/dev/null)
110  expect "$? -eq 0" || return 1
111  expect "'$dev/sda1' = '$out'" || return 1
112}
113run_test t01_sys_dev_match
114
115t02_sys_dev_match_block () {
116  local block=$WORKDIR/sys/block
117  local dev=$WORKDIR/dev
118  h00_setup_sda_tree $block $dev
119
120  out=$("${ROOTDEV}" --dev $dev --block $block --major 10 --minor 0 2>/dev/null)
121  expect "$? -eq 0" || return 1
122  expect "'$dev/sda' = '$out'" || return 1
123}
124run_test t02_sys_dev_match_block
125
126t03_sys_dev_match_block_no_dev () {
127  local block=$WORKDIR/sys/block
128  local dev=$WORKDIR/dev
129  h00_setup_sda_tree $block $dev
130  rm $dev/sda
131
132  out=$("${ROOTDEV}" --dev $dev --block $block --major 10 --minor 0 2>/dev/null)
133  expect "$? -eq 1" || return 1
134  expect "'$dev/sda' = '$out'" || return 1
135}
136run_test t03_sys_dev_match_block_no_dev
137
138t04_sys_dev_match_block_no_dev_ignore () {
139  local block=$WORKDIR/sys/block
140  local dev=$WORKDIR/dev
141  h00_setup_sda_tree $block $dev
142  rm $dev/sda
143
144  out=$("${ROOTDEV}" -i --dev $dev --block $block --major 10 --minor 0 2>/dev/null)
145  expect "$? -eq 0" || return 1
146  expect "'$dev/sda' = '$out'" || return 1
147}
148run_test t04_sys_dev_match_block_no_dev_ignore
149
150
151h01_setup_dm_tree() {
152  local block=$1
153  local dev=$2
154  mkdir -p $block
155  mkdir -p $dev
156  mkdir -p $block/dm-0
157  mkdir -p $block/dm-0/slaves/sda1
158  echo "254:0" > $block/dm-0/dev
159  echo "10:1" > $block/dm-0/slaves/sda1/dev
160  mknod $dev/dm-0 b 254 0
161}
162
163t05_match_dm () {
164  local block=$WORKDIR/sys/block
165  local dev=$WORKDIR/dev
166  h00_setup_sda_tree $block $dev
167  h01_setup_dm_tree $block $dev
168
169  out=$("${ROOTDEV}" --dev $dev --block $block --major 254 --minor 0 \
170        2>/dev/null)
171  expect "$? -eq 0" || return 1
172  expect "'$dev/dm-0' = '$out'" || return 1
173}
174run_test t05_match_dm
175
176t06_match_dm_slave () {
177  local block=$WORKDIR/sys/block
178  local dev=$WORKDIR/dev
179  h00_setup_sda_tree $block $dev
180  h01_setup_dm_tree $block $dev
181
182  out=$("${ROOTDEV}" -s --dev $dev --block $block --major 254 --minor 0 \
183        2>/dev/null)
184  expect "$? -eq 0" || return 1
185  expect "'$dev/sda1' = '$out'" || return 1
186}
187run_test t06_match_dm_slave
188
189t07_safe_fail_on_no_slave () {
190  local block=$WORKDIR/sys/block
191  local dev=$WORKDIR/dev
192  h00_setup_sda_tree $block $dev
193  h01_setup_dm_tree $block $dev
194
195  out=$("${ROOTDEV}" -s --dev $dev --block $block --major 10 --minor 1 \
196        2>/dev/null)
197  expect "$? -eq 0" || return 1
198  expect "'$dev/sda1' = '$out'" || return 1
199}
200run_test t07_safe_fail_on_no_slave
201
202t08_safe_fail_on_no_slave_dev () {
203  local block=$WORKDIR/sys/block
204  local dev=$WORKDIR/dev
205  h00_setup_sda_tree $block $dev
206  h01_setup_dm_tree $block $dev
207  # If the matching dev node is missing, an error code will be returned
208  # but the path will still represent the slave.
209  rm $dev/sda1
210
211  out=$("${ROOTDEV}" -s --dev $dev --block $block --major 254 --minor 0 \
212        2>/dev/null)
213  expect "$? -eq 1" || return 1
214  expect "'$dev/sda1' = '$out'" || return 1
215}
216run_test t08_safe_fail_on_no_slave_dev
217
218t09_safe_fail_on_no_slave_dev_ignore () {
219  local block=$WORKDIR/sys/block
220  local dev=$WORKDIR/dev
221  h00_setup_sda_tree $block $dev
222  h01_setup_dm_tree $block $dev
223  # If the matching dev node is missing, an error code will be returned
224  # but the path will still represent the slave.
225  rm $dev/sda1
226
227  out=$("${ROOTDEV}" -i -s --dev $dev --block $block --major 254 --minor 0 \
228        2>/dev/null)
229  expect "$? -eq 0" || return 1
230  expect "'$dev/sda1' = '$out'" || return 1
231}
232run_test t09_safe_fail_on_no_slave_dev_ignore
233
234h02_setup_mmc_tree() {
235  local block=$1
236  local dev=$2
237  mkdir -p $block
238  mkdir -p $dev
239  mkdir -p $block/mmcblk0/mmcblk0p1
240  mkdir -p $block/mmcblk0/mmcblk0p2
241  echo "11:0" > $block/mmcblk0/dev
242  echo "11:1" > $block/mmcblk0/mmcblk0p1/dev
243  echo "11:2" > $block/mmcblk0/mmcblk0p2/dev
244  mknod $dev/mmcblk0 b 11 0
245  mknod $dev/mmcblk0p1 b 11 1
246  mknod $dev/mmcblk0p2 b 11 2
247}
248
249t10_mmcdev () {
250  local block=$WORKDIR/sys/block
251  local dev=$WORKDIR/dev
252  h02_setup_mmc_tree $block $dev
253  out=$("${ROOTDEV}" --dev $dev --block $block --major 11 --minor 2 \
254        2>/dev/null)
255  expect "$? -eq 0" || return 1
256  expect "'$dev/mmcblk0p2' = '$out'" || return 1
257}
258run_test t10_mmcdev
259
260t11_mmcdev_strip () {
261  local block=$WORKDIR/sys/block
262  local dev=$WORKDIR/dev
263  h02_setup_mmc_tree $block $dev
264  out=$("${ROOTDEV}" -d --dev $dev --block $block --major 11 --minor 2 \
265        2>/dev/null)
266  expect "$? -eq 0" || return 1
267  expect "'$dev/mmcblk0' = '$out'" || return 1
268}
269run_test t11_mmcdev_strip
270
271t12_sda_strip () {
272  local block=$WORKDIR/sys/block
273  local dev=$WORKDIR/dev
274  h00_setup_sda_tree $block $dev
275  out=$("${ROOTDEV}" -d --dev $dev --block $block --major 10 --minor 2 \
276        2>/dev/null)
277  expect "$? -eq 0" || return 1
278  expect "'$dev/sda' = '$out'" || return 1
279}
280run_test t12_sda_strip
281
282# TODO(wad) add node creation tests
283
284TEST_COUNT=$((PASS_COUNT + FAIL_COUNT))
285
286echo "----"
287echo "Test passed:  $PASS_COUNT / $TEST_COUNT"
288echo "Test failed:  $FAIL_COUNT / $TEST_COUNT"
289
290if [ $FAIL_COUNT -ne 0 ]; then
291  exit 1
292fi
293