There are no general ways, and it is operating system specific. I am focusing on Linux and POSIX systems. Notice that test is a poor name (colliding with test(1)...) and that mytest < input.txt stills gets its input from stdin since the redirection is done by the shell before starting your mytest program with execve(2).
The usual way to read from a file would be to give it as explicit argument: mytest input.txt (then test argc). I strongly recommend having such a convention. See also getopt(3), read about program arguments.
On Linux (or POSIX), you might use fstat(2) and/or isatty(3) on STDIN_FILENO (i.e. 0) and even that is not be bullet proof, e.g. for pipelines or here documents.
You might even want to consider the case of batch invocation (i.e. at or crontab jobs) and background jobs.
For that you could also check the environment, see environ(7). Read also credentials(7) on controlling terminals and sessions (setsid(2)) and job control. See also /dev/tty (so termios(3), tty(4), and the tty demystified). BTW, you could also care about stdout or stderr being (or not) redirected.
I recommend being able to overcome such an autodetection with explicit program arguments, because it won't be perfect since there are corner cases (what about mytest < /dev/stdin and mytest < /dev/tty ? Do you consider these as redirections to be detected ?). There are conventions and habits about program arguments.
Few programs are doing such an autodetection, and those that do are providing a way, thru program arguments, to overcome it (for example, ls --color and emacs -nw).
isatty()function can be used../test input.txtand./test?