--- /dev/null
+
+"""Test the media accessors.
+
+If run directly from the command line, also tests the accessors and the names
+of all the media by getting just about everything in a naive brute-force way.
+This, of course, takes a lot of time to run.
+"""
+
+import os
+import re
+
+from nose.tools import *
+from nose.plugins.skip import SkipTest
+import nose
+import pkg_resources
+
+from pokedex.db import tables, connect
+from pokedex.util import media
+
+session = connect()
+basedir = pkg_resources.resource_filename('pokedex', 'data/media')
+
+path_re = re.compile('^[-a-z0-9./]*$')
+
+def test_totodile():
+ """Totodile's female sprite -- same as male"""
+ totodile = session.query(tables.Pokemon).filter_by(identifier=u'totodile').one()
+ accessor = media.PokemonMedia(totodile)
+ assert accessor.sprite() == accessor.sprite(female=True)
+
+def test_chimecho():
+ """Chimecho's Platinum female backsprite -- diffeent from male"""
+ chimecho = session.query(tables.Pokemon).filter_by(identifier=u'chimecho').one()
+ accessor = media.PokemonMedia(chimecho)
+ male = accessor.sprite('platinum', back=True, frame=2)
+ female = accessor.sprite('platinum', back=True, female=True, frame=2)
+ assert male != female
+
+def test_venonat():
+ """Venonat's shiny Yellow sprite -- same as non-shiny"""
+ venonat = session.query(tables.Pokemon).filter_by(identifier=u'venonat').one()
+ accessor = media.PokemonMedia(venonat)
+ assert accessor.sprite('yellow') == accessor.sprite('yellow', shiny=True)
+
+def test_arceus_icon():
+ """Arceus fire-form icon -- same as base icon"""
+ arceus = session.query(tables.Pokemon).filter_by(identifier=u'arceus').one()
+ accessor = media.PokemonMedia(arceus)
+ fire_arceus = [f for f in arceus.forms if f.identifier == 'fire'][0]
+ fire_accessor = media.PokemonFormMedia(fire_arceus)
+ assert accessor.icon() == fire_accessor.icon()
+
+@raises(ValueError)
+def test_strict_castform():
+ """Castform rainy form overworld with strict -- unavailable"""
+ castform = session.query(tables.Pokemon).filter_by(identifier=u'castform').first()
+ rainy_castform = [f for f in castform.forms if f.identifier == 'rainy'][0]
+ rainy_castform = media.PokemonFormMedia(rainy_castform)
+ rainy_castform.overworld('up', strict=True)
+
+@raises(ValueError)
+def test_strict_exeggcute():
+ """Exeggcutes's female backsprite, with strict -- unavailable"""
+ exeggcute = session.query(tables.Pokemon).filter_by(identifier=u'exeggcute').one()
+ accessor = media.PokemonMedia(exeggcute)
+ accessor.sprite(female=True, strict=True)
+
+
+
+def get_all_filenames():
+ print 'Reading all filenames...'
+
+ all_filenames = set()
+
+ for dirpath, dirnames, filenames in os.walk(basedir):
+ for filename in filenames:
+ path = os.path.join(dirpath, filename)
+ assert path_re.match(path), path
+ all_filenames.add(path)
+
+ return all_filenames
+
+def hit(filenames, method, *args, **kwargs):
+ """
+ Run the given accessor method with args & kwargs; if found remove the
+ result path from filenames and return True, else return False.
+ """
+ try:
+ medium = method(*args, **kwargs)
+ #print 'Hit', medium.relative_path
+ assert medium.exists
+ except ValueError, e:
+ #print 'DNF', e
+ return False
+ except:
+ print 'Error while processing', method, args, kwargs
+ raise
+ try:
+ filenames.remove(medium.path)
+ except KeyError:
+ pass
+ return True
+
+def check_get_everything():
+ """
+ For every the accessor method, loop over the Cartesian products of all
+ possible values for its arguments.
+ Make sure we get every file in the repo, and that we get a file whenever
+ we should.
+
+ Well, there are exceptions of course.
+ """
+
+ versions = list(session.query(tables.Version).all())
+ versions.append('red-green')
+
+ black = session.query(tables.Version).filter_by(identifier=u'black').one()
+
+ filenames = get_all_filenames()
+
+ # Some small stuff first
+
+ for damage_class in session.query(tables.MoveDamageClass).all():
+ assert hit(filenames, media.DamageClassMedia(damage_class).icon)
+
+ for habitat in session.query(tables.PokemonHabitat).all():
+ assert hit(filenames, media.HabitatMedia(habitat).icon)
+
+ for shape in session.query(tables.PokemonShape).all():
+ assert hit(filenames, media.ShapeMedia(shape).icon)
+
+ for item_pocket in session.query(tables.ItemPocket).all():
+ assert hit(filenames, media.ItemPocketMedia(item_pocket).icon)
+ assert hit(filenames, media.ItemPocketMedia(item_pocket).icon, selected=True)
+
+ for contest_type in session.query(tables.ContestType).all():
+ assert hit(filenames, media.ContestTypeMedia(contest_type).icon)
+
+ for elemental_type in session.query(tables.Type).all():
+ assert hit(filenames, media.TypeMedia(elemental_type).icon)
+
+ # Items
+ versions_for_items = [
+ None,
+ session.query(tables.Version).filter_by(identifier='emerald').one(),
+ ]
+
+ for item in session.query(tables.Item).all():
+ accessor = media.ItemMedia(item)
+ assert hit(filenames, accessor.berry_image) or not item.berry
+ for rotation in (0, 90, 180, 270):
+ assert hit(filenames, accessor.underground, rotation=rotation) or (
+ not item.appears_underground or rotation)
+ for version in versions_for_items:
+ success = hit(filenames, accessor.sprite, version=version)
+ if version is None:
+ assert success
+
+ for color in 'red green blue pale prism'.split():
+ for big in (True, False):
+ accessor = media.UndergroundSphereMedia(color=color, big=big)
+ assert hit(filenames, accessor.underground)
+
+ for rock_type in 'i ii o o-big s t z'.split():
+ accessor = media.UndergroundRockMedia(rock_type)
+ for rotation in (0, 90, 180, 270):
+ success = hit(filenames, accessor.underground, rotation=rotation)
+ assert success or rotation
+
+ # Pokemon!
+ accessors = []
+
+ accessors.append(media.UnknownPokemonMedia())
+ accessors.append(media.EggMedia())
+ manaphy = session.query(tables.Pokemon).filter_by(identifier=u'manaphy').one()
+ accessors.append(media.EggMedia(manaphy))
+ accessors.append(media.SubstituteMedia())
+
+ print 'Loading pokemon'
+
+ for form in session.query(tables.PokemonForm).filter(tables.PokemonForm.identifier != '').all():
+ accessors.append(media.PokemonFormMedia(form))
+
+ for pokemon in session.query(tables.Pokemon).all():
+ accessors.append(media.PokemonMedia(pokemon))
+
+ for accessor in accessors:
+ assert hit(filenames, accessor.footprint) or not accessor.form
+ assert hit(filenames, accessor.trozei) or not accessor.form or (
+ accessor.form.pokemon.generation.id > 3)
+ assert hit(filenames, accessor.cry) or not accessor.form
+ assert hit(filenames, accessor.cropped_sprite) or not accessor.form
+ for female in (True, False):
+ assert hit(filenames, accessor.icon, female=female) or not accessor.form
+ assert hit(filenames, accessor.sugimori, female=female) or (
+ not accessor.form or accessor.form.pokemon.id >= 647)
+ for shiny in (True, False):
+ for frame in (1, 2):
+ for direction in 'up down left right'.split():
+ assert hit(filenames, accessor.overworld,
+ direction=direction,
+ shiny=shiny,
+ female=female,
+ frame=frame,
+ ) or not accessor.form or (
+ accessor.form.pokemon.generation.id > 4)
+ for version in versions:
+ for animated in (True, False):
+ for back in (True, False):
+ for color in (None, 'gray', 'gbc'):
+ success = hit(filenames,
+ accessor.sprite,
+ version,
+ animated=animated,
+ back=back,
+ color=color,
+ shiny=shiny,
+ female=female,
+ frame=frame,
+ )
+ if (version == black and not animated
+ and not back and not color and not
+ shiny and not female and
+ frame == 1):
+ # All pokemon are in Black
+ assert success or not accessor.form
+ if (str(accessor.pokemon_id) == '1'
+ and not animated and not color and
+ frame == 1):
+ # Bulbasaur is in all versions
+ assert success
+
+ # Remove exceptions
+ exceptions = [os.path.join(basedir, dirname) for dirname in
+ 'chrome fonts ribbons'.split()]
+ exceptions.append(os.path.join(basedir, 'items', 'hm-'))
+ exceptions = tuple(exceptions)
+
+ for filename in tuple(filenames):
+ if filename.startswith(exceptions):
+ filenames.remove(filename)
+
+ if len(filenames):
+ print
+ print '-----------------'
+ print 'Unaccessed stuff:'
+ for filename in sorted(filenames):
+ print filename
+ print len(filenames), 'unaccessed files :('
+
+ return (not filenames)
+
+if __name__ == '__main__':
+ result = nose.run(defaultTest=__file__)
+ result = result and check_get_everything()
+ exit(not result)