diff options
Diffstat (limited to 'bitbake')
-rw-r--r-- | bitbake/lib/toaster/toastergui/tests.py | 223 |
1 files changed, 212 insertions, 11 deletions
diff --git a/bitbake/lib/toaster/toastergui/tests.py b/bitbake/lib/toaster/toastergui/tests.py index 9e6c46a253..a6312034a8 100644 --- a/bitbake/lib/toaster/toastergui/tests.py +++ b/bitbake/lib/toaster/toastergui/tests.py | |||
@@ -33,11 +33,14 @@ from orm.models import CustomImageRecipe, ProjectVariable | |||
33 | from orm.models import Branch | 33 | from orm.models import Branch |
34 | 34 | ||
35 | import toastermain | 35 | import toastermain |
36 | import inspect | ||
37 | import toastergui | ||
36 | 38 | ||
37 | from toastergui.tables import SoftwareRecipesTable | 39 | from toastergui.tables import SoftwareRecipesTable |
38 | import json | 40 | import json |
39 | from bs4 import BeautifulSoup | 41 | from bs4 import BeautifulSoup |
40 | import re | 42 | import re |
43 | import string | ||
41 | 44 | ||
42 | PROJECT_NAME = "test project" | 45 | PROJECT_NAME = "test project" |
43 | CLI_BUILDS_PROJECT_NAME = 'Command line builds' | 46 | CLI_BUILDS_PROJECT_NAME = 'Command line builds' |
@@ -69,32 +72,68 @@ class ViewTests(TestCase): | |||
69 | layer = Layer.objects.create(name="base-layer", layer_source=layersrc, | 72 | layer = Layer.objects.create(name="base-layer", layer_source=layersrc, |
70 | vcs_url="/tmp/") | 73 | vcs_url="/tmp/") |
71 | 74 | ||
75 | layer_two = Layer.objects.create(name="z-layer", | ||
76 | layer_source=layersrc, | ||
77 | vcs_url="git://two/") | ||
78 | |||
79 | |||
72 | branch = Branch.objects.create(name="master", layer_source=layersrc) | 80 | branch = Branch.objects.create(name="master", layer_source=layersrc) |
73 | 81 | ||
74 | lver = Layer_Version.objects.create(layer=layer, project=self.project, | 82 | self.lver = Layer_Version.objects.create(layer=layer, |
75 | layer_source=layersrc, commit="master", | 83 | project=self.project, |
76 | up_branch=branch) | 84 | layer_source=layersrc, |
85 | commit="master", | ||
86 | up_branch=branch) | ||
87 | |||
88 | lver_two = Layer_Version.objects.create(layer=layer_two, | ||
89 | layer_source=layersrc, | ||
90 | commit="master", | ||
91 | up_branch=branch) | ||
92 | |||
93 | Recipe.objects.create(layer_source=layersrc, | ||
94 | name="z recipe", | ||
95 | version="5.2", | ||
96 | summary="z recipe", | ||
97 | description="G recipe", | ||
98 | license="Z GPL", | ||
99 | section="h section", | ||
100 | layer_version=lver_two) | ||
77 | 101 | ||
78 | self.recipe1 = Recipe.objects.create(layer_source=layersrc, | 102 | self.recipe1 = Recipe.objects.create(layer_source=layersrc, |
79 | name="base-recipe", | 103 | name="base-recipe", |
80 | version="1.2", | 104 | version="1.2", |
81 | summary="one recipe", | 105 | summary="one recipe", |
82 | description="recipe", | 106 | description="recipe", |
83 | layer_version=lver) | 107 | section="A section", |
108 | license="Apache", | ||
109 | layer_version=self.lver) | ||
84 | 110 | ||
85 | Machine.objects.create(layer_version=lver, name="wisk", | 111 | Machine.objects.create(layer_version=self.lver, name="wisk", |
86 | description="wisking machine") | 112 | description="wisking machine") |
113 | Machine.objects.create(layer_version=self.lver, name="zap", | ||
114 | description="zap machine") | ||
115 | Machine.objects.create(layer_version=lver_two, name="xray", | ||
116 | description="xray machine") | ||
117 | |||
87 | 118 | ||
88 | ProjectLayer.objects.create(project=self.project, layercommit=lver) | 119 | |
120 | ProjectLayer.objects.create(project=self.project, layercommit=self.lver) | ||
89 | 121 | ||
90 | 122 | ||
91 | self.customr = CustomImageRecipe.objects.create(\ | 123 | self.customr = CustomImageRecipe.objects.create(\ |
92 | name="custom recipe", project=self.project, | 124 | name="custom recipe", project=self.project, |
93 | base_recipe=self.recipe1) | 125 | base_recipe=self.recipe1) |
94 | 126 | ||
95 | self.package = Package.objects.create(name='pkg1', recipe=self.recipe1, | 127 | CustomImageRecipe.objects.create(name="z custom recipe", |
128 | project=self.project, | ||
129 | base_recipe=self.recipe1) | ||
130 | |||
131 | self.package = Package.objects.create(name='pkg1', | ||
132 | size=999, | ||
133 | recipe=self.recipe1, | ||
96 | build=build) | 134 | build=build) |
97 | 135 | ||
136 | Package.objects.create(name='zpkg1', recipe=self.recipe1, build=build) | ||
98 | 137 | ||
99 | # recipe with project for testing AvailableRecipe table | 138 | # recipe with project for testing AvailableRecipe table |
100 | self.recipe2 = Recipe.objects.create(layer_source=layersrc, | 139 | self.recipe2 = Recipe.objects.create(layer_source=layersrc, |
@@ -102,10 +141,35 @@ class ViewTests(TestCase): | |||
102 | version="1.4", | 141 | version="1.4", |
103 | summary="a fancy recipe", | 142 | summary="a fancy recipe", |
104 | description="fancy recipe", | 143 | description="fancy recipe", |
105 | layer_version=lver, | 144 | license="MIT", |
145 | layer_version=self.lver, | ||
146 | section="Z section", | ||
106 | file_path='/home/foo') | 147 | file_path='/home/foo') |
107 | 148 | ||
108 | self.assertTrue(lver in self.project.compatible_layerversions()) | 149 | Recipe.objects.create(layer_source=layersrc, |
150 | is_image=True, | ||
151 | name="Test image one", | ||
152 | version="1.2", | ||
153 | summary="one recipe", | ||
154 | description="recipe", | ||
155 | section="A", | ||
156 | license="A", | ||
157 | file_path="/one/", | ||
158 | layer_version=self.lver) | ||
159 | |||
160 | Recipe.objects.create(layer_source=layersrc, | ||
161 | is_image=True, | ||
162 | name="Z Test image two", | ||
163 | version="1.3", | ||
164 | summary="two image recipe", | ||
165 | description="recipe two", | ||
166 | section="B", | ||
167 | license="Z", | ||
168 | file_path="/two/", | ||
169 | layer_version=lver_two) | ||
170 | |||
171 | |||
172 | |||
109 | 173 | ||
110 | def test_get_base_call_returns_html(self): | 174 | def test_get_base_call_returns_html(self): |
111 | """Basic test for all-projects view""" | 175 | """Basic test for all-projects view""" |
@@ -181,7 +245,6 @@ class ViewTests(TestCase): | |||
181 | 245 | ||
182 | return False | 246 | return False |
183 | 247 | ||
184 | import string | ||
185 | 248 | ||
186 | for url in urls: | 249 | for url in urls: |
187 | results = False | 250 | results = False |
@@ -344,7 +407,7 @@ class ViewTests(TestCase): | |||
344 | row2 = next(x for x in rows if x['name'] == self.recipe2.name) | 407 | row2 = next(x for x in rows if x['name'] == self.recipe2.name) |
345 | 408 | ||
346 | self.assertEqual(response.status_code, 200, 'should be 200 OK status') | 409 | self.assertEqual(response.status_code, 200, 'should be 200 OK status') |
347 | self.assertEqual(len(rows), 2, 'should be 2 recipes') | 410 | self.assertTrue(row2, 'should be 2 recipes') |
348 | 411 | ||
349 | # check other columns have been populated correctly | 412 | # check other columns have been populated correctly |
350 | self.assertEqual(row1['name'], self.recipe1.name) | 413 | self.assertEqual(row1['name'], self.recipe1.name) |
@@ -360,6 +423,144 @@ class ViewTests(TestCase): | |||
360 | self.assertEqual(row2['layer_version__layer__name'], | 423 | self.assertEqual(row2['layer_version__layer__name'], |
361 | self.recipe2.layer_version.layer.name) | 424 | self.recipe2.layer_version.layer.name) |
362 | 425 | ||
426 | def test_toaster_tables(self): | ||
427 | """Test all ToasterTables instances""" | ||
428 | |||
429 | def get_data(table, options={}): | ||
430 | """Send a request and parse the json response""" | ||
431 | options['format'] = "json" | ||
432 | options['nocache'] = "true" | ||
433 | request = RequestFactory().get('/', options) | ||
434 | # Add any kwargs that are needed by any of the possible tables | ||
435 | response = table.get(request, | ||
436 | pid=self.project.id, | ||
437 | layerid=self.lver.pk, | ||
438 | recipeid=self.recipe1.pk) | ||
439 | return json.loads(response.content) | ||
440 | |||
441 | # Get a list of classes in tables module | ||
442 | tables = inspect.getmembers(toastergui.tables, inspect.isclass) | ||
443 | |||
444 | for name, table_cls in tables: | ||
445 | # Filter out the non ToasterTables from the tables module | ||
446 | if not issubclass(table_cls, toastergui.widgets.ToasterTable) or \ | ||
447 | table_cls == toastergui.widgets.ToasterTable: | ||
448 | continue | ||
449 | |||
450 | # Get the table data without any options, this also does the | ||
451 | # initialisation of the table i.e. setup_columns, | ||
452 | # setup_filters and setup_queryset that we can use later | ||
453 | table = table_cls() | ||
454 | all_data = get_data(table) | ||
455 | |||
456 | self.assertTrue(len(all_data['rows']) > 1, | ||
457 | "Cannot test on a table with < 1 row") | ||
458 | |||
459 | if table.default_orderby: | ||
460 | row_one = all_data['rows'][0][table.default_orderby.strip("-")] | ||
461 | row_two = all_data['rows'][1][table.default_orderby.strip("-")] | ||
462 | |||
463 | if '-' in table.default_orderby: | ||
464 | self.assertTrue(row_one >= row_two, | ||
465 | "Default ordering not working on %s" % name) | ||
466 | else: | ||
467 | self.assertTrue(row_one <= row_two, | ||
468 | "Default ordering not working on %s" % name) | ||
469 | |||
470 | # Test the column ordering and filtering functionality | ||
471 | for column in table.columns: | ||
472 | if column['orderable']: | ||
473 | # If a column is orderable test it in both order | ||
474 | # directions ordering on the columns field_name | ||
475 | ascending = get_data(table_cls(), | ||
476 | {"orderby" : column['field_name']}) | ||
477 | |||
478 | row_one = ascending['rows'][0][column['field_name']] | ||
479 | row_two = ascending['rows'][1][column['field_name']] | ||
480 | |||
481 | self.assertTrue(row_one <= row_two, | ||
482 | "Ascending sort applied but row 0 is less " | ||
483 | "than row 1") | ||
484 | |||
485 | descending = get_data(table_cls(), | ||
486 | {"orderby" : | ||
487 | '-'+column['field_name']}) | ||
488 | |||
489 | row_one = descending['rows'][0][column['field_name']] | ||
490 | row_two = descending['rows'][1][column['field_name']] | ||
491 | |||
492 | self.assertTrue(row_one >= row_two, | ||
493 | "Descending sort applied but row 0 is " | ||
494 | "greater than row 1") | ||
495 | |||
496 | # If the two start rows are the same we haven't actually | ||
497 | # changed the order | ||
498 | self.assertNotEqual(ascending['rows'][0], | ||
499 | descending['rows'][0], | ||
500 | "An orderby %s has not changed the " | ||
501 | "order of the data in table %s" % | ||
502 | (column['field_name'], name)) | ||
503 | |||
504 | if column['filter_name']: | ||
505 | # If a filter is available for the column get the filter | ||
506 | # info. This contains what filter actions are defined. | ||
507 | filter_info = get_data(table_cls(), | ||
508 | {"cmd": "filterinfo", | ||
509 | "name": column['filter_name']}) | ||
510 | self.assertTrue(len(filter_info['filter_actions']) > 0, | ||
511 | "Filter %s was defined but no actions " | ||
512 | "added to it" % column['filter_name']) | ||
513 | |||
514 | for filter_action in filter_info['filter_actions']: | ||
515 | # filter string to pass as the option | ||
516 | # This is the name of the filter:action | ||
517 | # e.g. project_filter:not_in_project | ||
518 | filter_string = "%s:%s" % (column['filter_name'], | ||
519 | filter_action['name']) | ||
520 | # Now get the data with the filter applied | ||
521 | filtered_data = get_data(table_cls(), | ||
522 | {"filter" : filter_string}) | ||
523 | self.assertEqual(len(filtered_data['rows']), | ||
524 | int(filter_action['count']), | ||
525 | "We added a table filter for %s but " | ||
526 | "the number of rows returned was not " | ||
527 | "what the filter info said there " | ||
528 | "would be" % name) | ||
529 | |||
530 | |||
531 | # Test search functionality on the table | ||
532 | something_found = False | ||
533 | for search in list(string.ascii_letters): | ||
534 | search_data = get_data(table_cls(), {'search' : search}) | ||
535 | |||
536 | if len(search_data['rows']) > 0: | ||
537 | something_found = True | ||
538 | break | ||
539 | |||
540 | self.assertTrue(something_found, | ||
541 | "We went through the whole alphabet and nothing" | ||
542 | " was found for the search of table %s" % name) | ||
543 | |||
544 | # Test the limit functionality on the table | ||
545 | limited_data = get_data(table_cls(), {'limit' : "1"}) | ||
546 | self.assertEqual(len(limited_data['rows']), | ||
547 | 1, | ||
548 | "Limit 1 set on table %s but not 1 row returned" | ||
549 | % name) | ||
550 | |||
551 | # Test the pagination functionality on the table | ||
552 | page_one_data = get_data(table_cls(), {'limit' : "1", | ||
553 | "page": "1"})['rows'][0] | ||
554 | |||
555 | page_two_data = get_data(table_cls(), {'limit' : "1", | ||
556 | "page": "2"})['rows'][0] | ||
557 | |||
558 | self.assertNotEqual(page_one_data, | ||
559 | page_two_data, | ||
560 | "Changed page on table %s but first row is the " | ||
561 | "same as the previous page" % name) | ||
562 | |||
563 | |||
363 | class LandingPageTests(TestCase): | 564 | class LandingPageTests(TestCase): |
364 | """ Tests for redirects on the landing page """ | 565 | """ Tests for redirects on the landing page """ |
365 | # disable bogus pylint message error: | 566 | # disable bogus pylint message error: |