aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS12
-rw-r--r--ChangeLog317
-rw-r--r--LICENSE16
-rw-r--r--MANIFEST.in10
-rw-r--r--README31
-rw-r--r--TODO62
-rw-r--r--lib/bldcollector/admin.py33
-rw-r--r--lib/bldcollector/urls.py27
-rw-r--r--lib/bldcollector/views.py62
-rw-r--r--lib/bldcontrol/admin.py8
-rw-r--r--lib/bldcontrol/bbcontroller.py142
-rw-r--r--lib/bldcontrol/localhostbecontroller.py401
-rw-r--r--lib/bldcontrol/management/commands/checksettings.py167
-rw-r--r--lib/bldcontrol/management/commands/runbuilds.py192
-rw-r--r--lib/bldcontrol/migrations/0001_initial.py113
-rw-r--r--lib/bldcontrol/migrations/0002_auto_20160120_1250.py19
-rw-r--r--lib/bldcontrol/migrations/0003_add_cancelling_state.py19
-rw-r--r--lib/bldcontrol/migrations/0004_auto_20160523_1446.py34
-rw-r--r--lib/bldcontrol/migrations/0005_reorder_buildrequest_states.py19
-rw-r--r--lib/bldcontrol/migrations/0006_brlayer_local_source_dir.py19
-rw-r--r--lib/bldcontrol/migrations/0007_brlayers_optional_gitinfo.py29
-rw-r--r--lib/bldcontrol/models.py162
-rw-r--r--lib/bldcontrol/views.py1
-rw-r--r--lib/srtgui/__init__.py (renamed from lib/bldcollector/__init__.py)0
-rw-r--r--lib/srtgui/api.py (renamed from lib/toastergui/api.py)0
-rw-r--r--lib/srtgui/buildtables.py (renamed from lib/toastergui/buildtables.py)0
-rw-r--r--lib/srtgui/fixtures/toastergui-unittest-data.xml (renamed from lib/toastergui/fixtures/toastergui-unittest-data.xml)0
-rw-r--r--lib/srtgui/static/css/bootstrap.css (renamed from lib/toastergui/static/css/bootstrap.css)0
-rw-r--r--lib/srtgui/static/css/bootstrap.css.map (renamed from lib/toastergui/static/css/bootstrap.css.map)0
-rwxr-xr-xlib/srtgui/static/css/bootstrap.min.css (renamed from lib/toastergui/static/css/bootstrap.min.css)0
-rw-r--r--lib/srtgui/static/css/bootstrap.min.css.map (renamed from lib/toastergui/static/css/bootstrap.min.css.map)0
-rw-r--r--lib/srtgui/static/css/bootstrap3-transition.css (renamed from lib/toastergui/static/css/bootstrap3-transition.css)0
-rw-r--r--lib/srtgui/static/css/default.css (renamed from lib/toastergui/static/css/default.css)0
-rwxr-xr-xlib/srtgui/static/css/font-awesome.min.css (renamed from lib/toastergui/static/css/font-awesome.min.css)0
-rwxr-xr-xlib/srtgui/static/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png (renamed from lib/toastergui/static/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png)bin418 -> 418 bytes
-rwxr-xr-xlib/srtgui/static/css/images/ui-bg_diagonals-thick_20_666666_40x40.png (renamed from lib/toastergui/static/css/images/ui-bg_diagonals-thick_20_666666_40x40.png)bin312 -> 312 bytes
-rwxr-xr-xlib/srtgui/static/css/images/ui-bg_flat_10_000000_40x100.png (renamed from lib/toastergui/static/css/images/ui-bg_flat_10_000000_40x100.png)bin205 -> 205 bytes
-rwxr-xr-xlib/srtgui/static/css/images/ui-bg_glass_100_f6f6f6_1x400.png (renamed from lib/toastergui/static/css/images/ui-bg_glass_100_f6f6f6_1x400.png)bin262 -> 262 bytes
-rwxr-xr-xlib/srtgui/static/css/images/ui-bg_glass_100_fdf5ce_1x400.png (renamed from lib/toastergui/static/css/images/ui-bg_glass_100_fdf5ce_1x400.png)bin348 -> 348 bytes
-rwxr-xr-xlib/srtgui/static/css/images/ui-bg_glass_65_ffffff_1x400.png (renamed from lib/toastergui/static/css/images/ui-bg_glass_65_ffffff_1x400.png)bin207 -> 207 bytes
-rw-r--r--lib/srtgui/static/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png (renamed from lib/toastergui/static/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png)bin5815 -> 5815 bytes
-rwxr-xr-xlib/srtgui/static/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png (renamed from lib/toastergui/static/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png)bin278 -> 278 bytes
-rwxr-xr-xlib/srtgui/static/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png (renamed from lib/toastergui/static/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png)bin328 -> 328 bytes
-rw-r--r--lib/srtgui/static/css/images/ui-icons_222222_256x240.png (renamed from lib/toastergui/static/css/images/ui-icons_222222_256x240.png)bin6922 -> 6922 bytes
-rw-r--r--lib/srtgui/static/css/images/ui-icons_228ef1_256x240.png (renamed from lib/toastergui/static/css/images/ui-icons_228ef1_256x240.png)bin4549 -> 4549 bytes
-rw-r--r--lib/srtgui/static/css/images/ui-icons_ef8c08_256x240.png (renamed from lib/toastergui/static/css/images/ui-icons_ef8c08_256x240.png)bin4549 -> 4549 bytes
-rw-r--r--lib/srtgui/static/css/images/ui-icons_ffd27a_256x240.png (renamed from lib/toastergui/static/css/images/ui-icons_ffd27a_256x240.png)bin4549 -> 4549 bytes
-rw-r--r--lib/srtgui/static/css/images/ui-icons_ffffff_256x240.png (renamed from lib/toastergui/static/css/images/ui-icons_ffffff_256x240.png)bin6299 -> 6299 bytes
-rwxr-xr-xlib/srtgui/static/css/jquery-ui.min.css (renamed from lib/toastergui/static/css/jquery-ui.min.css)0
-rwxr-xr-xlib/srtgui/static/css/jquery-ui.structure.min.css (renamed from lib/toastergui/static/css/jquery-ui.structure.min.css)0
-rwxr-xr-xlib/srtgui/static/css/jquery-ui.theme.min.css (renamed from lib/toastergui/static/css/jquery-ui.theme.min.css)0
-rw-r--r--lib/srtgui/static/css/jquery.treetable.css (renamed from lib/toastergui/static/css/jquery.treetable.css)0
-rw-r--r--lib/srtgui/static/css/jquery.treetable.theme.default.css (renamed from lib/toastergui/static/css/jquery.treetable.theme.default.css)0
-rw-r--r--lib/srtgui/static/css/jquery.treetable.theme.toaster.css (renamed from lib/toastergui/static/css/jquery.treetable.theme.toaster.css)0
-rw-r--r--lib/srtgui/static/css/qunit-1.18.0.css (renamed from lib/toastergui/static/css/qunit-1.18.0.css)0
-rw-r--r--lib/srtgui/static/css/screen.css (renamed from lib/toastergui/static/css/screen.css)0
-rw-r--r--lib/srtgui/static/fonts/FontAwesome.otf (renamed from lib/toastergui/static/fonts/FontAwesome.otf)bin48748 -> 48748 bytes
-rw-r--r--lib/srtgui/static/fonts/fontawesome-webfont.eot (renamed from lib/toastergui/static/fonts/fontawesome-webfont.eot)bin25395 -> 25395 bytes
-rw-r--r--lib/srtgui/static/fonts/fontawesome-webfont.svg (renamed from lib/toastergui/static/fonts/fontawesome-webfont.svg)0
-rw-r--r--lib/srtgui/static/fonts/fontawesome-webfont.ttf (renamed from lib/toastergui/static/fonts/fontawesome-webfont.ttf)bin55096 -> 55096 bytes
-rw-r--r--lib/srtgui/static/fonts/fontawesome-webfont.woff (renamed from lib/toastergui/static/fonts/fontawesome-webfont.woff)bin29380 -> 29380 bytes
-rw-r--r--lib/srtgui/static/fonts/glyphicons-halflings-regular.eot (renamed from lib/toastergui/static/fonts/glyphicons-halflings-regular.eot)bin20127 -> 20127 bytes
-rw-r--r--lib/srtgui/static/fonts/glyphicons-halflings-regular.svg (renamed from lib/toastergui/static/fonts/glyphicons-halflings-regular.svg)0
-rw-r--r--lib/srtgui/static/fonts/glyphicons-halflings-regular.ttf (renamed from lib/toastergui/static/fonts/glyphicons-halflings-regular.ttf)bin45404 -> 45404 bytes
-rw-r--r--lib/srtgui/static/fonts/glyphicons-halflings-regular.woff (renamed from lib/toastergui/static/fonts/glyphicons-halflings-regular.woff)bin23424 -> 23424 bytes
-rw-r--r--lib/srtgui/static/fonts/glyphicons-halflings-regular.woff2 (renamed from lib/toastergui/static/fonts/glyphicons-halflings-regular.woff2)bin18028 -> 18028 bytes
-rw-r--r--lib/srtgui/static/html/layer_deps_modal.html (renamed from lib/toastergui/static/html/layer_deps_modal.html)0
-rw-r--r--lib/srtgui/static/img/logo.png (renamed from lib/toastergui/static/img/logo.png)bin3020 -> 3020 bytes
-rw-r--r--lib/srtgui/static/img/toaster_bw.png (renamed from lib/toastergui/static/img/toaster_bw.png)bin140514 -> 140514 bytes
-rw-r--r--lib/srtgui/static/jquery-treetable-license/GPL-LICENSE.txt (renamed from lib/toastergui/static/jquery-treetable-license/GPL-LICENSE.txt)0
-rw-r--r--lib/srtgui/static/jquery-treetable-license/MIT-LICENSE.txt (renamed from lib/toastergui/static/jquery-treetable-license/MIT-LICENSE.txt)0
-rw-r--r--lib/srtgui/static/jquery-treetable-license/README.md (renamed from lib/toastergui/static/jquery-treetable-license/README.md)0
-rw-r--r--lib/srtgui/static/jquery.treetable.theme.toaster.css (renamed from lib/toastergui/static/jquery.treetable.theme.toaster.css)0
-rw-r--r--lib/srtgui/static/js/.jshintrc (renamed from lib/toastergui/static/js/.jshintrc)0
-rw-r--r--lib/srtgui/static/js/bootstrap.js (renamed from lib/toastergui/static/js/bootstrap.js)0
-rw-r--r--lib/srtgui/static/js/bootstrap.min.js (renamed from lib/toastergui/static/js/bootstrap.min.js)0
-rw-r--r--lib/srtgui/static/js/customrecipe.js (renamed from lib/toastergui/static/js/customrecipe.js)0
-rwxr-xr-xlib/srtgui/static/js/filtersnippet.js (renamed from lib/toastergui/static/js/filtersnippet.js)0
-rw-r--r--lib/srtgui/static/js/highlight.pack.js (renamed from lib/toastergui/static/js/highlight.pack.js)0
-rw-r--r--lib/srtgui/static/js/importlayer.js (renamed from lib/toastergui/static/js/importlayer.js)0
-rw-r--r--lib/srtgui/static/js/jquery-2.0.3.min.js (renamed from lib/toastergui/static/js/jquery-2.0.3.min.js)0
-rw-r--r--lib/srtgui/static/js/jquery-2.0.3.min.map (renamed from lib/toastergui/static/js/jquery-2.0.3.min.map)0
-rwxr-xr-xlib/srtgui/static/js/jquery-ui.min.js (renamed from lib/toastergui/static/js/jquery-ui.min.js)0
-rw-r--r--lib/srtgui/static/js/jquery.cookie.js (renamed from lib/toastergui/static/js/jquery.cookie.js)0
-rw-r--r--lib/srtgui/static/js/jquery.treetable.js (renamed from lib/toastergui/static/js/jquery.treetable.js)0
-rw-r--r--lib/srtgui/static/js/jsrender.min.js (renamed from lib/toastergui/static/js/jsrender.min.js)0
-rw-r--r--lib/srtgui/static/js/layerBtn.js (renamed from lib/toastergui/static/js/layerBtn.js)0
-rw-r--r--lib/srtgui/static/js/layerDepsModal.js (renamed from lib/toastergui/static/js/layerDepsModal.js)0
-rw-r--r--lib/srtgui/static/js/layerdetails.js (renamed from lib/toastergui/static/js/layerdetails.js)0
-rw-r--r--lib/srtgui/static/js/libtoaster.js (renamed from lib/toastergui/static/js/libtoaster.js)0
-rw-r--r--lib/srtgui/static/js/mrbsection.js (renamed from lib/toastergui/static/js/mrbsection.js)0
-rw-r--r--lib/srtgui/static/js/newcustomimage_modal.js (renamed from lib/toastergui/static/js/newcustomimage_modal.js)0
-rw-r--r--lib/srtgui/static/js/projectpage.js (renamed from lib/toastergui/static/js/projectpage.js)0
-rw-r--r--lib/srtgui/static/js/projecttopbar.js (renamed from lib/toastergui/static/js/projecttopbar.js)0
-rw-r--r--lib/srtgui/static/js/qunit-1.18.0.js (renamed from lib/toastergui/static/js/qunit-1.18.0.js)0
-rw-r--r--lib/srtgui/static/js/recipedetails.js (renamed from lib/toastergui/static/js/recipedetails.js)0
-rw-r--r--lib/srtgui/static/js/table.js (renamed from lib/toastergui/static/js/table.js)0
-rw-r--r--lib/srtgui/static/js/tests/test.js (renamed from lib/toastergui/static/js/tests/test.js)0
-rw-r--r--lib/srtgui/static/js/typeahead.jquery.js (renamed from lib/toastergui/static/js/typeahead.jquery.js)0
-rw-r--r--lib/srtgui/static/js/ui-bootstrap-tpls-0.11.0.js (renamed from lib/toastergui/static/js/ui-bootstrap-tpls-0.11.0.js)0
-rw-r--r--lib/srtgui/static/js/ui-bootstrap-tpls-0.11.0.min.js (renamed from lib/toastergui/static/js/ui-bootstrap-tpls-0.11.0.min.js)0
-rw-r--r--lib/srtgui/tablefilter.py (renamed from lib/toastergui/tablefilter.py)0
-rw-r--r--lib/srtgui/tables.py (renamed from lib/toastergui/tables.py)0
-rw-r--r--lib/srtgui/templates/base.html (renamed from lib/toastergui/templates/base.html)0
-rw-r--r--lib/srtgui/templates/basebuilddetailpage.html (renamed from lib/toastergui/templates/basebuilddetailpage.html)0
-rw-r--r--lib/srtgui/templates/basebuildpage.html (renamed from lib/toastergui/templates/basebuildpage.html)0
-rw-r--r--lib/srtgui/templates/baseprojectbuildspage.html (renamed from lib/toastergui/templates/baseprojectbuildspage.html)0
-rw-r--r--lib/srtgui/templates/baseprojectpage.html (renamed from lib/toastergui/templates/baseprojectpage.html)0
-rw-r--r--lib/srtgui/templates/basetable_bottom.html (renamed from lib/toastergui/templates/basetable_bottom.html)0
-rw-r--r--lib/srtgui/templates/basetable_top.html (renamed from lib/toastergui/templates/basetable_top.html)0
-rw-r--r--lib/srtgui/templates/basetable_top_layers.html (renamed from lib/toastergui/templates/basetable_top_layers.html)0
-rw-r--r--lib/srtgui/templates/bfile.html (renamed from lib/toastergui/templates/bfile.html)0
-rw-r--r--lib/srtgui/templates/brtargets.html (renamed from lib/toastergui/templates/brtargets.html)0
-rw-r--r--lib/srtgui/templates/builddashboard.html (renamed from lib/toastergui/templates/builddashboard.html)0
-rw-r--r--lib/srtgui/templates/buildinfo-toastertable.html (renamed from lib/toastergui/templates/buildinfo-toastertable.html)0
-rw-r--r--lib/srtgui/templates/builds-toastertable.html (renamed from lib/toastergui/templates/builds-toastertable.html)0
-rw-r--r--lib/srtgui/templates/configuration.html (renamed from lib/toastergui/templates/configuration.html)0
-rw-r--r--lib/srtgui/templates/configvars.html (renamed from lib/toastergui/templates/configvars.html)0
-rw-r--r--lib/srtgui/templates/cpuusage.html (renamed from lib/toastergui/templates/cpuusage.html)0
-rw-r--r--lib/srtgui/templates/customise_btn.html (renamed from lib/toastergui/templates/customise_btn.html)0
-rw-r--r--lib/srtgui/templates/customrecipe.html (renamed from lib/toastergui/templates/customrecipe.html)0
-rw-r--r--lib/srtgui/templates/detail_pagination_bottom.html (renamed from lib/toastergui/templates/detail_pagination_bottom.html)0
-rw-r--r--lib/srtgui/templates/detail_search_header.html (renamed from lib/toastergui/templates/detail_search_header.html)0
-rw-r--r--lib/srtgui/templates/detail_sorted_header.html (renamed from lib/toastergui/templates/detail_sorted_header.html)0
-rw-r--r--lib/srtgui/templates/dirinfo.html (renamed from lib/toastergui/templates/dirinfo.html)0
-rw-r--r--lib/srtgui/templates/diskio.html (renamed from lib/toastergui/templates/diskio.html)0
-rw-r--r--lib/srtgui/templates/distro_btn.html (renamed from lib/toastergui/templates/distro_btn.html)0
-rw-r--r--lib/srtgui/templates/editcustomimage_modal.html (renamed from lib/toastergui/templates/editcustomimage_modal.html)0
-rw-r--r--lib/srtgui/templates/filtersnippet.html (renamed from lib/toastergui/templates/filtersnippet.html)0
-rw-r--r--lib/srtgui/templates/generic-toastertable-page.html (renamed from lib/toastergui/templates/generic-toastertable-page.html)0
-rw-r--r--lib/srtgui/templates/health.html (renamed from lib/toastergui/templates/health.html)0
-rw-r--r--lib/srtgui/templates/importlayer.html (renamed from lib/toastergui/templates/importlayer.html)0
-rw-r--r--lib/srtgui/templates/js-unit-tests.html (renamed from lib/toastergui/templates/js-unit-tests.html)0
-rw-r--r--lib/srtgui/templates/landing.html (renamed from lib/toastergui/templates/landing.html)0
-rw-r--r--lib/srtgui/templates/landing_not_managed.html (renamed from lib/toastergui/templates/landing_not_managed.html)0
-rw-r--r--lib/srtgui/templates/layer_btn.html (renamed from lib/toastergui/templates/layer_btn.html)0
-rw-r--r--lib/srtgui/templates/layerdetails.html (renamed from lib/toastergui/templates/layerdetails.html)0
-rw-r--r--lib/srtgui/templates/machine_btn.html (renamed from lib/toastergui/templates/machine_btn.html)0
-rw-r--r--lib/srtgui/templates/mrb_section.html (renamed from lib/toastergui/templates/mrb_section.html)0
-rw-r--r--lib/srtgui/templates/newcustomimage.html (renamed from lib/toastergui/templates/newcustomimage.html)0
-rw-r--r--lib/srtgui/templates/newcustomimage_modal.html (renamed from lib/toastergui/templates/newcustomimage_modal.html)0
-rw-r--r--lib/srtgui/templates/newproject.html (renamed from lib/toastergui/templates/newproject.html)0
-rw-r--r--lib/srtgui/templates/package_built_dependencies.html (renamed from lib/toastergui/templates/package_built_dependencies.html)0
-rw-r--r--lib/srtgui/templates/package_built_detail.html (renamed from lib/toastergui/templates/package_built_detail.html)0
-rw-r--r--lib/srtgui/templates/package_detail_base.html (renamed from lib/toastergui/templates/package_detail_base.html)0
-rw-r--r--lib/srtgui/templates/package_included_dependencies.html (renamed from lib/toastergui/templates/package_included_dependencies.html)0
-rw-r--r--lib/srtgui/templates/package_included_detail.html (renamed from lib/toastergui/templates/package_included_detail.html)0
-rw-r--r--lib/srtgui/templates/package_included_reverse_dependencies.html (renamed from lib/toastergui/templates/package_included_reverse_dependencies.html)0
-rw-r--r--lib/srtgui/templates/package_included_tabs.html (renamed from lib/toastergui/templates/package_included_tabs.html)0
-rw-r--r--lib/srtgui/templates/pkg_add_rm_btn.html (renamed from lib/toastergui/templates/pkg_add_rm_btn.html)0
-rw-r--r--lib/srtgui/templates/project.html (renamed from lib/toastergui/templates/project.html)0
-rw-r--r--lib/srtgui/templates/projectbuilds-toastertable.html (renamed from lib/toastergui/templates/projectbuilds-toastertable.html)0
-rw-r--r--lib/srtgui/templates/projectbuilds.html (renamed from lib/toastergui/templates/projectbuilds.html)0
-rw-r--r--lib/srtgui/templates/projectconf.html (renamed from lib/toastergui/templates/projectconf.html)0
-rw-r--r--lib/srtgui/templates/projects-toastertable.html (renamed from lib/toastergui/templates/projects-toastertable.html)0
-rw-r--r--lib/srtgui/templates/projecttopbar.html (renamed from lib/toastergui/templates/projecttopbar.html)0
-rw-r--r--lib/srtgui/templates/recipe.html (renamed from lib/toastergui/templates/recipe.html)0
-rw-r--r--lib/srtgui/templates/recipe_btn.html (renamed from lib/toastergui/templates/recipe_btn.html)0
-rw-r--r--lib/srtgui/templates/recipe_packages.html (renamed from lib/toastergui/templates/recipe_packages.html)0
-rw-r--r--lib/srtgui/templates/recipedetails.html (renamed from lib/toastergui/templates/recipedetails.html)0
-rw-r--r--lib/srtgui/templates/snippets/gitrev_popover.html (renamed from lib/toastergui/templates/snippets/gitrev_popover.html)0
-rw-r--r--lib/srtgui/templates/snippets/pkg_dependencies_popover.html (renamed from lib/toastergui/templates/snippets/pkg_dependencies_popover.html)0
-rw-r--r--lib/srtgui/templates/snippets/pkg_revdependencies_popover.html (renamed from lib/toastergui/templates/snippets/pkg_revdependencies_popover.html)0
-rw-r--r--lib/srtgui/templates/tablesort.html (renamed from lib/toastergui/templates/tablesort.html)0
-rw-r--r--lib/srtgui/templates/target.html (renamed from lib/toastergui/templates/target.html)0
-rw-r--r--lib/srtgui/templates/task.html (renamed from lib/toastergui/templates/task.html)0
-rw-r--r--lib/srtgui/templates/toastertable-filter.html (renamed from lib/toastergui/templates/toastertable-filter.html)0
-rw-r--r--lib/srtgui/templates/toastertable-simple.html (renamed from lib/toastergui/templates/toastertable-simple.html)0
-rw-r--r--lib/srtgui/templates/toastertable.html (renamed from lib/toastergui/templates/toastertable.html)0
-rw-r--r--lib/srtgui/templates/unavailable_artifact.html (renamed from lib/toastergui/templates/unavailable_artifact.html)0
-rw-r--r--lib/srtgui/templatetags/__init__.py (renamed from lib/bldcontrol/__init__.py)0
-rw-r--r--lib/srtgui/templatetags/field_values_filter.py (renamed from lib/toastergui/templatetags/field_values_filter.py)0
-rw-r--r--lib/srtgui/templatetags/objects_to_dictionaries_filter.py (renamed from lib/toastergui/templatetags/objects_to_dictionaries_filter.py)0
-rw-r--r--lib/srtgui/templatetags/project_url_tag.py (renamed from lib/toastergui/templatetags/project_url_tag.py)0
-rw-r--r--lib/srtgui/templatetags/projecttags.py (renamed from lib/toastergui/templatetags/projecttags.py)0
-rw-r--r--lib/srtgui/typeaheads.py (renamed from lib/toastergui/typeaheads.py)0
-rw-r--r--lib/srtgui/urls.py (renamed from lib/toastergui/urls.py)0
-rwxr-xr-xlib/srtgui/views.py (renamed from lib/toastergui/views.py)0
-rw-r--r--lib/srtgui/widgets.py (renamed from lib/toastergui/widgets.py)0
-rw-r--r--lib/srtmain/__init__.py (renamed from lib/bldcontrol/management/__init__.py)0
-rw-r--r--lib/srtmain/management/__init__.py (renamed from lib/bldcontrol/management/commands/__init__.py)0
-rw-r--r--lib/srtmain/management/commands/__init__.py (renamed from lib/bldcontrol/migrations/__init__.py)0
-rw-r--r--lib/srtmain/management/commands/builddelete.py (renamed from lib/toastermain/management/commands/builddelete.py)0
-rw-r--r--lib/srtmain/management/commands/buildslist.py (renamed from lib/toastermain/management/commands/buildslist.py)0
-rw-r--r--lib/srtmain/management/commands/checksocket.py (renamed from lib/toastermain/management/commands/checksocket.py)0
-rw-r--r--lib/srtmain/management/commands/perf.py (renamed from lib/toastermain/management/commands/perf.py)0
-rw-r--r--lib/srtmain/settings.py (renamed from lib/toastermain/settings.py)0
-rw-r--r--lib/srtmain/settings_production_example.py (renamed from lib/toastermain/settings_production_example.py)0
-rw-r--r--lib/srtmain/settings_test.py (renamed from lib/toastermain/settings_test.py)0
-rw-r--r--lib/srtmain/urls.py (renamed from lib/toastermain/urls.py)0
-rw-r--r--lib/srtmain/wsgi.py (renamed from lib/toastermain/wsgi.py)0
-rw-r--r--lib/tests/__init__.py0
-rw-r--r--lib/tests/browser/README74
-rw-r--r--lib/tests/browser/__init__.py0
-rw-r--r--lib/tests/browser/selenium_helpers.py34
-rw-r--r--lib/tests/browser/selenium_helpers_base.py227
-rw-r--r--lib/tests/browser/test_all_builds_page.py233
-rw-r--r--lib/tests/browser/test_all_projects_page.py217
-rw-r--r--lib/tests/browser/test_builddashboard_page.py347
-rw-r--r--lib/tests/browser/test_builddashboard_page_artifacts.py222
-rw-r--r--lib/tests/browser/test_builddashboard_page_recipes.py66
-rw-r--r--lib/tests/browser/test_builddashboard_page_tasks.py65
-rw-r--r--lib/tests/browser/test_js_unit_tests.py57
-rw-r--r--lib/tests/browser/test_landing_page.py108
-rw-r--r--lib/tests/browser/test_layerdetails_page.py216
-rw-r--r--lib/tests/browser/test_most_recent_builds_states.py211
-rw-r--r--lib/tests/browser/test_new_custom_image_page.py161
-rw-r--r--lib/tests/browser/test_new_project_page.py113
-rw-r--r--lib/tests/browser/test_project_builds_page.py168
-rw-r--r--lib/tests/browser/test_project_config_page.py231
-rw-r--r--lib/tests/browser/test_project_page.py59
-rw-r--r--lib/tests/browser/test_sample.py41
-rw-r--r--lib/tests/browser/test_task_page.py76
-rw-r--r--lib/tests/browser/test_toastertable_ui.py160
-rw-r--r--lib/tests/builds/README14
-rw-r--r--lib/tests/builds/__init__.py0
-rw-r--r--lib/tests/builds/buildtest.py169
-rw-r--r--lib/tests/builds/test_core_image_min.py386
-rw-r--r--lib/tests/commands/__init__.py0
-rw-r--r--lib/tests/commands/test_loaddata.py61
-rw-r--r--lib/tests/commands/test_lsupdates.py45
-rw-r--r--lib/tests/commands/test_runbuilds.py88
-rw-r--r--lib/tests/db/__init__.py0
-rw-r--r--lib/tests/db/test_db.py55
-rw-r--r--lib/tests/eventreplay/README22
-rw-r--r--lib/tests/eventreplay/__init__.py97
-rw-r--r--lib/tests/functional/README0
-rw-r--r--lib/tests/functional/__init__.py0
-rw-r--r--lib/tests/functional/functional_helpers.py122
-rw-r--r--lib/tests/functional/test_functional_basic.py243
-rw-r--r--lib/tests/toaster-tests-requirements.txt1
-rw-r--r--lib/tests/views/README4
-rw-r--r--lib/tests/views/__init__.py0
-rw-r--r--lib/tests/views/test_views.py540
-rw-r--r--lib/toastergui/__init__.py0
-rw-r--r--lib/toastergui/templatetags/__init__.py0
-rw-r--r--lib/toastermain/__init__.py0
-rw-r--r--lib/toastermain/management/__init__.py0
-rw-r--r--lib/toastermain/management/commands/__init__.py0
-rw-r--r--srtool-requirements.txt (renamed from toaster-requirements.txt)0
240 files changed, 22 insertions, 6806 deletions
diff --git a/AUTHORS b/AUTHORS
index 91fd78fd..6a3fb42f 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,10 +1,2 @@
-Tim Ansell <mithro@mithis.net>
-Phil Blundell <pb@handhelds.org>
-Seb Frankengul <seb@frankengul.org>
-Holger Freyther <holger@moiji-mobile.com>
-Marcin Juszkiewicz <marcin@juszkiewicz.com.pl>
-Chris Larson <kergoth@handhelds.org>
-Ulrich Luckas <luckas@musoft.de>
-Mickey Lauer <mickey@Vanille.de>
-Richard Purdie <rpurdie@rpsys.net>
-Holger Schurig <holgerschurig@gmx.de>
+David Reyna <david.reyna@windriver.com>
+
diff --git a/ChangeLog b/ChangeLog
index 4ac2a644..825db842 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,317 +1,2 @@
-Changes in Bitbake 1.9.x:
- - Add PE (Package Epoch) support from Philipp Zabel (pH5)
- - Treat python functions the same as shell functions for logging
- - Use TMPDIR/anonfunc as a __anonfunc temp directory (T)
- - Catch truncated cache file errors
- - Allow operations other than assignment on flag variables
- - Add code to handle inter-task dependencies
- - Fix cache errors when generation dotGraphs
- - Make sure __inherit_cache is updated before calling include() (from Michael Krelin)
- - Fix bug when target was in ASSUME_PROVIDED (#2236)
- - Raise ParseError for filenames with multiple underscores instead of infinitely looping (#2062)
- - Fix invalid regexp in BBMASK error handling (missing import) (#1124)
- - Promote certain warnings from debug to note 2 level
- - Update manual
- - Correctly redirect stdin when forking
- - If parsing errors are found, exit, too many users miss the errors
- - Remove supriours PREFERRED_PROVIDER warnings
- - svn fetcher: Add _buildsvncommand function
- - Improve certain error messages
- - Rewrite svn fetcher to make adding extra operations easier
- as part of future SRCDATE="now" fixes
- (requires new FETCHCMD_svn definition in bitbake.conf)
- - Change SVNDIR layout to be more unique (fixes #2644 and #2624)
- - Add ConfigParsed Event after configuration parsing is complete
- - Add SRCREV support for svn fetcher
- - data.emit_var() - only call getVar if we need the variable
- - Stop generating the A variable (seems to be legacy code)
- - Make sure intertask depends get processed correcting in recursive depends
- - Add pn-PN to overrides when evaluating PREFERRED_VERSION
- - Improve the progress indicator by skipping tasks that have
- already run before starting the build rather than during it
- - Add profiling option (-P)
- - Add BB_SRCREV_POLICY variable (clear or cache) to control SRCREV cache
- - Add SRCREV_FORMAT support
- - Fix local fetcher's localpath return values
- - Apply OVERRIDES before performing immediate expansions
- - Allow the -b -e option combination to take regular expressions
- - Fix handling of variables with expansion in the name using _append/_prepend
- e.g. RRECOMMENDS_${PN}_append_xyz = "abc"
- - Add plain message function to bb.msg
- - Sort the list of providers before processing so dependency problems are
- reproducible rather than effectively random
- - Fix/improve bitbake -s output
- - Add locking for fetchers so only one tries to fetch a given file at a given time
- - Fix int(0)/None confusion in runqueue.py which causes random gaps in dependency chains
- - Expand data in addtasks
- - Print the list of missing DEPENDS,RDEPENDS for the "No buildable providers available for required...."
- error message.
- - Rework add_task to be more efficient (6% speedup, 7% number of function calls reduction)
- - Sort digraph output to make builds more reproducible
- - Split expandKeys into two for loops to benefit from the expand_cache (12% speedup)
- - runqueue.py: Fix idepends handling to avoid dependency errors
- - Clear the terminal TOSTOP flag if set (and warn the user)
- - Fix regression from r653 and make SRCDATE/CVSDATE work for packages again
- - Fix a bug in bb.decodeurl where http://some.where.com/somefile.tgz decoded to host="" (#1530)
- - Warn about malformed PREFERRED_PROVIDERS (#1072)
- - Add support for BB_NICE_LEVEL option (#1627)
- - Psyco is used only on x86 as there is no support for other architectures.
- - Sort initial providers list by default preference (#1145, #2024)
- - Improve provider sorting so prefered versions have preference over latest versions (#768)
- - Detect builds of tasks with overlapping providers and warn (will become a fatal error) (#1359)
- - Add MULTI_PROVIDER_WHITELIST variable to allow known safe multiple providers to be listed
- - Handle paths in svn fetcher module parameter
- - Support the syntax "export VARIABLE"
- - Add bzr fetcher
- - Add support for cleaning directories before a task in the form:
- do_taskname[cleandirs] = "dir"
- - bzr fetcher tweaks from Robert Schuster (#2913)
- - Add mercurial (hg) fetcher from Robert Schuster (#2913)
- - Don't add duplicates to BBPATH
- - Fix preferred_version return values (providers.py)
- - Fix 'depends' flag splitting
- - Fix unexport handling (#3135)
- - Add bb.copyfile function similar to bb.movefile (and improve movefile error reporting)
- - Allow multiple options for deptask flag
- - Use git-fetch instead of git-pull removing any need for merges when
- fetching (we don't care about the index). Fixes fetch errors.
- - Add BB_GENERATE_MIRROR_TARBALLS option, set to 0 to make git fetches
- faster at the expense of not creating mirror tarballs.
- - SRCREV handling updates, improvements and fixes from Poky
- - Add bb.utils.lockfile() and bb.utils.unlockfile() from Poky
- - Add support for task selfstamp and lockfiles flags
- - Disable task number acceleration since it can allow the tasks to run
- out of sequence
- - Improve runqueue code comments
- - Add task scheduler abstraction and some example schedulers
- - Improve circular dependency chain debugging code and user feedback
- - Don't give a stacktrace for invalid tasks, have a user friendly message (#3431)
- - Add support for "-e target" (#3432)
- - Fix shell showdata command (#3259)
- - Fix shell data updating problems (#1880)
- - Properly raise errors for invalid source URI protocols
- - Change the wget fetcher failure handling to avoid lockfile problems
- - Add support for branches in git fetcher (Otavio Salvador, Michael Lauer)
- - Make taskdata and runqueue errors more user friendly
- - Add norecurse and fullpath options to cvs fetcher
- - Fix exit code for build failures in --continue mode
- - Fix git branch tags fetching
- - Change parseConfigurationFile so it works on real data, not a copy
- - Handle 'base' inherit and all other INHERITs from parseConfigurationFile
- instead of BBHandler
- - Fix getVarFlags bug in data_smart
- - Optmise cache handling by more quickly detecting an invalid cache, only
- saving the cache when its changed, moving the cache validity check into
- the parsing loop and factoring some getVar calls outside a for loop
- - Cooker: Remove a debug message from the parsing loop to lower overhead
- - Convert build.py exec_task to use getVarFlags
- - Update shell to use cooker.buildFile
- - Add StampUpdate event
- - Convert -b option to use taskdata/runqueue
- - Remove digraph and switch to new stamp checking code. exec_task no longer
- honours dependencies
- - Make fetcher timestamp updating non-fatal when permissions don't allow
- updates
- - Add BB_SCHEDULER variable/option ("completion" or "speed") controlling
- the way bitbake schedules tasks
- - Add BB_STAMP_POLICY variable/option ("perfile" or "full") controlling
- how extensively stamps are looked at for validity
- - When handling build target failures make sure idepends are checked and
- failed where needed. Fixes --continue mode crashes.
- - Fix -f (force) in conjunction with -b
- - Fix problems with recrdeptask handling where some idepends weren't handled
- correctly.
- - Handle exit codes correctly (from pH5)
- - Work around refs/HEAD issues with git over http (#3410)
- - Add proxy support to the CVS fetcher (from Cyril Chemparathy)
- - Improve runfetchcmd so errors are seen and various GIT variables are exported
- - Add ability to fetchers to check URL validity without downloading
- - Improve runtime PREFERRED_PROVIDERS warning message
- - Add BB_STAMP_WHITELIST option which contains a list of stamps to ignore when
- checking stamp dependencies and using a BB_STAMP_POLICY of "whitelist"
- - No longer weight providers on the basis of a package being "already staged". This
- leads to builds being non-deterministic.
- - Flush stdout/stderr before forking to fix duplicate console output
- - Make sure recrdeps tasks include all inter-task dependencies of a given fn
- - Add bb.runqueue.check_stamp_fn() for use by packaged-staging
- - Add PERSISTENT_DIR to store the PersistData in a persistent
- directory != the cache dir.
- - Add md5 and sha256 checksum generation functions to utils.py
- - Correctly handle '-' characters in class names (#2958)
- - Make sure expandKeys has been called on the data dictionary before running tasks
- - Correctly add a task override in the form task-TASKNAME.
- - Revert the '-' character fix in class names since it breaks things
- - When a regexp fails to compile for PACKAGES_DYNAMIC, print a more useful error (#4444)
- - Allow to checkout CVS by Date and Time. Just add HHmm to the SRCDATE.
- - Move prunedir function to utils.py and add explode_dep_versions function
- - Raise an exception if SRCREV == 'INVALID'
- - Fix hg fetcher username/password handling and fix crash
- - Fix PACKAGES_DYNAMIC handling of packages with '++' in the name
- - Rename __depends to __base_depends after configuration parsing so we don't
- recheck the validity of the config files time after time
- - Add better environmental variable handling. By default it will now only pass certain
- whitelisted variables into the data store. If BB_PRESERVE_ENV is set bitbake will use
- all variable from the environment. If BB_ENV_WHITELIST is set, that whitelist will be
- used instead of the internal bitbake one. Alternatively, BB_ENV_EXTRAWHITE can be used
- to extend the internal whitelist.
- - Perforce fetcher fix to use commandline options instead of being overriden by the environment
- - bb.utils.prunedir can cope with symlinks to directoriees without exceptions
- - use @rev when doing a svn checkout
- - Add osc fetcher (from Joshua Lock in Poky)
- - When SRCREV autorevisioning for a recipe is in use, don't cache the recipe
- - Add tryaltconfigs option to control whether bitbake trys using alternative providers
- to fulfil failed dependencies. It defaults to off, changing the default since this
- behaviour confuses many users and isn't often useful.
- - Improve lock file function error handling
- - Add username handling to the git fetcher (Robert Bragg)
- - Add support for HTTP_PROXY and HTTP_PROXY_IGNORE variables to the wget fetcher
- - Export more variables to the fetcher commands to allow ssh checkouts and checkouts through
- proxies to work better. (from Poky)
- - Also allow user and pswd options in SRC_URIs globally (from Poky)
- - Improve proxy handling when using mirrors (from Poky)
- - Add bb.utils.prune_suffix function
- - Fix hg checkouts of specific revisions (from Poky)
- - Fix wget fetching of urls with parameters specified (from Poky)
- - Add username handling to git fetcher (from Poky)
- - Set HOME environmental variable when running fetcher commands (from Poky)
- - Make sure allowed variables inherited from the environment are exported again (from Poky)
- - When running a stage task in bbshell, run populate_staging, not the stage task (from Poky)
- - Fix + character escaping from PACKAGES_DYNAMIC (thanks Otavio Salvador)
- - Addition of BBCLASSEXTEND support for allowing one recipe to provide multiple targets (from Poky)
-
-Changes in Bitbake 1.8.0:
- - Release 1.7.x as a stable series
-
-Changes in BitBake 1.7.x:
- - Major updates of the dependency handling and execution
- of tasks. Code from bin/bitbake replaced with runqueue.py
- and taskdata.py
- - New task execution code supports multithreading with a simplistic
- threading algorithm controlled by BB_NUMBER_THREADS
- - Change of the SVN Fetcher to keep the checkout around
- courtsey of Paul Sokolovsky (#1367)
- - PATH fix to bbimage (#1108)
- - Allow debug domains to be specified on the commandline (-l)
- - Allow 'interactive' tasks
- - Logging message improvements
- - Drop now uneeded BUILD_ALL_DEPS variable
- - Add support for wildcards to -b option
- - Major overhaul of the fetchers making a large amount of code common
- including mirroring code
- - Fetchers now touch md5 stamps upon access (to show activity)
- - Fix -f force option when used without -b (long standing bug)
- - Add expand_cache to data_cache.py, caching expanded data (speedup)
- - Allow version field in DEPENDS (ignored for now)
- - Add abort flag support to the shell
- - Make inherit fail if the class doesn't exist (#1478)
- - Fix data.emit_env() to expand keynames as well as values
- - Add ssh fetcher
- - Add perforce fetcher
- - Make PREFERRED_PROVIDER_foobar defaults to foobar if available
- - Share the parser's mtime_cache, reducing the number of stat syscalls
- - Compile all anonfuncs at once!
- *** Anonfuncs must now use common spacing format ***
- - Memorise the list of handlers in __BBHANDLERS and tasks in __BBTASKS
- This removes 2 million function calls resulting in a 5-10% speedup
- - Add manpage
- - Update generateDotGraph to use taskData/runQueue improving accuracy
- and also adding a task dependency graph
- - Fix/standardise on GPLv2 licence
- - Move most functionality from bin/bitbake to cooker.py and split into
- separate funcitons
- - CVS fetcher: Added support for non-default port
- - Add BBINCLUDELOGS_LINES, the number of lines to read from any logfile
- - Drop shebangs from lib/bb scripts
-
-Changes in Bitbake 1.6.0:
- - Better msg handling
- - COW dict implementation from Tim Ansell (mithro) leading
- to better performance
- - Speed up of -s
-
-Changes in Bitbake 1.4.4:
- - SRCDATE now handling courtsey Justin Patrin
- - #1017 fix to work with rm_work
-
-Changes in BitBake 1.4.2:
- - Send logs to oe.pastebin.com instead of pastebin.com
- fixes #856
- - Copy the internal bitbake data before building the
- dependency graph. This fixes nano not having a
- virtual/libc dependency
- - Allow multiple TARBALL_STASH entries
- - Cache, check if the directory exists before changing
- into it
- - git speedup cloning by not doing a checkout
- - allow to have spaces in filenames (.conf, .bb, .bbclass)
-
-Changes in BitBake 1.4.0:
- - Fix to check both RDEPENDS and RDEPENDS_${PN}
- - Fix a RDEPENDS parsing bug in utils:explode_deps()
- - Update git fetcher behaviour to match git changes
- - ASSUME_PROVIDED allowed to include runtime packages
- - git fetcher cleanup and efficency improvements
- - Change the format of the cache
- - Update usermanual to document the Fetchers
- - Major changes to caching with a new strategy
- giving a major performance increase when reparsing
- with few data changes
-
-Changes in BitBake 1.3.3:
- - Create a new Fetcher module to ease the
- development of new Fetchers.
- Issue #438 fixed by rpurdie@openedhand.com
- - Make the Subversion fetcher honor the SRC Date
- (CVSDATE).
- Issue #555 fixed by chris@openedhand.com
- - Expand PREFERRED_PROVIDER properly
- Issue #436 fixed by rprudie@openedhand.com
- - Typo fix for Issue #531 by Philipp Zabel for the
- BitBake Shell
- - Introduce a new special variable SRCDATE as
- a generic naming to replace CVSDATE.
- - Introduce a new keyword 'required'. In contrast
- to 'include' parsing will fail if a to be included
- file can not be found.
- - Remove hardcoding of the STAMP directory. Patch
- courtsey pHilipp Zabel
- - Track the RDEPENDS of each package (rpurdie@openedhand.com)
- - Introduce BUILD_ALL_DEPS to build all RDEPENDS. E.g
- this is used by the OpenEmbedded Meta Packages.
- (rpurdie@openedhand.com).
-
-Changes in BitBake 1.3.2:
- - reintegration of make.py into BitBake
- - bbread is gone, use bitbake -e
- - lots of shell updates and bugfixes
- - Introduction of the .= and =. operator
- - Sort variables, keys and groups in bitdoc
- - Fix regression in the handling of BBCOLLECTIONS
- - Update the bitbake usermanual
-
-Changes in BitBake 1.3.0:
- - add bitbake interactive shell (bitbake -i)
- - refactor bitbake utility in OO style
- - kill default arguments in methods in the bb.data module
- - kill default arguments in methods in the bb.fetch module
- - the http/https/ftp fetcher will fail if the to be
- downloaded file was not found in DL_DIR (this is needed
- to avoid unpacking the sourceforge mirror page)
- - Switch to a cow like data instance for persistent and non
- persisting mode (called data_smart.py)
- - Changed the callback of bb.make.collect_bbfiles to carry
- additional parameters
- - Drastically reduced the amount of needed RAM by not holding
- each data instance in memory when using a cache/persistent
- storage
-
-Changes in BitBake 1.2.1:
- The 1.2.1 release is meant as a intermediate release to lay the
- ground for more radical changes. The most notable changes are:
-
- - Do not hardcode {}, use bb.data.init() instead if you want to
- get a instance of a data class
- - bb.data.init() is a factory and the old bb.data methods are delegates
- - Do not use deepcopy use bb.data.createCopy() instead.
- - Removed default arguments in bb.fetch
+Changes in SRTool 0.0.4:
diff --git a/LICENSE b/LICENSE
index 7d4e5f44..06e544e3 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,19 +1,7 @@
-BitBake is licensed under the GNU General Public License version 2.0. See COPYING for further details.
+SRTool is licensed under the GNU General Public License version 2.0. See COPYING for further details.
The following external components are distributed with this software:
-* The Toaster Simple UI application is based upon the Django project template, the files of which are covered by the BSD license and are copyright (c) Django Software
+* The SRTool Simple UI application is based upon the Django project template, the files of which are covered by the BSD license and are copyright (c) Django Software
Foundation and individual contributors.
-* Twitter Bootstrap (including Glyphicons), redistributed under the MIT license
-* jQuery is redistributed under the MIT license.
-
-* Twitter typeahead.js redistributed under the MIT license. Note that the JS source has one small modification, so the full unminified file is currently included to make it obvious where this is.
-
-* jsrender is redistributed under the MIT license.
-
-* QUnit is redistributed under the MIT license.
-
-* Font Awesome fonts redistributed under the SIL Open Font License 1.1
-
-* simplediff is distributed under the zlib license.
diff --git a/MANIFEST.in b/MANIFEST.in
index b1973781..5bf518c2 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,11 +1,9 @@
include COPYING
include ChangeLog
include AUTHORS
-include contrib/*
-include contrib/vim/*/*
-include conf/*
-include classes/*
+include data/*
+include lib/*
+include filters/*
include doc/*
-include doc/manual/*
-include ez_setup.py
include HEADER
+
diff --git a/README b/README
index 479c3765..429b85ed 100644
--- a/README
+++ b/README
@@ -1,35 +1,28 @@
-Bitbake
+SRTool
=======
-BitBake is a generic task execution engine that allows shell and Python tasks to be run
-efficiently and in parallel while working within complex inter-task dependency constraints.
-One of BitBake's main users, OpenEmbedded, takes this core and builds embedded Linux software
-stacks using a task-oriented approach.
+SRTool is a set of GUI and command line tools to manage security CVEs.
-For information about Bitbake, see the OpenEmbedded website:
- http://www.openembedded.org/
-Bitbake plain documentation can be found under the doc directory or its integrated
+For information about SRTool, see the website:
+ http://www.tbd.org/
+
+SRTool plain documentation can be found under the doc directory or its integrated
html version at the Yocto Project website:
- http://yoctoproject.org/documentation
+ http://tbd.org/documentation
Contributing
------------
Please refer to
-http://www.openembedded.org/wiki/How_to_submit_a_patch_to_OpenEmbedded
-for guidelines on how to submit patches, just note that the latter documentation is intended
-for OpenEmbedded (and its core) not bitbake patches (bitbake-devel@lists.openembedded.org)
-but in general main guidelines apply. Once the commit(s) have been created, the way to send
-the patch is through git-send-email. For example, to send the last commit (HEAD) on current
-branch, type:
-
- git send-email -M -1 --to bitbake-devel@lists.openembedded.org
+http://www.tbd.org/wiki/tbd
+for guidelines on how to submit patches.
Mailing list:
- http://lists.openembedded.org/mailman/listinfo/bitbake-devel
+ http://lists.tbd.org/mailman/listinfo/tbd
Source code:
- http://git.openembedded.org/bitbake/
+ ssh://git@push.yoctoproject.org/srtool
+
diff --git a/TODO b/TODO
index 54d091fb..b10262af 100644
--- a/TODO
+++ b/TODO
@@ -1,62 +1,2 @@
-- Reimplement the interactive mode as a proper ui
-- Continue dropping fatal/SystemExit/sys.exit usage in favor of raising
- appropriate exceptions
-- Continue pylint / pyflakes / pychecker / pep8 fixups
-- Drop os.system usage in favor of direct subprocess usage or a subprocess
- wrapper
-- Kill the execution of 'tee' for the task log file in build.py
-- Fix up the exception handling
-
- - Kill exec_task's catch of FuncFailed, instead catch it in the other
- callers of exec_task/exec_func
- - What exactly is the purpose of the "EventException"? I can see using an
- exception like that, *perhaps*, to abstract away exceptions raised by
- event handlers, but it has no place in bb.build.exec_task
-
-- BUG: if you chmod 000 local.conf, it silently doesn't parse it, when it
- should really fail, so the user can fix the problem.
-
-- Audit bb.fatal usage - these should all be able to be replaced with
- exceptions
-- Figure out how to handle the ncurses UI. Should some of our logging
- formatting stuff be made common to all of bitbake, or perhaps all UIs via
- the UIHelper?
-
-Long term, high impact:
-
- - Change override application to actually *move* it over -- so the original
- override specific version of the variable goes away, rather than sticking
- around as a duplicate.
- - Change the behavior when a variable is referenced and is unset. Today, it
- evaluates to ${FOO} and then shell has a chance to expand it, but this is
- far from ideal. We had considered evaluating it to the empty string, but
- that has other potential problems. Frans Meulenbroeks has proposed just
- erroring when this occurs, as we can always define default values for the
- variables in bitbake.conf. This seems reasonable. My only concern with
- that is the case where you want to reference a shell variable with odd
- characters in it -- where you'd have to use ${} style shell variable
- expansion rather than normal $. To handle that case, we'd really need a
- way to escape / disable bitbake variable expansion, \${} perhaps.
-
-Uncertain:
-
- - Leverage the python 2.6 multiprocessing module
-
- - Worker processes for bb.cooker
- - Server / UI processes
-
- - Create a bitbake configuration class which is utilized by the library, not
- just bin/bitbake. This class should be responsible for extracting
- configuration parameters from the metadata for bitbake internal use, as well
- as pulling specific items like BBDEBUG, and importing settings from an
- optparse options object.
-
- - Python version bits
-
- - Utilize the new string formatting where appropriate
- - Do we need to take into account the bytes literals changes?
- - Do we have any file-like objects that would benefit from using the "io"
- module?
- - Do we want to leverage the abstract base classes in collections?
- - Aside: Set methods now accept multiple iterables
+Todo for SRTool
diff --git a/lib/bldcollector/admin.py b/lib/bldcollector/admin.py
deleted file mode 100644
index 1f2e07f5..00000000
--- a/lib/bldcollector/admin.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from django.contrib import admin
-from orm.models import BitbakeVersion, Release, ToasterSetting, Layer_Version
-from django import forms
-import django.db.models as models
-
-
-class BitbakeVersionAdmin(admin.ModelAdmin):
-
- # we override the formfield for db URLField
- # because of broken URL validation
-
- def formfield_for_dbfield(self, db_field, **kwargs):
- if isinstance(db_field, models.fields.URLField):
- return forms.fields.CharField()
- return super(BitbakeVersionAdmin, self).formfield_for_dbfield(
- db_field, **kwargs)
-
-
-class ReleaseAdmin(admin.ModelAdmin):
- pass
-
-
-class ToasterSettingAdmin(admin.ModelAdmin):
- pass
-
-
-class LayerVersionsAdmin(admin.ModelAdmin):
- pass
-
-admin.site.register(Layer_Version, LayerVersionsAdmin)
-admin.site.register(BitbakeVersion, BitbakeVersionAdmin)
-admin.site.register(Release, ReleaseAdmin)
-admin.site.register(ToasterSetting, ToasterSettingAdmin)
diff --git a/lib/bldcollector/urls.py b/lib/bldcollector/urls.py
deleted file mode 100644
index 888175d0..00000000
--- a/lib/bldcollector/urls.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2014-2017 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-
-from django.conf.urls import include, url
-
-import bldcollector.views
-
-urlpatterns = [
- # landing point for pushing a bitbake_eventlog.json file to this toaster instace
- url(r'^eventfile$', bldcollector.views.eventfile, name='eventfile'),
-]
diff --git a/lib/bldcollector/views.py b/lib/bldcollector/views.py
deleted file mode 100644
index f32fa4d2..00000000
--- a/lib/bldcollector/views.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2014 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-from django.views.decorators.cache import cache_control
-from django.core.urlresolvers import reverse
-from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
-from django.http import HttpResponseBadRequest, HttpResponse
-from django.utils import timezone
-from django.utils.html import escape
-from datetime import timedelta
-from django.utils import formats
-from toastergui.templatetags.projecttags import json as jsonfilter
-import json
-import os
-import tempfile
-import subprocess
-import toastermain
-from django.views.decorators.csrf import csrf_exempt
-
-
-@csrf_exempt
-def eventfile(request):
- """ Receives a file by POST, and runs toaster-eventreply on this file """
- if request.method != "POST":
- return HttpResponseBadRequest("This API only accepts POST requests. Post a file with:\n\ncurl -F eventlog=@bitbake_eventlog.json %s\n" % request.build_absolute_uri(reverse('eventfile')), content_type="text/plain;utf8")
-
- # write temporary file
- (handle, abstemppath) = tempfile.mkstemp(dir="/tmp/")
- with os.fdopen(handle, "w") as tmpfile:
- for chunk in request.FILES['eventlog'].chunks():
- tmpfile.write(chunk)
- tmpfile.close()
-
- # compute the path to "bitbake/bin/toaster-eventreplay"
- from os.path import dirname as DN
- import_script = os.path.join(DN(DN(DN(DN(os.path.abspath(__file__))))), "bin/toaster-eventreplay")
- if not os.path.exists(import_script):
- raise Exception("script missing %s" % import_script)
- scriptenv = os.environ.copy()
- scriptenv["DATABASE_URL"] = toastermain.settings.getDATABASE_URL()
-
- # run the data loading process and return the results
- importer = subprocess.Popen([import_script, abstemppath], stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=scriptenv)
- (out, err) = importer.communicate()
- if importer.returncode == 0:
- os.remove(abstemppath)
- return HttpResponse("== Retval %d\n== STDOUT\n%s\n\n== STDERR\n%s" % (importer.returncode, out, err), content_type="text/plain;utf8")
diff --git a/lib/bldcontrol/admin.py b/lib/bldcontrol/admin.py
deleted file mode 100644
index fcbe5f59..00000000
--- a/lib/bldcontrol/admin.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from django.contrib import admin
-from django.contrib.admin.filters import RelatedFieldListFilter
-from .models import BuildEnvironment
-
-class BuildEnvironmentAdmin(admin.ModelAdmin):
- pass
-
-admin.site.register(BuildEnvironment, BuildEnvironmentAdmin)
diff --git a/lib/bldcontrol/bbcontroller.py b/lib/bldcontrol/bbcontroller.py
deleted file mode 100644
index 5195600d..00000000
--- a/lib/bldcontrol/bbcontroller.py
+++ /dev/null
@@ -1,142 +0,0 @@
-#
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2014 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-
-import os
-import sys
-import re
-from django.db import transaction
-from django.db.models import Q
-from bldcontrol.models import BuildEnvironment, BRLayer, BRVariable, BRTarget, BRBitbake
-
-# load Bitbake components
-path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
-sys.path.insert(0, path)
-
-class BitbakeController(object):
- """ This is the basic class that controlls a bitbake server.
- It is outside the scope of this class on how the server is started and aquired
- """
-
- def __init__(self, be):
- import bb.server.xmlrpcclient
- self.connection = bb.server.xmlrpcclient._create_server(be.bbaddress,
- int(be.bbport))[0]
-
- def _runCommand(self, command):
- result, error = self.connection.runCommand(command)
- if error:
- raise Exception(error)
- return result
-
- def disconnect(self):
- return self.connection.removeClient()
-
- def setVariable(self, name, value):
- return self._runCommand(["setVariable", name, value])
-
- def getVariable(self, name):
- return self._runCommand(["getVariable", name])
-
- def triggerEvent(self, event):
- return self._runCommand(["triggerEvent", event])
-
- def build(self, targets, task = None):
- if task is None:
- task = "build"
- return self._runCommand(["buildTargets", targets, task])
-
- def forceShutDown(self):
- return self._runCommand(["stateForceShutdown"])
-
-
-
-def getBuildEnvironmentController(**kwargs):
- """ Gets you a BuildEnvironmentController that encapsulates a build environment,
- based on the query dictionary sent in.
-
- This is used to retrieve, for example, the currently running BE from inside
- the toaster UI, or find a new BE to start a new build in it.
-
- The return object MUST always be a BuildEnvironmentController.
- """
-
- from bldcontrol.localhostbecontroller import LocalhostBEController
-
- be = BuildEnvironment.objects.filter(Q(**kwargs))[0]
- if be.betype == BuildEnvironment.TYPE_LOCAL:
- return LocalhostBEController(be)
- else:
- raise Exception("FIXME: Implement BEC for type %s" % str(be.betype))
-
-
-class BuildEnvironmentController(object):
- """ BuildEnvironmentController (BEC) is the abstract class that defines the operations that MUST
- or SHOULD be supported by a Build Environment. It is used to establish the framework, and must
- not be instantiated directly by the user.
-
- Use the "getBuildEnvironmentController()" function to get a working BEC for your remote.
-
- How the BuildEnvironments are discovered is outside the scope of this class.
-
- You must derive this class to teach Toaster how to operate in your own infrastructure.
- We provide some specific BuildEnvironmentController classes that can be used either to
- directly set-up Toaster infrastructure, or as a model for your own infrastructure set:
-
- * Localhost controller will run the Toaster BE on the same account as the web server
- (current user if you are using the the Django development web server)
- on the local machine, with the "build/" directory under the "poky/" source checkout directory.
- Bash is expected to be available.
-
- """
- def __init__(self, be):
- """ Takes a BuildEnvironment object as parameter that points to the settings of the BE.
- """
- self.be = be
- self.connection = None
-
- def setLayers(self, bitbake, ls):
- """ Checks-out bitbake executor and layers from git repositories.
- Sets the layer variables in the config file, after validating local layer paths.
- bitbake must be a single BRBitbake instance
- The layer paths must be in a list of BRLayer object
-
- a word of attention: by convention, the first layer for any build will be poky!
- """
- raise NotImplementedError("FIXME: Must override setLayers")
-
- def getArtifact(self, path):
- """ This call returns an artifact identified by the 'path'. How 'path' is interpreted as
- up to the implementing BEC. The return MUST be a REST URL where a GET will actually return
- the content of the artifact, e.g. for use as a "download link" in a web UI.
- """
- raise NotImplementedError("Must return the REST URL of the artifact")
-
- def triggerBuild(self, bitbake, layers, variables, targets):
- raise NotImplementedError("Must override BE release")
-
-class ShellCmdException(Exception):
- pass
-
-
-class BuildSetupException(Exception):
- pass
-
diff --git a/lib/bldcontrol/localhostbecontroller.py b/lib/bldcontrol/localhostbecontroller.py
deleted file mode 100644
index 16c7c804..00000000
--- a/lib/bldcontrol/localhostbecontroller.py
+++ /dev/null
@@ -1,401 +0,0 @@
-#
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2014 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-
-import os
-import sys
-import re
-import shutil
-import time
-from django.db import transaction
-from django.db.models import Q
-from bldcontrol.models import BuildEnvironment, BRLayer, BRVariable, BRTarget, BRBitbake
-from orm.models import CustomImageRecipe, Layer, Layer_Version, ProjectLayer, ToasterSetting
-import subprocess
-
-from toastermain import settings
-
-from bldcontrol.bbcontroller import BuildEnvironmentController, ShellCmdException, BuildSetupException, BitbakeController
-
-import logging
-logger = logging.getLogger("toaster")
-
-from pprint import pprint, pformat
-
-class LocalhostBEController(BuildEnvironmentController):
- """ Implementation of the BuildEnvironmentController for the localhost;
- this controller manages the default build directory,
- the server setup and system start and stop for the localhost-type build environment
-
- """
-
- def __init__(self, be):
- super(LocalhostBEController, self).__init__(be)
- self.pokydirname = None
- self.islayerset = False
-
- def _shellcmd(self, command, cwd=None, nowait=False,env=None):
- if cwd is None:
- cwd = self.be.sourcedir
- if env is None:
- env=os.environ.copy()
-
- logger.debug("lbc_shellcmd: (%s) %s" % (cwd, command))
- p = subprocess.Popen(command, cwd = cwd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
- if nowait:
- return
- (out,err) = p.communicate()
- p.wait()
- if p.returncode:
- if len(err) == 0:
- err = "command: %s \n%s" % (command, out)
- else:
- err = "command: %s \n%s" % (command, err)
- logger.warning("localhostbecontroller: shellcmd error %s" % err)
- raise ShellCmdException(err)
- else:
- logger.debug("localhostbecontroller: shellcmd success")
- return out.decode('utf-8')
-
- def getGitCloneDirectory(self, url, branch):
- """Construct unique clone directory name out of url and branch."""
- if branch != "HEAD":
- return "_toaster_clones/_%s_%s" % (re.sub('[:/@+%]', '_', url), branch)
-
- # word of attention; this is a localhost-specific issue; only on the localhost we expect to have "HEAD" releases
- # which _ALWAYS_ means the current poky checkout
- from os.path import dirname as DN
- local_checkout_path = DN(DN(DN(DN(DN(os.path.abspath(__file__))))))
- #logger.debug("localhostbecontroller: using HEAD checkout in %s" % local_checkout_path)
- return local_checkout_path
-
-
- def setCloneStatus(self,bitbake,status,total,current):
- bitbake.req.build.repos_cloned=current
- bitbake.req.build.repos_to_clone=total
- bitbake.req.build.save()
-
- def setLayers(self, bitbake, layers, targets):
- """ a word of attention: by convention, the first layer for any build will be poky! """
-
- assert self.be.sourcedir is not None
-
- layerlist = []
- nongitlayerlist = []
- git_env = os.environ.copy()
- # (note: add custom environment settings here)
-
- # set layers in the layersource
-
- # 1. get a list of repos with branches, and map dirpaths for each layer
- gitrepos = {}
-
- # if we're using a remotely fetched version of bitbake add its git
- # details to the list of repos to clone
- if bitbake.giturl and bitbake.commit:
- gitrepos[(bitbake.giturl, bitbake.commit)] = []
- gitrepos[(bitbake.giturl, bitbake.commit)].append(
- ("bitbake", bitbake.dirpath))
-
- for layer in layers:
- # We don't need to git clone the layer for the CustomImageRecipe
- # as it's generated by us layer on if needed
- if CustomImageRecipe.LAYER_NAME in layer.name:
- continue
-
- # If we have local layers then we don't need clone them
- # For local layers giturl will be empty
- if not layer.giturl:
- nongitlayerlist.append(layer.layer_version.layer.local_source_dir)
- continue
-
- if not (layer.giturl, layer.commit) in gitrepos:
- gitrepos[(layer.giturl, layer.commit)] = []
- gitrepos[(layer.giturl, layer.commit)].append( (layer.name, layer.dirpath) )
-
-
- logger.debug("localhostbecontroller, our git repos are %s" % pformat(gitrepos))
-
-
- # 2. Note for future use if the current source directory is a
- # checked-out git repos that could match a layer's vcs_url and therefore
- # be used to speed up cloning (rather than fetching it again).
-
- cached_layers = {}
-
- try:
- for remotes in self._shellcmd("git remote -v", self.be.sourcedir,env=git_env).split("\n"):
- try:
- remote = remotes.split("\t")[1].split(" ")[0]
- if remote not in cached_layers:
- cached_layers[remote] = self.be.sourcedir
- except IndexError:
- pass
- except ShellCmdException:
- # ignore any errors in collecting git remotes this is an optional
- # step
- pass
-
- logger.info("Using pre-checked out source for layer %s", cached_layers)
-
- # 3. checkout the repositories
- clone_count=0
- clone_total=len(gitrepos.keys())
- self.setCloneStatus(bitbake,'Started',clone_total,clone_count)
- for giturl, commit in gitrepos.keys():
- self.setCloneStatus(bitbake,'progress',clone_total,clone_count)
- clone_count += 1
-
- localdirname = os.path.join(self.be.sourcedir, self.getGitCloneDirectory(giturl, commit))
- logger.debug("localhostbecontroller: giturl %s:%s checking out in current directory %s" % (giturl, commit, localdirname))
-
- # see if our directory is a git repository
- if os.path.exists(localdirname):
- try:
- localremotes = self._shellcmd("git remote -v",
- localdirname,env=git_env)
- if not giturl in localremotes and commit != 'HEAD':
- raise BuildSetupException("Existing git repository at %s, but with different remotes ('%s', expected '%s'). Toaster will not continue out of fear of damaging something." % (localdirname, ", ".join(localremotes.split("\n")), giturl))
- except ShellCmdException:
- # our localdirname might not be a git repository
- #- that's fine
- pass
- else:
- if giturl in cached_layers:
- logger.debug("localhostbecontroller git-copying %s to %s" % (cached_layers[giturl], localdirname))
- self._shellcmd("git clone \"%s\" \"%s\"" % (cached_layers[giturl], localdirname),env=git_env)
- self._shellcmd("git remote remove origin", localdirname,env=git_env)
- self._shellcmd("git remote add origin \"%s\"" % giturl, localdirname,env=git_env)
- else:
- logger.debug("localhostbecontroller: cloning %s in %s" % (giturl, localdirname))
- self._shellcmd('git clone "%s" "%s"' % (giturl, localdirname),env=git_env)
-
- # branch magic name "HEAD" will inhibit checkout
- if commit != "HEAD":
- logger.debug("localhostbecontroller: checking out commit %s to %s " % (commit, localdirname))
- ref = commit if re.match('^[a-fA-F0-9]+$', commit) else 'origin/%s' % commit
- self._shellcmd('git fetch && git reset --hard "%s"' % ref, localdirname,env=git_env)
-
- # take the localdirname as poky dir if we can find the oe-init-build-env
- if self.pokydirname is None and os.path.exists(os.path.join(localdirname, "oe-init-build-env")):
- logger.debug("localhostbecontroller: selected poky dir name %s" % localdirname)
- self.pokydirname = localdirname
-
- # make sure we have a working bitbake
- if not os.path.exists(os.path.join(self.pokydirname, 'bitbake')):
- logger.debug("localhostbecontroller: checking bitbake into the poky dirname %s " % self.pokydirname)
- self._shellcmd("git clone -b \"%s\" \"%s\" \"%s\" " % (bitbake.commit, bitbake.giturl, os.path.join(self.pokydirname, 'bitbake')),env=git_env)
-
- # verify our repositories
- for name, dirpath in gitrepos[(giturl, commit)]:
- localdirpath = os.path.join(localdirname, dirpath)
- logger.debug("localhostbecontroller: localdirpath expected '%s'" % localdirpath)
- if not os.path.exists(localdirpath):
- raise BuildSetupException("Cannot find layer git path '%s' in checked out repository '%s:%s'. Aborting." % (localdirpath, giturl, commit))
-
- if name != "bitbake":
- layerlist.append(localdirpath.rstrip("/"))
-
- self.setCloneStatus(bitbake,'complete',clone_total,clone_count)
- logger.debug("localhostbecontroller: current layer list %s " % pformat(layerlist))
-
- if self.pokydirname is None and os.path.exists(os.path.join(self.be.sourcedir, "oe-init-build-env")):
- logger.debug("localhostbecontroller: selected poky dir name %s" % self.be.sourcedir)
- self.pokydirname = self.be.sourcedir
-
- # 5. create custom layer and add custom recipes to it
- for target in targets:
- try:
- customrecipe = CustomImageRecipe.objects.get(
- name=target.target,
- project=bitbake.req.project)
-
- custom_layer_path = self.setup_custom_image_recipe(
- customrecipe, layers)
-
- if os.path.isdir(custom_layer_path):
- layerlist.append(custom_layer_path)
-
- except CustomImageRecipe.DoesNotExist:
- continue # not a custom recipe, skip
-
- layerlist.extend(nongitlayerlist)
- logger.debug("\n\nset layers gives this list %s" % pformat(layerlist))
- self.islayerset = True
- return layerlist
-
- def setup_custom_image_recipe(self, customrecipe, layers):
- """ Set up toaster-custom-images layer and recipe files """
- layerpath = os.path.join(self.be.builddir,
- CustomImageRecipe.LAYER_NAME)
-
- # create directory structure
- for name in ("conf", "recipes"):
- path = os.path.join(layerpath, name)
- if not os.path.isdir(path):
- os.makedirs(path)
-
- # create layer.conf
- config = os.path.join(layerpath, "conf", "layer.conf")
- if not os.path.isfile(config):
- with open(config, "w") as conf:
- conf.write('BBPATH .= ":${LAYERDIR}"\nBBFILES += "${LAYERDIR}/recipes/*.bb"\n')
-
- # Update the Layer_Version dirpath that has our base_recipe in
- # to be able to read the base recipe to then generate the
- # custom recipe.
- br_layer_base_recipe = layers.get(
- layer_version=customrecipe.base_recipe.layer_version)
-
- # If the layer is one that we've cloned we know where it lives
- if br_layer_base_recipe.giturl and br_layer_base_recipe.commit:
- layer_path = self.getGitCloneDirectory(
- br_layer_base_recipe.giturl,
- br_layer_base_recipe.commit)
- # Otherwise it's a local layer
- elif br_layer_base_recipe.local_source_dir:
- layer_path = br_layer_base_recipe.local_source_dir
- else:
- logger.error("Unable to workout the dir path for the custom"
- " image recipe")
-
- br_layer_base_dirpath = os.path.join(
- self.be.sourcedir,
- layer_path,
- customrecipe.base_recipe.layer_version.dirpath)
-
- customrecipe.base_recipe.layer_version.dirpath = br_layer_base_dirpath
-
- customrecipe.base_recipe.layer_version.save()
-
- # create recipe
- recipe_path = os.path.join(layerpath, "recipes", "%s.bb" %
- customrecipe.name)
- with open(recipe_path, "w") as recipef:
- recipef.write(customrecipe.generate_recipe_file_contents())
-
- # Update the layer and recipe objects
- customrecipe.layer_version.dirpath = layerpath
- customrecipe.layer_version.layer.local_source_dir = layerpath
- customrecipe.layer_version.layer.save()
- customrecipe.layer_version.save()
-
- customrecipe.file_path = recipe_path
- customrecipe.save()
-
- return layerpath
-
-
- def readServerLogFile(self):
- return open(os.path.join(self.be.builddir, "toaster_server.log"), "r").read()
-
-
- def triggerBuild(self, bitbake, layers, variables, targets, brbe):
- layers = self.setLayers(bitbake, layers, targets)
-
- # init build environment from the clone
- builddir = '%s-toaster-%d' % (self.be.builddir, bitbake.req.project.id)
- oe_init = os.path.join(self.pokydirname, 'oe-init-build-env')
- # init build environment
- try:
- custom_script = ToasterSetting.objects.get(name="CUSTOM_BUILD_INIT_SCRIPT").value
- custom_script = custom_script.replace("%BUILDDIR%" ,builddir)
- self._shellcmd("bash -c 'source %s'" % (custom_script))
- except ToasterSetting.DoesNotExist:
- self._shellcmd("bash -c 'source %s %s'" % (oe_init, builddir),
- self.be.sourcedir)
-
- # update bblayers.conf
- bblconfpath = os.path.join(builddir, "conf/toaster-bblayers.conf")
- with open(bblconfpath, 'w') as bblayers:
- bblayers.write('# line added by toaster build control\n'
- 'BBLAYERS = "%s"' % ' '.join(layers))
-
- # write configuration file
- confpath = os.path.join(builddir, 'conf/toaster.conf')
- with open(confpath, 'w') as conf:
- for var in variables:
- conf.write('%s="%s"\n' % (var.name, var.value))
- conf.write('INHERIT+="toaster buildhistory"')
-
- # clean the Toaster to build environment
- env_clean = 'unset BBPATH;' # clean BBPATH for <= YP-2.4.0
-
- # run bitbake server from the clone
- bitbake = os.path.join(self.pokydirname, 'bitbake', 'bin', 'bitbake')
- toasterlayers = os.path.join(builddir,"conf/toaster-bblayers.conf")
- self._shellcmd('%s bash -c \"source %s %s; BITBAKE_UI="knotty" %s --read %s --read %s '
- '--server-only -B 0.0.0.0:0\"' % (env_clean, oe_init,
- builddir, bitbake, confpath, toasterlayers), self.be.sourcedir)
-
- # read port number from bitbake.lock
- self.be.bbport = -1
- bblock = os.path.join(builddir, 'bitbake.lock')
- # allow 10 seconds for bb lock file to appear but also be populated
- for lock_check in range(10):
- if not os.path.exists(bblock):
- logger.debug("localhostbecontroller: waiting for bblock file to appear")
- time.sleep(1)
- continue
- if 10 < os.stat(bblock).st_size:
- break
- logger.debug("localhostbecontroller: waiting for bblock content to appear")
- time.sleep(1)
- else:
- raise BuildSetupException("Cannot find bitbake server lock file '%s'. Aborting." % bblock)
-
- with open(bblock) as fplock:
- for line in fplock:
- if ":" in line:
- self.be.bbport = line.split(":")[-1].strip()
- logger.debug("localhostbecontroller: bitbake port %s", self.be.bbport)
- break
-
- if -1 == self.be.bbport:
- raise BuildSetupException("localhostbecontroller: can't read bitbake port from %s" % bblock)
-
- self.be.bbaddress = "localhost"
- self.be.bbstate = BuildEnvironment.SERVER_STARTED
- self.be.lock = BuildEnvironment.LOCK_RUNNING
- self.be.save()
-
- bbtargets = ''
- for target in targets:
- task = target.task
- if task:
- if not task.startswith('do_'):
- task = 'do_' + task
- task = ':%s' % task
- bbtargets += '%s%s ' % (target.target, task)
-
- # run build with local bitbake. stop the server after the build.
- log = os.path.join(builddir, 'toaster_ui.log')
- local_bitbake = os.path.join(os.path.dirname(os.getenv('BBBASEDIR')),
- 'bitbake')
- self._shellcmd(['%s bash -c \"(TOASTER_BRBE="%s" BBSERVER="0.0.0.0:%s" '
- '%s %s -u toasterui --read %s --read %s --token="" >>%s 2>&1;'
- 'BITBAKE_UI="knotty" BBSERVER=0.0.0.0:%s %s -m)&\"' \
- % (env_clean, brbe, self.be.bbport, local_bitbake, bbtargets, confpath, toasterlayers, log,
- self.be.bbport, bitbake,)],
- builddir, nowait=True)
-
- logger.debug('localhostbecontroller: Build launched, exiting. '
- 'Follow build logs at %s' % log)
diff --git a/lib/bldcontrol/management/commands/checksettings.py b/lib/bldcontrol/management/commands/checksettings.py
deleted file mode 100644
index 823c6f15..00000000
--- a/lib/bldcontrol/management/commands/checksettings.py
+++ /dev/null
@@ -1,167 +0,0 @@
-from django.core.management.base import BaseCommand, CommandError
-from django.db import transaction
-
-from django.core.management import call_command
-from bldcontrol.bbcontroller import getBuildEnvironmentController, ShellCmdException
-from bldcontrol.models import BuildRequest, BuildEnvironment, BRError
-from orm.models import ToasterSetting, Build, Layer
-
-import os
-import traceback
-import warnings
-
-
-def DN(path):
- if path is None:
- return ""
- else:
- return os.path.dirname(path)
-
-
-class Command(BaseCommand):
- args = ""
- help = "Verifies that the configured settings are valid and usable, or prompts the user to fix the settings."
-
- def __init__(self, *args, **kwargs):
- super(Command, self).__init__(*args, **kwargs)
- self.guesspath = DN(DN(DN(DN(DN(DN(DN(__file__)))))))
-
- def _verify_build_environment(self):
- # provide a local build env. This will be extended later to include non local
- if BuildEnvironment.objects.count() == 0:
- BuildEnvironment.objects.create(betype=BuildEnvironment.TYPE_LOCAL)
-
- # we make sure we have builddir and sourcedir for all defined build envionments
- for be in BuildEnvironment.objects.all():
- be.needs_import = False
- def _verify_be():
- is_changed = False
-
- def _update_sourcedir():
- be.sourcedir = os.environ.get('TOASTER_DIR')
- return True
-
- if len(be.sourcedir) == 0:
- is_changed = _update_sourcedir()
-
- if not be.sourcedir.startswith("/"):
- print("\n -- Validation: The layers checkout directory must be set to an absolute path.")
- is_changed = _update_sourcedir()
-
- if is_changed:
- if be.betype == BuildEnvironment.TYPE_LOCAL:
- be.needs_import = True
- return True
-
- def _update_builddir():
- be.builddir = os.environ.get('TOASTER_DIR')+"/build"
- return True
-
- if len(be.builddir) == 0:
- is_changed = _update_builddir()
-
- if not be.builddir.startswith("/"):
- print("\n -- Validation: The build directory must to be set to an absolute path.")
- is_changed = _update_builddir()
-
- if is_changed:
- print("\nBuild configuration saved")
- be.save()
- return True
-
- if be.needs_import:
- try:
- print("Loading default settings")
- call_command("loaddata", "settings")
- template_conf = os.environ.get("TEMPLATECONF", "")
-
- if ToasterSetting.objects.filter(name='CUSTOM_XML_ONLY').count() > 0:
- # only use the custom settings
- pass
- elif "poky" in template_conf:
- print("Loading poky configuration")
- call_command("loaddata", "poky")
- else:
- print("Loading OE-Core configuration")
- call_command("loaddata", "oe-core")
- if template_conf:
- oe_core_path = os.path.realpath(
- template_conf +
- "/../")
- else:
- print("TEMPLATECONF not found. You may have to"
- " manually configure layer paths")
- oe_core_path = input("Please enter the path of"
- " your openembedded-core "
- "layer: ")
- # Update the layer instances of openemebedded-core
- for layer in Layer.objects.filter(
- name="openembedded-core",
- local_source_dir="OE-CORE-LAYER-DIR"):
- layer.local_path = oe_core_path
- layer.save()
-
- # Import the custom fixture if it's present
- with warnings.catch_warnings():
- warnings.filterwarnings(
- action="ignore",
- message="^.*No fixture named.*$")
- print("Importing custom settings if present")
- try:
- call_command("loaddata", "custom")
- except:
- print("NOTE: optional fixture 'custom' not found")
-
- # we run lsupdates after config update
- print("\nFetching information from the layer index, "
- "please wait.\nYou can re-update any time later "
- "by running bitbake/lib/toaster/manage.py "
- "lsupdates\n")
- call_command("lsupdates")
-
- # we don't look for any other config files
- return is_changed
- except Exception as e:
- print("Failure while trying to setup toaster: %s"
- % e)
- traceback.print_exc()
-
- return is_changed
-
- while _verify_be():
- pass
- return 0
-
- def _verify_default_settings(self):
- # verify that default settings are there
- if ToasterSetting.objects.filter(name='DEFAULT_RELEASE').count() != 1:
- ToasterSetting.objects.filter(name='DEFAULT_RELEASE').delete()
- ToasterSetting.objects.get_or_create(name='DEFAULT_RELEASE', value='')
- return 0
-
- def _verify_builds_in_progress(self):
- # we are just starting up. we must not have any builds in progress, or build environments taken
- for b in BuildRequest.objects.filter(state=BuildRequest.REQ_INPROGRESS):
- BRError.objects.create(req=b, errtype="toaster",
- errmsg=
- "Toaster found this build IN PROGRESS while Toaster started up. This is an inconsistent state, and the build was marked as failed")
-
- BuildRequest.objects.filter(state=BuildRequest.REQ_INPROGRESS).update(state=BuildRequest.REQ_FAILED)
-
- BuildEnvironment.objects.update(lock=BuildEnvironment.LOCK_FREE)
-
- # also mark "In Progress builds as failures"
- from django.utils import timezone
- Build.objects.filter(outcome=Build.IN_PROGRESS).update(outcome=Build.FAILED, completed_on=timezone.now())
-
- return 0
-
-
-
- def handle(self, **options):
- retval = 0
- retval += self._verify_build_environment()
- retval += self._verify_default_settings()
- retval += self._verify_builds_in_progress()
-
- return retval
diff --git a/lib/bldcontrol/management/commands/runbuilds.py b/lib/bldcontrol/management/commands/runbuilds.py
deleted file mode 100644
index 791e53ea..00000000
--- a/lib/bldcontrol/management/commands/runbuilds.py
+++ /dev/null
@@ -1,192 +0,0 @@
-from django.core.management.base import BaseCommand
-from django.db import transaction
-from django.db.models import Q
-
-from bldcontrol.bbcontroller import getBuildEnvironmentController
-from bldcontrol.models import BuildRequest, BuildEnvironment
-from bldcontrol.models import BRError, BRVariable
-
-from orm.models import Build, LogMessage, Target
-
-import logging
-import traceback
-import signal
-import os
-
-logger = logging.getLogger("toaster")
-
-
-class Command(BaseCommand):
- args = ""
- help = "Schedules and executes build requests as possible. "\
- "Does not return (interrupt with Ctrl-C)"
-
- @transaction.atomic
- def _selectBuildEnvironment(self):
- bec = getBuildEnvironmentController(lock=BuildEnvironment.LOCK_FREE)
- bec.be.lock = BuildEnvironment.LOCK_LOCK
- bec.be.save()
- return bec
-
- @transaction.atomic
- def _selectBuildRequest(self):
- br = BuildRequest.objects.filter(state=BuildRequest.REQ_QUEUED).first()
- return br
-
- def schedule(self):
- try:
- # select the build environment and the request to build
- br = self._selectBuildRequest()
- if br:
- br.state = BuildRequest.REQ_INPROGRESS
- br.save()
- else:
- return
-
- try:
- bec = self._selectBuildEnvironment()
- except IndexError as e:
- # we could not find a BEC; postpone the BR
- br.state = BuildRequest.REQ_QUEUED
- br.save()
- logger.debug("runbuilds: No build env")
- return
-
- logger.info("runbuilds: starting build %s, environment %s" %
- (br, bec.be))
-
- # let the build request know where it is being executed
- br.environment = bec.be
- br.save()
-
- # this triggers an async build
- bec.triggerBuild(br.brbitbake, br.brlayer_set.all(),
- br.brvariable_set.all(), br.brtarget_set.all(),
- "%d:%d" % (br.pk, bec.be.pk))
-
- except Exception as e:
- logger.error("runbuilds: Error launching build %s" % e)
- traceback.print_exc()
- if "[Errno 111] Connection refused" in str(e):
- # Connection refused, read toaster_server.out
- errmsg = bec.readServerLogFile()
- else:
- errmsg = str(e)
-
- BRError.objects.create(req=br, errtype=str(type(e)), errmsg=errmsg,
- traceback=traceback.format_exc())
- br.state = BuildRequest.REQ_FAILED
- br.save()
- bec.be.lock = BuildEnvironment.LOCK_FREE
- bec.be.save()
- # Cancel the pending build and report the exception to the UI
- log_object = LogMessage.objects.create(
- build = br.build,
- level = LogMessage.EXCEPTION,
- message = errmsg)
- log_object.save()
- br.build.outcome = Build.FAILED
- br.build.save()
-
- def archive(self):
- for br in BuildRequest.objects.filter(state=BuildRequest.REQ_ARCHIVE):
- if br.build is None:
- br.state = BuildRequest.REQ_FAILED
- else:
- br.state = BuildRequest.REQ_COMPLETED
- br.save()
-
- def cleanup(self):
- from django.utils import timezone
- from datetime import timedelta
- # environments locked for more than 30 seconds
- # they should be unlocked
- BuildEnvironment.objects.filter(
- Q(buildrequest__state__in=[BuildRequest.REQ_FAILED,
- BuildRequest.REQ_COMPLETED,
- BuildRequest.REQ_CANCELLING]) &
- Q(lock=BuildEnvironment.LOCK_LOCK) &
- Q(updated__lt=timezone.now() - timedelta(seconds=30))
- ).update(lock=BuildEnvironment.LOCK_FREE)
-
- # update all Builds that were in progress and failed to start
- for br in BuildRequest.objects.filter(
- state=BuildRequest.REQ_FAILED,
- build__outcome=Build.IN_PROGRESS):
- # transpose the launch errors in ToasterExceptions
- br.build.outcome = Build.FAILED
- for brerror in br.brerror_set.all():
- logger.debug("Saving error %s" % brerror)
- LogMessage.objects.create(build=br.build,
- level=LogMessage.EXCEPTION,
- message=brerror.errmsg)
- br.build.save()
-
- # we don't have a true build object here; hence, toasterui
- # didn't have a change to release the BE lock
- br.environment.lock = BuildEnvironment.LOCK_FREE
- br.environment.save()
-
- # update all BuildRequests without a build created
- for br in BuildRequest.objects.filter(build=None):
- br.build = Build.objects.create(project=br.project,
- completed_on=br.updated,
- started_on=br.created)
- br.build.outcome = Build.FAILED
- try:
- br.build.machine = br.brvariable_set.get(name='MACHINE').value
- except BRVariable.DoesNotExist:
- pass
- br.save()
- # transpose target information
- for brtarget in br.brtarget_set.all():
- Target.objects.create(build=br.build,
- target=brtarget.target,
- task=brtarget.task)
- # transpose the launch errors in ToasterExceptions
- for brerror in br.brerror_set.all():
- LogMessage.objects.create(build=br.build,
- level=LogMessage.EXCEPTION,
- message=brerror.errmsg)
-
- br.build.save()
-
- # Make sure the LOCK is removed for builds which have been fully
- # cancelled
- for br in BuildRequest.objects.filter(
- Q(build__outcome=Build.CANCELLED) &
- Q(state=BuildRequest.REQ_CANCELLING) &
- ~Q(environment=None)):
- br.environment.lock = BuildEnvironment.LOCK_FREE
- br.environment.save()
-
- def runbuild(self):
- try:
- self.cleanup()
- except Exception as e:
- logger.warn("runbuilds: cleanup exception %s" % str(e))
-
- try:
- self.archive()
- except Exception as e:
- logger.warn("runbuilds: archive exception %s" % str(e))
-
- try:
- self.schedule()
- except Exception as e:
- logger.warn("runbuilds: schedule exception %s" % str(e))
-
- def handle(self, **options):
- pidfile_path = os.path.join(os.environ.get("BUILDDIR", "."),
- ".runbuilds.pid")
-
- with open(pidfile_path, 'w') as pidfile:
- pidfile.write("%s" % os.getpid())
-
- self.runbuild()
-
- signal.signal(signal.SIGUSR1, lambda sig, frame: None)
-
- while True:
- signal.pause()
- self.runbuild()
diff --git a/lib/bldcontrol/migrations/0001_initial.py b/lib/bldcontrol/migrations/0001_initial.py
deleted file mode 100644
index 67db3785..00000000
--- a/lib/bldcontrol/migrations/0001_initial.py
+++ /dev/null
@@ -1,113 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('orm', '0001_initial'),
- ]
-
- operations = [
- migrations.CreateModel(
- name='BRBitbake',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('giturl', models.CharField(max_length=254)),
- ('commit', models.CharField(max_length=254)),
- ('dirpath', models.CharField(max_length=254)),
- ],
- ),
- migrations.CreateModel(
- name='BRError',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('errtype', models.CharField(max_length=100)),
- ('errmsg', models.TextField()),
- ('traceback', models.TextField()),
- ],
- ),
- migrations.CreateModel(
- name='BRLayer',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('name', models.CharField(max_length=100)),
- ('giturl', models.CharField(max_length=254)),
- ('commit', models.CharField(max_length=254)),
- ('dirpath', models.CharField(max_length=254)),
- ('layer_version', models.ForeignKey(to='orm.Layer_Version', null=True)),
- ],
- ),
- migrations.CreateModel(
- name='BRTarget',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('target', models.CharField(max_length=100)),
- ('task', models.CharField(max_length=100, null=True)),
- ],
- ),
- migrations.CreateModel(
- name='BRVariable',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('name', models.CharField(max_length=100)),
- ('value', models.TextField(blank=True)),
- ],
- ),
- migrations.CreateModel(
- name='BuildEnvironment',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('address', models.CharField(max_length=254)),
- ('betype', models.IntegerField(choices=[(0, b'local'), (1, b'ssh')])),
- ('bbaddress', models.CharField(max_length=254, blank=True)),
- ('bbport', models.IntegerField(default=-1)),
- ('bbtoken', models.CharField(max_length=126, blank=True)),
- ('bbstate', models.IntegerField(default=0, choices=[(0, b'stopped'), (1, b'started')])),
- ('sourcedir', models.CharField(max_length=512, blank=True)),
- ('builddir', models.CharField(max_length=512, blank=True)),
- ('lock', models.IntegerField(default=0, choices=[(0, b'free'), (1, b'lock'), (2, b'running')])),
- ('created', models.DateTimeField(auto_now_add=True)),
- ('updated', models.DateTimeField(auto_now=True)),
- ],
- ),
- migrations.CreateModel(
- name='BuildRequest',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('state', models.IntegerField(default=0, choices=[(0, b'created'), (1, b'queued'), (2, b'in progress'), (3, b'completed'), (4, b'failed'), (5, b'deleted'), (6, b'archive')])),
- ('created', models.DateTimeField(auto_now_add=True)),
- ('updated', models.DateTimeField(auto_now=True)),
- ('build', models.OneToOneField(null=True, to='orm.Build')),
- ('environment', models.ForeignKey(to='bldcontrol.BuildEnvironment', null=True)),
- ('project', models.ForeignKey(to='orm.Project')),
- ],
- ),
- migrations.AddField(
- model_name='brvariable',
- name='req',
- field=models.ForeignKey(to='bldcontrol.BuildRequest'),
- ),
- migrations.AddField(
- model_name='brtarget',
- name='req',
- field=models.ForeignKey(to='bldcontrol.BuildRequest'),
- ),
- migrations.AddField(
- model_name='brlayer',
- name='req',
- field=models.ForeignKey(to='bldcontrol.BuildRequest'),
- ),
- migrations.AddField(
- model_name='brerror',
- name='req',
- field=models.ForeignKey(to='bldcontrol.BuildRequest'),
- ),
- migrations.AddField(
- model_name='brbitbake',
- name='req',
- field=models.OneToOneField(to='bldcontrol.BuildRequest'),
- ),
- ]
diff --git a/lib/bldcontrol/migrations/0002_auto_20160120_1250.py b/lib/bldcontrol/migrations/0002_auto_20160120_1250.py
deleted file mode 100644
index 0c2475ab..00000000
--- a/lib/bldcontrol/migrations/0002_auto_20160120_1250.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('bldcontrol', '0001_initial'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='buildenvironment',
- name='betype',
- field=models.IntegerField(choices=[(0, b'local')]),
- ),
- ]
diff --git a/lib/bldcontrol/migrations/0003_add_cancelling_state.py b/lib/bldcontrol/migrations/0003_add_cancelling_state.py
deleted file mode 100644
index eec9216c..00000000
--- a/lib/bldcontrol/migrations/0003_add_cancelling_state.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('bldcontrol', '0002_auto_20160120_1250'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='buildrequest',
- name='state',
- field=models.IntegerField(default=0, choices=[(0, b'created'), (1, b'queued'), (2, b'in progress'), (3, b'completed'), (4, b'failed'), (5, b'deleted'), (6, b'cancelling'), (7, b'archive')]),
- ),
- ]
diff --git a/lib/bldcontrol/migrations/0004_auto_20160523_1446.py b/lib/bldcontrol/migrations/0004_auto_20160523_1446.py
deleted file mode 100644
index 3d906295..00000000
--- a/lib/bldcontrol/migrations/0004_auto_20160523_1446.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('bldcontrol', '0003_add_cancelling_state'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='buildenvironment',
- name='bbstate',
- field=models.IntegerField(default=0, choices=[(0, 'stopped'), (1, 'started')]),
- ),
- migrations.AlterField(
- model_name='buildenvironment',
- name='betype',
- field=models.IntegerField(choices=[(0, 'local')]),
- ),
- migrations.AlterField(
- model_name='buildenvironment',
- name='lock',
- field=models.IntegerField(default=0, choices=[(0, 'free'), (1, 'lock'), (2, 'running')]),
- ),
- migrations.AlterField(
- model_name='buildrequest',
- name='state',
- field=models.IntegerField(default=0, choices=[(0, 'created'), (1, 'queued'), (2, 'in progress'), (3, 'completed'), (4, 'failed'), (5, 'deleted'), (6, 'cancelling'), (7, 'archive')]),
- ),
- ]
diff --git a/lib/bldcontrol/migrations/0005_reorder_buildrequest_states.py b/lib/bldcontrol/migrations/0005_reorder_buildrequest_states.py
deleted file mode 100644
index 4bb95177..00000000
--- a/lib/bldcontrol/migrations/0005_reorder_buildrequest_states.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('bldcontrol', '0004_auto_20160523_1446'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='buildrequest',
- name='state',
- field=models.IntegerField(choices=[(0, 'created'), (1, 'queued'), (2, 'in progress'), (3, 'failed'), (4, 'deleted'), (5, 'cancelling'), (6, 'completed'), (7, 'archive')], default=0),
- ),
- ]
diff --git a/lib/bldcontrol/migrations/0006_brlayer_local_source_dir.py b/lib/bldcontrol/migrations/0006_brlayer_local_source_dir.py
deleted file mode 100644
index 2460002f..00000000
--- a/lib/bldcontrol/migrations/0006_brlayer_local_source_dir.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('bldcontrol', '0005_reorder_buildrequest_states'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='brlayer',
- name='local_source_dir',
- field=models.CharField(max_length=254, null=True),
- ),
- ]
diff --git a/lib/bldcontrol/migrations/0007_brlayers_optional_gitinfo.py b/lib/bldcontrol/migrations/0007_brlayers_optional_gitinfo.py
deleted file mode 100644
index 4be42a4c..00000000
--- a/lib/bldcontrol/migrations/0007_brlayers_optional_gitinfo.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('bldcontrol', '0006_brlayer_local_source_dir'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='brlayer',
- name='commit',
- field=models.CharField(max_length=254, null=True),
- ),
- migrations.AlterField(
- model_name='brlayer',
- name='dirpath',
- field=models.CharField(max_length=254, null=True),
- ),
- migrations.AlterField(
- model_name='brlayer',
- name='giturl',
- field=models.CharField(max_length=254, null=True),
- ),
- ]
diff --git a/lib/bldcontrol/models.py b/lib/bldcontrol/models.py
deleted file mode 100644
index 409614b9..00000000
--- a/lib/bldcontrol/models.py
+++ /dev/null
@@ -1,162 +0,0 @@
-from __future__ import unicode_literals
-from django.db import models
-from django.core.validators import MaxValueValidator, MinValueValidator
-from django.utils.encoding import force_text
-from orm.models import Project, ProjectLayer, ProjectVariable, ProjectTarget, Build, Layer_Version
-
-import logging
-logger = logging.getLogger("toaster")
-# a BuildEnvironment is the equivalent of the "build/" directory on the localhost
-class BuildEnvironment(models.Model):
- SERVER_STOPPED = 0
- SERVER_STARTED = 1
- SERVER_STATE = (
- (SERVER_STOPPED, "stopped"),
- (SERVER_STARTED, "started"),
- )
-
- TYPE_LOCAL = 0
- TYPE = (
- (TYPE_LOCAL, "local"),
- )
-
- LOCK_FREE = 0
- LOCK_LOCK = 1
- LOCK_RUNNING = 2
- LOCK_STATE = (
- (LOCK_FREE, "free"),
- (LOCK_LOCK, "lock"),
- (LOCK_RUNNING, "running"),
- )
-
- address = models.CharField(max_length = 254)
- betype = models.IntegerField(choices = TYPE)
- bbaddress = models.CharField(max_length = 254, blank = True)
- bbport = models.IntegerField(default = -1)
- bbtoken = models.CharField(max_length = 126, blank = True)
- bbstate = models.IntegerField(choices = SERVER_STATE, default = SERVER_STOPPED)
- sourcedir = models.CharField(max_length = 512, blank = True)
- builddir = models.CharField(max_length = 512, blank = True)
- lock = models.IntegerField(choices = LOCK_STATE, default = LOCK_FREE)
- created = models.DateTimeField(auto_now_add = True)
- updated = models.DateTimeField(auto_now = True)
-
- def get_artifact(self, path):
- if self.betype == BuildEnvironment.TYPE_LOCAL:
- return open(path, "r")
- raise NotImplementedError("FIXME: artifact download not implemented "\
- "for build environment type %s" % \
- self.get_betype_display())
-
- def has_artifact(self, path):
- import os
- if self.betype == BuildEnvironment.TYPE_LOCAL:
- return os.path.exists(path)
- raise NotImplementedError("FIXME: has artifact not implemented for "\
- "build environment type %s" % \
- self.get_betype_display())
-
-# a BuildRequest is a request that the scheduler will build using a BuildEnvironment
-# the build request queue is the table itself, ordered by state
-
-class BuildRequest(models.Model):
- REQ_CREATED = 0
- REQ_QUEUED = 1
- REQ_INPROGRESS = 2
- REQ_FAILED = 3
- REQ_DELETED = 4
- REQ_CANCELLING = 5
- REQ_COMPLETED = 6
- REQ_ARCHIVE = 7
-
- REQUEST_STATE = (
- (REQ_CREATED, "created"),
- (REQ_QUEUED, "queued"),
- (REQ_INPROGRESS, "in progress"),
- (REQ_FAILED, "failed"),
- (REQ_DELETED, "deleted"),
- (REQ_CANCELLING, "cancelling"),
- (REQ_COMPLETED, "completed"),
- (REQ_ARCHIVE, "archive"),
- )
-
- search_allowed_fields = ("brtarget__target", "build__project__name")
-
- project = models.ForeignKey(Project)
- build = models.OneToOneField(Build, null = True) # TODO: toasterui should set this when Build is created
- environment = models.ForeignKey(BuildEnvironment, null = True)
- state = models.IntegerField(choices = REQUEST_STATE, default = REQ_CREATED)
- created = models.DateTimeField(auto_now_add = True)
- updated = models.DateTimeField(auto_now = True)
-
- def __init__(self, *args, **kwargs):
- super(BuildRequest, self).__init__(*args, **kwargs)
- # Save the old state in case it's about to be modified
- self.old_state = self.state
-
- def save(self, *args, **kwargs):
- # Check that the state we're trying to set is not going backwards
- # e.g. from REQ_FAILED to REQ_INPROGRESS
- if self.old_state != self.state and self.old_state > self.state:
- logger.warning("Invalid state change requested: "
- "Cannot go from %s to %s - ignoring request" %
- (BuildRequest.REQUEST_STATE[self.old_state][1],
- BuildRequest.REQUEST_STATE[self.state][1])
- )
- # Set property back to the old value
- self.state = self.old_state
- return
-
- super(BuildRequest, self).save(*args, **kwargs)
-
-
- def get_duration(self):
- return (self.updated - self.created).total_seconds()
-
- def get_sorted_target_list(self):
- tgts = self.brtarget_set.order_by( 'target' );
- return( tgts );
-
- def get_machine(self):
- return self.brvariable_set.get(name="MACHINE").value
-
- def __str__(self):
- return force_text('%s %s' % (self.project, self.get_state_display()))
-
-# These tables specify the settings for running an actual build.
-# They MUST be kept in sync with the tables in orm.models.Project*
-
-
-class BRLayer(models.Model):
- req = models.ForeignKey(BuildRequest)
- name = models.CharField(max_length=100)
- giturl = models.CharField(max_length=254, null=True)
- local_source_dir = models.CharField(max_length=254, null=True)
- commit = models.CharField(max_length=254, null=True)
- dirpath = models.CharField(max_length=254, null=True)
- layer_version = models.ForeignKey(Layer_Version, null=True)
-
-class BRBitbake(models.Model):
- req = models.OneToOneField(BuildRequest) # only one bitbake for a request
- giturl = models.CharField(max_length =254)
- commit = models.CharField(max_length = 254)
- dirpath = models.CharField(max_length = 254)
-
-class BRVariable(models.Model):
- req = models.ForeignKey(BuildRequest)
- name = models.CharField(max_length=100)
- value = models.TextField(blank = True)
-
-class BRTarget(models.Model):
- req = models.ForeignKey(BuildRequest)
- target = models.CharField(max_length=100)
- task = models.CharField(max_length=100, null=True)
-
-class BRError(models.Model):
- req = models.ForeignKey(BuildRequest)
- errtype = models.CharField(max_length=100)
- errmsg = models.TextField()
- traceback = models.TextField()
-
- def __str__(self):
- return "%s (%s)" % (self.errmsg, self.req)
diff --git a/lib/bldcontrol/views.py b/lib/bldcontrol/views.py
deleted file mode 100644
index 60f00ef0..00000000
--- a/lib/bldcontrol/views.py
+++ /dev/null
@@ -1 +0,0 @@
-# Create your views here.
diff --git a/lib/bldcollector/__init__.py b/lib/srtgui/__init__.py
index e69de29b..e69de29b 100644
--- a/lib/bldcollector/__init__.py
+++ b/lib/srtgui/__init__.py
diff --git a/lib/toastergui/api.py b/lib/srtgui/api.py
index ab6ba69e..ab6ba69e 100644
--- a/lib/toastergui/api.py
+++ b/lib/srtgui/api.py
diff --git a/lib/toastergui/buildtables.py b/lib/srtgui/buildtables.py
index 755a7c2e..755a7c2e 100644
--- a/lib/toastergui/buildtables.py
+++ b/lib/srtgui/buildtables.py
diff --git a/lib/toastergui/fixtures/toastergui-unittest-data.xml b/lib/srtgui/fixtures/toastergui-unittest-data.xml
index 4517ed17..4517ed17 100644
--- a/lib/toastergui/fixtures/toastergui-unittest-data.xml
+++ b/lib/srtgui/fixtures/toastergui-unittest-data.xml
diff --git a/lib/toastergui/static/css/bootstrap.css b/lib/srtgui/static/css/bootstrap.css
index 42c79d6e..42c79d6e 100644
--- a/lib/toastergui/static/css/bootstrap.css
+++ b/lib/srtgui/static/css/bootstrap.css
diff --git a/lib/toastergui/static/css/bootstrap.css.map b/lib/srtgui/static/css/bootstrap.css.map
index 09f8cda7..09f8cda7 100644
--- a/lib/toastergui/static/css/bootstrap.css.map
+++ b/lib/srtgui/static/css/bootstrap.css.map
diff --git a/lib/toastergui/static/css/bootstrap.min.css b/lib/srtgui/static/css/bootstrap.min.css
index 4cf729e4..4cf729e4 100755
--- a/lib/toastergui/static/css/bootstrap.min.css
+++ b/lib/srtgui/static/css/bootstrap.min.css
diff --git a/lib/toastergui/static/css/bootstrap.min.css.map b/lib/srtgui/static/css/bootstrap.min.css.map
index 5f49bb37..5f49bb37 100644
--- a/lib/toastergui/static/css/bootstrap.min.css.map
+++ b/lib/srtgui/static/css/bootstrap.min.css.map
diff --git a/lib/toastergui/static/css/bootstrap3-transition.css b/lib/srtgui/static/css/bootstrap3-transition.css
index 9644485c..9644485c 100644
--- a/lib/toastergui/static/css/bootstrap3-transition.css
+++ b/lib/srtgui/static/css/bootstrap3-transition.css
diff --git a/lib/toastergui/static/css/default.css b/lib/srtgui/static/css/default.css
index 5cd7e211..5cd7e211 100644
--- a/lib/toastergui/static/css/default.css
+++ b/lib/srtgui/static/css/default.css
diff --git a/lib/toastergui/static/css/font-awesome.min.css b/lib/srtgui/static/css/font-awesome.min.css
index fa15fd52..fa15fd52 100755
--- a/lib/toastergui/static/css/font-awesome.min.css
+++ b/lib/srtgui/static/css/font-awesome.min.css
diff --git a/lib/toastergui/static/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png b/lib/srtgui/static/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png
index d5d78a3c..d5d78a3c 100755
--- a/lib/toastergui/static/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png
+++ b/lib/srtgui/static/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png
Binary files differ
diff --git a/lib/toastergui/static/css/images/ui-bg_diagonals-thick_20_666666_40x40.png b/lib/srtgui/static/css/images/ui-bg_diagonals-thick_20_666666_40x40.png
index 1b0a045e..1b0a045e 100755
--- a/lib/toastergui/static/css/images/ui-bg_diagonals-thick_20_666666_40x40.png
+++ b/lib/srtgui/static/css/images/ui-bg_diagonals-thick_20_666666_40x40.png
Binary files differ
diff --git a/lib/toastergui/static/css/images/ui-bg_flat_10_000000_40x100.png b/lib/srtgui/static/css/images/ui-bg_flat_10_000000_40x100.png
index c55f8ef7..c55f8ef7 100755
--- a/lib/toastergui/static/css/images/ui-bg_flat_10_000000_40x100.png
+++ b/lib/srtgui/static/css/images/ui-bg_flat_10_000000_40x100.png
Binary files differ
diff --git a/lib/toastergui/static/css/images/ui-bg_glass_100_f6f6f6_1x400.png b/lib/srtgui/static/css/images/ui-bg_glass_100_f6f6f6_1x400.png
index ea4fa0fc..ea4fa0fc 100755
--- a/lib/toastergui/static/css/images/ui-bg_glass_100_f6f6f6_1x400.png
+++ b/lib/srtgui/static/css/images/ui-bg_glass_100_f6f6f6_1x400.png
Binary files differ
diff --git a/lib/toastergui/static/css/images/ui-bg_glass_100_fdf5ce_1x400.png b/lib/srtgui/static/css/images/ui-bg_glass_100_fdf5ce_1x400.png
index 2f59e2d8..2f59e2d8 100755
--- a/lib/toastergui/static/css/images/ui-bg_glass_100_fdf5ce_1x400.png
+++ b/lib/srtgui/static/css/images/ui-bg_glass_100_fdf5ce_1x400.png
Binary files differ
diff --git a/lib/toastergui/static/css/images/ui-bg_glass_65_ffffff_1x400.png b/lib/srtgui/static/css/images/ui-bg_glass_65_ffffff_1x400.png
index f172b302..f172b302 100755
--- a/lib/toastergui/static/css/images/ui-bg_glass_65_ffffff_1x400.png
+++ b/lib/srtgui/static/css/images/ui-bg_glass_65_ffffff_1x400.png
Binary files differ
diff --git a/lib/toastergui/static/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png b/lib/srtgui/static/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png
index 1039d548..1039d548 100644
--- a/lib/toastergui/static/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png
+++ b/lib/srtgui/static/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png
Binary files differ
diff --git a/lib/toastergui/static/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png b/lib/srtgui/static/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
index 1089b70c..1089b70c 100755
--- a/lib/toastergui/static/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
+++ b/lib/srtgui/static/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
Binary files differ
diff --git a/lib/toastergui/static/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png b/lib/srtgui/static/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png
index 561b7f84..561b7f84 100755
--- a/lib/toastergui/static/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png
+++ b/lib/srtgui/static/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png
Binary files differ
diff --git a/lib/toastergui/static/css/images/ui-icons_222222_256x240.png b/lib/srtgui/static/css/images/ui-icons_222222_256x240.png
index e9c8e16a..e9c8e16a 100644
--- a/lib/toastergui/static/css/images/ui-icons_222222_256x240.png
+++ b/lib/srtgui/static/css/images/ui-icons_222222_256x240.png
Binary files differ
diff --git a/lib/toastergui/static/css/images/ui-icons_228ef1_256x240.png b/lib/srtgui/static/css/images/ui-icons_228ef1_256x240.png
index 8d68c543..8d68c543 100644
--- a/lib/toastergui/static/css/images/ui-icons_228ef1_256x240.png
+++ b/lib/srtgui/static/css/images/ui-icons_228ef1_256x240.png
Binary files differ
diff --git a/lib/toastergui/static/css/images/ui-icons_ef8c08_256x240.png b/lib/srtgui/static/css/images/ui-icons_ef8c08_256x240.png
index 18bbfe82..18bbfe82 100644
--- a/lib/toastergui/static/css/images/ui-icons_ef8c08_256x240.png
+++ b/lib/srtgui/static/css/images/ui-icons_ef8c08_256x240.png
Binary files differ
diff --git a/lib/toastergui/static/css/images/ui-icons_ffd27a_256x240.png b/lib/srtgui/static/css/images/ui-icons_ffd27a_256x240.png
index 4435b497..4435b497 100644
--- a/lib/toastergui/static/css/images/ui-icons_ffd27a_256x240.png
+++ b/lib/srtgui/static/css/images/ui-icons_ffd27a_256x240.png
Binary files differ
diff --git a/lib/toastergui/static/css/images/ui-icons_ffffff_256x240.png b/lib/srtgui/static/css/images/ui-icons_ffffff_256x240.png
index 4d66f596..4d66f596 100644
--- a/lib/toastergui/static/css/images/ui-icons_ffffff_256x240.png
+++ b/lib/srtgui/static/css/images/ui-icons_ffffff_256x240.png
Binary files differ
diff --git a/lib/toastergui/static/css/jquery-ui.min.css b/lib/srtgui/static/css/jquery-ui.min.css
index c486ec04..c486ec04 100755
--- a/lib/toastergui/static/css/jquery-ui.min.css
+++ b/lib/srtgui/static/css/jquery-ui.min.css
diff --git a/lib/toastergui/static/css/jquery-ui.structure.min.css b/lib/srtgui/static/css/jquery-ui.structure.min.css
index d1578a4e..d1578a4e 100755
--- a/lib/toastergui/static/css/jquery-ui.structure.min.css
+++ b/lib/srtgui/static/css/jquery-ui.structure.min.css
diff --git a/lib/toastergui/static/css/jquery-ui.theme.min.css b/lib/srtgui/static/css/jquery-ui.theme.min.css
index 34543111..34543111 100755
--- a/lib/toastergui/static/css/jquery-ui.theme.min.css
+++ b/lib/srtgui/static/css/jquery-ui.theme.min.css
diff --git a/lib/toastergui/static/css/jquery.treetable.css b/lib/srtgui/static/css/jquery.treetable.css
index 4e95bfd3..4e95bfd3 100644
--- a/lib/toastergui/static/css/jquery.treetable.css
+++ b/lib/srtgui/static/css/jquery.treetable.css
diff --git a/lib/toastergui/static/css/jquery.treetable.theme.default.css b/lib/srtgui/static/css/jquery.treetable.theme.default.css
index 48289baa..48289baa 100644
--- a/lib/toastergui/static/css/jquery.treetable.theme.default.css
+++ b/lib/srtgui/static/css/jquery.treetable.theme.default.css
diff --git a/lib/toastergui/static/css/jquery.treetable.theme.toaster.css b/lib/srtgui/static/css/jquery.treetable.theme.toaster.css
index d8552e58..d8552e58 100644
--- a/lib/toastergui/static/css/jquery.treetable.theme.toaster.css
+++ b/lib/srtgui/static/css/jquery.treetable.theme.toaster.css
diff --git a/lib/toastergui/static/css/qunit-1.18.0.css b/lib/srtgui/static/css/qunit-1.18.0.css
index 28cca1cc..28cca1cc 100644
--- a/lib/toastergui/static/css/qunit-1.18.0.css
+++ b/lib/srtgui/static/css/qunit-1.18.0.css
diff --git a/lib/toastergui/static/css/screen.css b/lib/srtgui/static/css/screen.css
index e233ef6a..e233ef6a 100644
--- a/lib/toastergui/static/css/screen.css
+++ b/lib/srtgui/static/css/screen.css
diff --git a/lib/toastergui/static/fonts/FontAwesome.otf b/lib/srtgui/static/fonts/FontAwesome.otf
index 64049bf2..64049bf2 100644
--- a/lib/toastergui/static/fonts/FontAwesome.otf
+++ b/lib/srtgui/static/fonts/FontAwesome.otf
Binary files differ
diff --git a/lib/toastergui/static/fonts/fontawesome-webfont.eot b/lib/srtgui/static/fonts/fontawesome-webfont.eot
index 7d81019e..7d81019e 100644
--- a/lib/toastergui/static/fonts/fontawesome-webfont.eot
+++ b/lib/srtgui/static/fonts/fontawesome-webfont.eot
Binary files differ
diff --git a/lib/toastergui/static/fonts/fontawesome-webfont.svg b/lib/srtgui/static/fonts/fontawesome-webfont.svg
index ba0afe5e..ba0afe5e 100644
--- a/lib/toastergui/static/fonts/fontawesome-webfont.svg
+++ b/lib/srtgui/static/fonts/fontawesome-webfont.svg
diff --git a/lib/toastergui/static/fonts/fontawesome-webfont.ttf b/lib/srtgui/static/fonts/fontawesome-webfont.ttf
index d4617247..d4617247 100644
--- a/lib/toastergui/static/fonts/fontawesome-webfont.ttf
+++ b/lib/srtgui/static/fonts/fontawesome-webfont.ttf
Binary files differ
diff --git a/lib/toastergui/static/fonts/fontawesome-webfont.woff b/lib/srtgui/static/fonts/fontawesome-webfont.woff
index 3c89ae09..3c89ae09 100644
--- a/lib/toastergui/static/fonts/fontawesome-webfont.woff
+++ b/lib/srtgui/static/fonts/fontawesome-webfont.woff
Binary files differ
diff --git a/lib/toastergui/static/fonts/glyphicons-halflings-regular.eot b/lib/srtgui/static/fonts/glyphicons-halflings-regular.eot
index b93a4953..b93a4953 100644
--- a/lib/toastergui/static/fonts/glyphicons-halflings-regular.eot
+++ b/lib/srtgui/static/fonts/glyphicons-halflings-regular.eot
Binary files differ
diff --git a/lib/toastergui/static/fonts/glyphicons-halflings-regular.svg b/lib/srtgui/static/fonts/glyphicons-halflings-regular.svg
index 94fb5490..94fb5490 100644
--- a/lib/toastergui/static/fonts/glyphicons-halflings-regular.svg
+++ b/lib/srtgui/static/fonts/glyphicons-halflings-regular.svg
diff --git a/lib/toastergui/static/fonts/glyphicons-halflings-regular.ttf b/lib/srtgui/static/fonts/glyphicons-halflings-regular.ttf
index 1413fc60..1413fc60 100644
--- a/lib/toastergui/static/fonts/glyphicons-halflings-regular.ttf
+++ b/lib/srtgui/static/fonts/glyphicons-halflings-regular.ttf
Binary files differ
diff --git a/lib/toastergui/static/fonts/glyphicons-halflings-regular.woff b/lib/srtgui/static/fonts/glyphicons-halflings-regular.woff
index 9e612858..9e612858 100644
--- a/lib/toastergui/static/fonts/glyphicons-halflings-regular.woff
+++ b/lib/srtgui/static/fonts/glyphicons-halflings-regular.woff
Binary files differ
diff --git a/lib/toastergui/static/fonts/glyphicons-halflings-regular.woff2 b/lib/srtgui/static/fonts/glyphicons-halflings-regular.woff2
index 64539b54..64539b54 100644
--- a/lib/toastergui/static/fonts/glyphicons-halflings-regular.woff2
+++ b/lib/srtgui/static/fonts/glyphicons-halflings-regular.woff2
Binary files differ
diff --git a/lib/toastergui/static/html/layer_deps_modal.html b/lib/srtgui/static/html/layer_deps_modal.html
index e843d8d8..e843d8d8 100644
--- a/lib/toastergui/static/html/layer_deps_modal.html
+++ b/lib/srtgui/static/html/layer_deps_modal.html
diff --git a/lib/toastergui/static/img/logo.png b/lib/srtgui/static/img/logo.png
index 35ad733e..35ad733e 100644
--- a/lib/toastergui/static/img/logo.png
+++ b/lib/srtgui/static/img/logo.png
Binary files differ
diff --git a/lib/toastergui/static/img/toaster_bw.png b/lib/srtgui/static/img/toaster_bw.png
index b4659079..b4659079 100644
--- a/lib/toastergui/static/img/toaster_bw.png
+++ b/lib/srtgui/static/img/toaster_bw.png
Binary files differ
diff --git a/lib/toastergui/static/jquery-treetable-license/GPL-LICENSE.txt b/lib/srtgui/static/jquery-treetable-license/GPL-LICENSE.txt
index 76927f58..76927f58 100644
--- a/lib/toastergui/static/jquery-treetable-license/GPL-LICENSE.txt
+++ b/lib/srtgui/static/jquery-treetable-license/GPL-LICENSE.txt
diff --git a/lib/toastergui/static/jquery-treetable-license/MIT-LICENSE.txt b/lib/srtgui/static/jquery-treetable-license/MIT-LICENSE.txt
index c2e824fb..c2e824fb 100644
--- a/lib/toastergui/static/jquery-treetable-license/MIT-LICENSE.txt
+++ b/lib/srtgui/static/jquery-treetable-license/MIT-LICENSE.txt
diff --git a/lib/toastergui/static/jquery-treetable-license/README.md b/lib/srtgui/static/jquery-treetable-license/README.md
index ece7afb5..ece7afb5 100644
--- a/lib/toastergui/static/jquery-treetable-license/README.md
+++ b/lib/srtgui/static/jquery-treetable-license/README.md
diff --git a/lib/toastergui/static/jquery.treetable.theme.toaster.css b/lib/srtgui/static/jquery.treetable.theme.toaster.css
index 5194b234..5194b234 100644
--- a/lib/toastergui/static/jquery.treetable.theme.toaster.css
+++ b/lib/srtgui/static/jquery.treetable.theme.toaster.css
diff --git a/lib/toastergui/static/js/.jshintrc b/lib/srtgui/static/js/.jshintrc
index b02f3efa..b02f3efa 100644
--- a/lib/toastergui/static/js/.jshintrc
+++ b/lib/srtgui/static/js/.jshintrc
diff --git a/lib/toastergui/static/js/bootstrap.js b/lib/srtgui/static/js/bootstrap.js
index d47d640f..d47d640f 100644
--- a/lib/toastergui/static/js/bootstrap.js
+++ b/lib/srtgui/static/js/bootstrap.js
diff --git a/lib/toastergui/static/js/bootstrap.min.js b/lib/srtgui/static/js/bootstrap.min.js
index c4a92416..c4a92416 100644
--- a/lib/toastergui/static/js/bootstrap.min.js
+++ b/lib/srtgui/static/js/bootstrap.min.js
diff --git a/lib/toastergui/static/js/customrecipe.js b/lib/srtgui/static/js/customrecipe.js
index 8b1c190d..8b1c190d 100644
--- a/lib/toastergui/static/js/customrecipe.js
+++ b/lib/srtgui/static/js/customrecipe.js
diff --git a/lib/toastergui/static/js/filtersnippet.js b/lib/srtgui/static/js/filtersnippet.js
index 2b84c546..2b84c546 100755
--- a/lib/toastergui/static/js/filtersnippet.js
+++ b/lib/srtgui/static/js/filtersnippet.js
diff --git a/lib/toastergui/static/js/highlight.pack.js b/lib/srtgui/static/js/highlight.pack.js
index 8cc886f1..8cc886f1 100644
--- a/lib/toastergui/static/js/highlight.pack.js
+++ b/lib/srtgui/static/js/highlight.pack.js
diff --git a/lib/toastergui/static/js/importlayer.js b/lib/srtgui/static/js/importlayer.js
index 29648398..29648398 100644
--- a/lib/toastergui/static/js/importlayer.js
+++ b/lib/srtgui/static/js/importlayer.js
diff --git a/lib/toastergui/static/js/jquery-2.0.3.min.js b/lib/srtgui/static/js/jquery-2.0.3.min.js
index 2be209dd..2be209dd 100644
--- a/lib/toastergui/static/js/jquery-2.0.3.min.js
+++ b/lib/srtgui/static/js/jquery-2.0.3.min.js
diff --git a/lib/toastergui/static/js/jquery-2.0.3.min.map b/lib/srtgui/static/js/jquery-2.0.3.min.map
index 1edecd1a..1edecd1a 100644
--- a/lib/toastergui/static/js/jquery-2.0.3.min.map
+++ b/lib/srtgui/static/js/jquery-2.0.3.min.map
diff --git a/lib/toastergui/static/js/jquery-ui.min.js b/lib/srtgui/static/js/jquery-ui.min.js
index 4e6396b2..4e6396b2 100755
--- a/lib/toastergui/static/js/jquery-ui.min.js
+++ b/lib/srtgui/static/js/jquery-ui.min.js
diff --git a/lib/toastergui/static/js/jquery.cookie.js b/lib/srtgui/static/js/jquery.cookie.js
index 92719000..92719000 100644
--- a/lib/toastergui/static/js/jquery.cookie.js
+++ b/lib/srtgui/static/js/jquery.cookie.js
diff --git a/lib/toastergui/static/js/jquery.treetable.js b/lib/srtgui/static/js/jquery.treetable.js
index 794b902c..794b902c 100644
--- a/lib/toastergui/static/js/jquery.treetable.js
+++ b/lib/srtgui/static/js/jquery.treetable.js
diff --git a/lib/toastergui/static/js/jsrender.min.js b/lib/srtgui/static/js/jsrender.min.js
index 87cac4eb..87cac4eb 100644
--- a/lib/toastergui/static/js/jsrender.min.js
+++ b/lib/srtgui/static/js/jsrender.min.js
diff --git a/lib/toastergui/static/js/layerBtn.js b/lib/srtgui/static/js/layerBtn.js
index 9f9eda1e..9f9eda1e 100644
--- a/lib/toastergui/static/js/layerBtn.js
+++ b/lib/srtgui/static/js/layerBtn.js
diff --git a/lib/toastergui/static/js/layerDepsModal.js b/lib/srtgui/static/js/layerDepsModal.js
index e9622243..e9622243 100644
--- a/lib/toastergui/static/js/layerDepsModal.js
+++ b/lib/srtgui/static/js/layerDepsModal.js
diff --git a/lib/toastergui/static/js/layerdetails.js b/lib/srtgui/static/js/layerdetails.js
index 9ead393c..9ead393c 100644
--- a/lib/toastergui/static/js/layerdetails.js
+++ b/lib/srtgui/static/js/layerdetails.js
diff --git a/lib/toastergui/static/js/libtoaster.js b/lib/srtgui/static/js/libtoaster.js
index 6f9b5d0f..6f9b5d0f 100644
--- a/lib/toastergui/static/js/libtoaster.js
+++ b/lib/srtgui/static/js/libtoaster.js
diff --git a/lib/toastergui/static/js/mrbsection.js b/lib/srtgui/static/js/mrbsection.js
index c0c5fa95..c0c5fa95 100644
--- a/lib/toastergui/static/js/mrbsection.js
+++ b/lib/srtgui/static/js/mrbsection.js
diff --git a/lib/toastergui/static/js/newcustomimage_modal.js b/lib/srtgui/static/js/newcustomimage_modal.js
index dace8e32..dace8e32 100644
--- a/lib/toastergui/static/js/newcustomimage_modal.js
+++ b/lib/srtgui/static/js/newcustomimage_modal.js
diff --git a/lib/toastergui/static/js/projectpage.js b/lib/srtgui/static/js/projectpage.js
index 506471e0..506471e0 100644
--- a/lib/toastergui/static/js/projectpage.js
+++ b/lib/srtgui/static/js/projectpage.js
diff --git a/lib/toastergui/static/js/projecttopbar.js b/lib/srtgui/static/js/projecttopbar.js
index 69220aaf..69220aaf 100644
--- a/lib/toastergui/static/js/projecttopbar.js
+++ b/lib/srtgui/static/js/projecttopbar.js
diff --git a/lib/toastergui/static/js/qunit-1.18.0.js b/lib/srtgui/static/js/qunit-1.18.0.js
index fadd3403..fadd3403 100644
--- a/lib/toastergui/static/js/qunit-1.18.0.js
+++ b/lib/srtgui/static/js/qunit-1.18.0.js
diff --git a/lib/toastergui/static/js/recipedetails.js b/lib/srtgui/static/js/recipedetails.js
index 604db5f0..604db5f0 100644
--- a/lib/toastergui/static/js/recipedetails.js
+++ b/lib/srtgui/static/js/recipedetails.js
diff --git a/lib/toastergui/static/js/table.js b/lib/srtgui/static/js/table.js
index abcb5ca7..abcb5ca7 100644
--- a/lib/toastergui/static/js/table.js
+++ b/lib/srtgui/static/js/table.js
diff --git a/lib/toastergui/static/js/tests/test.js b/lib/srtgui/static/js/tests/test.js
index 4a4c83f4..4a4c83f4 100644
--- a/lib/toastergui/static/js/tests/test.js
+++ b/lib/srtgui/static/js/tests/test.js
diff --git a/lib/toastergui/static/js/typeahead.jquery.js b/lib/srtgui/static/js/typeahead.jquery.js
index f3efd80c..f3efd80c 100644
--- a/lib/toastergui/static/js/typeahead.jquery.js
+++ b/lib/srtgui/static/js/typeahead.jquery.js
diff --git a/lib/toastergui/static/js/ui-bootstrap-tpls-0.11.0.js b/lib/srtgui/static/js/ui-bootstrap-tpls-0.11.0.js
index fa6a8613..fa6a8613 100644
--- a/lib/toastergui/static/js/ui-bootstrap-tpls-0.11.0.js
+++ b/lib/srtgui/static/js/ui-bootstrap-tpls-0.11.0.js
diff --git a/lib/toastergui/static/js/ui-bootstrap-tpls-0.11.0.min.js b/lib/srtgui/static/js/ui-bootstrap-tpls-0.11.0.min.js
index fa6a8613..fa6a8613 100644
--- a/lib/toastergui/static/js/ui-bootstrap-tpls-0.11.0.min.js
+++ b/lib/srtgui/static/js/ui-bootstrap-tpls-0.11.0.min.js
diff --git a/lib/toastergui/tablefilter.py b/lib/srtgui/tablefilter.py
index 65454e14..65454e14 100644
--- a/lib/toastergui/tablefilter.py
+++ b/lib/srtgui/tablefilter.py
diff --git a/lib/toastergui/tables.py b/lib/srtgui/tables.py
index dca2fa29..dca2fa29 100644
--- a/lib/toastergui/tables.py
+++ b/lib/srtgui/tables.py
diff --git a/lib/toastergui/templates/base.html b/lib/srtgui/templates/base.html
index 4f720648..4f720648 100644
--- a/lib/toastergui/templates/base.html
+++ b/lib/srtgui/templates/base.html
diff --git a/lib/toastergui/templates/basebuilddetailpage.html b/lib/srtgui/templates/basebuilddetailpage.html
index 4d506673..4d506673 100644
--- a/lib/toastergui/templates/basebuilddetailpage.html
+++ b/lib/srtgui/templates/basebuilddetailpage.html
diff --git a/lib/toastergui/templates/basebuildpage.html b/lib/srtgui/templates/basebuildpage.html
index a41911f5..a41911f5 100644
--- a/lib/toastergui/templates/basebuildpage.html
+++ b/lib/srtgui/templates/basebuildpage.html
diff --git a/lib/toastergui/templates/baseprojectbuildspage.html b/lib/srtgui/templates/baseprojectbuildspage.html
index 229cd17b..229cd17b 100644
--- a/lib/toastergui/templates/baseprojectbuildspage.html
+++ b/lib/srtgui/templates/baseprojectbuildspage.html
diff --git a/lib/toastergui/templates/baseprojectpage.html b/lib/srtgui/templates/baseprojectpage.html
index f2bb2ebf..f2bb2ebf 100644
--- a/lib/toastergui/templates/baseprojectpage.html
+++ b/lib/srtgui/templates/baseprojectpage.html
diff --git a/lib/toastergui/templates/basetable_bottom.html b/lib/srtgui/templates/basetable_bottom.html
index a2011fa9..a2011fa9 100644
--- a/lib/toastergui/templates/basetable_bottom.html
+++ b/lib/srtgui/templates/basetable_bottom.html
diff --git a/lib/toastergui/templates/basetable_top.html b/lib/srtgui/templates/basetable_top.html
index 5a9076d2..5a9076d2 100644
--- a/lib/toastergui/templates/basetable_top.html
+++ b/lib/srtgui/templates/basetable_top.html
diff --git a/lib/toastergui/templates/basetable_top_layers.html b/lib/srtgui/templates/basetable_top_layers.html
index 722091b2..722091b2 100644
--- a/lib/toastergui/templates/basetable_top_layers.html
+++ b/lib/srtgui/templates/basetable_top_layers.html
diff --git a/lib/toastergui/templates/bfile.html b/lib/srtgui/templates/bfile.html
index c7f59434..c7f59434 100644
--- a/lib/toastergui/templates/bfile.html
+++ b/lib/srtgui/templates/bfile.html
diff --git a/lib/toastergui/templates/brtargets.html b/lib/srtgui/templates/brtargets.html
index 4ebd0587..4ebd0587 100644
--- a/lib/toastergui/templates/brtargets.html
+++ b/lib/srtgui/templates/brtargets.html
diff --git a/lib/toastergui/templates/builddashboard.html b/lib/srtgui/templates/builddashboard.html
index 02a29816..02a29816 100644
--- a/lib/toastergui/templates/builddashboard.html
+++ b/lib/srtgui/templates/builddashboard.html
diff --git a/lib/toastergui/templates/buildinfo-toastertable.html b/lib/srtgui/templates/buildinfo-toastertable.html
index eb4c6569..eb4c6569 100644
--- a/lib/toastergui/templates/buildinfo-toastertable.html
+++ b/lib/srtgui/templates/buildinfo-toastertable.html
diff --git a/lib/toastergui/templates/builds-toastertable.html b/lib/srtgui/templates/builds-toastertable.html
index 0afe0a31..0afe0a31 100644
--- a/lib/toastergui/templates/builds-toastertable.html
+++ b/lib/srtgui/templates/builds-toastertable.html
diff --git a/lib/toastergui/templates/configuration.html b/lib/srtgui/templates/configuration.html
index 58989f86..58989f86 100644
--- a/lib/toastergui/templates/configuration.html
+++ b/lib/srtgui/templates/configuration.html
diff --git a/lib/toastergui/templates/configvars.html b/lib/srtgui/templates/configvars.html
index ca2e1eab..ca2e1eab 100644
--- a/lib/toastergui/templates/configvars.html
+++ b/lib/srtgui/templates/configvars.html
diff --git a/lib/toastergui/templates/cpuusage.html b/lib/srtgui/templates/cpuusage.html
index 02f07b76..02f07b76 100644
--- a/lib/toastergui/templates/cpuusage.html
+++ b/lib/srtgui/templates/cpuusage.html
diff --git a/lib/toastergui/templates/customise_btn.html b/lib/srtgui/templates/customise_btn.html
index 38c258ac..38c258ac 100644
--- a/lib/toastergui/templates/customise_btn.html
+++ b/lib/srtgui/templates/customise_btn.html
diff --git a/lib/toastergui/templates/customrecipe.html b/lib/srtgui/templates/customrecipe.html
index 945fc979..945fc979 100644
--- a/lib/toastergui/templates/customrecipe.html
+++ b/lib/srtgui/templates/customrecipe.html
diff --git a/lib/toastergui/templates/detail_pagination_bottom.html b/lib/srtgui/templates/detail_pagination_bottom.html
index 15adfbc9..15adfbc9 100644
--- a/lib/toastergui/templates/detail_pagination_bottom.html
+++ b/lib/srtgui/templates/detail_pagination_bottom.html
diff --git a/lib/toastergui/templates/detail_search_header.html b/lib/srtgui/templates/detail_search_header.html
index 7a986590..7a986590 100644
--- a/lib/toastergui/templates/detail_search_header.html
+++ b/lib/srtgui/templates/detail_search_header.html
diff --git a/lib/toastergui/templates/detail_sorted_header.html b/lib/srtgui/templates/detail_sorted_header.html
index 4434df43..4434df43 100644
--- a/lib/toastergui/templates/detail_sorted_header.html
+++ b/lib/srtgui/templates/detail_sorted_header.html
diff --git a/lib/toastergui/templates/dirinfo.html b/lib/srtgui/templates/dirinfo.html
index ab89e279..ab89e279 100644
--- a/lib/toastergui/templates/dirinfo.html
+++ b/lib/srtgui/templates/dirinfo.html
diff --git a/lib/toastergui/templates/diskio.html b/lib/srtgui/templates/diskio.html
index c5cef6f3..c5cef6f3 100644
--- a/lib/toastergui/templates/diskio.html
+++ b/lib/srtgui/templates/diskio.html
diff --git a/lib/toastergui/templates/distro_btn.html b/lib/srtgui/templates/distro_btn.html
index fac79472..fac79472 100644
--- a/lib/toastergui/templates/distro_btn.html
+++ b/lib/srtgui/templates/distro_btn.html
diff --git a/lib/toastergui/templates/editcustomimage_modal.html b/lib/srtgui/templates/editcustomimage_modal.html
index baa36c0e..baa36c0e 100644
--- a/lib/toastergui/templates/editcustomimage_modal.html
+++ b/lib/srtgui/templates/editcustomimage_modal.html
diff --git a/lib/toastergui/templates/filtersnippet.html b/lib/srtgui/templates/filtersnippet.html
index 1286ca31..1286ca31 100644
--- a/lib/toastergui/templates/filtersnippet.html
+++ b/lib/srtgui/templates/filtersnippet.html
diff --git a/lib/toastergui/templates/generic-toastertable-page.html b/lib/srtgui/templates/generic-toastertable-page.html
index b3eabe1a..b3eabe1a 100644
--- a/lib/toastergui/templates/generic-toastertable-page.html
+++ b/lib/srtgui/templates/generic-toastertable-page.html
diff --git a/lib/toastergui/templates/health.html b/lib/srtgui/templates/health.html
index f17fdbc4..f17fdbc4 100644
--- a/lib/toastergui/templates/health.html
+++ b/lib/srtgui/templates/health.html
diff --git a/lib/toastergui/templates/importlayer.html b/lib/srtgui/templates/importlayer.html
index 97d52c76..97d52c76 100644
--- a/lib/toastergui/templates/importlayer.html
+++ b/lib/srtgui/templates/importlayer.html
diff --git a/lib/toastergui/templates/js-unit-tests.html b/lib/srtgui/templates/js-unit-tests.html
index ca248962..ca248962 100644
--- a/lib/toastergui/templates/js-unit-tests.html
+++ b/lib/srtgui/templates/js-unit-tests.html
diff --git a/lib/toastergui/templates/landing.html b/lib/srtgui/templates/landing.html
index 70c7359f..70c7359f 100644
--- a/lib/toastergui/templates/landing.html
+++ b/lib/srtgui/templates/landing.html
diff --git a/lib/toastergui/templates/landing_not_managed.html b/lib/srtgui/templates/landing_not_managed.html
index baa4b72c..baa4b72c 100644
--- a/lib/toastergui/templates/landing_not_managed.html
+++ b/lib/srtgui/templates/landing_not_managed.html
diff --git a/lib/toastergui/templates/layer_btn.html b/lib/srtgui/templates/layer_btn.html
index 1580991a..1580991a 100644
--- a/lib/toastergui/templates/layer_btn.html
+++ b/lib/srtgui/templates/layer_btn.html
diff --git a/lib/toastergui/templates/layerdetails.html b/lib/srtgui/templates/layerdetails.html
index e0069db8..e0069db8 100644
--- a/lib/toastergui/templates/layerdetails.html
+++ b/lib/srtgui/templates/layerdetails.html
diff --git a/lib/toastergui/templates/machine_btn.html b/lib/srtgui/templates/machine_btn.html
index 6debe657..6debe657 100644
--- a/lib/toastergui/templates/machine_btn.html
+++ b/lib/srtgui/templates/machine_btn.html
diff --git a/lib/toastergui/templates/mrb_section.html b/lib/srtgui/templates/mrb_section.html
index c5b9fe90..c5b9fe90 100644
--- a/lib/toastergui/templates/mrb_section.html
+++ b/lib/srtgui/templates/mrb_section.html
diff --git a/lib/toastergui/templates/newcustomimage.html b/lib/srtgui/templates/newcustomimage.html
index 980179a4..980179a4 100644
--- a/lib/toastergui/templates/newcustomimage.html
+++ b/lib/srtgui/templates/newcustomimage.html
diff --git a/lib/toastergui/templates/newcustomimage_modal.html b/lib/srtgui/templates/newcustomimage_modal.html
index d448d3af..d448d3af 100644
--- a/lib/toastergui/templates/newcustomimage_modal.html
+++ b/lib/srtgui/templates/newcustomimage_modal.html
diff --git a/lib/toastergui/templates/newproject.html b/lib/srtgui/templates/newproject.html
index acb614e9..acb614e9 100644
--- a/lib/toastergui/templates/newproject.html
+++ b/lib/srtgui/templates/newproject.html
diff --git a/lib/toastergui/templates/package_built_dependencies.html b/lib/srtgui/templates/package_built_dependencies.html
index a5d58935..a5d58935 100644
--- a/lib/toastergui/templates/package_built_dependencies.html
+++ b/lib/srtgui/templates/package_built_dependencies.html
diff --git a/lib/toastergui/templates/package_built_detail.html b/lib/srtgui/templates/package_built_detail.html
index 0bdbc2a4..0bdbc2a4 100644
--- a/lib/toastergui/templates/package_built_detail.html
+++ b/lib/srtgui/templates/package_built_detail.html
diff --git a/lib/toastergui/templates/package_detail_base.html b/lib/srtgui/templates/package_detail_base.html
index 66f8e7f0..66f8e7f0 100644
--- a/lib/toastergui/templates/package_detail_base.html
+++ b/lib/srtgui/templates/package_detail_base.html
diff --git a/lib/toastergui/templates/package_included_dependencies.html b/lib/srtgui/templates/package_included_dependencies.html
index 95e56ded..95e56ded 100644
--- a/lib/toastergui/templates/package_included_dependencies.html
+++ b/lib/srtgui/templates/package_included_dependencies.html
diff --git a/lib/toastergui/templates/package_included_detail.html b/lib/srtgui/templates/package_included_detail.html
index 568e2f23..568e2f23 100644
--- a/lib/toastergui/templates/package_included_detail.html
+++ b/lib/srtgui/templates/package_included_detail.html
diff --git a/lib/toastergui/templates/package_included_reverse_dependencies.html b/lib/srtgui/templates/package_included_reverse_dependencies.html
index fb310c7f..fb310c7f 100644
--- a/lib/toastergui/templates/package_included_reverse_dependencies.html
+++ b/lib/srtgui/templates/package_included_reverse_dependencies.html
diff --git a/lib/toastergui/templates/package_included_tabs.html b/lib/srtgui/templates/package_included_tabs.html
index e89fa211..e89fa211 100644
--- a/lib/toastergui/templates/package_included_tabs.html
+++ b/lib/srtgui/templates/package_included_tabs.html
diff --git a/lib/toastergui/templates/pkg_add_rm_btn.html b/lib/srtgui/templates/pkg_add_rm_btn.html
index 303faecb..303faecb 100644
--- a/lib/toastergui/templates/pkg_add_rm_btn.html
+++ b/lib/srtgui/templates/pkg_add_rm_btn.html
diff --git a/lib/toastergui/templates/project.html b/lib/srtgui/templates/project.html
index 11603d1e..11603d1e 100644
--- a/lib/toastergui/templates/project.html
+++ b/lib/srtgui/templates/project.html
diff --git a/lib/toastergui/templates/projectbuilds-toastertable.html b/lib/srtgui/templates/projectbuilds-toastertable.html
index a5fed2dd..a5fed2dd 100644
--- a/lib/toastergui/templates/projectbuilds-toastertable.html
+++ b/lib/srtgui/templates/projectbuilds-toastertable.html
diff --git a/lib/toastergui/templates/projectbuilds.html b/lib/srtgui/templates/projectbuilds.html
index 50697a15..50697a15 100644
--- a/lib/toastergui/templates/projectbuilds.html
+++ b/lib/srtgui/templates/projectbuilds.html
diff --git a/lib/toastergui/templates/projectconf.html b/lib/srtgui/templates/projectconf.html
index 933c588f..933c588f 100644
--- a/lib/toastergui/templates/projectconf.html
+++ b/lib/srtgui/templates/projectconf.html
diff --git a/lib/toastergui/templates/projects-toastertable.html b/lib/srtgui/templates/projects-toastertable.html
index d8020a97..d8020a97 100644
--- a/lib/toastergui/templates/projects-toastertable.html
+++ b/lib/srtgui/templates/projects-toastertable.html
diff --git a/lib/toastergui/templates/projecttopbar.html b/lib/srtgui/templates/projecttopbar.html
index 768ca945..768ca945 100644
--- a/lib/toastergui/templates/projecttopbar.html
+++ b/lib/srtgui/templates/projecttopbar.html
diff --git a/lib/toastergui/templates/recipe.html b/lib/srtgui/templates/recipe.html
index bf2cd716..bf2cd716 100644
--- a/lib/toastergui/templates/recipe.html
+++ b/lib/srtgui/templates/recipe.html
diff --git a/lib/toastergui/templates/recipe_btn.html b/lib/srtgui/templates/recipe_btn.html
index 0ee0ba55..0ee0ba55 100644
--- a/lib/toastergui/templates/recipe_btn.html
+++ b/lib/srtgui/templates/recipe_btn.html
diff --git a/lib/toastergui/templates/recipe_packages.html b/lib/srtgui/templates/recipe_packages.html
index 37a586f3..37a586f3 100644
--- a/lib/toastergui/templates/recipe_packages.html
+++ b/lib/srtgui/templates/recipe_packages.html
diff --git a/lib/toastergui/templates/recipedetails.html b/lib/srtgui/templates/recipedetails.html
index 66c1f7bc..66c1f7bc 100644
--- a/lib/toastergui/templates/recipedetails.html
+++ b/lib/srtgui/templates/recipedetails.html
diff --git a/lib/toastergui/templates/snippets/gitrev_popover.html b/lib/srtgui/templates/snippets/gitrev_popover.html
index c1e3dabf..c1e3dabf 100644
--- a/lib/toastergui/templates/snippets/gitrev_popover.html
+++ b/lib/srtgui/templates/snippets/gitrev_popover.html
diff --git a/lib/toastergui/templates/snippets/pkg_dependencies_popover.html b/lib/srtgui/templates/snippets/pkg_dependencies_popover.html
index 273437e3..273437e3 100644
--- a/lib/toastergui/templates/snippets/pkg_dependencies_popover.html
+++ b/lib/srtgui/templates/snippets/pkg_dependencies_popover.html
diff --git a/lib/toastergui/templates/snippets/pkg_revdependencies_popover.html b/lib/srtgui/templates/snippets/pkg_revdependencies_popover.html
index e6ef816e..e6ef816e 100644
--- a/lib/toastergui/templates/snippets/pkg_revdependencies_popover.html
+++ b/lib/srtgui/templates/snippets/pkg_revdependencies_popover.html
diff --git a/lib/toastergui/templates/tablesort.html b/lib/srtgui/templates/tablesort.html
index 36247429..36247429 100644
--- a/lib/toastergui/templates/tablesort.html
+++ b/lib/srtgui/templates/tablesort.html
diff --git a/lib/toastergui/templates/target.html b/lib/srtgui/templates/target.html
index 1924a0da..1924a0da 100644
--- a/lib/toastergui/templates/target.html
+++ b/lib/srtgui/templates/target.html
diff --git a/lib/toastergui/templates/task.html b/lib/srtgui/templates/task.html
index 214c7778..214c7778 100644
--- a/lib/toastergui/templates/task.html
+++ b/lib/srtgui/templates/task.html
diff --git a/lib/toastergui/templates/toastertable-filter.html b/lib/srtgui/templates/toastertable-filter.html
index 25eef52a..25eef52a 100644
--- a/lib/toastergui/templates/toastertable-filter.html
+++ b/lib/srtgui/templates/toastertable-filter.html
diff --git a/lib/toastergui/templates/toastertable-simple.html b/lib/srtgui/templates/toastertable-simple.html
index 56cd2ce3..56cd2ce3 100644
--- a/lib/toastergui/templates/toastertable-simple.html
+++ b/lib/srtgui/templates/toastertable-simple.html
diff --git a/lib/toastergui/templates/toastertable.html b/lib/srtgui/templates/toastertable.html
index aa148955..aa148955 100644
--- a/lib/toastergui/templates/toastertable.html
+++ b/lib/srtgui/templates/toastertable.html
diff --git a/lib/toastergui/templates/unavailable_artifact.html b/lib/srtgui/templates/unavailable_artifact.html
index fc77e405..fc77e405 100644
--- a/lib/toastergui/templates/unavailable_artifact.html
+++ b/lib/srtgui/templates/unavailable_artifact.html
diff --git a/lib/bldcontrol/__init__.py b/lib/srtgui/templatetags/__init__.py
index e69de29b..e69de29b 100644
--- a/lib/bldcontrol/__init__.py
+++ b/lib/srtgui/templatetags/__init__.py
diff --git a/lib/toastergui/templatetags/field_values_filter.py b/lib/srtgui/templatetags/field_values_filter.py
index 5a73af79..5a73af79 100644
--- a/lib/toastergui/templatetags/field_values_filter.py
+++ b/lib/srtgui/templatetags/field_values_filter.py
diff --git a/lib/toastergui/templatetags/objects_to_dictionaries_filter.py b/lib/srtgui/templatetags/objects_to_dictionaries_filter.py
index 0dcc7d27..0dcc7d27 100644
--- a/lib/toastergui/templatetags/objects_to_dictionaries_filter.py
+++ b/lib/srtgui/templatetags/objects_to_dictionaries_filter.py
diff --git a/lib/toastergui/templatetags/project_url_tag.py b/lib/srtgui/templatetags/project_url_tag.py
index 04770ac6..04770ac6 100644
--- a/lib/toastergui/templatetags/project_url_tag.py
+++ b/lib/srtgui/templatetags/project_url_tag.py
diff --git a/lib/toastergui/templatetags/projecttags.py b/lib/srtgui/templatetags/projecttags.py
index b170a161..b170a161 100644
--- a/lib/toastergui/templatetags/projecttags.py
+++ b/lib/srtgui/templatetags/projecttags.py
diff --git a/lib/toastergui/typeaheads.py b/lib/srtgui/typeaheads.py
index 5aa0f8d8..5aa0f8d8 100644
--- a/lib/toastergui/typeaheads.py
+++ b/lib/srtgui/typeaheads.py
diff --git a/lib/toastergui/urls.py b/lib/srtgui/urls.py
index e07b0efc..e07b0efc 100644
--- a/lib/toastergui/urls.py
+++ b/lib/srtgui/urls.py
diff --git a/lib/toastergui/views.py b/lib/srtgui/views.py
index 34ed2b2e..34ed2b2e 100755
--- a/lib/toastergui/views.py
+++ b/lib/srtgui/views.py
diff --git a/lib/toastergui/widgets.py b/lib/srtgui/widgets.py
index a1792d99..a1792d99 100644
--- a/lib/toastergui/widgets.py
+++ b/lib/srtgui/widgets.py
diff --git a/lib/bldcontrol/management/__init__.py b/lib/srtmain/__init__.py
index e69de29b..e69de29b 100644
--- a/lib/bldcontrol/management/__init__.py
+++ b/lib/srtmain/__init__.py
diff --git a/lib/bldcontrol/management/commands/__init__.py b/lib/srtmain/management/__init__.py
index e69de29b..e69de29b 100644
--- a/lib/bldcontrol/management/commands/__init__.py
+++ b/lib/srtmain/management/__init__.py
diff --git a/lib/bldcontrol/migrations/__init__.py b/lib/srtmain/management/commands/__init__.py
index e69de29b..e69de29b 100644
--- a/lib/bldcontrol/migrations/__init__.py
+++ b/lib/srtmain/management/commands/__init__.py
diff --git a/lib/toastermain/management/commands/builddelete.py b/lib/srtmain/management/commands/builddelete.py
index 0bef8d41..0bef8d41 100644
--- a/lib/toastermain/management/commands/builddelete.py
+++ b/lib/srtmain/management/commands/builddelete.py
diff --git a/lib/toastermain/management/commands/buildslist.py b/lib/srtmain/management/commands/buildslist.py
index 70b5812d..70b5812d 100644
--- a/lib/toastermain/management/commands/buildslist.py
+++ b/lib/srtmain/management/commands/buildslist.py
diff --git a/lib/toastermain/management/commands/checksocket.py b/lib/srtmain/management/commands/checksocket.py
index 0399b865..0399b865 100644
--- a/lib/toastermain/management/commands/checksocket.py
+++ b/lib/srtmain/management/commands/checksocket.py
diff --git a/lib/toastermain/management/commands/perf.py b/lib/srtmain/management/commands/perf.py
index 6b450bbd..6b450bbd 100644
--- a/lib/toastermain/management/commands/perf.py
+++ b/lib/srtmain/management/commands/perf.py
diff --git a/lib/toastermain/settings.py b/lib/srtmain/settings.py
index 13541d38..13541d38 100644
--- a/lib/toastermain/settings.py
+++ b/lib/srtmain/settings.py
diff --git a/lib/toastermain/settings_production_example.py b/lib/srtmain/settings_production_example.py
index 61a28886..61a28886 100644
--- a/lib/toastermain/settings_production_example.py
+++ b/lib/srtmain/settings_production_example.py
diff --git a/lib/toastermain/settings_test.py b/lib/srtmain/settings_test.py
index a3227115..a3227115 100644
--- a/lib/toastermain/settings_test.py
+++ b/lib/srtmain/settings_test.py
diff --git a/lib/toastermain/urls.py b/lib/srtmain/urls.py
index e2fb0aeb..e2fb0aeb 100644
--- a/lib/toastermain/urls.py
+++ b/lib/srtmain/urls.py
diff --git a/lib/toastermain/wsgi.py b/lib/srtmain/wsgi.py
index 031b314b..031b314b 100644
--- a/lib/toastermain/wsgi.py
+++ b/lib/srtmain/wsgi.py
diff --git a/lib/tests/__init__.py b/lib/tests/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/lib/tests/__init__.py
+++ /dev/null
diff --git a/lib/tests/browser/README b/lib/tests/browser/README
deleted file mode 100644
index 352c4fe3..00000000
--- a/lib/tests/browser/README
+++ /dev/null
@@ -1,74 +0,0 @@
-# Running Toaster's browser-based test suite
-
-These tests require Selenium to be installed in your Python environment.
-
-The simplest way to install this is via pip3:
-
- pip3 install selenium==2.53.2
-
-Note that if you use other versions of Selenium, some of the tests (such as
-tests.browser.test_js_unit_tests.TestJsUnitTests) may fail, as these rely on
-a Selenium test report with a version-specific format.
-
-To run tests against Chrome:
-
-* Download chromedriver for your host OS from
- https://sites.google.com/a/chromium.org/chromedriver/downloads
-* On *nix systems, put chromedriver on PATH
-* On Windows, put chromedriver.exe in the same directory as chrome.exe
-
-To run tests against PhantomJS (headless):
---NOTE - Selenium seems to be deprecating support for this mode ---
-* Download and install PhantomJS:
- http://phantomjs.org/download.html
-* On *nix systems, put phantomjs on PATH
-* Not tested on Windows
-
-To run tests against Firefox, you may need to install the Marionette driver,
-depending on how new your version of Firefox is. One clue that you need to do
-this is if you see an exception like:
-
- selenium.common.exceptions.WebDriverException: Message: The browser
- appears to have exited before we could connect. If you specified
- a log_file in the FirefoxBinary constructor, check it for details.
-
-See https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette/WebDriver
-for installation instructions. Ensure that the Marionette executable (renamed
-as wires on Linux or wires.exe on Windows) is on your PATH; and use "marionette"
-as the browser string passed via TOASTER_TESTS_BROWSER (see below).
-
-(Note: The Toaster tests have been checked against Firefox 47 with the
-Marionette driver.)
-
-The test cases will instantiate a Selenium driver set by the
-TOASTER_TESTS_BROWSER environment variable, or Chrome if this is not specified.
-
-To run tests against the Selenium Firefox Docker container:
-More explanation is located at https://wiki.yoctoproject.org/wiki/TipsAndTricks/TestingToasterWithContainers
-* Run the Selenium container:
- ** docker run -it --rm=true -p 5900:5900 -p 4444:4444 --name=selenium selenium/standalone-firefox-debug:2.53.0
- *** 5900 is the default vnc port. If you are runing a vnc server on your machine map a different port e.g. -p 6900:5900 and connect vnc client to 127.0.0.1:6900
- *** 4444 is the default selenium sever port.
-* Run the tests
- ** TOASTER_TESTS_BROWSER=http://127.0.0.1:4444/wd/hub TOASTER_TESTS_URL=http://172.17.0.1:8000 ./bitbake/lib/toaster/manage.py test --liveserver=172.17.0.1:8000 tests.browser
- ** TOASTER_TESTS_BROWSER=remote TOASTER_REMOTE_HUB=http://127.0.0.1:4444/wd/hub ./bitbake/lib/toaster/manage.py test --liveserver=172.17.0.1:8000 tests.browser
- *** TOASTER_REMOTE_HUB - This is the address for the Selenium Remote Web Driver hub. Assuming you ran the contianer with -p 4444:4444 it will be http://127.0.0.1:4444/wd/hub.
- *** --liveserver=xxx tells Django to run the test server on an interface and port reachable by both host and container.
- **** 172.17.0.1 is the default docker bridge on linux, viewable from inside and outside the contianers. Find it with "ip -4 addr show dev docker0"
-* connect to the vnc server to see the tests if you would like
- ** xtightvncviewer 127.0.0.1:5900
- ** note, you need to wait for the test container to come up before this can connect.
-
-Available drivers:
-
-* chrome (default)
-* firefox
-* marionette (for newer Firefoxes)
-* ie
-* phantomjs (deprecated)
-* remote
-
-e.g. to run the test suite with phantomjs where you have phantomjs installed
-in /home/me/apps/phantomjs:
-
-PATH=/home/me/apps/phantomjs/bin:$PATH TOASTER_TESTS_BROWSER=phantomjs manage.py test tests.browser
diff --git a/lib/tests/browser/__init__.py b/lib/tests/browser/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/lib/tests/browser/__init__.py
+++ /dev/null
diff --git a/lib/tests/browser/selenium_helpers.py b/lib/tests/browser/selenium_helpers.py
deleted file mode 100644
index 08711e45..00000000
--- a/lib/tests/browser/selenium_helpers.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# The Wait class and some of SeleniumDriverHelper and SeleniumTestCase are
-# modified from Patchwork, released under the same licence terms as Toaster:
-# https://github.com/dlespiau/patchwork/blob/master/patchwork/tests.browser.py
-
-"""
-Helper methods for creating Toaster Selenium tests which run within
-the context of Django unit tests.
-"""
-from django.contrib.staticfiles.testing import StaticLiveServerTestCase
-from tests.browser.selenium_helpers_base import SeleniumTestCaseBase
-
-class SeleniumTestCase(SeleniumTestCaseBase, StaticLiveServerTestCase):
- pass
diff --git a/lib/tests/browser/selenium_helpers_base.py b/lib/tests/browser/selenium_helpers_base.py
deleted file mode 100644
index 156d639b..00000000
--- a/lib/tests/browser/selenium_helpers_base.py
+++ /dev/null
@@ -1,227 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# The Wait class and some of SeleniumDriverHelper and SeleniumTestCase are
-# modified from Patchwork, released under the same licence terms as Toaster:
-# https://github.com/dlespiau/patchwork/blob/master/patchwork/tests.browser.py
-
-"""
-Helper methods for creating Toaster Selenium tests which run within
-the context of Django unit tests.
-"""
-
-import os
-import time
-import unittest
-
-from django.contrib.staticfiles.testing import StaticLiveServerTestCase
-from selenium import webdriver
-from selenium.webdriver.support.ui import WebDriverWait
-from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
-from selenium.common.exceptions import NoSuchElementException, \
- StaleElementReferenceException, TimeoutException
-
-def create_selenium_driver(cls,browser='chrome'):
- # set default browser string based on env (if available)
- env_browser = os.environ.get('TOASTER_TESTS_BROWSER')
- if env_browser:
- browser = env_browser
-
- if browser == 'chrome':
- return webdriver.Chrome(
- service_args=["--verbose", "--log-path=selenium.log"]
- )
- elif browser == 'firefox':
- return webdriver.Firefox()
- elif browser == 'marionette':
- capabilities = DesiredCapabilities.FIREFOX
- capabilities['marionette'] = True
- return webdriver.Firefox(capabilities=capabilities)
- elif browser == 'ie':
- return webdriver.Ie()
- elif browser == 'phantomjs':
- return webdriver.PhantomJS()
- elif browser == 'remote':
- # if we were to add yet another env variable like TOASTER_REMOTE_BROWSER
- # we could let people pick firefox or chrome, left for later
- remote_hub= os.environ.get('TOASTER_REMOTE_HUB')
- driver = webdriver.Remote(remote_hub,
- webdriver.DesiredCapabilities.FIREFOX.copy())
-
- driver.get("http://%s:%s"%(cls.server_thread.host,cls.server_thread.port))
- return driver
- else:
- msg = 'Selenium driver for browser %s is not available' % browser
- raise RuntimeError(msg)
-
-class Wait(WebDriverWait):
- """
- Subclass of WebDriverWait with predetermined timeout and poll
- frequency. Also deals with a wider variety of exceptions.
- """
- _TIMEOUT = 10
- _POLL_FREQUENCY = 0.5
-
- def __init__(self, driver):
- super(Wait, self).__init__(driver, self._TIMEOUT, self._POLL_FREQUENCY)
-
- def until(self, method, message=''):
- """
- Calls the method provided with the driver as an argument until the
- return value is not False.
- """
-
- end_time = time.time() + self._timeout
- while True:
- try:
- value = method(self._driver)
- if value:
- return value
- except NoSuchElementException:
- pass
- except StaleElementReferenceException:
- pass
-
- time.sleep(self._poll)
- if time.time() > end_time:
- break
-
- raise TimeoutException(message)
-
- def until_not(self, method, message=''):
- """
- Calls the method provided with the driver as an argument until the
- return value is False.
- """
-
- end_time = time.time() + self._timeout
- while True:
- try:
- value = method(self._driver)
- if not value:
- return value
- except NoSuchElementException:
- return True
- except StaleElementReferenceException:
- pass
-
- time.sleep(self._poll)
- if time.time() > end_time:
- break
-
- raise TimeoutException(message)
-
-class SeleniumTestCaseBase(unittest.TestCase):
- """
- NB StaticLiveServerTestCase is used as the base test case so that
- static files are served correctly in a Selenium test run context; see
- https://docs.djangoproject.com/en/1.9/ref/contrib/staticfiles/#specialized-test-case-to-support-live-testing
- """
-
- @classmethod
- def setUpClass(cls):
- """ Create a webdriver driver at the class level """
-
- super(SeleniumTestCaseBase, cls).setUpClass()
-
- # instantiate the Selenium webdriver once for all the test methods
- # in this test case
- cls.driver = create_selenium_driver(cls)
- cls.driver.maximize_window()
-
- @classmethod
- def tearDownClass(cls):
- """ Clean up webdriver driver """
-
- cls.driver.quit()
- super(SeleniumTestCaseBase, cls).tearDownClass()
-
- def get(self, url):
- """
- Selenium requires absolute URLs, so convert Django URLs returned
- by resolve() or similar to absolute ones and get using the
- webdriver instance.
-
- url: a relative URL
- """
- abs_url = '%s%s' % (self.live_server_url, url)
- self.driver.get(abs_url)
-
- def find(self, selector):
- """ Find single element by CSS selector """
- return self.driver.find_element_by_css_selector(selector)
-
- def find_all(self, selector):
- """ Find all elements matching CSS selector """
- return self.driver.find_elements_by_css_selector(selector)
-
- def element_exists(self, selector):
- """
- Return True if one element matching selector exists,
- False otherwise
- """
- return len(self.find_all(selector)) == 1
-
- def focused_element(self):
- """ Return the element which currently has focus on the page """
- return self.driver.switch_to.active_element
-
- def wait_until_present(self, selector):
- """ Wait until element matching CSS selector is on the page """
- is_present = lambda driver: self.find(selector)
- msg = 'An element matching "%s" should be on the page' % selector
- element = Wait(self.driver).until(is_present, msg)
- return element
-
- def wait_until_visible(self, selector):
- """ Wait until element matching CSS selector is visible on the page """
- is_visible = lambda driver: self.find(selector).is_displayed()
- msg = 'An element matching "%s" should be visible' % selector
- Wait(self.driver).until(is_visible, msg)
- return self.find(selector)
-
- def wait_until_focused(self, selector):
- """ Wait until element matching CSS selector has focus """
- is_focused = \
- lambda driver: self.find(selector) == self.focused_element()
- msg = 'An element matching "%s" should be focused' % selector
- Wait(self.driver).until(is_focused, msg)
- return self.find(selector)
-
- def enter_text(self, selector, value):
- """ Insert text into element matching selector """
- # note that keyup events don't occur until the element is clicked
- # (in the case of <input type="text"...>, for example), so simulate
- # user clicking the element before inserting text into it
- field = self.click(selector)
-
- field.send_keys(value)
- return field
-
- def click(self, selector):
- """ Click on element which matches CSS selector """
- element = self.wait_until_visible(selector)
- element.click()
- return element
-
- def get_page_source(self):
- """ Get raw HTML for the current page """
- return self.driver.page_source
diff --git a/lib/tests/browser/test_all_builds_page.py b/lib/tests/browser/test_all_builds_page.py
deleted file mode 100644
index b86f29bd..00000000
--- a/lib/tests/browser/test_all_builds_page.py
+++ /dev/null
@@ -1,233 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import re
-
-from django.core.urlresolvers import reverse
-from django.utils import timezone
-from tests.browser.selenium_helpers import SeleniumTestCase
-
-from orm.models import BitbakeVersion, Release, Project, Build, Target
-
-
-class TestAllBuildsPage(SeleniumTestCase):
- """ Tests for all builds page /builds/ """
-
- PROJECT_NAME = 'test project'
- CLI_BUILDS_PROJECT_NAME = 'command line builds'
-
- def setUp(self):
- bbv = BitbakeVersion.objects.create(name='bbv1', giturl='/tmp/',
- branch='master', dirpath='')
- release = Release.objects.create(name='release1',
- bitbake_version=bbv)
- self.project1 = Project.objects.create_project(name=self.PROJECT_NAME,
- release=release)
- self.default_project = Project.objects.create_project(
- name=self.CLI_BUILDS_PROJECT_NAME,
- release=release
- )
- self.default_project.is_default = True
- self.default_project.save()
-
- # parameters for builds to associate with the projects
- now = timezone.now()
-
- self.project1_build_success = {
- 'project': self.project1,
- 'started_on': now,
- 'completed_on': now,
- 'outcome': Build.SUCCEEDED
- }
-
- self.project1_build_failure = {
- 'project': self.project1,
- 'started_on': now,
- 'completed_on': now,
- 'outcome': Build.FAILED
- }
-
- self.default_project_build_success = {
- 'project': self.default_project,
- 'started_on': now,
- 'completed_on': now,
- 'outcome': Build.SUCCEEDED
- }
-
- def _get_build_time_element(self, build):
- """
- Return the HTML element containing the build time for a build
- in the recent builds area
- """
- selector = 'div[data-latest-build-result="%s"] ' \
- '[data-role="data-recent-build-buildtime-field"]' % build.id
-
- # because this loads via Ajax, wait for it to be visible
- self.wait_until_present(selector)
-
- build_time_spans = self.find_all(selector)
-
- self.assertEqual(len(build_time_spans), 1)
-
- return build_time_spans[0]
-
- def _get_row_for_build(self, build):
- """ Get the table row for the build from the all builds table """
- self.wait_until_present('#allbuildstable')
-
- rows = self.find_all('#allbuildstable tr')
-
- # look for the row with a download link on the recipe which matches the
- # build ID
- url = reverse('builddashboard', args=(build.id,))
- selector = 'td.target a[href="%s"]' % url
-
- found_row = None
- for row in rows:
-
- outcome_links = row.find_elements_by_css_selector(selector)
- if len(outcome_links) == 1:
- found_row = row
- break
-
- self.assertNotEqual(found_row, None)
-
- return found_row
-
- def test_show_tasks_with_suffix(self):
- """ Task should be shown as suffix on build name """
- build = Build.objects.create(**self.project1_build_success)
- target = 'bash'
- task = 'clean'
- Target.objects.create(build=build, target=target, task=task)
-
- url = reverse('all-builds')
- self.get(url)
- self.wait_until_present('td[class="target"]')
-
- cell = self.find('td[class="target"]')
- content = cell.get_attribute('innerHTML')
- expected_text = '%s:%s' % (target, task)
-
- self.assertTrue(re.search(expected_text, content),
- '"target" cell should contain text %s' % expected_text)
-
- def test_rebuild_buttons(self):
- """
- Test 'Rebuild' buttons in recent builds section
-
- 'Rebuild' button should not be shown for command-line builds,
- but should be shown for other builds
- """
- build1 = Build.objects.create(**self.project1_build_success)
- default_build = Build.objects.create(**self.default_project_build_success)
-
- url = reverse('all-builds')
- self.get(url)
-
- # shouldn't see a rebuild button for command-line builds
- selector = 'div[data-latest-build-result="%s"] .rebuild-btn' % default_build.id
- run_again_button = self.find_all(selector)
- self.assertEqual(len(run_again_button), 0,
- 'should not see a rebuild button for cli builds')
-
- # should see a rebuild button for non-command-line builds
- selector = 'div[data-latest-build-result="%s"] .rebuild-btn' % build1.id
- run_again_button = self.find_all(selector)
- self.assertEqual(len(run_again_button), 1,
- 'should see a rebuild button for non-cli builds')
-
- def test_tooltips_on_project_name(self):
- """
- Test tooltips shown next to project name in the main table
-
- A tooltip should be present next to the command line
- builds project name in the all builds page, but not for
- other projects
- """
- Build.objects.create(**self.project1_build_success)
- Build.objects.create(**self.default_project_build_success)
-
- url = reverse('all-builds')
- self.get(url)
-
- # get the project name cells from the table
- cells = self.find_all('#allbuildstable td[class="project"]')
-
- selector = 'span.get-help'
-
- for cell in cells:
- content = cell.get_attribute('innerHTML')
- help_icons = cell.find_elements_by_css_selector(selector)
-
- if re.search(self.PROJECT_NAME, content):
- # no help icon next to non-cli project name
- msg = 'should not be a help icon for non-cli builds name'
- self.assertEqual(len(help_icons), 0, msg)
- elif re.search(self.CLI_BUILDS_PROJECT_NAME, content):
- # help icon next to cli project name
- msg = 'should be a help icon for cli builds name'
- self.assertEqual(len(help_icons), 1, msg)
- else:
- msg = 'found unexpected project name cell in all builds table'
- self.fail(msg)
-
- def test_builds_time_links(self):
- """
- Successful builds should have links on the time column and in the
- recent builds area; failed builds should not have links on the time column,
- or in the recent builds area
- """
- build1 = Build.objects.create(**self.project1_build_success)
- build2 = Build.objects.create(**self.project1_build_failure)
-
- # add some targets to these builds so they have recipe links
- # (and so we can find the row in the ToasterTable corresponding to
- # a particular build)
- Target.objects.create(build=build1, target='foo')
- Target.objects.create(build=build2, target='bar')
-
- url = reverse('all-builds')
- self.get(url)
-
- # test recent builds area for successful build
- element = self._get_build_time_element(build1)
- links = element.find_elements_by_css_selector('a')
- msg = 'should be a link on the build time for a successful recent build'
- self.assertEquals(len(links), 1, msg)
-
- # test recent builds area for failed build
- element = self._get_build_time_element(build2)
- links = element.find_elements_by_css_selector('a')
- msg = 'should not be a link on the build time for a failed recent build'
- self.assertEquals(len(links), 0, msg)
-
- # test the time column for successful build
- build1_row = self._get_row_for_build(build1)
- links = build1_row.find_elements_by_css_selector('td.time a')
- msg = 'should be a link on the build time for a successful build'
- self.assertEquals(len(links), 1, msg)
-
- # test the time column for failed build
- build2_row = self._get_row_for_build(build2)
- links = build2_row.find_elements_by_css_selector('td.time a')
- msg = 'should not be a link on the build time for a failed build'
- self.assertEquals(len(links), 0, msg)
diff --git a/lib/tests/browser/test_all_projects_page.py b/lib/tests/browser/test_all_projects_page.py
deleted file mode 100644
index 44da6407..00000000
--- a/lib/tests/browser/test_all_projects_page.py
+++ /dev/null
@@ -1,217 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import re
-
-from django.core.urlresolvers import reverse
-from django.utils import timezone
-from tests.browser.selenium_helpers import SeleniumTestCase
-
-from orm.models import BitbakeVersion, Release, Project, Build
-from orm.models import ProjectVariable
-
-class TestAllProjectsPage(SeleniumTestCase):
- """ Browser tests for projects page /projects/ """
-
- PROJECT_NAME = 'test project'
- CLI_BUILDS_PROJECT_NAME = 'command line builds'
- MACHINE_NAME = 'delorean'
-
- def setUp(self):
- """ Add default project manually """
- project = Project.objects.create_project(self.CLI_BUILDS_PROJECT_NAME, None)
- self.default_project = project
- self.default_project.is_default = True
- self.default_project.save()
-
- # this project is only set for some of the tests
- self.project = None
-
- self.release = None
-
- def _add_build_to_default_project(self):
- """ Add a build to the default project (not used in all tests) """
- now = timezone.now()
- build = Build.objects.create(project=self.default_project,
- started_on=now,
- completed_on=now)
- build.save()
-
- def _add_non_default_project(self):
- """ Add another project """
- bbv = BitbakeVersion.objects.create(name='test bbv', giturl='/tmp/',
- branch='master', dirpath='')
- self.release = Release.objects.create(name='test release',
- branch_name='master',
- bitbake_version=bbv)
- self.project = Project.objects.create_project(self.PROJECT_NAME, self.release)
- self.project.is_default = False
- self.project.save()
-
- # fake the MACHINE variable
- project_var = ProjectVariable.objects.create(project=self.project,
- name='MACHINE',
- value=self.MACHINE_NAME)
- project_var.save()
-
- def _get_row_for_project(self, project_name):
- """ Get the HTML row for a project, or None if not found """
- self.wait_until_present('#projectstable tbody tr')
- rows = self.find_all('#projectstable tbody tr')
-
- # find the row with a project name matching the one supplied
- found_row = None
- for row in rows:
- if re.search(project_name, row.get_attribute('innerHTML')):
- found_row = row
- break
-
- return found_row
-
- def test_default_project_hidden(self):
- """
- The default project should be hidden if it has no builds
- and we should see the "no results" area
- """
- url = reverse('all-projects')
- self.get(url)
- self.wait_until_visible('#empty-state-projectstable')
-
- rows = self.find_all('#projectstable tbody tr')
- self.assertEqual(len(rows), 0, 'should be no projects displayed')
-
- def test_default_project_has_build(self):
- """ The default project should be shown if it has builds """
- self._add_build_to_default_project()
-
- url = reverse('all-projects')
- self.get(url)
-
- default_project_row = self._get_row_for_project(self.default_project.name)
-
- self.assertNotEqual(default_project_row, None,
- 'default project "cli builds" should be in page')
-
- def test_default_project_release(self):
- """
- The release for the default project should display as
- 'Not applicable'
- """
- # need a build, otherwise project doesn't display at all
- self._add_build_to_default_project()
-
- # another project to test, which should show release
- self._add_non_default_project()
-
- self.get(reverse('all-projects'))
- self.wait_until_visible("#projectstable tr")
-
- # find the row for the default project
- default_project_row = self._get_row_for_project(self.default_project.name)
-
- # check the release text for the default project
- selector = 'span[data-project-field="release"] span.text-muted'
- element = default_project_row.find_element_by_css_selector(selector)
- text = element.text.strip()
- self.assertEqual(text, 'Not applicable',
- 'release should be "not applicable" for default project')
-
- # find the row for the default project
- other_project_row = self._get_row_for_project(self.project.name)
-
- # check the link in the release cell for the other project
- selector = 'span[data-project-field="release"]'
- element = other_project_row.find_element_by_css_selector(selector)
- text = element.text.strip()
- self.assertEqual(text, self.release.name,
- 'release name should be shown for non-default project')
-
- def test_default_project_machine(self):
- """
- The machine for the default project should display as
- 'Not applicable'
- """
- # need a build, otherwise project doesn't display at all
- self._add_build_to_default_project()
-
- # another project to test, which should show machine
- self._add_non_default_project()
-
- self.get(reverse('all-projects'))
-
- self.wait_until_visible("#projectstable tr")
-
- # find the row for the default project
- default_project_row = self._get_row_for_project(self.default_project.name)
-
- # check the machine cell for the default project
- selector = 'span[data-project-field="machine"] span.text-muted'
- element = default_project_row.find_element_by_css_selector(selector)
- text = element.text.strip()
- self.assertEqual(text, 'Not applicable',
- 'machine should be not applicable for default project')
-
- # find the row for the default project
- other_project_row = self._get_row_for_project(self.project.name)
-
- # check the link in the machine cell for the other project
- selector = 'span[data-project-field="machine"]'
- element = other_project_row.find_element_by_css_selector(selector)
- text = element.text.strip()
- self.assertEqual(text, self.MACHINE_NAME,
- 'machine name should be shown for non-default project')
-
- def test_project_page_links(self):
- """
- Test that links for the default project point to the builds
- page /projects/X/builds for that project, and that links for
- other projects point to their configuration pages /projects/X/
- """
-
- # need a build, otherwise project doesn't display at all
- self._add_build_to_default_project()
-
- # another project to test
- self._add_non_default_project()
-
- self.get(reverse('all-projects'))
-
- # find the row for the default project
- default_project_row = self._get_row_for_project(self.default_project.name)
-
- # check the link on the name field
- selector = 'span[data-project-field="name"] a'
- element = default_project_row.find_element_by_css_selector(selector)
- link_url = element.get_attribute('href').strip()
- expected_url = reverse('projectbuilds', args=(self.default_project.id,))
- msg = 'link on default project name should point to builds but was %s' % link_url
- self.assertTrue(link_url.endswith(expected_url), msg)
-
- # find the row for the other project
- other_project_row = self._get_row_for_project(self.project.name)
-
- # check the link for the other project
- selector = 'span[data-project-field="name"] a'
- element = other_project_row.find_element_by_css_selector(selector)
- link_url = element.get_attribute('href').strip()
- expected_url = reverse('project', args=(self.project.id,))
- msg = 'link on project name should point to configuration but was %s' % link_url
- self.assertTrue(link_url.endswith(expected_url), msg)
diff --git a/lib/tests/browser/test_builddashboard_page.py b/lib/tests/browser/test_builddashboard_page.py
deleted file mode 100644
index f8ccb545..00000000
--- a/lib/tests/browser/test_builddashboard_page.py
+++ /dev/null
@@ -1,347 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-from django.core.urlresolvers import reverse
-from django.utils import timezone
-
-from tests.browser.selenium_helpers import SeleniumTestCase
-
-from orm.models import Project, Release, BitbakeVersion, Build, LogMessage
-from orm.models import Layer, Layer_Version, Recipe, CustomImageRecipe, Variable
-
-class TestBuildDashboardPage(SeleniumTestCase):
- """ Tests for the build dashboard /build/X """
-
- def setUp(self):
- bbv = BitbakeVersion.objects.create(name='bbv1', giturl='/tmp/',
- branch='master', dirpath="")
- release = Release.objects.create(name='release1',
- bitbake_version=bbv)
- project = Project.objects.create_project(name='test project',
- release=release)
-
- now = timezone.now()
-
- self.build1 = Build.objects.create(project=project,
- started_on=now,
- completed_on=now,
- outcome=Build.SUCCEEDED)
-
- self.build2 = Build.objects.create(project=project,
- started_on=now,
- completed_on=now,
- outcome=Build.SUCCEEDED)
-
- self.build3 = Build.objects.create(project=project,
- started_on=now,
- completed_on=now,
- outcome=Build.FAILED)
-
- # add Variable objects to the successful builds, as this is the criterion
- # used to determine whether the left-hand panel should be displayed
- Variable.objects.create(build=self.build1,
- variable_name='Foo',
- variable_value='Bar')
- Variable.objects.create(build=self.build2,
- variable_name='Foo',
- variable_value='Bar')
-
- # exception
- msg1 = 'an exception was thrown'
- self.exception_message = LogMessage.objects.create(
- build=self.build1,
- level=LogMessage.EXCEPTION,
- message=msg1
- )
-
- # critical
- msg2 = 'a critical error occurred'
- self.critical_message = LogMessage.objects.create(
- build=self.build1,
- level=LogMessage.CRITICAL,
- message=msg2
- )
-
- # error on the failed build
- msg3 = 'an error occurred'
- self.error_message = LogMessage.objects.create(
- build=self.build3,
- level=LogMessage.ERROR,
- message=msg3
- )
-
- # warning on the failed build
- msg4 = 'DANGER WILL ROBINSON'
- self.warning_message = LogMessage.objects.create(
- build=self.build3,
- level=LogMessage.WARNING,
- message=msg4
- )
-
- # recipes related to the build, for testing the edit custom image/new
- # custom image buttons
- layer = Layer.objects.create(name='alayer')
- layer_version = Layer_Version.objects.create(
- layer=layer, build=self.build1
- )
-
- # non-image recipes related to a build, for testing the new custom
- # image button
- layer_version2 = Layer_Version.objects.create(layer=layer,
- build=self.build3)
-
- # image recipes
- self.image_recipe1 = Recipe.objects.create(
- name='recipeA',
- layer_version=layer_version,
- file_path='/foo/recipeA.bb',
- is_image=True
- )
- self.image_recipe2 = Recipe.objects.create(
- name='recipeB',
- layer_version=layer_version,
- file_path='/foo/recipeB.bb',
- is_image=True
- )
-
- # custom image recipes for this project
- self.custom_image_recipe1 = CustomImageRecipe.objects.create(
- name='customRecipeY',
- project=project,
- layer_version=layer_version,
- file_path='/foo/customRecipeY.bb',
- base_recipe=self.image_recipe1,
- is_image=True
- )
- self.custom_image_recipe2 = CustomImageRecipe.objects.create(
- name='customRecipeZ',
- project=project,
- layer_version=layer_version,
- file_path='/foo/customRecipeZ.bb',
- base_recipe=self.image_recipe2,
- is_image=True
- )
-
- # custom image recipe for a different project (to test filtering
- # of image recipes and custom image recipes is correct: this shouldn't
- # show up in either query against self.build1)
- self.custom_image_recipe3 = CustomImageRecipe.objects.create(
- name='customRecipeOmega',
- project=Project.objects.create(name='baz', release=release),
- layer_version=Layer_Version.objects.create(
- layer=layer, build=self.build2
- ),
- file_path='/foo/customRecipeOmega.bb',
- base_recipe=self.image_recipe2,
- is_image=True
- )
-
- # another non-image recipe (to test filtering of image recipes and
- # custom image recipes is correct: this shouldn't show up in either
- # for any build)
- self.non_image_recipe = Recipe.objects.create(
- name='nonImageRecipe',
- layer_version=layer_version,
- file_path='/foo/nonImageRecipe.bb',
- is_image=False
- )
-
- def _get_build_dashboard(self, build):
- """
- Navigate to the build dashboard for build
- """
- url = reverse('builddashboard', args=(build.id,))
- self.get(url)
-
- def _get_build_dashboard_errors(self, build):
- """
- Get a list of HTML fragments representing the errors on the
- dashboard for the Build object build
- """
- self._get_build_dashboard(build)
- return self.find_all('#errors div.alert-danger')
-
- def _check_for_log_message(self, message_elements, log_message):
- """
- Check that the LogMessage <log_message> has a representation in
- the HTML elements <message_elements>.
-
- message_elements: WebElements representing the log messages shown
- in the build dashboard; each should have a <pre> element inside
- it with a data-log-message-id attribute
-
- log_message: orm.models.LogMessage instance
- """
- expected_text = log_message.message
- expected_pk = str(log_message.pk)
-
- found = False
- for element in message_elements:
- log_message_text = element.find_element_by_tag_name('pre').text.strip()
- text_matches = (log_message_text == expected_text)
-
- log_message_pk = element.get_attribute('data-log-message-id')
- id_matches = (log_message_pk == expected_pk)
-
- if text_matches and id_matches:
- found = True
- break
-
- template_vars = (expected_text, expected_pk)
- assertion_failed_msg = 'message not found: ' \
- 'expected text "%s" and ID %s' % template_vars
- self.assertTrue(found, assertion_failed_msg)
-
- def _check_for_error_message(self, build, log_message):
- """
- Check whether the LogMessage instance <log_message> is
- represented as an HTML error in the dashboard page for the Build object
- build
- """
- errors = self._get_build_dashboard_errors(build)
- self._check_for_log_message(errors, log_message)
-
- def _check_labels_in_modal(self, modal, expected):
- """
- Check that the text values of the <label> elements inside
- the WebElement modal match the list of text values in expected
- """
- # labels containing the radio buttons we're testing for
- labels = modal.find_elements_by_css_selector(".radio")
-
- labels_text = [lab.text for lab in labels]
- self.assertEqual(len(labels_text), len(expected))
-
- for expected_text in expected:
- self.assertTrue(expected_text in labels_text,
- "Could not find %s in %s" % (expected_text,
- labels_text))
-
- def test_exceptions_show_as_errors(self):
- """
- LogMessages with level EXCEPTION should display in the errors
- section of the page
- """
- self._check_for_error_message(self.build1, self.exception_message)
-
- def test_criticals_show_as_errors(self):
- """
- LogMessages with level CRITICAL should display in the errors
- section of the page
- """
- self._check_for_error_message(self.build1, self.critical_message)
-
- def test_edit_custom_image_button(self):
- """
- A build which built two custom images should present a modal which lets
- the user choose one of them to edit
- """
- self._get_build_dashboard(self.build1)
-
- # click the "edit custom image" button, which populates the modal
- selector = '[data-role="edit-custom-image-trigger"]'
- self.click(selector)
-
- modal = self.driver.find_element_by_id('edit-custom-image-modal')
- self.wait_until_visible("#edit-custom-image-modal")
-
- # recipes we expect to see in the edit custom image modal
- expected_recipes = [
- self.custom_image_recipe1.name,
- self.custom_image_recipe2.name
- ]
-
- self._check_labels_in_modal(modal, expected_recipes)
-
- def test_new_custom_image_button(self):
- """
- Check that a build with multiple images and custom images presents
- all of them as options for creating a new custom image from
- """
- self._get_build_dashboard(self.build1)
-
- # click the "new custom image" button, which populates the modal
- selector = '[data-role="new-custom-image-trigger"]'
- self.click(selector)
-
- modal = self.driver.find_element_by_id('new-custom-image-modal')
- self.wait_until_visible("#new-custom-image-modal")
-
- # recipes we expect to see in the new custom image modal
- expected_recipes = [
- self.image_recipe1.name,
- self.image_recipe2.name,
- self.custom_image_recipe1.name,
- self.custom_image_recipe2.name
- ]
-
- self._check_labels_in_modal(modal, expected_recipes)
-
- def test_new_custom_image_button_no_image(self):
- """
- Check that a build which builds non-image recipes doesn't show
- the new custom image button on the dashboard.
- """
- self._get_build_dashboard(self.build3)
- selector = '[data-role="new-custom-image-trigger"]'
- self.assertFalse(self.element_exists(selector),
- 'new custom image button should not show for builds which ' \
- 'don\'t have any image recipes')
-
- def test_left_panel(self):
- """"
- Builds which succeed should have a left panel and a build summary
- """
- self._get_build_dashboard(self.build1)
-
- left_panel = self.find_all('#nav')
- self.assertEqual(len(left_panel), 1)
-
- build_summary = self.find_all('[data-role="build-summary-heading"]')
- self.assertEqual(len(build_summary), 1)
-
- def test_failed_no_left_panel(self):
- """
- Builds which fail should have no left panel and no build summary
- """
- self._get_build_dashboard(self.build3)
-
- left_panel = self.find_all('#nav')
- self.assertEqual(len(left_panel), 0)
-
- build_summary = self.find_all('[data-role="build-summary-heading"]')
- self.assertEqual(len(build_summary), 0)
-
- def test_failed_shows_errors_and_warnings(self):
- """
- Failed builds should still show error and warning messages
- """
- self._get_build_dashboard(self.build3)
-
- errors = self.find_all('#errors div.alert-danger')
- self._check_for_log_message(errors, self.error_message)
-
- # expand the warnings area
- self.click('#warning-toggle')
- self.wait_until_visible('#warnings div.alert-warning')
-
- warnings = self.find_all('#warnings div.alert-warning')
- self._check_for_log_message(warnings, self.warning_message)
diff --git a/lib/tests/browser/test_builddashboard_page_artifacts.py b/lib/tests/browser/test_builddashboard_page_artifacts.py
deleted file mode 100644
index 1c627ad4..00000000
--- a/lib/tests/browser/test_builddashboard_page_artifacts.py
+++ /dev/null
@@ -1,222 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-from django.core.urlresolvers import reverse
-from django.utils import timezone
-
-from tests.browser.selenium_helpers import SeleniumTestCase
-
-from orm.models import Project, Release, BitbakeVersion, Build, Target, Package
-from orm.models import Target_Image_File, TargetSDKFile, TargetKernelFile
-from orm.models import Target_Installed_Package, Variable
-
-class TestBuildDashboardPageArtifacts(SeleniumTestCase):
- """ Tests for artifacts on the build dashboard /build/X """
-
- def setUp(self):
- bbv = BitbakeVersion.objects.create(name='bbv1', giturl='/tmp/',
- branch='master', dirpath="")
- release = Release.objects.create(name='release1',
- bitbake_version=bbv)
- self.project = Project.objects.create_project(name='test project',
- release=release)
-
- def _get_build_dashboard(self, build):
- """
- Navigate to the build dashboard for build
- """
- url = reverse('builddashboard', args=(build.id,))
- self.get(url)
-
- def _has_build_artifacts_heading(self):
- """
- Check whether the "Build artifacts" heading is visible (True if it
- is, False otherwise).
- """
- return self.element_exists('[data-heading="build-artifacts"]')
-
- def _has_images_menu_option(self):
- """
- Try to get the "Images" list element from the left-hand menu in the
- build dashboard, and return True if it is present, False otherwise.
- """
- return self.element_exists('li.nav-header[data-menu-heading="images"]')
-
- def test_no_artifacts(self):
- """
- If a build produced no artifacts, the artifacts heading and images
- menu option shouldn't show.
- """
- now = timezone.now()
- build = Build.objects.create(project=self.project,
- started_on=now, completed_on=now, outcome=Build.SUCCEEDED)
-
- Target.objects.create(is_image=False, build=build, task='',
- target='mpfr-native')
-
- self._get_build_dashboard(build)
-
- # check build artifacts heading
- msg = 'Build artifacts heading should not be displayed for non-image' \
- 'builds'
- self.assertFalse(self._has_build_artifacts_heading(), msg)
-
- # check "Images" option in left-hand menu (should not be there)
- msg = 'Images option should not be shown in left-hand menu'
- self.assertFalse(self._has_images_menu_option(), msg)
-
- def test_sdk_artifacts(self):
- """
- If a build produced SDK artifacts, they should be shown, but the section
- for image files and the images menu option should be hidden.
-
- The packages count and size should also be hidden.
- """
- now = timezone.now()
- build = Build.objects.create(project=self.project,
- started_on=now, completed_on=timezone.now(),
- outcome=Build.SUCCEEDED)
-
- target = Target.objects.create(is_image=True, build=build,
- task='populate_sdk', target='core-image-minimal')
-
- sdk_file1 = TargetSDKFile.objects.create(target=target,
- file_size=100000,
- file_name='/home/foo/core-image-minimal.toolchain.sh')
-
- sdk_file2 = TargetSDKFile.objects.create(target=target,
- file_size=120000,
- file_name='/home/foo/x86_64.toolchain.sh')
-
- self._get_build_dashboard(build)
-
- # check build artifacts heading
- msg = 'Build artifacts heading should be displayed for SDK ' \
- 'builds which generate artifacts'
- self.assertTrue(self._has_build_artifacts_heading(), msg)
-
- # check "Images" option in left-hand menu (should not be there)
- msg = 'Images option should not be shown in left-hand menu for ' \
- 'builds which didn\'t generate an image file'
- self.assertFalse(self._has_images_menu_option(), msg)
-
- # check links to SDK artifacts
- sdk_artifact_links = self.find_all('[data-links="sdk-artifacts"] li')
- self.assertEqual(len(sdk_artifact_links), 2,
- 'should be links to 2 SDK artifacts')
-
- # package count and size should not be visible, no link on
- # target name
- selector = '[data-value="target-package-count"]'
- self.assertFalse(self.element_exists(selector),
- 'package count should not be shown for non-image builds')
-
- selector = '[data-value="target-package-size"]'
- self.assertFalse(self.element_exists(selector),
- 'package size should not be shown for non-image builds')
-
- selector = '[data-link="target-packages"]'
- self.assertFalse(self.element_exists(selector),
- 'link to target packages should not be on target heading')
-
- def test_image_artifacts(self):
- """
- If a build produced image files, kernel artifacts, and manifests,
- they should all be shown, as well as the image link in the left-hand
- menu.
-
- The packages count and size should be shown, with a link to the
- package display page.
- """
- now = timezone.now()
- build = Build.objects.create(project=self.project,
- started_on=now, completed_on=timezone.now(),
- outcome=Build.SUCCEEDED)
-
- # add a variable to the build so that it counts as "started"
- Variable.objects.create(build=build,
- variable_name='Christopher',
- variable_value='Lee')
-
- target = Target.objects.create(is_image=True, build=build,
- task='', target='core-image-minimal',
- license_manifest_path='/home/foo/license.manifest',
- package_manifest_path='/home/foo/package.manifest')
-
- image_file = Target_Image_File.objects.create(target=target,
- file_name='/home/foo/core-image-minimal.ext4', file_size=9000)
-
- kernel_file1 = TargetKernelFile.objects.create(target=target,
- file_name='/home/foo/bzImage', file_size=2000)
-
- kernel_file2 = TargetKernelFile.objects.create(target=target,
- file_name='/home/foo/bzImage', file_size=2000)
-
- package = Package.objects.create(build=build, name='foo', size=1024,
- installed_name='foo1')
- installed_package = Target_Installed_Package.objects.create(
- target=target, package=package)
-
- self._get_build_dashboard(build)
-
- # check build artifacts heading
- msg = 'Build artifacts heading should be displayed for image ' \
- 'builds'
- self.assertTrue(self._has_build_artifacts_heading(), msg)
-
- # check "Images" option in left-hand menu (should be there)
- msg = 'Images option should be shown in left-hand menu for image builds'
- self.assertTrue(self._has_images_menu_option(), msg)
-
- # check link to image file
- selector = '[data-links="image-artifacts"] li'
- self.assertTrue(self.element_exists(selector),
- 'should be a link to the image file (selector %s)' % selector)
-
- # check links to kernel artifacts
- kernel_artifact_links = \
- self.find_all('[data-links="kernel-artifacts"] li')
- self.assertEqual(len(kernel_artifact_links), 2,
- 'should be links to 2 kernel artifacts')
-
- # check manifest links
- selector = 'a[data-link="license-manifest"]'
- self.assertTrue(self.element_exists(selector),
- 'should be a link to the license manifest (selector %s)' % selector)
-
- selector = 'a[data-link="package-manifest"]'
- self.assertTrue(self.element_exists(selector),
- 'should be a link to the package manifest (selector %s)' % selector)
-
- # check package count and size, link on target name
- selector = '[data-value="target-package-count"]'
- element = self.find(selector)
- self.assertEquals(element.text, '1',
- 'package count should be shown for image builds')
-
- selector = '[data-value="target-package-size"]'
- element = self.find(selector)
- self.assertEquals(element.text, '1.0 KB',
- 'package size should be shown for image builds')
-
- selector = '[data-link="target-packages"]'
- self.assertTrue(self.element_exists(selector),
- 'link to target packages should be on target heading')
diff --git a/lib/tests/browser/test_builddashboard_page_recipes.py b/lib/tests/browser/test_builddashboard_page_recipes.py
deleted file mode 100644
index ed18324e..00000000
--- a/lib/tests/browser/test_builddashboard_page_recipes.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-from django.core.urlresolvers import reverse
-from django.utils import timezone
-from tests.browser.selenium_helpers import SeleniumTestCase
-from orm.models import Project, Build, Recipe, Task, Layer, Layer_Version
-from orm.models import Target
-
-class TestBuilddashboardPageRecipes(SeleniumTestCase):
- """ Test build dashboard recipes sub-page """
-
- def setUp(self):
- project = Project.objects.get_or_create_default_project()
-
- now = timezone.now()
-
- self.build = Build.objects.create(project=project,
- started_on=now,
- completed_on=now)
-
- layer = Layer.objects.create()
-
- layer_version = Layer_Version.objects.create(layer=layer,
- build=self.build)
-
- recipe = Recipe.objects.create(layer_version=layer_version)
-
- task = Task.objects.create(build=self.build, recipe=recipe, order=1)
-
- Target.objects.create(build=self.build, task=task, target='do_build')
-
- def test_build_recipes_columns(self):
- """
- Check that non-hideable columns of the table on the recipes sub-page
- are disabled on the edit columns dropdown.
- """
- url = reverse('recipes', args=(self.build.id,))
- self.get(url)
-
- self.wait_until_visible('#edit-columns-button')
-
- # check that options for the non-hideable columns are disabled
- non_hideable = ['name', 'version']
-
- for column in non_hideable:
- selector = 'input#checkbox-%s[disabled="disabled"]' % column
- self.wait_until_present(selector)
diff --git a/lib/tests/browser/test_builddashboard_page_tasks.py b/lib/tests/browser/test_builddashboard_page_tasks.py
deleted file mode 100644
index da50f160..00000000
--- a/lib/tests/browser/test_builddashboard_page_tasks.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-from django.core.urlresolvers import reverse
-from django.utils import timezone
-from tests.browser.selenium_helpers import SeleniumTestCase
-from orm.models import Project, Build, Recipe, Task, Layer, Layer_Version
-from orm.models import Target
-
-class TestBuilddashboardPageTasks(SeleniumTestCase):
- """ Test build dashboard tasks sub-page """
-
- def setUp(self):
- project = Project.objects.get_or_create_default_project()
-
- now = timezone.now()
-
- self.build = Build.objects.create(project=project,
- started_on=now,
- completed_on=now)
-
- layer = Layer.objects.create()
-
- layer_version = Layer_Version.objects.create(layer=layer)
-
- recipe = Recipe.objects.create(layer_version=layer_version)
-
- task = Task.objects.create(build=self.build, recipe=recipe, order=1)
-
- Target.objects.create(build=self.build, task=task, target='do_build')
-
- def test_build_tasks_columns(self):
- """
- Check that non-hideable columns of the table on the tasks sub-page
- are disabled on the edit columns dropdown.
- """
- url = reverse('tasks', args=(self.build.id,))
- self.get(url)
-
- self.wait_until_visible('#edit-columns-button')
-
- # check that options for the non-hideable columns are disabled
- non_hideable = ['order', 'task_name', 'recipe__name']
-
- for column in non_hideable:
- selector = 'input#checkbox-%s[disabled="disabled"]' % column
- self.wait_until_present(selector)
diff --git a/lib/tests/browser/test_js_unit_tests.py b/lib/tests/browser/test_js_unit_tests.py
deleted file mode 100644
index 3c0b9625..00000000
--- a/lib/tests/browser/test_js_unit_tests.py
+++ /dev/null
@@ -1,57 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-"""
-Run the js unit tests
-"""
-
-from django.core.urlresolvers import reverse
-from tests.browser.selenium_helpers import SeleniumTestCase
-import logging
-
-logger = logging.getLogger("toaster")
-
-
-class TestJsUnitTests(SeleniumTestCase):
- """ Test landing page shows the Toaster brand """
-
- fixtures = ['toastergui-unittest-data']
-
- def test_that_js_unit_tests_pass(self):
- url = reverse('js-unit-tests')
- self.get(url)
- self.wait_until_present('#qunit-testresult .failed')
-
- failed = self.find("#qunit-testresult .failed").text
- passed = self.find("#qunit-testresult .passed").text
- total = self.find("#qunit-testresult .total").text
-
- logger.info("Js unit tests completed %s out of %s passed, %s failed",
- passed,
- total,
- failed)
-
- failed_tests = self.find_all("li .fail .test-message")
- for fail in failed_tests:
- logger.error("JS unit test failed: %s" % fail.text)
-
- self.assertEqual(failed, '0',
- "%s JS unit tests failed" % failed)
diff --git a/lib/tests/browser/test_landing_page.py b/lib/tests/browser/test_landing_page.py
deleted file mode 100644
index 4d4cd660..00000000
--- a/lib/tests/browser/test_landing_page.py
+++ /dev/null
@@ -1,108 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-from django.core.urlresolvers import reverse
-from django.utils import timezone
-from tests.browser.selenium_helpers import SeleniumTestCase
-
-from orm.models import Project, Build
-
-class TestLandingPage(SeleniumTestCase):
- """ Tests for redirects on the landing page """
-
- PROJECT_NAME = 'test project'
- LANDING_PAGE_TITLE = 'This is Toaster'
- CLI_BUILDS_PROJECT_NAME = 'command line builds'
-
- def setUp(self):
- """ Add default project manually """
- self.project = Project.objects.create_project(
- self.CLI_BUILDS_PROJECT_NAME,
- None
- )
- self.project.is_default = True
- self.project.save()
-
- def test_only_default_project(self):
- """
- No projects except default
- => should see the landing page
- """
- self.get(reverse('landing'))
- self.assertTrue(self.LANDING_PAGE_TITLE in self.get_page_source())
-
- def test_default_project_has_build(self):
- """
- Default project has a build, no other projects
- => should see the builds page
- """
- now = timezone.now()
- build = Build.objects.create(project=self.project,
- started_on=now,
- completed_on=now)
- build.save()
-
- self.get(reverse('landing'))
-
- elements = self.find_all('#allbuildstable')
- self.assertEqual(len(elements), 1, 'should redirect to builds')
- content = self.get_page_source()
- self.assertFalse(self.PROJECT_NAME in content,
- 'should not show builds for project %s' % self.PROJECT_NAME)
- self.assertTrue(self.CLI_BUILDS_PROJECT_NAME in content,
- 'should show builds for cli project')
-
- def test_user_project_exists(self):
- """
- User has added a project (without builds)
- => should see the projects page
- """
- user_project = Project.objects.create_project('foo', None)
- user_project.save()
-
- self.get(reverse('landing'))
-
- elements = self.find_all('#projectstable')
- self.assertEqual(len(elements), 1, 'should redirect to projects')
-
- def test_user_project_has_build(self):
- """
- User has added a project (with builds), command line builds doesn't
- => should see the builds page
- """
- user_project = Project.objects.create_project(self.PROJECT_NAME, None)
- user_project.save()
-
- now = timezone.now()
- build = Build.objects.create(project=user_project,
- started_on=now,
- completed_on=now)
- build.save()
-
- self.get(reverse('landing'))
-
- elements = self.find_all('#allbuildstable')
- self.assertEqual(len(elements), 1, 'should redirect to builds')
- content = self.get_page_source()
- self.assertTrue(self.PROJECT_NAME in content,
- 'should show builds for project %s' % self.PROJECT_NAME)
- self.assertFalse(self.CLI_BUILDS_PROJECT_NAME in content,
- 'should not show builds for cli project')
diff --git a/lib/tests/browser/test_layerdetails_page.py b/lib/tests/browser/test_layerdetails_page.py
deleted file mode 100644
index f24fb093..00000000
--- a/lib/tests/browser/test_layerdetails_page.py
+++ /dev/null
@@ -1,216 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-from django.core.urlresolvers import reverse
-from tests.browser.selenium_helpers import SeleniumTestCase
-
-from orm.models import Layer, Layer_Version, Project, LayerSource, Release
-from orm.models import BitbakeVersion
-
-from selenium.webdriver.support import expected_conditions as EC
-from selenium.webdriver.support.ui import WebDriverWait
-from selenium.webdriver.common.by import By
-
-
-class TestLayerDetailsPage(SeleniumTestCase):
- """ Test layerdetails page works correctly """
-
- def __init__(self, *args, **kwargs):
- super(TestLayerDetailsPage, self).__init__(*args, **kwargs)
-
- self.initial_values = None
- self.url = None
- self.imported_layer_version = None
-
- def setUp(self):
- release = Release.objects.create(
- name='baz',
- bitbake_version=BitbakeVersion.objects.create(name='v1')
- )
-
- # project to add new custom images to
- self.project = Project.objects.create(name='foo', release=release)
-
- name = "meta-imported"
- vcs_url = "git://example.com/meta-imported"
- subdir = "/layer"
- gitrev = "d33d"
- summary = "A imported layer"
- description = "This was imported"
-
- imported_layer = Layer.objects.create(name=name,
- vcs_url=vcs_url,
- summary=summary,
- description=description)
-
- self.imported_layer_version = Layer_Version.objects.create(
- layer=imported_layer,
- layer_source=LayerSource.TYPE_IMPORTED,
- branch=gitrev,
- commit=gitrev,
- dirpath=subdir,
- project=self.project)
-
- self.initial_values = [name, vcs_url, subdir, gitrev, summary,
- description]
- self.url = reverse('layerdetails',
- args=(self.project.pk,
- self.imported_layer_version.pk))
-
- def test_edit_layerdetails(self):
- """ Edit all the editable fields for the layer refresh the page and
- check that the new values exist"""
-
- self.get(self.url)
-
- self.click("#add-remove-layer-btn")
- self.click("#edit-layer-source")
- self.click("#repo")
-
- self.wait_until_visible("#layer-git-repo-url")
-
- # Open every edit box
- for btn in self.find_all("dd .glyphicon-edit"):
- btn.click()
-
- # Wait for the inputs to become visible after animation
- self.wait_until_visible("#layer-git input[type=text]")
- self.wait_until_visible("dd textarea")
- self.wait_until_visible("dd .change-btn")
-
- # Edit each value
- for inputs in self.find_all("#layer-git input[type=text]") + \
- self.find_all("dd textarea"):
- # ignore the tt inputs (twitter typeahead input)
- if "tt-" in inputs.get_attribute("class"):
- continue
-
- value = inputs.get_attribute("value")
-
- self.assertTrue(value in self.initial_values,
- "Expecting any of \"%s\"but got \"%s\"" %
- (self.initial_values, value))
-
- inputs.send_keys("-edited")
-
- # Save the new values
- for save_btn in self.find_all(".change-btn"):
- save_btn.click()
-
- self.click("#save-changes-for-switch")
- self.wait_until_visible("#edit-layer-source")
-
- # Refresh the page to see if the new values are returned
- self.get(self.url)
-
- new_values = ["%s-edited" % old_val
- for old_val in self.initial_values]
-
- for inputs in self.find_all('#layer-git input[type="text"]') + \
- self.find_all('dd textarea'):
- # ignore the tt inputs (twitter typeahead input)
- if "tt-" in inputs.get_attribute("class"):
- continue
-
- value = inputs.get_attribute("value")
-
- self.assertTrue(value in new_values,
- "Expecting any of \"%s\" but got \"%s\"" %
- (new_values, value))
-
- # Now convert it to a local layer
- self.click("#edit-layer-source")
- self.click("#dir")
- dir_input = self.wait_until_visible("#layer-dir-path-in-details")
-
- new_dir = "/home/test/my-meta-dir"
- dir_input.send_keys(new_dir)
-
- self.click("#save-changes-for-switch")
- self.wait_until_visible("#edit-layer-source")
-
- # Refresh the page to see if the new values are returned
- self.get(self.url)
- dir_input = self.find("#layer-dir-path-in-details")
- self.assertTrue(new_dir in dir_input.get_attribute("value"),
- "Expected %s in the dir value for layer directory" %
- new_dir)
-
- def test_delete_layer(self):
- """ Delete the layer """
-
- self.get(self.url)
-
- # Wait for the tables to load to avoid a race condition where the
- # toaster tables have made an async request. If the layer is deleted
- # before the request finishes it will cause an exception and fail this
- # test.
- wait = WebDriverWait(self.driver, 30)
-
- wait.until(EC.text_to_be_present_in_element(
- (By.CLASS_NAME,
- "table-count-recipestable"), "0"))
-
- wait.until(EC.text_to_be_present_in_element(
- (By.CLASS_NAME,
- "table-count-machinestable"), "0"))
-
- self.click('a[data-target="#delete-layer-modal"]')
- self.wait_until_visible("#delete-layer-modal")
- self.click("#layer-delete-confirmed")
-
- notification = self.wait_until_visible("#change-notification-msg")
- expected_text = "You have deleted 1 layer from your project: %s" % \
- self.imported_layer_version.layer.name
-
- self.assertTrue(expected_text in notification.text,
- "Expected notification text \"%s\" not found instead"
- "it was \"%s\"" %
- (expected_text, notification.text))
-
- def test_addrm_to_project(self):
- self.get(self.url)
-
- # Add the layer
- self.click("#add-remove-layer-btn")
-
- notification = self.wait_until_visible("#change-notification-msg")
-
- expected_text = "You have added 1 layer to your project: %s" % \
- self.imported_layer_version.layer.name
-
- self.assertTrue(expected_text in notification.text,
- "Expected notification text %s not found was "
- " \"%s\" instead" %
- (expected_text, notification.text))
-
- # Remove the layer
- self.click("#add-remove-layer-btn")
-
- notification = self.wait_until_visible("#change-notification-msg")
-
- expected_text = "You have removed 1 layer from your project: %s" % \
- self.imported_layer_version.layer.name
-
- self.assertTrue(expected_text in notification.text,
- "Expected notification text %s not found was "
- " \"%s\" instead" %
- (expected_text, notification.text))
diff --git a/lib/tests/browser/test_most_recent_builds_states.py b/lib/tests/browser/test_most_recent_builds_states.py
deleted file mode 100644
index abc0b0bc..00000000
--- a/lib/tests/browser/test_most_recent_builds_states.py
+++ /dev/null
@@ -1,211 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-from django.core.urlresolvers import reverse
-from django.utils import timezone
-from tests.browser.selenium_helpers import SeleniumTestCase
-from tests.browser.selenium_helpers_base import Wait
-from orm.models import Project, Build, Task, Recipe, Layer, Layer_Version
-from bldcontrol.models import BuildRequest
-
-class TestMostRecentBuildsStates(SeleniumTestCase):
- """ Test states update correctly in most recent builds area """
-
- def _create_build_request(self):
- project = Project.objects.get_or_create_default_project()
-
- now = timezone.now()
-
- build = Build.objects.create(project=project, build_name='fakebuild',
- started_on=now, completed_on=now)
-
- return BuildRequest.objects.create(build=build, project=project,
- state=BuildRequest.REQ_QUEUED)
-
- def _create_recipe(self):
- """ Add a recipe to the database and return it """
- layer = Layer.objects.create()
- layer_version = Layer_Version.objects.create(layer=layer)
- return Recipe.objects.create(name='foo', layer_version=layer_version)
-
- def _check_build_states(self, build_request):
- recipes_to_parse = 10
- url = reverse('all-builds')
- self.get(url)
-
- build = build_request.build
- base_selector = '[data-latest-build-result="%s"] ' % build.id
-
- # build queued; check shown as queued
- selector = base_selector + '[data-build-state="Queued"]'
- element = self.wait_until_visible(selector)
- self.assertRegexpMatches(element.get_attribute('innerHTML'),
- 'Build queued', 'build should show queued status')
-
- # waiting for recipes to be parsed
- build.outcome = Build.IN_PROGRESS
- build.recipes_to_parse = recipes_to_parse
- build.recipes_parsed = 0
-
- build_request.state = BuildRequest.REQ_INPROGRESS
- build_request.save()
-
- self.get(url)
-
- selector = base_selector + '[data-build-state="Parsing"]'
- element = self.wait_until_visible(selector)
-
- bar_selector = '#recipes-parsed-percentage-bar-%s' % build.id
- bar_element = element.find_element_by_css_selector(bar_selector)
- self.assertEqual(bar_element.value_of_css_property('width'), '0px',
- 'recipe parse progress should be at 0')
-
- # recipes being parsed; check parse progress
- build.recipes_parsed = 5
- build.save()
-
- self.get(url)
-
- element = self.wait_until_visible(selector)
- bar_element = element.find_element_by_css_selector(bar_selector)
- recipe_bar_updated = lambda driver: \
- bar_element.get_attribute('style') == 'width: 50%;'
- msg = 'recipe parse progress bar should update to 50%'
- element = Wait(self.driver).until(recipe_bar_updated, msg)
-
- # all recipes parsed, task started, waiting for first task to finish;
- # check status is shown as "Tasks starting..."
- build.recipes_parsed = recipes_to_parse
- build.save()
-
- recipe = self._create_recipe()
- task1 = Task.objects.create(build=build, recipe=recipe,
- task_name='Lionel')
- task2 = Task.objects.create(build=build, recipe=recipe,
- task_name='Jeffries')
-
- self.get(url)
-
- selector = base_selector + '[data-build-state="Starting"]'
- element = self.wait_until_visible(selector)
- self.assertRegexpMatches(element.get_attribute('innerHTML'),
- 'Tasks starting', 'build should show "tasks starting" status')
-
- # first task finished; check tasks progress bar
- task1.order = 1
- task1.save()
-
- self.get(url)
-
- selector = base_selector + '[data-build-state="In Progress"]'
- element = self.wait_until_visible(selector)
-
- bar_selector = '#build-pc-done-bar-%s' % build.id
- bar_element = element.find_element_by_css_selector(bar_selector)
-
- task_bar_updated = lambda driver: \
- bar_element.get_attribute('style') == 'width: 50%;'
- msg = 'tasks progress bar should update to 50%'
- element = Wait(self.driver).until(task_bar_updated, msg)
-
- # last task finished; check tasks progress bar updates
- task2.order = 2
- task2.save()
-
- self.get(url)
-
- element = self.wait_until_visible(selector)
- bar_element = element.find_element_by_css_selector(bar_selector)
- task_bar_updated = lambda driver: \
- bar_element.get_attribute('style') == 'width: 100%;'
- msg = 'tasks progress bar should update to 100%'
- element = Wait(self.driver).until(task_bar_updated, msg)
-
- def test_states_to_success(self):
- """
- Test state transitions in the recent builds area for a build which
- completes successfully.
- """
- build_request = self._create_build_request()
-
- self._check_build_states(build_request)
-
- # all tasks complete and build succeeded; check success state shown
- build = build_request.build
- build.outcome = Build.SUCCEEDED
- build.save()
-
- selector = '[data-latest-build-result="%s"] ' \
- '[data-build-state="Succeeded"]' % build.id
- element = self.wait_until_visible(selector)
-
- def test_states_to_failure(self):
- """
- Test state transitions in the recent builds area for a build which
- completes in a failure.
- """
- build_request = self._create_build_request()
-
- self._check_build_states(build_request)
-
- # all tasks complete and build succeeded; check fail state shown
- build = build_request.build
- build.outcome = Build.FAILED
- build.save()
-
- selector = '[data-latest-build-result="%s"] ' \
- '[data-build-state="Failed"]' % build.id
- element = self.wait_until_visible(selector)
-
- def test_states_cancelling(self):
- """
- Test that most recent build area updates correctly for a build
- which is cancelled.
- """
- url = reverse('all-builds')
-
- build_request = self._create_build_request()
- build = build_request.build
-
- # cancel the build
- build_request.state = BuildRequest.REQ_CANCELLING
- build_request.save()
-
- self.get(url)
-
- # check cancelling state
- selector = '[data-latest-build-result="%s"] ' \
- '[data-build-state="Cancelling"]' % build.id
- element = self.wait_until_visible(selector)
- self.assertRegexpMatches(element.get_attribute('innerHTML'),
- 'Cancelling the build', 'build should show "cancelling" status')
-
- # check cancelled state
- build.outcome = Build.CANCELLED
- build.save()
-
- self.get(url)
-
- selector = '[data-latest-build-result="%s"] ' \
- '[data-build-state="Cancelled"]' % build.id
- element = self.wait_until_visible(selector)
- self.assertRegexpMatches(element.get_attribute('innerHTML'),
- 'Build cancelled', 'build should show "cancelled" status')
diff --git a/lib/tests/browser/test_new_custom_image_page.py b/lib/tests/browser/test_new_custom_image_page.py
deleted file mode 100644
index ab5a8e66..00000000
--- a/lib/tests/browser/test_new_custom_image_page.py
+++ /dev/null
@@ -1,161 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-from django.core.urlresolvers import reverse
-from tests.browser.selenium_helpers import SeleniumTestCase
-
-from orm.models import BitbakeVersion, Release, Project, ProjectLayer, Layer
-from orm.models import Layer_Version, Recipe, CustomImageRecipe
-
-
-class TestNewCustomImagePage(SeleniumTestCase):
- CUSTOM_IMAGE_NAME = 'roopa-doopa'
-
- def setUp(self):
- release = Release.objects.create(
- name='baz',
- bitbake_version=BitbakeVersion.objects.create(name='v1')
- )
-
- # project to add new custom images to
- self.project = Project.objects.create(name='foo', release=release)
-
- # layer associated with the project
- layer = Layer.objects.create(name='bar')
- layer_version = Layer_Version.objects.create(
- layer=layer,
- project=self.project
- )
-
- # properly add the layer to the project
- ProjectLayer.objects.create(
- project=self.project,
- layercommit=layer_version,
- optional=False
- )
-
- # add a fake image recipe to the layer that can be customised
- self.recipe = Recipe.objects.create(
- name='core-image-minimal',
- layer_version=layer_version,
- is_image=True
- )
-
- # another project with a custom image already in it
- project2 = Project.objects.create(name='whoop', release=release)
- layer_version2 = Layer_Version.objects.create(
- layer=layer,
- project=project2
- )
- ProjectLayer.objects.create(
- project=project2,
- layercommit=layer_version2,
- optional=False
- )
- recipe2 = Recipe.objects.create(
- name='core-image-minimal',
- layer_version=layer_version2,
- is_image=True
- )
- CustomImageRecipe.objects.create(
- name=self.CUSTOM_IMAGE_NAME,
- base_recipe=recipe2,
- layer_version=layer_version2,
- file_path='/1/2',
- project=project2
- )
-
- def _create_custom_image(self, new_custom_image_name):
- """
- 1. Go to the 'new custom image' page
- 2. Click the button for the fake core-image-minimal
- 3. Wait for the dialog box for setting the name of the new custom
- image
- 4. Insert new_custom_image_name into that dialog's text box
- """
- url = reverse('newcustomimage', args=(self.project.id,))
- self.get(url)
-
- self.click('button[data-recipe="%s"]' % self.recipe.id)
-
- selector = '#new-custom-image-modal input[type="text"]'
- self.enter_text(selector, new_custom_image_name)
-
- self.click('#create-new-custom-image-btn')
-
- def _check_for_custom_image(self, image_name):
- """
- Fetch the list of custom images for the project and check the
- image with name image_name is listed there
- """
- url = reverse('projectcustomimages', args=(self.project.id,))
- self.get(url)
-
- self.wait_until_visible('#customimagestable')
-
- element = self.find('#customimagestable td[class="name"] a')
- msg = 'should be a custom image link with text %s' % image_name
- self.assertEqual(element.text.strip(), image_name, msg)
-
- def test_new_image(self):
- """
- Should be able to create a new custom image
- """
- custom_image_name = 'boo-image'
- self._create_custom_image(custom_image_name)
- self.wait_until_visible('#image-created-notification')
- self._check_for_custom_image(custom_image_name)
-
- def test_new_duplicates_other_project_image(self):
- """
- Should be able to create a new custom image if its name is the same
- as a custom image in another project
- """
- self._create_custom_image(self.CUSTOM_IMAGE_NAME)
- self.wait_until_visible('#image-created-notification')
- self._check_for_custom_image(self.CUSTOM_IMAGE_NAME)
-
- def test_new_duplicates_non_image_recipe(self):
- """
- Should not be able to create a new custom image whose name is the
- same as an existing non-image recipe
- """
- self._create_custom_image(self.recipe.name)
- element = self.wait_until_visible('#invalid-name-help')
- self.assertRegexpMatches(element.text.strip(),
- 'image with this name already exists')
-
- def test_new_duplicates_project_image(self):
- """
- Should not be able to create a new custom image whose name is the same
- as a custom image in this project
- """
- # create the image
- custom_image_name = 'doh-image'
- self._create_custom_image(custom_image_name)
- self.wait_until_visible('#image-created-notification')
- self._check_for_custom_image(custom_image_name)
-
- # try to create an image with the same name
- self._create_custom_image(custom_image_name)
- element = self.wait_until_visible('#invalid-name-help')
- expected = 'An image with this name already exists in this project'
- self.assertRegexpMatches(element.text.strip(), expected)
diff --git a/lib/tests/browser/test_new_project_page.py b/lib/tests/browser/test_new_project_page.py
deleted file mode 100644
index 77e5f152..00000000
--- a/lib/tests/browser/test_new_project_page.py
+++ /dev/null
@@ -1,113 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-from django.core.urlresolvers import reverse
-from tests.browser.selenium_helpers import SeleniumTestCase
-from selenium.webdriver.support.ui import Select
-from selenium.common.exceptions import InvalidElementStateException
-
-from orm.models import Project, Release, BitbakeVersion
-
-
-class TestNewProjectPage(SeleniumTestCase):
- """ Test project data at /project/X/ is displayed correctly """
-
- def setUp(self):
- bitbake, c = BitbakeVersion.objects.get_or_create(
- name="master",
- giturl="git://master",
- branch="master",
- dirpath="master")
-
- release, c = Release.objects.get_or_create(name="msater",
- description="master"
- "release",
- branch_name="master",
- helptext="latest",
- bitbake_version=bitbake)
-
- self.release, c = Release.objects.get_or_create(
- name="msater2",
- description="master2"
- "release2",
- branch_name="master2",
- helptext="latest2",
- bitbake_version=bitbake)
-
- def test_create_new_project(self):
- """ Test creating a project """
-
- project_name = "masterproject"
-
- url = reverse('newproject')
- self.get(url)
-
- self.enter_text('#new-project-name', project_name)
-
- select = Select(self.find('#projectversion'))
- select.select_by_value(str(self.release.pk))
-
- self.click("#create-project-button")
-
- # We should get redirected to the new project's page with the
- # notification at the top
- element = self.wait_until_visible('#project-created-notification')
-
- self.assertTrue(project_name in element.text,
- "New project name not in new project notification")
-
- self.assertTrue(Project.objects.filter(name=project_name).count(),
- "New project not found in database")
-
- def test_new_duplicates_project_name(self):
- """
- Should not be able to create a new project whose name is the same
- as an existing project
- """
-
- project_name = "dupproject"
-
- Project.objects.create_project(name=project_name,
- release=self.release)
-
- url = reverse('newproject')
- self.get(url)
-
- self.enter_text('#new-project-name', project_name)
-
- select = Select(self.find('#projectversion'))
- select.select_by_value(str(self.release.pk))
-
- element = self.wait_until_visible('#hint-error-project-name')
-
- self.assertTrue(("Project names must be unique" in element.text),
- "Did not find unique project name error message")
-
- # Try and click it anyway, if it submits we'll have a new project in
- # the db and assert then
- try:
- self.click("#create-project-button")
- except InvalidElementStateException:
- pass
-
- self.assertTrue(
- (Project.objects.filter(name=project_name).count() == 1),
- "New project not found in database")
diff --git a/lib/tests/browser/test_project_builds_page.py b/lib/tests/browser/test_project_builds_page.py
deleted file mode 100644
index 9fe91ab0..00000000
--- a/lib/tests/browser/test_project_builds_page.py
+++ /dev/null
@@ -1,168 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import re
-
-from django.core.urlresolvers import reverse
-from django.utils import timezone
-from tests.browser.selenium_helpers import SeleniumTestCase
-
-from orm.models import BitbakeVersion, Release, Project, Build, Target
-
-class TestProjectBuildsPage(SeleniumTestCase):
- """ Test data at /project/X/builds is displayed correctly """
-
- PROJECT_NAME = 'test project'
- CLI_BUILDS_PROJECT_NAME = 'command line builds'
-
- def setUp(self):
- bbv = BitbakeVersion.objects.create(name='bbv1', giturl='/tmp/',
- branch='master', dirpath='')
- release = Release.objects.create(name='release1',
- bitbake_version=bbv)
- self.project1 = Project.objects.create_project(name=self.PROJECT_NAME,
- release=release)
- self.project1.save()
-
- self.project2 = Project.objects.create_project(name=self.PROJECT_NAME,
- release=release)
- self.project2.save()
-
- self.default_project = Project.objects.create_project(
- name=self.CLI_BUILDS_PROJECT_NAME,
- release=release
- )
- self.default_project.is_default = True
- self.default_project.save()
-
- # parameters for builds to associate with the projects
- now = timezone.now()
-
- self.project1_build_success = {
- 'project': self.project1,
- 'started_on': now,
- 'completed_on': now,
- 'outcome': Build.SUCCEEDED
- }
-
- self.project1_build_in_progress = {
- 'project': self.project1,
- 'started_on': now,
- 'completed_on': now,
- 'outcome': Build.IN_PROGRESS
- }
-
- self.project2_build_success = {
- 'project': self.project2,
- 'started_on': now,
- 'completed_on': now,
- 'outcome': Build.SUCCEEDED
- }
-
- self.project2_build_in_progress = {
- 'project': self.project2,
- 'started_on': now,
- 'completed_on': now,
- 'outcome': Build.IN_PROGRESS
- }
-
- def _get_rows_for_project(self, project_id):
- """
- Helper to retrieve HTML rows for a project's builds,
- as shown in the main table of the page
- """
- url = reverse('projectbuilds', args=(project_id,))
- self.get(url)
- self.wait_until_present('#projectbuildstable tbody tr')
- return self.find_all('#projectbuildstable tbody tr')
-
- def test_show_builds_for_project(self):
- """ Builds for a project should be displayed in the main table """
- Build.objects.create(**self.project1_build_success)
- Build.objects.create(**self.project1_build_success)
- build_rows = self._get_rows_for_project(self.project1.id)
- self.assertEqual(len(build_rows), 2)
-
- def test_show_builds_project_only(self):
- """ Builds for other projects should be excluded """
- Build.objects.create(**self.project1_build_success)
- Build.objects.create(**self.project1_build_success)
- Build.objects.create(**self.project1_build_success)
-
- # shouldn't see these two
- Build.objects.create(**self.project2_build_success)
- Build.objects.create(**self.project2_build_in_progress)
-
- build_rows = self._get_rows_for_project(self.project1.id)
- self.assertEqual(len(build_rows), 3)
-
- def test_builds_exclude_in_progress(self):
- """ "in progress" builds should not be shown in main table """
- Build.objects.create(**self.project1_build_success)
- Build.objects.create(**self.project1_build_success)
-
- # shouldn't see this one
- Build.objects.create(**self.project1_build_in_progress)
-
- # shouldn't see these two either, as they belong to a different project
- Build.objects.create(**self.project2_build_success)
- Build.objects.create(**self.project2_build_in_progress)
-
- build_rows = self._get_rows_for_project(self.project1.id)
- self.assertEqual(len(build_rows), 2)
-
- def test_show_tasks_with_suffix(self):
- """ Task should be shown as suffixes on build names """
- build = Build.objects.create(**self.project1_build_success)
- target = 'bash'
- task = 'clean'
- Target.objects.create(build=build, target=target, task=task)
-
- url = reverse('projectbuilds', args=(self.project1.id,))
- self.get(url)
- self.wait_until_present('td[class="target"]')
-
- cell = self.find('td[class="target"]')
- content = cell.get_attribute('innerHTML')
- expected_text = '%s:%s' % (target, task)
-
- self.assertTrue(re.search(expected_text, content),
- '"target" cell should contain text %s' % expected_text)
-
- def test_cli_builds_hides_tabs(self):
- """
- Display for command line builds should hide tabs
- """
- url = reverse('projectbuilds', args=(self.default_project.id,))
- self.get(url)
- tabs = self.find_all('#project-topbar')
- self.assertEqual(len(tabs), 0,
- 'should be no top bar shown for command line builds')
-
- def test_non_cli_builds_has_tabs(self):
- """
- Non-command-line builds projects should show the tabs
- """
- url = reverse('projectbuilds', args=(self.project1.id,))
- self.get(url)
- tabs = self.find_all('#project-topbar')
- self.assertEqual(len(tabs), 1,
- 'should be a top bar shown for non-command-line builds')
diff --git a/lib/tests/browser/test_project_config_page.py b/lib/tests/browser/test_project_config_page.py
deleted file mode 100644
index 07100849..00000000
--- a/lib/tests/browser/test_project_config_page.py
+++ /dev/null
@@ -1,231 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import re
-
-from django.core.urlresolvers import reverse
-from django.utils import timezone
-from tests.browser.selenium_helpers import SeleniumTestCase
-
-from orm.models import BitbakeVersion, Release, Project, ProjectVariable
-
-class TestProjectConfigsPage(SeleniumTestCase):
- """ Test data at /project/X/builds is displayed correctly """
-
- PROJECT_NAME = 'test project'
- INVALID_PATH_START_TEXT = 'The directory path should either start with a /'
- INVALID_PATH_CHAR_TEXT = 'The directory path cannot include spaces or ' \
- 'any of these characters'
-
- def setUp(self):
- bbv = BitbakeVersion.objects.create(name='bbv1', giturl='/tmp/',
- branch='master', dirpath='')
- release = Release.objects.create(name='release1',
- bitbake_version=bbv)
- self.project1 = Project.objects.create_project(name=self.PROJECT_NAME,
- release=release)
- self.project1.save()
-
-
- def test_no_underscore_iamgefs_type(self):
- """
- Should not accept IMAGEFS_TYPE with an underscore
- """
-
- imagefs_type = "foo_bar"
-
- ProjectVariable.objects.get_or_create(project = self.project1, name = "IMAGE_FSTYPES", value = "abcd ")
- url = reverse('projectconf', args=(self.project1.id,));
- self.get(url);
-
- self.click('#change-image_fstypes-icon')
-
- self.enter_text('#new-imagefs_types', imagefs_type)
-
- element = self.wait_until_visible('#hintError-image-fs_type')
-
- self.assertTrue(("A valid image type cannot include underscores" in element.text),
- "Did not find underscore error message")
-
-
- def test_checkbox_verification(self):
- """
- Should automatically check the checkbox if user enters value
- text box, if value is there in the checkbox.
- """
- imagefs_type = "btrfs"
-
- ProjectVariable.objects.get_or_create(project = self.project1, name = "IMAGE_FSTYPES", value = "abcd ")
- url = reverse('projectconf', args=(self.project1.id,));
- self.get(url);
-
- self.click('#change-image_fstypes-icon')
-
- self.enter_text('#new-imagefs_types', imagefs_type)
-
- checkboxes = self.driver.find_elements_by_xpath("//input[@class='fs-checkbox-fstypes']")
-
- for checkbox in checkboxes:
- if checkbox.get_attribute("value") == "btrfs":
- self.assertEqual(checkbox.is_selected(), True)
-
-
- def test_textbox_with_checkbox_verification(self):
- """
- Should automatically add or remove value in textbox, if user checks
- or unchecks checkboxes.
- """
-
- ProjectVariable.objects.get_or_create(project = self.project1, name = "IMAGE_FSTYPES", value = "abcd ")
- url = reverse('projectconf', args=(self.project1.id,));
- self.get(url);
-
- self.click('#change-image_fstypes-icon')
-
- self.wait_until_visible('#new-imagefs_types')
-
- checkboxes_selector = '.fs-checkbox-fstypes'
-
- self.wait_until_visible(checkboxes_selector)
- checkboxes = self.find_all(checkboxes_selector)
-
- for checkbox in checkboxes:
- if checkbox.get_attribute("value") == "cpio":
- checkbox.click()
- element = self.driver.find_element_by_id('new-imagefs_types')
-
- self.wait_until_visible('#new-imagefs_types')
-
- self.assertTrue(("cpio" in element.get_attribute('value'),
- "Imagefs not added into the textbox"))
- checkbox.click()
- self.assertTrue(("cpio" not in element.text),
- "Image still present in the textbox")
-
- def test_set_download_dir(self):
- """
- Validate the allowed and disallowed types in the directory field for
- DL_DIR
- """
-
- ProjectVariable.objects.get_or_create(project=self.project1,
- name='DL_DIR')
- url = reverse('projectconf', args=(self.project1.id,))
- self.get(url)
-
- # activate the input to edit download dir
- self.click('#change-dl_dir-icon')
- self.wait_until_visible('#new-dl_dir')
-
- # downloads dir path doesn't start with / or ${...}
- self.enter_text('#new-dl_dir', 'home/foo')
- element = self.wait_until_visible('#hintError-initialChar-dl_dir')
-
- msg = 'downloads directory path starts with invalid character but ' \
- 'treated as valid'
- self.assertTrue((self.INVALID_PATH_START_TEXT in element.text), msg)
-
- # downloads dir path has a space
- self.driver.find_element_by_id('new-dl_dir').clear()
- self.enter_text('#new-dl_dir', '/foo/bar a')
-
- element = self.wait_until_visible('#hintError-dl_dir')
- msg = 'downloads directory path characters invalid but treated as valid'
- self.assertTrue((self.INVALID_PATH_CHAR_TEXT in element.text), msg)
-
- # downloads dir path starts with ${...} but has a space
- self.driver.find_element_by_id('new-dl_dir').clear()
- self.enter_text('#new-dl_dir', '${TOPDIR}/down foo')
-
- element = self.wait_until_visible('#hintError-dl_dir')
- msg = 'downloads directory path characters invalid but treated as valid'
- self.assertTrue((self.INVALID_PATH_CHAR_TEXT in element.text), msg)
-
- # downloads dir path starts with /
- self.driver.find_element_by_id('new-dl_dir').clear()
- self.enter_text('#new-dl_dir', '/bar/foo')
-
- hidden_element = self.driver.find_element_by_id('hintError-dl_dir')
- self.assertEqual(hidden_element.is_displayed(), False,
- 'downloads directory path valid but treated as invalid')
-
- # downloads dir path starts with ${...}
- self.driver.find_element_by_id('new-dl_dir').clear()
- self.enter_text('#new-dl_dir', '${TOPDIR}/down')
-
- hidden_element = self.driver.find_element_by_id('hintError-dl_dir')
- self.assertEqual(hidden_element.is_displayed(), False,
- 'downloads directory path valid but treated as invalid')
-
- def test_set_sstate_dir(self):
- """
- Validate the allowed and disallowed types in the directory field for
- SSTATE_DIR
- """
-
- ProjectVariable.objects.get_or_create(project=self.project1,
- name='SSTATE_DIR')
- url = reverse('projectconf', args=(self.project1.id,))
- self.get(url)
-
- self.click('#change-sstate_dir-icon')
-
- self.wait_until_visible('#new-sstate_dir')
-
- # path doesn't start with / or ${...}
- self.enter_text('#new-sstate_dir', 'home/foo')
- element = self.wait_until_visible('#hintError-initialChar-sstate_dir')
-
- msg = 'sstate directory path starts with invalid character but ' \
- 'treated as valid'
- self.assertTrue((self.INVALID_PATH_START_TEXT in element.text), msg)
-
- # path has a space
- self.driver.find_element_by_id('new-sstate_dir').clear()
- self.enter_text('#new-sstate_dir', '/foo/bar a')
-
- element = self.wait_until_visible('#hintError-sstate_dir')
- msg = 'sstate directory path characters invalid but treated as valid'
- self.assertTrue((self.INVALID_PATH_CHAR_TEXT in element.text), msg)
-
- # path starts with ${...} but has a space
- self.driver.find_element_by_id('new-sstate_dir').clear()
- self.enter_text('#new-sstate_dir', '${TOPDIR}/down foo')
-
- element = self.wait_until_visible('#hintError-sstate_dir')
- msg = 'sstate directory path characters invalid but treated as valid'
- self.assertTrue((self.INVALID_PATH_CHAR_TEXT in element.text), msg)
-
- # path starts with /
- self.driver.find_element_by_id('new-sstate_dir').clear()
- self.enter_text('#new-sstate_dir', '/bar/foo')
-
- hidden_element = self.driver.find_element_by_id('hintError-sstate_dir')
- self.assertEqual(hidden_element.is_displayed(), False,
- 'sstate directory path valid but treated as invalid')
-
- # paths starts with ${...}
- self.driver.find_element_by_id('new-sstate_dir').clear()
- self.enter_text('#new-sstate_dir', '${TOPDIR}/down')
-
- hidden_element = self.driver.find_element_by_id('hintError-sstate_dir')
- self.assertEqual(hidden_element.is_displayed(), False,
- 'sstate directory path valid but treated as invalid') \ No newline at end of file
diff --git a/lib/tests/browser/test_project_page.py b/lib/tests/browser/test_project_page.py
deleted file mode 100644
index 01864633..00000000
--- a/lib/tests/browser/test_project_page.py
+++ /dev/null
@@ -1,59 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-from django.core.urlresolvers import reverse
-from django.utils import timezone
-from tests.browser.selenium_helpers import SeleniumTestCase
-
-from orm.models import Build, Project
-
-class TestProjectPage(SeleniumTestCase):
- """ Test project data at /project/X/ is displayed correctly """
-
- CLI_BUILDS_PROJECT_NAME = 'Command line builds'
-
- def test_cli_builds_in_progress(self):
- """
- In progress builds should not cause an error to be thrown
- when navigating to "command line builds" project page;
- see https://bugzilla.yoctoproject.org/show_bug.cgi?id=8277
- """
-
- # add the "command line builds" default project; this mirrors what
- # we do with get_or_create_default_project()
- default_project = Project.objects.create_project(self.CLI_BUILDS_PROJECT_NAME, None)
- default_project.is_default = True
- default_project.save()
-
- # add an "in progress" build for the default project
- now = timezone.now()
- Build.objects.create(project=default_project,
- started_on=now,
- completed_on=now,
- outcome=Build.IN_PROGRESS)
-
- # navigate to the project page for the default project
- url = reverse("project", args=(default_project.id,))
- self.get(url)
-
- # check that we get a project page with the correct heading
- project_name = self.find('.project-name').text.strip()
- self.assertEqual(project_name, self.CLI_BUILDS_PROJECT_NAME)
diff --git a/lib/tests/browser/test_sample.py b/lib/tests/browser/test_sample.py
deleted file mode 100644
index 20ec53c2..00000000
--- a/lib/tests/browser/test_sample.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-"""
-A small example test demonstrating the basics of writing a test with
-Toaster's SeleniumTestCase; this just fetches the Toaster home page
-and checks it has the word "Toaster" in the brand link
-
-New test files should follow this structure, should be named "test_*.py",
-and should be in the same directory as this sample.
-"""
-
-from django.core.urlresolvers import reverse
-from tests.browser.selenium_helpers import SeleniumTestCase
-
-class TestSample(SeleniumTestCase):
- """ Test landing page shows the Toaster brand """
-
- def test_landing_page_has_brand(self):
- url = reverse('landing')
- self.get(url)
- brand_link = self.find('.toaster-navbar-brand a.brand')
- self.assertEqual(brand_link.text.strip(), 'Toaster')
diff --git a/lib/tests/browser/test_task_page.py b/lib/tests/browser/test_task_page.py
deleted file mode 100644
index 690d116c..00000000
--- a/lib/tests/browser/test_task_page.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-from django.core.urlresolvers import reverse
-from django.utils import timezone
-from tests.browser.selenium_helpers import SeleniumTestCase
-from orm.models import Project, Build, Layer, Layer_Version, Recipe, Target
-from orm.models import Task, Task_Dependency
-
-class TestTaskPage(SeleniumTestCase):
- """ Test page which shows an individual task """
- RECIPE_NAME = 'bar'
- RECIPE_VERSION = '0.1'
- TASK_NAME = 'do_da_doo_ron_ron'
-
- def setUp(self):
- now = timezone.now()
-
- project = Project.objects.get_or_create_default_project()
-
- self.build = Build.objects.create(project=project, started_on=now,
- completed_on=now)
-
- Target.objects.create(target='foo', build=self.build)
-
- layer = Layer.objects.create()
-
- layer_version = Layer_Version.objects.create(layer=layer)
-
- recipe = Recipe.objects.create(name=TestTaskPage.RECIPE_NAME,
- layer_version=layer_version, version=TestTaskPage.RECIPE_VERSION)
-
- self.task = Task.objects.create(build=self.build, recipe=recipe,
- order=1, outcome=Task.OUTCOME_COVERED, task_executed=False,
- task_name=TestTaskPage.TASK_NAME)
-
- def test_covered_task(self):
- """
- Check that covered tasks are displayed for tasks which have
- dependencies on themselves
- """
-
- # the infinite loop which of bug 9952 was down to tasks which
- # depend on themselves, so add self-dependent tasks to replicate the
- # situation which caused the infinite loop (now fixed)
- Task_Dependency.objects.create(task=self.task, depends_on=self.task)
-
- url = reverse('task', args=(self.build.id, self.task.id,))
- self.get(url)
-
- # check that we see the task name
- self.wait_until_visible('.page-header h1')
-
- heading = self.find('.page-header h1')
- expected_heading = '%s_%s %s' % (TestTaskPage.RECIPE_NAME,
- TestTaskPage.RECIPE_VERSION, TestTaskPage.TASK_NAME)
- self.assertEqual(heading.text, expected_heading,
- 'Heading should show recipe name, version and task')
diff --git a/lib/tests/browser/test_toastertable_ui.py b/lib/tests/browser/test_toastertable_ui.py
deleted file mode 100644
index 53ddf30c..00000000
--- a/lib/tests/browser/test_toastertable_ui.py
+++ /dev/null
@@ -1,160 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-from datetime import datetime
-
-from django.core.urlresolvers import reverse
-from django.utils import timezone
-from tests.browser.selenium_helpers import SeleniumTestCase
-from orm.models import BitbakeVersion, Release, Project, Build
-
-class TestToasterTableUI(SeleniumTestCase):
- """
- Tests for the UI elements of ToasterTable (sorting etc.);
- note that the tests cover generic functionality of ToasterTable which
- manifests as UI elements in the browser, and can only be tested via
- Selenium.
- """
-
- def setUp(self):
- pass
-
- def _get_orderby_heading(self, table):
- """
- Get the current order by finding the column heading in <table> with
- the sorted class on it.
-
- table: WebElement for a ToasterTable
- """
- selector = 'thead a.sorted'
- heading = table.find_element_by_css_selector(selector)
- return heading.get_attribute('innerHTML').strip()
-
- def _get_datetime_from_cell(self, row, selector):
- """
- Return the value in the cell selected by <selector> on <row> as a
- datetime.
-
- row: <tr> WebElement for a row in the ToasterTable
- selector: CSS selector to use to find the cell containing the date time
- string
- """
- cell = row.find_element_by_css_selector(selector)
- cell_text = cell.get_attribute('innerHTML').strip()
- return datetime.strptime(cell_text, '%d/%m/%y %H:%M')
-
- def test_revert_orderby(self):
- """
- Test that sort order for a table reverts to the default sort order
- if the current sort column is hidden.
- """
- now = timezone.now()
- later = now + timezone.timedelta(hours=1)
- even_later = later + timezone.timedelta(hours=1)
-
- bbv = BitbakeVersion.objects.create(name='test bbv', giturl='/tmp/',
- branch='master', dirpath='')
- release = Release.objects.create(name='test release',
- branch_name='master',
- bitbake_version=bbv)
-
- project = Project.objects.create_project('project', release)
-
- # set up two builds which will order differently when sorted by
- # started_on or completed_on
-
- # started first, finished last
- build1 = Build.objects.create(project=project,
- started_on=now,
- completed_on=even_later,
- outcome=Build.SUCCEEDED)
-
- # started second, finished first
- build2 = Build.objects.create(project=project,
- started_on=later,
- completed_on=later,
- outcome=Build.SUCCEEDED)
-
- url = reverse('all-builds')
- self.get(url)
- table = self.wait_until_visible('#allbuildstable')
-
- # check ordering (default is by -completed_on); so build1 should be
- # first as it finished last
- active_heading = self._get_orderby_heading(table)
- self.assertEqual(active_heading, 'Completed on',
- 'table should be sorted by "Completed on" by default')
-
- row_selector = '#allbuildstable tbody tr'
- cell_selector = 'td.completed_on'
-
- rows = self.find_all(row_selector)
- row1_completed_on = self._get_datetime_from_cell(rows[0], cell_selector)
- row2_completed_on = self._get_datetime_from_cell(rows[1], cell_selector)
- self.assertTrue(row1_completed_on > row2_completed_on,
- 'table should be sorted by -completed_on')
-
- # turn on started_on column
- self.click('#edit-columns-button')
- self.click('#checkbox-started_on')
-
- # sort by started_on column
- links = table.find_elements_by_css_selector('th.started_on a')
- for link in links:
- if link.get_attribute('innerHTML').strip() == 'Started on':
- link.click()
- break
-
- # wait for table data to reload in response to new sort
- self.wait_until_visible('#allbuildstable')
-
- # check ordering; build1 should be first
- active_heading = self._get_orderby_heading(table)
- self.assertEqual(active_heading, 'Started on',
- 'table should be sorted by "Started on"')
-
- cell_selector = 'td.started_on'
-
- rows = self.find_all(row_selector)
- row1_started_on = self._get_datetime_from_cell(rows[0], cell_selector)
- row2_started_on = self._get_datetime_from_cell(rows[1], cell_selector)
- self.assertTrue(row1_started_on < row2_started_on,
- 'table should be sorted by started_on')
-
- # turn off started_on column
- self.click('#edit-columns-button')
- self.click('#checkbox-started_on')
-
- # wait for table data to reload in response to new sort
- self.wait_until_visible('#allbuildstable')
-
- # check ordering (should revert to completed_on); build2 should be first
- active_heading = self._get_orderby_heading(table)
- self.assertEqual(active_heading, 'Completed on',
- 'table should be sorted by "Completed on" after hiding sort column')
-
- cell_selector = 'td.completed_on'
-
- rows = self.find_all(row_selector)
- row1_completed_on = self._get_datetime_from_cell(rows[0], cell_selector)
- row2_completed_on = self._get_datetime_from_cell(rows[1], cell_selector)
- self.assertTrue(row1_completed_on > row2_completed_on,
- 'table should be sorted by -completed_on')
diff --git a/lib/tests/builds/README b/lib/tests/builds/README
deleted file mode 100644
index 4a3b5328..00000000
--- a/lib/tests/builds/README
+++ /dev/null
@@ -1,14 +0,0 @@
-# Running build tests
-
-These tests are to test the running of builds and the data produced by the builds.
-Your oe build environment must be sourced/initialised for these tests to run.
-
-The simplest way to run the tests are the following commands:
-
-$ . oe-init-build-env
-$ cd bitbake/lib/toaster/ # path my vary but this is into toaster's directory
-$ DJANGO_SETTINGS_MODULE='toastermain.settings_test' ./manage.py test tests.builds
-
-Optional environment variables:
- - TOASTER_DIR (where toaster keeps it's artifacts)
- - TOASTER_CONF a path to the toasterconf.json file. This will need to be set if you don't execute the tests from toaster's own directory.
diff --git a/lib/tests/builds/__init__.py b/lib/tests/builds/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/lib/tests/builds/__init__.py
+++ /dev/null
diff --git a/lib/tests/builds/buildtest.py b/lib/tests/builds/buildtest.py
deleted file mode 100644
index 5a56a110..00000000
--- a/lib/tests/builds/buildtest.py
+++ /dev/null
@@ -1,169 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import os
-import sys
-import time
-import unittest
-
-from orm.models import Project, Release, ProjectTarget, Build, ProjectVariable
-from bldcontrol.models import BuildEnvironment
-
-from bldcontrol.management.commands.runbuilds import Command\
- as RunBuildsCommand
-
-from django.core.management import call_command
-
-import subprocess
-import logging
-
-logger = logging.getLogger("toaster")
-
-# We use unittest.TestCase instead of django.test.TestCase because we don't
-# want to wrap everything in a database transaction as an external process
-# (bitbake needs access to the database)
-
-def load_build_environment():
- call_command('loaddata', 'settings.xml', app_label="orm")
- call_command('loaddata', 'poky.xml', app_label="orm")
-
- current_builddir = os.environ.get("BUILDDIR")
- if current_builddir:
- BuildTest.BUILDDIR = current_builddir
- else:
- # Setup a builddir based on default layout
- # bitbake inside openebedded-core
- oe_init_build_env_path = os.path.join(
- os.path.dirname(os.path.abspath(__file__)),
- os.pardir,
- os.pardir,
- os.pardir,
- os.pardir,
- os.pardir,
- 'oe-init-build-env'
- )
- if not os.path.exists(oe_init_build_env_path):
- raise Exception("We had no BUILDDIR set and couldn't "
- "find oe-init-build-env to set this up "
- "ourselves please run oe-init-build-env "
- "before running these tests")
-
- oe_init_build_env_path = os.path.realpath(oe_init_build_env_path)
- cmd = "bash -c 'source oe-init-build-env %s'" % BuildTest.BUILDDIR
- p = subprocess.Popen(
- cmd,
- cwd=os.path.dirname(oe_init_build_env_path),
- shell=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
-
- output, err = p.communicate()
- p.wait()
-
- logger.info("oe-init-build-env %s %s" % (output, err))
-
- os.environ['BUILDDIR'] = BuildTest.BUILDDIR
-
- # Setup the path to bitbake we know where to find this
- bitbake_path = os.path.join(
- os.path.dirname(os.path.abspath(__file__)),
- os.pardir,
- os.pardir,
- os.pardir,
- os.pardir,
- 'bin',
- 'bitbake')
- if not os.path.exists(bitbake_path):
- raise Exception("Could not find bitbake at the expected path %s"
- % bitbake_path)
-
- os.environ['BBBASEDIR'] = bitbake_path
-
-class BuildTest(unittest.TestCase):
-
- PROJECT_NAME = "Testbuild"
- BUILDDIR = "/tmp/build/"
-
- def build(self, target):
- # So that the buildinfo helper uses the test database'
- self.assertEqual(
- os.environ.get('DJANGO_SETTINGS_MODULE', ''),
- 'toastermain.settings_test',
- "Please initialise django with the tests settings: "
- "DJANGO_SETTINGS_MODULE='toastermain.settings_test'")
-
- built = self.target_already_built(target)
- if built:
- return built
-
- load_build_environment()
-
- BuildEnvironment.objects.get_or_create(
- betype=BuildEnvironment.TYPE_LOCAL,
- sourcedir=BuildTest.BUILDDIR,
- builddir=BuildTest.BUILDDIR
- )
-
- release = Release.objects.get(name='local')
-
- # Create a project for this build to run in
- project = Project.objects.create_project(name=BuildTest.PROJECT_NAME,
- release=release)
-
- if os.environ.get("TOASTER_TEST_USE_SSTATE_MIRROR"):
- ProjectVariable.objects.get_or_create(
- name="SSTATE_MIRRORS",
- value="file://.* http://autobuilder.yoctoproject.org/pub/sstate/PATH;downloadfilename=PATH",
- project=project)
-
- ProjectTarget.objects.create(project=project,
- target=target,
- task="")
- build_request = project.schedule_build()
-
- # run runbuilds command to dispatch the build
- # e.g. manage.py runubilds
- RunBuildsCommand().runbuild()
-
- build_pk = build_request.build.pk
- while Build.objects.get(pk=build_pk).outcome == Build.IN_PROGRESS:
- sys.stdout.write("\rBuilding %s %d%%" %
- (target,
- build_request.build.completeper()))
- sys.stdout.flush()
- time.sleep(1)
-
- self.assertEqual(Build.objects.get(pk=build_pk).outcome,
- Build.SUCCEEDED,
- "Build did not SUCCEEDED")
-
- logger.info("\nBuild finished %s" % build_request.build.outcome)
- return build_request.build
-
- def target_already_built(self, target):
- """ If the target is already built no need to build it again"""
- for build in Build.objects.filter(
- project__name=BuildTest.PROJECT_NAME):
- targets = build.target_set.values_list('target', flat=True)
- if target in targets:
- return build
-
- return None
diff --git a/lib/tests/builds/test_core_image_min.py b/lib/tests/builds/test_core_image_min.py
deleted file mode 100644
index 586f4a8f..00000000
--- a/lib/tests/builds/test_core_image_min.py
+++ /dev/null
@@ -1,386 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-# Tests were part of openembedded-core oe selftest Authored by: Lucian Musat
-# Ionut Chisanovici, Paul Eggleton and Cristian Iorga
-
-import os
-
-from django.db.models import Q
-
-from orm.models import Target_Image_File, Target_Installed_Package, Task
-from orm.models import Package_Dependency, Recipe_Dependency, Build
-from orm.models import Task_Dependency, Package, Target, Recipe
-from orm.models import CustomImagePackage
-
-from tests.builds.buildtest import BuildTest
-
-
-class BuildCoreImageMinimal(BuildTest):
- """Build core-image-minimal and test the results"""
-
- def setUp(self):
- self.completed_build = self.build("core-image-minimal")
-
- # Check if build name is unique - tc_id=795
- def test_Build_Unique_Name(self):
- all_builds = Build.objects.all().count()
- distinct_builds = Build.objects.values('id').distinct().count()
- self.assertEqual(distinct_builds,
- all_builds,
- msg='Build name is not unique')
-
- # Check if build cooker log path is unique - tc_id=819
- def test_Build_Unique_Cooker_Log_Path(self):
- distinct_path = Build.objects.values(
- 'cooker_log_path').distinct().count()
- total_builds = Build.objects.values('id').count()
- self.assertEqual(distinct_path,
- total_builds,
- msg='Build cooker log path is not unique')
-
- # Check if task order is unique for one build - tc=824
- def test_Task_Unique_Order(self):
- total_task_order = Task.objects.filter(
- build=self.built).values('order').count()
- distinct_task_order = Task.objects.filter(
- build=self.completed_build).values('order').distinct().count()
-
- self.assertEqual(total_task_order,
- distinct_task_order,
- msg='Errors task order is not unique')
-
- # Check task order sequence for one build - tc=825
- def test_Task_Order_Sequence(self):
- cnt_err = []
- tasks = Task.objects.filter(
- Q(build=self.completed_build),
- ~Q(order=None),
- ~Q(task_name__contains='_setscene')
- ).values('id', 'order').order_by("order")
-
- cnt_tasks = 0
- for task in tasks:
- cnt_tasks += 1
- if (task['order'] != cnt_tasks):
- cnt_err.append(task['id'])
- self.assertEqual(
- len(cnt_err), 0, msg='Errors for task id: %s' % cnt_err)
-
- # Check if disk_io matches the difference between EndTimeIO and
- # StartTimeIO in build stats - tc=828
- # def test_Task_Disk_IO_TC828(self):
-
- # Check if outcome = 2 (SSTATE) then sstate_result must be 3 (RESTORED) -
- # tc=832
- def test_Task_If_Outcome_2_Sstate_Result_Must_Be_3(self):
- tasks = Task.objects.filter(outcome=2).values('id', 'sstate_result')
- cnt_err = []
- for task in tasks:
- if (task['sstate_result'] != 3):
- cnt_err.append(task['id'])
-
- self.assertEqual(len(cnt_err),
- 0,
- msg='Errors for task id: %s' % cnt_err)
-
- # Check if outcome = 1 (COVERED) or 3 (EXISTING) then sstate_result must
- # be 0 (SSTATE_NA) - tc=833
- def test_Task_If_Outcome_1_3_Sstate_Result_Must_Be_0(self):
- tasks = Task.objects.filter(
- outcome__in=(Task.OUTCOME_COVERED,
- Task.OUTCOME_PREBUILT)).values('id',
- 'task_name',
- 'sstate_result')
- cnt_err = []
-
- for task in tasks:
- if (task['sstate_result'] != Task.SSTATE_NA and
- task['sstate_result'] != Task.SSTATE_MISS):
- cnt_err.append({'id': task['id'],
- 'name': task['task_name'],
- 'sstate_result': task['sstate_result']})
-
- self.assertEqual(len(cnt_err),
- 0,
- msg='Errors for task id: %s' % cnt_err)
-
- # Check if outcome is 0 (SUCCESS) or 4 (FAILED) then sstate_result must be
- # 0 (NA), 1 (MISS) or 2 (FAILED) - tc=834
- def test_Task_If_Outcome_0_4_Sstate_Result_Must_Be_0_1_2(self):
- tasks = Task.objects.filter(
- outcome__in=(0, 4)).values('id', 'sstate_result')
- cnt_err = []
-
- for task in tasks:
- if (task['sstate_result'] not in [0, 1, 2]):
- cnt_err.append(task['id'])
-
- self.assertEqual(len(cnt_err),
- 0,
- msg='Errors for task id: %s' % cnt_err)
-
- # Check if task_executed = TRUE (1), script_type must be 0 (CODING_NA), 2
- # (CODING_PYTHON), 3 (CODING_SHELL) - tc=891
- def test_Task_If_Task_Executed_True_Script_Type_0_2_3(self):
- tasks = Task.objects.filter(
- task_executed=1).values('id', 'script_type')
- cnt_err = []
-
- for task in tasks:
- if (task['script_type'] not in [0, 2, 3]):
- cnt_err.append(task['id'])
- self.assertEqual(len(cnt_err),
- 0,
- msg='Errors for task id: %s' % cnt_err)
-
- # Check if task_executed = TRUE (1), outcome must be 0 (SUCCESS) or 4
- # (FAILED) - tc=836
- def test_Task_If_Task_Executed_True_Outcome_0_4(self):
- tasks = Task.objects.filter(task_executed=1).values('id', 'outcome')
- cnt_err = []
-
- for task in tasks:
- if (task['outcome'] not in [0, 4]):
- cnt_err.append(task['id'])
-
- self.assertEqual(len(cnt_err),
- 0,
- msg='Errors for task id: %s' % cnt_err)
-
- # Check if task_executed = FALSE (0), script_type must be 0 - tc=890
- def test_Task_If_Task_Executed_False_Script_Type_0(self):
- tasks = Task.objects.filter(
- task_executed=0).values('id', 'script_type')
- cnt_err = []
-
- for task in tasks:
- if (task['script_type'] != 0):
- cnt_err.append(task['id'])
-
- self.assertEqual(len(cnt_err),
- 0,
- msg='Errors for task id: %s' % cnt_err)
-
- # Check if task_executed = FALSE (0) and build outcome = SUCCEEDED (0),
- # task outcome must be 1 (COVERED), 2 (CACHED), 3 (PREBUILT), 5 (EMPTY) -
- # tc=837
- def test_Task_If_Task_Executed_False_Outcome_1_2_3_5(self):
- builds = Build.objects.filter(outcome=0).values('id')
- cnt_err = []
- for build in builds:
- tasks = Task.objects.filter(
- build=build['id'], task_executed=0).values('id', 'outcome')
- for task in tasks:
- if (task['outcome'] not in [1, 2, 3, 5]):
- cnt_err.append(task['id'])
-
- self.assertEqual(len(cnt_err),
- 0,
- msg='Errors for task id: %s' % cnt_err)
-
- # Key verification - tc=888
- def test_Target_Installed_Package(self):
- rows = Target_Installed_Package.objects.values('id',
- 'target_id',
- 'package_id')
- cnt_err = []
-
- for row in rows:
- target = Target.objects.filter(id=row['target_id']).values('id')
- package = Package.objects.filter(id=row['package_id']).values('id')
- if (not target or not package):
- cnt_err.append(row['id'])
- self.assertEqual(len(cnt_err),
- 0,
- msg='Errors for target installed package id: %s' %
- cnt_err)
-
- # Key verification - tc=889
- def test_Task_Dependency(self):
- rows = Task_Dependency.objects.values('id',
- 'task_id',
- 'depends_on_id')
- cnt_err = []
- for row in rows:
- task_id = Task.objects.filter(id=row['task_id']).values('id')
- depends_on_id = Task.objects.filter(
- id=row['depends_on_id']).values('id')
- if (not task_id or not depends_on_id):
- cnt_err.append(row['id'])
- self.assertEqual(len(cnt_err),
- 0,
- msg='Errors for task dependency id: %s' % cnt_err)
-
- # Check if build target file_name is populated only if is_image=true AND
- # orm_build.outcome=0 then if the file exists and its size matches
- # the file_size value. Need to add the tc in the test run
- def test_Target_File_Name_Populated(self):
- builds = Build.objects.filter(outcome=0).values('id')
- for build in builds:
- targets = Target.objects.filter(
- build_id=build['id'], is_image=1).values('id')
- for target in targets:
- target_files = Target_Image_File.objects.filter(
- target_id=target['id']).values('id',
- 'file_name',
- 'file_size')
- cnt_err = []
- for file_info in target_files:
- target_id = file_info['id']
- target_file_name = file_info['file_name']
- target_file_size = file_info['file_size']
- if (not target_file_name or not target_file_size):
- cnt_err.append(target_id)
- else:
- if (not os.path.exists(target_file_name)):
- cnt_err.append(target_id)
- else:
- if (os.path.getsize(target_file_name) !=
- target_file_size):
- cnt_err.append(target_id)
- self.assertEqual(len(cnt_err), 0,
- msg='Errors for target image file id: %s' %
- cnt_err)
-
- # Key verification - tc=884
- def test_Package_Dependency(self):
- cnt_err = []
- deps = Package_Dependency.objects.values(
- 'id', 'package_id', 'depends_on_id')
- for dep in deps:
- if (dep['package_id'] == dep['depends_on_id']):
- cnt_err.append(dep['id'])
- self.assertEqual(len(cnt_err), 0,
- msg='Errors for package dependency id: %s' % cnt_err)
-
- # Recipe key verification, recipe name does not depends on a recipe having
- # the same name - tc=883
- def test_Recipe_Dependency(self):
- deps = Recipe_Dependency.objects.values(
- 'id', 'recipe_id', 'depends_on_id')
- cnt_err = []
- for dep in deps:
- if (not dep['recipe_id'] or not dep['depends_on_id']):
- cnt_err.append(dep['id'])
- else:
- name = Recipe.objects.filter(
- id=dep['recipe_id']).values('name')
- dep_name = Recipe.objects.filter(
- id=dep['depends_on_id']).values('name')
- if (name == dep_name):
- cnt_err.append(dep['id'])
- self.assertEqual(len(cnt_err), 0,
- msg='Errors for recipe dependency id: %s' % cnt_err)
-
- # Check if package name does not start with a number (0-9) - tc=846
- def test_Package_Name_For_Number(self):
- packages = Package.objects.filter(~Q(size=-1)).values('id', 'name')
- cnt_err = []
- for package in packages:
- if (package['name'][0].isdigit() is True):
- cnt_err.append(package['id'])
- self.assertEqual(
- len(cnt_err), 0, msg='Errors for package id: %s' % cnt_err)
-
- # Check if package version starts with a number (0-9) - tc=847
- def test_Package_Version_Starts_With_Number(self):
- packages = Package.objects.filter(
- ~Q(size=-1)).values('id', 'version')
- cnt_err = []
- for package in packages:
- if (package['version'][0].isdigit() is False):
- cnt_err.append(package['id'])
- self.assertEqual(
- len(cnt_err), 0, msg='Errors for package id: %s' % cnt_err)
-
- # Check if package revision starts with 'r' - tc=848
- def test_Package_Revision_Starts_With_r(self):
- packages = Package.objects.filter(
- ~Q(size=-1)).values('id', 'revision')
- cnt_err = []
- for package in packages:
- if (package['revision'][0].startswith("r") is False):
- cnt_err.append(package['id'])
- self.assertEqual(
- len(cnt_err), 0, msg='Errors for package id: %s' % cnt_err)
-
- # Check the validity of the package build_id
- # TC must be added in test run
- def test_Package_Build_Id(self):
- packages = Package.objects.filter(
- ~Q(size=-1)).values('id', 'build_id')
- cnt_err = []
- for package in packages:
- build_id = Build.objects.filter(
- id=package['build_id']).values('id')
- if (not build_id):
- # They have no build_id but if they are
- # CustomImagePackage that's expected
- try:
- CustomImagePackage.objects.get(pk=package['id'])
- except CustomImagePackage.DoesNotExist:
- cnt_err.append(package['id'])
-
- self.assertEqual(len(cnt_err),
- 0,
- msg="Errors for package id: %s they have no build"
- "associated with them" % cnt_err)
-
- # Check the validity of package recipe_id
- # TC must be added in test run
- def test_Package_Recipe_Id(self):
- packages = Package.objects.filter(
- ~Q(size=-1)).values('id', 'recipe_id')
- cnt_err = []
- for package in packages:
- recipe_id = Recipe.objects.filter(
- id=package['recipe_id']).values('id')
- if (not recipe_id):
- cnt_err.append(package['id'])
- self.assertEqual(
- len(cnt_err), 0, msg='Errors for package id: %s' % cnt_err)
-
- # Check if package installed_size field is not null
- # TC must be aded in test run
- def test_Package_Installed_Size_Not_NULL(self):
- packages = Package.objects.filter(
- installed_size__isnull=True).values('id')
- cnt_err = []
- for package in packages:
- cnt_err.append(package['id'])
- self.assertEqual(
- len(cnt_err), 0, msg='Errors for package id: %s' % cnt_err)
-
- def test_custom_packages_generated(self):
- """Test if there is a corresponding generated CustomImagePackage"""
- """ for each of the packages generated"""
- missing_packages = []
-
- for package in Package.objects.all():
- try:
- CustomImagePackage.objects.get(name=package.name)
- except CustomImagePackage.DoesNotExist:
- missing_packages.append(package.name)
-
- self.assertEqual(len(missing_packages), 0,
- "Some package were created from the build but their"
- " corresponding CustomImagePackage was not found")
diff --git a/lib/tests/commands/__init__.py b/lib/tests/commands/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/lib/tests/commands/__init__.py
+++ /dev/null
diff --git a/lib/tests/commands/test_loaddata.py b/lib/tests/commands/test_loaddata.py
deleted file mode 100644
index 951f6ff5..00000000
--- a/lib/tests/commands/test_loaddata.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-from django.test import TestCase
-from django.core import management
-
-from orm.models import Layer_Version, Layer, Release, ToasterSetting
-
-
-class TestLoadDataFixtures(TestCase):
- """ Test loading our 3 provided fixtures """
- def test_run_loaddata_poky_command(self):
- management.call_command('loaddata', 'poky')
-
- num_releases = Release.objects.count()
-
- self.assertTrue(
- Layer_Version.objects.filter(
- layer__name="meta-poky").count() == num_releases,
- "Loaded poky fixture but don't have a meta-poky for all releases"
- " defined")
-
- def test_run_loaddata_oecore_command(self):
- management.call_command('loaddata', 'oe-core')
-
- # We only have the one layer for oe-core setup
- self.assertTrue(
- Layer.objects.filter(name="openembedded-core").count() > 0,
- "Loaded oe-core fixture but still have no openemebedded-core"
- " layer")
-
- def test_run_loaddata_settings_command(self):
- management.call_command('loaddata', 'settings')
-
- self.assertTrue(
- ToasterSetting.objects.filter(name="DEFAULT_RELEASE").count() > 0,
- "Loaded settings but have no DEFAULT_RELEASE")
-
- self.assertTrue(
- ToasterSetting.objects.filter(
- name__startswith="DEFCONF").count() > 0,
- "Loaded settings but have no DEFCONF (default project "
- "configuration values)")
diff --git a/lib/tests/commands/test_lsupdates.py b/lib/tests/commands/test_lsupdates.py
deleted file mode 100644
index 49897a47..00000000
--- a/lib/tests/commands/test_lsupdates.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-from django.test import TestCase
-from django.core import management
-
-from orm.models import Layer_Version, Machine, Recipe
-
-
-class TestLayerIndexUpdater(TestCase):
- def test_run_lsupdates_command(self):
- # Load some release information for us to fetch from the layer index
- management.call_command('loaddata', 'poky')
-
- old_layers_count = Layer_Version.objects.count()
- old_recipes_count = Recipe.objects.count()
- old_machines_count = Machine.objects.count()
-
- # Now fetch the metadata from the layer index
- management.call_command('lsupdates')
-
- self.assertTrue(Layer_Version.objects.count() > old_layers_count,
- "lsupdates ran but we still have no more layers!")
- self.assertTrue(Recipe.objects.count() > old_recipes_count,
- "lsupdates ran but we still have no more Recipes!")
- self.assertTrue(Machine.objects.count() > old_machines_count,
- "lsupdates ran but we still have no more Machines!")
diff --git a/lib/tests/commands/test_runbuilds.py b/lib/tests/commands/test_runbuilds.py
deleted file mode 100644
index 3e634835..00000000
--- a/lib/tests/commands/test_runbuilds.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import os
-
-from django.test import TestCase
-from django.core import management
-
-from orm.models import signal_runbuilds
-
-import threading
-import time
-import subprocess
-import signal
-
-
-class KillRunbuilds(threading.Thread):
- """ Kill the runbuilds process after an amount of time """
- def __init__(self, *args, **kwargs):
- super(KillRunbuilds, self).__init__(*args, **kwargs)
- self.setDaemon(True)
-
- def run(self):
- time.sleep(5)
- signal_runbuilds()
- time.sleep(1)
-
- pidfile_path = os.path.join(os.environ.get("BUILDDIR", "."),
- ".runbuilds.pid")
-
- with open(pidfile_path) as pidfile:
- pid = pidfile.read()
- os.kill(int(pid), signal.SIGTERM)
-
-
-class TestCommands(TestCase):
- """ Sanity test that runbuilds executes OK """
-
- def setUp(self):
- os.environ.setdefault("DJANGO_SETTINGS_MODULE",
- "toastermain.settings_test")
- os.environ.setdefault("BUILDDIR",
- "/tmp/")
-
- # Setup a real database if needed for runbuilds process
- # to connect to
- management.call_command('migrate')
-
- def test_runbuilds_command(self):
- kill_runbuilds = KillRunbuilds()
- kill_runbuilds.start()
-
- manage_py = os.path.join(
- os.path.dirname(os.path.abspath(__file__)),
- os.pardir,
- os.pardir,
- "manage.py")
-
- command = "%s runbuilds" % manage_py
-
- process = subprocess.Popen(command,
- shell=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
-
- (out, err) = process.communicate()
- process.wait()
-
- self.assertNotEqual(process.returncode, 1,
- "Runbuilds returned an error %s" % err)
diff --git a/lib/tests/db/__init__.py b/lib/tests/db/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/lib/tests/db/__init__.py
+++ /dev/null
diff --git a/lib/tests/db/test_db.py b/lib/tests/db/test_db.py
deleted file mode 100644
index a0f5f6ec..00000000
--- a/lib/tests/db/test_db.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# The MIT License (MIT)
-#
-# Copyright (c) 2016 Damien Lespiau
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-import sys
-
-try:
- from StringIO import StringIO
-except ImportError:
- from io import StringIO
-
-from contextlib import contextmanager
-
-from django.core import management
-from django.test import TestCase
-
-
-@contextmanager
-def capture(command, *args, **kwargs):
- out, sys.stdout = sys.stdout, StringIO()
- command(*args, **kwargs)
- sys.stdout.seek(0)
- yield sys.stdout.read()
- sys.stdout = out
-
-
-def makemigrations():
- management.call_command('makemigrations')
-
-
-class MigrationTest(TestCase):
-
- def testPendingMigration(self):
- """Make sure there's no pending migration."""
-
- with capture(makemigrations) as output:
- self.assertEqual(output, "No changes detected\n")
diff --git a/lib/tests/eventreplay/README b/lib/tests/eventreplay/README
deleted file mode 100644
index 8c5bb643..00000000
--- a/lib/tests/eventreplay/README
+++ /dev/null
@@ -1,22 +0,0 @@
-# Running eventreplay tests
-
-These tests use event log files produced by bitbake <target> -w <event log file>
-You need to have event log files produced before running this tests.
-
-At the moment of writing this document tests use 2 event log files: zlib.events
-and core-image-minimal.events. They're not provided with the tests due to their
-significant size.
-
-Here is how to produce them:
-
-$ . oe-init-build-env
-$ rm -r tmp sstate-cache
-$ bitbake core-image-minimal -w core-image-minimal.events
-$ rm -rf tmp sstate-cache
-$ bitbake zlib -w zlib.events
-
-After that it should be possible to run eventreplay tests this way:
-
-$ EVENTREPLAY_DIR=./ DJANGO_SETTINGS_MODULE=toastermain.settings_test ../bitbake/lib/toaster/manage.py test -v2 tests.eventreplay
-
-Note that environment variable EVENTREPLAY_DIR should point to the directory with event log files.
diff --git a/lib/tests/eventreplay/__init__.py b/lib/tests/eventreplay/__init__.py
deleted file mode 100644
index 69566194..00000000
--- a/lib/tests/eventreplay/__init__.py
+++ /dev/null
@@ -1,97 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2016 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-# Tests were part of openembedded-core oe selftest Authored by: Lucian Musat
-# Ionut Chisanovici, Paul Eggleton and Cristian Iorga
-
-"""
-Test toaster backend by playing build event log files
-using toaster-eventreplay script
-"""
-
-import os
-
-from subprocess import getstatusoutput
-from pathlib import Path
-
-from django.test import TestCase
-
-from orm.models import Target_Installed_Package, Package, Build
-
-class EventReplay(TestCase):
- """Base class for eventreplay test cases"""
-
- def setUp(self):
- """
- Setup build environment:
- - set self.script to toaster-eventreplay path
- - set self.eventplay_dir to the value of EVENTPLAY_DIR env variable
- """
- bitbake_dir = Path(__file__.split('lib/toaster')[0])
- self.script = bitbake_dir / 'bin' / 'toaster-eventreplay'
- self.assertTrue(self.script.exists(), "%s doesn't exist")
- self.eventplay_dir = os.getenv("EVENTREPLAY_DIR")
- self.assertTrue(self.eventplay_dir,
- "Environment variable EVENTREPLAY_DIR is not set")
-
- def _replay(self, eventfile):
- """Run toaster-eventplay <eventfile>"""
- eventpath = Path(self.eventplay_dir) / eventfile
- status, output = getstatusoutput('%s %s' % (self.script, eventpath))
- if status:
- print(output)
-
- self.assertEqual(status, 0)
-
-class CoreImageMinimalEventReplay(EventReplay):
- """Replay core-image-minimal events"""
-
- def test_installed_packages(self):
- """Test if all required packages have been installed"""
-
- self._replay('core-image-minimal.events')
-
- # test installed packages
- packages = sorted(Target_Installed_Package.objects.\
- values_list('package__name', flat=True))
- self.assertEqual(packages, ['base-files', 'base-passwd', 'busybox',
- 'busybox-hwclock', 'busybox-syslog',
- 'busybox-udhcpc', 'eudev', 'glibc',
- 'init-ifupdown', 'initscripts',
- 'initscripts-functions', 'kernel-base',
- 'kernel-module-uvesafb', 'libkmod',
- 'modutils-initscripts', 'netbase',
- 'packagegroup-core-boot', 'run-postinsts',
- 'sysvinit', 'sysvinit-inittab',
- 'sysvinit-pidof', 'udev-cache',
- 'update-alternatives-opkg',
- 'update-rc.d', 'util-linux-libblkid',
- 'util-linux-libuuid', 'v86d', 'zlib'])
-
-class ZlibEventReplay(EventReplay):
- """Replay zlib events"""
-
- def test_replay_zlib(self):
- """Test if zlib build and package are in the database"""
- self._replay("zlib.events")
-
- self.assertEqual(Build.objects.last().target_set.last().target, "zlib")
- self.assertTrue('zlib' in Package.objects.values_list('name', flat=True))
diff --git a/lib/tests/functional/README b/lib/tests/functional/README
deleted file mode 100644
index e69de29b..00000000
--- a/lib/tests/functional/README
+++ /dev/null
diff --git a/lib/tests/functional/__init__.py b/lib/tests/functional/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/lib/tests/functional/__init__.py
+++ /dev/null
diff --git a/lib/tests/functional/functional_helpers.py b/lib/tests/functional/functional_helpers.py
deleted file mode 100644
index 486078a6..00000000
--- a/lib/tests/functional/functional_helpers.py
+++ /dev/null
@@ -1,122 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster functional tests implementation
-#
-# Copyright (C) 2017 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import os
-import logging
-import subprocess
-import signal
-import time
-import re
-
-from tests.browser.selenium_helpers_base import SeleniumTestCaseBase
-from tests.builds.buildtest import load_build_environment
-
-logger = logging.getLogger("toaster")
-
-class SeleniumFunctionalTestCase(SeleniumTestCaseBase):
- wait_toaster_time = 5
-
- @classmethod
- def setUpClass(cls):
- # So that the buildinfo helper uses the test database'
- if os.environ.get('DJANGO_SETTINGS_MODULE', '') != \
- 'toastermain.settings_test':
- raise RuntimeError("Please initialise django with the tests settings: " \
- "DJANGO_SETTINGS_MODULE='toastermain.settings_test'")
-
- load_build_environment()
-
- # start toaster
- cmd = "bash -c 'source toaster start'"
- p = subprocess.Popen(
- cmd,
- cwd=os.environ.get("BUILDDIR"),
- shell=True)
- if p.wait() != 0:
- raise RuntimeError("Can't initialize toaster")
-
- super(SeleniumFunctionalTestCase, cls).setUpClass()
- cls.live_server_url = 'http://localhost:8000/'
-
- @classmethod
- def tearDownClass(cls):
- super(SeleniumFunctionalTestCase, cls).tearDownClass()
-
- # XXX: source toaster stop gets blocked, to review why?
- # from now send SIGTERM by hand
- time.sleep(cls.wait_toaster_time)
- builddir = os.environ.get("BUILDDIR")
-
- with open(os.path.join(builddir, '.toastermain.pid'), 'r') as f:
- toastermain_pid = int(f.read())
- os.kill(toastermain_pid, signal.SIGTERM)
- with open(os.path.join(builddir, '.runbuilds.pid'), 'r') as f:
- runbuilds_pid = int(f.read())
- os.kill(runbuilds_pid, signal.SIGTERM)
-
-
- def get_URL(self):
- rc=self.get_page_source()
- project_url=re.search("(projectPageUrl\s:\s\")(.*)(\",)",rc)
- return project_url.group(2)
-
-
- def find_element_by_link_text_in_table(self, table_id, link_text):
- """
- Assume there're multiple suitable "find_element_by_link_text".
- In this circumstance we need to specify "table".
- """
- try:
- table_element = self.get_table_element(table_id)
- element = table_element.find_element_by_link_text(link_text)
- except NoSuchElementException as e:
- print('no element found')
- raise
- return element
-
- def get_table_element(self, table_id, *coordinate):
- if len(coordinate) == 0:
-#return whole-table element
- element_xpath = "//*[@id='" + table_id + "']"
- try:
- element = self.driver.find_element_by_xpath(element_xpath)
- except NoSuchElementException as e:
- raise
- return element
- row = coordinate[0]
-
- if len(coordinate) == 1:
-#return whole-row element
- element_xpath = "//*[@id='" + table_id + "']/tbody/tr[" + str(row) + "]"
- try:
- element = self.driver.find_element_by_xpath(element_xpath)
- except NoSuchElementException as e:
- return False
- return element
-#now we are looking for an element with specified X and Y
- column = coordinate[1]
-
- element_xpath = "//*[@id='" + table_id + "']/tbody/tr[" + str(row) + "]/td[" + str(column) + "]"
- try:
- element = self.driver.find_element_by_xpath(element_xpath)
- except NoSuchElementException as e:
- return False
- return element
diff --git a/lib/tests/functional/test_functional_basic.py b/lib/tests/functional/test_functional_basic.py
deleted file mode 100644
index cfa2b0fd..00000000
--- a/lib/tests/functional/test_functional_basic.py
+++ /dev/null
@@ -1,243 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster functional tests implementation
-#
-# Copyright (C) 2017 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import time
-import re
-from tests.functional.functional_helpers import SeleniumFunctionalTestCase
-from orm.models import Project
-
-class FuntionalTestBasic(SeleniumFunctionalTestCase):
-
-# testcase (1514)
- def test_create_slenium_project(self):
- project_name = 'selenium-project'
- self.get('')
- self.driver.find_element_by_link_text("To start building, create your first Toaster project").click()
- self.driver.find_element_by_id("new-project-name").send_keys(project_name)
- self.driver.find_element_by_id('projectversion').click()
- self.driver.find_element_by_id("create-project-button").click()
- element = self.wait_until_visible('#project-created-notification')
- self.assertTrue(self.element_exists('#project-created-notification'),'Project creation notification not shown')
- self.assertTrue(project_name in element.text,
- "New project name not in new project notification")
- self.assertTrue(Project.objects.filter(name=project_name).count(),
- "New project not found in database")
-
- # testcase (1515)
- def test_verify_left_bar_menu(self):
- self.get('')
- self.wait_until_visible('#projectstable')
- self.find_element_by_link_text_in_table('projectstable', 'selenium-project').click()
- self.assertTrue(self.element_exists('#config-nav'),'Configuration Tab does not exist')
- project_URL=self.get_URL()
- self.driver.find_element_by_xpath('//a[@href="'+project_URL+'"]').click()
-
- try:
- self.driver.find_element_by_xpath("//*[@id='config-nav']/ul/li/a[@href="+'"'+project_URL+'customimages/"'+"]").click()
- self.assertTrue(re.search("Custom images",self.driver.find_element_by_xpath("//div[@class='col-md-10']").text),'Custom images information is not loading properly')
- except:
- self.fail(msg='No Custom images tab available')
-
- try:
- self.driver.find_element_by_xpath("//*[@id='config-nav']/ul/li/a[@href="+'"'+project_URL+'images/"'+"]").click()
- self.assertTrue(re.search("Compatible image recipes",self.driver.find_element_by_xpath("//div[@class='col-md-10']").text),'The Compatible image recipes information is not loading properly')
- except:
- self.fail(msg='No Compatible image tab available')
-
- try:
- self.driver.find_element_by_xpath("//*[@id='config-nav']/ul/li/a[@href="+'"'+project_URL+'softwarerecipes/"'+"]").click()
- self.assertTrue(re.search("Compatible software recipes",self.driver.find_element_by_xpath("//div[@class='col-md-10']").text),'The Compatible software recipe information is not loading properly')
- except:
- self.fail(msg='No Compatible software recipe tab available')
-
- try:
- self.driver.find_element_by_xpath("//*[@id='config-nav']/ul/li/a[@href="+'"'+project_URL+'machines/"'+"]").click()
- self.assertTrue(re.search("Compatible machines",self.driver.find_element_by_xpath("//div[@class='col-md-10']").text),'The Compatible machine information is not loading properly')
- except:
- self.fail(msg='No Compatible machines tab available')
-
- try:
- self.driver.find_element_by_xpath("//*[@id='config-nav']/ul/li/a[@href="+'"'+project_URL+'layers/"'+"]").click()
- self.assertTrue(re.search("Compatible layers",self.driver.find_element_by_xpath("//div[@class='col-md-10']").text),'The Compatible layer information is not loading properly')
- except:
- self.fail(msg='No Compatible layers tab available')
-
- try:
- self.driver.find_element_by_xpath("//*[@id='config-nav']/ul/li/a[@href="+'"'+project_URL+'configuration"'+"]").click()
- self.assertTrue(re.search("Bitbake variables",self.driver.find_element_by_xpath("//div[@class='col-md-10']").text),'The Bitbake variables information is not loading properly')
- except:
- self.fail(msg='No Bitbake variables tab available')
-
-# testcase (1516)
- def test_review_configuration_information(self):
- self.get('')
- self.driver.find_element_by_xpath("//div[@id='global-nav']/ul/li/a[@href="+'"'+'/toastergui/projects/'+'"'+"]").click()
- self.wait_until_visible('#projectstable')
- self.find_element_by_link_text_in_table('projectstable', 'selenium-project').click()
- project_URL=self.get_URL()
-
- try:
- self.assertTrue(self.element_exists('#machine-section'),'Machine section for the project configuration page does not exist')
- self.assertTrue(re.search("qemux86",self.driver.find_element_by_xpath("//span[@id='project-machine-name']").text),'The machine type is not assigned')
- self.driver.find_element_by_xpath("//span[@id='change-machine-toggle']").click()
- self.wait_until_visible('#select-machine-form')
- self.wait_until_visible('#cancel-machine-change')
- self.driver.find_element_by_xpath("//form[@id='select-machine-form']/a[@id='cancel-machine-change']").click()
- except:
- self.fail(msg='The machine information is wrong in the configuration page')
-
- try:
- self.driver.find_element_by_id('no-most-built')
- except:
- self.fail(msg='No Most built information in project detail page')
-
- try:
- self.assertTrue(re.search("Yocto Project master",self.driver.find_element_by_xpath("//span[@id='project-release-title']").text),'The project release is not defined')
- except:
- self.fail(msg='No project release title information in project detail page')
-
- try:
- self.driver.find_element_by_xpath("//div[@id='layer-container']")
- self.assertTrue(re.search("3",self.driver.find_element_by_id("project-layers-count").text),'There should be 3 layers listed in the layer count')
- layer_list = self.driver.find_element_by_id("layers-in-project-list")
- layers = layer_list.find_elements_by_tag_name("li")
- for layer in layers:
- if re.match ("openembedded-core",layer.text):
- print ("openembedded-core layer is a default layer in the project configuration")
- elif re.match ("meta-poky",layer.text):
- print ("meta-poky layer is a default layer in the project configuration")
- elif re.match ("meta-yocto-bsp",layer.text):
- print ("meta-yocto-bsp is a default layer in the project configuratoin")
- else:
- self.fail(msg='default layers are missing from the project configuration')
- except:
- self.fail(msg='No Layer information in project detail page')
-
-# testcase (1517)
- def test_verify_machine_information(self):
- self.get('')
- self.driver.find_element_by_xpath("//div[@id='global-nav']/ul/li/a[@href="+'"'+'/toastergui/projects/'+'"'+"]").click()
- self.wait_until_visible('#projectstable')
- self.find_element_by_link_text_in_table('projectstable', 'selenium-project').click()
-
- try:
- self.assertTrue(self.element_exists('#machine-section'),'Machine section for the project configuration page does not exist')
- self.assertTrue(re.search("qemux86",self.driver.find_element_by_id("project-machine-name").text),'The machine type is not assigned')
- self.driver.find_element_by_id("change-machine-toggle").click()
- self.wait_until_visible('#select-machine-form')
- self.wait_until_visible('#cancel-machine-change')
- self.driver.find_element_by_id("cancel-machine-change").click()
- except:
- self.fail(msg='The machine information is wrong in the configuration page')
-
-# testcase (1518)
- def test_verify_most_built_recipes_information(self):
- self.get('')
- self.driver.find_element_by_xpath("//div[@id='global-nav']/ul/li/a[@href="+'"'+'/toastergui/projects/'+'"'+"]").click()
- self.wait_until_visible('#projectstable')
- self.find_element_by_link_text_in_table('projectstable', 'selenium-project').click()
- project_URL=self.get_URL()
-
- try:
- self.assertTrue(re.search("You haven't built any recipes yet",self.driver.find_element_by_id("no-most-built").text),'Default message of no builds is not present')
- self.driver.find_element_by_xpath("//div[@id='no-most-built']/p/a[@href="+'"'+project_URL+'images/"'+"]").click()
- self.assertTrue(re.search("Compatible image recipes",self.driver.find_element_by_xpath("//div[@class='col-md-10']").text),'The Choose a recipe to build link is not working properly')
- except:
- self.fail(msg='No Most built information in project detail page')
-
-# testcase (1519)
- def test_verify_project_release_information(self):
- self.get('')
- self.driver.find_element_by_xpath("//div[@id='global-nav']/ul/li/a[@href="+'"'+'/toastergui/projects/'+'"'+"]").click()
- self.wait_until_visible('#projectstable')
- self.find_element_by_link_text_in_table('projectstable', 'selenium-project').click()
-
- try:
- self.assertTrue(re.search("Yocto Project master",self.driver.find_element_by_id("project-release-title").text),'The project release is not defined')
- except:
- self.fail(msg='No project release title information in project detail page')
-
-# testcase (1520)
- def test_verify_layer_information(self):
- self.get('')
- self.driver.find_element_by_xpath("//div[@id='global-nav']/ul/li/a[@href="+'"'+'/toastergui/projects/'+'"'+"]").click()
- self.wait_until_visible('#projectstable')
- self.find_element_by_link_text_in_table('projectstable', 'selenium-project').click()
- project_URL=self.get_URL()
-
- try:
- self.driver.find_element_by_xpath("//div[@id='layer-container']")
- self.assertTrue(re.search("3",self.driver.find_element_by_id("project-layers-count").text),'There should be 3 layers listed in the layer count')
- layer_list = self.driver.find_element_by_id("layers-in-project-list")
- layers = layer_list.find_elements_by_tag_name("li")
-
- for layer in layers:
- if re.match ("openembedded-core",layer.text):
- print ("openembedded-core layer is a default layer in the project configuration")
- elif re.match ("meta-poky",layer.text):
- print ("meta-poky layer is a default layer in the project configuration")
- elif re.match ("meta-yocto-bsp",layer.text):
- print ("meta-yocto-bsp is a default layer in the project configuratoin")
- else:
- self.fail(msg='default layers are missing from the project configuration')
-
- self.driver.find_element_by_xpath("//input[@id='layer-add-input']")
- self.driver.find_element_by_xpath("//button[@id='add-layer-btn']")
- self.driver.find_element_by_xpath("//div[@id='layer-container']/form[@class='form-inline']/p/a[@id='view-compatible-layers']")
- self.driver.find_element_by_xpath("//div[@id='layer-container']/form[@class='form-inline']/p/a[@href="+'"'+project_URL+'importlayer"'+"]")
- except:
- self.fail(msg='No Layer information in project detail page')
-
-# testcase (1521)
- def test_verify_project_detail_links(self):
- self.get('')
- self.driver.find_element_by_xpath("//div[@id='global-nav']/ul/li/a[@href="+'"'+'/toastergui/projects/'+'"'+"]").click()
- self.wait_until_visible('#projectstable')
- self.find_element_by_link_text_in_table('projectstable', 'selenium-project').click()
- project_URL=self.get_URL()
-
- self.driver.find_element_by_xpath("//div[@id='project-topbar']/ul[@class='nav nav-tabs']/li[@id='topbar-configuration-tab']/a[@href="+'"'+project_URL+'"'+"]").click()
- self.assertTrue(re.search("Configuration",self.driver.find_element_by_xpath("//div[@id='project-topbar']/ul[@class='nav nav-tabs']/li[@id='topbar-configuration-tab']/a[@href="+'"'+project_URL+'"'+"]").text), 'Configuration tab in project topbar is misspelled')
-
- try:
- self.driver.find_element_by_xpath("//div[@id='project-topbar']/ul[@class='nav nav-tabs']/li/a[@href="+'"'+project_URL+'builds/"'+"]").click()
- self.assertTrue(re.search("Builds",self.driver.find_element_by_xpath("//div[@id='project-topbar']/ul[@class='nav nav-tabs']/li/a[@href="+'"'+project_URL+'builds/"'+"]").text), 'Builds tab in project topbar is misspelled')
- self.driver.find_element_by_xpath("//div[@id='empty-state-projectbuildstable']")
- except:
- self.fail(msg='Builds tab information is not present')
-
- try:
- self.driver.find_element_by_xpath("//div[@id='project-topbar']/ul[@class='nav nav-tabs']/li/a[@href="+'"'+project_URL+'importlayer"'+"]").click()
- self.assertTrue(re.search("Import layer",self.driver.find_element_by_xpath("//div[@id='project-topbar']/ul[@class='nav nav-tabs']/li/a[@href="+'"'+project_URL+'importlayer"'+"]").text), 'Import layer tab in project topbar is misspelled')
- self.driver.find_element_by_xpath("//fieldset[@id='repo-select']")
- self.driver.find_element_by_xpath("//fieldset[@id='git-repo']")
- except:
- self.fail(msg='Import layer tab not loading properly')
-
- try:
- self.driver.find_element_by_xpath("//div[@id='project-topbar']/ul[@class='nav nav-tabs']/li/a[@href="+'"'+project_URL+'newcustomimage/"'+"]").click()
- self.assertTrue(re.search("New custom image",self.driver.find_element_by_xpath("//div[@id='project-topbar']/ul[@class='nav nav-tabs']/li/a[@href="+'"'+project_URL+'newcustomimage/"'+"]").text), 'New custom image tab in project topbar is misspelled')
- self.assertTrue(re.search("Select the image recipe you want to customise",self.driver.find_element_by_xpath("//div[@class='col-md-12']/h2").text),'The new custom image tab is not loading correctly')
- except:
- self.fail(msg='New custom image tab not loading properly')
-
-
-
diff --git a/lib/tests/toaster-tests-requirements.txt b/lib/tests/toaster-tests-requirements.txt
deleted file mode 100644
index 4f9fcc46..00000000
--- a/lib/tests/toaster-tests-requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-selenium==2.49.2
diff --git a/lib/tests/views/README b/lib/tests/views/README
deleted file mode 100644
index 950c7c98..00000000
--- a/lib/tests/views/README
+++ /dev/null
@@ -1,4 +0,0 @@
-
-Django unit tests to verify classes and functions based on django Views
-
-To run just these tests use ./manage.py test tests.views
diff --git a/lib/tests/views/__init__.py b/lib/tests/views/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/lib/tests/views/__init__.py
+++ /dev/null
diff --git a/lib/tests/views/test_views.py b/lib/tests/views/test_views.py
deleted file mode 100644
index 1463077e..00000000
--- a/lib/tests/views/test_views.py
+++ /dev/null
@@ -1,540 +0,0 @@
-#! /usr/bin/env python
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2013-2015 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-"""Test cases for Toaster GUI and ReST."""
-
-from django.test import TestCase
-from django.test.client import RequestFactory
-from django.core.urlresolvers import reverse
-from django.db.models import Q
-
-from orm.models import Project, Package
-from orm.models import Layer_Version, Recipe
-from orm.models import CustomImageRecipe
-from orm.models import CustomImagePackage
-
-import inspect
-import toastergui
-
-from toastergui.tables import SoftwareRecipesTable
-import json
-from bs4 import BeautifulSoup
-import string
-
-PROJECT_NAME = "test project"
-PROJECT_NAME2 = "test project 2"
-CLI_BUILDS_PROJECT_NAME = 'Command line builds'
-
-
-class ViewTests(TestCase):
- """Tests to verify view APIs."""
-
- fixtures = ['toastergui-unittest-data']
-
- def setUp(self):
-
- self.project = Project.objects.first()
- self.recipe1 = Recipe.objects.get(pk=2)
- self.customr = CustomImageRecipe.objects.first()
- self.cust_package = CustomImagePackage.objects.first()
- self.package = Package.objects.first()
- self.lver = Layer_Version.objects.first()
-
- def test_get_base_call_returns_html(self):
- """Basic test for all-projects view"""
- response = self.client.get(reverse('all-projects'), follow=True)
- self.assertEqual(response.status_code, 200)
- self.assertTrue(response['Content-Type'].startswith('text/html'))
- self.assertTemplateUsed(response, "projects-toastertable.html")
-
- def test_get_json_call_returns_json(self):
- """Test for all projects output in json format"""
- url = reverse('all-projects')
- response = self.client.get(url, {"format": "json"}, follow=True)
- self.assertEqual(response.status_code, 200)
- self.assertTrue(response['Content-Type'].startswith(
- 'application/json'))
-
- data = json.loads(response.content.decode('utf-8'))
-
- self.assertTrue("error" in data)
- self.assertEqual(data["error"], "ok")
- self.assertTrue("rows" in data)
-
- name_found = False
- for row in data["rows"]:
- name_found = row['name'].find(self.project.name)
-
- self.assertTrue(name_found,
- "project name not found in projects table")
-
- def test_typeaheads(self):
- """Test typeahead ReST API"""
- layers_url = reverse('xhr_layerstypeahead', args=(self.project.id,))
- prj_url = reverse('xhr_projectstypeahead')
-
- urls = [layers_url,
- prj_url,
- reverse('xhr_recipestypeahead', args=(self.project.id,)),
- reverse('xhr_machinestypeahead', args=(self.project.id,))]
-
- def basic_reponse_check(response, url):
- """Check data structure of http response."""
- self.assertEqual(response.status_code, 200)
- self.assertTrue(response['Content-Type'].startswith(
- 'application/json'))
-
- data = json.loads(response.content.decode('utf-8'))
-
- self.assertTrue("error" in data)
- self.assertEqual(data["error"], "ok")
- self.assertTrue("results" in data)
-
- # We got a result so now check the fields
- if len(data['results']) > 0:
- result = data['results'][0]
-
- self.assertTrue(len(result['name']) > 0)
- self.assertTrue("detail" in result)
- self.assertTrue(result['id'] > 0)
-
- # Special check for the layers typeahead's extra fields
- if url == layers_url:
- self.assertTrue(len(result['layerdetailurl']) > 0)
- self.assertTrue(len(result['vcs_url']) > 0)
- self.assertTrue(len(result['vcs_reference']) > 0)
- # Special check for project typeahead extra fields
- elif url == prj_url:
- self.assertTrue(len(result['projectPageUrl']) > 0)
-
- return True
-
- return False
-
- for url in urls:
- results = False
-
- for typeing in list(string.ascii_letters):
- response = self.client.get(url, {'search': typeing})
- results = basic_reponse_check(response, url)
- if results:
- break
-
- # After "typeing" the alpabet we should have result true
- # from each of the urls
- self.assertTrue(results)
-
- def test_xhr_add_layer(self):
- """Test xhr_add API"""
- # Test for importing an already existing layer
- api_url = reverse('xhr_layer', args=(self.project.id,))
-
- layer_data = {'vcs_url': "git://git.example.com/test",
- 'name': "base-layer",
- 'git_ref': "c12b9596afd236116b25ce26dbe0d793de9dc7ce",
- 'project_id': self.project.id,
- 'local_source_dir': "",
- 'add_to_project': True,
- 'dir_path': "/path/in/repository"}
-
- layer_data_json = json.dumps(layer_data)
-
- response = self.client.put(api_url, layer_data_json)
- data = json.loads(response.content.decode('utf-8'))
- self.assertEqual(response.status_code, 200)
- self.assertEqual(data["error"], "ok")
-
- self.assertTrue(
- layer_data['name'] in
- self.project.get_all_compatible_layer_versions().values_list(
- 'layer__name',
- flat=True),
- "Could not find imported layer in project's all layers list"
- )
-
- # Empty data passed
- response = self.client.put(api_url, "{}")
- data = json.loads(response.content.decode('utf-8'))
- self.assertNotEqual(data["error"], "ok")
-
- def test_custom_ok(self):
- """Test successful return from ReST API xhr_customrecipe"""
- url = reverse('xhr_customrecipe')
- params = {'name': 'custom', 'project': self.project.id,
- 'base': self.recipe1.id}
- response = self.client.post(url, params)
- self.assertEqual(response.status_code, 200)
- data = json.loads(response.content.decode('utf-8'))
- self.assertEqual(data['error'], 'ok')
- self.assertTrue('url' in data)
- # get recipe from the database
- recipe = CustomImageRecipe.objects.get(project=self.project,
- name=params['name'])
- args = (self.project.id, recipe.id,)
- self.assertEqual(reverse('customrecipe', args=args), data['url'])
-
- def test_custom_incomplete_params(self):
- """Test not passing all required parameters to xhr_customrecipe"""
- url = reverse('xhr_customrecipe')
- for params in [{}, {'name': 'custom'},
- {'name': 'custom', 'project': self.project.id}]:
- response = self.client.post(url, params)
- self.assertEqual(response.status_code, 200)
- data = json.loads(response.content.decode('utf-8'))
- self.assertNotEqual(data["error"], "ok")
-
- def test_xhr_custom_wrong_project(self):
- """Test passing wrong project id to xhr_customrecipe"""
- url = reverse('xhr_customrecipe')
- params = {'name': 'custom', 'project': 0, "base": self.recipe1.id}
- response = self.client.post(url, params)
- self.assertEqual(response.status_code, 200)
- data = json.loads(response.content.decode('utf-8'))
- self.assertNotEqual(data["error"], "ok")
-
- def test_xhr_custom_wrong_base(self):
- """Test passing wrong base recipe id to xhr_customrecipe"""
- url = reverse('xhr_customrecipe')
- params = {'name': 'custom', 'project': self.project.id, "base": 0}
- response = self.client.post(url, params)
- self.assertEqual(response.status_code, 200)
- data = json.loads(response.content.decode('utf-8'))
- self.assertNotEqual(data["error"], "ok")
-
- def test_xhr_custom_details(self):
- """Test getting custom recipe details"""
- url = reverse('xhr_customrecipe_id', args=(self.customr.id,))
- response = self.client.get(url)
- self.assertEqual(response.status_code, 200)
- expected = {"error": "ok",
- "info": {'id': self.customr.id,
- 'name': self.customr.name,
- 'base_recipe_id': self.recipe1.id,
- 'project_id': self.project.id}}
- self.assertEqual(json.loads(response.content.decode('utf-8')),
- expected)
-
- def test_xhr_custom_del(self):
- """Test deleting custom recipe"""
- name = "to be deleted"
- recipe = CustomImageRecipe.objects.create(
- name=name, project=self.project,
- base_recipe=self.recipe1,
- file_path="/tmp/testing",
- layer_version=self.customr.layer_version)
- url = reverse('xhr_customrecipe_id', args=(recipe.id,))
- response = self.client.delete(url)
- self.assertEqual(response.status_code, 200)
-
- gotoUrl = reverse('projectcustomimages', args=(self.project.pk,))
-
- self.assertEqual(json.loads(response.content.decode('utf-8')),
- {"error": "ok",
- "gotoUrl": gotoUrl})
-
- # try to delete not-existent recipe
- url = reverse('xhr_customrecipe_id', args=(recipe.id,))
- response = self.client.delete(url)
- self.assertEqual(response.status_code, 200)
- self.assertNotEqual(json.loads(
- response.content.decode('utf-8'))["error"], "ok")
-
- def test_xhr_custom_packages(self):
- """Test adding and deleting package to a custom recipe"""
- # add self.package to recipe
- response = self.client.put(reverse('xhr_customrecipe_packages',
- args=(self.customr.id,
- self.cust_package.id)))
-
- self.assertEqual(response.status_code, 200)
- self.assertEqual(json.loads(response.content.decode('utf-8')),
- {"error": "ok"})
- self.assertEqual(self.customr.appends_set.first().name,
- self.cust_package.name)
- # delete it
- to_delete = self.customr.appends_set.first().pk
- del_url = reverse('xhr_customrecipe_packages',
- args=(self.customr.id, to_delete))
-
- response = self.client.delete(del_url)
- self.assertEqual(response.status_code, 200)
- self.assertEqual(json.loads(response.content.decode('utf-8')),
- {"error": "ok"})
- all_packages = self.customr.get_all_packages().values_list('pk',
- flat=True)
-
- self.assertFalse(to_delete in all_packages)
- # delete invalid package to test error condition
- del_url = reverse('xhr_customrecipe_packages',
- args=(self.customr.id,
- 99999))
-
- response = self.client.delete(del_url)
- self.assertEqual(response.status_code, 200)
- self.assertNotEqual(json.loads(
- response.content.decode('utf-8'))["error"], "ok")
-
- def test_xhr_custom_packages_err(self):
- """Test error conditions of xhr_customrecipe_packages"""
- # test calls with wrong recipe id and wrong package id
- for args in [(0, self.package.id), (self.customr.id, 0)]:
- url = reverse('xhr_customrecipe_packages', args=args)
- # test put and delete methods
- for method in (self.client.put, self.client.delete):
- response = method(url)
- self.assertEqual(response.status_code, 200)
- self.assertNotEqual(json.loads(
- response.content.decode('utf-8')),
- {"error": "ok"})
-
- def test_download_custom_recipe(self):
- """Download the recipe file generated for the custom image"""
-
- # Create a dummy recipe file for the custom image generation to read
- open("/tmp/a_recipe.bb", 'a').close()
- response = self.client.get(reverse('customrecipedownload',
- args=(self.project.id,
- self.customr.id)))
-
- self.assertEqual(response.status_code, 200)
-
- def test_software_recipes_table(self):
- """Test structure returned for Software RecipesTable"""
- table = SoftwareRecipesTable()
- request = RequestFactory().get('/foo/', {'format': 'json'})
- response = table.get(request, pid=self.project.id)
- data = json.loads(response.content.decode('utf-8'))
-
- recipes = Recipe.objects.filter(Q(is_image=False))
- self.assertTrue(len(recipes) > 1,
- "Need more than one software recipe to test "
- "SoftwareRecipesTable")
-
- recipe1 = recipes[0]
- recipe2 = recipes[1]
-
- rows = data['rows']
- row1 = next(x for x in rows if x['name'] == recipe1.name)
- row2 = next(x for x in rows if x['name'] == recipe2.name)
-
- self.assertEqual(response.status_code, 200, 'should be 200 OK status')
-
- # check other columns have been populated correctly
- self.assertTrue(recipe1.name in row1['name'])
- self.assertTrue(recipe1.version in row1['version'])
- self.assertTrue(recipe1.description in
- row1['get_description_or_summary'])
-
- self.assertTrue(recipe1.layer_version.layer.name in
- row1['layer_version__layer__name'])
-
- self.assertTrue(recipe2.name in row2['name'])
- self.assertTrue(recipe2.version in row2['version'])
- self.assertTrue(recipe2.description in
- row2['get_description_or_summary'])
-
- self.assertTrue(recipe2.layer_version.layer.name in
- row2['layer_version__layer__name'])
-
- def test_toaster_tables(self):
- """Test all ToasterTables instances"""
-
- def get_data(table, options={}):
- """Send a request and parse the json response"""
- options['format'] = "json"
- options['nocache'] = "true"
- request = RequestFactory().get('/', options)
-
- # This is the image recipe needed for a package list for
- # PackagesTable do this here to throw a non exist exception
- image_recipe = Recipe.objects.get(pk=4)
-
- # Add any kwargs that are needed by any of the possible tables
- args = {'pid': self.project.id,
- 'layerid': self.lver.pk,
- 'recipeid': self.recipe1.pk,
- 'recipe_id': image_recipe.pk,
- 'custrecipeid': self.customr.pk,
- 'build_id': 1,
- 'target_id': 1}
-
- response = table.get(request, **args)
- return json.loads(response.content.decode('utf-8'))
-
- def get_text_from_td(td):
- """If we have html in the td then extract the text portion"""
- # just so we don't waste time parsing non html
- if "<" not in td:
- ret = td
- else:
- ret = BeautifulSoup(td, "html.parser").text
-
- if len(ret):
- return "0"
- else:
- return ret
-
- # Get a list of classes in tables module
- tables = inspect.getmembers(toastergui.tables, inspect.isclass)
- tables.extend(inspect.getmembers(toastergui.buildtables,
- inspect.isclass))
-
- for name, table_cls in tables:
- # Filter out the non ToasterTables from the tables module
- if not issubclass(table_cls, toastergui.widgets.ToasterTable) or \
- table_cls == toastergui.widgets.ToasterTable or \
- 'Mixin' in name:
- continue
-
- # Get the table data without any options, this also does the
- # initialisation of the table i.e. setup_columns,
- # setup_filters and setup_queryset that we can use later
- table = table_cls()
- all_data = get_data(table)
-
- self.assertTrue(len(all_data['rows']) > 1,
- "Cannot test on a %s table with < 1 row" % name)
-
- if table.default_orderby:
- row_one = get_text_from_td(
- all_data['rows'][0][table.default_orderby.strip("-")])
- row_two = get_text_from_td(
- all_data['rows'][1][table.default_orderby.strip("-")])
-
- if '-' in table.default_orderby:
- self.assertTrue(row_one >= row_two,
- "Default ordering not working on %s"
- " '%s' should be >= '%s'" %
- (name, row_one, row_two))
- else:
- self.assertTrue(row_one <= row_two,
- "Default ordering not working on %s"
- " '%s' should be <= '%s'" %
- (name, row_one, row_two))
-
- # Test the column ordering and filtering functionality
- for column in table.columns:
- if column['orderable']:
- # If a column is orderable test it in both order
- # directions ordering on the columns field_name
- ascending = get_data(table_cls(),
- {"orderby": column['field_name']})
-
- row_one = get_text_from_td(
- ascending['rows'][0][column['field_name']])
- row_two = get_text_from_td(
- ascending['rows'][1][column['field_name']])
-
- self.assertTrue(row_one <= row_two,
- "Ascending sort applied but row 0: \"%s\""
- " is less than row 1: \"%s\" "
- "%s %s " %
- (row_one, row_two,
- column['field_name'], name))
-
- descending = get_data(table_cls(),
- {"orderby":
- '-'+column['field_name']})
-
- row_one = get_text_from_td(
- descending['rows'][0][column['field_name']])
- row_two = get_text_from_td(
- descending['rows'][1][column['field_name']])
-
- self.assertTrue(row_one >= row_two,
- "Descending sort applied but row 0: %s"
- "is greater than row 1: %s"
- "field %s table %s" %
- (row_one,
- row_two,
- column['field_name'], name))
-
- # If the two start rows are the same we haven't actually
- # changed the order
- self.assertNotEqual(ascending['rows'][0],
- descending['rows'][0],
- "An orderby %s has not changed the "
- "order of the data in table %s" %
- (column['field_name'], name))
-
- if column['filter_name']:
- # If a filter is available for the column get the filter
- # info. This contains what filter actions are defined.
- filter_info = get_data(table_cls(),
- {"cmd": "filterinfo",
- "name": column['filter_name']})
- self.assertTrue(len(filter_info['filter_actions']) > 0,
- "Filter %s was defined but no actions "
- "added to it" % column['filter_name'])
-
- for filter_action in filter_info['filter_actions']:
- # filter string to pass as the option
- # This is the name of the filter:action
- # e.g. project_filter:not_in_project
- filter_string = "%s:%s" % (
- column['filter_name'],
- filter_action['action_name'])
- # Now get the data with the filter applied
- filtered_data = get_data(table_cls(),
- {"filter": filter_string})
-
- # date range filter actions can't specify the
- # number of results they return, so their count is 0
- if filter_action['count'] is not None:
- self.assertEqual(
- len(filtered_data['rows']),
- int(filter_action['count']),
- "We added a table filter for %s but "
- "the number of rows returned was not "
- "what the filter info said there "
- "would be" % name)
-
- # Test search functionality on the table
- something_found = False
- for search in list(string.ascii_letters):
- search_data = get_data(table_cls(), {'search': search})
-
- if len(search_data['rows']) > 0:
- something_found = True
- break
-
- self.assertTrue(something_found,
- "We went through the whole alphabet and nothing"
- " was found for the search of table %s" % name)
-
- # Test the limit functionality on the table
- limited_data = get_data(table_cls(), {'limit': "1"})
- self.assertEqual(len(limited_data['rows']),
- 1,
- "Limit 1 set on table %s but not 1 row returned"
- % name)
-
- # Test the pagination functionality on the table
- page_one_data = get_data(table_cls(), {'limit': "1",
- "page": "1"})['rows'][0]
-
- page_two_data = get_data(table_cls(), {'limit': "1",
- "page": "2"})['rows'][0]
-
- self.assertNotEqual(page_one_data,
- page_two_data,
- "Changed page on table %s but first row is"
- " the same as the previous page" % name)
diff --git a/lib/toastergui/__init__.py b/lib/toastergui/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/lib/toastergui/__init__.py
+++ /dev/null
diff --git a/lib/toastergui/templatetags/__init__.py b/lib/toastergui/templatetags/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/lib/toastergui/templatetags/__init__.py
+++ /dev/null
diff --git a/lib/toastermain/__init__.py b/lib/toastermain/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/lib/toastermain/__init__.py
+++ /dev/null
diff --git a/lib/toastermain/management/__init__.py b/lib/toastermain/management/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/lib/toastermain/management/__init__.py
+++ /dev/null
diff --git a/lib/toastermain/management/commands/__init__.py b/lib/toastermain/management/commands/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/lib/toastermain/management/commands/__init__.py
+++ /dev/null
diff --git a/toaster-requirements.txt b/srtool-requirements.txt
index c0ec3682..c0ec3682 100644
--- a/toaster-requirements.txt
+++ b/srtool-requirements.txt