blob: c3efaaca51843eebf9fffc1d4d6bbcb32cb02d14 [file] [log] [blame] [edit]
# Copyright 2011 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unit tests for cros_portage_upgrade.py."""
import os
import tempfile
from chromite.lib import cros_test_lib
from chromite.lib import table
from chromite.scripts import merge_package_status as mps
# pylint: disable=protected-access
class MergeTest(cros_test_lib.OutputTestCase, cros_test_lib.TempDirTestCase):
"""Test the functionality of merge_package_status."""
# These taken from cros_portage_upgrade column names.
COL_VER_x86 = "Current x86 Version"
COL_VER_arm = "Current arm Version"
COL_CROS_TARGET = "ChromeOS Root Target"
COL_HOST_TARGET = "Host Root Target"
COL_CMP_ARCH = "Comparing arm vs x86 Versions"
COLUMNS = [
mps.COL_PACKAGE,
mps.COL_SLOT,
mps.COL_OVERLAY,
COL_VER_x86,
COL_VER_arm,
mps.COL_TARGET,
]
ROW0 = {
mps.COL_PACKAGE: "lib/foo",
mps.COL_SLOT: "0",
mps.COL_OVERLAY: "portage",
COL_VER_x86: "1.2.3",
COL_VER_arm: "1.2.3",
mps.COL_TARGET: "virtual/target-os-dev virtual/target-sdk",
}
ROW0_FINAL = dict(ROW0)
ROW0_FINAL[mps.COL_PACKAGE] = (
ROW0[mps.COL_PACKAGE] + ":" + ROW0[mps.COL_SLOT]
)
ROW0_FINAL[COL_CROS_TARGET] = "virtual/target-os-dev"
ROW0_FINAL[COL_HOST_TARGET] = "virtual/target-sdk"
ROW0_FINAL[COL_CMP_ARCH] = "same"
ROW1 = {
mps.COL_PACKAGE: "dev/bar",
mps.COL_SLOT: "0",
mps.COL_OVERLAY: "chromiumos-overlay",
COL_VER_x86: "1.2.3",
COL_VER_arm: "1.2.3-r1",
mps.COL_TARGET: "virtual/target-os",
}
ROW1_FINAL = dict(ROW1)
ROW1_FINAL[COL_CROS_TARGET] = "virtual/target-os"
ROW1_FINAL[COL_HOST_TARGET] = ""
ROW1_FINAL[COL_CMP_ARCH] = "different"
ROW2 = {
mps.COL_PACKAGE: "lib/foo",
mps.COL_SLOT: "1",
mps.COL_OVERLAY: "portage",
COL_VER_x86: "1.2.3",
COL_VER_arm: "",
mps.COL_TARGET: "virtual/target-os-dev world",
}
ROW2_FINAL = dict(ROW2)
ROW2_FINAL[mps.COL_PACKAGE] = (
ROW2[mps.COL_PACKAGE] + ":" + ROW2[mps.COL_SLOT]
)
ROW2_FINAL[COL_CROS_TARGET] = "virtual/target-os-dev"
ROW2_FINAL[COL_HOST_TARGET] = "world"
ROW2_FINAL[COL_CMP_ARCH] = ""
def setUp(self):
self._table = self._CreateTableWithRows(
self.COLUMNS, [self.ROW0, self.ROW1, self.ROW2]
)
def _CreateTableWithRows(self, cols, rows):
mytable = table.Table(list(cols))
if rows:
for row in rows:
mytable.AppendRow(dict(row))
return mytable
def _CreateTmpCsvFile(self, table_obj):
with tempfile.NamedTemporaryFile(mode="w", delete=False) as f:
table_obj.WriteCSV(f)
f.flush()
return f.name
def _GetFullRowFor(self, row, cols):
return dict((col, row.get(col, "")) for col in cols)
def assertRowsEqual(self, row1, row2):
# Determine column superset
cols = set(row1) | set(row2)
self.assertEqual(
self._GetFullRowFor(row1, cols), self._GetFullRowFor(row2, cols)
)
def testGetCrosTargetRank(self):
cros_rank = mps._GetCrosTargetRank("virtual/target-os")
crosdev_rank = mps._GetCrosTargetRank("virtual/target-os-dev")
crostest_rank = mps._GetCrosTargetRank("virtual/target-os-test")
other_rank = mps._GetCrosTargetRank("foobar")
self.assertTrue(cros_rank)
self.assertTrue(crosdev_rank)
self.assertTrue(crostest_rank)
self.assertFalse(other_rank)
self.assertTrue(cros_rank < crosdev_rank)
self.assertTrue(crosdev_rank < crostest_rank)
def testProcessTargets(self):
test_in = [
["virtual/target-os", "virtual/target-os-dev"],
[
"world",
"virtual/target-os",
"virtual/target-os-dev",
"virtual/target-os-test",
],
[
"world",
"virtual/target-sdk",
"virtual/target-os-dev",
"virtual/target-os-test",
],
]
test_out = [
["virtual/target-os-dev"],
["virtual/target-os-test", "world"],
["virtual/target-os-test", "virtual/target-sdk", "world"],
]
test_rev_out = [
["virtual/target-os"],
["virtual/target-os", "world"],
["virtual/target-os-dev", "virtual/target-sdk", "world"],
]
for targets, good_out, rev_out in zip(test_in, test_out, test_rev_out):
output = mps.ProcessTargets(targets)
self.assertEqual(output, good_out)
output = mps.ProcessTargets(targets, reverse_cros=True)
self.assertEqual(output, rev_out)
def testLoadTable(self):
path = self._CreateTmpCsvFile(self._table)
csv_table = mps.LoadTable(path)
self.assertEqual(self._table, csv_table)
os.unlink(path)
def testLoadAndMergeTables(self):
# Create a second table to merge with standard table.
row0_2 = {
mps.COL_PACKAGE: "lib/foo",
mps.COL_SLOT: "1",
mps.COL_OVERLAY: "portage",
self.COL_VER_arm: "1.2.4",
mps.COL_TARGET: "virtual/target-os-dev world",
}
row1_2 = {
mps.COL_PACKAGE: "dev/bar",
mps.COL_SLOT: "0",
mps.COL_OVERLAY: "chromiumos-overlay",
self.COL_VER_arm: "1.2.3-r1",
mps.COL_TARGET: "virtual/target-os-test",
}
row2_2 = {
mps.COL_PACKAGE: "dev/newby",
mps.COL_SLOT: "2",
mps.COL_OVERLAY: "chromiumos-overlay",
self.COL_VER_arm: "3.2.1",
mps.COL_TARGET: "virtual/target-os virtual/target-sdk",
}
cols = [col for col in self.COLUMNS if col != self.COL_VER_x86]
table_2 = self._CreateTableWithRows(cols, [row0_2, row1_2, row2_2])
# Minor patch to main table for this test.
self._table.GetRowByIndex(2)[self.COL_VER_arm] = "1.2.4"
with self.OutputCapturer():
path1 = self._CreateTmpCsvFile(self._table)
path2 = self._CreateTmpCsvFile(table_2)
combined_table1 = mps.MergeTables([self._table, table_2])
combined_table2 = mps.LoadAndMergeTables([path1, path2])
final_row0 = {
mps.COL_PACKAGE: "dev/bar",
mps.COL_SLOT: "0",
mps.COL_OVERLAY: "chromiumos-overlay",
self.COL_VER_x86: "1.2.3",
self.COL_VER_arm: "1.2.3-r1",
mps.COL_TARGET: "virtual/target-os",
}
final_row1 = {
mps.COL_PACKAGE: "dev/newby",
mps.COL_SLOT: "2",
mps.COL_OVERLAY: "chromiumos-overlay",
self.COL_VER_x86: "",
self.COL_VER_arm: "3.2.1",
mps.COL_TARGET: "virtual/target-os virtual/target-sdk",
}
final_row2 = {
mps.COL_PACKAGE: "lib/foo",
mps.COL_SLOT: "0",
mps.COL_OVERLAY: "portage",
self.COL_VER_x86: "1.2.3",
self.COL_VER_arm: "1.2.3",
mps.COL_TARGET: "virtual/target-os-dev virtual/target-sdk",
}
final_row3 = {
mps.COL_PACKAGE: "lib/foo",
mps.COL_SLOT: "1",
mps.COL_OVERLAY: "portage",
self.COL_VER_x86: "1.2.3",
self.COL_VER_arm: "1.2.4",
mps.COL_TARGET: "virtual/target-os-dev world",
}
final_rows = (final_row0, final_row1, final_row2, final_row3)
for ix, row_out in enumerate(final_rows):
self.assertRowsEqual(row_out, combined_table1[ix])
self.assertRowsEqual(row_out, combined_table2[ix])
os.unlink(path1)
os.unlink(path2)
def testFinalizeTable(self):
self.assertEqual(3, self._table.GetNumRows())
self.assertEqual(len(self.COLUMNS), self._table.GetNumColumns())
with self.OutputCapturer():
mps.FinalizeTable(self._table)
self.assertEqual(3, self._table.GetNumRows())
self.assertEqual(len(self.COLUMNS) + 3, self._table.GetNumColumns())
final_rows = (self.ROW0_FINAL, self.ROW1_FINAL, self.ROW2_FINAL)
for ix, row_out in enumerate(final_rows):
self.assertRowsEqual(row_out, self._table[ix])
class MainTest(cros_test_lib.MockOutputTestCase):
"""Test argument handling at the main method level."""
def testHelp(self):
"""Test that --help is functioning"""
with self.OutputCapturer() as output:
# Running with --help should exit with code==0
try:
mps.main(["--help"])
except SystemExit as e:
self.assertEqual(e.args[0], 0)
# Verify that a message beginning with "Usage: " was printed
stdout = output.GetStdout()
self.assertTrue(
stdout.startswith("usage: "),
msg='Expected output starting with "usage: " but got:\n%s' % stdout,
)
def testMissingOut(self):
"""Test that running without --out exits with an error."""
with self.OutputCapturer() as output:
# Running without --out should exit with code!=0
try:
mps.main(["pkg"])
except SystemExit as e:
self.assertNotEqual(e.args[0], 0)
# Verify that output ends in error.
self.assertIn(
"error: the following arguments are required: --out",
output.GetStderr(),
)
def testMissingPackage(self):
"""Test that running without a package argument exits with an error."""
with self.OutputCapturer() as output:
# Running without a package should exit with code!=0
try:
mps.main(["--out=any-out"])
except SystemExit as e:
self.assertNotEqual(e.args[0], 0)
# Verify that output ends in error.
self.assertIn(
"error: the following arguments are required", output.GetStderr()
)
def testMain(self):
"""Verify that running main method runs expected functons.
Expected: LoadAndMergeTables, WriteTable.
"""
self.PatchObject(mps, "LoadAndMergeTables", return_value="csv_table")
m = self.PatchObject(mps, "WriteTable")
mps.main(["--out=any-out", "any-package"])
m.assert_called_with("csv_table", os.path.join(os.getcwd(), "any-out"))